Merge pull request #15961 from igfoo/igfoo/MissingEnumInSwitch

Java: Limit the amount of results that MissingEnumInSwitch produces per switch
This commit is contained in:
Ian Lynagh
2024-03-28 11:13:45 +00:00
committed by GitHub
5 changed files with 249 additions and 6 deletions

View File

@@ -13,10 +13,51 @@
import java
from SwitchStmt switch, EnumType enum, EnumConstant missing
where
switch.getExpr().getType() = enum and
missing.getDeclaringType() = enum and
EnumConstant nthMissing(SwitchStmt switch, int index) {
not exists(switch.getDefaultCase()) and
not switch.getAConstCase().getValue() = missing.getAnAccess()
select switch, "Switch statement does not have a case for $@.", missing, missing.getName()
exists(EnumType enum |
switch.getExpr().getType() = enum and
result =
rank[index](EnumConstant ec |
ec.getDeclaringType() = enum and
not switch.getAConstCase().getValue() = ec.getAnAccess()
|
ec order by ec.getName()
)
)
}
predicate first3(string msg, SwitchStmt switch, EnumConstant e1, EnumConstant e2, EnumConstant e3) {
exists(int n | n = strictcount(nthMissing(switch, _)) |
if n > 3
then msg = "Switch statement does not have a case for $@, $@, $@, or " + (n - 3) + " more."
else msg = "Switch statement does not have a case for $@, $@, or $@."
) and
e1 = nthMissing(switch, 1) and
e2 = nthMissing(switch, 2) and
e3 = nthMissing(switch, 3)
}
predicate only2(string msg, SwitchStmt switch, EnumConstant e1, EnumConstant e2) {
msg = "Switch statement does not have a case for $@ or $@." and
e1 = nthMissing(switch, 1) and
e2 = nthMissing(switch, 2)
}
predicate only1(string msg, SwitchStmt switch, EnumConstant e) {
msg = "Switch statement does not have a case for $@." and
e = nthMissing(switch, 1)
}
from string msg, SwitchStmt switch, EnumConstant e1, EnumConstant e2, EnumConstant e3
where
if first3(_, switch, _, _, _)
then first3(msg, switch, e1, e2, e3)
else
if only2(_, switch, _, _)
then (
only2(msg, switch, e1, e2) and e1 = e3
) else (
only1(msg, switch, e1) and e1 = e2 and e1 = e3
)
select switch, msg, e1, e1.getName(), e2, e2.getName(), e3, e3.getName()

View File

@@ -0,0 +1,4 @@
---
category: majorAnalysis
---
* 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.

View File

@@ -0,0 +1,10 @@
| 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 |
| 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 |
| 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 |
| 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 |
| 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 |
| 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 |
| 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 |
| 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 |
| 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 |
| 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 |

View File

@@ -0,0 +1 @@
Likely Bugs/Statements/MissingEnumInSwitch.ql

View File

@@ -0,0 +1,187 @@
public class Test {
private enum MyEnum {
// A..Z in random order
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
}
public void use(MyEnum e) {
switch(e) {
case A: break;
}
switch(e) {
case A: break;
case B: break;
}
switch(e) {
case A: break;
case B: break;
case C: break;
}
switch(e) {
case A: break;
case B: break;
case C: break;
case D: break;
}
switch(e) {
case A: break;
case B: break;
case C: break;
case D: break;
case E: break;
}
switch(e) {
case A: break;
case B: break;
case C: break;
case D: break;
case E: break;
case F: break;
case G: break;
case H: break;
case I: break;
case J: break;
case K: break;
case L: break;
case M: break;
case N: break;
case O: break;
case P: break;
case Q: break;
case R: break;
case S: break;
case T: break;
case U: break;
}
switch(e) {
case A: break;
case B: break;
case C: break;
case D: break;
case E: break;
case F: break;
case G: break;
case H: break;
case I: break;
case J: break;
case K: break;
case L: break;
case M: break;
case N: break;
case O: break;
case P: break;
case Q: break;
case R: break;
case S: break;
case T: break;
case U: break;
case V: break;
}
switch(e) {
case A: break;
case B: break;
case C: break;
case D: break;
case E: break;
case F: break;
case G: break;
case H: break;
case I: break;
case J: break;
case K: break;
case L: break;
case M: break;
case N: break;
case O: break;
case P: break;
case Q: break;
case R: break;
case S: break;
case T: break;
case U: break;
case V: break;
case W: break;
}
switch(e) {
case A: break;
case B: break;
case C: break;
case D: break;
case E: break;
case F: break;
case G: break;
case H: break;
case I: break;
case J: break;
case K: break;
case L: break;
case M: break;
case N: break;
case O: break;
case P: break;
case Q: break;
case R: break;
case S: break;
case T: break;
case U: break;
case V: break;
case W: break;
case X: break;
}
switch(e) {
case A: break;
case B: break;
case C: break;
case D: break;
case E: break;
case F: break;
case G: break;
case H: break;
case I: break;
case J: break;
case K: break;
case L: break;
case M: break;
case N: break;
case O: break;
case P: break;
case Q: break;
case R: break;
case S: break;
case T: break;
case U: break;
case V: break;
case W: break;
case X: break;
case Y: break;
}
switch(e) {
case A: break;
case B: break;
case C: break;
case D: break;
case E: break;
case F: break;
case G: break;
case H: break;
case I: break;
case J: break;
case K: break;
case L: break;
case M: break;
case N: break;
case O: break;
case P: break;
case Q: break;
case R: break;
case S: break;
case T: break;
case U: break;
case V: break;
case W: break;
case X: break;
case Y: break;
case Z: break;
}
}
}