@@ -115,6 +115,7 @@ final class NullSpecAnnotatedTypeFactory
115
115
private final AnnotationMirror minusNull ;
116
116
private final AnnotationMirror unionNull ;
117
117
private final AnnotationMirror nullnessOperatorUnspecified ;
118
+ private final AnnotationMirror parametricNull ;
118
119
119
120
private final boolean isLeastConvenientWorld ;
120
121
private final NullSpecAnnotatedTypeFactory withLeastConvenientWorld ;
@@ -128,6 +129,11 @@ final class NullSpecAnnotatedTypeFactory
128
129
final AnnotatedDeclaredType javaLangThreadLocal ;
129
130
final AnnotatedDeclaredType javaUtilMap ;
130
131
132
+ // Ensure that all locations that appear in the `defaultLocations` also appear somewhere in the
133
+ // `nullMarkedLocations`.
134
+ // As defaults are added and removed to the same environment, we need to ensure that all values
135
+ // are correctly changed.
136
+
131
137
private static final TypeUseLocation [] defaultLocationsMinusNull =
132
138
new TypeUseLocation [] {
133
139
TypeUseLocation .CONSTRUCTOR_RESULT ,
@@ -138,14 +144,38 @@ final class NullSpecAnnotatedTypeFactory
138
144
139
145
private static final TypeUseLocation [] defaultLocationsUnionNull =
140
146
new TypeUseLocation [] {
141
- TypeUseLocation .LOCAL_VARIABLE , TypeUseLocation .RESOURCE_VARIABLE ,
147
+ TypeUseLocation .IMPLICIT_WILDCARD_UPPER_BOUND_SUPER ,
148
+ TypeUseLocation .LOCAL_VARIABLE ,
149
+ TypeUseLocation .RESOURCE_VARIABLE ,
142
150
};
143
151
144
152
private static final TypeUseLocation [] defaultLocationsUnspecified =
145
153
new TypeUseLocation [] {
146
- // TypeUseLocation.UNBOUNDED_WILDCARD_UPPER_BOUND, TODO
154
+ TypeUseLocation .IMPLICIT_WILDCARD_UPPER_BOUND_NO_SUPER ,
155
+ TypeUseLocation .TYPE_VARIABLE_USE ,
156
+ TypeUseLocation .OTHERWISE
157
+ };
158
+
159
+ private static final TypeUseLocation [] nullMarkedLocationsMinusNull =
160
+ new TypeUseLocation [] {
161
+ TypeUseLocation .CONSTRUCTOR_RESULT ,
162
+ TypeUseLocation .EXCEPTION_PARAMETER ,
163
+ TypeUseLocation .IMPLICIT_LOWER_BOUND ,
164
+ TypeUseLocation .RECEIVER ,
147
165
TypeUseLocation .OTHERWISE
148
166
};
167
+ private static final TypeUseLocation [] nullMarkedLocationsUnionNull =
168
+ new TypeUseLocation [] {
169
+ TypeUseLocation .LOCAL_VARIABLE ,
170
+ TypeUseLocation .RESOURCE_VARIABLE ,
171
+ TypeUseLocation .IMPLICIT_WILDCARD_UPPER_BOUND_NO_SUPER ,
172
+ TypeUseLocation .IMPLICIT_WILDCARD_UPPER_BOUND_SUPER ,
173
+ };
174
+
175
+ private static final TypeUseLocation [] nullMarkedLocationsParametric =
176
+ new TypeUseLocation [] {TypeUseLocation .TYPE_VARIABLE_USE };
177
+
178
+ private static final TypeUseLocation [] nullMarkedLocationsUnspecified = new TypeUseLocation [] {};
149
179
150
180
/** Constructor that takes all configuration from the provided {@code checker}. */
151
181
NullSpecAnnotatedTypeFactory (BaseTypeChecker checker , Util util ) {
@@ -170,6 +200,7 @@ private NullSpecAnnotatedTypeFactory(
170
200
minusNull = util .minusNull ;
171
201
unionNull = util .unionNull ;
172
202
nullnessOperatorUnspecified = util .nullnessOperatorUnspecified ;
203
+ parametricNull = util .parametricNull ;
173
204
174
205
addAliasedTypeAnnotation (
175
206
"org.jspecify.annotations.NullnessUnspecified" , nullnessOperatorUnspecified );
@@ -187,30 +218,36 @@ private NullSpecAnnotatedTypeFactory(
187
218
AnnotationMirror nullMarkedDefaultQualMinusNull =
188
219
new AnnotationBuilder (processingEnv , DefaultQualifier .class )
189
220
.setValue ("value" , MinusNull .class )
190
- .setValue (
191
- "locations" ,
192
- new TypeUseLocation [] {
193
- TypeUseLocation .EXCEPTION_PARAMETER , TypeUseLocation .OTHERWISE
194
- })
221
+ .setValue ("locations" , nullMarkedLocationsMinusNull )
195
222
.setValue ("applyToSubpackages" , false )
196
223
.build ();
197
224
AnnotationMirror nullMarkedDefaultQualUnionNull =
198
225
new AnnotationBuilder (processingEnv , DefaultQualifier .class )
199
226
.setValue ("value" , Nullable .class )
200
- .setValue (
201
- "locations" ,
202
- new TypeUseLocation [] {
203
- TypeUseLocation .LOCAL_VARIABLE , TypeUseLocation .RESOURCE_VARIABLE ,
204
- // TypeUseLocation.UNBOUNDED_WILDCARD_UPPER_BOUND TODO
205
- })
227
+ .setValue ("locations" , nullMarkedLocationsUnionNull )
228
+ .setValue ("applyToSubpackages" , false )
229
+ .build ();
230
+ AnnotationMirror nullMarkedDefaultQualParametric =
231
+ new AnnotationBuilder (processingEnv , DefaultQualifier .class )
232
+ .setValue ("value" , ParametricNull .class )
233
+ .setValue ("locations" , nullMarkedLocationsParametric )
234
+ .setValue ("applyToSubpackages" , false )
235
+ .build ();
236
+ AnnotationMirror nullMarkedDefaultQualUnspecified =
237
+ new AnnotationBuilder (processingEnv , DefaultQualifier .class )
238
+ .setValue ("value" , NullnessUnspecified .class )
239
+ .setValue ("locations" , nullMarkedLocationsUnspecified )
206
240
.setValue ("applyToSubpackages" , false )
207
241
.build ();
208
242
AnnotationMirror nullMarkedDefaultQual =
209
243
new AnnotationBuilder (processingEnv , DefaultQualifier .List .class )
210
244
.setValue (
211
245
"value" ,
212
246
new AnnotationMirror [] {
213
- nullMarkedDefaultQualMinusNull , nullMarkedDefaultQualUnionNull
247
+ nullMarkedDefaultQualMinusNull ,
248
+ nullMarkedDefaultQualUnionNull ,
249
+ nullMarkedDefaultQualParametric ,
250
+ nullMarkedDefaultQualUnspecified
214
251
})
215
252
.build ();
216
253
@@ -359,7 +396,8 @@ protected void addUncheckedStandardDefaults(QualifierDefaults defs) {
359
396
360
397
@ Override
361
398
protected Set <Class <? extends Annotation >> createSupportedTypeQualifiers () {
362
- return new LinkedHashSet <>(asList (Nullable .class , NullnessUnspecified .class , MinusNull .class ));
399
+ return new LinkedHashSet <>(
400
+ asList (Nullable .class , NullnessUnspecified .class , MinusNull .class , ParametricNull .class ));
363
401
}
364
402
365
403
@ Override
@@ -438,10 +476,16 @@ protected Map<DefaultQualifierKind, Set<DefaultQualifierKind>> createDirectSuper
438
476
nameToQualifierKind .get (Nullable .class .getCanonicalName ());
439
477
DefaultQualifierKind nullnessOperatorUnspecified =
440
478
nameToQualifierKind .get (NullnessUnspecified .class .getCanonicalName ());
479
+ DefaultQualifierKind parametricNullKind =
480
+ nameToQualifierKind .get (ParametricNull .class .getCanonicalName ());
441
481
442
482
Map <DefaultQualifierKind , Set <DefaultQualifierKind >> supers = new HashMap <>();
443
- supers .put (minusNullKind , singleton (nullnessOperatorUnspecified ));
483
+ LinkedHashSet <DefaultQualifierKind > superOfMinusNull = new LinkedHashSet <>();
484
+ superOfMinusNull .add (nullnessOperatorUnspecified );
485
+ superOfMinusNull .add (parametricNullKind );
486
+ supers .put (minusNullKind , superOfMinusNull );
444
487
supers .put (nullnessOperatorUnspecified , singleton (unionNullKind ));
488
+ supers .put (parametricNullKind , singleton (unionNullKind ));
445
489
supers .put (unionNullKind , emptySet ());
446
490
return supers ;
447
491
/*
@@ -457,6 +501,16 @@ protected Map<DefaultQualifierKind, Set<DefaultQualifierKind>> createDirectSuper
457
501
}
458
502
};
459
503
}
504
+
505
+ @ Override
506
+ public AnnotationMirror getParametricQualifier (AnnotationMirror qualifier ) {
507
+ return parametricNull ;
508
+ }
509
+
510
+ @ Override
511
+ public boolean isParametricQualifier (AnnotationMirror qualifier ) {
512
+ return areSame (parametricNull , qualifier );
513
+ }
460
514
}
461
515
462
516
@ Override
@@ -706,6 +760,9 @@ private List<? extends AnnotatedTypeMirror> getUpperBounds(AnnotatedTypeMirror t
706
760
*
707
761
* My only worry is that I always worry about making calls to getAnnotatedType, as discussed in
708
762
* various comments in this file (e.g., in NullSpecTreeAnnotator.visitMethodInvocation).
763
+ *
764
+ * This is likely caused by https://github.com/eisop/checker-framework/issues/737.
765
+ * Revisit this once that issue is fixed.
709
766
*/
710
767
if (type instanceof AnnotatedTypeVariable
711
768
&& !isCapturedTypeVariable (type .getUnderlyingType ())) {
@@ -861,8 +918,8 @@ protected AnnotatedTypeMirror substituteTypeVariable(
861
918
substitute .replaceAnnotation (minusNull );
862
919
} else if (argument .hasAnnotation (unionNull ) || use .hasAnnotation (unionNull )) {
863
920
substitute .replaceAnnotation (unionNull );
864
- } else if (argument .hasAnnotation (nullnessOperatorUnspecified )
865
- || use .hasAnnotation (nullnessOperatorUnspecified )) {
921
+ } else if (argument .hasEffectiveAnnotation (nullnessOperatorUnspecified )
922
+ || use .hasEffectiveAnnotation (nullnessOperatorUnspecified )) {
866
923
substitute .replaceAnnotation (nullnessOperatorUnspecified );
867
924
}
868
925
0 commit comments