Skip to content

Commit d5cb4f1

Browse files
authored
Fix multiple issues with NewClassTrees that have enclosing expressions (#1191)
Fixes #1188, exactly as suggested in that issue. This both simplifies the code and fixes a false negative with `@Nullable` enclosing expressions.
1 parent 86febe1 commit d5cb4f1

File tree

2 files changed

+28
-13
lines changed

2 files changed

+28
-13
lines changed

nullaway/src/main/java/com/uber/nullaway/NullAway.java

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -441,9 +441,15 @@ public Description matchNewClass(NewClassTree tree, VisitorState state) {
441441
if (methodSymbol == null) {
442442
throw new RuntimeException("not expecting unresolved method here");
443443
}
444+
ExpressionTree enclosingExpression = tree.getEnclosingExpression();
445+
if (enclosingExpression != null) {
446+
// technically this is not a dereference; there is a requireNonNull() call in the
447+
// bytecode. but it's close enough for error reporting
448+
state.reportMatch(matchDereference(enclosingExpression, tree, state));
449+
}
444450
List<? extends ExpressionTree> actualParams = tree.getArguments();
445-
if (tree.getClassBody() != null && actualParams.size() > 0) {
446-
// passing parameters to constructor of anonymous class
451+
if (tree.getClassBody() != null) {
452+
// invoking constructor of anonymous class
447453
// this constructor just invokes the constructor of the superclass, and
448454
// in the AST does not have the parameter nullability annotations from the superclass.
449455
// so, treat as if the superclass constructor is being invoked directly
@@ -1861,18 +1867,7 @@ private Description handleInvocation(
18611867
Symbol.MethodSymbol methodSymbol,
18621868
List<? extends ExpressionTree> actualParams) {
18631869
List<VarSymbol> formalParams = methodSymbol.getParameters();
1864-
18651870
boolean varArgsMethod = methodSymbol.isVarArgs();
1866-
if (formalParams.size() != actualParams.size()
1867-
&& !varArgsMethod
1868-
&& !methodSymbol.isStatic()
1869-
&& methodSymbol.isConstructor()
1870-
&& methodSymbol.enclClass().isInner()) {
1871-
// In special cases like one in issue #366
1872-
// formal params and actual params do not match while using JDK11+
1873-
// we bail out in this particular case
1874-
return Description.NO_MATCH;
1875-
}
18761871

18771872
// always do unboxing checks, whether or not the invoked method is annotated
18781873
for (int i = 0; i < formalParams.size() && i < actualParams.size(); i++) {

nullaway/src/test/java/com/uber/nullaway/CoreTests.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1134,4 +1134,24 @@ public void synchronizedInUnannotatedLambda() {
11341134
"}")
11351135
.doTest();
11361136
}
1137+
1138+
@Test
1139+
public void enclosingExpressionForNewClassTree() {
1140+
defaultCompilationHelper
1141+
.addSourceLines(
1142+
"Outer.java",
1143+
"package com.uber;",
1144+
"import org.jspecify.annotations.Nullable;",
1145+
"class Outer {",
1146+
" class Inner {}",
1147+
" static Inner testNegative(Outer outer) {",
1148+
" return outer.new Inner() {};",
1149+
" }",
1150+
" static Inner testPositive(@Nullable Outer outer) {",
1151+
" // BUG: Diagnostic contains: dereferenced expression outer is @Nullable",
1152+
" return outer.new Inner() {};",
1153+
" }",
1154+
"}")
1155+
.doTest();
1156+
}
11371157
}

0 commit comments

Comments
 (0)