Skip to content

Commit 5dcd635

Browse files
authored
Merge pull request #15961 from igfoo/igfoo/MissingEnumInSwitch
Java: Limit the amount of results that MissingEnumInSwitch produces per switch
2 parents 3d8ac14 + b6a1266 commit 5dcd635

File tree

5 files changed

+249
-6
lines changed

5 files changed

+249
-6
lines changed

java/ql/src/Likely Bugs/Statements/MissingEnumInSwitch.ql

Lines changed: 47 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,51 @@
1313

1414
import java
1515

16-
from SwitchStmt switch, EnumType enum, EnumConstant missing
17-
where
18-
switch.getExpr().getType() = enum and
19-
missing.getDeclaringType() = enum and
16+
EnumConstant nthMissing(SwitchStmt switch, int index) {
2017
not exists(switch.getDefaultCase()) and
21-
not switch.getAConstCase().getValue() = missing.getAnAccess()
22-
select switch, "Switch statement does not have a case for $@.", missing, missing.getName()
18+
exists(EnumType enum |
19+
switch.getExpr().getType() = enum and
20+
result =
21+
rank[index](EnumConstant ec |
22+
ec.getDeclaringType() = enum and
23+
not switch.getAConstCase().getValue() = ec.getAnAccess()
24+
|
25+
ec order by ec.getName()
26+
)
27+
)
28+
}
29+
30+
predicate first3(string msg, SwitchStmt switch, EnumConstant e1, EnumConstant e2, EnumConstant e3) {
31+
exists(int n | n = strictcount(nthMissing(switch, _)) |
32+
if n > 3
33+
then msg = "Switch statement does not have a case for $@, $@, $@, or " + (n - 3) + " more."
34+
else msg = "Switch statement does not have a case for $@, $@, or $@."
35+
) and
36+
e1 = nthMissing(switch, 1) and
37+
e2 = nthMissing(switch, 2) and
38+
e3 = nthMissing(switch, 3)
39+
}
40+
41+
predicate only2(string msg, SwitchStmt switch, EnumConstant e1, EnumConstant e2) {
42+
msg = "Switch statement does not have a case for $@ or $@." and
43+
e1 = nthMissing(switch, 1) and
44+
e2 = nthMissing(switch, 2)
45+
}
46+
47+
predicate only1(string msg, SwitchStmt switch, EnumConstant e) {
48+
msg = "Switch statement does not have a case for $@." and
49+
e = nthMissing(switch, 1)
50+
}
51+
52+
from string msg, SwitchStmt switch, EnumConstant e1, EnumConstant e2, EnumConstant e3
53+
where
54+
if first3(_, switch, _, _, _)
55+
then first3(msg, switch, e1, e2, e3)
56+
else
57+
if only2(_, switch, _, _)
58+
then (
59+
only2(msg, switch, e1, e2) and e1 = e3
60+
) else (
61+
only1(msg, switch, e1) and e1 = e2 and e1 = e3
62+
)
63+
select switch, msg, e1, e1.getName(), e2, e2.getName(), e3, e3.getName()
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
category: majorAnalysis
3+
---
4+
* The `java/missing-case-in-switch` query now gives only a single alert for each switch statement, giving some examples of the missing cases as well as a count of how many are missing.
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
| Test.java:8:5:8:13 | switch (...) | Switch statement does not have a case for $@, $@, $@, or 22 more. | Test.java:4:27:4:27 | B | B | Test.java:4:25:4:25 | C | C | Test.java:4:45:4:45 | D | D |
2+
| Test.java:11:5:11:13 | switch (...) | Switch statement does not have a case for $@, $@, $@, or 21 more. | Test.java:4:25:4:25 | C | C | Test.java:4:45:4:45 | D | D | Test.java:4:15:4:15 | E | E |
3+
| Test.java:15:5:15:13 | switch (...) | Switch statement does not have a case for $@, $@, $@, or 20 more. | Test.java:4:45:4:45 | D | D | Test.java:4:15:4:15 | E | E | Test.java:4:43:4:43 | F | F |
4+
| Test.java:20:5:20:13 | switch (...) | Switch statement does not have a case for $@, $@, $@, or 19 more. | Test.java:4:15:4:15 | E | E | Test.java:4:43:4:43 | F | F | Test.java:4:49:4:49 | G | G |
5+
| Test.java:26:5:26:13 | switch (...) | Switch statement does not have a case for $@, $@, $@, or 18 more. | Test.java:4:43:4:43 | F | F | Test.java:4:49:4:49 | G | G | Test.java:4:35:4:35 | H | H |
6+
| Test.java:33:5:33:13 | switch (...) | Switch statement does not have a case for $@, $@, $@, or 2 more. | Test.java:4:21:4:21 | V | V | Test.java:4:13:4:13 | W | W | Test.java:4:23:4:23 | X | X |
7+
| Test.java:56:5:56:13 | switch (...) | Switch statement does not have a case for $@, $@, $@, or 1 more. | Test.java:4:13:4:13 | W | W | Test.java:4:23:4:23 | X | X | Test.java:4:11:4:11 | Y | Y |
8+
| Test.java:80:5:80:13 | switch (...) | Switch statement does not have a case for $@, $@, or $@. | Test.java:4:23:4:23 | X | X | Test.java:4:11:4:11 | Y | Y | Test.java:4:33:4:33 | Z | Z |
9+
| Test.java:105:5:105:13 | switch (...) | Switch statement does not have a case for $@ or $@. | Test.java:4:11:4:11 | Y | Y | Test.java:4:33:4:33 | Z | Z | Test.java:4:11:4:11 | Y | Y |
10+
| Test.java:131:5:131:13 | switch (...) | Switch statement does not have a case for $@. | Test.java:4:33:4:33 | Z | Z | Test.java:4:33:4:33 | Z | Z | Test.java:4:33:4:33 | Z | Z |
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Likely Bugs/Statements/MissingEnumInSwitch.ql
Lines changed: 187 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,187 @@
1+
public class Test {
2+
private enum MyEnum {
3+
// A..Z in random order
4+
N,R,S,Y,W,E,K,I,V,X,C,B,O,J,Z,H,T,P,A,F,D,M,G,U,L,Q
5+
}
6+
7+
public void use(MyEnum e) {
8+
switch(e) {
9+
case A: break;
10+
}
11+
switch(e) {
12+
case A: break;
13+
case B: break;
14+
}
15+
switch(e) {
16+
case A: break;
17+
case B: break;
18+
case C: break;
19+
}
20+
switch(e) {
21+
case A: break;
22+
case B: break;
23+
case C: break;
24+
case D: break;
25+
}
26+
switch(e) {
27+
case A: break;
28+
case B: break;
29+
case C: break;
30+
case D: break;
31+
case E: break;
32+
}
33+
switch(e) {
34+
case A: break;
35+
case B: break;
36+
case C: break;
37+
case D: break;
38+
case E: break;
39+
case F: break;
40+
case G: break;
41+
case H: break;
42+
case I: break;
43+
case J: break;
44+
case K: break;
45+
case L: break;
46+
case M: break;
47+
case N: break;
48+
case O: break;
49+
case P: break;
50+
case Q: break;
51+
case R: break;
52+
case S: break;
53+
case T: break;
54+
case U: break;
55+
}
56+
switch(e) {
57+
case A: break;
58+
case B: break;
59+
case C: break;
60+
case D: break;
61+
case E: break;
62+
case F: break;
63+
case G: break;
64+
case H: break;
65+
case I: break;
66+
case J: break;
67+
case K: break;
68+
case L: break;
69+
case M: break;
70+
case N: break;
71+
case O: break;
72+
case P: break;
73+
case Q: break;
74+
case R: break;
75+
case S: break;
76+
case T: break;
77+
case U: break;
78+
case V: break;
79+
}
80+
switch(e) {
81+
case A: break;
82+
case B: break;
83+
case C: break;
84+
case D: break;
85+
case E: break;
86+
case F: break;
87+
case G: break;
88+
case H: break;
89+
case I: break;
90+
case J: break;
91+
case K: break;
92+
case L: break;
93+
case M: break;
94+
case N: break;
95+
case O: break;
96+
case P: break;
97+
case Q: break;
98+
case R: break;
99+
case S: break;
100+
case T: break;
101+
case U: break;
102+
case V: break;
103+
case W: break;
104+
}
105+
switch(e) {
106+
case A: break;
107+
case B: break;
108+
case C: break;
109+
case D: break;
110+
case E: break;
111+
case F: break;
112+
case G: break;
113+
case H: break;
114+
case I: break;
115+
case J: break;
116+
case K: break;
117+
case L: break;
118+
case M: break;
119+
case N: break;
120+
case O: break;
121+
case P: break;
122+
case Q: break;
123+
case R: break;
124+
case S: break;
125+
case T: break;
126+
case U: break;
127+
case V: break;
128+
case W: break;
129+
case X: break;
130+
}
131+
switch(e) {
132+
case A: break;
133+
case B: break;
134+
case C: break;
135+
case D: break;
136+
case E: break;
137+
case F: break;
138+
case G: break;
139+
case H: break;
140+
case I: break;
141+
case J: break;
142+
case K: break;
143+
case L: break;
144+
case M: break;
145+
case N: break;
146+
case O: break;
147+
case P: break;
148+
case Q: break;
149+
case R: break;
150+
case S: break;
151+
case T: break;
152+
case U: break;
153+
case V: break;
154+
case W: break;
155+
case X: break;
156+
case Y: break;
157+
}
158+
switch(e) {
159+
case A: break;
160+
case B: break;
161+
case C: break;
162+
case D: break;
163+
case E: break;
164+
case F: break;
165+
case G: break;
166+
case H: break;
167+
case I: break;
168+
case J: break;
169+
case K: break;
170+
case L: break;
171+
case M: break;
172+
case N: break;
173+
case O: break;
174+
case P: break;
175+
case Q: break;
176+
case R: break;
177+
case S: break;
178+
case T: break;
179+
case U: break;
180+
case V: break;
181+
case W: break;
182+
case X: break;
183+
case Y: break;
184+
case Z: break;
185+
}
186+
}
187+
}

0 commit comments

Comments
 (0)