diff --git a/org.eclipse.jdt.ls.core/plugin.xml b/org.eclipse.jdt.ls.core/plugin.xml
index 9188d895a8..4de51d6e89 100644
--- a/org.eclipse.jdt.ls.core/plugin.xml
+++ b/org.eclipse.jdt.ls.core/plugin.xml
@@ -4,6 +4,7 @@
+
@@ -115,4 +116,28 @@
order="1500"
class="org.eclipse.jdt.ls.core.internal.managers.InvisibleProjectImporter" />
+
+
+
+
+
+
+
diff --git a/org.eclipse.jdt.ls.core/schema/org.eclipse.jdt.ls.core.buildSupport.exsd b/org.eclipse.jdt.ls.core/schema/org.eclipse.jdt.ls.core.buildSupport.exsd
new file mode 100644
index 0000000000..84c37ea0b9
--- /dev/null
+++ b/org.eclipse.jdt.ls.core/schema/org.eclipse.jdt.ls.core.buildSupport.exsd
@@ -0,0 +1,101 @@
+
+
+
+
+
+
+
+
+ This extension point represents different kinds of project build supporters for the JDT LS.
+Each extension must implement <code>org.eclipse.jdt.ls.core.internal.managers.IBuildSupport</code>.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ a fully qualified identifier of the target extension point
+
+
+
+
+
+
+ an optional identifier of the extension instance
+
+
+
+
+
+
+ an optional name of the extension instance
+
+
+
+
+
+
+
+
+
+
+
+ A unique identifier that can be used to reference this IBuildSupport.
+
+
+
+
+
+
+ The class that implements this build support. The class must implement IBuildSupport.
+
+
+
+
+
+
+
+
+
+ The query order of the build support. Lowest value has the highest priority.
+
+
+
+
+
+
+
+
+
+
+
+
+ The following is an example of a language server content provider extension:
+
+<pre>
+ <extension
+ id="buildSupport"
+ point="org.eclipse.jdt.ls.core.buildSupport">
+ <buildSupport
+ id="someBuildSupport"
+ order="200"
+ class="com.example.SomeBuildSupport" />
+ </extension>
+</pre>
+
+
+
+
+
+
+
diff --git a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/managers/DefaultProjectBuildSupport.java b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/managers/DefaultProjectBuildSupport.java
index c3cb493683..1690fa02c2 100644
--- a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/managers/DefaultProjectBuildSupport.java
+++ b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/managers/DefaultProjectBuildSupport.java
@@ -13,18 +13,13 @@
package org.eclipse.jdt.ls.core.internal.managers;
import org.eclipse.core.resources.IProject;
+import org.eclipse.jdt.ls.core.internal.JavaLanguageServerPlugin;
public class DefaultProjectBuildSupport extends EclipseBuildSupport implements IBuildSupport {
- private ProjectsManager projectManager;
-
- public DefaultProjectBuildSupport(ProjectsManager projectManager) {
- this.projectManager = projectManager;
- }
-
@Override
public boolean applies(IProject project) {
- return projectManager.getDefaultProject().equals(project);
+ return JavaLanguageServerPlugin.getProjectsManager().getDefaultProject().equals(project);
}
}
diff --git a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/managers/GradleBuildSupport.java b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/managers/GradleBuildSupport.java
index c4d15b1341..d6d29791a2 100644
--- a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/managers/GradleBuildSupport.java
+++ b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/managers/GradleBuildSupport.java
@@ -14,6 +14,8 @@
import java.io.File;
import java.nio.file.Paths;
+import java.util.Arrays;
+import java.util.List;
import java.util.Optional;
import org.eclipse.buildship.core.BuildConfiguration;
@@ -45,6 +47,7 @@ public class GradleBuildSupport implements IBuildSupport {
public static final String GRADLE_SUFFIX = ".gradle";
public static final String GRADLE_PROPERTIES = "gradle.properties";
+ public static final List WATCH_FILE_PATTERNS = Arrays.asList("**/*.gradle", "**/gradle.properties");
@Override
public boolean applies(IProject project) {
@@ -131,4 +134,10 @@ public static void saveModels() {
public ILaunchConfiguration getLaunchConfiguration(IJavaProject javaProject, String scope) throws CoreException {
return new JavaApplicationLaunchConfiguration(javaProject.getProject(), scope, GradleClasspathProvider.ID);
}
+
+ @Override
+ public List getWatchPatterns() {
+ return WATCH_FILE_PATTERNS;
+ }
+
}
diff --git a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/managers/IBuildSupport.java b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/managers/IBuildSupport.java
index 25491fdbb0..c27f605f97 100644
--- a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/managers/IBuildSupport.java
+++ b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/managers/IBuildSupport.java
@@ -12,6 +12,9 @@
*******************************************************************************/
package org.eclipse.jdt.ls.core.internal.managers;
+import java.util.Collections;
+import java.util.List;
+
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
@@ -109,4 +112,8 @@ default ILaunchConfiguration getLaunchConfiguration(IJavaProject javaProject, St
return new JavaApplicationLaunchConfiguration(javaProject.getProject(), scope, null);
}
+ default List getWatchPatterns() {
+ return Collections.emptyList();
+ }
+
}
diff --git a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/managers/MavenBuildSupport.java b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/managers/MavenBuildSupport.java
index 255fdffaa8..7ab89e7965 100644
--- a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/managers/MavenBuildSupport.java
+++ b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/managers/MavenBuildSupport.java
@@ -14,6 +14,7 @@
import java.nio.file.Path;
import java.util.Collection;
+import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
@@ -57,6 +58,7 @@
public class MavenBuildSupport implements IBuildSupport {
private static final int MAX_TIME_MILLIS = 3000;
+ private static final List WATCH_FILE_PATTERNS = Collections.singletonList("**/pom.xml");
private static Cache downloadRequestsCache = CacheBuilder.newBuilder().maximumSize(100).expireAfterWrite(1, TimeUnit.HOURS).build();
private IProjectConfigurationManager configurationManager;
@@ -185,4 +187,10 @@ public void discoverSource(IClassFile classFile, IProgressMonitor monitor) throw
public ILaunchConfiguration getLaunchConfiguration(IJavaProject javaProject, String scope) throws CoreException {
return new JavaApplicationLaunchConfiguration(javaProject.getProject(), scope, MavenRuntimeClasspathProvider.MAVEN_CLASSPATH_PROVIDER);
}
+
+ @Override
+ public List getWatchPatterns() {
+ return WATCH_FILE_PATTERNS;
+ }
+
}
diff --git a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/managers/StandardProjectsManager.java b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/managers/StandardProjectsManager.java
index af0ccac75d..180c52e866 100644
--- a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/managers/StandardProjectsManager.java
+++ b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/managers/StandardProjectsManager.java
@@ -28,8 +28,10 @@
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
+import java.util.Map;
import java.util.Optional;
import java.util.Set;
+import java.util.TreeMap;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@@ -42,11 +44,14 @@
import org.eclipse.core.resources.ISaveContext;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IExtensionPoint;
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.Path;
+import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.SubMonitor;
import org.eclipse.core.runtime.jobs.Job;
@@ -55,6 +60,7 @@
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.ls.core.internal.ActionableNotification;
+import org.eclipse.jdt.ls.core.internal.IConstants;
import org.eclipse.jdt.ls.core.internal.JDTUtils;
import org.eclipse.jdt.ls.core.internal.JavaLanguageServerPlugin;
import org.eclipse.jdt.ls.core.internal.JobHelpers;
@@ -72,14 +78,12 @@
import org.eclipse.lsp4j.WatchKind;
public class StandardProjectsManager extends ProjectsManager {
+ protected static final String BUILD_SUPPORT_EXTENSION_POINT_ID = "buildSupport";
private static final Set watchers = new LinkedHashSet<>();
private PreferenceManager preferenceManager;
//@formatter:off
private static final List basicWatchers = Arrays.asList(
"**/*.java",
- "**/pom.xml",
- "**/*.gradle",
- "**/gradle.properties",
"**/.project",
"**/.classpath",
"**/.settings/*.prefs",
@@ -272,8 +276,19 @@ public Optional getBuildSupport(IProject project) {
return buildSupports().filter(bs -> bs.applies(project)).findFirst();
}
- private Stream buildSupports() {
- return Stream.of(new GradleBuildSupport(), new MavenBuildSupport(), new InvisibleProjectBuildSupport(), new DefaultProjectBuildSupport(this), new EclipseBuildSupport());
+ protected Stream buildSupports() {
+ Map supporters = new TreeMap<>();
+ IExtensionPoint extensionPoint = Platform.getExtensionRegistry().getExtensionPoint(IConstants.PLUGIN_ID, BUILD_SUPPORT_EXTENSION_POINT_ID);
+ IConfigurationElement[] configs = extensionPoint.getConfigurationElements();
+ for (IConfigurationElement config : configs) {
+ try {
+ Integer order = Integer.valueOf(config.getAttribute("order"));
+ supporters.put(order, (IBuildSupport) config.createExecutableExtension("class")); //$NON-NLS-1$
+ } catch (CoreException e) {
+ JavaLanguageServerPlugin.logError(config.getAttribute("class") + " implementation was skipped \n" + e.getStatus());
+ }
+ }
+ return supporters.values().stream();
}
@Override
@@ -302,6 +317,7 @@ public List registerWatchers() {
logInfo(">> registerFeature 'workspace/didChangeWatchedFiles'");
if (preferenceManager.getClientPreferences().isWorkspaceChangeWatchedFilesDynamicRegistered()) {
Set patterns = new LinkedHashSet<>(basicWatchers);
+ buildSupports().forEach(e -> e.getWatchPatterns().forEach(patterns::add));
Set sources = new HashSet<>();
IProject[] projects = ResourcesPlugin.getWorkspace().getRoot().getProjects();
try {
diff --git a/org.eclipse.jdt.ls.tests/src/org/eclipse/jdt/ls/core/internal/managers/StandardProjectManagerTest.java b/org.eclipse.jdt.ls.tests/src/org/eclipse/jdt/ls/core/internal/managers/StandardProjectManagerTest.java
new file mode 100644
index 0000000000..6fca84102a
--- /dev/null
+++ b/org.eclipse.jdt.ls.tests/src/org/eclipse/jdt/ls/core/internal/managers/StandardProjectManagerTest.java
@@ -0,0 +1,58 @@
+/*******************************************************************************
+ * Copyright (c) 2020 Red Hat Inc. and others.
+ * All rights reserved. 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
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ * Red Hat Inc. - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.ls.core.internal.managers;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.mock;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import org.eclipse.jdt.ls.core.internal.preferences.PreferenceManager;
+import org.eclipse.jdt.ls.core.internal.preferences.StandardPreferenceManager;
+import org.junit.Test;
+
+/**
+ * @author siarhei_leanavets1
+ *
+ */
+public class StandardProjectManagerTest {
+
+ private class StandardProjectsManagerDummy extends StandardProjectsManager {
+ /**
+ * @param preferenceManager
+ */
+ public StandardProjectsManagerDummy(PreferenceManager preferenceManager) {
+ super(preferenceManager);
+ }
+
+ @Override
+ public Stream buildSupports() {
+ return super.buildSupports();
+ }
+ }
+
+ @Test
+ public void testCheckBuildSupportOrder() {
+ PreferenceManager preferenceManager = mock(StandardPreferenceManager.class);
+ StandardProjectsManagerDummy projectsManagerDummy = new StandardProjectsManagerDummy(preferenceManager);
+ List> expectedList = Arrays.asList(GradleBuildSupport.class, MavenBuildSupport.class, InvisibleProjectBuildSupport.class, DefaultProjectBuildSupport.class, EclipseBuildSupport.class);
+ List actualList = projectsManagerDummy.buildSupports().collect(Collectors.toList());
+ for (int i = 0; i < expectedList.size(); i++) {
+ assertEquals(expectedList.get(i), actualList.get(i).getClass());
+ }
+ }
+
+}