Java: Extend control flow analysis to support enhanced switch & switch expression. No break-with-value yet (IDEA-202131)

This commit is contained in:
Pavel Dolgov
2018-11-19 17:26:28 +03:00
parent 21ba76171a
commit cdee0f85e5
6 changed files with 302 additions and 6 deletions
@@ -0,0 +1,108 @@
class C {
void finalVariableAssignedInAllBranches(int k) {
final String s;
switch (k) {
case 1 -> s = "a";
case 2 -> s = "b";
case 3, 4 -> s = "c";
default -> s = "d";
}
System.out.println(s);
}
enum EnumAB {A, B}
void finalVariableAssignedInAllEnumConstantBranches(EnumAB ab) {
final int n;
switch (ab) {
case A -> n = 1;
case B -> n = 2;
}
System.out.println(<error descr="Variable 'n' might not have been initialized">n</error>);
}
void assignedInSomeBranches(String s) {
int n;
switch ((int)Math.random()) {
case 1 -> n = 1;
default -> {}
}
System.out.println(<error descr="Variable 'n' might not have been initialized">n</error>);
}
void finalVariableReassignedAfterSwitchStatement(int n) {
final String s;
switch (n) {
case 1 -> s = "a";
default -> {}
}
<error descr="Variable 's' might already have been assigned to">s</error> = "b";
System.out.println(s);
}
void finalVariableReassignedAfterSwitchExpression(int n) {
final String s;
String t = switch (n) {
case 1 -> s = "a";
default -> "";
};
<error descr="Variable 's' might already have been assigned to">s</error> = t;
System.out.println(s);
}
void finalVariableReassignedInSwitchStatement(int n) {
final String s = "b";
switch (n) {
case 1 -> <error descr="Cannot assign a value to final variable 's'">s</error> = "a";
default -> {}
};
System.out.println(s);
}
void finalVariableReassignedInSwitchExpression(int n) {
final String s = "b";
String string = switch (n) {
case 1 -> <error descr="Cannot assign a value to final variable 's'">s</error> = "a";
default -> "";
};
System.out.println(s);
}
static class FinalFieldAssignedInSomeBranches {
<error descr="Variable 'n' might not have been initialized">final int n</error>;
{
switch ((int)Math.random()) {
case 1 -> n = 1;
default -> {}
}
}
}
static class FinalFieldAssignedInSomeBranchesNoDefault {
<error descr="Variable 'n' might not have been initialized">final int n</error>;
{
switch ((int)Math.random()) {
case 1 -> n = 1;
case 0 -> n = 0;
}
}
}
static class FinalFieldAssignedInAllBranches {
final int n;
{
switch ((int)Math.random()) {
case 1 -> n = 1;
default -> n = 0;
}
}
}
static class FinalFieldInitializedWithswitchExpression {
final int n =
switch ((int)Math.random()) {
case 1 -> 1;
default -> 0;
};
}
}
@@ -0,0 +1,146 @@
class C {
void alwaysThrow(String s) {
switch (s) {
case "a" -> throw new IllegalArgumentException();
default -> throw new IllegalStateException();
}
<error descr="Unreachable statement">System.out.println();</error>
}
void breakFromEndlessLoop() {
EndlessLoop:
for (;;) {
switch ((int)Math.random()) {
case 1 -> {break EndlessLoop;}
default -> throw new RuntimeException();
}
}
System.out.println();
}
void continueEndlessLoop() {
EndlessLoop:
for (;;) {
switch ((int)Math.random()) {
case 1 -> {continue EndlessLoop;}
default -> throw new RuntimeException();
}
}
<error descr="Unreachable statement">System.out.println();</error>
}
void endlessLoopsInAllBranches(String s) {
switch (s) {
case "a" -> { while(true); }
default -> { for(;;); }
}
<error descr="Unreachable statement">System.out.println();</error>
}
void endlessLoopInBranch(String s) {
switch (s) {
case "a" -> { while(true); }
default -> {}
};
System.out.println();
}
/* todo
void endlessLoopInBranchWithValue(String arg) {
int result = switch (arg) {
case "one" -> { while(true); break 1;}
default -> 0;
};
System.out.println(result);
}
*/
static class FinalFieldSwitchExpression {
final String s = switch ((int)Math.random()) {
case 1 -> "a";
default -> "?";
};
{
System.out.println(s);
}
}
void finalVariableSwitchExpression(String s) {
final int n = switch (s) {
case "a" -> 1;
default -> 0;
};
System.out.println(n);
}
void notDefinitelyAssigned(String s) {
int n;
switch (s) {
case "a" -> n = 1;
}
System.out.println(<error descr="Variable 'n' might not have been initialized">n</error>);
}
int returnBeforeEnhancedSwitchStatement(String s) {
return 2;
<error descr="Unreachable statement">switch</error>(s) {
case "a" -> {return 1;}
default -> {return 0;}
}
}
int returnBeforeSwitchExpressionInInitializer(String s) {
return 2;
int n = <error descr="Unreachable statement">switch</error>(s) {
case "a" -> 1;
default -> 0;
};
}
int returnBeforeSwitchExpressionInAssignment(String s) {
int n;
return 2;
n = <error descr="Unreachable statement">switch</error>(s) {
case "a": n= 1;break;
default: n= 0;
};
}
int returnSwitchExpression(String s) {
return switch(s) {
case "a" -> 1;
default -> 0;
};
<error descr="Unreachable statement">System.out.println();</error>
}
static class SwitchExpressionReturnedFromTry {
int foo(String s) throws Exception {
try {
return switch (s) {
case "a" -> bar(1);
default -> bar(0);
};
} finally {
System.out.println("b");
}
<error descr="Unreachable statement">System.out.println("c");</error>
}
int bar(int i) throws Exception { return i; }
}
static class SwitchStatementReturnsFromTry {
int foo(String s) throws Exception {
try {
switch (s) {
case "a" -> { return bar(1); }
default -> { return bar(0); }
}
} finally {
System.out.println("b");
}
<error descr="Unreachable statement">System.out.println("c");</error>
}
int bar(int i) throws Exception { return i; }
}
}