|
29 | 29 | import com.sun.source.tree.MemberSelectTree;
|
30 | 30 | import com.sun.source.tree.Tree;
|
31 | 31 | import com.sun.tools.javac.code.Symbol;
|
| 32 | +import com.sun.tools.javac.code.Symbol.MethodSymbol; |
32 | 33 | import javax.lang.model.element.AnnotationMirror;
|
| 34 | +import java.util.Set; |
33 | 35 |
|
34 | 36 | abstract class AnnotationChecker extends BugChecker implements IdentifierTreeMatcher,
|
35 | 37 | MemberSelectTreeMatcher {
|
36 | 38 |
|
37 | 39 | private final String annotationType;
|
38 | 40 |
|
| 41 | + // When this is set to true, method calls will look for an annotation on the top-level method |
| 42 | + // declaration. This is used to avoid io.grpc.internal implementations "hiding" publicly declared |
| 43 | + // API methods. |
| 44 | + protected boolean checkTopOfMethodHierarchy = false; |
| 45 | + |
39 | 46 | AnnotationChecker(String annotationType) {
|
40 | 47 | this.annotationType = checkNotNull(annotationType, "annotationType");
|
41 | 48 | }
|
@@ -64,6 +71,15 @@ private Description match(Tree tree, VisitorState state) {
|
64 | 71 | if (symbol == null) {
|
65 | 72 | return NO_MATCH;
|
66 | 73 | }
|
| 74 | + if (checkTopOfMethodHierarchy && symbol instanceof MethodSymbol) { |
| 75 | + // Returns an ordered LinkedHashSet |
| 76 | + Set<MethodSymbol> superMethods = |
| 77 | + ASTHelpers.findSuperMethods((MethodSymbol) symbol, state.getTypes()); |
| 78 | + for (MethodSymbol superMethod : superMethods) { |
| 79 | + // The last method in the set will be the top-level declaration |
| 80 | + symbol = superMethod; |
| 81 | + } |
| 82 | + } |
67 | 83 | AnnotationMirror annotation = findAnnotatedApi(symbol);
|
68 | 84 | if (annotation == null) {
|
69 | 85 | return NO_MATCH;
|
|
0 commit comments