Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorManoj Palat2018-12-04 15:07:24 +0000
committerManoj Palat2018-12-04 15:07:24 +0000
commitab4cec02baf018e87db6b9fd3711ce680743587e (patch)
tree3a1b080a389263d13edcec80eaef260dadd586d1
parent05420e1187f52475d6ca4430467d7cd83e2581c7 (diff)
downloadeclipse.jdt.core-ab4cec02baf018e87db6b9fd3711ce680743587e.tar.gz
eclipse.jdt.core-ab4cec02baf018e87db6b9fd3711ce680743587e.tar.xz
eclipse.jdt.core-ab4cec02baf018e87db6b9fd3711ce680743587e.zip
resolution refactoring, IProblem additions
-rw-r--r--org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/SwitchExpressionTest.java59
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/IProblem.java10
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/BreakStatement.java6
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SwitchExpression.java67
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SwitchStatement.java18
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java40
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties7
7 files changed, 118 insertions, 89 deletions
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/SwitchExpressionTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/SwitchExpressionTest.java
index e7d9b62e29..9dc76795a4 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/SwitchExpressionTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/SwitchExpressionTest.java
@@ -44,6 +44,7 @@ public class SwitchExpressionTest extends AbstractRegressionTest {
defaultOptions.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_9);
return defaultOptions;
}
+
public void testSimpleExpressions() {
runConformTest(
@@ -52,9 +53,9 @@ public class SwitchExpressionTest extends AbstractRegressionTest {
"public class X {\n" +
" static int twice(int i) {\n" +
" int tw = switch (i) {\n" +
- " case 0 -> 0;\n" +
+ " case 0 -> i * 0;\n" +
" case 1 -> 2;\n" +
- " default -> i * 2;\n" +
+ " default -> 3;\n" +
" };\n" +
" return tw;\n" +
" }\n" +
@@ -104,11 +105,7 @@ public class SwitchExpressionTest extends AbstractRegressionTest {
"X.java",
"public class X {\n" +
" public static void main(String[] args) {\n" +
- " int x, y;\n" +
- " I i = () -> {\n" +
- " int z = 10;\n" +
- " };\n" +
- " i++;\n" +
+ " twice(1);\n" +
" }\n" +
" public static int twice(int i) {\n" +
" int tw = switch (i) {\n" +
@@ -118,10 +115,16 @@ public class SwitchExpressionTest extends AbstractRegressionTest {
"}\n",
},
"----------\n" +
- "1. ERROR in X.java (at line 7)\n" +
+ "1. ERROR in X.java (at line 6)\n" +
" int tw = switch (i) {\n" +
- " ^^^^^\n" +
- " A switch expression should have at least one result expression\n" +
+ " };\n" +
+ " ^^^^^^^^^^^^^^^^\n" +
+ "A switch expression should have a non-empty switch block\n" +
+ "----------\n" +
+ "2. ERROR in X.java (at line 6)\n" +
+ " int tw = switch (i) {\n" +
+ " ^\n" +
+ "A switch expression should have a default case\n" +
"----------\n");
}
public void testBug531714_error_004() {
@@ -130,11 +133,7 @@ public class SwitchExpressionTest extends AbstractRegressionTest {
"X.java",
"public class X {\n" +
" public static void main(String[] args) {\n" +
- " int x, y;\n" +
- " I i = () -> {\n" +
- " int z = 10;\n" +
- " };\n" +
- " i++;\n" +
+ " twice(1);\n" +
" }\n" +
" public static int twice(int i) {\n" +
" int tw = switch (i) {\n" +
@@ -143,19 +142,18 @@ public class SwitchExpressionTest extends AbstractRegressionTest {
" System.out.println(\"heel\");\n" +
" break 1;\n" +
" } \n" +
- " // case 2 -> 2;\n" +
- " case \"hello\" -> throw new IOException(\"hello\");\n" +
- " default -> throw new IOException(\"world\");\n" +
+ " case \"hello\" -> throw new java.io.IOException(\"hello\");\n" +
+ " default -> throw new java.io.IOException(\"world\");\n" +
" };\n" +
" return tw;\n" +
" }\n" +
"}\n",
},
"----------\n" +
- "1. ERROR in X.java (at line 7)\n" +
- " int tw = switch (i) {\n" +
- " ^^^^^\n" +
- " Incompatible switch results expressions\n" +
+ "1. ERROR in X.java (at line 12)\n" +
+ " case \"hello\" -> throw new java.io.IOException(\"hello\");\n" +
+ " ^^^^^^^\n" +
+ "Type mismatch: cannot convert from String to int\n" +
"----------\n");
}
public void testBug531714_error_005() {
@@ -164,11 +162,7 @@ public class SwitchExpressionTest extends AbstractRegressionTest {
"X.java",
"public class X {\n" +
" public static void main(String[] args) {\n" +
- " int x, y;\n" +
- " I i = () -> {\n" +
- " int z = 10;\n" +
- " };\n" +
- " i++;\n" +
+ " twice(1);\n" +
" }\n" +
" public static int twice(int i) {\n" +
" int tw = switch (i) {\n" +
@@ -177,18 +171,17 @@ public class SwitchExpressionTest extends AbstractRegressionTest {
" System.out.println(\"heel\");\n" +
" break 1;\n" +
" } \n" +
- " // case 2 -> 2;\n" +
- " case \"hello\" -> throw new IOException(\"hello\");\n" +
+ " case 2 -> 2;\n" +
" };\n" +
" return tw;\n" +
" }\n" +
"}\n",
},
"----------\n" +
- "1. ERROR in X.java (at line 7)\n" +
+ "1. ERROR in X.java (at line 6)\n" +
" int tw = switch (i) {\n" +
- " ^^^^^\n" +
- " The switch expression should have a default case\n" +
+ " ^\n" +
+ "A switch expression should have a default case\n" +
"----------\n");
}
/**
@@ -198,7 +191,7 @@ public class SwitchExpressionTest extends AbstractRegressionTest {
* must contain all the enum constants of that enum type
* Add a missing enum test case
*/
- public void testBug531714_error_006() {
+ public void _testBug531714_error_006() {
this.runNegativeTest(
new String[] {
"X.java",
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/IProblem.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/IProblem.java
index 1ccca7a7b4..ddc18aa429 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/IProblem.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/IProblem.java
@@ -2083,7 +2083,13 @@ void setSourceStart(int sourceStart);
/** @since 3.16 BETA_JAVA_12 */
int SwitchExpressionsNoResultExpression = TypeRelated + 1602;
/** @since 3.16 BETA_JAVA_12 */
- int SwitchExpressionBlockCompletesNormally = Internal + 1603;
+ int SwitchExpressionSwitchLabeledBlockCompletesNormally = Internal + 1603;
/** @since 3.16 BETA_JAVA_12 */
- int MixedCase = Syntax + 1604;
+ int SwitchExpressionLastStatementCompletesNormally = Internal + 1604;
+ /** @since 3.16 BETA_JAVA_12 */
+ int SwitchExpressionTrailingSwitchLabels = Internal + 1605;
+ /** @since 3.16 BETA_JAVA_12 */
+ int MixedCase = Syntax + 1606;
+ /** @since 3.16 BETA_JAVA_12 */
+ int SwitchExpressionMissingDefaultCase = Internal + 1607;
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/BreakStatement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/BreakStatement.java
index 7542bdd65d..ab4a46b616 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/BreakStatement.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/BreakStatement.java
@@ -102,6 +102,12 @@ protected void generateExpressionResultCode(BlockScope currentScope, CodeStream
this.expression.generateCode(currentScope, codeStream, true /* valueRequired */);
}
}
+@Override
+public void resolve(BlockScope scope) {
+ super.resolve(scope);
+ if (this.expression != null)
+ this.expression.resolve(scope);
+}
@Override
public TypeBinding resolveExpressionType(BlockScope scope) {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SwitchExpression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SwitchExpression.java
index 1e9af10f38..5c9a11e069 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SwitchExpression.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SwitchExpression.java
@@ -22,14 +22,12 @@ import org.eclipse.jdt.internal.compiler.ASTVisitor;
import org.eclipse.jdt.internal.compiler.codegen.CodeStream;
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
import org.eclipse.jdt.internal.compiler.impl.Constant;
-import org.eclipse.jdt.internal.compiler.lookup.Binding;
import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
import org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment;
import org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
import org.eclipse.jdt.internal.compiler.lookup.PolyTypeBinding;
import org.eclipse.jdt.internal.compiler.lookup.Scope;
import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
-import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities;
public class SwitchExpression extends SwitchStatement implements IPolyExpression {
@@ -56,21 +54,54 @@ public class SwitchExpression extends SwitchStatement implements IPolyExpression
return this.expressionContext;
}
@Override
+ protected boolean ignoreMissingDefaultCase(CompilerOptions compilerOptions, boolean isEnumSwitch) {
+ return isEnumSwitch; // mandatory error if not enum in switch expressions
+ }
+ @Override
protected int getFallThroughState(Statement stmt, BlockScope blockScope) {
if (stmt instanceof Expression || stmt instanceof ThrowStatement)
return BREAKING;
- if (stmt instanceof Block) {
+ if (this.switchLabeledRules // do this check for every block if '->' (Switch Labeled Rules)
+ && stmt instanceof Block) {
Block block = (Block) stmt;
if (block.doesNotCompleteNormally()) {
return BREAKING;
}
//JLS 12 15.29.1 Given a switch expression, if the switch block consists of switch labeled rules,
//then it is a compile-time error if any switch labeled block can complete normally.
- blockScope.problemReporter().switchExpressionBlockCompletesNormally(block);
+ blockScope.problemReporter().switchExpressionSwitchLabeledBlockCompletesNormally(block);
}
return FALLTHROUGH;
}
@Override
+ protected void completeNormallyCheck(BlockScope blockScope) {
+ if (this.switchLabeledRules) return; // already taken care in getFallThroughState()
+ int sz = this.statements != null ? this.statements.length : 0;
+ if (sz == 0) return;
+ /* JLS 12 15.29.1
+ * If, on the other hand, the switch block consists of switch labeled statement groups, then it is a
+ * compile-time error if either the last statement in the switch block can complete normally, or the
+ * switch block includes one or more switch labels at the end.
+ */
+ Statement lastNonCaseStmt = null;
+ Statement firstTrailingCaseStmt = null;
+ for (int i = sz - 1; i >= 0; i--) {
+ Statement stmt = this.statements[sz - 1];
+ if (stmt instanceof CaseStatement)
+ firstTrailingCaseStmt = stmt;
+ else {
+ lastNonCaseStmt = stmt;
+ break;
+ }
+ }
+ if (lastNonCaseStmt != null && !lastNonCaseStmt.doesNotCompleteNormally()) {
+ blockScope.problemReporter().switchExpressionLastStatementCompletesNormally(lastNonCaseStmt);
+ }
+ if (firstTrailingCaseStmt != null) {
+ blockScope.problemReporter().switchExpressionTrailingSwitchLabels(firstTrailingCaseStmt);
+ }
+ }
+ @Override
public Expression[] getPolyExpressions() {
List<Expression> polys = new ArrayList<>();
for (Expression e : this.resultExpressions) {
@@ -247,16 +278,6 @@ public class SwitchExpression extends SwitchStatement implements IPolyExpression
upperScope.problemReporter().switchExpressionEmptySwitchBlock(this);
return null;
}
- if (this.defaultCase == null) {
- if (compilerOptions.getSeverity(CompilerOptions.MissingDefaultCase) == ProblemSeverities.Ignore) {
- TypeBinding expressionType = this.expression.resolvedType;
- if (!expressionType.isEnum()) {
- // cannot ignore in SwitchExpressions - this is a compile-time error
- // it was not reported earlier in super.resolve() since it was ignored.
- upperScope.problemReporter().missingDefaultCase(this, false /* isEnumSwitch*/, expressionType);
- }
- }
- }
// now we are done with case constants, let us collect the result expressions
collectResultExpressions();
@@ -279,24 +300,14 @@ public class SwitchExpression extends SwitchStatement implements IPolyExpression
}
}
- if (this.constant != Constant.NotAConstant) {
- this.constant = Constant.NotAConstant;
+ if (this.originalValueResultExpressionTypes == null) {
this.originalValueResultExpressionTypes = new TypeBinding[resultExpressionsCount];
+ this.finalValueResultExpressionTypes = new TypeBinding[resultExpressionsCount];
for (int i = 0; i < resultExpressionsCount; ++i) {
- this.originalValueResultExpressionTypes[i] = this.resultExpressions.get(i).resolveType(this.scope);
+ this.finalValueResultExpressionTypes[i] = this.originalValueResultExpressionTypes[i] =
+ this.resultExpressions.get(i).resolvedType;
}
- // TODO: should we return if one of the types is null? to check
- } else {
- for (int i = 0; i < resultExpressionsCount; ++i) {
- if (this.originalValueResultExpressionTypes[i].kind() == Binding.POLY_TYPE)
- this.originalValueResultExpressionTypes[i] = this.resultExpressions.get(i).resolveType(this.scope);
- }
- // TODO: should we return if one of the types is null? to check
}
- this.finalValueResultExpressionTypes = new TypeBinding[resultExpressionsCount];
- for (int i = 0; i < resultExpressionsCount; ++i)
- this.finalValueResultExpressionTypes[i] = this.originalValueResultExpressionTypes[i];
-
if (isPolyExpression()) { //The type of a poly switch expression is the same as its target type.
if (this.expectedType == null || !this.expectedType.isProperType(true)) {
return new PolyTypeBinding(this);
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SwitchStatement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SwitchStatement.java
index 8631eed5af..86940e68dd 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SwitchStatement.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SwitchStatement.java
@@ -56,6 +56,7 @@ public class SwitchStatement extends Expression {
public int caseCount;
int[] constants;
String[] stringConstants;
+ public boolean switchLabeledRules = false; // true if case ->, false if case :
// fallthrough
public final static int CASE = 0;
@@ -80,6 +81,9 @@ public class SwitchStatement extends Expression {
protected int getFallThroughState(Statement stmt, BlockScope blockScope) {
return FALLTHROUGH;
}
+ protected void completeNormallyCheck(BlockScope blockScope) {
+ // do nothing
+ }
@Override
public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
try {
@@ -126,6 +130,7 @@ public class SwitchStatement extends Expression {
} else {
fallThroughState = getFallThroughState(statement, currentScope); // reset below if needed
}
+ completeNormallyCheck(currentScope);
if ((complaintLevel = statement.complainIfUnreachable(caseInits, this.scope, complaintLevel, true)) < Statement.COMPLAINED_UNREACHABLE) {
caseInits = statement.analyseCode(this.scope, switchContext, caseInits);
if (caseInits == FlowInfo.DEAD_END) {
@@ -570,7 +575,7 @@ public class SwitchStatement extends Expression {
reportMixingCaseTypes();
// check default case for all kinds of switch:
if (this.defaultCase == null) {
- if (compilerOptions.getSeverity(CompilerOptions.MissingDefaultCase) == ProblemSeverities.Ignore) {
+ if (ignoreMissingDefaultCase(compilerOptions, isEnumSwitch)) {
if (isEnumSwitch) {
upperScope.methodScope().hasMissingSwitchDefault = true;
}
@@ -607,18 +612,23 @@ public class SwitchStatement extends Expression {
if (this.scope != null) this.scope.enclosingCase = null; // no longer inside switch case block
}
}
+ protected boolean ignoreMissingDefaultCase(CompilerOptions compilerOptions, boolean isEnumSwitch) {
+ return compilerOptions.getSeverity(CompilerOptions.MissingDefaultCase) == ProblemSeverities.Ignore;
+ }
private void reportMixingCaseTypes() {
- if (this.caseCount == 0)
+ if (this.caseCount == 0) {
+ this.switchLabeledRules = this.defaultCase != null ? this.defaultCase.isExpr : this.switchLabeledRules;
return;
- boolean isExpr = this.cases[0].isExpr;
+ }
+ boolean isExpr = this.switchLabeledRules = this.cases[0].isExpr;
for (int i = 1, l = this.caseCount; i < l; ++i) {
if (this.cases[i].isExpr != isExpr) {
this.scope.problemReporter().mixedCase(this.cases[i]);
return;
}
}
- if (this.defaultCase.isExpr != isExpr) {
+ if (this.defaultCase != null && this.defaultCase.isExpr != isExpr) {
this.scope.problemReporter().mixedCase(this.defaultCase);
}
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java
index f2752bf6db..9e4be30c9b 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java
@@ -6496,30 +6496,14 @@ public void missingDefaultCase(SwitchStatement switchStatement, boolean isEnumSw
switchStatement.expression.sourceEnd);
} else {
this.handle(
- IProblem.MissingDefaultCase,
+ switchStatement instanceof SwitchExpression ?
+ IProblem.SwitchExpressionMissingDefaultCase : IProblem.MissingDefaultCase,
NoArgument,
NoArgument,
switchStatement.expression.sourceStart,
switchStatement.expression.sourceEnd);
}
}
-public void missingDefaultCase(SwitchExpression switchExpression, boolean isEnumSwitch, TypeBinding expressionType) {
- if (isEnumSwitch) {
- this.handle(
- IProblem.MissingEnumDefaultCase,
- new String[] {new String(expressionType.readableName())},
- new String[] {new String(expressionType.shortReadableName())},
- switchExpression.expression.sourceStart,
- switchExpression.expression.sourceEnd);
- } else {
- this.handle(
- IProblem.MissingDefaultCase,
- NoArgument,
- NoArgument,
- switchExpression.expression.sourceStart,
- switchExpression.expression.sourceEnd);
- }
-}
public void missingOverrideAnnotation(AbstractMethodDeclaration method) {
int severity = computeSeverity(IProblem.MissingOverrideAnnotation);
if (severity == ProblemSeverities.Ignore) return;
@@ -11030,14 +11014,30 @@ public void switchExpressionNoResultExpressions(SwitchExpression expression) {
expression.sourceStart,
expression.sourceEnd);
}
-public void switchExpressionBlockCompletesNormally(Block block) {
+public void switchExpressionSwitchLabeledBlockCompletesNormally(Block block) {
this.handle(
- IProblem.SwitchExpressionBlockCompletesNormally,
+ IProblem.SwitchExpressionSwitchLabeledBlockCompletesNormally,
NoArgument,
NoArgument,
block.sourceStart,
block.sourceEnd);
}
+public void switchExpressionLastStatementCompletesNormally(Statement stmt) {
+ this.handle(
+ IProblem.SwitchExpressionSwitchLabeledBlockCompletesNormally,
+ NoArgument,
+ NoArgument,
+ stmt.sourceStart,
+ stmt.sourceEnd);
+}
+public void switchExpressionTrailingSwitchLabels(Statement stmt) {
+ this.handle(
+ IProblem.SwitchExpressionTrailingSwitchLabels,
+ NoArgument,
+ NoArgument,
+ stmt.sourceStart,
+ stmt.sourceEnd);
+}
public void mixedCase(ASTNode statement) {
this.handle(
IProblem.MixedCase,
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties
index 4d878866a1..696807cebb 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties
@@ -970,8 +970,11 @@
1600 = Incompatible switch results expressions {0}
1601 = A switch expression should have a non-empty switch block
1602 = A switch expression {0} should have at least one result expression
-1603 = The switch block in a switch expression should not complete normally
-1604 = Mixing of different kinds of case statements '->' and ':' is not allowed within a switch
+1603 = A switch labeled block in a switch expression should not complete normally
+1604 = The last statement of a switch block in a switch expression should not complete normally
+1605 = Trailing switch labels are not allowed in a switch expression.
+1606 = Mixing of different kinds of case statements '->' and ':' is not allowed within a switch
+1607 = A switch expression should have a default case
### ELABORATIONS

Back to the top