Start decomposing CF language server into beans t
Instead of explicitly instantiating a SimpleLanguageServer subclass, let autoconf create and configure it.
This commit is contained in:
@@ -0,0 +1,24 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2018 Pivotal, Inc.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* Pivotal, Inc. - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.springframework.ide.vscode.commons.languageserver.config;
|
||||
|
||||
import org.springframework.ide.vscode.commons.languageserver.util.SimpleLanguageServer;
|
||||
|
||||
/**
|
||||
* Callback to apply configuration to a {@link SimpleLanguageServer}. THis callback is
|
||||
* called meant to be called on a newly instantiated SimpleLanguageServer, right after it
|
||||
* was created (and prior to actually starting the language server).
|
||||
*
|
||||
* @author Kris De Volder
|
||||
*/
|
||||
public interface LanguageServerInitializer {
|
||||
void initialize(SimpleLanguageServer server) throws Exception;
|
||||
}
|
||||
@@ -167,7 +167,7 @@ public class SimpleLanguageServer implements Sts4LanguageServer, LanguageClientA
|
||||
return null;
|
||||
}
|
||||
|
||||
protected synchronized QuickfixRegistry getQuickfixRegistry() {
|
||||
public synchronized QuickfixRegistry getQuickfixRegistry() {
|
||||
if (quickfixRegistry==null) {
|
||||
quickfixRegistry = new QuickfixRegistry();
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ import org.springframework.boot.context.properties.EnableConfigurationProperties
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.ide.vscode.commons.languageserver.LanguageServerRunner;
|
||||
import org.springframework.ide.vscode.commons.languageserver.config.LanguageServerInitializer;
|
||||
import org.springframework.ide.vscode.commons.languageserver.config.LanguageServerProperties;
|
||||
import org.springframework.ide.vscode.commons.languageserver.util.SimpleLanguageServer;
|
||||
|
||||
@@ -32,8 +33,10 @@ public class LanguageServerAutoconf {
|
||||
}
|
||||
|
||||
@ConditionalOnMissingBean
|
||||
@Bean public SimpleLanguageServer languageServer(LanguageServerProperties props) {
|
||||
return new SimpleLanguageServer(props.getExtensionId());
|
||||
@Bean public SimpleLanguageServer languageServer(LanguageServerProperties props, LanguageServerInitializer initializer) throws Exception {
|
||||
SimpleLanguageServer server = new SimpleLanguageServer(props.getExtensionId());
|
||||
initializer.initialize(server);
|
||||
return server;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -99,6 +99,7 @@ import org.springframework.ide.vscode.commons.languageserver.JavadocResponse;
|
||||
import org.springframework.ide.vscode.commons.languageserver.ProgressParams;
|
||||
import org.springframework.ide.vscode.commons.languageserver.STS4LanguageClient;
|
||||
import org.springframework.ide.vscode.commons.languageserver.completion.DocumentEdits;
|
||||
import org.springframework.ide.vscode.commons.languageserver.config.LanguageServerInitializer;
|
||||
import org.springframework.ide.vscode.commons.languageserver.jdt.ls.ClasspathListenerParams;
|
||||
import org.springframework.ide.vscode.commons.languageserver.quickfix.QuickfixEdit.CursorMovement;
|
||||
import org.springframework.ide.vscode.commons.languageserver.util.LanguageServerTestListener;
|
||||
@@ -147,6 +148,15 @@ public class LanguageServerHarness<S extends SimpleLanguageServerWrapper> {
|
||||
|
||||
public static final Duration HIGHLIGHTS_TIMEOUT = Duration.ofMillis(15000000000L); //Why so long?
|
||||
|
||||
public static LanguageServerHarness<SimpleLanguageServer> create(String extensionId, LanguageServerInitializer initializer) throws Exception {
|
||||
Callable<SimpleLanguageServer> factory = () -> {
|
||||
SimpleLanguageServer s = new SimpleLanguageServer(extensionId);
|
||||
initializer.initialize(s);
|
||||
return s;
|
||||
};
|
||||
return new LanguageServerHarness<>(factory);
|
||||
}
|
||||
|
||||
public LanguageServerHarness(Callable<S> factory) throws Exception {
|
||||
this(factory, LanguageId.PLAINTEXT);
|
||||
}
|
||||
|
||||
@@ -14,7 +14,6 @@ import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.ide.vscode.commons.util.LogRedirect;
|
||||
import org.springframework.ide.vscode.commons.yaml.completion.YamlCompletionEngineOptions;
|
||||
|
||||
@SpringBootApplication
|
||||
public class ManifestYamlLanguageServerBootApp {
|
||||
@@ -29,9 +28,4 @@ public class ManifestYamlLanguageServerBootApp {
|
||||
@Bean public String serverName() {
|
||||
return SERVER_NAME;
|
||||
}
|
||||
|
||||
@Bean ManifestYamlLanguageServer languageServer() {
|
||||
return new ManifestYamlLanguageServer();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ import java.util.List;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.ide.vscode.commons.cloudfoundry.client.ClientTimeouts;
|
||||
import org.springframework.ide.vscode.commons.cloudfoundry.client.CloudFoundryClientFactory;
|
||||
import org.springframework.ide.vscode.commons.cloudfoundry.client.cftarget.CFTargetCache;
|
||||
@@ -26,6 +27,7 @@ import org.springframework.ide.vscode.commons.cloudfoundry.client.cftarget.Clien
|
||||
import org.springframework.ide.vscode.commons.cloudfoundry.client.cftarget.NoTargetsException;
|
||||
import org.springframework.ide.vscode.commons.cloudfoundry.client.v2.DefaultCloudFoundryClientFactoryV2;
|
||||
import org.springframework.ide.vscode.commons.languageserver.completion.VscodeCompletionEngineAdapter;
|
||||
import org.springframework.ide.vscode.commons.languageserver.config.LanguageServerInitializer;
|
||||
import org.springframework.ide.vscode.commons.languageserver.hover.HoverInfoProvider;
|
||||
import org.springframework.ide.vscode.commons.languageserver.hover.VscodeHoverEngineAdapter;
|
||||
import org.springframework.ide.vscode.commons.languageserver.reconcile.IReconcileEngine;
|
||||
@@ -48,33 +50,33 @@ import org.springframework.ide.vscode.commons.yaml.reconcile.TypeBasedYamlSymbol
|
||||
import org.springframework.ide.vscode.commons.yaml.reconcile.YamlSchemaBasedReconcileEngine;
|
||||
import org.springframework.ide.vscode.commons.yaml.schema.YValueHint;
|
||||
import org.springframework.ide.vscode.commons.yaml.structure.YamlStructureProvider;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.Assert;
|
||||
import org.yaml.snakeyaml.Yaml;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
|
||||
public class ManifestYamlLanguageServer extends SimpleLanguageServer {
|
||||
@Component
|
||||
public class ManifestYamlLanguageServerInitializer implements LanguageServerInitializer {
|
||||
|
||||
private Yaml yaml = new Yaml();
|
||||
private CfJson cfJson = new CfJson();
|
||||
private ManifestYmlSchema schema;
|
||||
private CFTargetCache cfTargetCache;
|
||||
|
||||
private final ImmutableSet<LanguageId> FALLBACK_YML_IDS = ImmutableSet.of(LanguageId.of("yml"), LanguageId.of("yaml"));
|
||||
final private ClientParamsProvider defaultClientParamsProvider;
|
||||
|
||||
public ManifestYamlLanguageServer() {
|
||||
this(DefaultCloudFoundryClientFactoryV2.INSTANCE, CfCliParamsProvider.getInstance());
|
||||
}
|
||||
|
||||
public ManifestYamlLanguageServer(CloudFoundryClientFactory cfClientFactory, ClientParamsProvider defaultClientParamsProvider) {
|
||||
super("vscode-manifest-yaml");
|
||||
this.defaultClientParamsProvider = defaultClientParamsProvider;
|
||||
private CloudFoundryClientFactory cfClientFactory;
|
||||
ClientParamsProvider defaultClientParamsProvider;
|
||||
private SimpleLanguageServer server;
|
||||
|
||||
@Override
|
||||
public void initialize(SimpleLanguageServer server) throws Exception {
|
||||
Assert.isNull(this.server, "This initializer should only be called once");
|
||||
this.server = server;
|
||||
this.cfTargetCache = new CFTargetCache(ImmutableList.of(this.defaultClientParamsProvider), cfClientFactory, new ClientTimeouts());
|
||||
|
||||
SimpleTextDocumentService documents = getTextDocumentService();
|
||||
SimpleWorkspaceService workspace = getWorkspaceService();
|
||||
SimpleTextDocumentService documents = server.getTextDocumentService();
|
||||
SimpleWorkspaceService workspace = server.getWorkspaceService();
|
||||
|
||||
YamlASTProvider parser = new YamlParser(yaml);
|
||||
|
||||
@@ -83,10 +85,10 @@ public class ManifestYamlLanguageServer extends SimpleLanguageServer {
|
||||
YamlStructureProvider structureProvider = YamlStructureProvider.DEFAULT;
|
||||
YamlAssistContextProvider contextProvider = new SchemaBasedYamlAssistContextProvider(schema);
|
||||
YamlCompletionEngine yamlCompletionEngine = new YamlCompletionEngine(structureProvider, contextProvider, YamlCompletionEngineOptions.DEFAULT);
|
||||
VscodeCompletionEngineAdapter completionEngine = createCompletionEngineAdapter(this, yamlCompletionEngine);
|
||||
VscodeCompletionEngineAdapter completionEngine = server.createCompletionEngineAdapter(server, yamlCompletionEngine);
|
||||
HoverInfoProvider infoProvider = new YamlHoverInfoProvider(parser, structureProvider, contextProvider);
|
||||
HoverHandler hoverEngine = new VscodeHoverEngineAdapter(this, infoProvider);
|
||||
YamlQuickfixes quickfixes = new YamlQuickfixes(getQuickfixRegistry(), getTextDocumentService(), structureProvider);
|
||||
HoverHandler hoverEngine = new VscodeHoverEngineAdapter(server, infoProvider);
|
||||
YamlQuickfixes quickfixes = new YamlQuickfixes(server.getQuickfixRegistry(), server.getTextDocumentService(), structureProvider);
|
||||
YamlSchemaBasedReconcileEngine engine = new YamlSchemaBasedReconcileEngine(parser, schema, quickfixes);
|
||||
|
||||
ASTTypeCache astTypeCache = new ASTTypeCache();
|
||||
@@ -128,6 +130,19 @@ public class ManifestYamlLanguageServer extends SimpleLanguageServer {
|
||||
applyCfLoginParameterSettings(info);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
private final ImmutableSet<LanguageId> FALLBACK_YML_IDS = ImmutableSet.of(LanguageId.of("yml"), LanguageId.of("yaml"));
|
||||
|
||||
@Autowired
|
||||
public ManifestYamlLanguageServerInitializer() {
|
||||
this(DefaultCloudFoundryClientFactoryV2.INSTANCE, CfCliParamsProvider.getInstance());
|
||||
}
|
||||
|
||||
public ManifestYamlLanguageServerInitializer(CloudFoundryClientFactory cfClientFactory, ClientParamsProvider defaultClientParamsProvider) {
|
||||
this.cfClientFactory = cfClientFactory;
|
||||
this.defaultClientParamsProvider = defaultClientParamsProvider;
|
||||
}
|
||||
|
||||
private void applyCfLoginParameterSettings(CfTargetsInfo info) {
|
||||
@@ -143,13 +158,13 @@ public class ManifestYamlLanguageServer extends SimpleLanguageServer {
|
||||
//
|
||||
// this FALLBACK_YML_ID got introduced to workaround a limitation in LSP4E, which sets the file extension as language ID to the document
|
||||
//
|
||||
validateWith(doc.getId(), engine);
|
||||
server.validateWith(doc.getId(), engine);
|
||||
} else {
|
||||
validateWith(doc.getId(), IReconcileEngine.NULL);
|
||||
server.validateWith(doc.getId(), IReconcileEngine.NULL);
|
||||
}
|
||||
}
|
||||
|
||||
protected ManifestYmlHintProviders getHintProviders() {
|
||||
private ManifestYmlHintProviders getHintProviders() {
|
||||
Callable<Collection<YValueHint>> buildPacksProvider = new ManifestYamlCFBuildpacksProvider(getCfTargetCache());
|
||||
Callable<Collection<YValueHint>> servicesProvider = new ManifestYamlCFServicesProvider(getCfTargetCache());
|
||||
Callable<Collection<YValueHint>> domainsProvider = new ManifestYamlCFDomainsProvider(getCfTargetCache());
|
||||
@@ -0,0 +1,2 @@
|
||||
languageserver:
|
||||
extension-id: vscode-manifest-yaml
|
||||
@@ -33,6 +33,7 @@ import org.springframework.ide.vscode.commons.cloudfoundry.client.CFServiceInsta
|
||||
import org.springframework.ide.vscode.commons.cloudfoundry.client.CFStack;
|
||||
import org.springframework.ide.vscode.commons.cloudfoundry.client.ClientRequests;
|
||||
import org.springframework.ide.vscode.commons.cloudfoundry.client.cftarget.NoTargetsException;
|
||||
import org.springframework.ide.vscode.commons.languageserver.util.SimpleLanguageServer;
|
||||
import org.springframework.ide.vscode.commons.util.Unicodes;
|
||||
import org.springframework.ide.vscode.commons.util.text.LanguageId;
|
||||
import org.springframework.ide.vscode.languageserver.testharness.CodeAction;
|
||||
@@ -43,12 +44,14 @@ import com.google.common.collect.ImmutableList;
|
||||
|
||||
public class ManifestYamlEditorTest {
|
||||
|
||||
LanguageServerHarness harness;
|
||||
LanguageServerHarness<SimpleLanguageServer> harness;
|
||||
MockCloudfoundry cloudfoundry = new MockCloudfoundry();
|
||||
|
||||
@Before public void setup() throws Exception {
|
||||
harness = new LanguageServerHarness(
|
||||
()-> new ManifestYamlLanguageServer(cloudfoundry.factory, cloudfoundry.defaultParamsProvider),
|
||||
SimpleLanguageServer server = new SimpleLanguageServer("vscode-manifest-yaml");
|
||||
new ManifestYamlLanguageServerInitializer(cloudfoundry.factory, cloudfoundry.defaultParamsProvider).initialize(server);
|
||||
harness = new LanguageServerHarness<>(
|
||||
()-> server,
|
||||
LanguageId.CF_MANIFEST
|
||||
);
|
||||
harness.intialize(null);
|
||||
@@ -67,8 +70,8 @@ public class ManifestYamlEditorTest {
|
||||
}
|
||||
|
||||
@Test public void reconcileRunsOnDocumentOpenAndChange() throws Exception {
|
||||
LanguageServerHarness harness = new LanguageServerHarness(ManifestYamlLanguageServer::new, LanguageId.CF_MANIFEST);
|
||||
harness.intialize(null);
|
||||
// LanguageServerHarness harness = new LanguageServerHarness(ManifestYamlLanguageServerInitializer::new, LanguageId.CF_MANIFEST);
|
||||
// harness.intialize(null);
|
||||
|
||||
Editor editor = harness.newEditor(
|
||||
"somemap: val\n"+
|
||||
|
||||
@@ -29,20 +29,22 @@ import org.eclipse.lsp4j.TextDocumentSyncKind;
|
||||
import org.junit.Test;
|
||||
import org.springframework.ide.vscode.commons.cloudfoundry.client.cftarget.CFClientParams;
|
||||
import org.springframework.ide.vscode.commons.cloudfoundry.client.cftarget.ClientParamsProvider;
|
||||
import org.springframework.ide.vscode.commons.languageserver.util.SimpleLanguageServer;
|
||||
import org.springframework.ide.vscode.commons.languageserver.util.SimpleLanguageServerWrapper;
|
||||
import org.springframework.ide.vscode.commons.util.text.LanguageId;
|
||||
import org.springframework.ide.vscode.languageserver.testharness.LanguageServerHarness;
|
||||
|
||||
import com.google.gson.JsonParser;
|
||||
|
||||
public class ManifestYamlLanguageServerTest {
|
||||
public class ManifestYamlLanguageServerInitializerTest {
|
||||
|
||||
public static File getTestResource(String name) throws URISyntaxException {
|
||||
return Paths.get(ManifestYamlLanguageServerTest.class.getResource(name).toURI()).toFile();
|
||||
return Paths.get(ManifestYamlLanguageServerInitializerTest.class.getResource(name).toURI()).toFile();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createAndInitializeServerWithWorkspace() throws Exception {
|
||||
LanguageServerHarness harness = new LanguageServerHarness(ManifestYamlLanguageServer::new);
|
||||
LanguageServerHarness<SimpleLanguageServer> harness = LanguageServerHarness.create("vscode-manifest-yaml", new ManifestYamlLanguageServerInitializer());
|
||||
File workspaceRoot = getTestResource("/workspace/");
|
||||
assertExpectedInitResult(harness.intialize(workspaceRoot));
|
||||
}
|
||||
@@ -50,7 +52,7 @@ public class ManifestYamlLanguageServerTest {
|
||||
@Test
|
||||
public void createAndInitializeServerWithoutWorkspace() throws Exception {
|
||||
File workspaceRoot = null;
|
||||
LanguageServerHarness harness = new LanguageServerHarness(ManifestYamlLanguageServer::new);
|
||||
LanguageServerHarness<SimpleLanguageServer> harness = LanguageServerHarness.create("vscode-manifest-yaml", new ManifestYamlLanguageServerInitializer());
|
||||
assertExpectedInitResult(harness.intialize(workspaceRoot));
|
||||
}
|
||||
|
||||
@@ -93,17 +95,19 @@ public class ManifestYamlLanguageServerTest {
|
||||
|
||||
@Test public void changeCfClientParams() throws Exception {
|
||||
MockCloudfoundry cloudfoundry = new MockCloudfoundry();
|
||||
ManifestYamlLanguageServer manifestYamlLanguageServer = new ManifestYamlLanguageServer(cloudfoundry.factory, cloudfoundry.defaultParamsProvider);
|
||||
ManifestYamlLanguageServerInitializer serverInitializer = new ManifestYamlLanguageServerInitializer(cloudfoundry.factory, cloudfoundry.defaultParamsProvider);
|
||||
SimpleLanguageServer server = new SimpleLanguageServer("vscode-manifest-yaml");
|
||||
serverInitializer.initialize(server);
|
||||
|
||||
LanguageServerHarness harness = new LanguageServerHarness(
|
||||
() -> manifestYamlLanguageServer,
|
||||
LanguageServerHarness<SimpleLanguageServer> harness = new LanguageServerHarness<>(
|
||||
() -> server,
|
||||
LanguageId.CF_MANIFEST
|
||||
);
|
||||
harness.intialize(null);
|
||||
|
||||
// This is an initial target, for example from cf CLI
|
||||
assertEquals(1, getAllParams(manifestYamlLanguageServer.getParamsProvider()).size());
|
||||
assertEquals(Arrays.asList("test.io"), manifestYamlLanguageServer.getCfTargets());
|
||||
assertEquals(1, getAllParams(serverInitializer.getParamsProvider()).size());
|
||||
assertEquals(Arrays.asList("test.io"), serverInitializer.getCfTargets());
|
||||
|
||||
// This tests a change in workspace (e.g. boot dash) that results in two more targets created.
|
||||
DidChangeConfigurationParams params = new DidChangeConfigurationParams();
|
||||
@@ -111,11 +115,11 @@ public class ManifestYamlLanguageServerTest {
|
||||
JsonParser parser = new JsonParser();
|
||||
params.setSettings(parser.parse(new InputStreamReader(getClass().getResourceAsStream("/cf-targets1.json"))));
|
||||
|
||||
manifestYamlLanguageServer.getWorkspaceService().didChangeConfiguration(params);
|
||||
assertEquals(3, getAllParams(manifestYamlLanguageServer.getParamsProvider()).size());
|
||||
server.getWorkspaceService().didChangeConfiguration(params);
|
||||
assertEquals(3, getAllParams(serverInitializer.getParamsProvider()).size());
|
||||
|
||||
// End result should have the initial target as well as the two additional targets obtained on workspace change
|
||||
assertEquals(Arrays.asList("test.io", "api.system.demo-gcp.springapps.io", "api.run.pivotal.io"), manifestYamlLanguageServer.getCfTargets());
|
||||
assertEquals(Arrays.asList("test.io", "api.system.demo-gcp.springapps.io", "api.run.pivotal.io"), serverInitializer.getCfTargets());
|
||||
}
|
||||
|
||||
private List<CFClientParams> getAllParams(List<ClientParamsProvider> providers) throws Exception {
|
||||
@@ -0,0 +1,15 @@
|
||||
<configuration>
|
||||
|
||||
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<!-- encoders are assigned the type
|
||||
ch.qos.logback.classic.encoder.PatternLayoutEncoder by default -->
|
||||
<target>System.err</target>
|
||||
<encoder>
|
||||
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<root level="info">
|
||||
<appender-ref ref="STDOUT" />
|
||||
</root>
|
||||
</configuration>
|
||||
Reference in New Issue
Block a user