update jdt.core to I20210809-1800 for 4.21 M3
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/parser/CompletionParserTest2.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/parser/CompletionParserTest2.java
index 14f7784..7247ee2 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/parser/CompletionParserTest2.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/parser/CompletionParserTest2.java
@@ -7346,7 +7346,7 @@
 	String expectedCompletionNodeToString = "<CompleteOnName:zzz>";
 	String expectedParentNodeToString = "(1 == <CompleteOnName:zzz>)";
 	String completionIdentifier = "zzz";
-	String expectedReplacedSource = "(zzz)";
+	String expectedReplacedSource = "zzz";
 	String expectedUnitDisplayString =
 			"package p;\n" +
 			"public class X {\n" +
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/PatternMatching16Test.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/PatternMatching16Test.java
index 2b27609..f853c26 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/PatternMatching16Test.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/PatternMatching16Test.java
@@ -12,8 +12,11 @@
  *******************************************************************************/
 package org.eclipse.jdt.core.tests.compiler.regression;
 
+import java.io.IOException;
 import java.util.Map;
 
+import org.eclipse.jdt.core.util.ClassFileBytesDisassembler;
+import org.eclipse.jdt.core.util.ClassFormatException;
 import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
 
 import junit.framework.Test;
@@ -3876,4 +3879,89 @@
                 "true",
                 options);
     }
+    public void testBug575035() throws ClassFormatException, IOException {
+        Map<String, String> options = getCompilerOptions(false);
+    	String source =
+    			"import java.lang.annotation.ElementType;\n" +
+    			"import java.lang.annotation.Retention;\n" +
+    			"import java.lang.annotation.RetentionPolicy;\n" +
+    			"import java.lang.annotation.Target;\n" +
+    			" \n" +
+    			"public class Test {\n" +
+    			"    @Target({ ElementType.LOCAL_VARIABLE})\n" +
+    			"    @Retention(RetentionPolicy.RUNTIME)\n" +
+    			"    @interface Var {}\n" +
+    			"    @Target({ ElementType.TYPE_USE})\n" +
+    			"    @Retention(RetentionPolicy.RUNTIME)\n" +
+    			"    @interface Type {}\n" +
+    			"    public static void main(String[] args) {" +
+    			"        @Var @Type String y = \"OK: \";\n" +
+    			"        if (((Object)\"local\") instanceof @Var @Type String x) {\n" +
+    			"            System.out.println(y + x);\n" +
+    			"        }\n" +
+    		    "    }\n" +
+    			"}";
+    	String expectedOutput = ""
+    			+ "  // Method descriptor #15 ([Ljava/lang/String;)V\n"
+    			+ "  // Stack: 4, Locals: 4\n"
+    			+ "  public static void main(String[] args);\n"
+    			+ "     0  ldc <String \"OK: \"> [16]\n"
+    			+ "     2  astore_1 [y]\n"
+    			+ "     3  ldc <String \"local\"> [18]\n"
+    			+ "     5  astore_3 [ instanceOfPatternExpressionValue]\n"
+    			+ "     6  aload_3 [ instanceOfPatternExpressionValue]\n"
+    			+ "     7  instanceof String [20]\n"
+    			+ "    10  ifeq 50\n"
+    			+ "    13  aload_3 [ instanceOfPatternExpressionValue]\n"
+    			+ "    14  checkcast String [20]\n"
+    			+ "    17  dup\n"
+    			+ "    18  astore_2\n"
+    			+ "    19  aload_3\n"
+    			+ "    20  checkcast String [20]\n"
+    			+ "    23  if_acmpne 50\n"
+    			+ "    26  getstatic System.out : PrintStream [22]\n"
+    			+ "    29  new StringBuilder [28]\n"
+    			+ "    32  dup\n"
+    			+ "    33  aload_1 [y]\n"
+    			+ "    34  invokestatic String.valueOf(Object) : String [30]\n"
+    			+ "    37  invokespecial StringBuilder(String) [34]\n"
+    			+ "    40  aload_2 [x]\n"
+    			+ "    41  invokevirtual StringBuilder.append(String) : StringBuilder [37]\n"
+    			+ "    44  invokevirtual StringBuilder.toString() : String [41]\n"
+    			+ "    47  invokevirtual PrintStream.println(String) : void [45]\n"
+    			+ "    50  return\n"
+    			+ "      Line numbers:\n"
+    			+ "        [pc: 0, line: 13]\n"
+    			+ "        [pc: 3, line: 14]\n"
+    			+ "        [pc: 26, line: 15]\n"
+    			+ "        [pc: 50, line: 17]\n"
+    			+ "      Local variable table:\n"
+    			+ "        [pc: 0, pc: 51] local: args index: 0 type: String[]\n"
+    			+ "        [pc: 3, pc: 51] local: y index: 1 type: String\n"
+    			+ "        [pc: 26, pc: 50] local: x index: 2 type: String\n"
+    			+ "        [pc: 6, pc: 20] local:  instanceOfPatternExpressionValue index: 3 type: Object\n"
+    			+ "      Stack map table: number of frames 1\n"
+    			+ "        [pc: 50, append: {String}]\n"
+    			+ "    RuntimeVisibleTypeAnnotations: \n"
+    			+ "      #59 @Type(\n"
+    			+ "        target type = 0x40 LOCAL_VARIABLE\n"
+    			+ "        local variable entries:\n"
+    			+ "          [pc: 3, pc: 51] index: 1\n"
+    			+ "      )\n"
+    			+ "      #59 @Type(\n"
+    			+ "        target type = 0x40 LOCAL_VARIABLE\n"
+    			+ "        local variable entries:\n"
+    			+ "          [pc: 26, pc: 50] index: 2\n"
+    			+ "      )\n"
+    			+ "\n";
+    	checkClassFile("Test", source, expectedOutput, ClassFileBytesDisassembler.DETAILED | ClassFileBytesDisassembler.COMPACT);
+        runConformTest(
+                new String[] {
+                        "Test.java",
+                        source,
+                },
+                "OK: local",
+                options);
+
+    }
 }
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/util/AbstractCompilerTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/util/AbstractCompilerTest.java
index a705a2b..35b6bba 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/util/AbstractCompilerTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/util/AbstractCompilerTest.java
@@ -321,7 +321,11 @@
 			isJRE10Plus = isJRE11Plus || CompilerOptions.VERSION_10.equals(specVersion);
 			isJRE9Plus = isJRE10Plus || CompilerOptions.VERSION_9.equals(specVersion);
 			initReflectionVersion();
-			String compliances = System.getProperty("compliance");
+			String key = "compliance.jre." + specVersion;
+			String compliances = System.getProperty(key);
+			if (compliances == null) {
+				compliances = System.getProperty("compliance");
+			}
 			if (compliances != null) {
 				possibleComplianceLevels = 0;
 				for (String compliance : compliances.split(",")) {
diff --git a/org.eclipse.jdt.core.tests.compiler/test.xml b/org.eclipse.jdt.core.tests.compiler/test.xml
index 5ea814b..69a3341 100644
--- a/org.eclipse.jdt.core.tests.compiler/test.xml
+++ b/org.eclipse.jdt.core.tests.compiler/test.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 
 <!--
-    Copyright (c) 2002, 2014 IBM Corporation and others.
+    Copyright (c) 2002, 2021 IBM Corporation and others.
 
     This program and the accompanying materials
     are made available under the terms of the Eclipse Public License 2.0
@@ -57,6 +57,9 @@
       <property name="plugin-name" value="${plugin-name}"/>
       <property name="classname" 
                 value="org.eclipse.jdt.core.tests.compiler.regression.TestAll"/>
+      <property name="vmargs" 
+      	value="-Dcompliance.jre.11=1.8,9,10,11 -Dcompliance.jre.16=1.8,11,15,16 -Dcompliance.jre.17=1.8,11,16,17"
+      />
     </ant>
 
 	<antcall target="evaluation_tests"/>
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTStructuralPropertyTest.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTStructuralPropertyTest.java
index a937572..1136e84 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTStructuralPropertyTest.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTStructuralPropertyTest.java
@@ -447,9 +447,9 @@
 		}
 // {ObjectTeams: adapted for OT specific ASTNodes
 /* orig:
-		assertEquals("Wrong last known type", 104, hi); // last known one
+		assertEquals("Wrong last known type", 105, hi); // last known one
   :giro */
-		assertEquals("Wrong last known type", 120, hi); // last known one
+		assertEquals("Wrong last known type", 121, hi); // last known one
 // jwl}
 		assertEquals("Wrong number of distinct types",  hi, classes.size()); // all classes are distinct
 	}
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTTest.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTTest.java
index 4829bff..9048872 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTTest.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTTest.java
@@ -9501,6 +9501,7 @@
 			ASTNode.TEXT_BLOCK,
 			ASTNode.RECORD_DECLARATION,
 			ASTNode.PATTERN_INSTANCEOF_EXPRESSION,
+			ASTNode.MODULE_QUALIFIED_NAME,
 //{ObjectTeams:
 			ASTNode.METHOD_SPEC,
 			ASTNode.CALLIN_MAPPING_DECLARATION,
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompletionTests3.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompletionTests3.java
index 5c61ca4..d6b8dd6 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompletionTests3.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompletionTests3.java
@@ -922,6 +922,7 @@
 		int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length();
 		this.workingCopies[0].codeComplete(cursorLocation, requestor, this.wcOwner);
 		assertResults(
+				"for[KEYWORD]{for, null, null, for, null, 49}\n" +
 				"fooo[LOCAL_VARIABLE_REF]{fooo, null, Ljava.lang.String;, fooo, null, " + (R_DEFAULT + R_RESOLVED + R_INTERESTING + R_CASE + R_UNQUALIFIED + R_NON_RESTRICTED) + "}",
 				requestor.getResults());
 	} finally {
@@ -953,6 +954,7 @@
 		this.workingCopies[0].codeComplete(cursorLocation, requestor, this.wcOwner);
 		int relevance = R_DEFAULT + R_INTERESTING + R_RESOLVED + R_CASE + R_UNQUALIFIED + R_NON_RESTRICTED;
 		assertResults(
+				"Cast[TYPE_REF]{Cast, , LCast;, null, null, "+relevance+"}\n" +
 				"clone[METHOD_REF]{clone(), Ljava.lang.Object;, ()Ljava.lang.Object;, clone, null, " + relevance + "}\n" +
 				"equals[METHOD_REF]{equals(), Ljava.lang.Object;, (Ljava.lang.Object;)Z, equals, (obj), " + relevance + "}\n" +
 				"field[FIELD_REF]{field, LCast;, Ljava.lang.Object;, field, null, " + relevance + "}\n" +
@@ -996,7 +998,9 @@
 		int cursorLocation = str.indexOf(completeBefore);
 		this.workingCopies[0].codeComplete(cursorLocation, requestor, this.wcOwner);
 		int relevance = R_DEFAULT + R_INTERESTING + R_RESOLVED + R_CASE + R_UNQUALIFIED + R_NON_RESTRICTED;
+		int relevanceNoCase = R_DEFAULT + R_INTERESTING + R_RESOLVED + R_UNQUALIFIED + R_NON_RESTRICTED;
 		assertResults(
+				"Object[TYPE_REF]{Object, java.lang, Ljava.lang.Object;, null, null, "+relevanceNoCase+"}\n" +
 				"oArg[LOCAL_VARIABLE_REF]{oArg, null, Ljava.lang.Object;, oArg, null, "+relevance+"}\n" +
 				"oField[FIELD_REF]{oField, LCast;, Ljava.lang.Object;, oField, null, " + relevance + "}",
 				requestor.getResults());
@@ -1135,4 +1139,127 @@
 		deleteProject("P");
 	}
 }
+public void testBug574979() throws Exception {
+	try {
+		createJavaProject("P", new String[] {"src"}, new String[]{"JCL17_LIB"}, "bin", "1.7");
+		this.workingCopies = new ICompilationUnit[1];
+		this.workingCopies[0] = getWorkingCopy(
+			"/P/src/Bug.java",
+			"public class Bug {\n" +
+			"	void test (Object o) {\n" +
+			"		if (true) {\n" +
+			"			Str\n" +
+			"			((String) o).toCharArray();\n" +
+			"		}\n" +
+			"	}\n" +
+			"}\n");
+		CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true);
+		String str = this.workingCopies[0].getSource();
+		String completeAfter = "Str";
+		int cursorLocation = str.indexOf(completeAfter) + completeAfter.length();
+		this.workingCopies[0].codeComplete(cursorLocation, requestor, this.wcOwner);
+		int relevance = R_DEFAULT + R_INTERESTING + R_RESOLVED + R_CASE + R_UNQUALIFIED + R_NON_RESTRICTED;
+		assertResults(
+			"String[TYPE_REF]{String, java.lang, Ljava.lang.String;, null, null, "+relevance+"}",
+			requestor.getResults());
+	} finally {
+		deleteProject("P");
+	}
+}
+public void testBug575397a() throws Exception {
+	try {
+		createJavaProject("P", new String[] {"src"}, new String[]{"JCL11_LIB"}, "bin", "11");
+		this.workingCopies = new ICompilationUnit[1];
+		this.workingCopies[0] = getWorkingCopy(
+			"/P/src/ContentAssist.java",
+			"class Thread {\n" +
+			"	static void sleep(int millis) {}\n" +
+			"}\n" +
+			"public class ContentAssist {\n" +
+			"	protected void test() {\n" +
+			"		if (true) {\n" +
+			"			Thread.\n" +
+			"			someMethod();\n" +
+			"		}\n" +
+			"	}\n" +
+			"	void someMethod() { }\n" +
+			"}\n");
+		CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true);
+		String str = this.workingCopies[0].getSource();
+		String completeAfter = "Thread.";
+		int cursorLocation = str.indexOf(completeAfter) + completeAfter.length();
+		this.workingCopies[0].codeComplete(cursorLocation, requestor, this.wcOwner);
+		assertResults(
+			"sleep[METHOD_REF]{sleep(), LThread;, (I)V, sleep, (millis), 51}",
+			requestor.getResults());
+	} finally {
+		deleteProject("P");
+	}
+}
+public void testBug575397b() throws Exception {
+	try {
+		createJavaProject("P", new String[] {"src"}, new String[]{"JCL11_LIB"}, "bin", "11");
+		this.workingCopies = new ICompilationUnit[1];
+		this.workingCopies[0] = getWorkingCopy(
+			"/P/src/ContentAssist.java",
+			"class Thread {\n" +
+			"	static void sleep(int millis) {}\n" +
+			"	public enum State { NEW, BLOCKED }\n" +
+			"}\n" +
+			"public class ContentAssist {\n" +
+			"	protected void test() {\n" +
+			"		if (true) {\n" +
+			"			Thread.Sta\n" +
+			"			someMethod();\n" +
+			"		}\n" +
+			"	}\n" +
+			"	void someMethod() { }\n" +
+			"}\n");
+		CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true);
+		String str = this.workingCopies[0].getSource();
+		String completeAfter = "Thread.Sta";
+		int cursorLocation = str.indexOf(completeAfter) + completeAfter.length();
+		this.workingCopies[0].codeComplete(cursorLocation, requestor, this.wcOwner);
+		assertResults(
+			"Thread.State[TYPE_REF]{State, , LThread$State;, null, null, 49}",
+			requestor.getResults());
+	} finally {
+		deleteProject("P");
+	}
+}
+public void testBug575397c() throws Exception {
+	try {
+		createJavaProject("P", new String[] {"src"}, new String[]{"JCL11_LIB"}, "bin", "11");
+		this.workingCopies = new ICompilationUnit[1];
+		this.workingCopies[0] = getWorkingCopy(
+			"/P/src/ContentAssist.java",
+			"class Thread {\n" +
+			"	static void sleep(int millis) {}\n" +
+			"	public enum State { NEW, BLOCKED }\n" +
+			"}\n" +
+			"public class ContentAssist {\n" +
+			"	protected void test() {\n" +
+			"		if (true) {\n" +
+			"			Thread.State.\n" +
+			"			someMethod();\n" +
+			"		}\n" +
+			"	}\n" +
+			"	void someMethod() { }\n" +
+			"}\n");
+		CompletionTestsRequestor2 requestor = new CompletionTestsRequestor2(true);
+		String str = this.workingCopies[0].getSource();
+		String completeAfter = "Thread.State.";
+		int cursorLocation = str.indexOf(completeAfter) + completeAfter.length();
+		this.workingCopies[0].codeComplete(cursorLocation, requestor, this.wcOwner);
+		assertResults(
+			"serialVersionUID[FIELD_REF]{serialVersionUID, Ljava.lang.Enum<LThread$State;>;, J, serialVersionUID, null, 49}\n" +
+			"BLOCKED[FIELD_REF]{BLOCKED, LThread$State;, LThread$State;, BLOCKED, null, 51}\n" +
+			"NEW[FIELD_REF]{NEW, LThread$State;, LThread$State;, NEW, null, 51}\n" +
+			"valueOf[METHOD_REF]{valueOf(), LThread$State;, (Ljava.lang.String;)LThread$State;, valueOf, (arg0), 51}\n" +
+			"values[METHOD_REF]{values(), LThread$State;, ()[LThread$State;, values, null, 51}",
+			requestor.getResults());
+	} finally {
+		deleteProject("P");
+	}
+}
 }
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/MementoTests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/MementoTests.java
index 5711170..221adc1 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/MementoTests.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/MementoTests.java
@@ -77,7 +77,9 @@
 	return getEscapedPath(getExternalJCLPath().toString());
 }
 String getEscapedJrtJarPath() {
-	return getEscapedPath(System.getProperty("java.home")+"/lib/jrt-fs.jar");
+	String pathStr = System.getProperty("java.home")+"/lib/jrt-fs.jar";
+	String path = new Path(pathStr).toPortableString();
+	return getEscapedPath(path);
 }
 protected String getEscapedPath(String path) {
 	StringBuilder buffer = new StringBuilder();
@@ -875,8 +877,9 @@
 		String expectedIdentifier = "=Test/"+getEscapedJrtJarPath()+"`java.base"+attributesMemento; // for specific PFR (see below)
 		IModuleDescription module = project.findModule("java.base", null);
 		String moduleIdentifier = expectedIdentifier+"<'`java.base"; // PFR - PackageFragment - ModularClassFile - Module
-		assertEquals("Module mementos", moduleIdentifier, module.getHandleIdentifier());
-		IJavaElement module2 = JavaCore.create(module.getHandleIdentifier(), null);
+		String moduleHandleIdentifier = module.getHandleIdentifier();
+		assertEquals("Module mementos", moduleIdentifier, moduleHandleIdentifier);
+		IJavaElement module2 = JavaCore.create(moduleHandleIdentifier, null);
 		assertTrue("Module existence", module2.exists());
 		assertEquals("Module equivalence", module, module2);
 
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ResolveTests12To15.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ResolveTests12To15.java
index 4144c5c..9880b94 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ResolveTests12To15.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ResolveTests12To15.java
@@ -744,4 +744,35 @@
 		elements
 	);
 }
+public void testBug574697() throws JavaModelException {
+	this.workingCopies = new ICompilationUnit[2];
+	this.workingCopies[0] = getWorkingCopy(
+			"/Resolve/src/Test2.java",
+			"import java.util.List;\n" +
+			"import java.util.ArrayList;\n" +
+			"public class Test2 {\n" +
+			"    public String getGreeting() {\n" +
+			"        return \"foo\";\n" +
+			"    }\n" +
+			"    public static void main(String[] args) {\n" +
+			"        List<Integer> foo = new List<>() {\n" +
+			"            private void test() {\n" +
+			"                new Test2().getGreeting();\n" +
+			"            }\n" +
+			"        };\n" +
+			"    }\n" +
+			"}\n");
+
+	String str = this.workingCopies[0].getSource();
+	String selectAt = "getGreeting()";
+	String selection = "getGreeting";
+	int start = str.lastIndexOf(selectAt);
+	int length = selection.length();
+	IJavaElement[] elements = this.workingCopies[0].codeSelect(start, length, this.wcOwner);
+
+	assertElementsEqual(
+			"Unexpected elements",
+			"getGreeting() [in Test2 [in [Working copy] Test2.java [in <default> [in src [in Resolve]]]]]",
+			elements);
+}
 }
diff --git a/org.eclipse.jdt.core/.settings/.api_filters b/org.eclipse.jdt.core/.settings/.api_filters
index a820ef2..6e3a6d4 100644
--- a/org.eclipse.jdt.core/.settings/.api_filters
+++ b/org.eclipse.jdt.core/.settings/.api_filters
@@ -200,6 +200,15 @@
             </message_arguments>
         </filter>
     </resource>
+    <resource path="dom/org/eclipse/jdt/core/dom/ASTNode.java" type="org.eclipse.jdt.core.dom.ASTNode">
+        <filter comment="To fix the mistake and considering nodes added till 107 in BETA Branch" id="388194388">
+            <message_arguments>
+                <message_argument value="org.eclipse.jdt.core.dom.ASTNode"/>
+                <message_argument value="MODULE_QUALIFIED_NAME"/>
+                <message_argument value="103"/>
+            </message_arguments>
+        </filter>
+    </resource>
     <resource path="dom/org/eclipse/jdt/core/dom/Annotation.java" type="org.eclipse.jdt.core.dom.Annotation">
         <filter id="576725006">
             <message_arguments>
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/CompletionEngine.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/CompletionEngine.java
index 6c098b3..4a3550f 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/CompletionEngine.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/CompletionEngine.java
@@ -3360,6 +3360,7 @@
 			if (messageSend.nextIsCast) {
 				// optionalPrefix|((String) s) was mistaken as a messageSend(?). Treat like beginning of statement.
 				findVariablesAndMethods(this.completionToken, scope, messageSend, scope, false, false);
+				findTypesAndPackages(this.completionToken, scope, true, false, new ObjectVector());
 				return;
 			}
 
@@ -3819,6 +3820,17 @@
 				}
 			}
 		} else if (qualifiedBinding instanceof ReferenceBinding && !(qualifiedBinding instanceof TypeVariableBinding)) {
+			ReferenceBinding receiverType = (ReferenceBinding) qualifiedBinding;
+			if (astNodeParent instanceof LocalDeclaration && ref.nextToken == TerminalTokens.TokenNameLPAREN && !this.assistNodeIsConstructor) {
+				// the subsequent '(' makes the interpretation as LocalDeclaration illegal (unless it's "new prefix.token()").
+				// therefore we assume that "name(" (where name is LocalDeclaration.name) is the start of a new statement,
+				// and propose *everything* that can be referenced via the receiverType:
+				findMethods(this.completionToken, null, null, receiverType, scope, new ObjectVector(), true/*onlyStatic*/, false,
+						FakeInvocationSite, scope, false, false, false, null, null, null, false, null, -1, -1);
+				findFields(this.completionToken, receiverType, scope, new ObjectVector(), new ObjectVector(), true/*onlyStatic*/,
+						FakeInvocationSite, scope, false, false, null, null, null, false, null, -1, -1);
+				// fall through to propose member types
+			}
 			if (!this.requestor.isIgnored(CompletionProposal.TYPE_REF)) {
 				setSourceAndTokenRange((int) (completionPosition >>> 32), (int) completionPosition);
 
@@ -3827,7 +3839,7 @@
 				if (this.assistNodeIsException && astNodeParent instanceof TryStatement) {
 					findExceptionFromTryStatement(
 							this.completionToken,
-							(ReferenceBinding)qualifiedBinding,
+							receiverType,
 							scope.enclosingSourceType(),
 							(BlockScope)scope,
 							typesFound);
@@ -3837,7 +3849,7 @@
 
 				findMemberTypes(
 					this.completionToken,
-					(ReferenceBinding) qualifiedBinding,
+					receiverType,
 					scope,
 					scope.enclosingSourceType(),
 					false,
@@ -4045,8 +4057,15 @@
 			if (receiverType != null && receiverType.isValidBinding()) {
 				findVariablesAndMethods(this.completionToken, scope, FakeInvocationSite, scope, false, false);
 			}
+			// ... or a keyword (possibly starting a new statement):
+			if (!this.requestor.isIgnored(CompletionProposal.KEYWORD)) {
+				if (this.completionToken != null && this.completionToken.length != 0) {
+					findKeywords(this.completionToken, singleRef.possibleKeywords, false, false);
+				} else {
+					findTrueOrFalseKeywords(singleRef.possibleKeywords);
+				}
+			}
 		}
-
 	}
 
 	private void completionOnProvidesInterfacesSingleTypeReference(ASTNode astNode, ASTNode astNodeParent, Binding qualifiedBinding, Scope scope) {
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/SelectionEngine.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/SelectionEngine.java
index a48a549..90d7bdf 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/SelectionEngine.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/SelectionEngine.java
@@ -51,6 +51,7 @@
 import org.eclipse.jdt.internal.codeassist.select.SelectionOnPackageVisibilityReference;
 import org.eclipse.jdt.internal.codeassist.select.SelectionOnImportReference;
 import org.eclipse.jdt.internal.codeassist.select.SelectionOnLocalName;
+import org.eclipse.jdt.internal.codeassist.select.SelectionOnMessageSend;
 import org.eclipse.jdt.internal.codeassist.select.SelectionOnPackageReference;
 import org.eclipse.jdt.internal.codeassist.select.SelectionOnQualifiedTypeReference;
 import org.eclipse.jdt.internal.codeassist.select.SelectionOnSingleTypeReference;
@@ -67,6 +68,7 @@
 import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.ImportReference;
 import org.eclipse.jdt.internal.compiler.ast.LocalDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.MessageSend;
 import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.ModuleDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.PackageVisibilityStatement;
@@ -1634,6 +1636,12 @@
 		// for traversing the parse tree, the parser assist identifier is necessary for identitiy checks
 		final char[] assistIdentifier = getParser().assistIdentifier();
 		if (assistIdentifier == null) return;
+		final BlockScope nodeScope;
+		if (node instanceof AbstractMethodDeclaration) {
+			nodeScope = ((AbstractMethodDeclaration)node).scope;
+		} else {
+			nodeScope = null;
+		}
 
 		class Visitor extends ASTVisitor {
 			@Override
@@ -1699,6 +1707,19 @@
 				return true;
 			}
 			@Override
+			public boolean visit(MessageSend messageSend, BlockScope scope) {
+				if (messageSend.selector == assistIdentifier && messageSend instanceof SelectionOnMessageSend) {
+					if (scope == null) {
+						scope = nodeScope;
+					}
+					if (scope != null) {
+						messageSend.resolve(scope);
+						throw new SelectionNodeFound(messageSend.binding);
+					}
+				}
+				return true;
+			}
+			@Override
 			public boolean visit(
 		    		Argument argument, BlockScope scope) {
 				if (argument.type instanceof SingleTypeReference && ((SingleTypeReference)argument.type).token == assistIdentifier)
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnQualifiedTypeReference.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnQualifiedTypeReference.java
index c69faaf..4ab064b 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnQualifiedTypeReference.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnQualifiedTypeReference.java
@@ -40,6 +40,7 @@
 	public char[] completionIdentifier;
 
 	public boolean isConstructorType;
+	public int nextToken;
 
 public CompletionOnQualifiedTypeReference(char[][] previousIdentifiers, char[] completionIdentifier, long[] positions) {
 	this(previousIdentifiers, completionIdentifier, positions, K_TYPE);
@@ -49,6 +50,10 @@
 	this.completionIdentifier = completionIdentifier;
 	this.kind = kind;
 }
+public CompletionOnQualifiedTypeReference(char[][] previousIdentifiers, char[] assistName, long[] positions, int kind, int nextToken) {
+	this(previousIdentifiers, assistName, positions, kind);
+	this.nextToken = nextToken;
+}
 @Override
 public void aboutToResolve(Scope scope) {
 	getTypeBinding(scope);
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnSingleTypeReference.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnSingleTypeReference.java
index 6b182e9..5f820f4 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnSingleTypeReference.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnSingleTypeReference.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2012 IBM Corporation and others.
+ * Copyright (c) 2000, 2021 IBM Corporation and others.
  *
  * This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License 2.0
@@ -43,6 +43,8 @@
 public boolean isLiftingRoleType;
 // SH}
 public CompletionOnFieldType fieldTypeCompletionNode;
+public char[][] possibleKeywords;
+public boolean canBeExplicitConstructor;
 
 public CompletionOnSingleTypeReference(char[] source, long pos) {
 	this(source, pos, K_TYPE);
@@ -52,6 +54,11 @@
 	this.isCompletionNode = true;
 	this.kind = kind;
 }
+public CompletionOnSingleTypeReference(char[] assistName, long position, char[][] keywords, boolean canBeSuperCall) {
+	this(assistName, position);
+	this.possibleKeywords = keywords;
+	this.canBeExplicitConstructor = canBeSuperCall;
+}
 @Override
 public void aboutToResolve(Scope scope) {
 	getTypeBinding(scope);
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionParser.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionParser.java
index edfd730..5206f08 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionParser.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionParser.java
@@ -20,6 +20,8 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.codeassist.complete;
 
+import java.util.ArrayList;
+
 /*
  * Parser able to build specific completion parse nodes, given a cursorLocation.
  *
@@ -31,6 +33,7 @@
  */
 
 import java.util.HashSet;
+import java.util.List;
 
 import org.eclipse.core.runtime.IProgressMonitor;
 import org.eclipse.jdt.internal.compiler.*;
@@ -1973,7 +1976,6 @@
 	}
 	return false;
 }
-
 /**
  * Checks if the completion is on a member access (i.e. in an identifier following a dot).
  * Returns whether we found a completion node.
@@ -5381,7 +5383,7 @@
 		if (isAfterWithClause()) return new CompletionOnProvidesImplementationsQualifiedTypeReference(previousIdentifiers, assistName, positions);
 		return new CompletionOnProvidesInterfacesQualifiedTypeReference(previousIdentifiers, assistName, positions);
 	}
-	return new CompletionOnQualifiedTypeReference(previousIdentifiers,	assistName,	positions);
+	return null;
 }
 @Override
 public TypeReference createQualifiedAssistTypeReference(char[][] previousIdentifiers, char[] assistName, long[] positions){
@@ -5407,10 +5409,14 @@
 					positions,
 					CompletionOnQualifiedTypeReference.K_INTERFACE);
 		default :
-			return checkAndCreateModuleQualifiedAssistTypeReference(
+			TypeReference ref = checkAndCreateModuleQualifiedAssistTypeReference(
 					previousIdentifiers,
 					assistName,
 					positions);
+			if (ref != null)
+				return ref;
+			return new CompletionOnQualifiedTypeReference(previousIdentifiers, assistName, positions,
+					CompletionOnQualifiedTypeReference.K_TYPE, this.currentToken);
 	}
 }
 @Override
@@ -5485,130 +5491,9 @@
 			&& topKnownElementInfo(COMPLETION_OR_ASSIST_PARSER) == SWITCH) {
 			return new CompletionOnKeyword3(assistName, position, new char[][]{Keywords.CASE, Keywords.DEFAULT}, false);
 		} else {
-			char[][] keywords = new char[Keywords.COUNT][];
-			int count = 0;
-
-			if((this.lastModifiers & ClassFileConstants.AccStatic) == 0) {
-				keywords[count++]= Keywords.SUPER;
-				keywords[count++]= Keywords.THIS;
-//{ObjectTeams: OT specific keyword:
-				keywords[count++]= Keywords.TSUPER;
-// SH}
-			}
-			keywords[count++]= Keywords.NEW;
-			// https://bugs.eclipse.org/bugs/show_bug.cgi?id=269493: Keywords are not proposed in a for
-			// loop without block. Completion while at K_CONTROL_STATEMENT_DELIMITER case needs to handled
-			// similar to the K_BLOCK_DELIMITER with minor differences.
-			if(kind == K_BLOCK_DELIMITER || kind == K_CONTROL_STATEMENT_DELIMITER || kind == K_LAMBDA_EXPRESSION_DELIMITER
-					|| kind == K_SWITCH_EXPRESSION_DELIMITTER) {
-				if(this.canBeExplicitConstructor == YES) {
-					canBeExplicitConstructorCall = true;
-				}
-				if (this.options.complianceLevel >= ClassFileConstants.JDK1_4) {
-					keywords[count++]= Keywords.ASSERT;
-				}
-				keywords[count++]= Keywords.DO;
-				keywords[count++]= Keywords.FOR;
-				keywords[count++]= Keywords.IF;
-				keywords[count++]= Keywords.RETURN;
-				keywords[count++]= Keywords.SWITCH;
-				keywords[count++]= Keywords.SYNCHRONIZED;
-				keywords[count++]= Keywords.THROW;
-				keywords[count++]= Keywords.TRY;
-				keywords[count++]= Keywords.WHILE;
-//{ObjectTeams: OT specific keywords/modifiers
-				// within a block only a restricted set is allowed:
-				// (note that CLASS below refers to local classes!)
-				keywords[count++]= Keywords.WITHIN;
-				keywords[count++]= Keywords.BASE;
-//gbr}
-				keywords[count++]= Keywords.FINAL;
-				keywords[count++]= Keywords.CLASS;
-				if (this.options.complianceLevel >= ClassFileConstants.JDK10) {
-					keywords[count++]= Keywords.VAR;
-				}
-				if (this.options.complianceLevel >= ClassFileConstants.JDK16) {
-					keywords[count++]= Keywords.INTERFACE;
-					keywords[count++]= Keywords.ENUM;
-				}
-
-				if(this.previousKind == K_BLOCK_DELIMITER) {
-					switch (this.previousInfo) {
-						case IF :
-							keywords[count++]= Keywords.ELSE;
-							break;
-						case CATCH :
-							keywords[count++]= Keywords.CATCH;
-							keywords[count++]= Keywords.FINALLY;
-							break;
-					}
-				} else if(this.previousKind == K_CONTROL_STATEMENT_DELIMITER && this.previousInfo == IF) {
-					keywords[count++]= Keywords.ELSE;
-				}
-				if(isInsideLoop()) {
-					keywords[count++]= Keywords.CONTINUE;
-				}
-				if(isInsideBreakable()) {
-					keywords[count++]= Keywords.BREAK;
-				}
-				if(isInsideSwitch()) {
-					keywords[count++]= Keywords.YIELD;
-				}
-//{ObjectTeams: keywords in parameter mapping:
-			} else if (kind == K_BETWEEN_WITH_AND_RIGHT_PAREN) {
-					keywords[count++] = Keywords.BASE;
-					keywords[count++] = Keywords.RESULT;
-// SH}
-			} else if (kind == K_BETWEEN_FOR_AND_RIGHT_PAREN) {
-				if (this.options.complianceLevel >= ClassFileConstants.JDK10) {
-					keywords[count++]= Keywords.VAR;
-				}
-			} else if(kind != K_BETWEEN_CASE_AND_COLON && kind != K_BETWEEN_DEFAULT_AND_COLON) {
-				if (kind == K_LOCAL_INITIALIZER_DELIMITER && this.options.complianceLevel >= ClassFileConstants.JDK11) {
-					keywords[count++]= Keywords.VAR;
-				}
-				if (kind == K_SELECTOR_QUALIFIER && this.options.complianceLevel >= ClassFileConstants.JDK12) {
-					keywords[count++] = Keywords.SWITCH;
-				}
-				keywords[count++]= Keywords.TRUE;
-				keywords[count++]= Keywords.FALSE;
-				keywords[count++]= Keywords.NULL;
-				if (kind == K_YIELD_KEYWORD) {
-					keywords[count++]= Keywords.YIELD;
-				}
-				if(kind == K_SWITCH_LABEL) {
-					if(topKnownElementInfo(COMPLETION_OR_ASSIST_PARSER) != DEFAULT) {
-						keywords[count++]= Keywords.DEFAULT;
-					}
-					keywords[count++]= Keywords.BREAK;
-					keywords[count++]= Keywords.CASE;
-					keywords[count++]= Keywords.YIELD;
-					if (this.options.complianceLevel >= ClassFileConstants.JDK1_4) {
-						keywords[count++]= Keywords.ASSERT;
-					}
-					keywords[count++]= Keywords.DO;
-					keywords[count++]= Keywords.FOR;
-					keywords[count++]= Keywords.IF;
-					keywords[count++]= Keywords.RETURN;
-					keywords[count++]= Keywords.SWITCH;
-					keywords[count++]= Keywords.SYNCHRONIZED;
-					keywords[count++]= Keywords.THROW;
-					keywords[count++]= Keywords.TRY;
-					keywords[count++]= Keywords.WHILE;
-
-					keywords[count++]= Keywords.FINAL;
-					keywords[count++]= Keywords.CLASS;
-
-					if (this.options.complianceLevel >= ClassFileConstants.JDK10) {
-						keywords[count++]= Keywords.VAR;
-					}
-					if(isInsideLoop()) {
-						keywords[count++]= Keywords.CONTINUE;
-					}
-				}
-			}
-			System.arraycopy(keywords, 0 , keywords = new char[count][], 0, count);
-
+			List<char[]> keywordsList = new ArrayList<>(Keywords.COUNT);
+			canBeExplicitConstructorCall = computeKeywords(kind, keywordsList);
+			char[][] keywords = keywordsList.toArray(char[][]::new);
 			return new CompletionOnSingleNameReference(assistName, position, keywords, canBeExplicitConstructorCall, isInsideAttributeValue()
 //{ObjectTeams: isBaseAccess? isTSuperAccess?
 					, (this.invocationType == BASE_RECEIVER), (this.invocationType == TSUPER_RECEIVER)
@@ -5617,13 +5502,140 @@
 		}
 	}
 }
+boolean computeKeywords(int kind, List<char[]> keywords) {
+	boolean canBeExplicitConstructorCall = false;
+
+	if((this.lastModifiers & ClassFileConstants.AccStatic) == 0) {
+		keywords.add(Keywords.SUPER);
+		keywords.add(Keywords.THIS);
+//{ObjectTeams: OT specific keyword:
+		keywords.add(Keywords.TSUPER);
+//SH}
+	}
+	keywords.add(Keywords.NEW);
+	// https://bugs.eclipse.org/bugs/show_bug.cgi?id=269493: Keywords are not proposed in a for
+	// loop without block. Completion while at K_CONTROL_STATEMENT_DELIMITER case needs to handled
+	// similar to the K_BLOCK_DELIMITER with minor differences.
+	if(kind == K_BLOCK_DELIMITER || kind == K_CONTROL_STATEMENT_DELIMITER || kind == K_LAMBDA_EXPRESSION_DELIMITER
+			|| kind == K_SWITCH_EXPRESSION_DELIMITTER) {
+		if(this.canBeExplicitConstructor == YES) {
+			canBeExplicitConstructorCall = true;
+		}
+		if (this.options.complianceLevel >= ClassFileConstants.JDK1_4) {
+			keywords.add(Keywords.ASSERT);
+		}
+		keywords.add(Keywords.DO);
+		keywords.add(Keywords.FOR);
+		keywords.add(Keywords.IF);
+		keywords.add(Keywords.RETURN);
+		keywords.add(Keywords.SWITCH);
+		keywords.add(Keywords.SYNCHRONIZED);
+		keywords.add(Keywords.THROW);
+		keywords.add(Keywords.TRY);
+		keywords.add(Keywords.WHILE);
+//{ObjectTeams: OT specific keywords/modifiers
+		// within a block only a restricted set is allowed:
+		// (note that CLASS below refers to local classes!)
+		keywords.add(Keywords.WITHIN);
+		keywords.add(Keywords.BASE);
+//gbr}
+
+		keywords.add(Keywords.FINAL);
+		keywords.add(Keywords.CLASS);
+		if (this.options.complianceLevel >= ClassFileConstants.JDK10) {
+			keywords.add(Keywords.VAR);
+		}
+		if (this.options.complianceLevel >= ClassFileConstants.JDK16) {
+			keywords.add(Keywords.INTERFACE);
+			keywords.add(Keywords.ENUM);
+		}
+
+		if(this.previousKind == K_BLOCK_DELIMITER) {
+			switch (this.previousInfo) {
+				case IF :
+					keywords.add(Keywords.ELSE);
+					break;
+				case CATCH :
+					keywords.add(Keywords.CATCH);
+					keywords.add(Keywords.FINALLY);
+					break;
+			}
+		} else if(this.previousKind == K_CONTROL_STATEMENT_DELIMITER && this.previousInfo == IF) {
+			keywords.add(Keywords.ELSE);
+		}
+		if(isInsideLoop()) {
+			keywords.add(Keywords.CONTINUE);
+		}
+		if(isInsideBreakable()) {
+			keywords.add(Keywords.BREAK);
+		}
+		if(isInsideSwitch()) {
+			keywords.add(Keywords.YIELD);
+		}
+		//{ObjectTeams: keywords in parameter mapping:
+	} else if (kind == K_BETWEEN_WITH_AND_RIGHT_PAREN) {
+		keywords.add(Keywords.BASE);
+		keywords.add(Keywords.RESULT);
+//SH}
+	} else if (kind == K_BETWEEN_FOR_AND_RIGHT_PAREN) {
+		if (this.options.complianceLevel >= ClassFileConstants.JDK10) {
+			keywords.add(Keywords.VAR);
+		}
+	} else if(kind != K_BETWEEN_CASE_AND_COLON && kind != K_BETWEEN_DEFAULT_AND_COLON) {
+		if (kind == K_LOCAL_INITIALIZER_DELIMITER && this.options.complianceLevel >= ClassFileConstants.JDK11) {
+			keywords.add(Keywords.VAR);
+		}
+		if (kind == K_SELECTOR_QUALIFIER && this.options.complianceLevel >= ClassFileConstants.JDK12) {
+			keywords.add(Keywords.SWITCH);
+		}
+		keywords.add(Keywords.TRUE);
+		keywords.add(Keywords.FALSE);
+		keywords.add(Keywords.NULL);
+		if (kind == K_YIELD_KEYWORD) {
+			keywords.add(Keywords.YIELD);
+		}
+		if(kind == K_SWITCH_LABEL) {
+			if(topKnownElementInfo(COMPLETION_OR_ASSIST_PARSER) != DEFAULT) {
+				keywords.add(Keywords.DEFAULT);
+			}
+			keywords.add(Keywords.BREAK);
+			keywords.add(Keywords.CASE);
+			keywords.add(Keywords.YIELD);
+			if (this.options.complianceLevel >= ClassFileConstants.JDK1_4) {
+				keywords.add(Keywords.ASSERT);
+			}
+			keywords.add(Keywords.DO);
+			keywords.add(Keywords.FOR);
+			keywords.add(Keywords.IF);
+			keywords.add(Keywords.RETURN);
+			keywords.add(Keywords.SWITCH);
+			keywords.add(Keywords.SYNCHRONIZED);
+			keywords.add(Keywords.THROW);
+			keywords.add(Keywords.TRY);
+			keywords.add(Keywords.WHILE);
+
+			keywords.add(Keywords.FINAL);
+			keywords.add(Keywords.CLASS);
+
+			if (this.options.complianceLevel >= ClassFileConstants.JDK10) {
+				keywords.add(Keywords.VAR);
+			}
+			if(isInsideLoop()) {
+				keywords.add(Keywords.CONTINUE);
+			}
+		}
+	}
+	return canBeExplicitConstructorCall;
+}
 private TypeReference checkAndCreateModuleSingleAssistTypeReference(char[] assistName, long position) {
 	if (isInUsesStatement()) return new CompletionOnUsesSingleTypeReference(assistName, position);
 	if (isInProvidesStatement()) {
 		if (isAfterWithClause()) return new CompletionOnProvidesImplementationsSingleTypeReference(assistName, position);
 		return new CompletionOnProvidesInterfacesSingleTypeReference(assistName, position);
 	}
-	return new CompletionOnSingleTypeReference(assistName,position);
+	List<char[]> keywords = new ArrayList<>(Keywords.COUNT);
+	boolean canBeCtorCall = computeKeywords(topKnownElementKind(COMPLETION_OR_ASSIST_PARSER), keywords);
+	return new CompletionOnSingleTypeReference(assistName,position, keywords.toArray(char[][]::new), canBeCtorCall);
 }
 @Override
 public TypeReference createSingleAssistTypeReference(char[] assistName, long position) {
@@ -5832,6 +5844,14 @@
 	return ref;
 }
 @Override
+protected void updateSourcePosition(Expression exp) {
+	// handles total positions of parenthesized expressions, but don't extend position of the assist node:
+	if (exp == this.assistNode)
+		this.intPtr -= 2;
+	else
+		super.updateSourcePosition(exp);
+}
+@Override
 protected void consumePostfixExpression() {
 	// PostfixExpression ::= Name
 	if (topKnownElementKind(COMPLETION_OR_ASSIST_PARSER) != K_YIELD_KEYWORD) {
@@ -6509,7 +6529,6 @@
 
 	recoveryExitFromVariable();
 }
-
 @Override
 protected CompilationUnitDeclaration endParse(int act) {
 	CompilationUnitDeclaration cud = super.endParse(act);
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/Parser.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/Parser.java
index 7abe92e..5292e0d 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/Parser.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/Parser.java
@@ -5600,6 +5600,9 @@
 	this.identifierLengthPtr--;
 
 	local.declarationSourceStart = type.sourceStart;
+	// Move annotations from type reference to LocalDeclaration
+	local.annotations = type.annotations != null && type.annotations.length > 0 ? type.annotations[0] : null;
+	type.annotations = null;
 	local.type = type;
 	problemReporter().validateJavaFeatureSupport(JavaFeature.PATTERN_MATCHING_IN_INSTANCEOF, type.sourceStart, local.declarationEnd);
 	local.modifiers |= ClassFileConstants.AccFinal;
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTNode.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTNode.java
index e7f57e4..9e096c7 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTNode.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTNode.java
@@ -989,15 +989,6 @@
 	 */
 	public static final int RECORD_DECLARATION = 103;
 
-
-	/**
-	 * Node type constant indicating a node of type
-	 * <code>ModuleQualifiedName</code>.
-	 * @see ModuleQualifiedName
-	 * @since 3.24
-	 */
-	public static final int MODULE_QUALIFIED_NAME = 103;
-
 	/**
 	 * Node type constant indicating a node of type
 	 * <code>PatternInstanceofExpression</code>.
@@ -1006,8 +997,16 @@
 	 */
 	public static final int PATTERN_INSTANCEOF_EXPRESSION = 104;
 
+	/**
+	 * Node type constant indicating a node of type
+	 * <code>ModuleQualifiedName</code>.
+	 * @see ModuleQualifiedName
+	 * @since 3.24
+	 */
+	public static final int MODULE_QUALIFIED_NAME = 105;
+
 //{ObjectTeams: required OT specific node type constants added
-	private static final int LAST_JDT = 104;
+	private static final int LAST_JDT = 105;
 	/**
 	 * Node type constant indicating a node of type
 	 * <code>MethodSpec</code>.
@@ -1222,6 +1221,8 @@
 				return ModuleDeclaration.class;
 			case MODULE_MODIFIER :
 				return ModuleModifier.class;
+			case MODULE_QUALIFIED_NAME :
+				return ModuleQualifiedName.class;
 			case NAME_QUALIFIED_TYPE :
 				return NameQualifiedType.class;
 			case NORMAL_ANNOTATION :
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaCore.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaCore.java
index b45edff..a16a6c2 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaCore.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaCore.java
@@ -5266,7 +5266,7 @@
 		return new ClasspathEntry(
 			IPackageFragmentRoot.K_BINARY,
 			IClasspathEntry.CPE_LIBRARY,
-			hasDotDot ? path : JavaProject.canonicalizedPath(path),
+			hasDotDot ? path : JavaProject.createPackageFragementKey(path),
 			ClasspathEntry.INCLUDE_ALL, // inclusion patterns
 			ClasspathEntry.EXCLUDE_NONE, // exclusion patterns
 			sourceAttachmentPath,
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DeltaProcessor.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DeltaProcessor.java
index dead751..c10d6ce 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DeltaProcessor.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DeltaProcessor.java
@@ -139,7 +139,7 @@
 			if (target instanceof IResource) {
 				tRoot = this.project.getPackageFragmentRoot((IResource)target, this.rootPath, this.extraAttributes);
 			} else {
-				IPath canonicalizedPath = JavaProject.canonicalizedPath(new Path(this.rootPath.toOSString()));
+				IPath canonicalizedPath = JavaProject.createPackageFragementKey(new Path(this.rootPath.toOSString()));
 				tRoot = this.project.getPackageFragmentRoot0(canonicalizedPath, this.extraAttributes);
 			}
 			return tRoot;
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaModelManager.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaModelManager.java
index 9c568c3..9fbda9f 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaModelManager.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaModelManager.java
@@ -148,7 +148,6 @@
 import org.eclipse.jdt.internal.core.search.JavaWorkspaceScope;
 import org.eclipse.jdt.internal.core.search.indexing.IndexManager;
 import org.eclipse.jdt.internal.core.search.processing.IJob;
-import org.eclipse.jdt.internal.core.search.processing.JobManager;
 import org.eclipse.jdt.internal.core.util.HashtableOfArrayToObject;
 import org.eclipse.jdt.internal.core.util.LRUCache;
 import org.eclipse.jdt.internal.core.util.Messages;
@@ -187,7 +186,7 @@
 	private static final String ASSUMED_EXTERNAL_FILES_CACHE = "assumedExternalFilesCache";  //$NON-NLS-1$
 
 	public static enum ArchiveValidity {
-		BAD_FORMAT, UNABLE_TO_READ, FILE_NOT_FOUND, VALID;
+		INVALID, VALID;
 
 		public boolean isValid() {
 			return this == VALID;
@@ -1335,7 +1334,7 @@
 		}
 
 		public synchronized ClasspathChange resetResolvedClasspath() {
-			// clear non-chaining jars cache and invalid jars cache
+			// clear non-chaining jars cache and external jars cache
 			JavaModelManager.getJavaModelManager().resetClasspathListCache();
 
 			// null out resolved information
@@ -1627,11 +1626,10 @@
 	}
 
 	/*
-	 * A map of IPaths for jars that are known to be invalid (such as not being in a valid/known format), to an eviction timestamp.
-	 * Synchronize on invalidArchivesMutex before accessing.
+	 * A map of IPaths for jars with known validity (such as being in a valid/known format or not), to an eviction timestamp.
+	 * Synchronize on invalidArchives before accessing.
 	 */
 	private final Map<IPath, InvalidArchiveInfo> invalidArchives = new HashMap<>();
-	private final Object invalidArchivesMutex = new Object();
 
 	/*
 	 * A set of IPaths for files that are known to be external to the workspace.
@@ -1803,9 +1801,9 @@
 
 	public void addInvalidArchive(IPath path, ArchiveValidity reason) {
 		if (DEBUG_INVALID_ARCHIVES) {
-			System.out.println("Invalid JAR cache: adding " + path + ", reason: " + reason);  //$NON-NLS-1$//$NON-NLS-2$
+			System.out.println("JAR cache: adding " + reason + " " + path);  //$NON-NLS-1$//$NON-NLS-2$
 		}
-		synchronized (this.invalidArchivesMutex) {
+		synchronized (this.invalidArchives) {
 			this.invalidArchives.put(path, new InvalidArchiveInfo(System.currentTimeMillis() + INVALID_ARCHIVE_TTL_MILLISECONDS, reason));
 		}
 	}
@@ -1879,7 +1877,7 @@
 				SourceRangeVerifier.DEBUG |= SourceRangeVerifier.DEBUG_THROW;
 				RewriteEventStore.DEBUG = debug && options.getBooleanOption(DOM_REWRITE_DEBUG, false);
 				TypeHierarchy.DEBUG = debug && options.getBooleanOption(HIERARCHY_DEBUG, false);
-				JobManager.VERBOSE = debug && options.getBooleanOption(INDEX_MANAGER_DEBUG, false);
+//				JobManager.VERBOSE = debug && options.getBooleanOption(INDEX_MANAGER_DEBUG, false);
 				IndexManager.DEBUG = debug && options.getBooleanOption(INDEX_MANAGER_ADVANCED_DEBUG, false);
 				JavaModelManager.DEBUG_CLASSPATH = debug && options.getBooleanOption(JAVAMODEL_CLASSPATH, false);
 				JavaModelManager.DEBUG_INVALID_ARCHIVES = debug && options.getBooleanOption(JAVAMODEL_INVALID_ARCHIVES, false);
@@ -2850,7 +2848,9 @@
 		if (isJrt(path)) {
 			return;
 		}
-		throwExceptionIfArchiveInvalid(path);
+		if (isArchiveStateKnownToBeValid(path)) {
+			return; // known to be valid
+		}
 		ZipFile file = getZipFile(path);
 		closeZipFile(file);
 	}
@@ -2884,7 +2884,7 @@
 
 	public ZipFile getZipFile(IPath path, boolean checkInvalidArchiveCache) throws CoreException {
 		if (checkInvalidArchiveCache) {
-			throwExceptionIfArchiveInvalid(path);
+			isArchiveStateKnownToBeValid(path);
 		}
 		ZipCache zipCache;
 		ZipFile zipFile;
@@ -2905,17 +2905,11 @@
 			if (zipCache != null) {
 				zipCache.setCache(path, zipFile);
 			}
+			addInvalidArchive(path, ArchiveValidity.VALID); // remember its valid
 			return zipFile;
 		} catch (IOException e) {
-			ArchiveValidity reason;
-
-			if (e instanceof ZipException) {
-				reason = ArchiveValidity.BAD_FORMAT;
-			} else if (e instanceof FileNotFoundException) {
-				reason = ArchiveValidity.FILE_NOT_FOUND;
-			} else {
-				reason = ArchiveValidity.UNABLE_TO_READ;
-			}
+			// file may exist but for some reason is inaccessible
+			ArchiveValidity reason=ArchiveValidity.INVALID;
 			addInvalidArchive(path, reason);
 			throw new CoreException(new Status(IStatus.ERROR, JavaCore.PLUGIN_ID, -1, Messages.status_IOException, e));
 		}
@@ -2941,18 +2935,12 @@
 		return localFile;
 	}
 
-	private void throwExceptionIfArchiveInvalid(IPath path) throws CoreException {
+	private boolean isArchiveStateKnownToBeValid(IPath path) throws CoreException {
 		ArchiveValidity validity = getArchiveValidity(path);
-		IOException reason;
-		switch (validity) {
-			case BAD_FORMAT: reason = new ZipException("Bad format in archive: " + path); break; //$NON-NLS-1$
-			case FILE_NOT_FOUND: reason = new FileNotFoundException("Archive not found for path: " + path); break; //$NON-NLS-1$
-			case UNABLE_TO_READ: reason = new IOException("Unable to read archive: " + path); break; //$NON-NLS-1$
-			default: reason = null;
+		if (validity == null || validity == ArchiveValidity.INVALID) {
+			return false; // chance the file has become accessible/readable now.
 		}
-		if (reason != null) {
-			throw new CoreException(new Status(IStatus.ERROR, JavaCore.PLUGIN_ID, -1, Messages.status_IOException, reason));
-		}
+		return true;
 	}
 
 	/*
@@ -3408,18 +3396,23 @@
 
 	public ArchiveValidity getArchiveValidity(IPath path) {
 		InvalidArchiveInfo invalidArchiveInfo;
-		synchronized (this.invalidArchivesMutex) {
+		synchronized (this.invalidArchives) {
 			invalidArchiveInfo = this.invalidArchives.get(path);
 		}
-		if (invalidArchiveInfo == null)
-			return ArchiveValidity.VALID;
+		if (invalidArchiveInfo == null) {
+			if (DEBUG_INVALID_ARCHIVES) {
+				System.out.println("JAR cache: UNKNOWN validity for " + path);  //$NON-NLS-1$
+			}
+			return null;
+		}
 		long now = System.currentTimeMillis();
 
 		// If the TTL for this cache entry has expired, directly check whether the archive is still invalid.
 		// If it transitioned to being valid, remove it from the cache and force an update to project caches.
 		if (now > invalidArchiveInfo.evictionTimestamp) {
 			try {
-				getZipFile(path, false);
+				ZipFile zipFile = getZipFile(path, false);
+				closeZipFile(zipFile);
 				removeFromInvalidArchiveCache(path);
 			} catch (CoreException e) {
 				// Archive is still invalid, fall through to reporting it is invalid.
@@ -3427,14 +3420,24 @@
 			// Retry the test from the start, now that we have an up-to-date result
 			return getArchiveValidity(path);
 		}
+		if (DEBUG_INVALID_ARCHIVES) {
+			System.out.println("JAR cache: " + invalidArchiveInfo.reason + " " + path);  //$NON-NLS-1$ //$NON-NLS-2$
+		}
 		return invalidArchiveInfo.reason;
 	}
 
 	public void removeFromInvalidArchiveCache(IPath path) {
-		synchronized(this.invalidArchivesMutex) {
+		synchronized(this.invalidArchives) {
+			InvalidArchiveInfo entry = this.invalidArchives.get(path);
+			if (entry != null && entry.reason == ArchiveValidity.VALID) {
+				if (DEBUG_INVALID_ARCHIVES) {
+					System.out.println("JAR cache: keep VALID " + path);  //$NON-NLS-1$
+				}
+				return; // do not remove the VALID information
+			}
 			if (this.invalidArchives.remove(path) != null) {
 				if (DEBUG_INVALID_ARCHIVES) {
-					System.out.println("Invalid JAR cache: removed " + path);  //$NON-NLS-1$
+					System.out.println("JAR cache: removed INVALID " + path);  //$NON-NLS-1$
 				}
 				try {
 					// Bug 455042: Force an update of the JavaProjectElementInfo project caches.
@@ -4301,16 +4304,6 @@
 	public void resetClasspathListCache() {
 		if (this.nonChainingJars != null)
 			this.nonChainingJars.clear();
-		if (DEBUG_INVALID_ARCHIVES) {
-			synchronized(this.invalidArchivesMutex) {
-				if (!this.invalidArchives.isEmpty()) {
-					System.out.println("Invalid JAR cache: clearing cache"); //$NON-NLS-1$
-				}
-			}
-		}
-		synchronized(this.invalidArchivesMutex) {
-			this.invalidArchives.clear();
-		}
 		if (this.externalFiles != null)
 			this.externalFiles.clear();
 		if (this.assumedExternalFiles != null)
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaProject.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaProject.java
index 7bcc371..459e002 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaProject.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaProject.java
@@ -151,8 +151,14 @@
 
 	/**
 	 * Whether the underlying file system is case sensitive.
+	 * @deprecated case sensitivity is not a constant but can be configured at runtime for individual folders (see bug 571614#c8)
 	 */
-	protected static final boolean IS_CASE_SENSITIVE = !new File("Temp").equals(new File("temp")); //$NON-NLS-1$ //$NON-NLS-2$
+	@Deprecated
+	private static final boolean IS_CASE_SENSITIVE = !new File("Temp").equals(new File("temp")); //$NON-NLS-1$ //$NON-NLS-2$
+	/**
+	 * ignore case insensitivity by default (see bug 571614#c8)
+	 */
+	static final boolean RESOLVE_ACTUAL_PACKAGEFRAGMENT_NAME = Boolean.getBoolean("org.eclipse.jdt.resolve_actual_packagefragment_name"); //$NON-NLS-1$
 
 	/**
 	 * An empty array of strings indicating that a project doesn't have any prerequesite projects.
@@ -311,20 +317,47 @@
 	}
 
 	/**
+	 * Does nothing by default. With system flag org.eclipse.jdt.resolve_actual_packagefragment_name=true it tries to find the actual filename
+	 */
+	public static IPath createPackageFragementKey(IPath externalPath) {
+		if (RESOLVE_ACTUAL_PACKAGEFRAGMENT_NAME) { //disabled by default
+			return capitailzePath(externalPath);
+		} else {
+			// trust the UI to already have resolved the actual capitalization:
+			return externalPath;  // do nothing
+		}
+	}
+
+	/**
 	 * Returns a canonicalized path from the given external path.
 	 * Note that the return path contains the same number of segments
 	 * and it contains a device only if the given path contained one.
 	 * @param externalPath IPath
-	 * @see java.io.File for the definition of a canonicalized path
 	 * @return IPath
+	 * @deprecated This method may not do what you expect from its name (see bug 571614):
+	 *             <p> On Linux/Mac (CASE_SENSITIVE by default) it does nothing - even when pointing to a case insensitive filesystem.
+	 *             <p> On Windows (CASE_INSENSITIVE by default) it will find the actual capitalization of all path segments.
+	 *             On Windows it will also resolve 8.3 filenames to its long names.
+	 *             On Windows this results in slow system calls for every segment of the path since JDK 12
+	 *             (see https://bugs.openjdk.java.net/browse/JDK-8207005) - even when the filesystem is configured to
+	 *             be case sensitive and 8.3 name resolving is disabled.
+	 *             <p> ALTERNATIVES:
+	 *             <p> For package fragments use {@link #createPackageFragementKey}
+	 *             <p> For comparing files use {@link java.nio.file.Files#isSameFile}
+	 *         	   <p> For getting the actual capitalization use {@link java.nio.file.Path#toRealPath}
 	 */
+	@Deprecated
 	public static IPath canonicalizedPath(IPath externalPath) {
+		return capitailzePath(externalPath);
+	}
+
+    private static IPath capitailzePath(IPath externalPath) {
 
 		if (externalPath == null)
 			return null;
 
-		if (IS_CASE_SENSITIVE) {
-			return externalPath;
+		if (IS_CASE_SENSITIVE) { // if Linux/Mac
+			return externalPath; // do nothing
 		}
 
 		// if not external path, return original path
@@ -1587,7 +1620,7 @@
 	public IPackageFragment findPackageFragment(IPath path)
 		throws JavaModelException {
 
-		return findPackageFragment0(JavaProject.canonicalizedPath(path));
+		return findPackageFragment0(createPackageFragementKey(path));
 	}
 	/*
 	 * non path canonicalizing version
@@ -1606,7 +1639,7 @@
 	public IPackageFragmentRoot findPackageFragmentRoot(IPath path)
 		throws JavaModelException {
 
-		return findPackageFragmentRoot0(JavaProject.canonicalizedPath(path));
+		return findPackageFragmentRoot0(createPackageFragementKey(path));
 	}
 	/*
 	 * no path canonicalization
@@ -2343,7 +2376,7 @@
 	 */
 	@Override
 	public IPackageFragmentRoot getPackageFragmentRoot(String externalLibraryPath) {
-		return getPackageFragmentRoot0(JavaProject.canonicalizedPath(new Path(externalLibraryPath)), null);
+		return getPackageFragmentRoot0(createPackageFragementKey(new Path(externalLibraryPath)), null);
 	}
 
 	/*
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaProjectElementInfo.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaProjectElementInfo.java
index 619011c..15ddf3b 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaProjectElementInfo.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaProjectElementInfo.java
@@ -212,7 +212,7 @@
 		if (cache != null) {
 			for (IPackageFragmentRoot root : cache.allPkgFragmentRootsCache) {
 				IJavaProject rootProject = root.getJavaProject();
-				if (rootProject != this && !rootProject.exists()) {
+				if (rootProject != project && !rootProject.exists()) {
 					cache = null; // force rebuilding
 					break;
 				}
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/processing/JobManager.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/processing/JobManager.java
index 24795d9..d0eadca 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/processing/JobManager.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/processing/JobManager.java
@@ -42,7 +42,7 @@
 	    it cannot go beyond 1 */
 	private int enableCount = 1;
 
-	public static boolean VERBOSE = false;
+	public static boolean VERBOSE = true;
 	/* flag indicating that the activation has completed */
 	public boolean activated = false;
 
@@ -137,7 +137,7 @@
 	public synchronized void enable() {
 		this.enableCount++;
 		if (VERBOSE)
-			Util.verbose("ENABLING  background indexing"); //$NON-NLS-1$
+			Util.verbose("ENABLING  background indexing "+this.enableCount); //$NON-NLS-1$
 		notifyAll(); // wake up the background thread if it is waiting (context must be synchronized)
 	}
 	protected synchronized boolean isJobWaiting(IJob request) {