Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJay Arthanareeswaran2020-02-05 10:27:16 +0000
committerStephan Herrmann2020-02-16 01:17:35 +0000
commitf8f67606ae10780ec62f44189f86b4bf1a166ba8 (patch)
tree174bb6422f5fb02f560dd4712de6f5b2027d69b3
parentb82b9536f86899de9c0d6386e0843e89b677dc72 (diff)
downloadeclipse.jdt.core-f8f67606ae10780ec62f44189f86b4bf1a166ba8.tar.gz
eclipse.jdt.core-f8f67606ae10780ec62f44189f86b4bf1a166ba8.tar.xz
eclipse.jdt.core-f8f67606ae10780ec62f44189f86b4bf1a166ba8.zip
Bug 531715: [14] JEP 305: Pattern Matching for instanceof (Preview)Y20200218-0315Y20200218-0120
Flow analysis looking good Change-Id: Iec4e81d7379bdf97f18c62afc918ae46d66512d6 Signed-off-by: Jay Arthanareeswaran <jarthana@in.ibm.com> Also-by: Stephan Herrmann <stephan.herrmann@berlin.de>
-rw-r--r--org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/CompilerInvocationTests.java2
-rw-r--r--org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/PatternMatching14Test.java192
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/IProblem.java4
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AND_AND_Expression.java1
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AbstractMethodDeclaration.java9
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/BinaryExpression.java11
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Block.java9
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ConditionalExpression.java7
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Expression.java6
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ForStatement.java45
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/IfStatement.java67
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/InstanceOfExpression.java49
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/LocalDeclaration.java31
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Statement.java31
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/UnaryExpression.java10
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/WhileStatement.java39
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BlockScope.java18
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ExtraCompilerModifiers.java1
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java47
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties2
20 files changed, 234 insertions, 347 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 37cdd0c7a6..45c96d788a 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
@@ -941,6 +941,7 @@ public void test011_problem_categories() {
expectedProblemAttributes.put("ParsingErrorOnKeywordNoSuggestion", new ProblemAttributes(CategorizedProblem.CAT_SYNTAX));
expectedProblemAttributes.put("ParsingErrorReplaceTokens", new ProblemAttributes(CategorizedProblem.CAT_SYNTAX));
expectedProblemAttributes.put("ParsingErrorUnexpectedEOF", new ProblemAttributes(CategorizedProblem.CAT_SYNTAX));
+ expectedProblemAttributes.put("PatternVariableNotInScope", new ProblemAttributes(CategorizedProblem.CAT_PREVIEW_RELATED));
expectedProblemAttributes.put("PolymorphicMethodNotBelow17", new ProblemAttributes(CategorizedProblem.CAT_MEMBER));
expectedProblemAttributes.put("PossibleAccidentalBooleanAssignment", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
expectedProblemAttributes.put("PotentialHeapPollutionFromVararg", new ProblemAttributes(CategorizedProblem.CAT_UNCHECKED_RAW));
@@ -1958,6 +1959,7 @@ public void test012_compiler_problems_tuning() {
expectedProblemAttributes.put("ParsingErrorOnKeywordNoSuggestion", SKIP);
expectedProblemAttributes.put("ParsingErrorReplaceTokens", SKIP);
expectedProblemAttributes.put("ParsingErrorUnexpectedEOF", SKIP);
+ expectedProblemAttributes.put("PatternVariableNotInScope", SKIP);
expectedProblemAttributes.put("PolymorphicMethodNotBelow17", SKIP);
expectedProblemAttributes.put("PossibleAccidentalBooleanAssignment", new ProblemAttributes(JavaCore.COMPILER_PB_POSSIBLE_ACCIDENTAL_BOOLEAN_ASSIGNMENT));
expectedProblemAttributes.put("PotentialHeapPollutionFromVararg", new ProblemAttributes(JavaCore.COMPILER_PB_UNCHECKED_TYPE_OPERATION));
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/PatternMatching14Test.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/PatternMatching14Test.java
index d688bfaaf0..652efc5091 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/PatternMatching14Test.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/PatternMatching14Test.java
@@ -24,11 +24,11 @@ import junit.framework.Test;
public class PatternMatching14Test extends AbstractRegressionTest {
- private static final JavacTestOptions JAVAC_OPTIONS = new JavacTestOptions("-source 14 --enable-preview");
+ private static final JavacTestOptions JAVAC_OPTIONS = new JavacTestOptions("-source 14 --enable-preview -Xlint:-preview");
static {
// TESTS_NUMBERS = new int [] { 40 };
// TESTS_RANGE = new int[] { 1, -1 };
-// TESTS_NAMES = new String[] { "test022" };
+// TESTS_NAMES = new String[] { "test005" };
}
public static Class<?> testClass() {
@@ -89,7 +89,7 @@ public class PatternMatching14Test extends AbstractRegressionTest {
" ^^^^^^^^\n" +
"Instanceof Pattern is a preview feature and disabled by default. Use --enable-preview to enable\n" +
"----------\n",
- "",
+ /* omit one arg to directly call super method without JAVA_OPTIONS */
null,
true,
options);
@@ -240,12 +240,12 @@ public class PatternMatching14Test extends AbstractRegressionTest {
"1. ERROR in X6a.java (at line 8)\n" +
" System.out.print(i);\n" +
" ^\n" +
- "i cannot be resolved to a variable\n" +
+ "The pattern variable i is not in scope in this location\n" +
"----------\n" +
"2. ERROR in X6a.java (at line 11)\n" +
" System.out.print(i);\n" +
" ^\n" +
- "i cannot be resolved to a variable\n" +
+ "The pattern variable i is not in scope in this location\n" +
"----------\n",
"",
null,
@@ -278,12 +278,12 @@ public class PatternMatching14Test extends AbstractRegressionTest {
"1. ERROR in X6b.java (at line 8)\n" +
" System.out.print(i);\n" +
" ^\n" +
- "i cannot be resolved to a variable\n" +
+ "The pattern variable i is not in scope in this location\n" +
"----------\n" +
"2. ERROR in X6b.java (at line 11)\n" +
" System.out.print(s);\n" +
" ^\n" +
- "s cannot be resolved to a variable\n" +
+ "The pattern variable s is not in scope in this location\n" +
"----------\n",
"",
null,
@@ -313,7 +313,7 @@ public class PatternMatching14Test extends AbstractRegressionTest {
"1. ERROR in X6c.java (at line 7)\n" +
" System.out.print(i);\n" +
" ^\n" +
- "i cannot be resolved to a variable\n" +
+ "The pattern variable i is not in scope in this location\n" +
"----------\n",
"",
null,
@@ -343,7 +343,7 @@ public class PatternMatching14Test extends AbstractRegressionTest {
"1. ERROR in X6d.java (at line 7)\n" +
" System.out.print(i);\n" +
" ^\n" +
- "i cannot be resolved to a variable\n" +
+ "The pattern variable i is not in scope in this location\n" +
"----------\n",
"",
null,
@@ -373,7 +373,7 @@ public class PatternMatching14Test extends AbstractRegressionTest {
"1. ERROR in X7.java (at line 7)\n" +
" System.out.print(i);\n" +
" ^\n" +
- "i cannot be resolved to a variable\n" +
+ "The pattern variable i is not in scope in this location\n" +
"----------\n",
"X7.java:4: warning: [preview] pattern matching in instanceof is a preview feature and may be removed in a future release.\n" +
" if (obj instanceof Integer i) {\n" +
@@ -494,7 +494,7 @@ public class PatternMatching14Test extends AbstractRegressionTest {
"1. ERROR in X11.java (at line 7)\n" +
" System.out.println(s);\n" +
" ^\n" +
- "s cannot be resolved to a variable\n" +
+ "The pattern variable s is not in scope in this location\n" +
"----------\n",
"",
null,
@@ -509,11 +509,11 @@ public class PatternMatching14Test extends AbstractRegressionTest {
"@SuppressWarnings(\"preview\")\n" +
"public class X12 {\n" +
" public static void foo(Object b) {\n" +
- " Object c = null;\n" +
+ " Object c = new Object();\n" +
" if (b != c) {\n" +
" if (b == null && (b instanceof String s)) {\n" +
" System.out.println(\"s:\" + s);\n" +
- " } else { " +
+ " } else {\n" +
" System.out.println(\"b:\" + b);\n" +
" }\n" +
" s = null;\n" +
@@ -526,10 +526,10 @@ public class PatternMatching14Test extends AbstractRegressionTest {
"}\n",
},
"----------\n" +
- "1. ERROR in X12.java (at line 10)\n" +
+ "1. ERROR in X12.java (at line 11)\n" +
" s = null;\n" +
" ^\n" +
- "s cannot be resolved to a variable\n" +
+ "The pattern variable s is not in scope in this location\n" +
"----------\n",
"",
null,
@@ -560,10 +560,15 @@ public class PatternMatching14Test extends AbstractRegressionTest {
"}\n",
},
"----------\n" +
- "1. ERROR in X13.java (at line 9)\n" +
+ "1. WARNING in X13.java (at line 7)\n" +
+ " System.out.println(\"s:\" + s);\n" +
+ " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
+ "Dead code\n" +
+ "----------\n" +
+ "2. ERROR in X13.java (at line 9)\n" +
" System.out.println(s);\n" +
" ^\n" +
- "s cannot be resolved to a variable\n" +
+ "The pattern variable s is not in scope in this location\n" +
"----------\n",
"",
null,
@@ -593,7 +598,7 @@ public class PatternMatching14Test extends AbstractRegressionTest {
"1. ERROR in X14.java (at line 5)\n" +
" System.out.print(\"then:\" + s);\n" +
" ^\n" +
- "s cannot be resolved to a variable\n" +
+ "The pattern variable s is not in scope in this location\n" +
"----------\n",
"",
null,
@@ -604,9 +609,9 @@ public class PatternMatching14Test extends AbstractRegressionTest {
Map<String, String> options = getCompilerOptions(true);
runNegativeTest(
new String[] {
- "X14.java",
+ "X14a.java",
"@SuppressWarnings(\"preview\")\n" +
- "public class X14 {\n" +
+ "public class X14a {\n" +
" public static void foo(Object o) {\n" +
" if (!(o instanceof String s)) {\n" +
" System.out.print(\"then:\" + s);\n" +
@@ -620,10 +625,10 @@ public class PatternMatching14Test extends AbstractRegressionTest {
"}\n",
},
"----------\n" +
- "1. ERROR in X14.java (at line 5)\n" +
+ "1. ERROR in X14a.java (at line 5)\n" +
" System.out.print(\"then:\" + s);\n" +
" ^\n" +
- "s cannot be resolved to a variable\n" +
+ "The pattern variable s is not in scope in this location\n" +
"----------\n",
"",
null,
@@ -634,9 +639,9 @@ public class PatternMatching14Test extends AbstractRegressionTest {
Map<String, String> options = getCompilerOptions(true);
runNegativeTest(
new String[] {
- "X14.java",
+ "X14b.java",
"@SuppressWarnings(\"preview\")\n" +
- "public class X14 {\n" +
+ "public class X14b {\n" +
" public static void foo(Object o) {\n" +
" if (!!(o instanceof String s)) {\n" +
" System.out.print(\"then:\" + s);\n" +
@@ -650,10 +655,10 @@ public class PatternMatching14Test extends AbstractRegressionTest {
"}\n",
},
"----------\n" +
- "1. ERROR in X14.java (at line 7)\n" +
+ "1. ERROR in X14b.java (at line 7)\n" +
" System.out.print(\"else:\" + s);\n" +
" ^\n" +
- "s cannot be resolved to a variable\n" +
+ "The pattern variable s is not in scope in this location\n" +
"----------\n",
"",
null,
@@ -664,9 +669,9 @@ public class PatternMatching14Test extends AbstractRegressionTest {
Map<String, String> options = getCompilerOptions(true);
runNegativeTest(
new String[] {
- "X14.java",
+ "X14c.java",
"@SuppressWarnings(\"preview\")\n" +
- "public class X14 {\n" +
+ "public class X14c {\n" +
" public static void foo(Object o) {\n" +
" if (o == null) {\n" +
" System.out.print(\"null\");\n" +
@@ -680,10 +685,10 @@ public class PatternMatching14Test extends AbstractRegressionTest {
"}\n",
},
"----------\n" +
- "1. ERROR in X14.java (at line 7)\n" +
+ "1. ERROR in X14c.java (at line 7)\n" +
" System.out.print(\"else:\" + s);\n" +
" ^\n" +
- "s cannot be resolved to a variable\n" +
+ "The pattern variable s is not in scope in this location\n" +
"----------\n",
"",
null,
@@ -694,9 +699,9 @@ public class PatternMatching14Test extends AbstractRegressionTest {
Map<String, String> options = getCompilerOptions(true);
runConformTest(
new String[] {
- "X14.java",
+ "X14d.java",
"@SuppressWarnings(\"preview\")\n" +
- "public class X14 {\n" +
+ "public class X14d {\n" +
" public static void foo(Object o) {\n" +
" if (o == null) {\n" +
" System.out.print(\"null\");\n" +
@@ -813,7 +818,7 @@ public class PatternMatching14Test extends AbstractRegressionTest {
"1. ERROR in X15b.java (at line 9)\n" +
" System.out.print(s);\n" +
" ^\n" +
- "s cannot be resolved to a variable\n" +
+ "The pattern variable s is not in scope in this location\n" +
"----------\n",
"",
null,
@@ -859,7 +864,7 @@ public class PatternMatching14Test extends AbstractRegressionTest {
"1. ERROR in X17.java (at line 5)\n" +
" System.out.print(s[0]);\n" +
" ^\n" +
- "s cannot be resolved to a variable\n" +
+ "The pattern variable s is not in scope in this location\n" +
"----------\n",
"",
null,
@@ -914,6 +919,35 @@ public class PatternMatching14Test extends AbstractRegressionTest {
"false,true",
options);
}
+ /* Test that we still detect duplicate pattern variable declarations
+ */
+ public void test019b() {
+ Map<String, String> options = getCompilerOptions(true);
+ runNegativeTest(
+ new String[] {
+ "X19b.java",
+ "@SuppressWarnings(\"preview\")\n" +
+ "public class X19b {\n" +
+ " public static void main(String[] obj) {\n" +
+ " boolean a = true;\n" +
+ " if (obj instanceof String[] s && s.length == 0) {\n" +
+ " boolean b = (obj instanceof String[] s && s.length == 0);\n" +
+ " System.out.print(b);\n" +
+ " }\n" +
+ " }\n" +
+ "}\n",
+ },
+ "----------\n" +
+ "1. ERROR in X19b.java (at line 6)\n" +
+ " boolean b = (obj instanceof String[] s && s.length == 0);\n" +
+ " ^\n" +
+ "Duplicate local variable s\n" +
+ "----------\n",
+ "",
+ null,
+ true,
+ options);
+ }
/* Test that we allow consequent pattern expressions in the same statement
*/
public void test020() {
@@ -952,12 +986,12 @@ public class PatternMatching14Test extends AbstractRegressionTest {
"1. ERROR in X21.java (at line 5)\n" +
" System.out.print(s);\n" +
" ^\n" +
- "s cannot be resolved to a variable\n" +
+ "The pattern variable s is not in scope in this location\n" +
"----------\n" +
"2. ERROR in X21.java (at line 6)\n" +
" System.out.print(s2);\n" +
" ^^\n" +
- "s2 cannot be resolved to a variable\n" +
+ "The pattern variable s2 is not in scope in this location\n" +
"----------\n",
"",
null,
@@ -1011,12 +1045,12 @@ public class PatternMatching14Test extends AbstractRegressionTest {
"1. ERROR in X23.java (at line 7)\n" +
" while (!(o instanceof String s) && s.length() > 0) {\n" +
" ^\n" +
- "s cannot be resolved\n" +
+ "The pattern variable s is not in scope in this location\n" +
"----------\n" +
"2. ERROR in X23.java (at line 8)\n" +
" System.out.println(s);\n" +
" ^\n" +
- "s cannot be resolved to a variable\n" +
+ "The pattern variable s is not in scope in this location\n" +
"----------\n",
"",
null,
@@ -1029,9 +1063,9 @@ public class PatternMatching14Test extends AbstractRegressionTest {
Map<String, String> options = getCompilerOptions(true);
runNegativeTest(
new String[] {
- "X23.java",
+ "X23a.java",
"@SuppressWarnings(\"preview\")\n" +
- "public class X23 {\n" +
+ "public class X23a {\n" +
" public static void main(String[] o) {\n" +
" foo(\"one\");\n" +
" }\n" +
@@ -1044,15 +1078,15 @@ public class PatternMatching14Test extends AbstractRegressionTest {
"}\n",
},
"----------\n" +
- "1. ERROR in X23.java (at line 7)\n" +
+ "1. ERROR in X23a.java (at line 7)\n" +
" while (!(o instanceof String s) && s.length() > 0) {\n" +
" ^\n" +
- "s cannot be resolved\n" +
+ "The pattern variable s is not in scope in this location\n" +
"----------\n" +
- "2. ERROR in X23.java (at line 8)\n" +
+ "2. ERROR in X23a.java (at line 8)\n" +
" System.out.println(s);\n" +
" ^\n" +
- "s cannot be resolved to a variable\n" +
+ "The pattern variable s is not in scope in this location\n" +
"----------\n",
"",
null,
@@ -1080,8 +1114,9 @@ public class PatternMatching14Test extends AbstractRegressionTest {
"one",
options);
}
- /* Test that we reject two patter variables with same name in the same
- * equals expression
+ /*
+ * It's not a problem to define the same var in two operands of a binary expression,
+ * but then it is not in scope below.
*/
public void test025() {
Map<String, String> options = getCompilerOptions(true);
@@ -1101,18 +1136,19 @@ public class PatternMatching14Test extends AbstractRegressionTest {
"}\n",
},
"----------\n" +
- "1. ERROR in X25.java (at line 7)\n" +
- " if ((o instanceof String s) != p instanceof String s) {\n" +
- " ^\n" +
- "Duplicate local variable s\n" +
+ "1. ERROR in X25.java (at line 8)\n" +
+ " System.out.print(\"s:\" + s);\n" +
+ " ^\n" +
+ "The pattern variable s is not in scope in this location\n" +
"----------\n",
"",
null,
true,
options);
}
- /* Test that we reject two patter variables with same name in the same
- * equals expression
+ /*
+ * It's not a problem to define the same var in two operands of a binary expression,
+ * but then it is not in scope below.
*/
public void test026() {
Map<String, String> options = getCompilerOptions(true);
@@ -1132,10 +1168,10 @@ public class PatternMatching14Test extends AbstractRegressionTest {
"}\n",
},
"----------\n" +
- "1. ERROR in X26.java (at line 7)\n" +
- " if ((o instanceof String s) == p instanceof String s) {\n" +
- " ^\n" +
- "Duplicate local variable s\n" +
+ "1. ERROR in X26.java (at line 8)\n" +
+ " System.out.print(\"s:\" + s);\n" +
+ " ^\n" +
+ "The pattern variable s is not in scope in this location\n" +
"----------\n",
"",
null,
@@ -1200,12 +1236,11 @@ public class PatternMatching14Test extends AbstractRegressionTest {
getCompilerOptions(true));
}
/*
- * Test that pattern variables are accepted in initialization of
- * a for statement
- * TODO: Javac rejects this
+ * Test that pattern variables are accepted in initialization of a for statement,
+ * but unavailable in the body if uncertain which if instanceof check was true
*/
public void test030() {
- runConformTest(
+ runNegativeTest(
new String[] {
"X30.java",
"@SuppressWarnings(\"preview\")\n" +
@@ -1220,7 +1255,15 @@ public class PatternMatching14Test extends AbstractRegressionTest {
" }\n" +
"}\n",
},
- "one",
+ "----------\n" +
+ "1. ERROR in X30.java (at line 8)\n" +
+ " System.out.print(s.charAt(i));\n" +
+ " ^\n" +
+ "The pattern variable s is not in scope in this location\n" +
+ "----------\n",
+ "",
+ null,
+ true,
getCompilerOptions(true));
}
public void test031() {
@@ -1243,17 +1286,17 @@ public class PatternMatching14Test extends AbstractRegressionTest {
"1. ERROR in X31.java (at line 7)\n" +
" for(int i = 0; !(obj instanceof String[] s) && s.length > 0 && i < s.length; i++) {\n" +
" ^\n" +
- "s cannot be resolved to a variable\n" +
+ "The pattern variable s is not in scope in this location\n" +
"----------\n" +
"2. ERROR in X31.java (at line 7)\n" +
" for(int i = 0; !(obj instanceof String[] s) && s.length > 0 && i < s.length; i++) {\n" +
" ^\n" +
- "s cannot be resolved to a variable\n" +
+ "The pattern variable s is not in scope in this location\n" +
"----------\n" +
"3. ERROR in X31.java (at line 8)\n" +
" System.out.println(s[i]);\n" +
" ^\n" +
- "s cannot be resolved to a variable\n" +
+ "The pattern variable s is not in scope in this location\n" +
"----------\n",
"",
null,
@@ -1285,11 +1328,8 @@ public class PatternMatching14Test extends AbstractRegressionTest {
"one",
getCompilerOptions(true));
}
- /*
- * FAILURE: Javac rejects this code, but we accept.
- */
public void test033() {
- runConformTest(
+ runNegativeTest(
new String[] {
"X33.java",
"@SuppressWarnings(\"preview\")\n" +
@@ -1311,7 +1351,15 @@ public class PatternMatching14Test extends AbstractRegressionTest {
" }\n" +
"}\n",
},
- "ne",
+ "----------\n" +
+ "1. ERROR in X33.java (at line 12)\n" +
+ " res = s.substring(1);\n" +
+ " ^\n" +
+ "The pattern variable s is not in scope in this location\n" +
+ "----------\n",
+ "",
+ null,
+ true,
getCompilerOptions(true));
}
public void test034() {
@@ -1377,12 +1425,12 @@ public class PatternMatching14Test extends AbstractRegressionTest {
"1. ERROR in X35.java (at line 11)\n" +
" yield s;\n" +
" ^\n" +
- "s cannot be resolved to a variable\n" +
+ "The pattern variable s is not in scope in this location\n" +
"----------\n" +
"2. ERROR in X35.java (at line 14)\n" +
" yield s;\n" +
" ^\n" +
- "s cannot be resolved to a variable\n" +
+ "The pattern variable s is not in scope in this location\n" +
"----------\n",
"",
null,
@@ -1435,6 +1483,7 @@ public class PatternMatching14Test extends AbstractRegressionTest {
" ^^^^\n" +
"The type of the expression must be an array type but it resolved to String\n" +
"----------\n",
+ "",
null,
true,
getCompilerOptions(true));
@@ -1462,6 +1511,7 @@ public class PatternMatching14Test extends AbstractRegressionTest {
" ^\n" +
"s cannot be resolved to a variable\n" +
"----------\n",
+ "",
null,
true,
getCompilerOptions(true));
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 1a89cf7759..ddcff78c6a 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
@@ -2315,5 +2315,9 @@ void setSourceStart(int sourceStart);
* @noreference preview feature error */
int RecordIllegalVararg= PreviewRelated + 1754;
/* records - end */
+ /* instanceof pattern: */
+ /** @since 3.21 BETA_JAVA14
+ * @noreference preview feature error */
+ int PatternVariableNotInScope = PreviewRelated + 1760;
/* Java14 errors - end */
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AND_AND_Expression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AND_AND_Expression.java
index 2bd0f31c60..66a6adb113 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AND_AND_Expression.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AND_AND_Expression.java
@@ -282,7 +282,6 @@ public class AND_AND_Expression extends BinaryExpression {
*/
@Override
public TypeBinding resolveType(BlockScope scope) {
- resolvePatternVariable(scope, true);
TypeBinding result = super.resolveType(scope);
// check whether comparing identical expressions
Binding leftDirect = Expression.getDirectBinding(this.left);
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AbstractMethodDeclaration.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AbstractMethodDeclaration.java
index 8f2086af01..33893e8756 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AbstractMethodDeclaration.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AbstractMethodDeclaration.java
@@ -346,8 +346,6 @@ public abstract class AbstractMethodDeclaration
if (this.statements != null) {
for (Statement stmt : this.statements) {
stmt.generateCode(this.scope, codeStream);
- if ((stmt.bits & ASTNode.HasInstancePatternExpression) != 0)
- stmt.exitPatternVariableScope(codeStream);
}
}
// if a problem got reported during code gen, then trigger problem method creation
@@ -650,12 +648,7 @@ public abstract class AbstractMethodDeclaration
if (this.statements != null) {
for (int i = 0, length = this.statements.length; i < length; i++) {
Statement stmt = this.statements[i];
- stmt.lookForPatternVariables(this.scope);
- if ((stmt.bits & ASTNode.HasInstancePatternExpression) == 0) {
- stmt.resolve(this.scope);
- } else {
- stmt.resolve(stmt.patternScope);
- }
+ stmt.resolve(this.scope);
}
} else if ((this.bits & UndocumentedEmptyBlock) != 0) {
if (!this.isConstructor() || this.arguments != null) { // https://bugs.eclipse.org/bugs/show_bug.cgi?id=319626
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/BinaryExpression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/BinaryExpression.java
index 86033e1cf7..915b205026 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/BinaryExpression.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/BinaryExpression.java
@@ -1812,16 +1812,6 @@ public void initializePatternVariables(BlockScope scope, CodeStream codeStream)
this.right.initializePatternVariables(scope, codeStream);
}
@Override
-public void resolvePatternVariable(BlockScope scope, boolean trueFalse) {
- this.left.resolvePatternVariable(scope, trueFalse);
- this.right.resolvePatternVariable(scope, trueFalse);
-}
-@Override
-public void generatePatternVariable(BlockScope currentScope, CodeStream codeStream) {
- this.left.generatePatternVariable(currentScope, codeStream);
- this.right.generatePatternVariable(currentScope, codeStream);
-}
-@Override
public TypeBinding resolveType(BlockScope scope) {
// keep implementation in sync with CombinedBinaryExpression#resolveType
// and nonRecursiveResolveTypeUpwards
@@ -1929,6 +1919,7 @@ public TypeBinding resolveType(BlockScope scope) {
}
// compute the constant when valid
computeConstant(scope, leftTypeID, rightTypeID);
+ this.bits |= (this.left.bits | this.right.bits) & ASTNode.HasInstancePatternExpression;
return this.resolvedType;
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Block.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Block.java
index ab8efa0069..de2a55f30f 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Block.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Block.java
@@ -90,8 +90,6 @@ public void generateCode(BlockScope currentScope, CodeStream codeStream) {
if (this.statements != null) {
for (Statement stmt : this.statements) {
stmt.generateCode(this.scope, codeStream);
- if ((stmt.bits & ASTNode.HasInstancePatternExpression) != 0)
- stmt.exitPatternVariableScope(codeStream);
}
} // for local variable debug attributes
if (this.scope != currentScope) { // was really associated with its own scope
@@ -134,12 +132,7 @@ public void resolve(BlockScope upperScope) {
: new BlockScope(upperScope, this.explicitDeclarations);
for (int i = 0, length = this.statements.length; i < length; i++) {
final Statement stmt = this.statements[i];
- stmt.lookForPatternVariables(this.scope);
- if ((stmt.bits & ASTNode.HasInstancePatternExpression) == 0) {
- stmt.resolve(this.scope);
- } else {
- stmt.resolve(stmt.patternScope);
- }
+ stmt.resolve(this.scope);
}
}
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ConditionalExpression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ConditionalExpression.java
index 12fbf324ea..0d6abb2775 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ConditionalExpression.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ConditionalExpression.java
@@ -451,9 +451,9 @@ public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext,
@Override
public void initializePatternVariables(BlockScope scope, CodeStream codeStream) {
- this.condition.initializePatternVariables(this.patternScope, codeStream);
- this.valueIfTrue.initializePatternVariables(this.patternScope, codeStream);
- this.valueIfFalse.initializePatternVariables(this.patternScope, codeStream);
+ this.condition.initializePatternVariables(scope, codeStream);
+ this.valueIfTrue.initializePatternVariables(scope, codeStream);
+ this.valueIfFalse.initializePatternVariables(scope, codeStream);
}
@Override
@@ -475,7 +475,6 @@ public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext,
if (this.constant != Constant.NotAConstant) {
this.constant = Constant.NotAConstant;
- this.condition.resolvePatternVariable(scope, true);
TypeBinding conditionType = this.condition.resolveTypeExpecting(scope, TypeBinding.BOOLEAN);
this.condition.computeConversion(scope, TypeBinding.BOOLEAN, conditionType);
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Expression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Expression.java
index a6706b9286..6e572a300f 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Expression.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Expression.java
@@ -778,15 +778,9 @@ public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean
throw new ShouldNotImplement(Messages.ast_missingCode);
}
}
-public void resolvePatternVariable(BlockScope scope, boolean trueFalse) {
- // Nothing by default
-}
public void initializePatternVariables(BlockScope scope, CodeStream codeStream) {
// Nothing by default
}
-public void generatePatternVariable(BlockScope currentScope, CodeStream codeStream) {
- // Nothing by default
-}
/**
* Default generation of a boolean value
* @param currentScope
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ForStatement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ForStatement.java
index 56a5c6aec0..298e92f5f6 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ForStatement.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ForStatement.java
@@ -265,7 +265,7 @@ public class ForStatement extends Statement {
this.initializations[i].generateCode(this.scope, codeStream);
}
}
- if (this.condition != null && (this.bits & ASTNode.HasInstancePatternExpression) != 0) {
+ if (this.condition != null && (this.condition.bits & ASTNode.HasInstancePatternExpression) != 0) {
this.condition.initializePatternVariables(currentScope, codeStream);
}
Constant cst = this.condition == null ? null : this.condition.optimizedBooleanConstant();
@@ -402,60 +402,21 @@ public class ForStatement extends Statement {
}
@Override
- public void lookForPatternVariables(BlockScope outerScope) {
- if (this.condition == null)
- return;
- this.condition.traverse(new ASTVisitor() {
- @Override
- public boolean visit(
- InstanceOfExpression instanceOfExpression,
- BlockScope sc) {
- if (instanceOfExpression.elementVariable != null) {
- ForStatement.this.bits |= ASTNode.HasInstancePatternExpression;
- }
- return false; // mission finished, exit
- }
- }, outerScope);
- this.patternScope = new BlockScope(outerScope);
- }
-
- @Override
public void resolve(BlockScope upperScope) {
- boolean hasPatternVariable = (this.bits & ASTNode.HasInstancePatternExpression) != 0;
- if (hasPatternVariable)
- upperScope = (BlockScope) upperScope.parent;
// use the scope that will hold the init declarations
this.scope = (this.bits & ASTNode.NeededScope) != 0 ? new BlockScope(upperScope) : upperScope;
if (this.initializations != null)
for (int i = 0, length = this.initializations.length; i < length; i++)
this.initializations[i].resolve(this.scope);
if (this.condition != null) {
- if (hasPatternVariable) {
- this.scope = this.patternScope = new BlockScope(this.scope);
- this.condition.resolvePatternVariable(this.scope, true);
- }
- }
-
- if (this.condition != null) {
TypeBinding type = this.condition.resolveTypeExpecting(this.scope, TypeBinding.BOOLEAN);
this.condition.computeConversion(this.scope, type, type);
}
if (this.increments != null)
for (int i = 0, length = this.increments.length; i < length; i++)
this.increments[i].resolve(this.scope);
- if (this.action != null) {
- BlockScope falseScope = null;
- BlockScope trueScope = null;
- if (hasPatternVariable) {
- trueScope = this.patternScope;
- if (this.action.doesNotCompleteNormally()) {
- falseScope = upperScope;
- }
- }
- this.action.resolve(hasPatternVariable ? trueScope : this.scope);
- if (falseScope != null)
- this.condition.resolvePatternVariable(falseScope, false);
- }
+ if (this.action != null)
+ this.action.resolve(this.scope);
}
@Override
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/IfStatement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/IfStatement.java
index 11aae31732..a75062fbef 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/IfStatement.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/IfStatement.java
@@ -202,10 +202,6 @@ public void generateCode(BlockScope currentScope, CodeStream codeStream) {
}
// generate then statement
this.thenStatement.generateCode(currentScope, codeStream);
- boolean hasPatternVariable = (this.bits & ASTNode.HasInstancePatternExpression) != 0;
- if (hasPatternVariable) {
- this.exitPatternVariableScope(codeStream);
- }
// jump around the else statement
if (hasElsePart) {
if ((this.bits & ASTNode.ThenExit) == 0) {
@@ -279,62 +275,13 @@ public StringBuffer printStatement(int indent, StringBuffer output) {
return output;
}
@Override
-public void lookForPatternVariables(BlockScope scope) {
- this.condition.traverse(new ASTVisitor() {
- @Override
- public boolean visit(
- InstanceOfExpression instanceOfExpression,
- BlockScope sc) {
- if (instanceOfExpression.elementVariable != null) {
- IfStatement.this.bits |= ASTNode.HasInstancePatternExpression;
- IfStatement.this.patternScope = new BlockScope(scope);
- }
- return false; // mission finished, exit
- }
- }, scope);
-}
-@Override
-public void resolve(BlockScope outerScope) {
- boolean hasPatternVariable = (this.bits & ASTNode.HasInstancePatternExpression) != 0;
- BlockScope trueScope = null;
- if (hasPatternVariable) {
- trueScope = this.patternScope;
- //new BlockScope((BlockScope) outerScope.parent);
- this.condition.resolvePatternVariable(trueScope, true);
- }
- TypeBinding type = this.condition.resolveTypeExpecting(hasPatternVariable ? trueScope : outerScope, TypeBinding.BOOLEAN);
- this.condition.computeConversion(hasPatternVariable ? trueScope : outerScope, type, type);
- if (this.thenStatement != null) {
- this.thenStatement.resolve(hasPatternVariable ? trueScope : outerScope);
- }
- if (hasPatternVariable) {
- BlockScope falseScope = null;
- if (this.thenStatement.doesNotCompleteNormally()) {
- falseScope = (BlockScope) outerScope.parent;
- } else {
- falseScope = new BlockScope((BlockScope) outerScope.parent);
- }
- this.condition.resolvePatternVariable(falseScope, false);
- outerScope = falseScope;
- }
- if (this.elseStatement != null) {
- this.elseStatement.traverse(new ASTVisitor() {
- @Override
- public boolean visit(
- InstanceOfExpression instanceOfExpression,
- BlockScope sc) {
- if (instanceOfExpression.elementVariable != null) {
- IfStatement.this.elseStatement.bits |= ASTNode.HasInstancePatternExpression;
- }
- return false;
- }
- }, outerScope);
- if ((this.elseStatement.bits & ASTNode.HasInstancePatternExpression) != 0) {
- this.elseStatement.patternScope = new BlockScope(outerScope);
- this.elseStatement.resolve(this.elseStatement.patternScope);
- } else
- this.elseStatement.resolve(outerScope);
- }
+public void resolve(BlockScope scope) {
+ TypeBinding type = this.condition.resolveTypeExpecting(scope, TypeBinding.BOOLEAN);
+ this.condition.computeConversion(scope, type, type);
+ if (this.thenStatement != null)
+ this.thenStatement.resolve(scope);
+ if (this.elseStatement != null)
+ this.elseStatement.resolve(scope);
}
@Override
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/InstanceOfExpression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/InstanceOfExpression.java
index 559283e261..6b827df116 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/InstanceOfExpression.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/InstanceOfExpression.java
@@ -63,9 +63,6 @@ public InstanceOfExpression(Expression expression, LocalDeclaration local) {
@Override
public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
- if (this.elementVariable != null) {
- flowInfo.markAsDefinitelyAssigned(this.elementVariable.binding);
- }
LocalVariableBinding local = this.expression.localVariableBinding();
if (local != null && (local.type.tagBits & TagBits.IsBaseType) == 0) {
flowInfo = this.expression.analyseCode(currentScope, flowContext, flowInfo).
@@ -74,6 +71,12 @@ public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, Fl
initsWhenTrue.markAsComparedEqualToNonNull(local);
flowContext.recordUsingNullReference(currentScope, local,
this.expression, FlowContext.CAN_ONLY_NULL | FlowContext.IN_INSTANCEOF, flowInfo);
+ if (this.elementVariable != null) {
+ if (this.elementVariable.duplicateCheckObligation != null) {
+ this.elementVariable.duplicateCheckObligation.accept(flowInfo);
+ }
+ initsWhenTrue.markAsDefinitelyAssigned(this.elementVariable.binding);
+ }
// no impact upon enclosing try context
return FlowInfo.conditional(initsWhenTrue, flowInfo.copy());
}
@@ -86,28 +89,6 @@ public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, Fl
return this.expression.analyseCode(currentScope, flowContext, flowInfo).
unconditionalInits();
}
-@Override
-public void generateOptimizedBoolean(BlockScope currentScope, CodeStream codeStream, BranchLabel trueLabel, BranchLabel falseLabel, boolean valueRequired) {
- super.generateOptimizedBoolean(currentScope, codeStream, trueLabel, falseLabel, valueRequired);
- generatePatternVariable(currentScope, codeStream);
-// if (this.elementVariable != null) {
-// int position = codeStream.position;
-// codeStream.load(this.expression.localVariableBinding());
-// codeStream.checkcast(this.type, this.type.resolvedType, position);
-// codeStream.store(this.elementVariable.binding, false);
-// codeStream.recordPositionsFrom(position, this.sourceEnd);
-// }
-}
-@Override
-public void generatePatternVariable(BlockScope currentScope, CodeStream codeStream) {
-// if (this.elementVariable != null) {
-// int position = codeStream.position;
-// codeStream.load(this.expression.localVariableBinding());
-// codeStream.checkcast(this.type, this.type.resolvedType, position);
-// codeStream.store(this.elementVariable.binding, false);
-// codeStream.recordPositionsFrom(position, this.sourceEnd);
-// }
-}
/**
* Code generation for instanceOfExpression
*
@@ -161,33 +142,25 @@ public void initializePatternVariables(BlockScope currentScope, CodeStream codeS
this.isInitialized = true;
codeStream.aconst_null();
codeStream.store(this.elementVariable.binding, false);
-// int position = codeStream.position;
-// codeStream.addVisibleLocalVariable(this.elementVariable.binding);
-// this.elementVariable.binding.recordInitializationStartPC(position);
}
int position = codeStream.position;
codeStream.addVisibleLocalVariable(this.elementVariable.binding);
this.elementVariable.binding.recordInitializationStartPC(position);
}
- //generatePatternVariable(currentScope, codeStream);
}
-@Override
-public void resolvePatternVariable(BlockScope scope, boolean inScope) {
- if (!inScope) return;
+public void resolvePatternVariable(BlockScope scope) {
if (this.elementVariable != null && this.elementVariable.binding == null) {
- this.patternScope = scope;
- this.elementVariable.resolve(scope);
+ this.elementVariable.resolve(scope, true);
+ this.elementVariable.binding.modifiers |= ExtraCompilerModifiers.AccPatterVariable;
// Why cant this be done in the constructor?
this.type = this.elementVariable.type;
+ this.bits |= ASTNode.HasInstancePatternExpression;
}
}
@Override
public TypeBinding resolveType(BlockScope scope) {
-// resolvePatternVariable(scope, scope);
this.constant = Constant.NotAConstant;
- if (this.type == null && this.elementVariable != null) {
- this.type = this.elementVariable.type;
- }
+ resolvePatternVariable(scope);
TypeBinding checkedType = this.type.resolveType(scope, true /* check bounds*/);
if (this.expression instanceof CastExpression) {
((CastExpression) this.expression).setInstanceofType(checkedType); // for cast expression we need to know instanceof type to not tag unnecessary when needed
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/LocalDeclaration.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/LocalDeclaration.java
index 57f81073df..e7f562d4e0 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/LocalDeclaration.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/LocalDeclaration.java
@@ -45,6 +45,7 @@ import static org.eclipse.jdt.internal.compiler.ast.ExpressionContext.VANILLA_CO
import java.util.HashSet;
import java.util.List;
import java.util.Set;
+import java.util.function.Consumer;
import org.eclipse.jdt.internal.compiler.ASTVisitor;
import org.eclipse.jdt.internal.compiler.impl.*;
@@ -60,6 +61,12 @@ public class LocalDeclaration extends AbstractVariableDeclaration {
public LocalVariableBinding binding;
+ /**
+ * For pattern variable, resolve() may store here an obligation to be checked when we have
+ * a flow info that tells us whether a potential duplicates is in fact in scope.
+ */
+ Consumer<FlowInfo> duplicateCheckObligation;
+
public LocalDeclaration(
char[] name,
int sourceStart,
@@ -257,7 +264,9 @@ public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, Fl
@Override
public void resolve(BlockScope scope) {
-
+ resolve(scope, false);
+ }
+ public void resolve(BlockScope scope, boolean isPatternVariable) {
// prescan NNBD
handleNonNullByDefault(scope, this.annotations, this);
@@ -296,13 +305,23 @@ public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, Fl
Binding existingVariable = scope.getBinding(this.name, Binding.VARIABLE, this, false /*do not resolve hidden field*/);
if (existingVariable != null && existingVariable.isValidBinding()){
- boolean localExists = existingVariable instanceof LocalVariableBinding;
- if (localExists && (this.bits & ASTNode.ShadowsOuterLocal) != 0 && scope.isLambdaSubscope() && this.hiddenVariableDepth == 0) {
+ boolean localExists = existingVariable instanceof LocalVariableBinding;
+ if (localExists && isPatternVariable
+ && (((LocalVariableBinding) existingVariable).modifiers & ExtraCompilerModifiers.AccPatterVariable) != 0)
+ {
+ this.duplicateCheckObligation = (flowInfo) -> {
+ if (flowInfo.isDefinitelyAssigned((LocalVariableBinding) existingVariable)) {
+ scope.problemReporter().redefineLocal(this);
+ }
+ };
+ } else {
+ if (localExists && (this.bits & ASTNode.ShadowsOuterLocal) != 0 && scope.isLambdaSubscope() && this.hiddenVariableDepth == 0) {
scope.problemReporter().lambdaRedeclaresLocal(this);
- } else if (localExists && this.hiddenVariableDepth == 0) {
+ } else if (localExists && this.hiddenVariableDepth == 0) {
scope.problemReporter().redefineLocal(this);
- } else {
- scope.problemReporter().localVariableHiding(this, existingVariable, false);
+ } else {
+ scope.problemReporter().localVariableHiding(this, existingVariable, false);
+ }
}
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Statement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Statement.java
index 1cf1230ac7..9d386d58a5 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Statement.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Statement.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2020 IBM Corporation and others.
+ * Copyright (c) 2000, 2019 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
@@ -8,10 +8,6 @@
*
* SPDX-License-Identifier: EPL-2.0
*
- * This is an implementation of an early-draft specification developed under the Java
- * Community Process (JCP) and is made available for testing and evaluation purposes
- * only. The code is not compatible with any specification of the JCP.
- *
* Contributors:
* IBM Corporation - initial API and implementation
* Stephan Herrmann - Contributions for
@@ -107,7 +103,6 @@ public boolean doesNotCompleteNormally() {
public boolean completesByContinue() {
return false;
}
- public BlockScope patternScope;
public static final int NOT_COMPLAINED = 0;
public static final int COMPLAINED_FAKE_REACHABLE = 1;
@@ -427,15 +422,6 @@ public void generateArguments(MethodBinding binding, Expression[] arguments, Blo
}
public abstract void generateCode(BlockScope currentScope, CodeStream codeStream);
-public void exitPatternVariableScope(CodeStream stream) {
- if (this.patternScope != null && (this.bits & ASTNode.HasInstancePatternExpression) != 0) {
- for (Scope s : this.patternScope.subscopes) {
- if (s == null) continue;
- stream.exitUserScope((BlockScope) s);
- }
- stream.exitUserScope(this.patternScope);
- }
-}
public boolean isBoxingCompatible(TypeBinding expressionType, TypeBinding targetType, Expression expression, Scope scope) {
if (scope.isBoxingCompatibleWith(expressionType, targetType))
@@ -477,21 +463,6 @@ public abstract StringBuffer printStatement(int indent, StringBuffer output);
public abstract void resolve(BlockScope scope);
-public void lookForPatternVariables(BlockScope scope) {
- this.traverse(new ASTVisitor() {
- @Override
- public boolean visit(
- InstanceOfExpression instanceOfExpression,
- BlockScope sc) {
- if (instanceOfExpression.elementVariable != null) {
- Statement.this.bits |= ASTNode.HasInstancePatternExpression;
- }
- return false; // mission finished, exit
- }
- }, scope);
- if ((this.bits & ASTNode.HasInstancePatternExpression) != 0)
- this.patternScope = new BlockScope(scope);
-}
/**
* Returns case constant associated to this statement (NotAConstant if none)
* parameter statement has to be either a SwitchStatement or a SwitchExpression
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/UnaryExpression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/UnaryExpression.java
index c1d0368878..b25157f635 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/UnaryExpression.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/UnaryExpression.java
@@ -224,16 +224,6 @@ public FlowInfo analyseCode(
}
@Override
- public void resolvePatternVariable(BlockScope scope, boolean trueFalse) {
- if ((((this.bits & OperatorMASK) >> OperatorSHIFT) == NOT)) {
- this.expression.resolvePatternVariable(scope, !trueFalse);
- }
- }
- @Override
- public void generatePatternVariable(BlockScope currentScope, CodeStream codeStream) {
- this.expression.generatePatternVariable(currentScope, codeStream);
- }
- @Override
public TypeBinding resolveType(BlockScope scope) {
boolean expressionIsCast;
if ((expressionIsCast = this.expression instanceof CastExpression) == true) this.expression.bits |= DisableUnnecessaryCastCheck; // will check later on
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/WhileStatement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/WhileStatement.java
index c0e5790e5c..09ef32e52e 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/WhileStatement.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/WhileStatement.java
@@ -194,6 +194,7 @@ public class WhileStatement extends Statement {
if ((this.bits & IsReachable) == 0) {
return;
}
+ // TODO: Do this at the appropriate point only
this.condition.initializePatternVariables(currentScope, codeStream);
int pc = codeStream.position;
Constant cst = this.condition.optimizedBooleanConstant();
@@ -236,7 +237,6 @@ public class WhileStatement extends Statement {
// generate the action
BranchLabel actionLabel = new BranchLabel(codeStream);
if (this.action != null) {
- this.condition.generatePatternVariable(currentScope, codeStream);
actionLabel.tagBits |= BranchLabel.USED;
// Required to fix 1PR0XVS: LFRE:WINNT - Compiler: variable table for method appears incorrect
if (this.condIfTrueInitStateIndex != -1) {
@@ -275,42 +275,11 @@ public class WhileStatement extends Statement {
}
@Override
- public void lookForPatternVariables(BlockScope scope) {
- this.condition.traverse(new ASTVisitor() {
- @Override
- public boolean visit(
- InstanceOfExpression instanceOfExpression,
- BlockScope sc) {
- if (instanceOfExpression.elementVariable != null) {
- WhileStatement.this.bits |= ASTNode.HasInstancePatternExpression;
- }
- return false; // mission finished, exit
- }
- }, scope);
- this.patternScope = new BlockScope(scope);
- }
-
- @Override
public void resolve(BlockScope scope) {
- boolean hasPatternVariable = (this.bits & ASTNode.HasInstancePatternExpression) != 0;
- BlockScope trueScope = null;
- BlockScope falseScope = null;
- if (hasPatternVariable) {
- trueScope = this.patternScope;
- this.condition.resolvePatternVariable(trueScope, true);
- }
- TypeBinding type = this.condition.resolveTypeExpecting(hasPatternVariable ? trueScope : scope, TypeBinding.BOOLEAN);
+ TypeBinding type = this.condition.resolveTypeExpecting(scope, TypeBinding.BOOLEAN);
this.condition.computeConversion(scope, type, type);
- if (this.action != null) {
- if (hasPatternVariable) {
- if (this.action.doesNotCompleteNormally()) {
- falseScope = (BlockScope) scope.parent;
- }
- }
- this.action.resolve(hasPatternVariable ? trueScope : scope);
- if (falseScope != null)
- this.condition.resolvePatternVariable(falseScope, false);
- }
+ if (this.action != null)
+ this.action.resolve(scope);
}
@Override
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BlockScope.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BlockScope.java
index 6980158b37..39d64e3762 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BlockScope.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BlockScope.java
@@ -134,7 +134,6 @@ public final void addLocalType(TypeDeclaration localType) {
methodScope = methodScope.enclosingMethodScope();
}
}
-
/* Insert a local variable into a given scope, updating its position
* and checking there are not too many locals or arguments allocated.
*/
@@ -419,7 +418,7 @@ public LocalDeclaration[] findLocalVariableDeclarations(int position) {
} else {
// consider variable first
LocalVariableBinding local = this.locals[ilocal]; // if no local at all, will be locals[ilocal]==null
- if (local != null) {
+ if (local != null && (local.modifiers & ExtraCompilerModifiers.AccPatterVariable) == 0) {
LocalDeclaration localDecl = local.declaration;
if (localDecl != null) {
if (localDecl.declarationSourceStart <= position) {
@@ -447,9 +446,20 @@ public LocalDeclaration[] findLocalVariableDeclarations(int position) {
public LocalVariableBinding findVariable(char[] variableName) {
int varLength = variableName.length;
for (int i = this.localIndex-1; i >= 0; i--) { // lookup backward to reach latest additions first
- LocalVariableBinding local;
+ LocalVariableBinding local = this.locals[i];
+ if ((local.modifiers & ExtraCompilerModifiers.AccPatterVariable) != 0)
+ continue;
+ char[] localName;
+ if ((localName = local.name).length == varLength && CharOperation.equals(localName, variableName))
+ return local;
+ }
+ // Look at the pattern variables now
+ for (int i = this.localIndex-1; i >= 0; i--) { // lookup backward to reach latest additions first
+ LocalVariableBinding local = this.locals[i];
+ if ((local.modifiers & ExtraCompilerModifiers.AccPatterVariable) == 0)
+ continue;
char[] localName;
- if ((localName = (local = this.locals[i]).name).length == varLength && CharOperation.equals(localName, variableName))
+ if ((localName = local.name).length == varLength && CharOperation.equals(localName, variableName))
return local;
}
return null;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ExtraCompilerModifiers.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ExtraCompilerModifiers.java
index fdba43ae5d..cc2f201db4 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ExtraCompilerModifiers.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ExtraCompilerModifiers.java
@@ -57,4 +57,5 @@ public interface ExtraCompilerModifiers { // modifier constant
final int AccOverriding = ASTNode.Bit29; // record fact a method overrides another one
final int AccImplementing = ASTNode.Bit30; // record fact a method implements another one (it is concrete and overrides an abstract one)
final int AccGenericSignature = ASTNode.Bit31; // record fact a type/method/field involves generics in its signature (and need special signature attr)
+ final int AccPatterVariable = ASTNode.Bit29;
}
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 aa2193a718..74d5ef7c87 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
@@ -2102,12 +2102,20 @@ public void duplicateInitializationOfBlankFinalField(FieldBinding field, Referen
}
public void duplicateInitializationOfFinalLocal(LocalVariableBinding local, ASTNode location) {
String[] arguments = new String[] { new String(local.readableName())};
- this.handle(
- IProblem.DuplicateFinalLocalInitialization,
- arguments,
- arguments,
- nodeSourceStart(local, location),
- nodeSourceEnd(local, location));
+ if ((local.modifiers & ExtraCompilerModifiers.AccPatterVariable) == 0) {
+ this.handle(
+ IProblem.DuplicateFinalLocalInitialization,
+ arguments,
+ arguments,
+ nodeSourceStart(local, location),
+ nodeSourceEnd(local, location));
+ } else {
+ this.handle(IProblem.PatternVariableNotInScope,
+ arguments,
+ arguments,
+ nodeSourceStart(local, location),
+ nodeSourceEnd(local, location));
+ }
}
public void duplicateMethodInType(AbstractMethodDeclaration methodDecl, boolean equalParameters, int severity) {
MethodBinding method = methodDecl.binding;
@@ -8716,14 +8724,25 @@ public void uninitializedNonNullField(FieldBinding field, ASTNode location) {
nodeSourceEnd(field, location));
}
public void uninitializedLocalVariable(LocalVariableBinding binding, ASTNode location, Scope scope) {
- binding.markAsUninitializedIn(scope);
- String[] arguments = new String[] {new String(binding.readableName())};
- this.handle(
- methodHasMissingSwitchDefault() ? IProblem.UninitializedLocalVariableHintMissingDefault : IProblem.UninitializedLocalVariable,
- arguments,
- arguments,
- nodeSourceStart(binding, location),
- nodeSourceEnd(binding, location));
+ if ((binding.modifiers & ExtraCompilerModifiers.AccPatterVariable) == 0) {
+ binding.markAsUninitializedIn(scope);
+ String[] arguments = new String[] {new String(binding.readableName())};
+ this.handle(
+ methodHasMissingSwitchDefault() ? IProblem.UninitializedLocalVariableHintMissingDefault : IProblem.UninitializedLocalVariable,
+ arguments,
+ arguments,
+ nodeSourceStart(binding, location),
+ nodeSourceEnd(binding, location));
+ } else {
+ String[] arguments = new String[] {new String(binding.readableName())};
+ this.handle(
+ IProblem.PatternVariableNotInScope,
+ arguments,
+ arguments,
+ nodeSourceStart(binding, location),
+ nodeSourceEnd(binding, location));
+
+ }
}
private boolean methodHasMissingSwitchDefault() {
MethodScope methodScope = null;
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 61367457cf..05d990a28a 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
@@ -1051,6 +1051,8 @@
1753 = void is an invalid type for the component {0} of a record
1754 = The variable argument type {0} of the record {1} must be the last parameter
+1760 = The pattern variable {0} is not in scope in this location
+
# Java 14 Preview - end
# Additional doc

Back to the top