51
51
import java .util .List ;
52
52
import java .util .Map ;
53
53
import java .util .Set ;
54
+ import java .util .function .BiPredicate ;
54
55
import java .util .stream .Collectors ;
55
56
import java .util .stream .Stream ;
56
57
import javax .lang .model .element .AnnotationMirror ;
@@ -328,13 +329,13 @@ private static Stream<Attribute.TypeCompound> getTypeUseAnnotations(
328
329
return rawTypeAttributes .filter (
329
330
(t ) ->
330
331
t .position .type .equals (TargetType .METHOD_RETURN )
331
- && isDirectTypeUseAnnotation (t , symbol , config ));
332
+ && (! onlyDirect || isDirectTypeUseAnnotation (t , symbol , config ) ));
332
333
} else {
333
334
// filter for annotations directly on the type
334
335
return rawTypeAttributes .filter (
335
336
t ->
336
337
targetTypeMatches (symbol , t .position )
337
- && (!onlyDirect || NullabilityUtil . isDirectTypeUseAnnotation (t , symbol , config )));
338
+ && (!onlyDirect || isDirectTypeUseAnnotation (t , symbol , config )));
338
339
}
339
340
}
340
341
@@ -540,22 +541,11 @@ public static <T> T castToNonNull(@Nullable T obj) {
540
541
* otherwise
541
542
*/
542
543
public static boolean isArrayElementNullable (Symbol arraySymbol , Config config ) {
543
- for (Attribute .TypeCompound t : arraySymbol .getRawTypeAttributes ()) {
544
- for (TypeAnnotationPosition .TypePathEntry entry : t .position .location ) {
545
- if (entry .tag == TypeAnnotationPosition .TypePathEntryKind .ARRAY ) {
546
- if (Nullness .isNullableAnnotation (t .type .toString (), config )) {
547
- return true ;
548
- }
549
- }
550
- }
551
- }
552
- // For varargs symbols we also consider the elements to be @Nullable if there is a @Nullable
553
- // declaration annotation on the parameter
554
- // NOTE this flag check does not work for the varargs parameter of a method defined in bytecodes
555
- if ((arraySymbol .flags () & Flags .VARARGS ) != 0 ) {
556
- return Nullness .hasNullableDeclarationAnnotation (arraySymbol , config );
557
- }
558
- return false ;
544
+ return checkArrayElementAnnotations (
545
+ arraySymbol ,
546
+ config ,
547
+ Nullness ::isNullableAnnotation ,
548
+ Nullness ::hasNullableDeclarationAnnotation );
559
549
}
560
550
561
551
/**
@@ -582,12 +572,50 @@ public static boolean nullableVarargsElementsForSourceOrBytecode(
582
572
* otherwise
583
573
*/
584
574
public static boolean isArrayElementNonNull (Symbol arraySymbol , Config config ) {
575
+ return checkArrayElementAnnotations (
576
+ arraySymbol ,
577
+ config ,
578
+ Nullness ::isNonNullAnnotation ,
579
+ Nullness ::hasNonNullDeclarationAnnotation );
580
+ }
581
+
582
+ /**
583
+ * Checks if the given varargs symbol has a {@code @NonNull} annotation for its elements. Works
584
+ * for both source and bytecode.
585
+ *
586
+ * @param varargsSymbol the symbol of the varargs parameter
587
+ * @param config NullAway configuration
588
+ * @return true if the varargs symbol has a {@code @NonNull} annotation for its elements, false
589
+ * otherwise
590
+ */
591
+ public static boolean nonnullVarargsElementsForSourceOrBytecode (
592
+ Symbol varargsSymbol , Config config ) {
593
+ return isArrayElementNonNull (varargsSymbol , config )
594
+ || Nullness .hasNonNullDeclarationAnnotation (varargsSymbol , config );
595
+ }
596
+
597
+ /**
598
+ * Checks if the annotations on the elements of some array symbol satisfy some predicate.
599
+ *
600
+ * @param arraySymbol the array symbol
601
+ * @param config NullAway configuration
602
+ * @param typeUseCheck the predicate to check the type-use annotations
603
+ * @param declarationCheck the predicate to check the declaration annotations (applied only to
604
+ * varargs symbols)
605
+ * @return true if the annotations on the elements of the array symbol satisfy the given
606
+ * predicates, false otherwise
607
+ */
608
+ private static boolean checkArrayElementAnnotations (
609
+ Symbol arraySymbol ,
610
+ Config config ,
611
+ BiPredicate <String , Config > typeUseCheck ,
612
+ BiPredicate <Symbol , Config > declarationCheck ) {
585
613
if (getTypeUseAnnotations (arraySymbol , config , /* onlyDirect= */ false )
586
614
.anyMatch (
587
615
t -> {
588
616
for (TypeAnnotationPosition .TypePathEntry entry : t .position .location ) {
589
617
if (entry .tag == TypeAnnotationPosition .TypePathEntryKind .ARRAY ) {
590
- if (Nullness . isNonNullAnnotation (t .type .toString (), config )) {
618
+ if (typeUseCheck . test (t .type .toString (), config )) {
591
619
return true ;
592
620
}
593
621
}
@@ -596,30 +624,14 @@ public static boolean isArrayElementNonNull(Symbol arraySymbol, Config config) {
596
624
})) {
597
625
return true ;
598
626
}
599
- // For varargs symbols we also consider the elements to be @NonNull if there is a @NonNull
600
- // declaration annotation on the parameter
627
+ // For varargs symbols we also check for declaration annotations on the parameter
601
628
// NOTE this flag check does not work for the varargs parameter of a method defined in bytecodes
602
629
if ((arraySymbol .flags () & Flags .VARARGS ) != 0 ) {
603
- return Nullness . hasNonNullDeclarationAnnotation (arraySymbol , config );
630
+ return declarationCheck . test (arraySymbol , config );
604
631
}
605
632
return false ;
606
633
}
607
634
608
- /**
609
- * Checks if the given varargs symbol has a {@code @NonNull} annotation for its elements. Works
610
- * for both source and bytecode.
611
- *
612
- * @param varargsSymbol the symbol of the varargs parameter
613
- * @param config NullAway configuration
614
- * @return true if the varargs symbol has a {@code @NonNull} annotation for its elements, false
615
- * otherwise
616
- */
617
- public static boolean nonnullVarargsElementsForSourceOrBytecode (
618
- Symbol varargsSymbol , Config config ) {
619
- return isArrayElementNonNull (varargsSymbol , config )
620
- || Nullness .hasNonNullDeclarationAnnotation (varargsSymbol , config );
621
- }
622
-
623
635
/**
624
636
* Does the given symbol have a JetBrains @NotNull declaration annotation? Useful for workarounds
625
637
* in light of https://github.com/uber/NullAway/issues/720
0 commit comments