in nullaway/src/main/java/com/uber/nullaway/handlers/LibraryModelsHandler.java [127:195]
public MethodParameterNullness onOverrideMethodInvocationParametersNullability(
Context context,
Symbol.MethodSymbol methodSymbol,
boolean isAnnotated,
MethodParameterNullness argumentNullness) {
OptimizedLibraryModels optimizedLibraryModels = getOptLibraryModels(context);
ImmutableSet<Integer> nullableParamsFromModel =
optimizedLibraryModels.explicitlyNullableParameters(methodSymbol);
ImmutableSet<Integer> nonNullParamsFromModel =
optimizedLibraryModels.nonNullParameters(methodSymbol);
// For sanity check: $ nonNullParamsFromModel \cap nullableParamsFromModel $ should be empty
Set<Integer> allParameterPositions = new HashSet<>();
boolean varargsArrayModeled = false;
boolean varArgsMethod = methodSymbol.isVarArgs();
int varargsIndex = methodSymbol.getParameters().size() - 1;
for (Integer nullParam : nullableParamsFromModel) {
if (varArgsMethod && nullParam == varargsIndex) {
argumentNullness.setVarargsArrayNullness(NULLABLE);
varargsArrayModeled = true;
continue;
}
allParameterPositions.add(nullParam);
argumentNullness.setParameterNullness(nullParam, NULLABLE);
}
for (Integer nonNullParam : nonNullParamsFromModel) {
if (varArgsMethod && nonNullParam == varargsIndex) {
if (varargsArrayModeled) {
throw new IllegalStateException(
String.format(
"Library models give conflicting nullability for the following parameter of method %s: %s",
methodSymbol.getQualifiedName().toString(), "varargs array"));
}
argumentNullness.setVarargsArrayNullness(NONNULL);
varargsArrayModeled = true;
continue;
}
if (!allParameterPositions.add(nonNullParam)) {
// position was already marked as nullable
throw new IllegalStateException(
String.format(
"Library models give conflicting nullability for the following parameter of method %s: %s",
methodSymbol.getQualifiedName().toString(), nonNullParam.toString()));
}
argumentNullness.setParameterNullness(nonNullParam, NONNULL);
}
if (varArgsMethod) {
ImmutableSetMultimap<Integer, NestedAnnotationInfo> nestedAnnotations =
optimizedLibraryModels.nestedAnnotationsForMethods(methodSymbol);
Nullness varargsContentsNullness = null;
for (NestedAnnotationInfo nestedAnnotation : nestedAnnotations.get(varargsIndex)) {
// check if it's for the array element
if (nestedAnnotation.typePath().size() == 1
&& nestedAnnotation.typePath().get(0).kind() == ARRAY_ELEMENT) {
// this is a nested annotation for the varargs array element, which applies when
// individual parameters are passed
if (varargsContentsNullness == null) {
varargsContentsNullness =
nestedAnnotation.annotation() == Annotation.NULLABLE ? NULLABLE : NONNULL;
argumentNullness.setParameterNullness(varargsIndex, varargsContentsNullness);
} else {
throw new IllegalStateException(
"varargs contents nullness set multiple times: "
+ nestedAnnotations.get(varargsIndex));
}
}
}
}
return argumentNullness;
}