Skip to content

Commit f239443

Browse files
SONARJAVA-5482 stop raising issues if variable or identifier symbol is unknown (#5141)
1 parent 17fe562 commit f239443

14 files changed

Lines changed: 172 additions & 30 deletions

File tree

its/ruling/src/test/resources/eclipse-jetty-similar-to-main/java-S1854.json

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,6 @@
99
"org.eclipse.jetty:jetty-project:jetty-http/src/test/java/org/eclipse/jetty/http/pathmap/WebSocketUriMappingTest.java": [
1010
91
1111
],
12-
"org.eclipse.jetty:jetty-project:jetty-io/src/test/java/org/eclipse/jetty/io/SslConnectionTest.java": [
13-
92,
14-
94,
15-
97,
16-
105,
17-
147,
18-
272
19-
],
2012
"org.eclipse.jetty:jetty-project:jetty-server/src/test/java/org/eclipse/jetty/server/HttpOutputTest.java": [
2113
861
2214
],

its/ruling/src/test/resources/eclipse-jetty/java-S1854.json

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,6 @@
99
"org.eclipse.jetty:jetty-project:jetty-http/src/test/java/org/eclipse/jetty/http/pathmap/WebSocketUriMappingTest.java": [
1010
91
1111
],
12-
"org.eclipse.jetty:jetty-project:jetty-io/src/test/java/org/eclipse/jetty/io/SslConnectionTest.java": [
13-
92,
14-
94,
15-
97,
16-
105,
17-
147,
18-
272
19-
],
2012
"org.eclipse.jetty:jetty-project:jetty-server/src/test/java/org/eclipse/jetty/server/HttpOutputTest.java": [
2113
861
2214
],
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package checks;
2+
3+
public class DeadStoreCheckBrokenSemantic {
4+
5+
public void singleAssignment() {
6+
int a = 42;
7+
System.out.println(a);
8+
}
9+
}

java-checks-test-sources/default/src/main/java/checks/DeadStoreCheckSample.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@ class DeadStoreCheckSample {
1010

1111
int var;
1212

13+
void singleAssignment(){
14+
int z = 10; // Noncompliant
15+
}
16+
1317
int foo(int u) {
1418
int x = 0;// Compliant - default value
1519
x = 3; // Noncompliant

java-checks-testkit/src/main/java/org/sonar/java/checks/verifier/CheckVerifier.java

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,15 @@
1818

1919
import java.io.File;
2020
import java.util.Collection;
21+
import java.util.function.Consumer;
2122
import javax.annotation.Nullable;
2223
import org.sonar.api.batch.fs.InputFile;
2324
import org.sonar.api.batch.sensor.cache.ReadCache;
2425
import org.sonar.api.batch.sensor.cache.WriteCache;
2526
import org.sonar.java.checks.verifier.internal.InternalCheckVerifier;
2627
import org.sonar.java.checks.verifier.internal.JavaCheckVerifier;
2728
import org.sonar.plugins.java.api.JavaFileScanner;
29+
import org.sonar.plugins.java.api.tree.CompilationUnitTree;
2830

2931
/**
3032
* This interface defines how to use checks (rules) verifiers. Its goal is to provide all the required information
@@ -235,7 +237,21 @@ static CheckVerifier newInternalVerifier() {
235237
* @param rootDirectory The path of the project root working directory
236238
* @return the verifier configured with the project root working directory.
237239
*/
238-
CheckVerifier withProjectLevelWorkDir(String rootDirectory);
240+
default CheckVerifier withProjectLevelWorkDir(String rootDirectory) {
241+
throw new UnsupportedOperationException("Method not implemented, feel free to implement.");
242+
}
243+
244+
/**
245+
* Allows to modify the compilation unit tree after parsing.
246+
* This is useful for adding or modifying nodes in the tree for testing purposes.
247+
* There is at most one modifier per {@link CheckVerifier}.
248+
*
249+
* @param compilationUnitModifier the modifier to apply to the compilation unit tree
250+
* @return the verifier configured with the compilation unit modifier.
251+
*/
252+
default CheckVerifier withCompilationUnitModifier(Consumer<CompilationUnitTree> compilationUnitModifier) {
253+
throw new UnsupportedOperationException("Method not implemented, feel free to implement.");
254+
}
239255

240256
/**
241257
* Verifies that all the expected issues are correctly raised by the rule(s),

java-checks-testkit/src/main/java/org/sonar/java/checks/verifier/internal/InternalCheckVerifier.java

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -248,11 +248,6 @@ public CheckVerifier withCache(@Nullable ReadCache readCache, @Nullable WriteCac
248248
return this;
249249
}
250250

251-
@Override
252-
public CheckVerifier withProjectLevelWorkDir(String rootDirectory) {
253-
throw new RuntimeException("Method not implemented, feel free to implement.");
254-
}
255-
256251
@Override
257252
public void verifyIssues() {
258253
requiresNonNull(checks, CHECK_OR_CHECKS);

java-checks-testkit/src/main/java/org/sonar/java/checks/verifier/internal/JavaCheckVerifier.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import java.util.List;
2929
import java.util.Objects;
3030
import java.util.Optional;
31+
import java.util.function.Consumer;
3132
import javax.annotation.Nullable;
3233
import org.sonar.api.batch.fs.InputFile;
3334
import org.sonar.api.batch.sensor.cache.ReadCache;
@@ -50,6 +51,7 @@
5051
import org.sonar.plugins.java.api.JavaFileScanner;
5152
import org.sonar.plugins.java.api.JavaVersion;
5253
import org.sonar.plugins.java.api.caching.CacheContext;
54+
import org.sonar.plugins.java.api.tree.CompilationUnitTree;
5355
import org.sonarsource.analyzer.commons.checks.verifier.MultiFileVerifier;
5456
import org.sonarsource.analyzer.commons.checks.verifier.quickfix.QuickFix;
5557
import org.sonarsource.analyzer.commons.checks.verifier.quickfix.TextEdit;
@@ -90,6 +92,7 @@ public static JavaCheckVerifier newInstance() {
9092
private List<InputFile> files = null;
9193
private boolean withoutSemantic = false;
9294
private boolean isCacheEnabled = false;
95+
private Consumer<CompilationUnitTree> compilationUnitModifier = unused -> {};
9396

9497
@VisibleForTesting
9598
CacheContext cacheContext = null;
@@ -124,7 +127,7 @@ private MultiFileVerifier createVerifier() {
124127
visitorsBridge.setCacheContext(cacheContext);
125128
filesToParse = astScanner.scanWithoutParsing(files).get(false);
126129
}
127-
astScanner.scan(filesToParse);
130+
astScanner.scanForTesting(filesToParse, compilationUnitModifier);
128131

129132
addComments(verifier, commentLinesVisitor);
130133

@@ -335,6 +338,12 @@ public CheckVerifier withProjectLevelWorkDir(String rootDirectory) {
335338
return this;
336339
}
337340

341+
@Override
342+
public CheckVerifier withCompilationUnitModifier(Consumer<CompilationUnitTree> compilationUnitModifier) {
343+
this.compilationUnitModifier = compilationUnitModifier;
344+
return this;
345+
}
346+
338347
@Override
339348
public void verifyIssues() {
340349
requiresNonNull(checks, CHECK_OR_CHECKS);

java-checks-testkit/src/test/java/org/sonar/java/checks/verifier/internal/InternalCheckVerifierTest.java

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -524,7 +524,7 @@ void context_root_working_directory_not_supported() {
524524
});
525525

526526
assertThat(e)
527-
.isInstanceOf(RuntimeException.class)
527+
.isInstanceOf(UnsupportedOperationException.class)
528528
.hasMessage("Method not implemented, feel free to implement.");
529529
}
530530

@@ -1053,4 +1053,21 @@ void withCache_can_handle_a_mix_of_caches_combination() {
10531053
assertThat(dummyReadInternalWrite.cacheContext.getWriteCache()).isInstanceOf(JavaWriteCache.class);
10541054
}
10551055

1056+
@Test
1057+
void compilationUnitModifier_not_supported() {
1058+
1059+
InternalCheckVerifier checkVerifier = InternalCheckVerifier.newInstance()
1060+
.onFile(TEST_FILE);
1061+
1062+
Throwable e = catchThrowable(() -> {
1063+
checkVerifier
1064+
.withCompilationUnitModifier(tree -> {
1065+
});
1066+
});
1067+
1068+
assertThat(e)
1069+
.isInstanceOf(UnsupportedOperationException.class)
1070+
.hasMessage("Method not implemented, feel free to implement.");
1071+
}
1072+
10561073
}

java-checks-testkit/src/test/java/org/sonar/java/checks/verifier/internal/JavaCheckVerifierTest.java

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
import java.io.IOException;
2121
import java.nio.file.Path;
2222
import java.security.NoSuchAlgorithmException;
23+
import java.util.List;
24+
import java.util.function.Consumer;
2325
import java.util.function.Supplier;
2426
import org.junit.jupiter.api.Test;
2527
import org.sonar.api.batch.fs.InputFile;
@@ -33,7 +35,11 @@
3335
import org.sonar.java.checks.verifier.CheckVerifier;
3436
import org.sonar.java.checks.verifier.internal.CheckVerifierTestUtils.IssueWithQuickFix;
3537
import org.sonar.java.checks.verifier.internal.CheckVerifierTestUtils.NoEffectEndOfAnalysisCheck;
38+
import org.sonar.java.model.InternalSyntaxToken;
3639
import org.sonar.java.model.JavaVersionImpl;
40+
import org.sonar.java.model.declaration.ClassTreeImpl;
41+
import org.sonar.java.model.declaration.ModifiersTreeImpl;
42+
import org.sonar.java.model.expression.IdentifierTreeImpl;
3743
import org.sonar.java.reporting.AnalyzerMessage;
3844
import org.sonar.java.reporting.JavaQuickFix;
3945
import org.sonar.java.reporting.JavaTextEdit;
@@ -42,6 +48,8 @@
4248
import org.sonar.plugins.java.api.caching.CacheContext;
4349
import org.sonar.plugins.java.api.caching.JavaReadCache;
4450
import org.sonar.plugins.java.api.caching.JavaWriteCache;
51+
import org.sonar.plugins.java.api.tree.CompilationUnitTree;
52+
import org.sonar.plugins.java.api.tree.IdentifierTree;
4553

4654
import static org.assertj.core.api.Assertions.assertThat;
4755
import static org.assertj.core.api.Assertions.assertThatCode;
@@ -307,4 +315,28 @@ void withCache_can_handle_a_mix_of_caches_combination() {
307315
assertThat(dummyReadInternalWrite.cacheContext.getWriteCache()).isInstanceOf(JavaWriteCache.class);
308316
}
309317

318+
@Test
319+
void compilationUnitModifier_modify_tree() {
320+
Consumer<CompilationUnitTree> modifier = tree -> {
321+
ClassTreeImpl classTree = (ClassTreeImpl) tree.types().get(0);
322+
IdentifierTree ident = new IdentifierTreeImpl(new InternalSyntaxToken(1, 1, "Modified", List.of(), false));
323+
classTree.complete((ModifiersTreeImpl)classTree.modifiers(), classTree.declarationKeyword(), ident);
324+
};
325+
326+
var check = new JavaFileScanner() {
327+
@Override
328+
public void scanFile(JavaFileScannerContext context) {
329+
CompilationUnitTree tree = context.getTree();
330+
ClassTreeImpl classTree = (ClassTreeImpl) tree.types().get(0);
331+
assertThat(classTree.simpleName().name()).isEqualTo("Modified");
332+
}
333+
};
334+
335+
JavaCheckVerifier.newInstance()
336+
.onFile(TEST_FILE)
337+
.withCheck(check)
338+
.withCompilationUnitModifier(modifier)
339+
.verifyNoIssues();
340+
}
341+
310342
}

java-checks/src/main/java/org/sonar/java/checks/DeadStoreCheck.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,7 @@ private void handleVariable(Set<Symbol> out, VariableTree localVar) {
181181
Symbol symbol = localVar.symbol();
182182
ExpressionTree initializer = localVar.initializer();
183183
if (initializer != null
184+
&& !localVar.symbol().isUnknown()
184185
&& !isUsualDefaultValue(initializer)
185186
&& !out.contains(symbol)
186187
&& !UNRESOLVED_IDENTIFIERS_VISITOR.isUnresolved(symbol.name())) {

0 commit comments

Comments
 (0)