in nullaway/src/main/java/com/uber/nullaway/handlers/StreamNullabilityPropagator.java [459:508]
public void onMatchMethodReference(
MemberReferenceTree tree, MethodAnalysisContext methodAnalysisContext) {
VisitorState state = methodAnalysisContext.state();
MapOrCollectMethodToFilterInstanceRecord callInstanceRecord =
mapOrCollectRecordToFilterMap.get(tree);
if (callInstanceRecord != null && ((JCTree.JCMemberReference) tree).kind.isUnbound()) {
// Unbound method reference, check if we know the corresponding path to be NonNull from the
// previous filter.
Tree filterTree = callInstanceRecord.getFilter();
if (!(filterTree instanceof MethodTree || filterTree instanceof LambdaExpressionTree)) {
throw new IllegalStateException(
"unexpected filterTree type "
+ filterTree.getClass()
+ " "
+ state.getSourceForNode(filterTree));
}
NullnessStore filterNullnessStore = filterToNSMap.get(filterTree);
if (filterNullnessStore == null) {
throw new IllegalStateException(
"null filterNullStore for tree " + state.getSourceForNode(filterTree));
}
for (AccessPath ap : filterNullnessStore.getAccessPathsWithValue(Nullness.NONNULL)) {
// Find the access path corresponding to the current unbound method reference after binding
ImmutableList<AccessPathElement> elements = ap.getElements();
if (elements.size() == 1) {
// We only care for single method call chains (e.g. this.foo(), not this.f.bar())
Element element = elements.get(0).getJavaElement();
if (!element.getKind().equals(ElementKind.METHOD)) {
// We are only looking for method APs
continue;
}
if (!element
.getSimpleName()
.equals(methodAnalysisContext.methodSymbol().getSimpleName())) {
// Check for the name match
continue;
}
if (((ExecutableElement) element).getParameters().size() != 0) {
// Methods that take parameters might have return values that don't depend only on this
// and the AP
continue;
}
// We found our method, and it was non-null when called inside the filter, so we mark the
// return of the
// method reference as non-null here
methodAnalysisContext.analysis().setComputedNullness(tree, Nullness.NONNULL);
}
}
}
}