From b7c273f800aa6b56871d7a494471cf1c16ff9fa5 Mon Sep 17 00:00:00 2001 From: "romain.birling" Date: Wed, 17 Dec 2025 10:26:29 +0100 Subject: [PATCH 1/3] Draft of "False positive for S1854 Solution" - https://community.sonarsource.com/t/false-positive-for-s1854-unused-assignments-should-be-removed/114110/10 --- .../java/checks/UnusedVariablesFPCheck.java | 119 ++++++++++++++++++ .../sonar/java/checks/DeadStoreCheckTest.java | 9 ++ .../java/org/sonar/java/model/Symbols.java | 5 +- 3 files changed, 132 insertions(+), 1 deletion(-) create mode 100644 java-checks-test-sources/default/src/main/java/checks/UnusedVariablesFPCheck.java diff --git a/java-checks-test-sources/default/src/main/java/checks/UnusedVariablesFPCheck.java b/java-checks-test-sources/default/src/main/java/checks/UnusedVariablesFPCheck.java new file mode 100644 index 0000000000..f7564e5fff --- /dev/null +++ b/java-checks-test-sources/default/src/main/java/checks/UnusedVariablesFPCheck.java @@ -0,0 +1,119 @@ +package com; + + +public class UnusedVariablesFPCheck { + public class DeobfuscatedUpdateManager { +// private interface DataContainer { +// Iterable getItems(); +// } +// +// private interface ModelObject { +// void performAction(); +// } +// +// private interface ItemElement { +// ModelObject getDataModel(); +// } +// +// private static class SystemConfig { +// static ConfigMode getMode() { +// return ConfigMode.ENABLED; +// } +// } +// +// private enum ConfigMode { +// ENABLED, +// DISABLED +// } +// +// static class A { +// interface GenericCallback { } +// } + + /** + * Deobfuscated names with AI from : + * ```java + * package com; + *

+ * public class BCid51 { + * void HJid232(EJid229 YHid199, Yid24.RIid217 QJid241) { + * for (XFid148 RJid242 : YHid199.WIid222()) { + * int DHid178; + * if (Fid5.BGid151() == CGid152.DGid153) { + * MBid37 IHid183 = RJid242.OFid139(); + * IHid183.AGid150(); + * } + * } + * } + * } + * ``` + */ + void processUpdates( + DataContainer container + // REMARK : the issue arises from the A.GenericCallback callback that is not even used (indirect type resolution problem) + , A.GenericCallback callback + ) { + for (ItemElement element : container.getItems()) { + if (SystemConfig.getMode() == ConfigMode.ENABLED) { + ModelObject dataModel = element.getDataModel(); + dataModel.performAction(); + } + } + } + + } + + static class StringConcatenation { +// private class AClass { +// private class BClass { +// public T b; +// } +// } + + public String doSomething(AClass.BClass instance) { + String c = "Hi"; // Rule S1854 + return instance.b + c; + } + } + + static class EnhancedSwitch { +// private enum DocumentStatus { +// DOC01, +// DOC02 +// } +// +// private interface Document { +// void setStatus(DocumentStatus status); +// } +// +// private interface Event { +// } +// +// private class SimpleStatusChangedEvent implements Event { +// } +// +// private class NeedClientRecheckEvent implements Event { +// } +// private interface DocumentRepository { +// void save(Document document); +// } + + void ko(Event event, Document document, DocumentRepository documentRepository) { + final DocumentStatus status = switch (event) { + case SimpleStatusChangedEvent ignored -> DocumentStatus.DOC01; + case NeedClientRecheckEvent ignored -> DocumentStatus.DOC02; + }; + document.setStatus(status); + // ... + documentRepository.save(document); + } + + } + + class Obvious { +// void obvious() { +// int i = 0; // doesn't raise issue +// i = 1; // raises issue +// } + } +} diff --git a/java-checks/src/test/java/org/sonar/java/checks/DeadStoreCheckTest.java b/java-checks/src/test/java/org/sonar/java/checks/DeadStoreCheckTest.java index 395d5e9635..3827751689 100644 --- a/java-checks/src/test/java/org/sonar/java/checks/DeadStoreCheckTest.java +++ b/java-checks/src/test/java/org/sonar/java/checks/DeadStoreCheckTest.java @@ -51,6 +51,15 @@ void test_non_compiling() { .verifyIssues(); } + @Test + void test_fp() { + CheckVerifier.newVerifier() + .onFile(TestUtils.mainCodeSourcesPath("checks/UnusedVariablesFPCheck.java")) + .withJavaVersion(14) + .withCheck(new DeadStoreCheck()) + .verifyNoIssues(); + } + private static class EraseSymbols extends BaseTreeVisitor { @Override diff --git a/java-frontend/src/main/java/org/sonar/java/model/Symbols.java b/java-frontend/src/main/java/org/sonar/java/model/Symbols.java index 901db702be..311fc94358 100644 --- a/java-frontend/src/main/java/org/sonar/java/model/Symbols.java +++ b/java-frontend/src/main/java/org/sonar/java/model/Symbols.java @@ -99,7 +99,7 @@ public final boolean isTypeSymbol() { } @Override - public final boolean isMethodSymbol() { + public boolean isMethodSymbol() { return false; } @@ -340,6 +340,9 @@ public boolean isVarArgsMethod() { public boolean isNativeMethod() { return false; } + + @Override + public boolean isMethodSymbol() { return true; } } public static final class UnknownType implements Type { From 947f91867d0980ce5172a0329e7052a79be86f86 Mon Sep 17 00:00:00 2001 From: "romain.birling" Date: Thu, 18 Dec 2025 09:39:05 +0100 Subject: [PATCH 2/3] Moved non-compiling java file to non-compiling/checks --- .../non-compiling}/checks/UnusedVariablesFPCheck.java | 2 +- .../src/test/java/org/sonar/java/checks/DeadStoreCheckTest.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename java-checks-test-sources/default/src/main/{java => files/non-compiling}/checks/UnusedVariablesFPCheck.java (99%) diff --git a/java-checks-test-sources/default/src/main/java/checks/UnusedVariablesFPCheck.java b/java-checks-test-sources/default/src/main/files/non-compiling/checks/UnusedVariablesFPCheck.java similarity index 99% rename from java-checks-test-sources/default/src/main/java/checks/UnusedVariablesFPCheck.java rename to java-checks-test-sources/default/src/main/files/non-compiling/checks/UnusedVariablesFPCheck.java index f7564e5fff..5fbca87214 100644 --- a/java-checks-test-sources/default/src/main/java/checks/UnusedVariablesFPCheck.java +++ b/java-checks-test-sources/default/src/main/files/non-compiling/checks/UnusedVariablesFPCheck.java @@ -1,4 +1,4 @@ -package com; +package checks; public class UnusedVariablesFPCheck { diff --git a/java-checks/src/test/java/org/sonar/java/checks/DeadStoreCheckTest.java b/java-checks/src/test/java/org/sonar/java/checks/DeadStoreCheckTest.java index 3827751689..fbc8b2b50b 100644 --- a/java-checks/src/test/java/org/sonar/java/checks/DeadStoreCheckTest.java +++ b/java-checks/src/test/java/org/sonar/java/checks/DeadStoreCheckTest.java @@ -54,7 +54,7 @@ void test_non_compiling() { @Test void test_fp() { CheckVerifier.newVerifier() - .onFile(TestUtils.mainCodeSourcesPath("checks/UnusedVariablesFPCheck.java")) + .onFile(TestUtils.nonCompilingTestSourcesPath("checks/UnusedVariablesFPCheck.java")) .withJavaVersion(14) .withCheck(new DeadStoreCheck()) .verifyNoIssues(); From 1d537b2ed6960a1d0eb13fef47c286d770e7949f Mon Sep 17 00:00:00 2001 From: "romain.birling" Date: Thu, 18 Dec 2025 15:29:52 +0100 Subject: [PATCH 3/3] Fix autoscan --- its/autoscan/src/test/resources/autoscan/diffs/diff_S1481.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/its/autoscan/src/test/resources/autoscan/diffs/diff_S1481.json b/its/autoscan/src/test/resources/autoscan/diffs/diff_S1481.json index 9bd4666fbb..0a9e1c62b2 100644 --- a/its/autoscan/src/test/resources/autoscan/diffs/diff_S1481.json +++ b/its/autoscan/src/test/resources/autoscan/diffs/diff_S1481.json @@ -1,6 +1,6 @@ { "ruleKey": "S1481", "hasTruePositives": true, - "falseNegatives": 10, + "falseNegatives": 8, "falsePositives": 0 }