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) {