-
Notifications
You must be signed in to change notification settings - Fork 746
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Automated rollback of commit 4b7f0e4.
*** Reason for rollback *** Roll forward, and disable the check in `tools/jdk/config/error_prone/build_defs.bzl` until the cleanup is done. *** Original change description *** Automated rollback of commit a3fdf64. *** Reason for rollback *** Requires a large number of fixes throughout the depot. I am not sure that that was intended, but if it was then those fixes should be made separately from the regularly-scheduled JavaBuilder release. A *subset* of the fixes, before I gave up, is here: unknown commit. *** Original change description *** Generalize InjectScopeOrQualifierAnnotationRetention to MissingRuntimeRetention *** *** PiperOrigin-RevId: 650310818
- Loading branch information
Showing
6 changed files
with
77 additions
and
50 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -14,85 +14,117 @@ | |
|
||
package com.google.errorprone.bugpatterns.inject; | ||
|
||
import static com.google.common.collect.ImmutableSet.toImmutableSet; | ||
import static com.google.errorprone.BugPattern.SeverityLevel.ERROR; | ||
import static com.google.errorprone.bugpatterns.inject.ElementPredicates.doesNotHaveRuntimeRetention; | ||
import static com.google.errorprone.bugpatterns.inject.ElementPredicates.hasSourceRetention; | ||
import static com.google.errorprone.matchers.Description.NO_MATCH; | ||
import static com.google.errorprone.matchers.InjectMatchers.DAGGER_MAP_KEY_ANNOTATION; | ||
import static com.google.errorprone.matchers.InjectMatchers.GUICE_BINDING_ANNOTATION; | ||
import static com.google.errorprone.matchers.InjectMatchers.GUICE_MAP_KEY_ANNOTATION; | ||
import static com.google.errorprone.matchers.InjectMatchers.GUICE_SCOPE_ANNOTATION; | ||
import static com.google.errorprone.matchers.InjectMatchers.JAVAX_QUALIFIER_ANNOTATION; | ||
import static com.google.errorprone.matchers.InjectMatchers.JAVAX_SCOPE_ANNOTATION; | ||
import static com.google.errorprone.matchers.Matchers.allOf; | ||
import static com.google.errorprone.matchers.Matchers.anyOf; | ||
import static com.google.errorprone.matchers.Matchers.hasAnnotation; | ||
import static com.google.errorprone.matchers.Matchers.kindIs; | ||
import static com.google.errorprone.util.ASTHelpers.annotationsAmong; | ||
import static com.google.errorprone.util.ASTHelpers.getDeclaredSymbol; | ||
import static com.sun.source.tree.Tree.Kind.ANNOTATION_TYPE; | ||
|
||
import com.google.common.collect.ImmutableSet; | ||
import com.google.common.collect.Iterables; | ||
import com.google.common.collect.Streams; | ||
import com.google.errorprone.BugPattern; | ||
import com.google.errorprone.VisitorState; | ||
import com.google.errorprone.bugpatterns.BugChecker; | ||
import com.google.errorprone.bugpatterns.BugChecker.ClassTreeMatcher; | ||
import com.google.errorprone.fixes.SuggestedFix; | ||
import com.google.errorprone.matchers.Description; | ||
import com.google.errorprone.matchers.InjectMatchers; | ||
import com.google.errorprone.matchers.Matcher; | ||
import com.google.errorprone.suppliers.Supplier; | ||
import com.google.errorprone.util.ASTHelpers; | ||
import com.sun.source.tree.AnnotationTree; | ||
import com.sun.source.tree.ClassTree; | ||
import com.sun.tools.javac.code.Symbol; | ||
import com.sun.tools.javac.code.Symbol.ClassSymbol; | ||
import com.sun.tools.javac.util.Name; | ||
import java.lang.annotation.Retention; | ||
import java.util.Collections; | ||
import java.util.Set; | ||
import java.util.stream.Stream; | ||
import javax.annotation.Nullable; | ||
|
||
// TODO(b/180081278): Rename this check to MissingRuntimeRetention | ||
/** | ||
* @author [email protected] (Steven Goldfeder) | ||
*/ | ||
@BugPattern( | ||
name = "InjectScopeOrQualifierAnnotationRetention", | ||
name = "MissingRuntimeRetention", | ||
altNames = "InjectScopeOrQualifierAnnotationRetention", | ||
summary = "Scoping and qualifier annotations must have runtime retention.", | ||
severity = ERROR) | ||
public class ScopeOrQualifierAnnotationRetention extends BugChecker implements ClassTreeMatcher { | ||
public class MissingRuntimeRetention extends BugChecker implements ClassTreeMatcher { | ||
|
||
private static final String RETENTION_ANNOTATION = "java.lang.annotation.Retention"; | ||
|
||
/** Matches classes that are qualifier, scope annotation or map binding keys. */ | ||
private static final Matcher<ClassTree> SCOPE_OR_QUALIFIER_ANNOTATION_MATCHER = | ||
allOf( | ||
kindIs(ANNOTATION_TYPE), | ||
anyOf( | ||
hasAnnotation(GUICE_SCOPE_ANNOTATION), | ||
hasAnnotation(JAVAX_SCOPE_ANNOTATION), | ||
hasAnnotation(GUICE_BINDING_ANNOTATION), | ||
hasAnnotation(JAVAX_QUALIFIER_ANNOTATION), | ||
hasAnnotation(GUICE_MAP_KEY_ANNOTATION), | ||
hasAnnotation(DAGGER_MAP_KEY_ANNOTATION))); | ||
private static final Supplier<ImmutableSet<Name>> INJECT_ANNOTATIONS = | ||
VisitorState.memoize( | ||
state -> | ||
Stream.of( | ||
GUICE_SCOPE_ANNOTATION, | ||
JAVAX_SCOPE_ANNOTATION, | ||
GUICE_BINDING_ANNOTATION, | ||
JAVAX_QUALIFIER_ANNOTATION, | ||
GUICE_MAP_KEY_ANNOTATION, | ||
DAGGER_MAP_KEY_ANNOTATION) | ||
.map(state::binaryNameFromClassname) | ||
.collect(toImmutableSet())); | ||
|
||
private static final Supplier<ImmutableSet<Name>> ANNOTATIONS = | ||
VisitorState.memoize( | ||
state -> | ||
Streams.concat( | ||
Stream.of("com.google.apps.framework.annotations.ProcessorAnnotation") | ||
.map(state::binaryNameFromClassname), | ||
INJECT_ANNOTATIONS.get(state).stream()) | ||
.collect(toImmutableSet())); | ||
|
||
@Override | ||
public final Description matchClass(ClassTree classTree, VisitorState state) { | ||
if (SCOPE_OR_QUALIFIER_ANNOTATION_MATCHER.matches(classTree, state)) { | ||
ClassSymbol classSymbol = ASTHelpers.getSymbol(classTree); | ||
if (hasSourceRetention(classSymbol)) { | ||
return describe(classTree, state, ASTHelpers.getAnnotation(classSymbol, Retention.class)); | ||
} | ||
if (!classTree.getKind().equals(ANNOTATION_TYPE)) { | ||
return NO_MATCH; | ||
} | ||
Set<Name> annotations = | ||
annotationsAmong(getDeclaredSymbol(classTree), ANNOTATIONS.get(state), state); | ||
if (annotations.isEmpty()) { | ||
return NO_MATCH; | ||
} | ||
ClassSymbol classSymbol = ASTHelpers.getSymbol(classTree); | ||
if (!doesNotHaveRuntimeRetention(classSymbol)) { | ||
return NO_MATCH; | ||
} | ||
if (!Collections.disjoint(annotations, INJECT_ANNOTATIONS.get(state)) | ||
&& exemptInjectAnnotation(state, classSymbol)) { | ||
return NO_MATCH; | ||
} | ||
return describe(classTree, state, ASTHelpers.getAnnotation(classSymbol, Retention.class)); | ||
} | ||
|
||
// TODO(glorioso): This is a poor hack to exclude android apps that are more likely to not | ||
// have reflective DI than normal java. JSR spec still says the annotations should be | ||
// runtime-retained, but this reduces the instances that are flagged. | ||
if (!state.isAndroidCompatible() && doesNotHaveRuntimeRetention(classSymbol)) { | ||
// Is this in a dagger component? | ||
ClassTree outer = ASTHelpers.findEnclosingNode(state.getPath(), ClassTree.class); | ||
if (outer != null | ||
&& allOf(InjectMatchers.IS_DAGGER_COMPONENT_OR_MODULE).matches(outer, state)) { | ||
return Description.NO_MATCH; | ||
} | ||
return describe(classTree, state, ASTHelpers.getAnnotation(classSymbol, Retention.class)); | ||
} | ||
private static boolean exemptInjectAnnotation(VisitorState state, ClassSymbol classSymbol) { | ||
// TODO(glorioso): This is a poor hack to exclude android apps that are more likely to not | ||
// have reflective DI than normal java. JSR spec still says the annotations should be | ||
// runtime-retained, but this reduces the instances that are flagged. | ||
if (hasSourceRetention(classSymbol)) { | ||
return false; | ||
} | ||
if (state.isAndroidCompatible()) { | ||
return true; | ||
} | ||
// Is this in a dagger component? | ||
ClassTree outer = ASTHelpers.findEnclosingNode(state.getPath(), ClassTree.class); | ||
if (outer != null | ||
&& allOf(InjectMatchers.IS_DAGGER_COMPONENT_OR_MODULE).matches(outer, state)) { | ||
return true; | ||
} | ||
return Description.NO_MATCH; | ||
return false; | ||
} | ||
|
||
private Description describe( | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -27,27 +27,22 @@ | |
* @author [email protected] (Steven Goldfeder) | ||
*/ | ||
@RunWith(JUnit4.class) | ||
public class ScopeOrQualifierAnnotationRetentionTest { | ||
public class MissingRuntimeRetentionTest { | ||
|
||
private final BugCheckerRefactoringTestHelper refactoringTestHelper = | ||
BugCheckerRefactoringTestHelper.newInstance( | ||
ScopeOrQualifierAnnotationRetention.class, getClass()); | ||
BugCheckerRefactoringTestHelper.newInstance(MissingRuntimeRetention.class, getClass()); | ||
|
||
private final CompilationTestHelper compilationHelper = | ||
CompilationTestHelper.newInstance(ScopeOrQualifierAnnotationRetention.class, getClass()); | ||
CompilationTestHelper.newInstance(MissingRuntimeRetention.class, getClass()); | ||
|
||
@Test | ||
public void positiveCase() { | ||
compilationHelper | ||
.addSourceFile("ScopeOrQualifierAnnotationRetentionPositiveCases.java") | ||
.doTest(); | ||
compilationHelper.addSourceFile("MissingRuntimeRetentionPositiveCases.java").doTest(); | ||
} | ||
|
||
@Test | ||
public void negativeCase() { | ||
compilationHelper | ||
.addSourceFile("ScopeOrQualifierAnnotationRetentionNegativeCases.java") | ||
.doTest(); | ||
compilationHelper.addSourceFile("MissingRuntimeRetentionNegativeCases.java").doTest(); | ||
} | ||
|
||
@Test | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -31,7 +31,7 @@ | |
/** | ||
* @author [email protected] (Steven Goldfeder) | ||
*/ | ||
public class ScopeOrQualifierAnnotationRetentionNegativeCases { | ||
public class MissingRuntimeRetentionNegativeCases { | ||
/** A scoping (@Scope) annotation with runtime retention */ | ||
@Scope | ||
@Target({TYPE, METHOD}) | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -30,7 +30,7 @@ | |
/** | ||
* @author [email protected] (Steven Goldfeder) | ||
*/ | ||
public class ScopeOrQualifierAnnotationRetentionPositiveCases { | ||
public class MissingRuntimeRetentionPositiveCases { | ||
/** A scoping (@Scope) annotation with SOURCE retention */ | ||
@Scope | ||
@Target({TYPE, METHOD}) | ||
|
File renamed without changes.