From 75aa1de2a8f88f8c23347d86465844df9887874c Mon Sep 17 00:00:00 2001 From: "David P. Baker" Date: Wed, 7 Feb 2024 14:14:30 -0500 Subject: [PATCH] Report irrelevant `@NonNull` annotations (#153) --- .../jspecify/nullness/NullSpecVisitor.java | 17 +++-- .../jspecify/nullness/messages.properties | 8 +- src/test/java/tests/ConformanceTest.java | 8 +- tests/ConformanceTest-report.txt | 76 +++++++++---------- 4 files changed, 61 insertions(+), 48 deletions(-) diff --git a/src/main/java/com/google/jspecify/nullness/NullSpecVisitor.java b/src/main/java/com/google/jspecify/nullness/NullSpecVisitor.java index f6dba3d..a2d1a67 100644 --- a/src/main/java/com/google/jspecify/nullness/NullSpecVisitor.java +++ b/src/main/java/com/google/jspecify/nullness/NullSpecVisitor.java @@ -28,6 +28,7 @@ import static javax.lang.model.element.ElementKind.ENUM_CONSTANT; import static javax.lang.model.element.ElementKind.PACKAGE; import static org.checkerframework.framework.util.AnnotatedTypes.asSuper; +import static org.checkerframework.javacutil.AnnotationUtils.annotationName; import static org.checkerframework.javacutil.AnnotationUtils.areSameByName; import static org.checkerframework.javacutil.TreeUtils.annotationsFromTypeAnnotationTrees; import static org.checkerframework.javacutil.TreeUtils.elementFromDeclaration; @@ -579,15 +580,21 @@ private void checkNoNullnessAnnotations( * represent the types internally in AnnotatedTypeMirror instances. Contrast this to almost * all other logic in the checker, which operates on the internal types. */ - if (areSameByName(annotation, "org.jspecify.annotations.Nullable") - || areSameByName(annotation, "org.jspecify.annotations.NullnessUnspecified") - || areSameByName(annotation, "org.jspecify.nullness.Nullable") - || areSameByName(annotation, "org.jspecify.nullness.NullnessUnspecified")) { - checker.reportError(treeToReportOn, messageKey); + if (NULLNESS_ANNOTATIONS.stream().anyMatch(na -> areSameByName(annotation, na))) { + checker.reportError(treeToReportOn, messageKey, annotationName(annotation)); } } } + private static final Set NULLNESS_ANNOTATIONS = + Set.of( + "org.jspecify.annotations.NonNull", + "org.jspecify.annotations.Nullable", + "org.jspecify.annotations.NullnessUnspecified", + "org.jspecify.nullness.NonNull", + "org.jspecify.nullness.Nullable", + "org.jspecify.nullness.NullnessUnspecified"); + @Override protected boolean checkMethodReferenceAsOverride(MemberReferenceTree tree, Void p) { /* diff --git a/src/main/resources/com/google/jspecify/nullness/messages.properties b/src/main/resources/com/google/jspecify/nullness/messages.properties index 53b25f2..d4c8dcd 100644 --- a/src/main/resources/com/google/jspecify/nullness/messages.properties +++ b/src/main/resources/com/google/jspecify/nullness/messages.properties @@ -1,9 +1,9 @@ atomicreference.must.include.null=expected a @Nullable type argument or else an initial-value constructor argument. The no-arg AtomicReference constructor sets the initial value to null, which is not compatible with %s. dereference=possible null dereference on type %s enum.constant.annotated=illegal location for annotation: enum constants are always non-null -local.variable.annotated=illegal location for annotation: local variables have their nullness automatically inferred (except for their type arguments, as in `List<@Nullable String>`) +local.variable.annotated=illegal location for annotation %s: local variables have their nullness automatically inferred (except for their type arguments, as in `List<@Nullable String>`) outer.annotated=illegal location for annotation: outer types are always non-null. To annotate the inner type, write `Foo.@Nullable Bar` instead of `@Nullable Foo.Bar`. -primitive.annotated=illegal location for annotation: primitives are always non-null. To annotate an array of primitives as nullable, write `int @Nullable[]` instead of `@Nullable int[]`. +primitive.annotated=illegal location for annotation %s: primitives are always non-null. To annotate an array of primitives as nullable, write `int @Nullable[]` instead of `@Nullable int[]`. threadlocal.must.include.null=expected a @Nullable type argument or else an override of initialValue(). Without an override of initialValue(), ThreadLocal.get() may return null, which is not compatible with %s. -type.parameter.annotated=illegal location for annotation: type parameter declarations do not have a nullness. To declare that a type parameter may be instantiated with nullable types, write `T extends @Nullable Object` instead of `@Nullable T`. -wildcard.annotated=illegal location for annotation: wildcard declarations do not have a nullness. To declare that a wildcard may match nullable types, write `? extends @Nullable Object` instead of `@Nullable ?`. Or, in null-aware code, simply write `?`. +type.parameter.annotated=illegal location for annotation %s: type parameter declarations do not have a nullness. To declare that a type parameter may be instantiated with nullable types, write `T extends @Nullable Object` instead of `@Nullable T`. +wildcard.annotated=illegal location for annotation %s: wildcard declarations do not have a nullness. To declare that a wildcard may match nullable types, write `? extends @Nullable Object` instead of `@Nullable ?`. Or, in null-aware code, simply write `?`. diff --git a/src/test/java/tests/ConformanceTest.java b/src/test/java/tests/ConformanceTest.java index 5789f2b..275a364 100644 --- a/src/test/java/tests/ConformanceTest.java +++ b/src/test/java/tests/ConformanceTest.java @@ -209,7 +209,13 @@ protected String getFactText() { return cannotConvert(sourceType, sinkType); } if (IRRELEVANT_ANNOTATION_KEYS.contains(detailMessage.messageKey)) { - return irrelevantAnnotation("Nullable"); // TODO(dpb): Support other annotations. + if (detailMessage.messageArguments.isEmpty()) { + // arguments must start with the annotation + return toString(); + } + return irrelevantAnnotation( + // Remove the package name (and any enclosing element name); emit just the simple name. + detailMessage.messageArguments.get(0).replaceFirst(".*\\.", "")); } switch (detailMessage.messageKey) { case "sourceType": diff --git a/tests/ConformanceTest-report.txt b/tests/ConformanceTest-report.txt index 78c664e..23c8a51 100644 --- a/tests/ConformanceTest-report.txt +++ b/tests/ConformanceTest-report.txt @@ -1,4 +1,4 @@ -# 53 pass; 61 fail; 114 total; 46.5% score +# 90 pass; 24 fail; 114 total; 78.9% score PASS: Basic.java:28:test:expression-type:Object?:nullable PASS: Basic.java:28:test:sink-type:Object!:return PASS: Basic.java:28:test:cannot-convert:Object? to Object! @@ -10,7 +10,7 @@ FAIL: Basic.java:49:test:expression-type:List!:nul PASS: Basic.java: no unexpected facts PASS: Irrelevant.java:28:test:irrelevant-annotation:Nullable PASS: Irrelevant.java:34:test:irrelevant-annotation:Nullable -FAIL: Irrelevant.java:38:test:irrelevant-annotation:NonNull +PASS: Irrelevant.java:38:test:irrelevant-annotation:NonNull FAIL: Irrelevant.java:43:test:irrelevant-annotation:NonNull FAIL: Irrelevant.java:43:test:irrelevant-annotation:Nullable FAIL: Irrelevant.java:47:test:irrelevant-annotation:NullMarked @@ -19,62 +19,62 @@ FAIL: Irrelevant.java: no unexpected facts PASS: UsesDep.java:24:test:cannot-convert:null? to Dep* PASS: UsesDep.java: no unexpected facts PASS: irrelevantannotations/notnullmarked/AnnotatedTypeParameters.java:Nullable on simple type parameter on method:test:irrelevant-annotation:Nullable -FAIL: irrelevantannotations/notnullmarked/AnnotatedTypeParameters.java:NonNull on simple type parameter on method:test:irrelevant-annotation:NonNull +PASS: irrelevantannotations/notnullmarked/AnnotatedTypeParameters.java:NonNull on simple type parameter on method:test:irrelevant-annotation:NonNull PASS: irrelevantannotations/notnullmarked/AnnotatedTypeParameters.java:Nullable on bounded type parameter on method:test:irrelevant-annotation:Nullable -FAIL: irrelevantannotations/notnullmarked/AnnotatedTypeParameters.java:NonNull on bounded type parameter on method:test:irrelevant-annotation:NonNull -FAIL: irrelevantannotations/notnullmarked/AnnotatedTypeParameters.java:NonNull on annotated-bounded type parameter on method:test:irrelevant-annotation:NonNull +PASS: irrelevantannotations/notnullmarked/AnnotatedTypeParameters.java:NonNull on bounded type parameter on method:test:irrelevant-annotation:NonNull +PASS: irrelevantannotations/notnullmarked/AnnotatedTypeParameters.java:NonNull on annotated-bounded type parameter on method:test:irrelevant-annotation:NonNull PASS: irrelevantannotations/notnullmarked/AnnotatedTypeParameters.java:Nullable on annotated-bounded type parameter on method:test:irrelevant-annotation:Nullable PASS: irrelevantannotations/notnullmarked/AnnotatedTypeParameters.java:Nullable on simple type parameter on class:test:irrelevant-annotation:Nullable -FAIL: irrelevantannotations/notnullmarked/AnnotatedTypeParameters.java:NonNull on simple type parameter on class:test:irrelevant-annotation:NonNull +PASS: irrelevantannotations/notnullmarked/AnnotatedTypeParameters.java:NonNull on simple type parameter on class:test:irrelevant-annotation:NonNull PASS: irrelevantannotations/notnullmarked/AnnotatedTypeParameters.java:Nullable on bounded type parameter on class:test:irrelevant-annotation:Nullable -FAIL: irrelevantannotations/notnullmarked/AnnotatedTypeParameters.java:NonNull on bounded type parameter on class:test:irrelevant-annotation:NonNull -FAIL: irrelevantannotations/notnullmarked/AnnotatedTypeParameters.java:NonNull on annotated-bounded type parameter on class:test:irrelevant-annotation:NonNull +PASS: irrelevantannotations/notnullmarked/AnnotatedTypeParameters.java:NonNull on bounded type parameter on class:test:irrelevant-annotation:NonNull +PASS: irrelevantannotations/notnullmarked/AnnotatedTypeParameters.java:NonNull on annotated-bounded type parameter on class:test:irrelevant-annotation:NonNull PASS: irrelevantannotations/notnullmarked/AnnotatedTypeParameters.java:Nullable on annotated-bounded type parameter on class:test:irrelevant-annotation:Nullable FAIL: irrelevantannotations/notnullmarked/AnnotatedTypeParameters.java: no unexpected facts PASS: irrelevantannotations/notnullmarked/AnnotatedWildcards.java:Nullable on unbounded wildcard:test:irrelevant-annotation:Nullable -FAIL: irrelevantannotations/notnullmarked/AnnotatedWildcards.java:NonNull on unbounded wildcard:test:irrelevant-annotation:NonNull +PASS: irrelevantannotations/notnullmarked/AnnotatedWildcards.java:NonNull on unbounded wildcard:test:irrelevant-annotation:NonNull PASS: irrelevantannotations/notnullmarked/AnnotatedWildcards.java:Nullable on bounded wildcard:test:irrelevant-annotation:Nullable -FAIL: irrelevantannotations/notnullmarked/AnnotatedWildcards.java:NonNull on bounded wildcard:test:irrelevant-annotation:NonNull -FAIL: irrelevantannotations/notnullmarked/AnnotatedWildcards.java:NonNull on annotated-bounded wildcard:test:irrelevant-annotation:NonNull +PASS: irrelevantannotations/notnullmarked/AnnotatedWildcards.java:NonNull on bounded wildcard:test:irrelevant-annotation:NonNull +PASS: irrelevantannotations/notnullmarked/AnnotatedWildcards.java:NonNull on annotated-bounded wildcard:test:irrelevant-annotation:NonNull PASS: irrelevantannotations/notnullmarked/AnnotatedWildcards.java:Nullable on annotated-bounded wildcard:test:irrelevant-annotation:Nullable FAIL: irrelevantannotations/notnullmarked/AnnotatedWildcards.java: no unexpected facts PASS: irrelevantannotations/notnullmarked/Other.java:Nullable local variable object:test:irrelevant-annotation:Nullable -FAIL: irrelevantannotations/notnullmarked/Other.java:NonNull local variable object:test:irrelevant-annotation:NonNull +PASS: irrelevantannotations/notnullmarked/Other.java:NonNull local variable object:test:irrelevant-annotation:NonNull PASS: irrelevantannotations/notnullmarked/Other.java:Nullable local variable array:test:irrelevant-annotation:Nullable -FAIL: irrelevantannotations/notnullmarked/Other.java:NonNull local variable array:test:irrelevant-annotation:NonNull +PASS: irrelevantannotations/notnullmarked/Other.java:NonNull local variable array:test:irrelevant-annotation:NonNull PASS: irrelevantannotations/notnullmarked/Other.java:Nullable exception parameter:test:irrelevant-annotation:Nullable -FAIL: irrelevantannotations/notnullmarked/Other.java:NonNull exception parameter:test:irrelevant-annotation:NonNull +PASS: irrelevantannotations/notnullmarked/Other.java:NonNull exception parameter:test:irrelevant-annotation:NonNull PASS: irrelevantannotations/notnullmarked/Other.java:Nullable try-with-resources:test:irrelevant-annotation:Nullable FAIL: irrelevantannotations/notnullmarked/Other.java:NonNull try-with-resources:test:irrelevant-annotation:NonNull FAIL: irrelevantannotations/notnullmarked/Other.java:Nullable exception type:test:irrelevant-annotation:Nullable FAIL: irrelevantannotations/notnullmarked/Other.java:NonNull exception type:test:irrelevant-annotation:NonNulll FAIL: irrelevantannotations/notnullmarked/Other.java: no unexpected facts PASS: irrelevantannotations/nullmarked/AnnotatedTypeParameters.java:Nullable on simple type parameter on method:test:irrelevant-annotation:Nullable -FAIL: irrelevantannotations/nullmarked/AnnotatedTypeParameters.java:NonNull on simple type parameter on method:test:irrelevant-annotation:NonNull +PASS: irrelevantannotations/nullmarked/AnnotatedTypeParameters.java:NonNull on simple type parameter on method:test:irrelevant-annotation:NonNull PASS: irrelevantannotations/nullmarked/AnnotatedTypeParameters.java:Nullable on bounded type parameter on method:test:irrelevant-annotation:Nullable -FAIL: irrelevantannotations/nullmarked/AnnotatedTypeParameters.java:NonNull on bounded type parameter on method:test:irrelevant-annotation:NonNull -FAIL: irrelevantannotations/nullmarked/AnnotatedTypeParameters.java:NonNull on annotated-bounded type parameter on method:test:irrelevant-annotation:NonNull +PASS: irrelevantannotations/nullmarked/AnnotatedTypeParameters.java:NonNull on bounded type parameter on method:test:irrelevant-annotation:NonNull +PASS: irrelevantannotations/nullmarked/AnnotatedTypeParameters.java:NonNull on annotated-bounded type parameter on method:test:irrelevant-annotation:NonNull PASS: irrelevantannotations/nullmarked/AnnotatedTypeParameters.java:Nullable on annotated-bounded type parameter on method:test:irrelevant-annotation:Nullable PASS: irrelevantannotations/nullmarked/AnnotatedTypeParameters.java:Nullable on simple type parameter on class:test:irrelevant-annotation:Nullable -FAIL: irrelevantannotations/nullmarked/AnnotatedTypeParameters.java:NonNull on simple type parameter on class:test:irrelevant-annotation:NonNull +PASS: irrelevantannotations/nullmarked/AnnotatedTypeParameters.java:NonNull on simple type parameter on class:test:irrelevant-annotation:NonNull PASS: irrelevantannotations/nullmarked/AnnotatedTypeParameters.java:Nullable on bounded type parameter on class:test:irrelevant-annotation:Nullable -FAIL: irrelevantannotations/nullmarked/AnnotatedTypeParameters.java:NonNull on bounded type parameter on class:test:irrelevant-annotation:NonNull -FAIL: irrelevantannotations/nullmarked/AnnotatedTypeParameters.java:NonNull on annotated-bounded type parameter on class:test:irrelevant-annotation:NonNull +PASS: irrelevantannotations/nullmarked/AnnotatedTypeParameters.java:NonNull on bounded type parameter on class:test:irrelevant-annotation:NonNull +PASS: irrelevantannotations/nullmarked/AnnotatedTypeParameters.java:NonNull on annotated-bounded type parameter on class:test:irrelevant-annotation:NonNull PASS: irrelevantannotations/nullmarked/AnnotatedTypeParameters.java:Nullable on annotated-bounded type parameter on class:test:irrelevant-annotation:Nullable FAIL: irrelevantannotations/nullmarked/AnnotatedTypeParameters.java: no unexpected facts PASS: irrelevantannotations/nullmarked/AnnotatedWildcards.java:Nullable on unbounded wildcard:test:irrelevant-annotation:Nullable -FAIL: irrelevantannotations/nullmarked/AnnotatedWildcards.java:NonNull on unbounded wildcard:test:irrelevant-annotation:NonNull +PASS: irrelevantannotations/nullmarked/AnnotatedWildcards.java:NonNull on unbounded wildcard:test:irrelevant-annotation:NonNull PASS: irrelevantannotations/nullmarked/AnnotatedWildcards.java:Nullable on bounded wildcard:test:irrelevant-annotation:Nullable -FAIL: irrelevantannotations/nullmarked/AnnotatedWildcards.java:NonNull on bounded wildcard:test:irrelevant-annotation:NonNull -FAIL: irrelevantannotations/nullmarked/AnnotatedWildcards.java:NonNull on annotated-bounded wildcard:test:irrelevant-annotation:NonNull +PASS: irrelevantannotations/nullmarked/AnnotatedWildcards.java:NonNull on bounded wildcard:test:irrelevant-annotation:NonNull +PASS: irrelevantannotations/nullmarked/AnnotatedWildcards.java:NonNull on annotated-bounded wildcard:test:irrelevant-annotation:NonNull PASS: irrelevantannotations/nullmarked/AnnotatedWildcards.java:Nullable on annotated-bounded wildcard:test:irrelevant-annotation:Nullable FAIL: irrelevantannotations/nullmarked/AnnotatedWildcards.java: no unexpected facts PASS: irrelevantannotations/nullmarked/Other.java:Nullable local variable object:test:irrelevant-annotation:Nullable -FAIL: irrelevantannotations/nullmarked/Other.java:NonNull local variable object:test:irrelevant-annotation:NonNull +PASS: irrelevantannotations/nullmarked/Other.java:NonNull local variable object:test:irrelevant-annotation:NonNull PASS: irrelevantannotations/nullmarked/Other.java:Nullable local variable array:test:irrelevant-annotation:Nullable -FAIL: irrelevantannotations/nullmarked/Other.java:NonNull local variable array:test:irrelevant-annotation:NonNull +PASS: irrelevantannotations/nullmarked/Other.java:NonNull local variable array:test:irrelevant-annotation:NonNull PASS: irrelevantannotations/nullmarked/Other.java:Nullable exception parameter:test:irrelevant-annotation:Nullable -FAIL: irrelevantannotations/nullmarked/Other.java:NonNull exception parameter:test:irrelevant-annotation:NonNull +PASS: irrelevantannotations/nullmarked/Other.java:NonNull exception parameter:test:irrelevant-annotation:NonNull PASS: irrelevantannotations/nullmarked/Other.java:Nullable try-with-resources:test:irrelevant-annotation:Nullable FAIL: irrelevantannotations/nullmarked/Other.java:NonNull try-with-resources:test:irrelevant-annotation:NonNull FAIL: irrelevantannotations/nullmarked/Other.java:Nullable exception type:test:irrelevant-annotation:Nullable @@ -82,31 +82,31 @@ FAIL: irrelevantannotations/nullmarked/Other.java:NonNull exception type:test:ir FAIL: irrelevantannotations/nullmarked/Other.java: no unexpected facts PASS: irrelevantannotations/nullmarked/package-info.java: no unexpected facts PASS: irrelevantannotations/nullunmarked/AnnotatedTypeParameters.java:Nullable on simple type parameter on method:test:irrelevant-annotation:Nullable -FAIL: irrelevantannotations/nullunmarked/AnnotatedTypeParameters.java:NonNull on simple type parameter on method:test:irrelevant-annotation:NonNull +PASS: irrelevantannotations/nullunmarked/AnnotatedTypeParameters.java:NonNull on simple type parameter on method:test:irrelevant-annotation:NonNull PASS: irrelevantannotations/nullunmarked/AnnotatedTypeParameters.java:Nullable on bounded type parameter on method:test:irrelevant-annotation:Nullable -FAIL: irrelevantannotations/nullunmarked/AnnotatedTypeParameters.java:NonNull on bounded type parameter on method:test:irrelevant-annotation:NonNull -FAIL: irrelevantannotations/nullunmarked/AnnotatedTypeParameters.java:NonNull on annotated-bounded type parameter on method:test:irrelevant-annotation:NonNull +PASS: irrelevantannotations/nullunmarked/AnnotatedTypeParameters.java:NonNull on bounded type parameter on method:test:irrelevant-annotation:NonNull +PASS: irrelevantannotations/nullunmarked/AnnotatedTypeParameters.java:NonNull on annotated-bounded type parameter on method:test:irrelevant-annotation:NonNull PASS: irrelevantannotations/nullunmarked/AnnotatedTypeParameters.java:Nullable on annotated-bounded type parameter on method:test:irrelevant-annotation:Nullable PASS: irrelevantannotations/nullunmarked/AnnotatedTypeParameters.java:Nullable on simple type parameter on class:test:irrelevant-annotation:Nullable -FAIL: irrelevantannotations/nullunmarked/AnnotatedTypeParameters.java:NonNull on simple type parameter on class:test:irrelevant-annotation:NonNull +PASS: irrelevantannotations/nullunmarked/AnnotatedTypeParameters.java:NonNull on simple type parameter on class:test:irrelevant-annotation:NonNull PASS: irrelevantannotations/nullunmarked/AnnotatedTypeParameters.java:Nullable on bounded type parameter on class:test:irrelevant-annotation:Nullable -FAIL: irrelevantannotations/nullunmarked/AnnotatedTypeParameters.java:NonNull on bounded type parameter on class:test:irrelevant-annotation:NonNull -FAIL: irrelevantannotations/nullunmarked/AnnotatedTypeParameters.java:NonNull on annotated-bounded type parameter on class:test:irrelevant-annotation:NonNull +PASS: irrelevantannotations/nullunmarked/AnnotatedTypeParameters.java:NonNull on bounded type parameter on class:test:irrelevant-annotation:NonNull +PASS: irrelevantannotations/nullunmarked/AnnotatedTypeParameters.java:NonNull on annotated-bounded type parameter on class:test:irrelevant-annotation:NonNull PASS: irrelevantannotations/nullunmarked/AnnotatedTypeParameters.java:Nullable on annotated-bounded type parameter on class:test:irrelevant-annotation:Nullable FAIL: irrelevantannotations/nullunmarked/AnnotatedTypeParameters.java: no unexpected facts PASS: irrelevantannotations/nullunmarked/AnnotatedWildcards.java:Nullable on unbounded wildcard:test:irrelevant-annotation:Nullable -FAIL: irrelevantannotations/nullunmarked/AnnotatedWildcards.java:NonNull on unbounded wildcard:test:irrelevant-annotation:NonNull +PASS: irrelevantannotations/nullunmarked/AnnotatedWildcards.java:NonNull on unbounded wildcard:test:irrelevant-annotation:NonNull PASS: irrelevantannotations/nullunmarked/AnnotatedWildcards.java:Nullable on bounded wildcard:test:irrelevant-annotation:Nullable -FAIL: irrelevantannotations/nullunmarked/AnnotatedWildcards.java:NonNull on bounded wildcard:test:irrelevant-annotation:NonNull -FAIL: irrelevantannotations/nullunmarked/AnnotatedWildcards.java:NonNull on annotated-bounded wildcard:test:irrelevant-annotation:NonNull +PASS: irrelevantannotations/nullunmarked/AnnotatedWildcards.java:NonNull on bounded wildcard:test:irrelevant-annotation:NonNull +PASS: irrelevantannotations/nullunmarked/AnnotatedWildcards.java:NonNull on annotated-bounded wildcard:test:irrelevant-annotation:NonNull PASS: irrelevantannotations/nullunmarked/AnnotatedWildcards.java:Nullable on annotated-bounded wildcard:test:irrelevant-annotation:Nullable FAIL: irrelevantannotations/nullunmarked/AnnotatedWildcards.java: no unexpected facts PASS: irrelevantannotations/nullunmarked/Other.java:Nullable local variable object:test:irrelevant-annotation:Nullable -FAIL: irrelevantannotations/nullunmarked/Other.java:NonNull local variable object:test:irrelevant-annotation:NonNull +PASS: irrelevantannotations/nullunmarked/Other.java:NonNull local variable object:test:irrelevant-annotation:NonNull PASS: irrelevantannotations/nullunmarked/Other.java:Nullable local variable array:test:irrelevant-annotation:Nullable -FAIL: irrelevantannotations/nullunmarked/Other.java:NonNull local variable array:test:irrelevant-annotation:NonNull +PASS: irrelevantannotations/nullunmarked/Other.java:NonNull local variable array:test:irrelevant-annotation:NonNull PASS: irrelevantannotations/nullunmarked/Other.java:Nullable exception parameter:test:irrelevant-annotation:Nullable -FAIL: irrelevantannotations/nullunmarked/Other.java:NonNull exception parameter:test:irrelevant-annotation:NonNull +PASS: irrelevantannotations/nullunmarked/Other.java:NonNull exception parameter:test:irrelevant-annotation:NonNull PASS: irrelevantannotations/nullunmarked/Other.java:Nullable try-with-resources:test:irrelevant-annotation:Nullable FAIL: irrelevantannotations/nullunmarked/Other.java:NonNull try-with-resources:test:irrelevant-annotation:NonNull FAIL: irrelevantannotations/nullunmarked/Other.java:Nullable exception type:test:irrelevant-annotation:Nullable