Skip to content

Commit 1f730dd

Browse files
SONARJAVA-5730 S1301 should report on small but non-exhaustive switch over enum (#5538)
1 parent 7a9542a commit 1f730dd

2 files changed

Lines changed: 68 additions & 3 deletions

File tree

java-checks-test-sources/default/src/test/java/checks/tests/SwitchAtLeastThreeCasesCheckSample.java

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,4 +122,59 @@ public int switchOverSmallEnum3(SmallEnum smallEnum) {
122122
}
123123
return ret;
124124
}
125+
126+
public enum LargeEnum {
127+
MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY
128+
};
129+
130+
public String switchOverLargeEnum(LargeEnum largeEnum) {
131+
String mood = "excited";
132+
switch (largeEnum) { // Noncompliant
133+
case FRIDAY:
134+
mood = "love";
135+
break;
136+
}
137+
return mood;
138+
}
139+
140+
public enum SmallEnumWithMethods {
141+
PUBLIC("pub"),
142+
PRIVATE("prv");
143+
144+
enum Weird {A, B, C}
145+
146+
private final String label;
147+
148+
SmallEnumWithMethods(String label) {
149+
this.label = label;
150+
}
151+
152+
public String getLabel() {
153+
return label;
154+
}
155+
156+
public int spaceRequired() {
157+
return label.length();
158+
}
159+
}
160+
161+
public int switchSmallEnumWithMethods1(SmallEnumWithMethods largeEnum) {
162+
int ret = -1;
163+
switch (largeEnum) { // Compliant
164+
case PRIVATE:
165+
ret = 1;
166+
break;
167+
case PUBLIC:
168+
ret = 2;
169+
break;
170+
}
171+
return ret;
172+
}
173+
174+
public void switchSmallEnumWithMethods2(SmallEnumWithMethods largeEnum) {
175+
switch (largeEnum) { // Compliant
176+
case PRIVATE, PUBLIC:
177+
System.out.println("Same, Same");
178+
}
179+
}
125180
}

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

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,10 +56,11 @@ public void visitNode(Tree tree) {
5656
return;
5757
}
5858

59-
// Switching over an enum without a default case will cause a compilation error
60-
// if a new enum constant is added. Therefore, using if-then should not be recommended.
59+
// Do not suggest replacing exhaustive switches over small enums.
60+
// It does not aid readability and can lead to error-prone code when
61+
// "->" switch is used (adding new enum constant would cause compilation error).
6162
Symbol.TypeSymbol typeSymbol = switchStatementTree.expression().symbolType().symbol();
62-
if (typeSymbol.isEnum() && !hasDefault) {
63+
if (typeSymbol.isEnum() && !hasDefault && enumConstantCount(typeSymbol) == count) {
6364
return;
6465
}
6566

@@ -94,6 +95,15 @@ private static boolean containsDefaultLabel(CaseGroupTree caseGroup) {
9495
return false;
9596
}
9697

98+
/**
99+
* Number of constants declared in the enum. Note, that it excludes fields and methods.
100+
*/
101+
private static long enumConstantCount(Symbol.TypeSymbol typeSymbol) {
102+
return typeSymbol.memberSymbols().stream()
103+
.filter(s -> s.isVariableSymbol() && s.isEnum())
104+
.count();
105+
}
106+
97107
private static boolean hasLabelWithAllowedPattern(CaseGroupTree caseGroupTree) {
98108
return caseGroupTree.labels().stream()
99109
.flatMap(label -> label.expressions().stream())

0 commit comments

Comments
 (0)