Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorManoj Palat2021-01-04 05:56:01 +0000
committerManoj Palat2021-01-04 06:07:53 +0000
commit9007a83c2488885d0ccac052ef8a8c04f1cd5736 (patch)
tree6bde76e28758a9ff0a4d3d30bc4877ebe4a9c43c
parent11169783ee3de0c3c47bdfe2fe93c52f17b1b06a (diff)
parentd5c188d78ee37a5a78869313b94fa62ff542cea6 (diff)
downloadeclipse.jdt.core-9007a83c2488885d0ccac052ef8a8c04f1cd5736.tar.gz
eclipse.jdt.core-9007a83c2488885d0ccac052ef8a8c04f1cd5736.tar.xz
eclipse.jdt.core-9007a83c2488885d0ccac052ef8a8c04f1cd5736.zip
Merge branch 'master' into BETA_JAVA16
Change-Id: I1e5c50ff51bfb0165660070e94d9a85cfbc98089 Signed-off-by: Manoj Palat <manpalat@in.ibm.com>
-rw-r--r--org.eclipse.jdt.core.tests.compiler/META-INF/MANIFEST.MF2
-rw-r--r--org.eclipse.jdt.core.tests.compiler/pom.xml2
-rw-r--r--org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ConstantTest.java21
-rw-r--r--org.eclipse.jdt.core.tests.model/META-INF/MANIFEST.MF2
-rw-r--r--org.eclipse.jdt.core.tests.model/pom.xml2
-rw-r--r--org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/formatter/FormatterBugsTests.java34
-rw-r--r--org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ExternalAnnotations18Test.java157
-rw-r--r--org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaSearchBugsTests.java15
-rw-r--r--org.eclipse.jdt.core/META-INF/MANIFEST.MF2
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ConditionalExpression.java3
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/ICompilationUnit.java6
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ClassScope.java8
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ExternalAnnotationSuperimposer.java8
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java2
-rw-r--r--org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/Token.java13
-rw-r--r--org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/linewrap/WrapPreparator.java8
-rw-r--r--org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaCorePreferenceInitializer.java2
-rw-r--r--org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathLocation.java5
-rw-r--r--org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathMultiDirectory.java6
-rw-r--r--org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/NameEnvironment.java3
-rw-r--r--org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/SourceFile.java4
-rw-r--r--org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/State.java22
-rw-r--r--org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/IndexBasedHierarchyBuilder.java6
-rw-r--r--org.eclipse.jdt.core/pom.xml2
-rw-r--r--org.eclipse.jdt.core/search/org/eclipse/jdt/core/search/IParallelizable.java57
-rw-r--r--org.eclipse.jdt.core/search/org/eclipse/jdt/core/search/SearchPattern.java10
-rw-r--r--org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/AbstractSearchScope.java12
-rw-r--r--org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/HierarchyScope.java37
-rw-r--r--org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/JavaSearchParticipant.java41
-rw-r--r--org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/JavaSearchScope.java5
-rw-r--r--org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/JavaWorkspaceScope.java5
-rw-r--r--org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/PatternSearchJob.java211
-rw-r--r--org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/SubTypeSearchJob.java29
-rw-r--r--org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/UnindexedSearchScope.java5
-rw-r--r--org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/AndPattern.java18
-rw-r--r--org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/JavaSearchPattern.java9
-rw-r--r--org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/OrPattern.java18
37 files changed, 700 insertions, 92 deletions
diff --git a/org.eclipse.jdt.core.tests.compiler/META-INF/MANIFEST.MF b/org.eclipse.jdt.core.tests.compiler/META-INF/MANIFEST.MF
index 48ccc37f34..96ae5aa3b7 100644
--- a/org.eclipse.jdt.core.tests.compiler/META-INF/MANIFEST.MF
+++ b/org.eclipse.jdt.core.tests.compiler/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: %pluginName
Bundle-SymbolicName: org.eclipse.jdt.core.tests.compiler;singleton:=true
-Bundle-Version: 3.12.1400.qualifier
+Bundle-Version: 3.12.1500.qualifier
Bundle-Vendor: %providerName
Bundle-Localization: plugin
Export-Package: org.eclipse.jdt.core.tests.compiler,
diff --git a/org.eclipse.jdt.core.tests.compiler/pom.xml b/org.eclipse.jdt.core.tests.compiler/pom.xml
index b9f1b7f33d..793238888a 100644
--- a/org.eclipse.jdt.core.tests.compiler/pom.xml
+++ b/org.eclipse.jdt.core.tests.compiler/pom.xml
@@ -20,7 +20,7 @@
</parent>
<groupId>org.eclipse.jdt</groupId>
<artifactId>org.eclipse.jdt.core.tests.compiler</artifactId>
- <version>3.12.1400-SNAPSHOT</version>
+ <version>3.12.1500-SNAPSHOT</version>
<packaging>eclipse-test-plugin</packaging>
<properties>
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ConstantTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ConstantTest.java
index 3d23a15138..0b9d164003 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ConstantTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ConstantTest.java
@@ -45,7 +45,7 @@ public ConstantTest(String name) {
// All specified tests which does not belong to the class are skipped...
static {
// TESTS_PREFIX = "testBug95521";
-// TESTS_NAMES = new String[] { "testBug83127a" };
+// TESTS_NAMES = new String[] { "testBug566332_01" };
// TESTS_NUMBERS = new int[] { 21 };
// TESTS_RANGE = new int[] { 23, -1 };
}
@@ -1604,6 +1604,25 @@ public void testBug566332_04() {
"case expressions must be constant expressions\n" +
"----------\n");
}
+public void testBug569498() {
+ if (this.complianceLevel < ClassFileConstants.JDK11) {
+ return;
+ }
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "public class X {\n"
+ + " final String s1 = \"\";\n"
+ + " public void m(Object s) {\n"
+ + " final boolean b = false;\n"
+ + " final String s2 = \"\";\n"
+ + " m(b? s1 : s2);\n"
+ + " }\n"
+ + " public static void main(String[] args) {}\n"
+ + "}",
+ },
+ "");
+}
public static Class testClass() {
return ConstantTest.class;
}
diff --git a/org.eclipse.jdt.core.tests.model/META-INF/MANIFEST.MF b/org.eclipse.jdt.core.tests.model/META-INF/MANIFEST.MF
index bfe5fed044..dac7d7b51b 100644
--- a/org.eclipse.jdt.core.tests.model/META-INF/MANIFEST.MF
+++ b/org.eclipse.jdt.core.tests.model/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: %pluginName
Bundle-SymbolicName: org.eclipse.jdt.core.tests.model;singleton:=true
-Bundle-Version: 3.10.1400.qualifier
+Bundle-Version: 3.10.1500.qualifier
Bundle-Vendor: %providerName
Bundle-Localization: plugin
Export-Package: org.eclipse.jdt.core.tests,
diff --git a/org.eclipse.jdt.core.tests.model/pom.xml b/org.eclipse.jdt.core.tests.model/pom.xml
index 396818dfd3..ad77b5273d 100644
--- a/org.eclipse.jdt.core.tests.model/pom.xml
+++ b/org.eclipse.jdt.core.tests.model/pom.xml
@@ -20,7 +20,7 @@
</parent>
<groupId>org.eclipse.jdt</groupId>
<artifactId>org.eclipse.jdt.core.tests.model</artifactId>
- <version>3.10.1400-SNAPSHOT</version>
+ <version>3.10.1500-SNAPSHOT</version>
<packaging>eclipse-test-plugin</packaging>
<properties>
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/formatter/FormatterBugsTests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/formatter/FormatterBugsTests.java
index 80a8a1dd2e..8e78f96099 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/formatter/FormatterBugsTests.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/formatter/FormatterBugsTests.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2020 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
@@ -13231,4 +13231,36 @@ public void testBug567714() {
" }\n" +
"}");
}
+/**
+ * https://bugs.eclipse.org/569798 - [formatter] Brace position - next line indented: bug for array within annotation
+ */
+public void testBug569798() {
+ this.formatterPrefs.brace_position_for_array_initializer = DefaultCodeFormatterConstants.NEXT_LINE_SHIFTED;
+ formatSource(
+ "class Test {\n" +
+ " @Nullable\n" +
+ " @SuppressWarnings(\n" +
+ " { \"\" })\n" +
+ " @Something(a =\n" +
+ " { \"\" })\n" +
+ " void f() {\n" +
+ " }\n" +
+ "}"
+ );
+}
+/**
+ * https://bugs.eclipse.org/569964 - [formatter] Keep braced code on one line: problem with comments after javadoc
+ */
+public void testBug569964() {
+ this.formatterPrefs.keep_method_body_on_one_line = DefaultCodeFormatterConstants.ONE_LINE_IF_EMPTY;
+ formatSource(
+ "class Test {\n" +
+ " /**\n" +
+ " * More Java doc comment\n" +
+ " */\n" +
+ " // A line comment\n" +
+ " /* package */ void nothing() {}\n" +
+ "}"
+ );
+}
}
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ExternalAnnotations18Test.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ExternalAnnotations18Test.java
index 06ff023b20..5024a9ed75 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ExternalAnnotations18Test.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ExternalAnnotations18Test.java
@@ -315,6 +315,13 @@ public class ExternalAnnotations18Test extends ModifyingResourceTests {
this.project.setRawClasspath(rawClasspath, new NullProgressMonitor());
}
+ protected void addSourceFolderWithExternalAnnotations(IJavaProject javaProject, String sourceFolder, String outputFolder, String externalAnnotationPath) throws JavaModelException {
+ IClasspathAttribute[] extraAttributes = new IClasspathAttribute[] { new ClasspathAttribute(IClasspathAttribute.EXTERNAL_ANNOTATION_PATH, externalAnnotationPath) };
+ IClasspathEntry entry = JavaCore.newSourceEntry(new Path(sourceFolder), null, null,
+ outputFolder != null ? new Path(outputFolder) : null, extraAttributes);
+ addClasspathEntry(javaProject, entry);
+ }
+
protected void createFileInProject(String projectRelativeFolder, String fileName, String content) throws CoreException {
String folderPath = this.project.getProject().getName()+'/'+projectRelativeFolder;
createFolder(folderPath);
@@ -2666,4 +2673,154 @@ public class ExternalAnnotations18Test extends ModifyingResourceTests {
deleteProject("Bug500024");
}
}
+
+ // reconcile client of a "generated" source+eea
+ @SuppressWarnings("deprecation")
+ public void testSourceFolder1() throws CoreException {
+ myCreateJavaProject("Bug509397");
+ addSourceFolderWithExternalAnnotations(this.project, "/Bug509397/src-gen", "/Bug509397/bin-gen", "/Bug509397/annot-gen");
+
+ createFileInProject("annot-gen/pgen", "CGen.eea",
+ "class pgen/CGen\n" +
+ "\n" +
+ "get\n" +
+ " (Ljava/lang/String;)Ljava/lang/String;\n" +
+ " (L1java/lang/String;)L1java/lang/String;\n");
+
+ createFileInProject("src-gen/pgen", "CGen.java",
+ "package pgen;\n" +
+ "public class CGen {\n" +
+ " public String get(String in) { return in; }\n" +
+ "}\n");
+
+ IPackageFragment fragment = this.project.getPackageFragmentRoots()[0].createPackageFragment("p", true, null);
+ ICompilationUnit unit = fragment.createCompilationUnit("Use.java",
+ "package p;\n" +
+ "import pgen.CGen;\n" +
+ "import org.eclipse.jdt.annotation.NonNull;\n" +
+ "public class Use {\n" +
+ " public @NonNull String test(CGen c) {\n" +
+ " String s = c.get(null);\n" + // problem here (6)
+ " return s;\n" + // no problem here
+ " }\n" +
+ "}\n",
+ true, new NullProgressMonitor()).getWorkingCopy(new NullProgressMonitor());
+ CompilationUnit reconciled = unit.reconcile(AST.JLS8, true, null, new NullProgressMonitor());
+ IProblem[] problems = reconciled.getProblems();
+ assertProblems(problems, new String[] {
+ "Pb(910) Null type mismatch: required '@NonNull String' but the provided value is null"
+ }, new int[] { 6 });
+ }
+
+ // reconcile client of a "generated" source+eea
+ // single merged output folder
+ @SuppressWarnings("deprecation")
+ public void testSourceFolder1a() throws CoreException {
+ myCreateJavaProject("Bug509397");
+ addSourceFolderWithExternalAnnotations(this.project, "/Bug509397/src-gen", null, "/Bug509397/annot-gen");
+
+ createFileInProject("annot-gen/pgen", "CGen.eea",
+ "class pgen/CGen\n" +
+ "\n" +
+ "get\n" +
+ " (Ljava/lang/String;)Ljava/lang/String;\n" +
+ " (L1java/lang/String;)L1java/lang/String;\n");
+
+ createFileInProject("src-gen/pgen", "CGen.java",
+ "package pgen;\n" +
+ "public class CGen {\n" +
+ " public String get(String in) { return in; }\n" +
+ "}\n");
+ this.project.getProject().build(IncrementalProjectBuilder.FULL_BUILD, null);
+
+ IPackageFragment fragment = this.project.getPackageFragmentRoots()[0].createPackageFragment("p", true, null);
+ ICompilationUnit unit = fragment.createCompilationUnit("Use.java",
+ "package p;\n" +
+ "import pgen.CGen;\n" +
+ "import org.eclipse.jdt.annotation.NonNull;\n" +
+ "public class Use {\n" +
+ " public @NonNull String test(CGen c) {\n" +
+ " String s = c.get(null);\n" + // problem here (6)
+ " return s;\n" + // no problem here
+ " }\n" +
+ "}\n",
+ true, new NullProgressMonitor()).getWorkingCopy(new NullProgressMonitor());
+ CompilationUnit reconciled = unit.reconcile(AST.JLS8, true, null, new NullProgressMonitor());
+ IProblem[] problems = reconciled.getProblems();
+ assertProblems(problems, new String[] {
+ "Pb(910) Null type mismatch: required '@NonNull String' but the provided value is null"
+ }, new int[] { 6 });
+ }
+
+ // full build of a project with src-gen & annot-gen
+ public void testSourceFolder2() throws CoreException {
+ myCreateJavaProject("Bug509397");
+ addSourceFolderWithExternalAnnotations(this.project, "/Bug509397/src-gen", "/Bug509397/bin-gen", "/Bug509397/annot-gen");
+
+ createFileInProject("annot-gen/pgen", "CGen.eea",
+ "class pgen/CGen\n" +
+ "\n" +
+ "get\n" +
+ " (Ljava/lang/String;)Ljava/lang/String;\n" +
+ " (L1java/lang/String;)L1java/lang/String;\n");
+
+ createFileInProject("src-gen/pgen", "CGen.java",
+ "package pgen;\n" +
+ "public class CGen {\n" +
+ " public String get(String in) { return in; }\n" +
+ "}\n");
+
+ createFileInProject("src/p", "Use.java",
+ "package p;\n" +
+ "import pgen.CGen;\n" +
+ "import org.eclipse.jdt.annotation.NonNull;\n" +
+ "public class Use {\n" +
+ " public @NonNull String test(CGen c) {\n" +
+ " String s = c.get(null);\n" + // problem here (6)
+ " return s;\n" + // no problem here
+ " }\n" +
+ "}\n");
+ this.project.getProject().build(IncrementalProjectBuilder.FULL_BUILD, null);
+ IMarker[] markers = this.project.getProject().findMarkers(IJavaModelMarker.JAVA_MODEL_PROBLEM_MARKER, false, IResource.DEPTH_INFINITE);
+ assertMarkers("Unexpected markers",
+ "Null type mismatch: required '@NonNull String' but the provided value is null",
+ markers);
+ }
+
+ // full build of a project with src-gen & annot-gen
+ // single merged output folder
+ public void testSourceFolder2a() throws CoreException {
+ myCreateJavaProject("Bug509397");
+ addSourceFolderWithExternalAnnotations(this.project, "/Bug509397/src-gen", null, "/Bug509397/annot-gen");
+
+ createFileInProject("annot-gen/pgen", "CGen.eea",
+ "class pgen/CGen\n" +
+ "\n" +
+ "get\n" +
+ " (Ljava/lang/String;)Ljava/lang/String;\n" +
+ " (L1java/lang/String;)L1java/lang/String;\n");
+
+ createFileInProject("src-gen/pgen", "CGen.java",
+ "package pgen;\n" +
+ "public class CGen {\n" +
+ " public String get(String in) { return in; }\n" +
+ "}\n");
+
+ createFileInProject("src/p", "Use.java",
+ "package p;\n" +
+ "import pgen.CGen;\n" +
+ "import org.eclipse.jdt.annotation.NonNull;\n" +
+ "public class Use {\n" +
+ " public @NonNull String test(CGen c) {\n" +
+ " String s = c.get(null);\n" + // problem here (6)
+ " return s;\n" + // no problem here
+ " }\n" +
+ "}\n");
+ this.project.getProject().build(IncrementalProjectBuilder.FULL_BUILD, null);
+ IMarker[] markers = this.project.getProject().findMarkers(IJavaModelMarker.JAVA_MODEL_PROBLEM_MARKER, false, IResource.DEPTH_INFINITE);
+ assertMarkers("Unexpected markers",
+ "Null type mismatch: required '@NonNull String' but the provided value is null",
+ markers);
+ }
+
}
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaSearchBugsTests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaSearchBugsTests.java
index 53740a9e94..705a5ea3b3 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaSearchBugsTests.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaSearchBugsTests.java
@@ -8618,7 +8618,16 @@ public void testBug166348_Qualified() throws CoreException {
* @test Ensure that types are found even when scope is not a {@link org.eclipse.jdt.internal.core.search.JavaSearchScope}
* @see "https://bugs.eclipse.org/bugs/show_bug.cgi?id=167190"
*/
+public void testBug167190_Parallel() throws CoreException, JavaModelException {
+ bug167190(true);
+}
+
public void testBug167190() throws CoreException, JavaModelException {
+ bug167190(false);
+}
+
+private void bug167190(boolean parallel) throws JavaModelException {
+
IJavaSearchScope scope = new AbstractSearchScope() {
IJavaSearchScope jsScope = getJavaSearchScope();
public void processDelta(IJavaElementDelta delta, int eventType) {
@@ -8633,6 +8642,10 @@ public void testBug167190() throws CoreException, JavaModelException {
public IPath[] enclosingProjectsAndJars() {
return this.jsScope.enclosingProjectsAndJars();
}
+ @Override
+ public boolean isParallelSearchSupported() {
+ return parallel;
+ }
};
// Search all type names with TypeNameMatchRequestor
TypeNameMatchCollector collector = new TypeNameMatchCollector() {
@@ -8664,7 +8677,7 @@ public void testBug167190() throws CoreException, JavaModelException {
IJavaSearchConstants.WAIT_UNTIL_READY_TO_SEARCH,
null);
// Should have same types with these 2 searches
- assertEquals("Found types sounds not to be correct", requestor.toString(), collector.toString());
+ assertEquals(String.format("Found types sounds not to be correct [Parallel=%s]", parallel), requestor.toString(), collector.toString());
}
/**
diff --git a/org.eclipse.jdt.core/META-INF/MANIFEST.MF b/org.eclipse.jdt.core/META-INF/MANIFEST.MF
index 9ee7dc3fc8..8283b9880e 100644
--- a/org.eclipse.jdt.core/META-INF/MANIFEST.MF
+++ b/org.eclipse.jdt.core/META-INF/MANIFEST.MF
@@ -3,7 +3,7 @@ Main-Class: org.eclipse.jdt.internal.compiler.batch.Main
Bundle-ManifestVersion: 2
Bundle-Name: %pluginName
Bundle-SymbolicName: org.eclipse.jdt.core; singleton:=true
-Bundle-Version: 3.24.0.qualifier
+Bundle-Version: 3.25.0.qualifier
Bundle-Activator: org.eclipse.jdt.core.JavaCore
Bundle-Vendor: %providerName
Bundle-Localization: plugin
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ConditionalExpression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ConditionalExpression.java
index 0dcd9d3fef..8d49d80066 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ConditionalExpression.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ConditionalExpression.java
@@ -521,6 +521,9 @@ public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext,
}
if (isPolyExpression()) {
if (this.expectedType == null || !this.expectedType.isProperType(true)) {
+ // We will be back here in case of a PolyTypeBinding. So, to enable
+ // further processing, set it back to default.
+ this.constant = Constant.NotAConstant;
return new PolyTypeBinding(this);
}
return this.resolvedType = computeConversions(scope, this.expectedType) ? this.expectedType : null;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/ICompilationUnit.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/ICompilationUnit.java
index 24bd52d73d..5e2cdfa662 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/ICompilationUnit.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/ICompilationUnit.java
@@ -74,4 +74,10 @@ default char[] getModuleName() {
default String getDestinationPath() {
return null;
}
+/**
+ * Answers a path for external annotations that has been configured for
+ * the providing classpath entry, or <code>null</code>.
+ */
+default String getExternalAnnotationPath() { return null; }
+
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ClassScope.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ClassScope.java
index 57cfa33fe4..6b231bd335 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ClassScope.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ClassScope.java
@@ -56,6 +56,7 @@ import org.eclipse.jdt.internal.compiler.ast.TypeParameter;
import org.eclipse.jdt.internal.compiler.ast.TypeReference;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.eclipse.jdt.internal.compiler.env.AccessRestriction;
+import org.eclipse.jdt.internal.compiler.env.ICompilationUnit;
import org.eclipse.jdt.internal.compiler.problem.AbortCompilation;
import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
import org.eclipse.jdt.internal.compiler.util.HashtableOfObject;
@@ -526,6 +527,13 @@ public class ClassScope extends Scope {
SourceTypeBinding sourceType = this.referenceContext.binding;
sourceType.module = module();
environment().setAccessRestriction(sourceType, accessRestriction);
+ ICompilationUnit compilationUnit = this.referenceContext.compilationResult.getCompilationUnit();
+ if (compilationUnit != null && compilerOptions().isAnnotationBasedNullAnalysisEnabled) {
+ String externalAnnotationPath = compilationUnit.getExternalAnnotationPath();
+ if (externalAnnotationPath != null) {
+ ExternalAnnotationSuperimposer.apply(sourceType, externalAnnotationPath);
+ }
+ }
TypeParameter[] typeParameters = this.referenceContext.typeParameters;
sourceType.typeVariables = typeParameters == null || typeParameters.length == 0 ? Binding.NO_TYPE_VARIABLES : null;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ExternalAnnotationSuperimposer.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ExternalAnnotationSuperimposer.java
index 9fd2eba530..ee946d3a23 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ExternalAnnotationSuperimposer.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ExternalAnnotationSuperimposer.java
@@ -21,6 +21,7 @@ import java.io.InputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
+import org.eclipse.jdt.internal.compiler.ast.Argument;
import org.eclipse.jdt.internal.compiler.classfmt.ExternalAnnotationProvider;
import org.eclipse.jdt.internal.compiler.env.IBinaryAnnotation;
import org.eclipse.jdt.internal.compiler.env.ITypeAnnotationWalker;
@@ -101,7 +102,7 @@ class ExternalAnnotationSuperimposer extends TypeBindingVisitor {
field.type = visitor.superimpose(field.type, TypeBinding.class);
}
- public static void annotateMethodBinding(MethodBinding method, ExternalAnnotationProvider provider, LookupEnvironment environment) {
+ public static void annotateMethodBinding(MethodBinding method, Argument[] arguments, ExternalAnnotationProvider provider, LookupEnvironment environment) {
char[] methodSignature = method.genericSignature();
if (methodSignature == null)
methodSignature = method.signature();
@@ -119,8 +120,11 @@ class ExternalAnnotationSuperimposer extends TypeBindingVisitor {
}
TypeBinding[] parameters = method.parameters;
for (short i = 0; i < parameters.length; i++) {
- if (visitor.go(walker.toMethodParameter(i)))
+ if (visitor.go(walker.toMethodParameter(i))) {
parameters[i] = visitor.superimpose(parameters[i], TypeBinding.class);
+ if (arguments != null && i < arguments.length)
+ arguments[i].binding.type = parameters[i];
+ }
}
}
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java
index 4a475f532e..7a1b542b22 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java
@@ -2841,7 +2841,7 @@ private MethodBinding resolveTypesWithSuspendedTempErrorHandlingPolicy(MethodBin
method.modifiers &= ~ExtraCompilerModifiers.AccUnresolved;
if (this.externalAnnotationProvider != null) {
- ExternalAnnotationSuperimposer.annotateMethodBinding(method, this.externalAnnotationProvider, this.environment);
+ ExternalAnnotationSuperimposer.annotateMethodBinding(method, arguments, this.externalAnnotationProvider, this.environment);
}
return method;
}
diff --git a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/Token.java b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/Token.java
index b2b7144267..ca4d701f38 100644
--- a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/Token.java
+++ b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/Token.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2014, 2015 Mateusz Matela and others.
+ * Copyright (c) 2014, 2021 Mateusz Matela and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
@@ -143,16 +143,19 @@ public class Token {
int start = scanner.getCurrentTokenStartPosition();
int end = scanner.getCurrentTokenEndPosition();
if (currentToken == TokenNameCOMMENT_LINE) {
- // don't include line separator
- while(end >= start) {
+ // don't include line separator, but set break-after
+ while (end > start) {
char c = scanner.source[end];
if (c != '\r' && c != '\n')
break;
end--;
}
+ Token token = new Token(start, end, currentToken);
+ token.breakAfter();
+ return token;
+ } else {
+ return new Token(start, end, currentToken);
}
- Token token = new Token(start, end, currentToken);
- return token;
}
/** Adds space before this token */
diff --git a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/linewrap/WrapPreparator.java b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/linewrap/WrapPreparator.java
index bb3301426c..d81b254ecf 100644
--- a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/linewrap/WrapPreparator.java
+++ b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/linewrap/WrapPreparator.java
@@ -81,6 +81,7 @@ import org.eclipse.jdt.core.dom.IfStatement;
import org.eclipse.jdt.core.dom.InfixExpression;
import org.eclipse.jdt.core.dom.InfixExpression.Operator;
import org.eclipse.jdt.core.dom.LambdaExpression;
+import org.eclipse.jdt.core.dom.MemberValuePair;
import org.eclipse.jdt.core.dom.MethodDeclaration;
import org.eclipse.jdt.core.dom.MethodInvocation;
import org.eclipse.jdt.core.dom.Name;
@@ -795,6 +796,13 @@ public class WrapPreparator extends ASTVisitor {
closingBraceIndex, 0, this.currentDepth, 1, true, false));
}
}
+ if (this.options.brace_position_for_array_initializer.equals(DefaultCodeFormatterConstants.NEXT_LINE_SHIFTED)
+ && openingBrace.getWrapPolicy() == null && (node.getParent() instanceof SingleMemberAnnotation
+ || node.getParent() instanceof MemberValuePair)) {
+ int parentIndex = this.tm.firstIndexIn(node.getParent(), -1);
+ int indent = this.options.indentation_size;
+ openingBrace.setWrapPolicy(new WrapPolicy(WrapMode.BLOCK_INDENT, parentIndex, indent));
+ }
return true;
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaCorePreferenceInitializer.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaCorePreferenceInitializer.java
index 031a67c4e9..b99ba966ec 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaCorePreferenceInitializer.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaCorePreferenceInitializer.java
@@ -26,6 +26,7 @@ import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.formatter.DefaultCodeFormatterConstants;
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
import org.eclipse.jdt.internal.core.nd.db.ChunkCache;
+import org.eclipse.jdt.internal.core.search.PatternSearchJob;
/**
* JavaCore eclipse preferences initializer.
@@ -116,6 +117,7 @@ public class JavaCorePreferenceInitializer extends AbstractPreferenceInitializer
defaultOptionsMap.put(ChunkCache.CHUNK_CACHE_SIZE_MB, Double.toString(ChunkCache.CHUNK_CACHE_SIZE_MB_DEFAULT));
defaultOptionsMap.put(ChunkCache.CHUNK_CACHE_SIZE_PERCENT,
Double.toString(ChunkCache.CHUNK_CACHE_SIZE_PERCENT_DEFAULT));
+ defaultOptionsMap.put(PatternSearchJob.ENABLE_PARALLEL_SEARCH, Boolean.toString(PatternSearchJob.ENABLE_PARALLEL_SEARCH_DEFAULT));
// Time out for parameter names
defaultOptionsMap.put(JavaCore.TIMEOUT_FOR_PARAMETER_NAME_FROM_ATTACHED_JAVADOC, "50"); //$NON-NLS-1$
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathLocation.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathLocation.java
index 4cdb930aae..44fc370bad 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathLocation.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathLocation.java
@@ -121,9 +121,8 @@ public abstract class ClasspathLocation {
return true;
}
static ClasspathLocation forSourceFolder(IContainer sourceFolder, IContainer outputFolder,
- char[][] inclusionPatterns, char[][] exclusionPatterns, boolean ignoreOptionalProblems) {
- return new ClasspathMultiDirectory(sourceFolder, outputFolder, inclusionPatterns, exclusionPatterns,
- ignoreOptionalProblems);
+ char[][] inclusionPatterns, char[][] exclusionPatterns, boolean ignoreOptionalProblems, IPath externalAnnotationPath) {
+ return new ClasspathMultiDirectory(sourceFolder, outputFolder, inclusionPatterns, exclusionPatterns, ignoreOptionalProblems, externalAnnotationPath);
}
public static ClasspathLocation forBinaryFolder(IContainer binaryFolder, boolean isOutputFolder, AccessRuleSet accessRuleSet, IPath externalAnnotationPath, boolean autoModule) {
return new ClasspathDirectory(binaryFolder, isOutputFolder, accessRuleSet, externalAnnotationPath, autoModule);
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathMultiDirectory.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathMultiDirectory.java
index 96b26f2552..e127fb7c71 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathMultiDirectory.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathMultiDirectory.java
@@ -15,6 +15,7 @@ package org.eclipse.jdt.internal.core.builder;
import org.eclipse.core.resources.*;
import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.internal.compiler.CompilationResult;
import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
@@ -32,8 +33,9 @@ char[][] exclusionPatterns; // used by builders when walking source folders
boolean hasIndependentOutputFolder; // if output folder is not equal to any of the source folders
public boolean ignoreOptionalProblems;
-ClasspathMultiDirectory(IContainer sourceFolder, IContainer binaryFolder, char[][] inclusionPatterns, char[][] exclusionPatterns, boolean ignoreOptionalProblems) {
- super(binaryFolder, true, null, null, false /* source never an automatic module*/);
+ClasspathMultiDirectory(IContainer sourceFolder, IContainer binaryFolder, char[][] inclusionPatterns, char[][] exclusionPatterns,
+ boolean ignoreOptionalProblems, IPath externalAnnotationPath) {
+ super(binaryFolder, true, null, externalAnnotationPath, false /* source never an automatic module*/);
this.sourceFolder = sourceFolder;
this.inclusionPatterns = inclusionPatterns;
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/NameEnvironment.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/NameEnvironment.java
index 577b3eed72..837ebc11bd 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/NameEnvironment.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/NameEnvironment.java
@@ -181,7 +181,8 @@ private void computeClasspathLocations(
outputFolder,
entry.fullInclusionPatternChars(),
entry.fullExclusionPatternChars(),
- entry.ignoreOptionalProblems());
+ entry.ignoreOptionalProblems(),
+ externalAnnotationPath);
if (patchedModule != null) {
ModuleEntryProcessor.combinePatchIntoModuleEntry(sourceLocation, patchedModule, moduleEntries);
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/SourceFile.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/SourceFile.java
index 8425b8a456..891a4ec581 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/SourceFile.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/SourceFile.java
@@ -117,6 +117,10 @@ public int hashCode() {
public boolean ignoreOptionalProblems() {
return this.sourceLocation.ignoreOptionalProblems;
}
+@Override
+public String getExternalAnnotationPath() {
+ return this.sourceLocation.externalAnnotationPath;
+}
String typeLocator() {
return this.resource.getProjectRelativePath().toString();
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/State.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/State.java
index eb188d4d91..e855d95a72 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/State.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/State.java
@@ -76,7 +76,7 @@ private long previousStructuralBuildTime;
private StringSet structurallyChangedTypes;
public static int MaxStructurallyChangedTypes = 100; // keep track of ? structurally changed types, otherwise consider all to be changed
-public static final byte VERSION = 0x0023;
+public static final byte VERSION = 0x0024;
static final byte SOURCE_FOLDER = 1;
static final byte BINARY_FOLDER = 2;
@@ -338,7 +338,7 @@ private static ClasspathMultiDirectory[] readSourceLocations(IProject project, D
if ((folderName = in.readUTF()).length() > 0) sourceFolder = project.getFolder(folderName);
if ((folderName = in.readUTF()).length() > 0) outputFolder = project.getFolder(folderName);
ClasspathMultiDirectory md =
- (ClasspathMultiDirectory) ClasspathLocation.forSourceFolder(sourceFolder, outputFolder, readNames(in), readNames(in), in.readBoolean());
+ (ClasspathMultiDirectory) ClasspathLocation.forSourceFolder(sourceFolder, outputFolder, readNames(in), readNames(in), in.readBoolean(), readNullablePath(in));
if (in.readBoolean())
md.hasIndependentOutputFolder = true;
sourceLocations[i] = md;
@@ -429,6 +429,13 @@ private static char[][] readNames(DataInputStream in) throws IOException {
return names;
}
+private static IPath readNullablePath(DataInputStream in) throws IOException {
+ String path = in.readUTF();
+ if (!path.isEmpty())
+ return new Path(path);
+ return null;
+}
+
private static AccessRuleSet readRestriction(DataInputStream in) throws IOException {
int length = in.readInt();
if (length == 0) return null; // no restriction specified
@@ -711,6 +718,7 @@ private void writeSourceLocations(DataOutputStream out, ClasspathMultiDirectory[
writeNames(md.inclusionPatterns, out);
writeNames(md.exclusionPatterns, out);
out.writeBoolean(md.ignoreOptionalProblems);
+ writeNullablePath(md.externalAnnotationPath, out);
out.writeBoolean(md.hasIndependentOutputFolder);
}
}
@@ -741,7 +749,7 @@ private void writeBinaryLocations(DataOutputStream out, ClasspathLocation[] loca
out.writeUTF(cd.binaryFolder.getFullPath().toString());
out.writeBoolean(cd.isOutputFolder);
writeRestriction(cd.accessRuleSet, out);
- out.writeUTF(cd.externalAnnotationPath != null ? cd.externalAnnotationPath : ""); //$NON-NLS-1$
+ writeNullablePath(cd.externalAnnotationPath, out);
out.writeBoolean(cd.isOnModulePath);
} else if (c instanceof ClasspathJar) {
ClasspathJar jar = (ClasspathJar) c;
@@ -754,7 +762,7 @@ private void writeBinaryLocations(DataOutputStream out, ClasspathLocation[] loca
out.writeUTF(jar.resource.getFullPath().toString());
}
writeRestriction(jar.accessRuleSet, out);
- out.writeUTF(jar.externalAnnotationPath != null ? jar.externalAnnotationPath : ""); //$NON-NLS-1$
+ writeNullablePath(jar.externalAnnotationPath, out);
out.writeBoolean(jar.isOnModulePath);
out.writeUTF(jar.compliance == null ? "" : jar.compliance); //$NON-NLS-1$
@@ -763,7 +771,7 @@ private void writeBinaryLocations(DataOutputStream out, ClasspathLocation[] loca
out.writeByte(EXTERNAL_JAR);
out.writeUTF(jrt.zipFilename);
writeRestriction(jrt.accessRuleSet, out);
- out.writeUTF(jrt.externalAnnotationPath != null ? jrt.externalAnnotationPath : ""); //$NON-NLS-1$
+ writeNullablePath(jrt.externalAnnotationPath, out);
if (jrt instanceof ClasspathJrtWithReleaseOption)
out.writeUTF(((ClasspathJrtWithReleaseOption) jrt).release);
else
@@ -835,6 +843,10 @@ private void writeNames(char[][] names, DataOutputStream out) throws IOException
writeName(names[i], out);
}
+private void writeNullablePath(String path, DataOutputStream out) throws IOException {
+ out.writeUTF(path != null ? path : ""); //$NON-NLS-1$
+}
+
private void writeRestriction(AccessRuleSet accessRuleSet, DataOutputStream out) throws IOException {
if (accessRuleSet == null) {
out.writeInt(0);
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/IndexBasedHierarchyBuilder.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/IndexBasedHierarchyBuilder.java
index 7ec88709e6..f68ec4c98c 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/IndexBasedHierarchyBuilder.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/IndexBasedHierarchyBuilder.java
@@ -74,6 +74,7 @@ import org.eclipse.jdt.internal.core.search.indexing.IIndexConstants;
import org.eclipse.jdt.internal.core.search.indexing.IndexManager;
import org.eclipse.jdt.internal.core.search.matching.MatchLocator;
import org.eclipse.jdt.internal.core.search.matching.SuperTypeReferencePattern;
+import org.eclipse.jdt.internal.core.search.processing.JobManager;
import org.eclipse.jdt.internal.core.util.HandleFactory;
import org.eclipse.jdt.internal.core.util.Util;
@@ -662,6 +663,7 @@ private static void legacySearchAllPossibleSubTypes(
searchRequestor);
queue.add(type.getElementName().toCharArray());
+ long startTime = System.currentTimeMillis();
try {
while (queue.start <= queue.end) {
subMonitor.setWorkRemaining(Math.max(queue.end - queue.start + 1, 100));
@@ -680,6 +682,10 @@ private static void legacySearchAllPossibleSubTypes(
}
} finally {
job.finished();
+ if (JobManager.VERBOSE) {
+ long wallClockTime = System.currentTimeMillis() - startTime;
+ Util.verbose("-> execution time: " + wallClockTime + "ms - " + IndexBasedHierarchyBuilder.class.getSimpleName());//$NON-NLS-1$//$NON-NLS-2$
+ }
}
}
}
diff --git a/org.eclipse.jdt.core/pom.xml b/org.eclipse.jdt.core/pom.xml
index 0bbb433d4e..3de233ee95 100644
--- a/org.eclipse.jdt.core/pom.xml
+++ b/org.eclipse.jdt.core/pom.xml
@@ -18,7 +18,7 @@
</parent>
<groupId>org.eclipse.jdt</groupId>
<artifactId>org.eclipse.jdt.core</artifactId>
- <version>3.24.0-SNAPSHOT</version>
+ <version>3.25.0-SNAPSHOT</version>
<packaging>eclipse-plugin</packaging>
<properties>
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/core/search/IParallelizable.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/core/search/IParallelizable.java
new file mode 100644
index 0000000000..f310fb1f3d
--- /dev/null
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/core/search/IParallelizable.java
@@ -0,0 +1,57 @@
+/*******************************************************************************
+ * Copyright (c) 2020 Gayan Perera and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ * Gayan Perera - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.core.search;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jdt.internal.core.search.JavaSearchParticipant;
+
+/**
+ * This interface can be used by {@link IJavaSearchScope}, {@link JavaSearchParticipant} and {@link SearchPattern} to
+ * mark implementors as eligible for parallel index search.
+ *
+ * @since 3.25
+ */
+public interface IParallelizable {
+ /**
+ * Answers {@code true} if the current instance supports parallel index search
+ *
+ * @return Returns <code>true</code> if the implementation is safe to be used in a parallel search.
+ */
+ boolean isParallelSearchSupported();
+
+ /**
+ * Initialize all needed data before search is started
+ *
+ * @param monitor
+ * non null progress callback
+ */
+ default void initBeforeSearch(IProgressMonitor monitor) throws JavaModelException {
+ // no op
+ }
+
+ /**
+ * Checks if the given object implements this interface and also returns <code>true</code> for
+ * {@link #isParallelSearchSupported()}.
+ *
+ * @param o
+ * The object that needs to be checked. <code>null</code> value will result in returning
+ * <code>false</code>.
+ * @return <code>true</code> if the given object can be used in parallel search.
+ */
+ public static boolean isParallelSearchSupported(Object o) {
+ return (o instanceof IParallelizable) && ((IParallelizable) o).isParallelSearchSupported();
+ }
+
+}
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/core/search/SearchPattern.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/core/search/SearchPattern.java
index db59626672..22ea4af367 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/core/search/SearchPattern.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/core/search/SearchPattern.java
@@ -2419,13 +2419,13 @@ public void findIndexMatches(Index index, IndexQueryRequestor requestor, SearchP
EntryResult[] entries = pattern.queryIn(index);
if (entries == null) return;
- SearchPattern decodedResult = pattern.getBlankPattern();
String containerPath = index.containerPath;
char separator = index.separator;
for (int i = 0, l = entries.length; i < l; i++) {
if (monitor != null && monitor.isCanceled()) throw new OperationCanceledException();
EntryResult entry = entries[i];
+ SearchPattern decodedResult = pattern.getBlankPattern();
decodedResult.decodeIndexKey(entry.getWord());
if (pattern.matchesDecodedKey(decodedResult)) {
// TODO (kent) some clients may not need the document names
@@ -2738,4 +2738,12 @@ public EntryResult[] queryIn(Index index) throws IOException {
public String toString() {
return "SearchPattern"; //$NON-NLS-1$
}
+
+/**
+ * @since 3.25
+ */
+@Override
+public SearchPattern clone() throws CloneNotSupportedException {
+ return (SearchPattern) super.clone();
+}
}
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/AbstractSearchScope.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/AbstractSearchScope.java
index 9ec75b6c25..dcb0cbdad9 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/AbstractSearchScope.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/AbstractSearchScope.java
@@ -15,8 +15,9 @@ package org.eclipse.jdt.internal.core.search;
import org.eclipse.jdt.core.IJavaElementDelta;
import org.eclipse.jdt.core.search.IJavaSearchScope;
+import org.eclipse.jdt.core.search.IParallelizable;
-public abstract class AbstractSearchScope implements IJavaSearchScope {
+public abstract class AbstractSearchScope implements IJavaSearchScope, IParallelizable, Cloneable {
/**
* @see IJavaSearchScope#includesBinaries()
@@ -60,4 +61,13 @@ public void setIncludesClasspaths(boolean includesClasspaths) {
// implements interface method
}
+@Override
+public boolean isParallelSearchSupported() {
+ return false;
+}
+
+@Override
+public AbstractSearchScope clone() throws CloneNotSupportedException {
+ return (AbstractSearchScope) super.clone();
+}
}
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/HierarchyScope.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/HierarchyScope.java
index 0066665f2e..25933caf1f 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/HierarchyScope.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/HierarchyScope.java
@@ -18,6 +18,7 @@ import java.io.File;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
+import java.util.Set;
import org.eclipse.core.resources.*;
import org.eclipse.core.runtime.IPath;
@@ -41,7 +42,7 @@ public class HierarchyScope extends AbstractSearchScope implements SuffixConstan
private HashSet resourcePaths;
private IPath[] enclosingProjectsAndJars;
- protected IResource[] elements;
+ protected Set<String> elements;
protected int elementCount;
public boolean needsRefresh;
@@ -55,15 +56,7 @@ public class HierarchyScope extends AbstractSearchScope implements SuffixConstan
* Adds the given resource to this search scope.
*/
public void add(IResource element) {
- if (this.elementCount == this.elements.length) {
- System.arraycopy(
- this.elements,
- 0,
- this.elements = new IResource[this.elementCount * 2],
- 0,
- this.elementCount);
- }
- this.elements[this.elementCount++] = element;
+ this.elements.add(element.getFullPath().toString());
}
/**
@@ -140,7 +133,6 @@ public class HierarchyScope extends AbstractSearchScope implements SuffixConstan
//JavaModelManager.getJavaModelManager().rememberScope(this);
}
private void buildResourceVector() {
- HashMap resources = new HashMap();
HashMap paths = new HashMap();
IType[] types = null;
if (this.subTypes != null) {
@@ -160,8 +152,7 @@ public class HierarchyScope extends AbstractSearchScope implements SuffixConstan
this.subTypes.add(type);
}
IResource resource = ((JavaElement)type).resource();
- if (resource != null && resources.get(resource) == null) {
- resources.put(resource, resource);
+ if (resource != null) {
add(resource);
}
IPackageFragmentRoot root =
@@ -318,13 +309,8 @@ public class HierarchyScope extends AbstractSearchScope implements SuffixConstan
if (separatorIndex != -1) {
return this.resourcePaths.contains(resourcePath);
} else {
- for (int i = 0; i < this.elementCount; i++) {
- if (resourcePath.startsWith(this.elements[i].getFullPath().toString())) {
- return true;
- }
- }
+ return this.elements.contains(resourcePath);
}
- return false;
}
/**
* Optionally perform additional checks after element has already passed matching based on index/documents.
@@ -455,7 +441,7 @@ public class HierarchyScope extends AbstractSearchScope implements SuffixConstan
}
protected void initialize(IProgressMonitor progressMonitor) throws JavaModelException {
this.resourcePaths = new HashSet();
- this.elements = new IResource[5];
+ this.elements = new HashSet<>();
this.elementCount = 0;
this.needsRefresh = false;
if (this.hierarchy == null) {
@@ -488,4 +474,15 @@ public class HierarchyScope extends AbstractSearchScope implements SuffixConstan
return "HierarchyScope on " + ((JavaElement)this.focusType).toStringWithAncestors(); //$NON-NLS-1$
}
+ @Override
+ public boolean isParallelSearchSupported() {
+ return true;
+ }
+
+ @Override
+ public void initBeforeSearch(IProgressMonitor monitor) throws JavaModelException {
+ if (this.needsRefresh) {
+ initialize(monitor);
+ }
+ }
}
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/JavaSearchParticipant.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/JavaSearchParticipant.java
index 78d8ab67fa..fe29c40e1f 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/JavaSearchParticipant.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/JavaSearchParticipant.java
@@ -33,10 +33,10 @@ import org.eclipse.jdt.internal.core.search.matching.MatchLocator;
* the workspace or no exist yet, and thus aren't just resources).
*/
@SuppressWarnings({"rawtypes", "unchecked"})
-public class JavaSearchParticipant extends SearchParticipant {
+public class JavaSearchParticipant extends SearchParticipant implements IParallelizable {
- private ThreadLocal indexSelector = new ThreadLocal();
- private SourceIndexer sourceIndexer;
+ private final ThreadLocal indexSelector = new ThreadLocal();
+ private final ThreadLocal<SourceIndexer> sourceIndexer = new ThreadLocal<SourceIndexer>();
@Override
public void beginSearching() {
@@ -67,8 +67,9 @@ public class JavaSearchParticipant extends SearchParticipant {
String documentPath = document.getPath();
if (org.eclipse.jdt.internal.core.util.Util.isJavaLikeFileName(documentPath)) {
- this.sourceIndexer = new SourceIndexer(document);
- this.sourceIndexer.indexDocument();
+ SourceIndexer indexer = new SourceIndexer(document);
+ this.sourceIndexer.set(indexer);
+ indexer.indexDocument();
} else if (org.eclipse.jdt.internal.compiler.util.Util.isClassFileName(documentPath)) {
new BinaryIndexer(document).indexDocument();
} else if (documentPath.endsWith(TypeConstants.AUTOMATIC_MODULE_NAME)) {
@@ -80,9 +81,10 @@ public class JavaSearchParticipant extends SearchParticipant {
public void indexResolvedDocument(SearchDocument document, IPath indexPath) {
String documentPath = document.getPath();
if (org.eclipse.jdt.internal.core.util.Util.isJavaLikeFileName(documentPath)) {
- if (this.sourceIndexer != null)
- this.sourceIndexer.indexResolvedDocument();
- this.sourceIndexer = null;
+ SourceIndexer indexer = this.sourceIndexer.get();
+ if (indexer != null)
+ indexer.indexResolvedDocument();
+ this.sourceIndexer.remove();
}
}
@@ -90,8 +92,9 @@ public class JavaSearchParticipant extends SearchParticipant {
public void resolveDocument(SearchDocument document) {
String documentPath = document.getPath();
if (org.eclipse.jdt.internal.core.util.Util.isJavaLikeFileName(documentPath)) {
- if (this.sourceIndexer != null)
- this.sourceIndexer.resolveDocument();
+ SourceIndexer indexer = this.sourceIndexer.get();
+ if (indexer != null)
+ indexer.resolveDocument();
}
}
@@ -114,11 +117,7 @@ public class JavaSearchParticipant extends SearchParticipant {
@Override
public IPath[] selectIndexes(SearchPattern pattern, IJavaSearchScope scope) {
- IndexSelector selector = (IndexSelector) this.indexSelector.get();
- if (selector == null) {
- selector = new IndexSelector(scope, pattern);
- this.indexSelector.set(selector);
- }
+ IndexSelector selector = getIndexSelector(pattern, scope);
IndexLocation[] urls = selector.getIndexLocations();
IPath[] paths = new IPath[urls.length];
for (int i = 0; i < urls.length; i++) {
@@ -127,13 +126,23 @@ public class JavaSearchParticipant extends SearchParticipant {
return paths;
}
- public IndexLocation[] selectIndexURLs(SearchPattern pattern, IJavaSearchScope scope) {
+ private IndexSelector getIndexSelector(SearchPattern pattern, IJavaSearchScope scope) {
IndexSelector selector = (IndexSelector) this.indexSelector.get();
if (selector == null) {
selector = new IndexSelector(scope, pattern);
this.indexSelector.set(selector);
}
+ return selector;
+ }
+
+ public IndexLocation[] selectIndexURLs(SearchPattern pattern, IJavaSearchScope scope) {
+ IndexSelector selector = getIndexSelector(pattern, scope);
return selector.getIndexLocations();
}
+ @Override
+ public boolean isParallelSearchSupported() {
+ return true;
+ }
+
}
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/JavaSearchScope.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/JavaSearchScope.java
index d6026931cf..697d2d3715 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/JavaSearchScope.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/JavaSearchScope.java
@@ -681,4 +681,9 @@ public String toString() {
}
return result.toString();
}
+
+@Override
+public boolean isParallelSearchSupported() {
+ return true;
+}
}
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/JavaWorkspaceScope.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/JavaWorkspaceScope.java
index 391e059bd0..70fb5a3fb7 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/JavaWorkspaceScope.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/JavaWorkspaceScope.java
@@ -239,4 +239,9 @@ public String toString() {
}
return result.toString();
}
+
+@Override
+public boolean isParallelSearchSupported() {
+ return true;
+}
}
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/PatternSearchJob.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/PatternSearchJob.java
index 6af6d897b8..32668eed2a 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/PatternSearchJob.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/PatternSearchJob.java
@@ -14,12 +14,29 @@
package org.eclipse.jdt.internal.core.search;
import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ForkJoinPool;
+import java.util.concurrent.Future;
+import java.util.concurrent.atomic.AtomicLong;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.OperationCanceledException;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.SubMonitor;
-import org.eclipse.jdt.core.search.*;
+import org.eclipse.core.runtime.preferences.IPreferencesService;
+import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jdt.core.search.IJavaSearchScope;
+import org.eclipse.jdt.core.search.IParallelizable;
+import org.eclipse.jdt.core.search.SearchParticipant;
+import org.eclipse.jdt.core.search.SearchPattern;
+import org.eclipse.jdt.internal.compiler.env.AccessRuleSet;
import org.eclipse.jdt.internal.core.JavaModelManager;
import org.eclipse.jdt.internal.core.index.FileIndexLocation;
import org.eclipse.jdt.internal.core.index.Index;
@@ -37,9 +54,14 @@ protected IJavaSearchScope scope;
protected SearchParticipant participant;
protected IndexQueryRequestor requestor;
protected boolean areIndexesReady;
-protected long executionTime = 0;
+protected AtomicLong executionTime;
+boolean parallel;
+
+public static final String ENABLE_PARALLEL_SEARCH = "enableParallelJavaIndexSearch";//$NON-NLS-1$
+public static final boolean ENABLE_PARALLEL_SEARCH_DEFAULT = true;
public PatternSearchJob(SearchPattern pattern, SearchParticipant participant, IJavaSearchScope scope, IndexQueryRequestor requestor) {
+ this.executionTime = new AtomicLong(0);
this.pattern = pattern;
this.participant = participant;
this.scope = scope;
@@ -63,21 +85,81 @@ public boolean execute(IProgressMonitor progressMonitor) {
SubMonitor subMonitor = SubMonitor.convert(progressMonitor, 3);
boolean isComplete = COMPLETE;
- this.executionTime = 0;
+ this.executionTime.set(0);
+ long startTime = System.currentTimeMillis();
+
Index[] indexes = getIndexes(subMonitor.split(1));
try {
int max = indexes.length;
SubMonitor loopMonitor = subMonitor.split(2).setWorkRemaining(max);
- for (int i = 0; i < max; i++) {
- isComplete &= search(indexes[i], loopMonitor.split(1));
+ this.parallel = canRunInParallel();
+ if(this.parallel) {
+ isComplete = performParallelSearch(indexes, loopMonitor);
+ } else {
+ for (int i = 0; i < max; i++) {
+ isComplete &= search(indexes[i], this.requestor, loopMonitor.split(1));
+ }
+ }
+
+ if (JobManager.VERBOSE) {
+ if (this.parallel) {
+ long wallClockTime = System.currentTimeMillis() - startTime;
+ Util.verbose("-> execution time: " + wallClockTime + "ms - " + this);//$NON-NLS-1$//$NON-NLS-2$
+ Util.verbose("-> cumulative execution time (" + ForkJoinPool.getCommonPoolParallelism() + "): " //$NON-NLS-1$//$NON-NLS-2$
+ + this.executionTime.get() + "ms - " + this);//$NON-NLS-1$
+ } else {
+ Util.verbose("-> execution time: " + this.executionTime.get() + "ms - " + this);//$NON-NLS-1$//$NON-NLS-2$
+ }
}
- if (JobManager.VERBOSE)
- Util.verbose("-> execution time: " + this.executionTime + "ms - " + this);//$NON-NLS-1$//$NON-NLS-2$
return isComplete;
} finally {
SubMonitor.done(progressMonitor);
}
}
+private boolean performParallelSearch(Index[] indexes, SubMonitor loopMonitor) {
+ boolean isComplete = true;
+ List<Future<IndexResult>> futures = new ArrayList<>(indexes.length);
+ ForkJoinPool commonPool = ForkJoinPool.commonPool();
+ ParallelSearchMonitor monitor = new ParallelSearchMonitor(loopMonitor);
+
+ try {
+ if (this.scope instanceof IParallelizable) {
+ ((IParallelizable) this.scope).initBeforeSearch(monitor);
+ }
+ for (Index index : indexes) {
+ futures.add(commonPool.submit(() -> search(index, monitor)));
+ }
+
+ for (Future<IndexResult> future : futures) {
+ loopMonitor.split(1);
+ try {
+ IndexResult result = future.get();
+ isComplete &= result.complete;
+ result.matches.forEach(m -> {
+ boolean continueSearch = this.requestor.acceptIndexMatch(m.documentPath, m.indexRecord, this.participant, m.access);
+ if(!continueSearch) {
+ throw new OperationCanceledException();
+ }
+ });
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ throw new OperationCanceledException();
+ } catch (ExecutionException e) {
+ if(e.getCause() instanceof RuntimeException) {
+ throw (RuntimeException) e.getCause();
+ }
+ throw new RuntimeException(e);
+ }
+ }
+ } catch (JavaModelException e) {
+ monitor.setCanceled(true);
+ throw new RuntimeException("Error initializing scope: " + this.scope, e); //$NON-NLS-1$
+ } catch (Exception e) {
+ monitor.setCanceled(true);
+ throw e;
+ }
+ return isComplete;
+}
public Index[] getIndexes(IProgressMonitor progressMonitor) {
// acquire the in-memory indexes on the fly
IndexLocation[] indexLocations;
@@ -106,7 +188,16 @@ public boolean waitNeeded() {
public String getJobFamily() {
return ""; //$NON-NLS-1$
}
-public boolean search(Index index, IProgressMonitor progressMonitor) {
+
+private IndexResult search(Index index, IProgressMonitor progressMonitor) {
+ List<IndexMatch> matches = new ArrayList<>();
+ boolean complete = search(index,
+ collectTo(matches, progressMonitor), progressMonitor);
+ return new IndexResult(complete, matches);
+}
+
+
+public boolean search(Index index, IndexQueryRequestor queryRequestor, IProgressMonitor progressMonitor) {
if (index == null) return COMPLETE;
if (progressMonitor != null && progressMonitor.isCanceled()) throw new OperationCanceledException();
ReadWriteMonitor monitor = index.monitor;
@@ -114,8 +205,14 @@ public boolean search(Index index, IProgressMonitor progressMonitor) {
try {
monitor.enterRead(); // ask permission to read
long start = System.currentTimeMillis();
- MatchLocator.findIndexMatches(this.pattern, index, this.requestor, this.participant, this.scope, progressMonitor);
- this.executionTime += System.currentTimeMillis() - start;
+ SearchPattern searchPattern = this.pattern;
+ IJavaSearchScope searchScope = this.scope;
+ if(this.parallel) {
+ searchPattern = clone(searchPattern);
+ searchScope = clone(searchScope);
+ }
+ MatchLocator.findIndexMatches(searchPattern, index, queryRequestor, this.participant, searchScope, progressMonitor);
+ this.executionTime.addAndGet(System.currentTimeMillis() - start);
return COMPLETE;
} catch (IOException e) {
if (e instanceof java.io.EOFException)
@@ -125,8 +222,102 @@ public boolean search(Index index, IProgressMonitor progressMonitor) {
monitor.exitRead(); // finished reading
}
}
+
+private static IJavaSearchScope clone(IJavaSearchScope searchScope) {
+ if (searchScope instanceof AbstractSearchScope) {
+ try {
+ searchScope = ((AbstractSearchScope)searchScope).clone();
+ } catch (CloneNotSupportedException e) {
+ Util.log(new Status(IStatus.WARNING, JavaCore.PLUGIN_ID,
+ "PatternSearchJob could not clone " + searchScope, e));//$NON-NLS-1$
+ }
+ }
+ return searchScope;
+}
+
+private static SearchPattern clone(SearchPattern searchPattern) {
+ if(searchPattern instanceof Cloneable) {
+ try {
+ searchPattern = searchPattern.clone();
+ } catch (CloneNotSupportedException e) {
+ Util.log(new Status(IStatus.WARNING, JavaCore.PLUGIN_ID,
+ "PatternSearchJob could not clone " + searchPattern, e));//$NON-NLS-1$
+ }
+ }
+ return searchPattern;
+}
+
@Override
public String toString() {
return "searching " + this.pattern.toString(); //$NON-NLS-1$
}
+
+private boolean canRunInParallel() {
+ return isParallelSearchEnabled() && IParallelizable.isParallelSearchSupported(this.scope)
+ && IParallelizable.isParallelSearchSupported(this.participant)
+ && IParallelizable.isParallelSearchSupported(this.pattern);
+}
+
+private boolean isParallelSearchEnabled() {
+ IPreferencesService preferenceService = Platform.getPreferencesService();
+ if (preferenceService == null) {
+ return true;
+ }
+ return preferenceService.getBoolean(JavaCore.PLUGIN_ID, ENABLE_PARALLEL_SEARCH, ENABLE_PARALLEL_SEARCH_DEFAULT,
+ null);
+}
+
+private static IndexQueryRequestor collectTo(final List<IndexMatch> collectTo, final IProgressMonitor monitor) {
+ return new IndexQueryRequestor() {
+
+ @Override
+ public boolean acceptIndexMatch(String documentPath, SearchPattern indexRecord, SearchParticipant participant,
+ AccessRuleSet access) {
+ collectTo.add(new IndexMatch(documentPath, indexRecord, access));
+ return !monitor.isCanceled();
+ }
+ };
+}
+
+static class IndexResult {
+ final boolean complete;
+ final List<IndexMatch> matches;
+
+ IndexResult(boolean complete, List<IndexMatch> matches) {
+ this.complete = complete;
+ this.matches = matches;
+ }
+}
+
+static class IndexMatch {
+ final String documentPath;
+ final SearchPattern indexRecord;
+ final AccessRuleSet access;
+
+ IndexMatch(String documentPath, SearchPattern indexRecord, AccessRuleSet access) {
+ this.documentPath = documentPath;
+ this.indexRecord = indexRecord;
+ this.access = access;
+ }
+}
+
+static class ParallelSearchMonitor extends NullProgressMonitor {
+ private volatile boolean canceled;
+ private IProgressMonitor original;
+
+ public ParallelSearchMonitor(IProgressMonitor original) {
+ this.original = original;
+ }
+
+ @Override
+ public boolean isCanceled() {
+ return this.canceled || this.original.isCanceled();
+ }
+
+ @Override
+ public void setCanceled(boolean canceled) {
+ this.canceled = canceled;
+ }
+}
+
}
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/SubTypeSearchJob.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/SubTypeSearchJob.java
index 42b5656d51..8249530e08 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/SubTypeSearchJob.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/SubTypeSearchJob.java
@@ -13,39 +13,40 @@
*******************************************************************************/
package org.eclipse.jdt.internal.core.search;
+import java.util.Collections;
+import java.util.LinkedHashSet;
+import java.util.Set;
+
import org.eclipse.core.runtime.IProgressMonitor;
-import org.eclipse.jdt.core.search.*;
-import org.eclipse.jdt.internal.compiler.util.SimpleSet;
+import org.eclipse.jdt.core.search.IJavaSearchScope;
+import org.eclipse.jdt.core.search.SearchParticipant;
+import org.eclipse.jdt.core.search.SearchPattern;
import org.eclipse.jdt.internal.core.index.Index;
public class SubTypeSearchJob extends PatternSearchJob {
-SimpleSet indexes = new SimpleSet(5);
+Set<Index> indexes = Collections.synchronizedSet(new LinkedHashSet<>(5));
public SubTypeSearchJob(SearchPattern pattern, SearchParticipant participant, IJavaSearchScope scope, IndexQueryRequestor requestor) {
super(pattern, participant, scope, requestor);
}
public void finished() {
- Object[] values = this.indexes.values;
- for (int i = 0, l = values.length; i < l; i++)
- if (values[i] != null)
- ((Index) values[i]).stopQuery();
+ this.indexes.forEach(Index::stopQuery);
}
@Override
public Index[] getIndexes(IProgressMonitor progressMonitor) {
- if (this.indexes.elementSize == 0) {
+ if (this.indexes.isEmpty()) {
return super.getIndexes(progressMonitor);
}
this.areIndexesReady = true; // use stored indexes until the job's end
- Index[] values = new Index[this.indexes.elementSize];
- this.indexes.asArray(values);
- return values;
+ return this.indexes.toArray(new Index[0]);
}
@Override
-public boolean search(Index index, IProgressMonitor progressMonitor) {
+public boolean search(Index index, IndexQueryRequestor queryRequestor, IProgressMonitor progressMonitor) {
if (index == null) return COMPLETE;
- if (this.indexes.addIfNotIncluded(index) == index)
+ if (this.indexes.add(index)) {
index.startQuery();
- return super.search(index, progressMonitor);
+ }
+ return super.search(index, queryRequestor, progressMonitor);
}
}
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/UnindexedSearchScope.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/UnindexedSearchScope.java
index 5fdc740c07..089dfd5b65 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/UnindexedSearchScope.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/UnindexedSearchScope.java
@@ -97,4 +97,9 @@ public class UnindexedSearchScope extends AbstractSearchScope {
}
}
+ @Override
+ public boolean isParallelSearchSupported() {
+ return true;
+ }
+
}
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/AndPattern.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/AndPattern.java
index d2f7ed053f..959382a814 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/AndPattern.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/AndPattern.java
@@ -13,6 +13,9 @@
*******************************************************************************/
package org.eclipse.jdt.internal.core.search.matching;
+import java.util.stream.Stream;
+
+import org.eclipse.jdt.core.search.IParallelizable;
import org.eclipse.jdt.core.search.SearchPattern;
public class AndPattern extends IntersectingPattern {
@@ -77,4 +80,19 @@ protected void resetQuery() {
this.current = 0;
}
+@Override
+public boolean isParallelSearchSupported() {
+ return Stream.of(this.patterns).allMatch(IParallelizable::isParallelSearchSupported);
+}
+
+@Override
+public SearchPattern clone() throws CloneNotSupportedException {
+ AndPattern pattern = (AndPattern) super.clone();
+ pattern.patterns = this.patterns.clone();
+ for (int i = 0; i < this.patterns.length; i++) {
+ pattern.patterns[i] = this.patterns[i].clone();
+ }
+ return pattern;
+}
+
}
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/JavaSearchPattern.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/JavaSearchPattern.java
index d3b8ea525f..32438f3619 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/JavaSearchPattern.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/JavaSearchPattern.java
@@ -22,12 +22,13 @@ import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.Signature;
import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.core.search.IJavaSearchConstants;
+import org.eclipse.jdt.core.search.IParallelizable;
import org.eclipse.jdt.core.search.SearchPattern;
import org.eclipse.jdt.internal.core.search.indexing.IIndexConstants;
import org.eclipse.jdt.internal.core.util.Util;
-public class JavaSearchPattern extends SearchPattern implements IIndexConstants {
+public class JavaSearchPattern extends SearchPattern implements IIndexConstants, IParallelizable, Cloneable {
/*
* Whether this pattern is case sensitive.
@@ -454,4 +455,10 @@ public class JavaSearchPattern extends SearchPattern implements IIndexConstants
public final String toString() {
return print(new StringBuffer(30)).toString();
}
+
+ @Override
+ public boolean isParallelSearchSupported() {
+ return true;
+ }
+
}
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/OrPattern.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/OrPattern.java
index 9bec6f4d27..784510e020 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/OrPattern.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/OrPattern.java
@@ -14,6 +14,7 @@
package org.eclipse.jdt.internal.core.search.matching;
import java.io.IOException;
+import java.util.stream.Stream;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jdt.core.search.*;
@@ -21,7 +22,7 @@ import org.eclipse.jdt.internal.core.index.Index;
import org.eclipse.jdt.internal.core.search.IndexQueryRequestor;
import org.eclipse.jdt.internal.core.search.indexing.IIndexConstants;
-public class OrPattern extends SearchPattern implements IIndexConstants {
+public class OrPattern extends SearchPattern implements IIndexConstants, IParallelizable, Cloneable {
protected SearchPattern[] patterns;
@@ -119,4 +120,19 @@ public class OrPattern extends SearchPattern implements IIndexConstants {
}
return buffer.toString();
}
+
+ @Override
+ public boolean isParallelSearchSupported() {
+ return Stream.of(this.patterns).allMatch(IParallelizable::isParallelSearchSupported);
+ }
+
+ @Override
+ public SearchPattern clone() throws CloneNotSupportedException {
+ OrPattern pattern = (OrPattern) super.clone();
+ pattern.patterns = this.patterns.clone();
+ for (int i = 0; i < this.patterns.length; i++) {
+ pattern.patterns[i] = this.patterns[i].clone();
+ }
+ return pattern;
+ }
}

Back to the top