diff --git a/check_api/src/main/java/com/google/errorprone/dataflow/nullnesspropagation/NullnessAnnotations.java b/check_api/src/main/java/com/google/errorprone/dataflow/nullnesspropagation/NullnessAnnotations.java index 6a4bb884b38..b9c53406d7b 100644 --- a/check_api/src/main/java/com/google/errorprone/dataflow/nullnesspropagation/NullnessAnnotations.java +++ b/check_api/src/main/java/com/google/errorprone/dataflow/nullnesspropagation/NullnessAnnotations.java @@ -93,13 +93,11 @@ public static Optional fromAnnotationsOn(@Nullable Symbol sym) { * We try to read annotations in two ways: * * 1. from the TypeMirror: This is how we "should" always read *type-use* annotations, but - * JDK-8225377 prevents it from working across compilation boundaries. + * we can't rely on it until the fix for JDK-8225377 is widely available. * * 2. from getRawAttributes(): This works around the problem across compilation boundaries, and * it handles declaration annotations (though there are other ways we could handle declaration - * annotations). But it has a bug of its own with type-use annotations on inner classes - * (b/203207989). To reduce the chance that we hit the inner-class bug, we apply it only if the - * first approach fails. + * annotations). */ TypeMirror elementType; switch (sym.getKind()) { diff --git a/check_api/src/main/java/com/google/errorprone/util/MoreAnnotations.java b/check_api/src/main/java/com/google/errorprone/util/MoreAnnotations.java index 7f76b18ff2e..5ea7a61acd0 100644 --- a/check_api/src/main/java/com/google/errorprone/util/MoreAnnotations.java +++ b/check_api/src/main/java/com/google/errorprone/util/MoreAnnotations.java @@ -27,7 +27,9 @@ import com.sun.tools.javac.code.Symbol; import com.sun.tools.javac.code.Symbol.MethodSymbol; import com.sun.tools.javac.code.TargetType; +import com.sun.tools.javac.code.Type; import com.sun.tools.javac.code.TypeAnnotationPosition; +import com.sun.tools.javac.code.TypeTag; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; @@ -92,9 +94,38 @@ public static Stream getTopLevelTypeAttributes(Symbol sym) { } private static boolean isAnnotationOnType(Symbol sym, TypeAnnotationPosition position) { - if (!position.location.isEmpty()) { + if (!position.location.stream() + .allMatch(e -> e.tag == TypeAnnotationPosition.TypePathEntryKind.INNER_TYPE)) { return false; } + if (!targetTypeMatches(sym, position)) { + return false; + } + Type type; + switch (sym.getKind()) { + case METHOD: + case CONSTRUCTOR: + type = ((MethodSymbol) sym).getReturnType(); + break; + default: + type = sym.asType(); + } + return isAnnotationOnType(type, position.location); + } + + private static boolean isAnnotationOnType( + Type type, com.sun.tools.javac.util.List location) { + com.sun.tools.javac.util.List expected = + com.sun.tools.javac.util.List.nil(); + for (Type curr = type.getEnclosingType(); + curr != null && !curr.hasTag(TypeTag.NONE); + curr = curr.getEnclosingType()) { + expected = expected.append(TypeAnnotationPosition.TypePathEntry.INNER_TYPE); + } + return expected.equals(location); + } + + private static boolean targetTypeMatches(Symbol sym, TypeAnnotationPosition position) { switch (sym.getKind()) { case LOCAL_VARIABLE: return position.type == TargetType.LOCAL_VARIABLE;