Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJay Arthanareeswaran2020-08-24 09:51:31 +0000
committerJay Arthanareeswaran2020-09-08 02:41:19 +0000
commit9c56002a7c3353a731cf08eb1cc844d7852d5c2d (patch)
tree4b8944eac65dbd0d5e3038a3b49fcb0e488f1c12
parent5a2906645ae1c15ab63cbd4e4f1f083490356aa9 (diff)
downloadeclipse.jdt.core-9c56002a7c3353a731cf08eb1cc844d7852d5c2d.tar.gz
eclipse.jdt.core-9c56002a7c3353a731cf08eb1cc844d7852d5c2d.tar.xz
eclipse.jdt.core-9c56002a7c3353a731cf08eb1cc844d7852d5c2d.zip
Bug 562824 - [14] Pattern variable with same name as outer local or
field is rejected Change-Id: I6ab2c0c0da62b7abd134fe93a0823c1582719044 Signed-off-by: Jay Arthanareeswaran <jarthana@in.ibm.com>
-rw-r--r--org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/PatternMatching15Test.java393
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/IProblem.java2
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AND_AND_Expression.java18
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ASTNode.java7
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AbstractMethodDeclaration.java3
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Argument.java14
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/BinaryExpression.java20
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ConditionalExpression.java23
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/DoStatement.java26
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Expression.java55
-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.java35
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/InstanceOfExpression.java50
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/JavadocSingleNameReference.java2
-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/OR_OR_Expression.java17
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Statement.java71
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/UnaryExpression.java19
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/WhileStatement.java27
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BlockScope.java26
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/InvocationSite.java9
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Scope.java9
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java37
23 files changed, 767 insertions, 172 deletions
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/PatternMatching15Test.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/PatternMatching15Test.java
index cd5309caee..bf948d99b8 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/PatternMatching15Test.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/PatternMatching15Test.java
@@ -28,7 +28,7 @@ public class PatternMatching15Test extends AbstractRegressionTest {
static {
// TESTS_NUMBERS = new int [] { 40 };
// TESTS_RANGE = new int[] { 1, -1 };
-// TESTS_NAMES = new String[] { "testBug562392" };
+// TESTS_NAMES = new String[] { "test022a" };
}
public static Class<?> testClass() {
@@ -322,12 +322,12 @@ public class PatternMatching15Test extends AbstractRegressionTest {
"1. ERROR in X6a.java (at line 8)\n" +
" System.out.print(i);\n" +
" ^\n" +
- "The pattern variable i is not in scope in this location\n" +
+ "i cannot be resolved to a variable\n" +
"----------\n" +
"2. ERROR in X6a.java (at line 11)\n" +
" System.out.print(i);\n" +
" ^\n" +
- "The pattern variable i is not in scope in this location\n" +
+ "i cannot be resolved to a variable\n" +
"----------\n",
"",
null,
@@ -360,12 +360,12 @@ public class PatternMatching15Test extends AbstractRegressionTest {
"1. ERROR in X6b.java (at line 8)\n" +
" System.out.print(i);\n" +
" ^\n" +
- "The pattern variable i is not in scope in this location\n" +
+ "i cannot be resolved to a variable\n" +
"----------\n" +
"2. ERROR in X6b.java (at line 11)\n" +
" System.out.print(s);\n" +
" ^\n" +
- "The pattern variable s is not in scope in this location\n" +
+ "s cannot be resolved to a variable\n" +
"----------\n",
"",
null,
@@ -395,7 +395,7 @@ public class PatternMatching15Test extends AbstractRegressionTest {
"1. ERROR in X6c.java (at line 7)\n" +
" System.out.print(i);\n" +
" ^\n" +
- "The pattern variable i is not in scope in this location\n" +
+ "i cannot be resolved to a variable\n" +
"----------\n",
"",
null,
@@ -425,7 +425,7 @@ public class PatternMatching15Test extends AbstractRegressionTest {
"1. ERROR in X6d.java (at line 7)\n" +
" System.out.print(i);\n" +
" ^\n" +
- "The pattern variable i is not in scope in this location\n" +
+ "i cannot be resolved to a variable\n" +
"----------\n",
"",
null,
@@ -455,7 +455,7 @@ public class PatternMatching15Test extends AbstractRegressionTest {
"1. ERROR in X7.java (at line 7)\n" +
" System.out.print(i);\n" +
" ^\n" +
- "The pattern variable i is not in scope in this location\n" +
+ "i cannot be resolved to a variable\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" +
@@ -576,7 +576,7 @@ public class PatternMatching15Test extends AbstractRegressionTest {
"1. ERROR in X11.java (at line 7)\n" +
" System.out.println(s);\n" +
" ^\n" +
- "The pattern variable s is not in scope in this location\n" +
+ "s cannot be resolved to a variable\n" +
"----------\n",
"",
null,
@@ -611,7 +611,7 @@ public class PatternMatching15Test extends AbstractRegressionTest {
"1. ERROR in X12.java (at line 11)\n" +
" s = null;\n" +
" ^\n" +
- "The pattern variable s is not in scope in this location\n" +
+ "s cannot be resolved to a variable\n" +
"----------\n",
"",
null,
@@ -642,15 +642,10 @@ public class PatternMatching15Test extends AbstractRegressionTest {
"}\n",
},
"----------\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" +
+ "1. ERROR in X13.java (at line 9)\n" +
" System.out.println(s);\n" +
" ^\n" +
- "The pattern variable s is not in scope in this location\n" +
+ "s cannot be resolved to a variable\n" +
"----------\n",
"",
null,
@@ -680,7 +675,7 @@ public class PatternMatching15Test extends AbstractRegressionTest {
"1. ERROR in X14.java (at line 5)\n" +
" System.out.print(\"then:\" + s);\n" +
" ^\n" +
- "The pattern variable s is not in scope in this location\n" +
+ "s cannot be resolved to a variable\n" +
"----------\n",
"",
null,
@@ -710,7 +705,7 @@ public class PatternMatching15Test extends AbstractRegressionTest {
"1. ERROR in X14a.java (at line 5)\n" +
" System.out.print(\"then:\" + s);\n" +
" ^\n" +
- "The pattern variable s is not in scope in this location\n" +
+ "s cannot be resolved to a variable\n" +
"----------\n",
"",
null,
@@ -740,7 +735,7 @@ public class PatternMatching15Test extends AbstractRegressionTest {
"1. ERROR in X14b.java (at line 7)\n" +
" System.out.print(\"else:\" + s);\n" +
" ^\n" +
- "The pattern variable s is not in scope in this location\n" +
+ "s cannot be resolved to a variable\n" +
"----------\n",
"",
null,
@@ -770,7 +765,7 @@ public class PatternMatching15Test extends AbstractRegressionTest {
"1. ERROR in X14c.java (at line 7)\n" +
" System.out.print(\"else:\" + s);\n" +
" ^\n" +
- "The pattern variable s is not in scope in this location\n" +
+ "s cannot be resolved to a variable\n" +
"----------\n",
"",
null,
@@ -900,7 +895,7 @@ public class PatternMatching15Test extends AbstractRegressionTest {
"1. ERROR in X15b.java (at line 9)\n" +
" System.out.print(s);\n" +
" ^\n" +
- "The pattern variable s is not in scope in this location\n" +
+ "s cannot be resolved to a variable\n" +
"----------\n",
"",
null,
@@ -946,7 +941,7 @@ public class PatternMatching15Test extends AbstractRegressionTest {
"1. ERROR in X17.java (at line 5)\n" +
" System.out.print(s[0]);\n" +
" ^\n" +
- "The pattern variable s is not in scope in this location\n" +
+ "s cannot be resolved to a variable\n" +
"----------\n",
"",
null,
@@ -1068,12 +1063,12 @@ public class PatternMatching15Test extends AbstractRegressionTest {
"1. ERROR in X21.java (at line 5)\n" +
" System.out.print(s);\n" +
" ^\n" +
- "The pattern variable s is not in scope in this location\n" +
+ "s cannot be resolved to a variable\n" +
"----------\n" +
"2. ERROR in X21.java (at line 6)\n" +
" System.out.print(s2);\n" +
" ^^\n" +
- "The pattern variable s2 is not in scope in this location\n" +
+ "s2 cannot be resolved to a variable\n" +
"----------\n",
"",
null,
@@ -1125,17 +1120,17 @@ public class PatternMatching15Test extends AbstractRegressionTest {
"1. ERROR in X22a.java (at line 8)\n" +
" o = s.substring(0, s.length() - 1);\n" +
" ^\n" +
- "The pattern variable s is not in scope in this location\n" +
+ "s cannot be resolved\n" +
"----------\n" +
"2. ERROR in X22a.java (at line 8)\n" +
" o = s.substring(0, s.length() - 1);\n" +
" ^\n" +
- "The pattern variable s is not in scope in this location\n" +
+ "s cannot be resolved\n" +
"----------\n" +
"3. ERROR in X22a.java (at line 9)\n" +
" System.out.println(s);\n" +
" ^\n" +
- "The pattern variable s is not in scope in this location\n" +
+ "s cannot be resolved to a variable\n" +
"----------\n",
null,
true,
@@ -1163,7 +1158,7 @@ public class PatternMatching15Test extends AbstractRegressionTest {
"1. ERROR in X22b.java (at line 10)\n" +
" System.out.println(s);\n" +
" ^\n" +
- "The pattern variable s is not in scope in this location\n" +
+ "s cannot be resolved to a variable\n" +
"----------\n",
null,
true,
@@ -1214,12 +1209,12 @@ public class PatternMatching15Test extends AbstractRegressionTest {
"1. ERROR in X23.java (at line 7)\n" +
" while (!(o instanceof String s) && s.length() > 0) {\n" +
" ^\n" +
- "The pattern variable s is not in scope in this location\n" +
+ "s cannot be resolved\n" +
"----------\n" +
"2. ERROR in X23.java (at line 8)\n" +
" System.out.println(s);\n" +
" ^\n" +
- "The pattern variable s is not in scope in this location\n" +
+ "s cannot be resolved to a variable\n" +
"----------\n",
"",
null,
@@ -1248,12 +1243,12 @@ public class PatternMatching15Test extends AbstractRegressionTest {
"1. ERROR in X23a.java (at line 8)\n" +
" System.out.println(s);\n" +
" ^\n" +
- "The pattern variable s is not in scope in this location\n" +
+ "s cannot be resolved to a variable\n" +
"----------\n" +
"2. ERROR in X23a.java (at line 10)\n" +
" } while (!(o instanceof String s) && s.length() > 0);\n" +
" ^\n" +
- "The pattern variable s is not in scope in this location\n" +
+ "s cannot be resolved\n" +
"----------\n",
"",
null,
@@ -1284,12 +1279,12 @@ public class PatternMatching15Test extends AbstractRegressionTest {
"1. ERROR in X23b.java (at line 7)\n" +
" while (!(o instanceof String s) && s.length() > 0) {\n" +
" ^\n" +
- "The pattern variable s is not in scope in this location\n" +
+ "s cannot be resolved\n" +
"----------\n" +
"2. ERROR in X23b.java (at line 8)\n" +
" System.out.println(s);\n" +
" ^\n" +
- "The pattern variable s is not in scope in this location\n" +
+ "s cannot be resolved to a variable\n" +
"----------\n",
"",
null,
@@ -1319,12 +1314,12 @@ public class PatternMatching15Test extends AbstractRegressionTest {
"1. ERROR in X23c.java (at line 8)\n" +
" System.out.println(s);\n" +
" ^\n" +
- "The pattern variable s is not in scope in this location\n" +
+ "s cannot be resolved to a variable\n" +
"----------\n" +
"2. ERROR in X23c.java (at line 10)\n" +
" }while (!(o instanceof String s) && s.length() > 0);\n" +
" ^\n" +
- "The pattern variable s is not in scope in this location\n" +
+ "s cannot be resolved\n" +
"----------\n",
"",
null,
@@ -1398,7 +1393,143 @@ public class PatternMatching15Test extends AbstractRegressionTest {
"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" +
+ "s cannot be resolved to a variable\n" +
+ "----------\n",
+ "",
+ null,
+ true,
+ options);
+ }
+ public void test025a() {
+ Map<String, String> options = getCompilerOptions(true);
+ runNegativeTest(
+ new String[] {
+ "X25.java",
+ "@SuppressWarnings(\"preview\")\n" +
+ "public class X25 {\n" +
+ " public static void main(String[] o) {\n" +
+ " foo(\"one\");\n" +
+ " }\n" +
+ " public static void foo(Object o) {\n" +
+ " if ( (o instanceof String a) || (! (o instanceof String a)) ) {\n" +
+ " System.out.print(\"a:\" + a);\n" +
+ " }\n" +
+ " }\n" +
+ "}\n",
+ },
+ "----------\n" +
+ "1. ERROR in X25.java (at line 8)\n" +
+ " System.out.print(\"a:\" + a);\n" +
+ " ^\n" +
+ "a cannot be resolved to a variable\n" +
+ "----------\n",
+ "",
+ null,
+ true,
+ options);
+ }
+ public void test025b() {
+ Map<String, String> options = getCompilerOptions(true);
+ runConformTest(
+ new String[] {
+ "X25.java",
+ "@SuppressWarnings(\"preview\")\n" +
+ "public class X25 {\n" +
+ " public static void main(String[] o) {\n" +
+ " foo(\"one\");\n" +
+ " }\n" +
+ " public static void foo(Object o) {\n" +
+ " if ( (o instanceof String a) || (! (o instanceof String a)) ) {\n" +
+ " System.out.println(\"none\");\n" +
+ " } else {\n" +
+ " System.out.print(\"a:\" + a);\n" +
+ " }\n" +
+ " }\n" +
+ "}\n",
+ },
+ "none",
+ options);
+ }
+ public void test025c() {
+ Map<String, String> options = getCompilerOptions(true);
+ runConformTest(
+ new String[] {
+ "X25.java",
+ "@SuppressWarnings(\"preview\")\n" +
+ "public class X25 {\n" +
+ " public static void main(String[] o) {\n" +
+ " foo(\"one\", new Integer(0));\n" +
+ " }\n" +
+ " public static void foo(Object o, Object p) {\n" +
+ " if ( (o instanceof String a) || (! (p instanceof String a)) ) {\n" +
+ " System.out.println(\"none\");\n" +
+ " } else {\n" +
+ " System.out.print(\"a:\" + a);\n" +
+ " }\n" +
+ " }\n" +
+ "}\n",
+ },
+ "none",
+ options);
+ }
+ /*
+ * It's not allowed to have two pattern variables with same name in the
+ * same scope
+ */
+ public void test026() {
+ Map<String, String> options = getCompilerOptions(true);
+ runNegativeTest(
+ new String[] {
+ "X26.java",
+ "@SuppressWarnings(\"preview\")\n" +
+ "public class X26 {\n" +
+ " public static void main(String[] o) {\n" +
+ " foo(\"one\", \"two\");\n" +
+ " }\n" +
+ " public static void foo(Object o, Object p) {\n" +
+ " if ((o instanceof String s) && (p instanceof String s)) {\n" +
+ " System.out.print(\"s:\" + s);\n" +
+ " }\n" +
+ " }\n" +
+ "}\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" +
+ "----------\n",
+ "",
+ null,
+ true,
+ options);
+ }
+ /*
+ * It's not allowed to have two pattern variables with same name in the
+ * same scope
+ */
+ public void test026a() {
+ Map<String, String> options = getCompilerOptions(true);
+ runNegativeTest(
+ new String[] {
+ "X26.java",
+ "@SuppressWarnings(\"preview\")\n" +
+ "public class X26 {\n" +
+ " public static void main(String[] o) {\n" +
+ " foo(\"one\", \"two\");\n" +
+ " }\n" +
+ " public static void foo(Object o, Object p) {\n" +
+ " if ((o instanceof String s) && (!(o instanceof String s))) {\n" +
+ " System.out.print(\"s:\" + s);\n" +
+ " }\n" +
+ " }\n" +
+ "}\n",
+ },
+ "----------\n" +
+ "1. ERROR in X26.java (at line 7)\n" +
+ " if ((o instanceof String s) && (!(o instanceof String s))) {\n" +
+ " ^\n" +
+ "Duplicate local variable s\n" +
"----------\n",
"",
null,
@@ -1409,7 +1540,7 @@ public class PatternMatching15Test extends AbstractRegressionTest {
* 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() {
+ public void test026b() {
Map<String, String> options = getCompilerOptions(true);
runNegativeTest(
new String[] {
@@ -1430,7 +1561,7 @@ public class PatternMatching15Test extends AbstractRegressionTest {
"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" +
+ "s cannot be resolved to a variable\n" +
"----------\n",
"",
null,
@@ -1518,7 +1649,7 @@ public class PatternMatching15Test extends AbstractRegressionTest {
"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" +
+ "s cannot be resolved\n" +
"----------\n",
"",
null,
@@ -1545,17 +1676,17 @@ public class PatternMatching15Test 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" +
- "The pattern variable s is not in scope in this location\n" +
+ "s cannot be resolved to a variable\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" +
- "The pattern variable s is not in scope in this location\n" +
+ "s cannot be resolved to a variable\n" +
"----------\n" +
"3. ERROR in X31.java (at line 8)\n" +
" System.out.println(s[i]);\n" +
" ^\n" +
- "The pattern variable s is not in scope in this location\n" +
+ "s cannot be resolved to a variable\n" +
"----------\n",
"",
null,
@@ -1614,7 +1745,7 @@ public class PatternMatching15Test extends AbstractRegressionTest {
"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" +
+ "s cannot be resolved\n" +
"----------\n",
"",
null,
@@ -1684,12 +1815,12 @@ public class PatternMatching15Test extends AbstractRegressionTest {
"1. ERROR in X35.java (at line 11)\n" +
" yield s;\n" +
" ^\n" +
- "The pattern variable s is not in scope in this location\n" +
+ "s cannot be resolved to a variable\n" +
"----------\n" +
"2. ERROR in X35.java (at line 14)\n" +
" yield s;\n" +
" ^\n" +
- "The pattern variable s is not in scope in this location\n" +
+ "s cannot be resolved to a variable\n" +
"----------\n",
"",
null,
@@ -1768,16 +1899,13 @@ public class PatternMatching15Test extends AbstractRegressionTest {
"1. ERROR in X38.java (at line 10)\n" +
" System.out.println(s);\n" +
" ^\n" +
- "The pattern variable s is not in scope in this location\n" +
+ "s cannot be resolved to a variable\n" +
"----------\n",
"",
null,
true,
getCompilerOptions(true));
}
- /*
- * Failing with VerifyError
- */
public void test039() {
runConformTest(
new String[] {
@@ -1875,7 +2003,7 @@ public class PatternMatching15Test extends AbstractRegressionTest {
"else_x",
getCompilerOptions(true));
}
- public void _test043() {
+ public void test043() {
runConformTest(
new String[] {
"X43.java",
@@ -1888,11 +2016,11 @@ public class PatternMatching15Test extends AbstractRegressionTest {
" class Inner {\n" +
" public boolean foo(Object obj) {\n" +
" if (obj instanceof String s) {\n" +
- " // x is shadowed now\n" +
+ " // s is shadowed now\n" +
" if (!\"foo\".equals(s))\n" +
" return false;\n" +
" }\n" +
- " // x is not shadowed\n" +
+ " // s is not shadowed\n" +
" return \"test\".equals(s);\n" +
" }\n" +
" }\n" +
@@ -1900,7 +2028,7 @@ public class PatternMatching15Test extends AbstractRegressionTest {
" }\n" +
"}\n",
},
- "else_x",
+ "true",
getCompilerOptions(true));
}
public void test044() {
@@ -2733,4 +2861,159 @@ public class PatternMatching15Test extends AbstractRegressionTest {
"PASS",
compilerOptions);
}
+ public void test062() {
+ Map<String, String> compilerOptions = getCompilerOptions(true);
+ runNegativeTest(
+ new String[] {
+ "X.java",
+ "public class X {\n"+
+ " @SuppressWarnings(\"preview\")\n"+
+ " public void foo(Object o) {\n"+
+ " int len = (o instanceof String p) ? test(p -> p.length()) : test(p -> p.length());\n"+
+ " }\n"+
+ " public int test(FI fi) {\n" +
+ " return fi.length(\"\");\n" +
+ " } \n" +
+ " interface FI {\n" +
+ " public int length(String str);\n" +
+ " }" +
+ "}",
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 4)\n" +
+ " int len = (o instanceof String p) ? test(p -> p.length()) : test(p -> p.length());\n" +
+ " ^\n" +
+ "Lambda expression\'s parameter p cannot redeclare another local variable defined in an enclosing scope. \n" +
+ "----------\n",
+ "",
+ null,
+ true,
+ compilerOptions);
+ }
+ // Same as above, but pattern variable in scope in false of conditional expression
+ public void test063() {
+ Map<String, String> compilerOptions = getCompilerOptions(true);
+ runNegativeTest(
+ new String[] {
+ "X.java",
+ "public class X {\n"+
+ " @SuppressWarnings(\"preview\")\n"+
+ " public void foo(Object o) {\n"+
+ " int len = !(o instanceof String p) ? test(p -> p.length()) : test(p -> p.length());\n"+
+ " }\n"+
+ " public int test(FI fi) {\n" +
+ " return fi.length(\"\");\n" +
+ " } \n" +
+ " interface FI {\n" +
+ " public int length(String str);\n" +
+ " }" +
+ "}",
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 4)\n" +
+ " int len = !(o instanceof String p) ? test(p -> p.length()) : test(p -> p.length());\n" +
+ " ^\n" +
+ "Lambda expression\'s parameter p cannot redeclare another local variable defined in an enclosing scope. \n" +
+ "----------\n",
+ "",
+ null,
+ true,
+ compilerOptions);
+ }
+ public void test064() {
+ Map<String, String> compilerOptions = getCompilerOptions(true);
+ runConformTest(
+ new String[] {
+ "X.java",
+ "@SuppressWarnings(\"preview\")\n"+
+ "public class X {\n"+
+ " public static void main(String argv[]) {\n" +
+ " System.out.println(new X().foo(\"foo\", \"test\"));\n" +
+ " }\n" +
+ " public boolean foo(Object obj, String s) {\n" +
+ " class Inner {\n" +
+ " public boolean foo(Object obj) {\n" +
+ " if (obj instanceof String s) {\n" +
+ " // s is shadowed now\n" +
+ " if (\"foo\".equals(s))\n" +
+ " return false;\n" +
+ " } else if (obj instanceof String s) { \n" +
+ " }\n"+
+ " // s is not shadowed\n" +
+ " return \"test\".equals(s);\n" +
+ " }\n" +
+ " }\n" +
+ " return new Inner().foo(obj);\n" +
+ " }" +
+ "}",
+ },
+ "false",
+ compilerOptions);
+ }
+ public void test065() {
+ Map<String, String> compilerOptions = getCompilerOptions(true);
+ runConformTest(
+ new String[] {
+ "X.java",
+ "@SuppressWarnings(\"preview\")\n"+
+ "public class X {\n"+
+ " public static void main(String argv[]) {\n"
+ + " new X().foo(\"foo\");\n"
+ + " }\n"
+ + " public void foo(Object o) {\n"
+ + " if ((o instanceof String s)) {\n"
+ + " System.out.println(\"if:\" + s);\n"
+ + " } else {\n"
+ + " throw new IllegalArgumentException();\n"
+ + " }\n"
+ + " System.out.println(\"after:\" + s);\n"
+ + " }" +
+ "}",
+ },
+ "if:foo\n" +
+ "after:foo",
+ compilerOptions);
+ }
+ public void test066() {
+ Map<String, String> compilerOptions = getCompilerOptions(true);
+ runConformTest(
+ new String[] {
+ "X.java",
+ "@SuppressWarnings(\"preview\")\n"+
+ "public class X {\n"
+ + " protected Object x = \"FIELD X\";\n"
+ + " public void f(Object obj, boolean b) {\n"
+ + " if ((x instanceof String x)) {\n"
+ + " System.out.println(x.toLowerCase());\n"
+ + " }\n"
+ + " }\n"
+ + " public static void main(String[] args) {\n"
+ + " new X().f(Integer.parseInt(\"1\"), false);\n"
+ + " }\n"
+ + "}",
+ },
+ "field x",
+ compilerOptions);
+ }
+ public void test067() {
+ Map<String, String> compilerOptions = getCompilerOptions(true);
+ runConformTest(
+ new String[] {
+ "X.java",
+ "@SuppressWarnings(\"preview\")\n"+
+ "public class X {\n"
+ + " protected String x = \"FIELD X\";\n"
+ + " public void f(Object obj, boolean b) {\n"
+ + " if ((x instanceof String x) && x.length() > 0) {\n"
+ + " System.out.println(x.toLowerCase());\n"
+ + " }\n"
+ + " }\n"
+ + " public static void main(String[] args) {\n"
+ + " new X().f(Integer.parseInt(\"1\"), false);\n"
+ + " }\n"
+ + "}",
+ },
+ "field x",
+ compilerOptions);
+ }
}
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 33550b9341..67fbd1a477 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
@@ -2366,7 +2366,7 @@ void setSourceStart(int sourceStart);
/* instanceof pattern: */
/** @since 3.22
- * @noreference preview feature error */
+ * @deprecated problem no longer generated */
int PatternVariableNotInScope = PreviewRelated + 1780;
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 422cc4420f..8089e0906e 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
@@ -8,6 +8,10 @@
*
* 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
@@ -272,7 +276,21 @@ public class AND_AND_Expression extends BinaryExpression {
codeStream.removeNotDefinitelyAssignedVariables(currentScope, this.mergedInitStateIndex);
}
}
+ @Override
+ public void collectPatternVariablesToScope(LocalVariableBinding[] variables, BlockScope scope) {
+ this.left.collectPatternVariablesToScope(this.patternVarsWhenTrue, scope);
+
+ variables = this.left.getPatternVariablesWhenTrue();
+ this.addPatternVariablesWhenTrue(variables);
+ this.right.addPatternVariablesWhenTrue(variables);
+ variables = this.left.getPatternVariablesWhenFalse();
+ this.right.addPatternVariablesWhenFalse(variables);
+
+ this.right.collectPatternVariablesToScope(this.patternVarsWhenTrue, scope);
+ variables = this.right.getPatternVariablesWhenTrue();
+ this.addPatternVariablesWhenTrue(variables);
+ }
@Override
public boolean isCompactableOperation() {
return false;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ASTNode.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ASTNode.java
index ef18911391..5a189cf6fd 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ASTNode.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ASTNode.java
@@ -8,6 +8,10 @@
*
* 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
* Matt McCutchen - partial fix for https://bugs.eclipse.org/bugs/show_bug.cgi?id=122995
@@ -176,8 +180,7 @@ public abstract class ASTNode implements TypeConstants, TypeIds {
public static final int GenerateCheckcast = Bit7;
public static final int UnsafeCast = Bit8;
- // for name references (Java 14 addition - Records preview - Bit18)
- public static final int RestrictiveFlagMASK = Bit1 | Bit2 | Bit3 | Bit18 ;
+ public static final int RestrictiveFlagMASK = Bit1 | Bit2 | Bit3 ;
// for local decls
public static final int IsTypeElided = Bit2; // type elided lambda argument.
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 2cc929fba4..c7276e5d9b 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
@@ -244,9 +244,6 @@ public abstract class AbstractMethodDeclaration
}
}
}
- if (methodArguments[i].duplicateCheckObligation != null) {
- methodArguments[i].duplicateCheckObligation.accept(flowInfo);
- }
// tag parameters as being set:
flowInfo.markAsDefinitelyAssigned(methodArguments[i].binding);
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Argument.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Argument.java
index c5b76d8ebf..3999b2760c 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Argument.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Argument.java
@@ -8,6 +8,10 @@
*
* 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
@@ -124,15 +128,7 @@ public class Argument extends LocalDeclaration {
final boolean localExists = existingVariable instanceof LocalVariableBinding;
if (localExists && this.hiddenVariableDepth == 0) {
if ((this.bits & ASTNode.ShadowsOuterLocal) != 0 && scope.isLambdaSubscope()) {
- if ((((LocalVariableBinding) existingVariable).modifiers & ExtraCompilerModifiers.AccPatternVariable) != 0) {
- this.duplicateCheckObligation = (flowInfo) -> {
- if (flowInfo.isDefinitelyAssigned((LocalVariableBinding) existingVariable)) {
- scope.problemReporter().lambdaRedeclaresArgument(this);
- }
- };
- } else {
- scope.problemReporter().lambdaRedeclaresArgument(this);
- }
+ scope.problemReporter().lambdaRedeclaresArgument(this);
} else if (scope.referenceContext instanceof CompactConstructorDeclaration) {
// skip error reporting - hidden params - already reported in record components
} else {
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 6736fcdca0..7ee189afbe 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
@@ -8,6 +8,10 @@
*
* 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 - Contribution for
@@ -1821,9 +1825,25 @@ public boolean containsPatternVariable() {
return this.left.containsPatternVariable() || this.right.containsPatternVariable();
}
@Override
+public void collectPatternVariablesToScope(LocalVariableBinding[] variables, BlockScope scope) {
+ this.left.addPatternVariablesWhenTrue(this.patternVarsWhenTrue);
+ this.right.addPatternVariablesWhenTrue(this.patternVarsWhenTrue);
+ this.left.addPatternVariablesWhenFalse(this.patternVarsWhenFalse);
+ this.right.addPatternVariablesWhenFalse(this.patternVarsWhenFalse);
+ this.left.collectPatternVariablesToScope(this.patternVarsWhenTrue, scope);
+ this.right.collectPatternVariablesToScope(this.patternVarsWhenTrue, scope);
+}
+@Override
public TypeBinding resolveType(BlockScope scope) {
// keep implementation in sync with CombinedBinaryExpression#resolveType
// and nonRecursiveResolveTypeUpwards
+ if(this.patternVarsWhenFalse == null && this.patternVarsWhenTrue == null &&
+ this.containsPatternVariable()) {
+ // the null check is to guard against a second round of collection.
+ // This usually doesn't happen,
+ // except when we call collectPatternVariablesToScope() from here
+ this.collectPatternVariablesToScope(null, scope);
+ }
boolean leftIsCast, rightIsCast;
if ((leftIsCast = this.left instanceof CastExpression) == true) this.left.bits |= ASTNode.DisableUnnecessaryCastCheck; // will check later on
TypeBinding leftType = this.left.resolveType(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 1685e69a74..a5cee27ad5 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
@@ -8,6 +8,10 @@
*
* 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
* Stephen Herrmann <stephan@cs.tu-berlin.de> - Contributions for
@@ -453,7 +457,20 @@ public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext,
this.valueIfTrue.addPatternVariables(scope, codeStream);
this.valueIfFalse.addPatternVariables(scope, codeStream);
}
-
+ @Override
+ public void collectPatternVariablesToScope(LocalVariableBinding[] variables, BlockScope scope) {
+ this.condition.collectPatternVariablesToScope(this.patternVarsWhenTrue, scope);
+
+ variables = this.condition.getPatternVariablesWhenTrue();
+ this.valueIfTrue.addPatternVariablesWhenTrue(variables);
+ this.valueIfFalse.addPatternVariablesWhenFalse(variables);
+ this.valueIfTrue.collectPatternVariablesToScope(variables, scope);
+
+ variables = this.condition.getPatternVariablesWhenFalse();
+ this.valueIfTrue.addPatternVariablesWhenFalse(variables);
+ this.valueIfFalse.addPatternVariablesWhenTrue(variables);
+ this.valueIfFalse.collectPatternVariablesToScope(variables, scope);
+ }
@Override
public TypeBinding resolveType(BlockScope scope) {
// JLS3 15.25
@@ -470,7 +487,9 @@ public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext,
this.valueIfFalse.setExpectedType(this.expectedType);
}
}
-
+ if (this.condition.containsPatternVariable()) {
+ collectPatternVariablesToScope(null, scope);
+ }
if (this.constant != Constant.NotAConstant) {
this.constant = Constant.NotAConstant;
TypeBinding conditionType = this.condition.resolveTypeExpecting(scope, TypeBinding.BOOLEAN);
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/DoStatement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/DoStatement.java
index 3c13922f01..2e46dcdb1b 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/DoStatement.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/DoStatement.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2020 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
@@ -8,6 +8,10 @@
*
* 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
@@ -227,10 +231,22 @@ public StringBuffer printStatement(int indent, StringBuffer output) {
@Override
public void resolve(BlockScope scope) {
- TypeBinding type = this.condition.resolveTypeExpecting(scope, TypeBinding.BOOLEAN);
- this.condition.computeConversion(scope, type, type);
- if (this.action != null)
- this.action.resolve(scope);
+ if (this.condition.containsPatternVariable()) {
+ this.condition.collectPatternVariablesToScope(null, scope);
+ LocalVariableBinding[] patternVariablesInFalseScope = this.condition.getPatternVariablesWhenFalse();
+ TypeBinding type = this.condition.resolveTypeExpecting(scope, TypeBinding.BOOLEAN);
+ this.condition.computeConversion(scope, type, type);
+ if (this.action != null) {
+ this.action.resolve(scope);
+ this.action.injectPatternVariablesIfApplicable(patternVariablesInFalseScope, scope,
+ (statement) -> { return !statement.breaksOut(null);});
+ }
+ } else {
+ TypeBinding type = this.condition.resolveTypeExpecting(scope, TypeBinding.BOOLEAN);
+ this.condition.computeConversion(scope, type, type);
+ if (this.action != null)
+ this.action.resolve(scope);
+ }
}
@Override
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 0192774c46..41ba72d4cc 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
@@ -8,6 +8,10 @@
*
* 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
@@ -791,6 +795,57 @@ public void addPatternVariables(BlockScope scope, CodeStream codeStream) {
public boolean containsPatternVariable() {
return false;
}
+public void collectPatternVariablesToScope(LocalVariableBinding[] variables, BlockScope scope) {
+ new ASTVisitor() {
+ LocalVariableBinding[] patternVariablesInScope;
+ @Override
+ public boolean visit(OR_OR_Expression exp, BlockScope skope) {
+ this.patternVariablesInScope = exp.getPatternVariablesWhenTrue();
+ return true;
+ }
+ @Override
+ public boolean visit(AND_AND_Expression exp, BlockScope skope) {
+ this.patternVariablesInScope = exp.getPatternVariablesWhenTrue();
+ return true;
+ }
+ @Override
+ public boolean visit(EqualExpression exp, BlockScope skope) {
+ this.patternVariablesInScope = exp.getPatternVariablesWhenTrue();
+ return true;
+ }
+ @Override
+ public boolean visit(UnaryExpression exp, BlockScope skope) {
+ this.patternVariablesInScope = exp.getPatternVariablesWhenTrue();
+ return true;
+ }
+ @Override
+ public boolean visit(Argument argument, BlockScope skope) {
+ // Most likely to be a lambda parameter
+ argument.addPatternVariablesWhenTrue(this.patternVariablesInScope);
+ return true;
+ }
+ @Override
+ public boolean visit(
+ QualifiedNameReference nameReference,
+ BlockScope skope) {
+ nameReference.addPatternVariablesWhenTrue(this.patternVariablesInScope);
+ return true;
+ }
+ @Override
+ public boolean visit(
+ SingleNameReference nameReference,
+ BlockScope skope) {
+ nameReference.addPatternVariablesWhenTrue(this.patternVariablesInScope);
+ return true;
+ }
+
+ public void propagatePatternVariablesInScope(LocalVariableBinding[] vars, BlockScope skope) {
+ this.patternVariablesInScope = vars;
+ Expression.this.traverse(this, skope);
+ }
+ }.propagatePatternVariablesInScope(variables, scope);
+}
+
/**
* 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 8e059b8dc3..a6b99d01bb 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
@@ -8,6 +8,10 @@
*
* 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
@@ -21,10 +25,16 @@ package org.eclipse.jdt.internal.compiler.ast;
import org.eclipse.jdt.internal.compiler.ASTVisitor;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
-import org.eclipse.jdt.internal.compiler.codegen.*;
-import org.eclipse.jdt.internal.compiler.flow.*;
+import org.eclipse.jdt.internal.compiler.codegen.BranchLabel;
+import org.eclipse.jdt.internal.compiler.codegen.CodeStream;
+import org.eclipse.jdt.internal.compiler.flow.FlowContext;
+import org.eclipse.jdt.internal.compiler.flow.FlowInfo;
+import org.eclipse.jdt.internal.compiler.flow.LoopingFlowContext;
+import org.eclipse.jdt.internal.compiler.flow.UnconditionalFlowInfo;
import org.eclipse.jdt.internal.compiler.impl.Constant;
-import org.eclipse.jdt.internal.compiler.lookup.*;
+import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
+import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding;
+import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
public class ForStatement extends Statement {
@@ -244,7 +254,6 @@ public class ForStatement extends Statement {
this.condition.updateFlowOnBooleanResult(mergedInfo, false);
return mergedInfo;
}
-
/**
* For statement code generation
*
@@ -403,16 +412,13 @@ public class ForStatement extends Statement {
@Override
public void resolve(BlockScope upperScope) {
+ LocalVariableBinding[] patternVariablesInTrueScope = null;
+ LocalVariableBinding[] patternVariablesInFalseScope = null;
+
if (this.condition != null && this.condition.containsPatternVariable()) {
- this.condition.traverse(new ASTVisitor() {
- @Override
- public boolean visit(
- InstanceOfExpression instanceOfExpression,
- BlockScope sc) {
- instanceOfExpression.resolvePatternVariable(upperScope);
- return true; // We want to resolve all pattern variables if any inside the condition
- }
- }, upperScope);
+ this.condition.collectPatternVariablesToScope(null, upperScope);
+ patternVariablesInTrueScope = this.condition.getPatternVariablesWhenTrue();
+ patternVariablesInFalseScope = this.condition.getPatternVariablesWhenFalse();
}
// use the scope that will hold the init declarations
this.scope = (this.bits & ASTNode.NeededScope) != 0 ? new BlockScope(upperScope) : upperScope;
@@ -424,10 +430,15 @@ public class ForStatement extends Statement {
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)
- this.action.resolve(this.scope);
+ for (int i = 0, length = this.increments.length; i < length; i++) {
+ this.increments[i].resolveWithPatternVariablesInScope(patternVariablesInTrueScope, this.scope);
+ }
+
+ if (this.action != null) {
+ this.action.resolveWithPatternVariablesInScope(patternVariablesInTrueScope, this.scope);
+ this.action.injectPatternVariablesIfApplicable(patternVariablesInFalseScope, this.scope,
+ (statement) -> { return !statement.breaksOut(null);});
+ }
}
@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 1cb95e1394..eb0897f451 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
@@ -8,6 +8,10 @@
*
* 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
@@ -158,7 +162,6 @@ public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, Fl
flowContext.conditionalLevel--;
return mergedInfo;
}
-
/**
* If code generation
*
@@ -217,7 +220,7 @@ public void generateCode(BlockScope currentScope, CodeStream codeStream) {
// May loose some local variable initializations : affecting the local variable attributes
if (this.elseInitStateIndex != -1) {
codeStream.removeNotDefinitelyAssignedVariables(
- currentScope,
+ currentScope,
this.elseInitStateIndex);
codeStream.addDefinitelyAssignedVariables(currentScope, this.elseInitStateIndex);
}
@@ -276,8 +279,7 @@ public StringBuffer printStatement(int indent, StringBuffer output) {
}
return output;
}
-@Override
-public void resolve(BlockScope scope) {
+private void resolveIfStatement(BlockScope scope) {
TypeBinding type = this.condition.resolveTypeExpecting(scope, TypeBinding.BOOLEAN);
this.condition.computeConversion(scope, type, type);
if (this.thenStatement != null)
@@ -285,6 +287,31 @@ public void resolve(BlockScope scope) {
if (this.elseStatement != null)
this.elseStatement.resolve(scope);
}
+@Override
+public void resolve(BlockScope scope) {
+ if (this.condition.containsPatternVariable()) {
+ this.condition.collectPatternVariablesToScope(null, scope);
+ LocalVariableBinding[] patternVariablesInTrueScope = this.condition.getPatternVariablesWhenTrue();
+ LocalVariableBinding[] patternVariablesInFalseScope = this.condition.getPatternVariablesWhenFalse();
+ TypeBinding type = this.condition.resolveTypeExpecting(scope, TypeBinding.BOOLEAN);
+ this.condition.computeConversion(scope, type, type);
+
+ if (this.thenStatement != null) {
+ this.thenStatement.resolveWithPatternVariablesInScope(patternVariablesInTrueScope, scope);
+ }
+ if (this.elseStatement != null) {
+ this.elseStatement.resolveWithPatternVariablesInScope(patternVariablesInFalseScope, scope);
+ }
+ if (this.thenStatement != null)
+ this.thenStatement.injectPatternVariablesIfApplicable(patternVariablesInFalseScope, scope,
+ (statement) -> { return statement.doesNotCompleteNormally();});
+ if (this.elseStatement != null)
+ this.elseStatement.injectPatternVariablesIfApplicable(patternVariablesInTrueScope, scope,
+ (statement) -> { return statement.doesNotCompleteNormally();});
+ } else {
+ resolveIfStatement(scope);
+ }
+}
@Override
public void traverse(ASTVisitor visitor, BlockScope blockScope) {
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 418fd906e1..14e8f0fce5 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
@@ -8,6 +8,10 @@
*
* 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 - Contribution for
@@ -24,6 +28,7 @@
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.ast;
+import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.internal.compiler.ASTVisitor;
import org.eclipse.jdt.internal.compiler.ast.TypeReference.AnnotationPosition;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
@@ -91,9 +96,6 @@ public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, Fl
}
}
if (this.elementVariable != null) {
- if (this.elementVariable.duplicateCheckObligation != null) {
- this.elementVariable.duplicateCheckObligation.accept(flowInfo);
- }
initsWhenTrue.markAsDefinitelyAssigned(this.elementVariable.binding);
}
return (initsWhenTrue == null) ? flowInfo :
@@ -250,14 +252,52 @@ public void addPatternVariables(BlockScope currentScope, CodeStream codeStream)
codeStream.addVisibleLocalVariable(this.elementVariable.binding);
}
}
-public void resolvePatternVariable(BlockScope scope) {
- if (this.elementVariable != null && this.elementVariable.binding == null) {
+public boolean resolvePatternVariable(BlockScope scope) {
+ if (this.elementVariable == null) return false;
+ if (this.elementVariable.binding == null) {
this.elementVariable.resolve(scope, true);
this.elementVariable.binding.modifiers |= ExtraCompilerModifiers.AccPatternVariable;
+ this.elementVariable.binding.modifiers |= ExtraCompilerModifiers.AccUnresolved; // TODO: Change to a different mechanism
this.elementVariable.binding.useFlag = LocalVariableBinding.USED;
// Why cant this be done in the constructor?
this.type = this.elementVariable.type;
}
+ return true;
+}
+@Override
+public void collectPatternVariablesToScope(LocalVariableBinding[] variables, BlockScope scope) {
+ this.expression.collectPatternVariablesToScope(this.patternVarsWhenTrue, scope);
+ if (this.elementVariable != null && this.elementVariable.binding == null) {
+ resolvePatternVariable(scope);
+ if (variables != null) {
+ for (LocalVariableBinding variable : variables) {
+ if (CharOperation.equals(this.elementVariable.name, variable.name)) {
+ scope.problemReporter().redefineLocal(this.elementVariable);
+ }
+ }
+ }
+ }
+ if (this.patternVarsWhenTrue == null) {
+ this.patternVarsWhenTrue = new LocalVariableBinding[1];
+ this.patternVarsWhenTrue[0] = this.elementVariable.binding;
+ } else {
+ this.addPatternVariablesWhenTrue(new LocalVariableBinding[] {this.elementVariable.binding});
+ }
+}
+@Override
+public void addPatternVariablesWhenTrue(LocalVariableBinding[] vars) {
+ if (this.patternVarsWhenTrue == null) {
+ this.getPatternVariablesWhenTrue();
+ }
+ if (vars == null || vars.length == 0) return;
+ if (this.patternVarsWhenTrue == null) {
+ this.patternVarsWhenTrue = vars;
+ } else {
+ int oldSize = this.patternVarsWhenTrue.length;
+ int newLength = oldSize + vars.length;
+ System.arraycopy(this.patternVarsWhenTrue, 0, (this.patternVarsWhenTrue = new LocalVariableBinding[newLength]), 0, oldSize);
+ System.arraycopy(vars, 0, this.patternVarsWhenTrue, oldSize, vars.length);
+ }
}
@Override
public boolean containsPatternVariable() {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/JavadocSingleNameReference.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/JavadocSingleNameReference.java
index 5987709196..a59e0a28e9 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/JavadocSingleNameReference.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/JavadocSingleNameReference.java
@@ -37,7 +37,7 @@ public class JavadocSingleNameReference extends SingleNameReference {
*/
public void resolve(BlockScope scope, boolean warn, boolean considerParamRefAsUsage) {
- LocalVariableBinding variableBinding = scope.findVariable(this.token);
+ LocalVariableBinding variableBinding = scope.findVariable(this.token, this);
if (variableBinding != null && variableBinding.isValidBinding() && ((variableBinding.tagBits & TagBits.IsArgument) != 0)) {
this.binding = variableBinding;
if (considerParamRefAsUsage) {
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 a364b9b3f3..240a7b92dc 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
@@ -49,7 +49,6 @@ 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.*;
@@ -64,12 +63,6 @@ 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,
@@ -128,9 +121,6 @@ public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, Fl
// no need to inform enclosing try block since its locals won't get
// known by the finally block
}
- if (this.duplicateCheckObligation != null) {
- this.duplicateCheckObligation.accept(flowInfo);
- }
return flowInfo;
}
@@ -312,23 +302,12 @@ 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 && (isPatternVariable
- || (((LocalVariableBinding) existingVariable).modifiers & ExtraCompilerModifiers.AccPatternVariable) != 0))
- {
- // Do this only if either one of them is a pattern variable.
- this.duplicateCheckObligation = (flowInfo) -> {
- if (flowInfo.isDefinitelyAssigned((LocalVariableBinding) existingVariable)) {
- scope.problemReporter().redefineLocal(this);
- }
- };
+ if (localExists && (this.bits & ASTNode.ShadowsOuterLocal) != 0 && scope.isLambdaSubscope() && this.hiddenVariableDepth == 0) {
+ scope.problemReporter().lambdaRedeclaresLocal(this);
+ } else if (localExists && this.hiddenVariableDepth == 0) {
+ 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) {
- scope.problemReporter().redefineLocal(this);
- } else {
- scope.problemReporter().localVariableHiding(this, existingVariable, false);
- }
+ scope.problemReporter().localVariableHiding(this, existingVariable, false);
}
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/OR_OR_Expression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/OR_OR_Expression.java
index e35c399cc7..cb5ac23392 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/OR_OR_Expression.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/OR_OR_Expression.java
@@ -8,6 +8,10 @@
*
* 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
@@ -277,7 +281,20 @@ public class OR_OR_Expression extends BinaryExpression {
codeStream.removeNotDefinitelyAssignedVariables(currentScope, this.mergedInitStateIndex);
}
}
+ @Override
+ public void collectPatternVariablesToScope(LocalVariableBinding[] variables, BlockScope scope) {
+ this.left.collectPatternVariablesToScope(variables, scope);
+ variables = this.left.getPatternVariablesWhenTrue();
+ this.right.addPatternVariablesWhenFalse(variables);
+ variables = this.left.getPatternVariablesWhenFalse();
+ this.right.addPatternVariablesWhenTrue(variables);
+ this.addPatternVariablesWhenFalse(variables);
+
+ this.right.collectPatternVariablesToScope(variables, scope);
+ variables = this.right.getPatternVariablesWhenFalse();
+ this.addPatternVariablesWhenFalse(variables);
+ }
@Override
public boolean isCompactableOperation() {
return 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 fac3135ca3..248e95519b 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, 2019 IBM Corporation and others.
+ * Copyright (c) 2000, 2020 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
@@ -8,6 +8,10 @@
*
* 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
@@ -41,6 +45,8 @@
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.ast;
+import java.util.function.Predicate;
+
import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.internal.compiler.ASTVisitor;
import org.eclipse.jdt.internal.compiler.ast.NullAnnotationMatching.CheckMode;
@@ -85,7 +91,6 @@ public abstract class Statement extends ASTNode {
return false;
}
public abstract FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo);
-
/** Lambda shape analysis: *Assuming* this is reachable, analyze if this completes normally i.e control flow can reach the textually next statement.
For blocks, we don't perform intra-reachability analysis. We assume the lambda body is free of intrinsic control flow errors (if such errors
exist they will not be flagged by this analysis, but are guaranteed to surface later on.)
@@ -124,6 +129,8 @@ public boolean continueCompletes() {
public static final int NOT_COMPLAINED = 0;
public static final int COMPLAINED_FAKE_REACHABLE = 1;
public static final int COMPLAINED_UNREACHABLE = 2;
+ LocalVariableBinding[] patternVarsWhenTrue = null;
+ LocalVariableBinding[] patternVarsWhenFalse = null;
/** Analysing arguments of MessageSend, ExplicitConstructorCall, AllocationExpression. */
@@ -483,7 +490,65 @@ public StringBuffer print(int indent, StringBuffer output) {
public abstract StringBuffer printStatement(int indent, StringBuffer output);
public abstract void resolve(BlockScope scope);
-
+public LocalVariableBinding[] getPatternVariablesWhenTrue() {
+ return this.patternVarsWhenTrue;
+}
+public LocalVariableBinding[] getPatternVariablesWhenFalse() {
+ return this.patternVarsWhenFalse;
+}
+public void addPatternVariablesWhenTrue(LocalVariableBinding[] vars) {
+ this.patternVarsWhenTrue = addPatternVariables(this.patternVarsWhenTrue, vars);
+}
+public void addPatternVariablesWhenFalse(LocalVariableBinding[] vars) {
+ this.patternVarsWhenFalse = addPatternVariables(this.patternVarsWhenFalse, vars);
+}
+private LocalVariableBinding[] addPatternVariables(LocalVariableBinding[] current, LocalVariableBinding[] add) {
+ if (add == null || add.length == 0)
+ return current;
+ if (current == null) {
+ current = add;
+ } else {
+ for (LocalVariableBinding local : add) {
+ current = addPatternVariables(current, local);
+ }
+ }
+ return current;
+}
+private LocalVariableBinding[] addPatternVariables(LocalVariableBinding[] current, LocalVariableBinding add) {
+ int oldSize = current.length;
+ // it's odd that we only look at the last element, but in most cases
+ // we will only have one in the array. In the unlikely case of having two
+ // distinct pattern variables, the cost is nothing but setting the same
+ // bit twice on the same object.
+ if (oldSize > 0 && current[oldSize - 1] == add) {
+ return current;
+ }
+ int newLength = current.length + 1;
+ System.arraycopy(current, 0, (current = new LocalVariableBinding[newLength]), 0, oldSize);
+ current[oldSize] = add;
+ return current;
+}
+public void injectPatternVariablesIfApplicable(LocalVariableBinding[] patternVariablesInScope, BlockScope scope,
+ Predicate<Statement> condition) {
+ if (patternVariablesInScope != null && condition.test(this)) {
+ for (LocalVariableBinding binding : patternVariablesInScope) {
+ binding.modifiers &= ~ExtraCompilerModifiers.AccUnresolved;
+ }
+ }
+}
+public void resolveWithPatternVariablesInScope(LocalVariableBinding[] patternVariablesInScope, BlockScope scope) {
+ if (patternVariablesInScope != null) {
+ for (LocalVariableBinding binding : patternVariablesInScope) {
+ binding.modifiers &= ~ExtraCompilerModifiers.AccUnresolved;
+ }
+ this.resolve(scope);
+ for (LocalVariableBinding binding : patternVariablesInScope) {
+ binding.modifiers |= ExtraCompilerModifiers.AccUnresolved;
+ }
+ } else {
+ resolve(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 c43e55c983..bc6a2a266c 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
@@ -8,6 +8,10 @@
*
* 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 - Contribution for
@@ -224,7 +228,22 @@ public class UnaryExpression extends OperatorExpression {
output.append(operatorToString()).append(' ');
return this.expression.printExpression(0, output);
}
+ @Override
+ public void collectPatternVariablesToScope(LocalVariableBinding[] variables, BlockScope scope) {
+ this.expression.collectPatternVariablesToScope(variables, scope);
+ if (((this.bits & OperatorMASK) >> OperatorSHIFT) == NOT) {
+ variables = this.expression.getPatternVariablesWhenTrue();
+ this.addPatternVariablesWhenFalse(variables);
+ variables = this.expression.getPatternVariablesWhenFalse();
+ this.addPatternVariablesWhenTrue(variables);
+ } else {
+ variables = this.expression.getPatternVariablesWhenTrue();
+ this.addPatternVariablesWhenTrue(variables);
+ variables = this.expression.getPatternVariablesWhenFalse();
+ this.addPatternVariablesWhenFalse(variables);
+ }
+ }
@Override
public TypeBinding resolveType(BlockScope scope) {
boolean expressionIsCast;
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 a02b59d849..616841fe48 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
@@ -8,6 +8,10 @@
*
* 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
@@ -275,10 +279,25 @@ public class WhileStatement extends Statement {
@Override
public void resolve(BlockScope scope) {
- TypeBinding type = this.condition.resolveTypeExpecting(scope, TypeBinding.BOOLEAN);
- this.condition.computeConversion(scope, type, type);
- if (this.action != null)
- this.action.resolve(scope);
+ if (this.condition.containsPatternVariable()) {
+ this.condition.collectPatternVariablesToScope(null, scope);
+ LocalVariableBinding[] patternVariablesInTrueScope = this.condition.getPatternVariablesWhenTrue();
+ LocalVariableBinding[] patternVariablesInFalseScope = this.condition.getPatternVariablesWhenFalse();
+
+ TypeBinding type = this.condition.resolveTypeExpecting(scope, TypeBinding.BOOLEAN);
+ this.condition.computeConversion(scope, type, type);
+ if (this.action != null) {
+ this.action.resolveWithPatternVariablesInScope(patternVariablesInTrueScope, scope);
+ this.action.injectPatternVariablesIfApplicable(patternVariablesInFalseScope, scope,
+ (statement) -> { return !statement.breaksOut(null);});
+ }
+ } else {
+ TypeBinding type = this.condition.resolveTypeExpecting(scope, TypeBinding.BOOLEAN);
+ this.condition.computeConversion(scope, type, type);
+ 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 34b0fc31f1..7b92ba33c3 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
@@ -8,6 +8,10 @@
*
* 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
@@ -477,9 +481,19 @@ public LocalDeclaration[] findLocalVariableDeclarations(int position) {
}
return null;
}
-
+private boolean isPatternVariableInScope(InvocationSite invocationSite, LocalVariableBinding variable) {
+ LocalVariableBinding[] patternVariablesInScope = invocationSite.getPatternVariablesWhenTrue();
+ if (patternVariablesInScope == null)
+ return false;
+ for (LocalVariableBinding v : patternVariablesInScope) {
+ if (v == variable) {
+ return true;
+ }
+ }
+ return false;
+}
@Override
-public LocalVariableBinding findVariable(char[] variableName) {
+public LocalVariableBinding findVariable(char[] variableName, InvocationSite invocationSite) {
int varLength = variableName.length;
for (int i = this.localIndex-1; i >= 0; i--) { // lookup backward to reach latest additions first
LocalVariableBinding local = this.locals[i];
@@ -495,8 +509,14 @@ public LocalVariableBinding findVariable(char[] variableName) {
if ((local.modifiers & ExtraCompilerModifiers.AccPatternVariable) == 0)
continue;
char[] localName;
- if ((localName = local.name).length == varLength && CharOperation.equals(localName, variableName))
+ if ((localName = local.name).length != varLength || !CharOperation.equals(localName, variableName))
+ continue;
+ if ((local.modifiers & ExtraCompilerModifiers.AccUnresolved) == 0) {
return local;
+ }
+ if (isPatternVariableInScope(invocationSite, local)) {
+ return local;
+ }
}
return null;
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/InvocationSite.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/InvocationSite.java
index afb5f22e0d..bf6657e908 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/InvocationSite.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/InvocationSite.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2019 IBM Corporation and others.
+ * Copyright (c) 2000, 2020 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
@@ -8,6 +8,10 @@
*
* 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 - Contribution for
@@ -40,6 +44,9 @@ public interface InvocationSite {
boolean receiverIsImplicitThis();
boolean checkingPotentialCompatibility();
void acceptPotentiallyCompatibleMethods(MethodBinding [] methods);
+ public default LocalVariableBinding[] getPatternVariablesWhenTrue() {
+ return null;
+ }
/** When inference for this invocationSite starts, get a fresh inference context, initialized from this site. */
InferenceContext18 freshInferenceContext(Scope scope);
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Scope.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Scope.java
index a328f9b517..b912fddefe 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Scope.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Scope.java
@@ -8,6 +8,10 @@
*
* 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
@@ -2034,8 +2038,7 @@ public abstract class Scope {
return typeBinding;
}
- public LocalVariableBinding findVariable(char[] variable) {
-
+ public LocalVariableBinding findVariable(char[] variable, InvocationSite invocationSite) {
return null;
}
@@ -2090,7 +2093,7 @@ public abstract class Scope {
//$FALL-THROUGH$ could duplicate the code below to save a cast - questionable optimization
case BLOCK_SCOPE :
- LocalVariableBinding variableBinding = scope.findVariable(name);
+ LocalVariableBinding variableBinding = scope.findVariable(name, invocationSite);
// looks in this scope only
if (variableBinding != null) {
if (foundField != null && foundField.isValidBinding())
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 1fe0b4a01b..a2ff3b4cd7 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
@@ -2114,20 +2114,12 @@ public void duplicateInitializationOfBlankFinalField(FieldBinding field, Referen
}
public void duplicateInitializationOfFinalLocal(LocalVariableBinding local, ASTNode location) {
String[] arguments = new String[] { new String(local.readableName())};
- if ((local.modifiers & ExtraCompilerModifiers.AccPatternVariable) == 0) {
- this.handle(
+ 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;
@@ -8820,25 +8812,14 @@ public void uninitializedNonNullField(FieldBinding field, ASTNode location) {
nodeSourceEnd(field, location));
}
public void uninitializedLocalVariable(LocalVariableBinding binding, ASTNode location, Scope scope) {
- if ((binding.modifiers & ExtraCompilerModifiers.AccPatternVariable) == 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));
-
- }
+ 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));
}
private boolean methodHasMissingSwitchDefault() {
MethodScope methodScope = null;

Back to the top