Skip to content

Commit 90e4a60

Browse files
stefanodallapalmastedapatimtebeek
authored
bugfix: false positive in AnnotateNullableParameters when parameter … (#865)
* bugfix: false positive in AnnotateNullableParameters when parameter is dereferenced before null check * Check all arguments for null-checked parameters Addresses review feedback: custom null-checkers may accept the parameter in a position other than first (e.g., `assertNotNull(message, param)`). --------- Co-authored-by: stefanod <stefano.dallapalma@adyen.com> Co-authored-by: Tim te Beek <tim@moderne.io>
1 parent b315bbc commit 90e4a60

2 files changed

Lines changed: 33 additions & 6 deletions

File tree

src/main/java/org/openrewrite/staticanalysis/AnnotateNullableParameters.java

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -319,15 +319,16 @@ private void handleBinary(J.Binary binary, Set<J.Identifier> nullCheckedParams)
319319

320320
private void handleMethodInvocation(J.MethodInvocation mi, Set<J.Identifier> nullCheckedParams) {
321321
if (isKnownNullMethodChecker(mi)) {
322-
new JavaIsoVisitor<Set<J.Identifier>>() {
323-
@Override
324-
public J.Identifier visitIdentifier(J.Identifier identifier, Set<J.Identifier> set) {
322+
// Only consider the parameter as null-checked if it's passed directly,
323+
// not if it's dereferenced first (e.g., map.get("key"))
324+
for (Expression arg : mi.getArguments()) {
325+
if (arg instanceof J.Identifier) {
326+
J.Identifier identifier = (J.Identifier) arg;
325327
if (containsIdentifierByName(identifiers, identifier)) {
326-
set.add(identifier);
328+
nullCheckedParams.add(identifier);
327329
}
328-
return identifier;
329330
}
330-
}.visit(mi.getArguments(), nullCheckedParams);
331+
}
331332
}
332333
}
333334

src/test/java/org/openrewrite/staticanalysis/AnnotateNullableParametersTest.java

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -909,4 +909,30 @@ public PersonBuilder setInfo(@Nullable String name, @Nullable String lastName) {
909909
)
910910
);
911911
}
912+
913+
@Test
914+
void unchangedWhenParameterDereferencedBeforeNullCheckingMethod() {
915+
List<String> additionalNullCheckingMethods = List.of("org.my.util.Text isEmptyOrNull(java.lang.String)");
916+
rewriteRun(
917+
spec -> spec.recipe(new AnnotateNullableParameters(null, additionalNullCheckingMethods)),
918+
//language=java
919+
java(
920+
"""
921+
import java.util.Map;
922+
import org.my.util.Text;
923+
924+
public class PersonBuilder {
925+
private String name = "Unknown";
926+
927+
public PersonBuilder setInfo(Map<String, String> infoMap) {
928+
if (!Text.isEmptyOrNull(infoMap.get("name"))) {
929+
this.name = infoMap.get("name");
930+
}
931+
return this;
932+
}
933+
}
934+
"""
935+
)
936+
);
937+
}
912938
}

0 commit comments

Comments
 (0)