diff --git a/lsp/org.eclipse.cdt.lsp.core.tests/src/org/eclipse/cdt/lsp/internal/core/tests/ContributedProtocolExtensionsTest.java b/lsp/org.eclipse.cdt.lsp.core.tests/src/org/eclipse/cdt/lsp/internal/core/tests/ContributedProtocolExtensionsTest.java
new file mode 100644
index 00000000000..3c5381b4663
--- /dev/null
+++ b/lsp/org.eclipse.cdt.lsp.core.tests/src/org/eclipse/cdt/lsp/internal/core/tests/ContributedProtocolExtensionsTest.java
@@ -0,0 +1,55 @@
+/*******************************************************************************
+ * Copyright (c) 2020 ArSysOp 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:
+ * Alexander Fedorov (ArSysOp) - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.lsp.internal.core.tests;
+
+import static org.junit.Assert.assertEquals;
+
+import org.eclipse.cdt.lsp.LanguageProtocolExtension;
+import org.eclipse.cdt.lsp.LanguageServerConfiguration;
+import org.eclipse.cdt.lsp.internal.core.ContributedProtocolExtensions;
+import org.junit.Test;
+
+public class ContributedProtocolExtensionsTest {
+
+ private final LanguageServerConfiguration s1 = new FakeServerConfiguration("s1");
+ private final LanguageServerConfiguration s2 = new FakeServerConfiguration("s2");
+ private final LanguageServerConfiguration s3 = new FakeServerConfiguration("s3");
+ private final LanguageProtocolExtension p1s1 = new FakeProtocolExtension("s1");
+ private final LanguageProtocolExtension p2s1 = new FakeProtocolExtension("s1");
+ private final LanguageProtocolExtension p3s2 = new FakeProtocolExtension("s2");
+
+ @Test
+ public void positive() {
+ ContributedProtocolExtensions extensions = new ContributedProtocolExtensions();
+ assertEquals(0, extensions.all().size());
+ assertEquals(0, extensions.applicable(s1).size());
+ assertEquals(0, extensions.applicable(s2).size());
+ assertEquals(0, extensions.applicable(s3).size());
+ extensions.register(p1s1);
+ extensions.register(p2s1);
+ extensions.register(p3s2);
+ assertEquals(3, extensions.all().size());
+ assertEquals(2, extensions.applicable(s1).size());
+ assertEquals(1, extensions.applicable(s2).size());
+ assertEquals(0, extensions.applicable(s3).size());
+ extensions.unregister(p1s1);
+ extensions.unregister(p2s1);
+ extensions.unregister(p3s2);
+ assertEquals(0, extensions.all().size());
+ assertEquals(0, extensions.applicable(s1).size());
+ assertEquals(0, extensions.applicable(s2).size());
+ assertEquals(0, extensions.applicable(s3).size());
+ }
+
+}
diff --git a/lsp/org.eclipse.cdt.lsp.core.tests/src/org/eclipse/cdt/lsp/internal/core/tests/FakeProtocolExtension.java b/lsp/org.eclipse.cdt.lsp.core.tests/src/org/eclipse/cdt/lsp/internal/core/tests/FakeProtocolExtension.java
new file mode 100644
index 00000000000..35dae5bf75f
--- /dev/null
+++ b/lsp/org.eclipse.cdt.lsp.core.tests/src/org/eclipse/cdt/lsp/internal/core/tests/FakeProtocolExtension.java
@@ -0,0 +1,31 @@
+/*******************************************************************************
+ * Copyright (c) 2020 ArSysOp 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:
+ * Alexander Fedorov (ArSysOp) - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.lsp.internal.core.tests;
+
+import org.eclipse.cdt.lsp.LanguageProtocolExtension;
+
+public class FakeProtocolExtension implements LanguageProtocolExtension {
+
+ private final String id;
+
+ public FakeProtocolExtension(String id) {
+ this.id = id;
+ }
+
+ @Override
+ public String targetIdentifier() {
+ return id;
+ }
+
+}
diff --git a/lsp/org.eclipse.cdt.lsp.core.tests/src/org/eclipse/cdt/lsp/internal/core/tests/FakeServerConfiguration.java b/lsp/org.eclipse.cdt.lsp.core.tests/src/org/eclipse/cdt/lsp/internal/core/tests/FakeServerConfiguration.java
new file mode 100644
index 00000000000..8fe839138d3
--- /dev/null
+++ b/lsp/org.eclipse.cdt.lsp.core.tests/src/org/eclipse/cdt/lsp/internal/core/tests/FakeServerConfiguration.java
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * Copyright (c) 2020 ArSysOp 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:
+ * Alexander Fedorov (ArSysOp) - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.lsp.internal.core.tests;
+
+import java.net.URI;
+
+import org.eclipse.cdt.lsp.LanguageServerConfiguration;
+
+public class FakeServerConfiguration implements LanguageServerConfiguration {
+
+ private final String id;
+
+ public FakeServerConfiguration(String id) {
+ this.id = id;
+ }
+
+ @Override
+ public String identifier() {
+ return id;
+ }
+
+ @Override
+ public String label() {
+ return id;
+ }
+
+ @Override
+ public Object options(Object defaults, URI uri) {
+ return defaults;
+ }
+
+}
diff --git a/lsp/org.eclipse.cdt.lsp.core.tests/src/org/eclipse/cdt/lsp/core/tests/ShowStatusTest.java b/lsp/org.eclipse.cdt.lsp.core.tests/src/org/eclipse/cdt/lsp/internal/core/tests/ShowStatusTest.java
similarity index 96%
rename from lsp/org.eclipse.cdt.lsp.core.tests/src/org/eclipse/cdt/lsp/core/tests/ShowStatusTest.java
rename to lsp/org.eclipse.cdt.lsp.core.tests/src/org/eclipse/cdt/lsp/internal/core/tests/ShowStatusTest.java
index cf9d15a0b4f..d3386d539e8 100644
--- a/lsp/org.eclipse.cdt.lsp.core.tests/src/org/eclipse/cdt/lsp/core/tests/ShowStatusTest.java
+++ b/lsp/org.eclipse.cdt.lsp.core.tests/src/org/eclipse/cdt/lsp/internal/core/tests/ShowStatusTest.java
@@ -11,7 +11,7 @@
* Contributors:
* Alexander Fedorov (ArSysOp) - initial API and implementation
*******************************************************************************/
-package org.eclipse.cdt.lsp.core.tests;
+package org.eclipse.cdt.lsp.internal.core.tests;
import static org.junit.Assert.assertEquals;
diff --git a/lsp/org.eclipse.cdt.lsp.core/META-INF/MANIFEST.MF b/lsp/org.eclipse.cdt.lsp.core/META-INF/MANIFEST.MF
index f361e02d61c..1f10dcf4912 100644
--- a/lsp/org.eclipse.cdt.lsp.core/META-INF/MANIFEST.MF
+++ b/lsp/org.eclipse.cdt.lsp.core/META-INF/MANIFEST.MF
@@ -35,4 +35,5 @@ Bundle-Activator: org.eclipse.cdt.lsp.core.Activator
Bundle-ActivationPolicy: lazy
Service-Component: OSGI-INF/org.eclipse.cdt.lsp.internal.core.ContributedLanguageServers.xml,
OSGI-INF/org.eclipse.cdt.internal.clangd.ClangdLanguageServer.xml,
- OSGI-INF/org.eclipse.cdt.internal.cquery.CqueryLanguageServer.xml
+ OSGI-INF/org.eclipse.cdt.internal.cquery.CqueryLanguageServer.xml,
+ OSGI-INF/org.eclipse.cdt.lsp.internal.core.ContributedProtocolExtensions.xml
diff --git a/lsp/org.eclipse.cdt.lsp.core/OSGI-INF/org.eclipse.cdt.lsp.internal.core.ContributedProtocolExtensions.xml b/lsp/org.eclipse.cdt.lsp.core/OSGI-INF/org.eclipse.cdt.lsp.internal.core.ContributedProtocolExtensions.xml
new file mode 100644
index 00000000000..7f69e40edea
--- /dev/null
+++ b/lsp/org.eclipse.cdt.lsp.core/OSGI-INF/org.eclipse.cdt.lsp.internal.core.ContributedProtocolExtensions.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/lsp/org.eclipse.cdt.lsp.core/src/org/eclipse/cdt/lsp/LanguageProtocolExtension.java b/lsp/org.eclipse.cdt.lsp.core/src/org/eclipse/cdt/lsp/LanguageProtocolExtension.java
new file mode 100644
index 00000000000..e3e23a6b98c
--- /dev/null
+++ b/lsp/org.eclipse.cdt.lsp.core/src/org/eclipse/cdt/lsp/LanguageProtocolExtension.java
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * Copyright (c) 2020 ArSysOp 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:
+ * Alexander Fedorov (ArSysOp) - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.lsp;
+
+import org.eclipse.lsp4j.jsonrpc.services.ServiceEndpoints;
+
+/**
+ *
+ * Declares the language protocol extension methods.
+ *
+ * @see ServiceEndpoints#getSupportedMethods(Class)
+ *
+ */
+public interface LanguageProtocolExtension {
+
+ /**
+ *
+ * @return the identifier of the target language server
+ * @see LanguageServerConfiguration#identifier()
+ */
+ String targetIdentifier();
+
+}
diff --git a/lsp/org.eclipse.cdt.lsp.core/src/org/eclipse/cdt/lsp/SupportedLanguageServers.java b/lsp/org.eclipse.cdt.lsp.core/src/org/eclipse/cdt/lsp/SupportedLanguageServers.java
index 6ab396c2025..72f25e28f97 100644
--- a/lsp/org.eclipse.cdt.lsp.core/src/org/eclipse/cdt/lsp/SupportedLanguageServers.java
+++ b/lsp/org.eclipse.cdt.lsp.core/src/org/eclipse/cdt/lsp/SupportedLanguageServers.java
@@ -17,7 +17,7 @@ import java.util.Collection;
/**
*
- * Provides access to configurations of supported language servers.
+ * Provides access to the configurations of supported language servers.
*
*/
public interface SupportedLanguageServers {
diff --git a/lsp/org.eclipse.cdt.lsp.core/src/org/eclipse/cdt/lsp/SupportedProtocolExtensions.java b/lsp/org.eclipse.cdt.lsp.core/src/org/eclipse/cdt/lsp/SupportedProtocolExtensions.java
new file mode 100644
index 00000000000..95e55302c9a
--- /dev/null
+++ b/lsp/org.eclipse.cdt.lsp.core/src/org/eclipse/cdt/lsp/SupportedProtocolExtensions.java
@@ -0,0 +1,29 @@
+/*******************************************************************************
+ * Copyright (c) 2020 ArSysOp 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:
+ * Alexander Fedorov (ArSysOp) - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.lsp;
+
+import java.util.Collection;
+
+/**
+ *
+ * Provides access to the language protocol extensions.
+ *
+ */
+public interface SupportedProtocolExtensions {
+
+ Collection all();
+
+ Collection applicable(LanguageServerConfiguration server);
+
+}
diff --git a/lsp/org.eclipse.cdt.lsp.core/src/org/eclipse/cdt/lsp/core/CPPStreamConnectionProvider.java b/lsp/org.eclipse.cdt.lsp.core/src/org/eclipse/cdt/lsp/core/CPPStreamConnectionProvider.java
index 64f08f82424..522fe7a9dc2 100644
--- a/lsp/org.eclipse.cdt.lsp.core/src/org/eclipse/cdt/lsp/core/CPPStreamConnectionProvider.java
+++ b/lsp/org.eclipse.cdt.lsp.core/src/org/eclipse/cdt/lsp/core/CPPStreamConnectionProvider.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2017-2020 Ericsson and others.
+ * Copyright (c) 2017, 2020 Ericsson and others.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
@@ -25,14 +25,13 @@ import java.util.Arrays;
import java.util.List;
import org.eclipse.cdt.lsp.LanguageServerConfiguration;
-import org.eclipse.cdt.lsp.SupportedLanguageServers;
+import org.eclipse.cdt.lsp.internal.core.ResolvePreferredServer;
import org.eclipse.cdt.utils.CommandLineUtil;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResourceChangeListener;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.Platform;
-import org.eclipse.core.runtime.ServiceCaller;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.lsp4e.server.ProcessStreamConnectionProvider;
@@ -47,7 +46,7 @@ public class CPPStreamConnectionProvider extends ProcessStreamConnectionProvider
private final LanguageServerConfiguration configuration;
public CPPStreamConnectionProvider() throws UnsupportedOperationException {
- configuration = configuration();
+ configuration = new ResolvePreferredServer().apply(getClass());
File defaultLSLocation = getDefaultLSLocation(configuration.identifier());
if (defaultLSLocation != null) {
store.setDefault(PreferenceConstants.P_SERVER_PATH, defaultLSLocation.getAbsolutePath());
@@ -67,13 +66,6 @@ public class CPPStreamConnectionProvider extends ProcessStreamConnectionProvider
setCommands(commands);
}
- private LanguageServerConfiguration configuration() {
- final LanguageServerConfiguration[] configs = new LanguageServerConfiguration[1];
- ServiceCaller.callOnce(CPPStreamConnectionProvider.class, SupportedLanguageServers.class,
- x -> configs[0] = x.preferred());
- return configs[0];
- }
-
@Override
public void stop() {
super.stop();
diff --git a/lsp/org.eclipse.cdt.lsp.core/src/org/eclipse/cdt/lsp/internal/core/ContributedProtocolExtensions.java b/lsp/org.eclipse.cdt.lsp.core/src/org/eclipse/cdt/lsp/internal/core/ContributedProtocolExtensions.java
new file mode 100644
index 00000000000..7131a66be21
--- /dev/null
+++ b/lsp/org.eclipse.cdt.lsp.core/src/org/eclipse/cdt/lsp/internal/core/ContributedProtocolExtensions.java
@@ -0,0 +1,74 @@
+/*******************************************************************************
+ * Copyright (c) 2020 ArSysOp 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:
+ * Alexander Fedorov (ArSysOp) - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.lsp.internal.core;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.stream.Collectors;
+
+import org.eclipse.cdt.lsp.LanguageProtocolExtension;
+import org.eclipse.cdt.lsp.LanguageServerConfiguration;
+import org.eclipse.cdt.lsp.SupportedProtocolExtensions;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Reference;
+import org.osgi.service.component.annotations.ReferenceCardinality;
+
+@Component
+public final class ContributedProtocolExtensions implements SupportedProtocolExtensions {
+
+ private final Map> extensions;
+
+ public ContributedProtocolExtensions() {
+ extensions = new LinkedHashMap<>();
+ }
+
+ @Override
+ public Collection all() {
+ return extensions.values().stream()//
+ .flatMap(List::stream)//
+ .collect(Collectors.toList());
+ }
+
+ @Override
+ public Collection applicable(LanguageServerConfiguration server) {
+ return new ArrayList<>(extensions.getOrDefault(server.identifier(), Collections.emptyList()));
+ }
+
+ @Reference(cardinality = ReferenceCardinality.MULTIPLE)
+ public void register(LanguageProtocolExtension extension) {
+ List list = extensions.computeIfAbsent(extension.targetIdentifier(),
+ x -> new ArrayList<>());
+ if (!list.contains(extension)) {
+ list.add(extension);
+ }
+ }
+
+ public void unregister(LanguageProtocolExtension extension) {
+ Optional> optional = Optional
+ .ofNullable(extensions.get(extension.targetIdentifier()));
+ if (optional.isPresent()) {
+ List list = optional.get();
+ list.remove(extension);
+ if (list.isEmpty()) {
+ extensions.remove(extension.targetIdentifier());
+ }
+ }
+ }
+
+}
diff --git a/lsp/org.eclipse.cdt.lsp.core/src/org/eclipse/cdt/lsp/internal/core/ResolvePreferredServer.java b/lsp/org.eclipse.cdt.lsp.core/src/org/eclipse/cdt/lsp/internal/core/ResolvePreferredServer.java
new file mode 100644
index 00000000000..90d0895d6f3
--- /dev/null
+++ b/lsp/org.eclipse.cdt.lsp.core/src/org/eclipse/cdt/lsp/internal/core/ResolvePreferredServer.java
@@ -0,0 +1,31 @@
+/*******************************************************************************
+ * Copyright (c) 2020 ArSysOp 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:
+ * Alexander Fedorov (ArSysOp) - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.lsp.internal.core;
+
+import java.util.function.Function;
+
+import org.eclipse.cdt.lsp.LanguageServerConfiguration;
+import org.eclipse.cdt.lsp.SupportedLanguageServers;
+import org.eclipse.core.runtime.ServiceCaller;
+
+public final class ResolvePreferredServer implements Function, LanguageServerConfiguration> {
+
+ @Override
+ public LanguageServerConfiguration apply(Class> caller) {
+ LanguageServerConfiguration[] configs = new LanguageServerConfiguration[1];
+ ServiceCaller.callOnce(caller, SupportedLanguageServers.class, x -> configs[0] = x.preferred());
+ return configs[0];
+ }
+
+}