in nullaway/src/main/java/com/uber/nullaway/NullAway.java [501:565]
public Description matchAssignment(AssignmentTree tree, VisitorState state) {
if (!withinAnnotatedCode(state)) {
return Description.NO_MATCH;
}
Type lhsType = ASTHelpers.getType(tree.getVariable());
if (lhsType != null && lhsType.isPrimitive()) {
doUnboxingCheck(state, tree.getExpression());
}
Symbol assigned = ASTHelpers.getSymbol(tree.getVariable());
if (assigned instanceof Symbol.MethodSymbol) {
// javac generates an AssignmentTree for setting an annotation attribute value. E.g., for
// `@SuppressWarnings("foo")`, javac generates an AssignmentTree of the form `value() =
// "foo"`, where the LHS is a MethodSymbol. We don't want to analyze these.
return Description.NO_MATCH;
}
if (assigned != null && codeAnnotationInfo.isSymbolUnannotated(assigned, config, handler)) {
// assigning to symbol that is unannotated
return Description.NO_MATCH;
}
// generics check
if (lhsType != null && config.isJSpecifyMode()) {
genericsChecks.checkTypeParameterNullnessForAssignability(tree, this, state);
}
if (config.isJSpecifyMode() && tree.getVariable() instanceof ArrayAccessTree) {
// check for a write of a @Nullable value into @NonNull array contents
ArrayAccessTree arrayAccess = (ArrayAccessTree) tree.getVariable();
ExpressionTree arrayExpr = arrayAccess.getExpression();
ExpressionTree expression = tree.getExpression();
Symbol arraySymbol = ASTHelpers.getSymbol(arrayExpr);
if (arraySymbol != null) {
boolean isElementNullable = isArrayElementNullable(arraySymbol, config);
if (!isElementNullable && mayBeNullExpr(state, expression)) {
String message = "Writing @Nullable expression into array with @NonNull contents.";
ErrorMessage errorMessage =
new ErrorMessage(MessageTypes.ASSIGN_NULLABLE_TO_NONNULL_ARRAY, message);
return errorBuilder.createErrorDescription(
errorMessage, buildDescription(tree), state, arraySymbol);
}
}
}
if (assigned == null || assigned.getKind() != ElementKind.FIELD) {
// not a field of nullable type
return Description.NO_MATCH;
}
if (Nullness.hasNullableAnnotation(assigned, config)
|| handler.onOverrideFieldNullability(assigned)) {
// field already annotated
return Description.NO_MATCH;
}
ExpressionTree expression = tree.getExpression();
if (mayBeNullExpr(state, expression)) {
String message = "assigning @Nullable expression to @NonNull field";
return errorBuilder.createErrorDescriptionForNullAssignment(
new ErrorMessage(MessageTypes.ASSIGN_FIELD_NULLABLE, message),
expression,
buildDescription(tree),
state,
ASTHelpers.getSymbol(tree.getVariable()));
}
handler.onNonNullFieldAssignment(assigned, getNullnessAnalysis(state), state);
return Description.NO_MATCH;
}