in nullaway/src/main/java/com/uber/nullaway/NullAway.java [1344:1402]
private ImmutableSet<Element> safeInitByCalleeBefore(
TreePath pathToRead, VisitorState state, TreePath enclosingBlockPath) {
Set<Element> safeInitMethods = new LinkedHashSet<>();
Tree enclosingBlockOrMethod = enclosingBlockPath.getLeaf();
if (enclosingBlockOrMethod instanceof VariableTree) {
return ImmutableSet.of();
}
ImmutableSet.Builder<Element> resultBuilder = ImmutableSet.builder();
BlockTree blockTree =
enclosingBlockOrMethod instanceof BlockTree
? (BlockTree) enclosingBlockOrMethod
: ((MethodTree) enclosingBlockOrMethod).getBody();
List<? extends StatementTree> statements = blockTree.getStatements();
Tree readExprTree = pathToRead.getLeaf();
int readStartPos = getStartPos((JCTree) readExprTree);
TreePath classTreePath = enclosingBlockPath;
// look for the parent ClassTree node, which represents the enclosing class / enum / interface
while (!(classTreePath.getLeaf() instanceof ClassTree)) {
classTreePath = classTreePath.getParentPath();
if (classTreePath == null) {
throw new IllegalStateException(
"could not find enclosing class / enum / interface for "
+ state.getSourceForNode(enclosingBlockPath.getLeaf()));
}
}
Symbol.ClassSymbol classSymbol = ASTHelpers.getSymbol((ClassTree) classTreePath.getLeaf());
for (int i = 0; i < statements.size(); i++) {
StatementTree curStmt = statements.get(i);
if (getStartPos((JCTree) curStmt) <= readStartPos) {
Element privMethodElem = getInvokeOfSafeInitMethod(curStmt, classSymbol, state);
if (privMethodElem != null) {
safeInitMethods.add(privMethodElem);
}
// Hack: Handling try{...}finally{...} statement, see getSafeInitMethods
if (curStmt.getKind().equals(Tree.Kind.TRY)) {
TryTree tryTree = (TryTree) curStmt;
// ToDo: Should we check initialization inside tryTree.getResources ? What is the scope of
// that initialization?
if (tryTree.getCatches().size() == 0) {
if (tryTree.getBlock() != null) {
resultBuilder.addAll(
safeInitByCalleeBefore(
pathToRead, state, new TreePath(enclosingBlockPath, tryTree.getBlock())));
}
if (tryTree.getFinallyBlock() != null) {
resultBuilder.addAll(
safeInitByCalleeBefore(
pathToRead,
state,
new TreePath(enclosingBlockPath, tryTree.getFinallyBlock())));
}
}
}
}
}
addGuaranteedNonNullFromInvokes(
state, getTreesInstance(state), safeInitMethods, getNullnessAnalysis(state), resultBuilder);
return resultBuilder.build();
}