Var/LazyInit/etc annotations can cause problems for Android builds due to reliance on javax.lang.model.element.Modifier
See original GitHub issueDescription of the problem / feature request:
Multiple annotations inside com.google.errorprone:error_prone_annotations
use the meta-annotation @IncompatibleModifiers(FINAL)
.
Here, FINAL
references javax.lang.model.element.Modifier.FINAL
. However, the android.jar
file used to build Android projects does not include javax.lang.model.element.Modifier
.
This results in the following error whenever code using @Var
, @LazyInit
, @ForOverride
, etc. is compiled for Android with a -Werror
flag (our default setup):
warning: unknown enum constant Modifier.FINAL
reason: class file for javax.lang.model.element.Modifier not found
error: warnings found and -Werror specified
1 error
1 warning
For an example, here is a simple repro as a standalone Android project using gradle (see below for instructions).
Bugs: what’s the simplest, easiest way to reproduce this bug? Please provide a minimal example if possible.
git clone https://github.com/lazaroclapp/ep_modifiers_android_repro.git
gradle build
Observe:
warning: unknown enum constant Modifier.FINAL
reason: class file for javax.lang.model.element.Modifier not found
error: warnings found and -Werror specified
1 error
1 warning
What version of Error Prone are you using?
Can repro on 2.5.1, 2.4, and 2.3.3
Have you found anything relevant by searching the web?
I posted on the mailing list and got prompt help from Liam figuring out the root cause of the issue. Thanks!
My recommended solution
The real problem here is @IncompatibleModifiers
and its use of javax.lang.model.element.Modifier
’s enum values as annotation parameters.
Could com.google.errorprone:error_prone_annotations
perhaps include a separate Modifier
enum that doesn’t depend on javax.lang.model.element.Modifier
, and use that for the public API of the @IncompatibleModifiers
meta-annotation and for annotating the relevant Error Prone annotations?
This will likely complicate IncompatibleModifiersChecker
a bit, or require a mapping from the new custom Modifier
enum to javax.lang.model.element.Modifier
, but it will make the annotation fully compatible with Android builds.
FYI, if you agree that supporting Android with -Werror
is important, and that the above is a reasonable solution, I’d be more than happy to give it a first try at a PR that replaces javax.lang.model.element.Modifier
with e.g. com.google.errorprone.annotations.Modifier
.
Issue Analytics
- State:
- Created 3 years ago
- Comments:7 (3 by maintainers)
Top GitHub Comments
I went ahead and deprecated
{Required,Incompatible}Modifiers.value
, and migrated uses within core Error Prone to a new modifier enum in 26f1f5498321c9e2c25f5546dc9aa026affde16a. I hope to remove the deprecated attributes eventually, but hopefully there’s no rush for that.So, I think - but I am not sure - that this might just work immediately for us:
But only if, at the same time the
modifier()
‘field’ is introduced, all usages of@IncompatibleModifiers
within Error Prone first party annotations switch to using themodifier =
version.I think it might be worth testing if that would be enough to prevent the compiler from trying to complete e.g.
Modifier.FINAL
when analyzing@Var
, or if just the act of trying to load@IncompatibleModifiers
will surface the same problem.I might do a quick internal experiment on this. If that works, we might even be fine with
value()
lingering there forever for third-party Error Prone users (although I imagine everyone will be happier if there is a path to having a single way of doing things there eventually, anyways).I understand this is not super high priority on your end, but would you guys consider a PR implementing the solution you detailed above if that fixed the issue for us?
We are currently doing this, and it does mitigate the problem for us. But we’d love to be able to go back to not forking any part of Error Prone and just being on mainline! (Plus, I suspect we aren’t the only ones using EP for Android outside of Google…)
So, this is separate from the issue at hand, but, since you ask…
We did run into an issue recently where to get NullAway to work with Error Prone 2.5.1, we had to drop compatibility with 2.3.x (https://github.com/uber/NullAway/pull/447). So far, that hasn’t been too painful a decision, to be honest. Internally, we are currently on Error Prone 2.4.0. Would have been more complicated if we were lagging further behind, though, and we might yet hear of some NullAway third-party user who has issues upgrading to 0.9.0 because of it.
As for why we aren’t on 2.5.1 yet, we build massive monorepos with
-Werror
, so EP upgrades are unsurprisingly painful 😃However, the main reasons are usually not any changes to core or the APIs (we modify our own checkers to match whichever EP version we are on and that’s often <1hr for all of them at worst), or new checkers being introduced (we can always set them to
:OFF
on the initial code change and then enable them independently).The true upgrade pain points for us are:
a) dependency changes where upgrading Error Prone can easily involve a cascading upgrade of core deps for us (e.g. Guava), and
b) existing checkers that have been updated to be more precise.
The later is often a trade-off between adding a dozen to a few hundred suppressions or setting to
:OFF
a checker which we were running before (albeit possibly in a less comprehensive version). For 2.4.0, the javadoc checkers were notorious for us here.The first issue, (a), just seems like a fact of life to me. Not sure (b) has an easy solution either, but at least in theory could be avoided if big changes to checkers resulted to checkers or in a world where you could say something like
-Xep:MissingSummary:WARN:3.3.4
while keeping all other checkers on 2.4.0 by default and upgrading that one as a follow up 😉We can simulate the later by forking a checker internally and renaming, but this is rarely worth it as an intermediate/mitigation step.
Just to be clear, though, I am not asking you to address any of this stuff. I am more concerned by the original issue. But you asked for feedback on breaking changes and EP versions, hence the brain-dump.