Skip to content

Commit 71f25f0

Browse files
SONARJAVA-4441 Fix FP on S1301 when mutiple case labels are used in Java 14 switch. (#4970)
1 parent 32060f9 commit 71f25f0

3 files changed

Lines changed: 48 additions & 11 deletions

File tree

java-checks/src/test/files/checks/SwitchAtLeastThreeCasesCheck.java renamed to java-checks-test-sources/default/src/test/java/checks/tests/SwitchAtLeastThreeCasesCheckSample.java

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,19 @@
1-
class A {
1+
package checks.tests;
22

3-
static void recordSwitch1(MyRecord object) {
3+
public class SwitchAtLeastThreeCasesCheckSample {
4+
record MyRecord(int x, int y) {}
5+
6+
static void recordSwitch1(Object object) {
47
switch (object) { // Compliant
58
case String x when x.length() > 42 -> { }
6-
case Integer i -> { }
9+
default -> { }
710
}
811
}
912

10-
static void recordSwitch1(Object object) {
13+
static void recordSwitch2(Object object) {
1114
switch (object) { // Compliant
1215
case MyRecord(int x, int y) -> { }
13-
case String s -> { }
16+
default -> { }
1417
}
1518
}
1619

@@ -19,22 +22,25 @@ sealed interface Shape permits Box, Circle {}
1922
record Box() implements Shape { }
2023
record Circle() implements Shape {}
2124

22-
void foo(Shape shape) {
25+
default void foo(Shape shape) {
2326
switch (shape) { // Compliant because of type pattern matching
2427
case Box ignored -> { }
2528
case Circle ignored -> System.out.println();
2629
}
2730
}
2831

29-
void goo(Shape shape) {
32+
default void goo(Shape shape) {
3033
switch (shape) { // Compliant because of type pattern matching
31-
default -> System.out.println();
3234
case Box ignored -> { }
35+
default -> System.out.println();
3336
}
3437
}
3538
}
3639

37-
public void f() {
40+
private static void doSomething() {}
41+
private static void doSomethingElse() {}
42+
43+
public void f(int variable) {
3844
switch (variable) { // Noncompliant {{Replace this "switch" statement by "if" statements to increase readability.}}
3945
// ^^^^^^
4046
case 0:
@@ -55,6 +61,15 @@ public void f() {
5561
break;
5662
}
5763

64+
switch (variable) {
65+
case 0, 1:
66+
doSomething();
67+
break;
68+
default:
69+
doSomethingElse();
70+
break;
71+
}
72+
5873
switch (variable) { // Noncompliant
5974
}
6075

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

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import org.sonar.check.Rule;
2020
import org.sonar.plugins.java.api.IssuableSubscriptionVisitor;
2121
import org.sonar.plugins.java.api.tree.CaseGroupTree;
22+
import org.sonar.plugins.java.api.tree.CaseLabelTree;
2223
import org.sonar.plugins.java.api.tree.SwitchStatementTree;
2324
import org.sonar.plugins.java.api.tree.Tree;
2425

@@ -42,13 +43,32 @@ public void visitNode(Tree tree) {
4243
if (hasLabelWithAllowedPattern(caseGroup)) {
4344
return;
4445
}
45-
count += caseGroup.labels().size();
46+
count += totalLabelCount(caseGroup);
4647
}
4748
if (count < 3) {
4849
reportIssue(switchStatementTree.switchKeyword(), "Replace this \"switch\" statement by \"if\" statements to increase readability.");
4950
}
5051
}
5152

53+
/**
54+
* Count labels, taking into account Java 14 multi-label switch.
55+
* For example, here we have 4 labels:
56+
* <pre>
57+
* case "Monday", "Tuesday":
58+
* case "Wednesday:
59+
* default: // considered 1 label
60+
* </pre>
61+
*/
62+
private static int totalLabelCount(CaseGroupTree caseGroup) {
63+
int total = 0;
64+
for (CaseLabelTree label: caseGroup.labels()) {
65+
int sz = label.expressions().size();
66+
// `default` does not have any expressions, but we consider it 1 label.
67+
total += sz > 0 ? sz : 1;
68+
}
69+
return total;
70+
}
71+
5272
private static boolean hasLabelWithAllowedPattern(CaseGroupTree caseGroupTree) {
5373
return caseGroupTree.labels().stream()
5474
.flatMap(label -> label.expressions().stream())

java-checks/src/test/java/org/sonar/java/checks/SwitchAtLeastThreeCasesCheckTest.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,14 @@
1919
import org.junit.jupiter.api.Test;
2020
import org.sonar.java.checks.verifier.CheckVerifier;
2121

22+
import static org.sonar.java.checks.verifier.TestUtils.testCodeSourcesPath;
23+
2224
class SwitchAtLeastThreeCasesCheckTest {
2325

2426
@Test
2527
void test() {
2628
CheckVerifier.newVerifier()
27-
.onFile("src/test/files/checks/SwitchAtLeastThreeCasesCheck.java")
29+
.onFile(testCodeSourcesPath("checks/tests/SwitchAtLeastThreeCasesCheckSample.java"))
2830
.withCheck(new SwitchAtLeastThreeCasesCheck())
2931
.verifyIssues();
3032
}

0 commit comments

Comments
 (0)