diff options
author | Manoj Palat | 2021-07-19 10:23:28 +0000 |
---|---|---|
committer | Manoj Palat | 2021-07-20 06:03:48 +0000 |
commit | 4df7abeadfe8285f7c6cd9602c94f5df27e3c3de (patch) | |
tree | 1755047b3de3aafc5d13a27abc6a1f294ba2b8fe | |
parent | 3061eef5b53f12845a18e3496b5f7e5941c616c3 (diff) | |
download | eclipse.jdt.core-4df7abeadfe8285f7c6cd9602c94f5df27e3c3de.tar.gz eclipse.jdt.core-4df7abeadfe8285f7c6cd9602c94f5df27e3c3de.tar.xz eclipse.jdt.core-4df7abeadfe8285f7c6cd9602c94f5df27e3c3de.zip |
Change-Id: I8d3cff818a97e328336f0d7ddd324dd1ddd33552
Signed-off-by: Manoj Palat <manpalat@in.ibm.com>
Reviewed-on: https://git.eclipse.org/r/c/jdt/eclipse.jdt.core/+/183161
Tested-by: JDT Bot <jdt-bot@eclipse.org>
6 files changed, 268 insertions, 28 deletions
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/CompilerInvocationTests.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/CompilerInvocationTests.java index f6c508b0b7..262b9b3c4c 100644 --- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/CompilerInvocationTests.java +++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/CompilerInvocationTests.java @@ -1301,6 +1301,7 @@ public void test011_problem_categories() { expectedProblemAttributes.put("SwitchPatternConstantCaseLabelIncompatible", new ProblemAttributes(true)); expectedProblemAttributes.put("SwitchPatternConstantWithPatternIncompatible", new ProblemAttributes(true)); expectedProblemAttributes.put("IllegalFallthroughToPattern", new ProblemAttributes(true)); + expectedProblemAttributes.put("SwitchPatternAnyPatternCaseLabelNotAllowed", new ProblemAttributes(true)); StringBuffer failures = new StringBuffer(); StringBuffer correctResult = new StringBuffer(70000); @@ -2372,6 +2373,7 @@ public void test012_compiler_problems_tuning() { expectedProblemAttributes.put("SwitchPatternConstantCaseLabelIncompatible", SKIP); expectedProblemAttributes.put("SwitchPatternConstantWithPatternIncompatible", SKIP); expectedProblemAttributes.put("IllegalFallthroughToPattern", SKIP); + expectedProblemAttributes.put("SwitchPatternAnyPatternCaseLabelNotAllowed", SKIP); Map constantNamesIndex = new HashMap(); Field[] fields = JavaCore.class.getFields(); for (int i = 0, length = fields.length; i < length; i++) { diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/SwitchPatternTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/SwitchPatternTest.java index 641953de86..f630fae6a2 100644 --- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/SwitchPatternTest.java +++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/SwitchPatternTest.java @@ -27,7 +27,7 @@ public class SwitchPatternTest extends AbstractRegressionTest9 { static { // TESTS_NUMBERS = new int [] { 40 }; // TESTS_RANGE = new int[] { 1, -1 }; -// TESTS_NAMES = new String[] { "testBug574793_001"}; +// TESTS_NAMES = new String[] { "testBug574564_00de6"}; } private static String previewLevel = "17"; @@ -1750,4 +1750,223 @@ public class SwitchPatternTest extends AbstractRegressionTest9 { "A switch labeled block in a switch expression should not complete normally\n" + "----------\n"); } + public void testBug574564_001() { + runNegativeTest( + new String[] { + "X.java", + "public class X {\n"+ + " public static void main(String[] args) {\n"+ + " foo(new String(\"Hello\"));\n"+ + " }\n"+ + " private static void foo(Object o) {\n"+ + " switch (o) {\n"+ + " case var i -> System.out.println(0);\n"+ + " default -> System.out.println(o);\n"+ + " }\n"+ + " }\n"+ + "}", + }, + "----------\n" + + "1. ERROR in X.java (at line 7)\n" + + " case var i -> System.out.println(0);\n" + + " ^^^^^\n" + + "Any patterns not allowed as switch case label elements\n" + + "----------\n"); + } + public void testBug574564_002() { + runNegativeTest( + new String[] { + "X.java", + "public class X {\n"+ + " public static void main(String[] args) {\n"+ + " foo(new String(\"Hello\"));\n"+ + " }\n"+ + " private static void foo(Object o) {\n"+ + " switch (o) {\n"+ + " case var i, var j, var k -> System.out.println(0);\n"+ + " default -> System.out.println(o);\n"+ + " }\n"+ + " }\n"+ + "}", + }, + "----------\n" + + "1. ERROR in X.java (at line 7)\n" + + " case var i, var j, var k -> System.out.println(0);\n" + + " ^^^^^\n" + + "Any patterns not allowed as switch case label elements\n" + + "----------\n" + + "2. ERROR in X.java (at line 7)\n" + + " case var i, var j, var k -> System.out.println(0);\n" + + " ^^^^^\n" + + "Any patterns not allowed as switch case label elements\n" + + "----------\n" + + "3. ERROR in X.java (at line 7)\n" + + " case var i, var j, var k -> System.out.println(0);\n" + + " ^^^^^\n" + + "Any patterns not allowed as switch case label elements\n" + + "----------\n"); + } + public void testBug574564_003() { + runNegativeTest( + new String[] { + "X.java", + "public class X {\n"+ + " public static void main(String[] args) {\n"+ + " foo(10);\n"+ + " }\n"+ + " private static void foo(Integer o) {\n"+ + " switch (o) {\n"+ + " case var i, 10 -> System.out.println(0);\n"+ + " default -> System.out.println(o);\n"+ + " }\n"+ + " }\n"+ + "}", + }, + "----------\n" + + "1. ERROR in X.java (at line 7)\n" + + " case var i, 10 -> System.out.println(0);\n" + + " ^^^^^\n" + + "Any patterns not allowed as switch case label elements\n" + + "----------\n"); + } + public void testBug574564_004() { + runNegativeTest( + new String[] { + "X.java", + "public class X {\n"+ + " public static void main(String[] args) {\n"+ + " foo(10);\n"+ + " }\n"+ + " private static void foo(Integer o) {\n"+ + " switch (o) {\n"+ + " case var i, 10, var k -> System.out.println(0);\n"+ + " default -> System.out.println(o);\n"+ + " }\n"+ + " }\n"+ + "}", + }, + "----------\n" + + "1. ERROR in X.java (at line 7)\n" + + " case var i, 10, var k -> System.out.println(0);\n" + + " ^^^^^\n" + + "Any patterns not allowed as switch case label elements\n" + + "----------\n" + + "2. ERROR in X.java (at line 7)\n" + + " case var i, 10, var k -> System.out.println(0);\n" + + " ^^^^^\n" + + "Any patterns not allowed as switch case label elements\n" + + "----------\n"); + } + public void testBug574564_005() { + runNegativeTest( + new String[] { + "X.java", + "public class X {\n"+ + " public static void main(String[] args) {\n"+ + " foo(10);\n"+ + " }\n"+ + " private static void foo(Integer o) {\n"+ + " switch (o) {\n"+ + " case 10, null, var k -> System.out.println(0);\n"+ + " default -> System.out.println(o);\n"+ + " }\n"+ + " }\n"+ + "}", + }, + "----------\n" + + "1. ERROR in X.java (at line 7)\n" + + " case 10, null, var k -> System.out.println(0);\n" + + " ^^^^^\n" + + "Any patterns not allowed as switch case label elements\n" + + "----------\n"); + } + public void testBug574564_006() { + runNegativeTest( + new String[] { + "X.java", + "public class X {\n"+ + " public static void main(String[] args) {\n"+ + " foo(10);\n"+ + " }\n"+ + " private static void foo(Integer o) {\n"+ + " switch (o) {\n"+ + " case default, var k -> System.out.println(0);\n"+ + " default -> System.out.println(o);\n"+ + " }\n"+ + " }\n"+ + "}", + }, + "----------\n" + + "1. ERROR in X.java (at line 7)\n" + + " case default, var k -> System.out.println(0);\n" + + " ^^^^^\n" + + "Any patterns not allowed as switch case label elements\n" + + "----------\n" + + "2. ERROR in X.java (at line 8)\n" + + " default -> System.out.println(o);\n" + + " ^^^^^^^\n" + + "The default case is already defined\n" + + "----------\n"); + } + public void testBug574564_007() { + runNegativeTest( + new String[] { + "X.java", + "public class X {\n"+ + " public static void main(String[] args) {\n"+ + " foo(10);\n"+ + " }\n"+ + " private static void foo(Integer o) {\n"+ + " switch (o) {\n"+ + " case default, default, var k -> System.out.println(0);\n"+ + " default -> System.out.println(o);\n"+ + " }\n"+ + " }\n"+ + "}", + }, + "----------\n" + + "1. ERROR in X.java (at line 7)\n" + + " case default, default, var k -> System.out.println(0);\n" + + " ^^^^^^^^\n" + + "The default case is already defined\n" + + "----------\n" + + "2. ERROR in X.java (at line 7)\n" + + " case default, default, var k -> System.out.println(0);\n" + + " ^^^^^\n" + + "Any patterns not allowed as switch case label elements\n" + + "----------\n" + + "3. ERROR in X.java (at line 8)\n" + + " default -> System.out.println(o);\n" + + " ^^^^^^^\n" + + "The default case is already defined\n" + + "----------\n"); + } + public void testBug574564_008() { + runNegativeTest( + new String[] { + "X.java", + "public class X {\n"+ + " public static void main(String[] args) {\n"+ + " foo(10);\n"+ + " }\n"+ + " private static void foo(Integer o) {\n"+ + " switch (o) {\n"+ + " case default, 1, var k -> System.out.println(0);\n"+ + " default -> System.out.println(o);\n"+ + " }\n"+ + " }\n"+ + "}", + }, + "----------\n" + + "1. ERROR in X.java (at line 7)\n" + + " case default, 1, var k -> System.out.println(0);\n" + + " ^^^^^\n" + + "Any patterns not allowed as switch case label elements\n" + + "----------\n" + + "2. ERROR in X.java (at line 8)\n" + + " default -> System.out.println(o);\n" + + " ^^^^^^^\n" + + "The default case is already defined\n" + + "----------\n"); + } } 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 652bc57ce3..ed5c682eaf 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 @@ -2486,4 +2486,7 @@ void setSourceStart(int sourceStart); */ int IllegalFallthroughToPattern = PreviewRelated + 1904; + /** @since 3.27 BETA_JAVA17 + * @noreference preview feature error */ + int SwitchPatternAnyPatternCaseLabelNotAllowed = PreviewRelated + 1905; }
\ No newline at end of file diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CaseStatement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CaseStatement.java index 844a5fad97..e2d03f8b31 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CaseStatement.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CaseStatement.java @@ -197,38 +197,40 @@ public Constant[] resolveWithPatternVariablesInScope(LocalVariableBinding[] patt return resolveCasePrivate(scope, switchExpressionType, switchStatement); } } -private Expression getFirstNonDefaultExpression() { - if (this.constantExpressions != null) { - for (Expression e : this.constantExpressions) { - if (!(e instanceof FakeDefaultLiteral)) return e; +private Expression getFirstValidExpression(BlockScope scope, SwitchStatement switchStatement) { + assert this.constantExpressions != null; + Expression ret = null; + + for (Expression e : this.constantExpressions) { + if (e instanceof PatternExpression && ((PatternExpression) e).pattern instanceof AnyPattern) { + // flag error + scope.problemReporter().switchPatternAnyPatternCaseLabelNotAllowed(e); + } else if (e instanceof FakeDefaultLiteral) { + flagDuplicateDefault(scope, switchStatement); + } else { + ret = ret != null ? ret : e; } } - return null; + return ret; } private Constant[] resolveCasePrivate(BlockScope scope, TypeBinding switchExpressionType, SwitchStatement switchStatement) { // switchExpressionType maybe null in error case scope.enclosingCase = this; // record entering in a switch case block - Expression constExpr = getFirstNonDefaultExpression(); - int defaultCount = 0; - int nConstExprs = this.constantExpressions != null ? this.constantExpressions.length : 0; + if (this.constantExpressions == null) { + flagDuplicateDefault(scope, switchStatement); + return Constant.NotAConstantList; + } + Expression constExpr = getFirstValidExpression(scope, switchStatement); if (constExpr == null) { - do { - ++defaultCount; - // remember the default case into the associated switch statement - if (switchStatement.defaultCase != null) - scope.problemReporter().duplicateDefaultCase(this); - - // on error the last default will be the selected one ... - switchStatement.defaultCase = this; - } while (defaultCount < nConstExprs); return Constant.NotAConstantList; } + // add into the collection of cases of the associated switch statement switchStatement.cases[switchStatement.caseCount++] = this; if (switchExpressionType != null && switchExpressionType.isEnum() && (constExpr instanceof SingleNameReference)) { ((SingleNameReference) constExpr).setActualReceiverType((ReferenceBinding)switchExpressionType); } -// this.scope = new BlockScope(scope); + TypeBinding caseType = constExpr.resolveType(scope); if (caseType == null || switchExpressionType == null) return Constant.NotAConstantList; // tag constant name with enum type for privileged access to its members @@ -238,15 +240,9 @@ private Constant[] resolveCasePrivate(BlockScope scope, TypeBinding switchExpres if (e != constExpr) { if (switchExpressionType.isEnum() && (e instanceof SingleNameReference)) { ((SingleNameReference) e).setActualReceiverType((ReferenceBinding)switchExpressionType); - } else if (e instanceof FakeDefaultLiteral) { - if (switchStatement.defaultCase != null) - scope.problemReporter().duplicateDefaultCase(this); - - // on error the last default will be the selected one ... - switchStatement.defaultCase = this; - continue; - // TODO: flag a preview error conditionally based on level? - // Predicate<BlockScope> patternSwitchAllowed = (skope) -> JavaFeature.PATTERN_MATCHING_IN_SWITCH.isSupported(skope.compilerOptions()); + } else if (e instanceof FakeDefaultLiteral + || e instanceof PatternExpression && ((PatternExpression) e).pattern instanceof AnyPattern) { + continue; // already processed } e.resolveType(scope); } @@ -262,6 +258,15 @@ private Constant[] resolveCasePrivate(BlockScope scope, TypeBinding switchExpres return Constant.NotAConstantList; } + +private void flagDuplicateDefault(BlockScope scope, SwitchStatement switchStatement) { + // remember the default case into the associated switch statement + if (switchStatement.defaultCase != null) + scope.problemReporter().duplicateDefaultCase(this); + + // on error the last default will be the selected one ... + switchStatement.defaultCase = this; +} public void collectPatternVariablesToScope(LocalVariableBinding[] variables, BlockScope scope) { if (!containsPatternVariable()) { return; 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 56102b61c9..c42adfbc4e 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 @@ -12241,4 +12241,14 @@ public void IllegalFallThroughToPattern(CaseStatement caseStatement) { caseStatement.sourceStart, caseStatement.sourceEnd); } +public void switchPatternAnyPatternCaseLabelNotAllowed(Expression element) { + if (!this.options.enablePreviewFeatures) + return; + this.handle( + IProblem.SwitchPatternAnyPatternCaseLabelNotAllowed, + NoArgument, + NoArgument, + element.sourceStart, + element.sourceEnd); +} } 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 b30cae879f..96192a3832 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 @@ -1121,6 +1121,7 @@ 1902 = The constant case label element is not compatible with switch expression type {0} 1903 = Constant case label elements and pattern case label elements cannot be present in a switch label 1904 = Illegal fall-through to a pattern case label +1905 = Any patterns not allowed as switch case label elements ### ELABORATIONS ## Access restrictions |