Bug 558664 - Cquery integration should be extracted from LSP Core

Part 6:
Declare SupportedProtocolExtensions interface to access contributed
LanguageProtocolExtension for a given language server.
Extract ResolvePreferredServer class.
Add ContributedProtocolExtensions OSGi component with tests.

Change-Id: Iecb1fff5a29a559e3c9d8703cc7d8fa71bb18042
Signed-off-by: Alexander Fedorov <alexander.fedorov@arsysop.ru>
This commit is contained in:
Alexander Fedorov 2020-08-19 20:01:30 +03:00
parent c609416622
commit 3efcecf379
12 changed files with 312 additions and 14 deletions

View file

@ -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());
}
}

View file

@ -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;
}
}

View file

@ -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;
}
}

View file

@ -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;

View file

@ -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

View file

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" name="org.eclipse.cdt.lsp.internal.core.ContributedProtocolExtensions">
<service>
<provide interface="org.eclipse.cdt.lsp.SupportedProtocolExtensions"/>
</service>
<reference bind="register" cardinality="0..n" interface="org.eclipse.cdt.lsp.LanguageProtocolExtension" name="register" unbind="unregister"/>
<implementation class="org.eclipse.cdt.lsp.internal.core.ContributedProtocolExtensions"/>
</scr:component>

View file

@ -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();
}

View file

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

View file

@ -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<LanguageProtocolExtension> all();
Collection<LanguageProtocolExtension> applicable(LanguageServerConfiguration server);
}

View file

@ -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();

View file

@ -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<String, List<LanguageProtocolExtension>> extensions;
public ContributedProtocolExtensions() {
extensions = new LinkedHashMap<>();
}
@Override
public Collection<LanguageProtocolExtension> all() {
return extensions.values().stream()//
.flatMap(List::stream)//
.collect(Collectors.toList());
}
@Override
public Collection<LanguageProtocolExtension> applicable(LanguageServerConfiguration server) {
return new ArrayList<>(extensions.getOrDefault(server.identifier(), Collections.emptyList()));
}
@Reference(cardinality = ReferenceCardinality.MULTIPLE)
public void register(LanguageProtocolExtension extension) {
List<LanguageProtocolExtension> list = extensions.computeIfAbsent(extension.targetIdentifier(),
x -> new ArrayList<>());
if (!list.contains(extension)) {
list.add(extension);
}
}
public void unregister(LanguageProtocolExtension extension) {
Optional<List<LanguageProtocolExtension>> optional = Optional
.ofNullable(extensions.get(extension.targetIdentifier()));
if (optional.isPresent()) {
List<LanguageProtocolExtension> list = optional.get();
list.remove(extension);
if (list.isEmpty()) {
extensions.remove(extension.targetIdentifier());
}
}
}
}

View file

@ -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<Class<?>, 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];
}
}