Skip to content

Commit 07eb081

Browse files
committed
SONARJAVA-1460 symplify recognition of methods from Objects
1 parent 401e795 commit 07eb081

6 files changed

Lines changed: 20 additions & 34 deletions

File tree

java-squid/src/main/java/org/sonar/java/se/ConstraintManager.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -104,11 +104,11 @@ public SymbolicValue createMethodSymbolicValue(MethodInvocationTree syntaxNode,
104104
SymbolicValue leftOp = values.get(0);
105105
SymbolicValue rightOp = values.get(1);
106106
result.computedFrom(ImmutableList.of(rightOp, leftOp));
107-
} else if (ExplodedGraphWalker.isObjectsMethod(syntaxNode, "isNull", 1)) {
107+
} else if (isObjectsMethod(syntaxNode.symbol(), "isNull")) {
108108
result = new NullCheckSymbolicValue(counter, true);
109109
SymbolicValue operand = values.get(1);
110110
result.computedFrom(ImmutableList.of(operand));
111-
} else if (ExplodedGraphWalker.isObjectsMethod(syntaxNode, "nonNull", 1)) {
111+
} else if (isObjectsMethod(syntaxNode.symbol(), "nonNull")) {
112112
result = new NullCheckSymbolicValue(counter, false);
113113
SymbolicValue operand = values.get(1);
114114
result.computedFrom(ImmutableList.of(operand));
@@ -119,6 +119,10 @@ public SymbolicValue createMethodSymbolicValue(MethodInvocationTree syntaxNode,
119119
return result;
120120
}
121121

122+
private static boolean isObjectsMethod(Symbol symbol, String methodName) {
123+
return symbol.owner().type().is("java.util.Objects") && methodName.equals(symbol.name());
124+
}
125+
122126
private static boolean isEqualsMethod(MethodInvocationTree syntaxNode) {
123127
if (syntaxNode.arguments().size() == 1) {
124128
ExpressionTree methodSelect = syntaxNode.methodSelect();

java-squid/src/main/java/org/sonar/java/se/ExplodedGraphWalker.java

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,6 @@ public class ExplodedGraphWalker extends BaseTreeVisitor {
8181
private static final int MAX_STEPS = 10000;
8282
private static final Logger LOG = LoggerFactory.getLogger(ExplodedGraphWalker.class);
8383
private static final Set<String> THIS_SUPER = ImmutableSet.of("this", "super");
84-
public static final String OBJECT_CLASS_NAME = "java.lang.Object";
8584

8685
private static final boolean DEBUG_MODE_ACTIVATED = false;
8786
private static final int MAX_EXEC_PROGRAM_POINT = 2;
@@ -575,17 +574,6 @@ private static boolean isLocalMethodInvocation(MethodInvocationTree tree) {
575574
return false;
576575
}
577576

578-
public static boolean isObjectsMethod(MethodInvocationTree syntaxNode, String methodName, int numberOfParameter) {
579-
Symbol symbol = syntaxNode.symbol();
580-
if (symbol.isMethodSymbol()) {
581-
Symbol.MethodSymbol methodSymbol = (Symbol.MethodSymbol) symbol;
582-
if (methodSymbol.owner().type().is("java.util.Objects") && methodName.equals(methodSymbol.name())) {
583-
return methodSymbol.parameterTypes().size() == numberOfParameter;
584-
}
585-
}
586-
return false;
587-
}
588-
589577
private void resetFieldValues() {
590578
programState = programState.resetFieldValues(constraintManager);
591579
}

java-squid/src/main/java/org/sonar/java/se/checks/NullDereferenceCheck.java

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,12 @@
2626
import org.sonar.check.Rule;
2727
import org.sonar.java.model.DefaultJavaFileScannerContext;
2828
import org.sonar.java.se.CheckerContext;
29-
import org.sonar.java.se.ExplodedGraphWalker;
3029
import org.sonar.java.se.ObjectConstraint;
3130
import org.sonar.java.se.ProgramState;
3231
import org.sonar.java.se.symbolicvalues.SymbolicValue;
3332
import org.sonar.plugins.java.api.JavaFileScanner;
3433
import org.sonar.plugins.java.api.JavaFileScannerContext;
34+
import org.sonar.plugins.java.api.semantic.Symbol;
3535
import org.sonar.plugins.java.api.tree.MemberSelectExpressionTree;
3636
import org.sonar.plugins.java.api.tree.MethodInvocationTree;
3737
import org.sonar.plugins.java.api.tree.Tree;
@@ -52,8 +52,6 @@
5252
@ActivatedByDefault
5353
public class NullDereferenceCheck extends SECheck implements JavaFileScanner {
5454

55-
private static final String REQUIRE_NON_NULL_METHOD_NAME = "requireNonNull";
56-
5755
@Override
5856
public void scanFile(JavaFileScannerContext context) {
5957
Multimap<Tree, String> issues = ((DefaultJavaFileScannerContext) context).getSEIssues(NullDereferenceCheck.class);
@@ -73,13 +71,10 @@ public ProgramState checkPreStatement(CheckerContext context, Tree syntaxNode) {
7371
if (syntaxNode.is(Tree.Kind.METHOD_INVOCATION)) {
7472
MethodInvocationTree methodInvocation = (MethodInvocationTree) syntaxNode;
7573
toCheck = methodInvocation.methodSelect();
76-
if (ExplodedGraphWalker.isObjectsMethod(methodInvocation, REQUIRE_NON_NULL_METHOD_NAME, 1)) {
77-
final List<SymbolicValue> values = context.getState().peekValues(2);
78-
return context.getState().addConstraint(values.get(1), ObjectConstraint.NOT_NULL);
79-
} else if (ExplodedGraphWalker.isObjectsMethod(methodInvocation, REQUIRE_NON_NULL_METHOD_NAME, 2)
80-
|| ExplodedGraphWalker.isObjectsMethod(methodInvocation, REQUIRE_NON_NULL_METHOD_NAME, 2)) {
81-
final List<SymbolicValue> values = context.getState().peekValues(3);
82-
return context.getState().addConstraint(values.get(2), ObjectConstraint.NOT_NULL);
74+
if (isObjectsRequireNonNullMethod(methodInvocation.symbol())) {
75+
int numberArguments = methodInvocation.arguments().size();
76+
List<SymbolicValue> values = context.getState().peekValues(numberArguments + 1);
77+
return context.getState().addConstraint(values.get(numberArguments), ObjectConstraint.NOT_NULL);
8378
}
8479
}
8580
if (toCheck.is(Tree.Kind.MEMBER_SELECT)) {
@@ -88,6 +83,10 @@ public ProgramState checkPreStatement(CheckerContext context, Tree syntaxNode) {
8883
return context.getState();
8984
}
9085

86+
private static boolean isObjectsRequireNonNullMethod(Symbol symbol) {
87+
return symbol.owner().type().is("java.util.Objects") && "requireNonNull".equals(symbol.name());
88+
}
89+
9190
private ProgramState checkMemberSelect(CheckerContext context, MemberSelectExpressionTree syntaxNode, SymbolicValue currentVal) {
9291
final ProgramState programState = context.getState();
9392
if ("class".equals(syntaxNode.identifier().name())) {

java-squid/src/main/java/org/sonar/java/se/symbolicvalues/NullCheckSymbolicValue.java

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -38,11 +38,9 @@ public NullCheckSymbolicValue(int id, boolean isNull) {
3838

3939
@Override
4040
public List<ProgramState> setConstraint(ProgramState programState, BooleanConstraint booleanConstraint) {
41-
final ObjectConstraint constraint;
42-
if (BooleanConstraint.TRUE.equals(booleanConstraint)) {
43-
constraint = isNull ? ObjectConstraint.NULL : ObjectConstraint.NOT_NULL;
44-
} else {
45-
constraint = isNull ? ObjectConstraint.NOT_NULL : ObjectConstraint.NULL;
41+
ObjectConstraint constraint = ObjectConstraint.NULL;
42+
if (BooleanConstraint.TRUE.equals(booleanConstraint) ^ isNull) {
43+
constraint = ObjectConstraint.NOT_NULL;
4644
}
4745
return ImmutableList.of(programState.addConstraint(operand, constraint));
4846
}

java-squid/src/test/files/se/NullDereferenceCheck.java

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,7 @@
11
@SomeAnnotation(name = value)
22
package javax.annotation;
33

4-
import java.util.function.Supplier;
5-
64
import java.util.List;
7-
import java.util.Objects;
85

96
@interface CheckForNull {}
107

java-squid/src/test/files/se/ObjectsMethodsTest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ public void testRequireNull(Supplier<String> supplier) {
4242
}
4343
}
4444

45-
// Needed to ensure that all methods of Objects are declared (for tests with Java version prior to 1.8
45+
// Needed to ensure that all methods of Objects are declared (for tests with Java version prior to 1.8)
4646

4747
class Objects {
4848
public static boolean isNull(Object obj) {
@@ -70,4 +70,4 @@ public static <T> T requireNonNull(T obj, Supplier<String> supplier) {
7070
throw new NullPointerException(supplier.get());
7171
}
7272
}
73-
}
73+
}

0 commit comments

Comments
 (0)