in nullaway/src/main/java/com/uber/nullaway/NullAway.java [1495:1535]
private boolean okToReadBeforeInitialized(TreePath path, VisitorState state) {
TreePath parentPath = path.getParentPath();
Tree leaf = path.getLeaf();
Tree parent = parentPath.getLeaf();
if (parent instanceof AssignmentTree) {
// ok if it's actually a write
AssignmentTree assignment = (AssignmentTree) parent;
return assignment.getVariable().equals(leaf);
} else if (parent instanceof BinaryTree) {
// ok if we're comparing to null
BinaryTree binaryTree = (BinaryTree) parent;
Tree.Kind kind = binaryTree.getKind();
if (kind.equals(Tree.Kind.EQUAL_TO) || kind.equals(Tree.Kind.NOT_EQUAL_TO)) {
ExpressionTree left = binaryTree.getLeftOperand();
ExpressionTree right = binaryTree.getRightOperand();
return (left.equals(leaf) && right.getKind().equals(Tree.Kind.NULL_LITERAL))
|| (right.equals(leaf) && left.getKind().equals(Tree.Kind.NULL_LITERAL));
}
} else if (parent instanceof MethodInvocationTree) {
// ok if it's invoking castToNonNull and the read is the argument
MethodInvocationTree methodInvoke = (MethodInvocationTree) parent;
Symbol.MethodSymbol methodSymbol = ASTHelpers.getSymbol(methodInvoke);
String qualifiedName =
ASTHelpers.enclosingClass(methodSymbol) + "." + methodSymbol.getSimpleName().toString();
List<? extends ExpressionTree> arguments = methodInvoke.getArguments();
Integer castToNonNullArg;
if (qualifiedName.equals(config.getCastToNonNullMethod())
&& methodSymbol.getParameters().size() == 1) {
castToNonNullArg = 0;
} else {
castToNonNullArg =
handler.castToNonNullArgumentPositionsForMethod(
arguments, null, new MethodAnalysisContext(this, state, methodSymbol));
}
if (castToNonNullArg != null && leaf.equals(arguments.get(castToNonNullArg))) {
return true;
}
return false;
}
return false;
}