Files
openide/java/java-tests/testData/inspection/dataFlow/fixture/SwitchExpressions.java
Tagir Valeev d09640c53d [java-dfa] Report unreachable switch branches after 100% reachable branch
Fixes IDEA-294215 Inspection "Constant conditions & exceptions" does not report all unreachable switch labels

GitOrigin-RevId: 6f1e493b6a665221c1978a5c918028638ec23c09
2022-05-18 10:20:33 +00:00

221 lines
7.0 KiB
Java

import java.util.function.*;
public class SwitchExpressionsJava12 {
void multiLabel(int[] arr) {
int z = switch (arr.length % 5) {
case 0, 4, 3, 2, 1 -> 0;
default -> throw new IllegalStateException("Unexpected value");
};
}
static void fooBar(int k) {
String s = switch (k) {
case 1, 2 -> "foo";
default -> "bar";
};
if(<warning descr="Condition 's.equals(\"baz\")' is always 'false'">s.equals("baz")</warning>) {}
}
enum X {A, B, C};
static void testEnum(X x) {
int i = switch(<error descr="'switch' expression does not cover all possible input values">x</error>) {
case A -> 1;
case B -> 2;
};
// default and case C is missing: we assume that IncompatibleClassChangeError is still thrown
if (<warning descr="Condition 'i == 0' is always 'false'">i == 0</warning>) {}
int i1 = switch(x) {
case A -> 1;
case B -> 2;
case <warning descr="Switch label 'C' is unreachable">C</warning> -> 3;
};
if (<warning descr="Condition 'i1 == 0' is always 'false'">i1 == 0</warning>) {} // exhaustive
}
static void testEnumAndCatch(X x) {
int i1 = 0;
try {
i1 = switch(x) {
case A -> 1;
case B -> 2;
case C -> 3;
};
}
catch (IncompatibleClassChangeError ex) {
if (<warning descr="Condition 'i1 == 0' is always 'true'">i1 == 0</warning>) {}
if (<warning descr="Condition 'x == X.A' is always 'false'">x == X.A</warning>) {}
if (<warning descr="Condition 'x == X.B' is always 'false'">x == X.B</warning>) {}
if (<warning descr="Condition 'x == X.C' is always 'false'">x == X.C</warning>) {}
}
}
static void testBoxed(int i) {
Integer j = switch(i) {
case 1 -> 2;
case 2 -> i+3;
case 3 -> i;
default -> 4;
};
if (<warning descr="Condition 'j > 1' is always 'true'">j > 1</warning>) {}
if (<warning descr="Condition 'j < 6' is always 'true'">j < 6</warning>) {}
if (j < 5) {}
}
static void testBoxedThrow(int i) {
Integer j = switch(i) {
case 1 -> 2;
case 2 -> i+3;
case 3 -> i;
default -> throw new IllegalArgumentException();
};
if (<warning descr="Condition 'j > 1' is always 'true'">j > 1</warning>) {}
if (<warning descr="Condition 'j < 6' is always 'true'">j < 6</warning>) {}
if (j < 5) {}
if (<warning descr="Condition 'j == 5 && i != 2' is always 'false'">j == 5 && <warning descr="Condition 'i != 2' is always 'false' when reached">i != 2</warning></warning>) {}
if (<warning descr="Condition 'i > 3' is always 'false'">i > 3</warning>) {}
if (<warning descr="Condition 'i < 1' is always 'false'">i < 1</warning>) {}
}
static void testIncomplete(Integer i) {
if (i == null) {
System.out.println(switch (<warning descr="Unboxing of 'i' may produce 'NullPointerException'">i</warning>)<error descr="'{' expected">)</error>;
} else {
int x = switch(i) {
case 1 -><EOLError descr="Expression, block or throw statement expected"></EOLError>
case 2 -> {
if (<warning descr="Condition 'i == 1' is always 'false'">i == 1</warning>) {}
throw new IllegalArgumentException();
}
default -> 1;
};
if (x != 1) {
// the only case where we don't know the returned value is i == 1, so the warning is logical here
if (<warning descr="Condition 'i == 1' is always 'true'">i == 1</warning>) {}
}
}
}
static void testSimpleBreak(int i) {
int j = switch(i) {
case 1 -> {
System.out.println("Hello");
yield 10;
}
case 2 -> {
i = i+1;
yield 20;
}
case 3 -> {
yield 33-i;
}
default -> 0;
};
if (j == 20 && <warning descr="Condition 'i == 3' is always 'true' when reached">i == 3</warning>) {}
if (j == 30 && <warning descr="Condition 'i == 3' is always 'true' when reached">i == 3</warning>) {}
if (j == 10 && <warning descr="Condition 'i == 1' is always 'true' when reached">i == 1</warning>) {}
if (<warning descr="Condition 'i == 2' is always 'false'">i == 2</warning>) {}
if (j == 0 && (<warning descr="Condition 'i < 1 || i > 3' is always 'true' when reached">i < 1 || <warning descr="Condition 'i > 3' is always 'true' when reached">i > 3</warning></warning>)) {}
}
static void testSwitchInInlinedLambda(int i) {
int x = ((IntSupplier)() -> {
int j = switch (i) {
case 1 -> 2;
case 2 -> 3;
case 3 -> {
System.out.println("hello");
yield 1;
}
default -> 4;
};
if (j < 2) {}
if (<warning descr="Condition 'j == 4 && i == 2' is always 'false'">j == 4 && <warning descr="Condition 'i == 2' is always 'false' when reached">i == 2</warning></warning>) {}
if (i == 3 && <warning descr="Condition 'j == 1' is always 'true' when reached">j == 1</warning>) {}
return 0;
}).getAsInt();
if (<warning descr="Condition 'x == 1 && i == 3' is always 'false'"><warning descr="Condition 'x == 1' is always 'false'">x == 1</warning> && i == 3</warning>) {}
}
static void testSwitchWithInnerFinally(int i) {
int j = switch (i) {
case 1 -> 2;
case 2 -> 3;
case 3 -> {
try {
System.out.println("hello");
yield 1; // never happens
}
finally {
yield 2;
}
}
default -> 4;
};
if (<warning descr="Condition 'j < 2' is always 'false'">j < 2</warning>) {}
if (<warning descr="Condition 'j == 4 && i == 2' is always 'false'">j == 4 && <warning descr="Condition 'i == 2' is always 'false' when reached">i == 2</warning></warning>) {}
}
static int get(int x) {
return x;
}
void testStatementInsideExpressionInsideBlockLambda(int x, int y) {
int i = ((IntSupplier)() -> {
System.out.println();
return switch(x) {
case 1 -> {
switch (y) {
default -> get(x);
}
yield 5;
}
default -> 10;
};
}).getAsInt();
if (i != 10) {}
}
void testSwitchWithCatch(int x) {
int i = switch(x) {
case 1, 2:
try {
if (x == 1) throw new IllegalArgumentException();
}
catch (IllegalArgumentException ex) {
yield 100;
}
case 3:
yield 200;
default:
yield 300;
};
if (i == 100 && <warning descr="Condition 'x == 1' is always 'true' when reached">x == 1</warning>) {}
if (i == 200 && (<warning descr="Condition 'x == 2 || x == 3' is always 'true' when reached">x == 2 || <warning descr="Condition 'x == 3' is always 'true' when reached">x == 3</warning></warning>)) {}
}
int i;
void testSwitchIncompleteBreak(X e) {
int z;
z = switch (e) {
case A:
i = 1;
yield 2;
case B:
i = 2;
yield 3;
case C:
i = 3;
<error descr="Break out of switch expression is not allowed">break;</error>
default: {
i = 10;
yield 10;/* todo one two */
}
};
System.out.println("i = " + i);
}
}