in nullaway/src/main/java/com/uber/nullaway/NullAway.java [1185:1245]
private Description checkForReadBeforeInit(ExpressionTree tree, VisitorState state) {
// do a bunch of filtering. first, filter out anything outside an initializer
TreePath path = state.getPath();
TreePath enclosingBlockPath;
if (config.assertsEnabled()) {
enclosingBlockPath = NullabilityUtil.findEnclosingMethodOrLambdaOrInitializer(path);
} else {
enclosingBlockPath =
NullabilityUtil.findEnclosingMethodOrLambdaOrInitializer(
path, ImmutableSet.of(Tree.Kind.ASSERT));
}
if (enclosingBlockPath == null) {
// is this possible?
return Description.NO_MATCH;
}
if (!config.assertsEnabled()
&& enclosingBlockPath.getLeaf().getKind().equals(Tree.Kind.ASSERT)) {
return Description.NO_MATCH;
}
if (!relevantInitializerMethodOrBlock(enclosingBlockPath, state)) {
return Description.NO_MATCH;
}
// now, make sure we have a field read
Symbol symbol = ASTHelpers.getSymbol(tree);
if (symbol == null) {
return Description.NO_MATCH;
}
if (!symbol.getKind().equals(ElementKind.FIELD)) {
return Description.NO_MATCH;
}
// for static fields, make sure the enclosing init is a static method or block
if (isStatic(symbol)) {
Tree enclosing = enclosingBlockPath.getLeaf();
if (enclosing instanceof MethodTree
&& !ASTHelpers.getSymbol((MethodTree) enclosing).isStatic()) {
return Description.NO_MATCH;
} else if (enclosing instanceof BlockTree && !((BlockTree) enclosing).isStatic()) {
return Description.NO_MATCH;
}
}
if (okToReadBeforeInitialized(path, state)) {
// writing the field, not reading it
return Description.NO_MATCH;
}
// check that the field might actually be problematic to read
FieldInitEntities entities =
castToNonNull(class2Entities.get(enclosingClassSymbol(enclosingBlockPath)));
if (!(entities.nonnullInstanceFields().contains(symbol)
|| entities.nonnullStaticFields().contains(symbol))) {
// field is either nullable or initialized at declaration
return Description.NO_MATCH;
}
if (errorBuilder.symbolHasSuppressWarningsAnnotation(symbol, INITIALIZATION_CHECK_NAME)) {
// also suppress checking read before init, as we may not find explicit initialization
return Description.NO_MATCH;
}
return checkPossibleUninitFieldRead(tree, state, symbol, path, enclosingBlockPath);
}