in nullaway/src/main/java/com/uber/nullaway/dataflow/AccessPathNullnessAnalysis.java [198:242]
public NullnessStore getNullnessInfoBeforeNestedMethodNode(
TreePath pathToNestedMethodNode, VisitorState state, Handler handler) {
NullnessStore store =
dataFlow.resultBefore(pathToNestedMethodNode, state.context, nullnessPropagation);
if (store == null) {
return NullnessStore.empty();
}
Predicate<AccessPath> handlerPredicate =
handler.getAccessPathPredicateForNestedMethod(pathToNestedMethodNode, state);
return store.filterAccessPaths(
(ap) -> {
boolean allAPNonRootElementsAreFinalFields = true;
ImmutableList<AccessPathElement> elements = ap.getElements();
for (int i = 0; i < elements.size(); i++) {
AccessPathElement ape = elements.get(i);
Element e = ape.getJavaElement();
if (i != elements.size() - 1) { // "inner" elements of the access path
if (!e.getKind().equals(ElementKind.FIELD)
|| !e.getModifiers().contains(Modifier.FINAL)) {
allAPNonRootElementsAreFinalFields = false;
break;
}
} else { // last element
// must be a field that is final or annotated with @MonotonicNonNull
if (!e.getKind().equals(ElementKind.FIELD)
|| !(e.getModifiers().contains(Modifier.FINAL)
|| hasMonotonicNonNullAnnotation(e))) {
allAPNonRootElementsAreFinalFields = false;
}
}
}
if (allAPNonRootElementsAreFinalFields) {
Element e = ap.getRoot();
return e == null // This is the case for: this(.f)* where each f is a final field.
|| e.getKind().equals(ElementKind.PARAMETER)
|| e.getKind().equals(ElementKind.LOCAL_VARIABLE)
// rooted at a static field that is either final or annotated with @MonotonicNonNull
|| (e.getKind().equals(ElementKind.FIELD)
&& (e.getModifiers().contains(Modifier.FINAL)
|| hasMonotonicNonNullAnnotation(e)));
}
return handlerPredicate.test(ap);
});
}