diff --git a/eclipse-distribution/org.springframework.boot.ide.branding.feature/build.properties b/eclipse-distribution/org.springframework.boot.ide.branding.feature/build.properties
index 3c54be93f..0658d02e0 100644
--- a/eclipse-distribution/org.springframework.boot.ide.branding.feature/build.properties
+++ b/eclipse-distribution/org.springframework.boot.ide.branding.feature/build.properties
@@ -1,2 +1,2 @@
-bin.includes = feature.xml,\
- p2.inf
+bin.includes = feature.xml
+includeLaunchers=false
\ No newline at end of file
diff --git a/eclipse-distribution/org.springframework.boot.ide.branding.feature/p2.inf b/eclipse-distribution/org.springframework.boot.ide.branding.feature/p2.inf
deleted file mode 100644
index db72e641d..000000000
--- a/eclipse-distribution/org.springframework.boot.ide.branding.feature/p2.inf
+++ /dev/null
@@ -1,7 +0,0 @@
-# tell pde.build not to generate start levels
-org.eclipse.pde.build.append.startlevels=false
-
-# add requirement on org.eclipse.platform.ide
-requires.1.namespace=org.eclipse.equinox.p2.iu
-requires.1.name=org.eclipse.platform.ide
-requires.1.greedy=true
diff --git a/eclipse-distribution/org.springframework.boot.ide.product.e410/org.springframework.boot.ide.product b/eclipse-distribution/org.springframework.boot.ide.product.e410/org.springframework.boot.ide.product
index 67ceefda0..a73b4bd1c 100644
--- a/eclipse-distribution/org.springframework.boot.ide.product.e410/org.springframework.boot.ide.product
+++ b/eclipse-distribution/org.springframework.boot.ide.product.e410/org.springframework.boot.ide.product
@@ -47,7 +47,7 @@
-
+
@@ -88,7 +88,7 @@
-
+
@@ -100,11 +100,17 @@
-
+
+
+
+
+
+
+
+
-
diff --git a/eclipse-distribution/pom.xml b/eclipse-distribution/pom.xml
index d212e5864..c4e20849a 100644
--- a/eclipse-distribution/pom.xml
+++ b/eclipse-distribution/pom.xml
@@ -61,7 +61,7 @@
http://dist.springframework.org/release/IDE/3.9.6.RELEASE -->
http://dist.springsource.com/${dist.type}/TOOLS/sts4-language-server-integrations/${sts4-language-servers-version}
- 1.1.0
+ 1.2.0
UTF-8
diff --git a/eclipse-language-servers/org.springframework.tooling.boot.ls/plugin.xml b/eclipse-language-servers/org.springframework.tooling.boot.ls/plugin.xml
index 94dd8ce06..6e01405b7 100644
--- a/eclipse-language-servers/org.springframework.tooling.boot.ls/plugin.xml
+++ b/eclipse-language-servers/org.springframework.tooling.boot.ls/plugin.xml
@@ -36,7 +36,8 @@
+ file-names="application.properties,application-dev.properties"
+ file-patterns="application-*.properties">
@@ -50,7 +51,8 @@
+ file-names="application.yml,bootstrap.yml,application-dev.yml"
+ file-patterns="application-*.yml">
diff --git a/headless-services/commons/commons-boot-app-cli/src/main/java/org/springframework/ide/vscode/commons/boot/app/cli/ContextPath.java b/headless-services/commons/commons-boot-app-cli/src/main/java/org/springframework/ide/vscode/commons/boot/app/cli/ContextPath.java
index 712b43057..aac68abe9 100644
--- a/headless-services/commons/commons-boot-app-cli/src/main/java/org/springframework/ide/vscode/commons/boot/app/cli/ContextPath.java
+++ b/headless-services/commons/commons-boot-app-cli/src/main/java/org/springframework/ide/vscode/commons/boot/app/cli/ContextPath.java
@@ -34,7 +34,18 @@ public class ContextPath {
String contextPath = null;
if (environment != null) {
JSONObject env = new JSONObject(environment);
-
+ // IMPORTANT: We want to check property sources (e.g. command line args, config
+ // files, env vars, etc..)
+ // for properties IN THE ORDER that they appear in the raw JSON, as the
+ // assumption is that order is the correct
+ // priority order of these property sources. We want to return the property from
+ // the highest priority source.
+ //
+ // In boot 2.x, the property sources appear in order in an ORDERED JSONArray
+ // "propertySource" under the top-level JSONObject for the environment
+ // but for boot 1.x, the property sources are all top level key/values in an
+ // UNORDERED JSONObject. Therefore for now we only support searching in "priority order"
+ // for Boot 2.x
if ("1.x".equals(bootVersion)) {
contextPath = findContextPathInBoot1x(env);
} else if ("2.x".equals(bootVersion)) {
@@ -46,11 +57,10 @@ public class ContextPath {
}
private static String findContextPathInBoot1x(JSONObject env) {
- // IMPORTANT: The order in which the env objects appear are assumed to be the
- // priority order defined
- // by boot rules in terms of which property source has higher precedence. Iterate
- // through ALL
- // sources in the order obtained from the env JSON
+ // LIMITATION: In Boot 1.x, property sources appear top level in an UNORDERED
+ // JSONObject (the key set obtained from the JSON Object may not match the order of properties as they appear in the raw JSON.
+ // Therefore for Boot 1.x we don't currently support "ordering" of property sources
+ // We don't know which one is the highest priority, so we just return the first encountered property
for (String key : env.keySet()) {
JSONObject jsonObj = env.optJSONObject(key);
if (jsonObj != null) {
diff --git a/headless-services/commons/commons-java/src/main/java/org/springframework/ide/vscode/commons/languageserver/java/JavaProjectFinder.java b/headless-services/commons/commons-java/src/main/java/org/springframework/ide/vscode/commons/languageserver/java/JavaProjectFinder.java
index 9f84a9463..095302477 100644
--- a/headless-services/commons/commons-java/src/main/java/org/springframework/ide/vscode/commons/languageserver/java/JavaProjectFinder.java
+++ b/headless-services/commons/commons-java/src/main/java/org/springframework/ide/vscode/commons/languageserver/java/JavaProjectFinder.java
@@ -25,9 +25,9 @@ import org.springframework.ide.vscode.commons.java.IJavaProject;
* @author Kris De Volder
*/
public interface JavaProjectFinder {
-
+
Optional find(TextDocumentIdentifier doc);
-
+
default JavaProjectFinder filter(Predicate acceptWhen) {
return doc -> this.find(doc).flatMap(jp -> {
if (acceptWhen.test(jp)) {
diff --git a/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/util/DocumentEventListenerManager.java b/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/util/DocumentEventListenerManager.java
new file mode 100644
index 000000000..c79cb6912
--- /dev/null
+++ b/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/util/DocumentEventListenerManager.java
@@ -0,0 +1,18 @@
+/*******************************************************************************
+ * 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.util;
+
+import java.util.function.Consumer;
+
+public interface DocumentEventListenerManager {
+ void onDidSave(Consumer l);
+ // add more 'onDidXXX' if needed/useful.
+}
diff --git a/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/util/SimpleServerFileObserver.java b/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/util/SimpleServerFileObserver.java
index ca87b358b..51fe37567 100644
--- a/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/util/SimpleServerFileObserver.java
+++ b/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/util/SimpleServerFileObserver.java
@@ -22,7 +22,6 @@ import org.eclipse.lsp4j.Unregistration;
import org.eclipse.lsp4j.UnregistrationParams;
import org.springframework.ide.vscode.commons.languageserver.json.DidChangeWatchedFilesRegistrationOptions;
import org.springframework.ide.vscode.commons.languageserver.json.FileSystemWatcher;
-import org.springframework.ide.vscode.commons.util.Assert;
import org.springframework.ide.vscode.commons.util.BasicFileObserver;
/**
diff --git a/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/util/SimpleTextDocumentService.java b/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/util/SimpleTextDocumentService.java
index 8f38442d6..c81d1274e 100644
--- a/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/util/SimpleTextDocumentService.java
+++ b/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/util/SimpleTextDocumentService.java
@@ -10,6 +10,7 @@
*******************************************************************************/
package org.springframework.ide.vscode.commons.languageserver.util;
+import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
@@ -66,7 +67,7 @@ import org.springframework.ide.vscode.commons.util.text.TextDocument;
import com.google.common.collect.ImmutableList;
-public class SimpleTextDocumentService implements TextDocumentService {
+public class SimpleTextDocumentService implements TextDocumentService, DocumentEventListenerManager {
final private SimpleLanguageServer server;
private Map documents = new HashMap<>();
@@ -85,7 +86,7 @@ public class SimpleTextDocumentService implements TextDocumentService {
private CodeLensHandler codeLensHandler;
private CodeLensResolveHandler codeLensResolveHandler;
- private Consumer documentSaveListener;
+ private List> documentSaveListeners = ImmutableList.of();
private AsyncRunner async;
public SimpleTextDocumentService(SimpleLanguageServer server) {
@@ -240,8 +241,12 @@ public class SimpleTextDocumentService implements TextDocumentService {
documentCloseListeners.add(l);
}
+ @Override
public void onDidSave(Consumer l) {
- documentSaveListener=l;
+ ImmutableList.Builder> builder = ImmutableList.builder();
+ builder.addAll(documentSaveListeners);
+ builder.add(l);
+ documentSaveListeners = builder.build();
}
public synchronized TextDocument getDocument(String url) {
@@ -407,13 +412,15 @@ public class SimpleTextDocumentService implements TextDocumentService {
// When STS uses the LSP4E editor and no longer needs its own YEdit-based editor, the issue with error markers disappearing
// on save should not be a problem anymore, and the workaround below will no longer be needed.
async.execute(() -> {
- if (documentSaveListener != null) {
+ if (documentSaveListeners != null) {
TextDocumentIdentifier docId = params.getTextDocument();
String url = docId.getUri();
Log.debug("didSave: "+url);
if (url!=null) {
TextDocument doc = getDocument(url);
- documentSaveListener.accept(new TextDocumentSaveChange(doc));
+ for (Consumer l : documentSaveListeners) {
+ l.accept(new TextDocumentSaveChange(doc));
+ }
}
}
});
diff --git a/headless-services/commons/commons-util/src/main/java/org/springframework/ide/vscode/commons/util/FuzzyMap.java b/headless-services/commons/commons-util/src/main/java/org/springframework/ide/vscode/commons/util/FuzzyMap.java
index 4df5f91a9..7428a9927 100644
--- a/headless-services/commons/commons-util/src/main/java/org/springframework/ide/vscode/commons/util/FuzzyMap.java
+++ b/headless-services/commons/commons-util/src/main/java/org/springframework/ide/vscode/commons/util/FuzzyMap.java
@@ -18,9 +18,6 @@ import java.util.Map.Entry;
import java.util.TreeMap;
import java.util.logging.Logger;
-import org.springframework.ide.vscode.commons.util.FuzzyMatcher;
-import org.springframework.ide.vscode.commons.util.StringUtil;
-
/**
* A collection of data that can be searched with a simple 'fuzzy' string
* matching algorithm. Clients must override 'getKey' method to define how
@@ -167,4 +164,8 @@ public abstract class FuzzyMap implements Iterable {
return entries.size();
}
+ public TreeMap getTreeMap() {
+ return entries;
+ }
+
}
diff --git a/headless-services/commons/commons-yaml/src/main/java/org/springframework/ide/vscode/commons/yaml/completion/AbstractYamlAssistContext.java b/headless-services/commons/commons-yaml/src/main/java/org/springframework/ide/vscode/commons/yaml/completion/AbstractYamlAssistContext.java
index 3e775681e..bb3bef27a 100644
--- a/headless-services/commons/commons-yaml/src/main/java/org/springframework/ide/vscode/commons/yaml/completion/AbstractYamlAssistContext.java
+++ b/headless-services/commons/commons-yaml/src/main/java/org/springframework/ide/vscode/commons/yaml/completion/AbstractYamlAssistContext.java
@@ -70,7 +70,7 @@ public abstract class AbstractYamlAssistContext implements YamlAssistContext {
private static PrefixFinder prefixfinder = new PrefixFinder() {
@Override
protected boolean isPrefixChar(char c) {
- return !Character.isWhitespace(c);
+ return !(Character.isWhitespace(c) || c==',');
}
};
@@ -87,7 +87,7 @@ public abstract class AbstractYamlAssistContext implements YamlAssistContext {
valueStart++;
}
if (offset>=valueStart) {
- return doc.textBetween(valueStart, offset);
+ return prefixfinder.getPrefix(doc.getDocument(), offset, valueStart);
} else {
//only whitespace, or nothing found upto the cursor
return "";
diff --git a/headless-services/spring-boot-language-server/.factorypath b/headless-services/spring-boot-language-server/.factorypath
index e9f5f4cce..44efa123e 100644
--- a/headless-services/spring-boot-language-server/.factorypath
+++ b/headless-services/spring-boot-language-server/.factorypath
@@ -1,5 +1,4 @@
-
@@ -10,8 +9,6 @@
-
-
@@ -20,7 +17,6 @@
-
@@ -61,11 +57,8 @@
-
-
-
@@ -73,10 +66,8 @@
-
-
diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/app/BootLanguagServerBootApp.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/app/BootLanguagServerBootApp.java
index 5e30a7b38..ff163c725 100644
--- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/app/BootLanguagServerBootApp.java
+++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/app/BootLanguagServerBootApp.java
@@ -10,6 +10,8 @@
*******************************************************************************/
package org.springframework.ide.vscode.boot.app;
+import org.springframework.beans.factory.InitializingBean;
+import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass;
@@ -25,11 +27,19 @@ import org.springframework.ide.vscode.boot.java.links.JdtJavaDocumentUriProvider
import org.springframework.ide.vscode.boot.java.links.SourceLinkFactory;
import org.springframework.ide.vscode.boot.java.links.SourceLinks;
import org.springframework.ide.vscode.boot.java.utils.CompilationUnitCache;
+import org.springframework.ide.vscode.boot.metadata.AdHocSpringPropertyIndexProvider;
+import org.springframework.ide.vscode.boot.metadata.ClassReferenceProvider;
+import org.springframework.ide.vscode.boot.metadata.LoggerNameProvider;
+import org.springframework.ide.vscode.boot.metadata.ProjectBasedPropertyIndexProvider;
import org.springframework.ide.vscode.boot.metadata.PropertyInfo;
+import org.springframework.ide.vscode.boot.metadata.SpringPropertyIndexProvider;
+import org.springframework.ide.vscode.boot.metadata.ValueProviderRegistry;
import org.springframework.ide.vscode.boot.yaml.completions.ApplicationYamlAssistContext;
+import org.springframework.ide.vscode.commons.languageserver.util.DocumentEventListenerManager;
import org.springframework.ide.vscode.commons.languageserver.util.LspClient;
import org.springframework.ide.vscode.commons.languageserver.util.SimpleLanguageServer;
import org.springframework.ide.vscode.commons.languageserver.util.SimpleTextDocumentService;
+import org.springframework.ide.vscode.commons.util.FileObserver;
import org.springframework.ide.vscode.commons.util.FuzzyMap;
import org.springframework.ide.vscode.commons.util.LogRedirect;
import org.springframework.ide.vscode.commons.util.text.IDocument;
@@ -55,8 +65,32 @@ public class BootLanguagServerBootApp {
}
@ConditionalOnMissingClass("org.springframework.ide.vscode.languageserver.testharness.LanguageServerHarness")
- @Bean BootLanguageServerParams serverParams(SimpleLanguageServer server) {
- return BootLanguageServerParams.createDefault(server);
+ @Bean AdHocSpringPropertyIndexProvider adHocProperties(BootLanguageServerParams params, FileObserver fileObserver, DocumentEventListenerManager documentEvents) {
+ return new AdHocSpringPropertyIndexProvider(params.projectFinder, params.projectObserver, fileObserver, documentEvents);
+ }
+
+ @Bean SimpleTextDocumentService documentEvents(SimpleLanguageServer server) {
+ return server.getTextDocumentService();
+ }
+
+ @Bean FileObserver fileObserver(SimpleLanguageServer server) {
+ return server.getWorkspaceService().getFileObserver();
+ }
+
+ @Bean ValueProviderRegistry valueProviders() {
+ return new ValueProviderRegistry();
+ }
+
+ @Bean InitializingBean initializeValueProviders(ValueProviderRegistry r, @Qualifier("adHocProperties") ProjectBasedPropertyIndexProvider adHocProperties) {
+ return () -> {
+ r.def("logger-name", new LoggerNameProvider(adHocProperties).FACTORY);
+ r.def("class-reference", ClassReferenceProvider.FACTORY);
+ };
+ }
+
+ @ConditionalOnMissingClass("org.springframework.ide.vscode.languageserver.testharness.LanguageServerHarness")
+ @Bean BootLanguageServerParams serverParams(SimpleLanguageServer server, ValueProviderRegistry valueProviders) {
+ return BootLanguageServerParams.createDefault(server, valueProviders);
}
@ConditionalOnMissingClass("org.springframework.ide.vscode.languageserver.testharness.LanguageServerHarness")
diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/app/BootLanguageServerInitializer.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/app/BootLanguageServerInitializer.java
index cefb3fa90..074246817 100644
--- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/app/BootLanguageServerInitializer.java
+++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/app/BootLanguageServerInitializer.java
@@ -14,10 +14,14 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.ide.vscode.boot.java.BootJavaLanguageServerComponents;
import org.springframework.ide.vscode.boot.java.links.JavaElementLocationProvider;
import org.springframework.ide.vscode.boot.java.links.SourceLinks;
import org.springframework.ide.vscode.boot.java.utils.CompilationUnitCache;
+import org.springframework.ide.vscode.boot.metadata.AdHocSpringPropertyIndexProvider;
+import org.springframework.ide.vscode.boot.metadata.ProjectBasedPropertyIndexProvider;
+import org.springframework.ide.vscode.boot.metadata.SpringPropertyIndexProvider;
import org.springframework.ide.vscode.boot.properties.BootPropertiesLanguageServerComponents;
import org.springframework.ide.vscode.commons.languageserver.completion.ICompletionEngine;
import org.springframework.ide.vscode.commons.languageserver.completion.VscodeCompletionEngineAdapter;
@@ -44,6 +48,7 @@ public class BootLanguageServerInitializer implements InitializingBean {
@Autowired YamlASTProvider parser;
@Autowired YamlStructureProvider yamlStructureProvider;
@Autowired YamlAssistContextProvider yamlAssistContextProvider;
+ @Qualifier("adHocProperties") @Autowired ProjectBasedPropertyIndexProvider adHocProperties;
private CompositeLanguageServerComponents components;
private VscodeCompletionEngineAdapter completionEngineAdapter;
@@ -67,7 +72,7 @@ public class BootLanguageServerInitializer implements InitializingBean {
// some server intialization code. Migrate that code and get rid of the ComposableLanguageServer class
CompositeLanguageServerComponents.Builder builder = new CompositeLanguageServerComponents.Builder();
builder.add(new BootPropertiesLanguageServerComponents(server, params, javaElementLocationProvider, parser, yamlStructureProvider, yamlAssistContextProvider));
- builder.add(new BootJavaLanguageServerComponents(server, params, sourceLinks, cuCache));
+ builder.add(new BootJavaLanguageServerComponents(server, params, sourceLinks, cuCache, adHocProperties));
components = builder.build(server);
params.projectObserver.addListener(reconcileOpenDocuments(server, components));
diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/app/BootLanguageServerParams.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/app/BootLanguageServerParams.java
index 3eaf4454c..da07a2063 100644
--- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/app/BootLanguageServerParams.java
+++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/app/BootLanguageServerParams.java
@@ -21,10 +21,9 @@ import org.springframework.ide.vscode.boot.java.utils.SpringLiveHoverWatchdog;
import org.springframework.ide.vscode.boot.jdt.ls.JavaProjectsService;
import org.springframework.ide.vscode.boot.jdt.ls.JavaProjectsServiceWithFallback;
import org.springframework.ide.vscode.boot.jdt.ls.JdtLsProjectCache;
-import org.springframework.ide.vscode.boot.metadata.AdHocSpringPropertyIndexProvider;
import org.springframework.ide.vscode.boot.metadata.DefaultSpringPropertyIndexProvider;
-import org.springframework.ide.vscode.boot.metadata.SpringPropertyIndex;
import org.springframework.ide.vscode.boot.metadata.SpringPropertyIndexProvider;
+import org.springframework.ide.vscode.boot.metadata.ValueProviderRegistry;
import org.springframework.ide.vscode.boot.metadata.types.TypeUtil;
import org.springframework.ide.vscode.boot.metadata.types.TypeUtilProvider;
import org.springframework.ide.vscode.commons.gradle.GradleCore;
@@ -59,7 +58,6 @@ public class BootLanguageServerParams {
public final JavaProjectFinder projectFinder;
public final ProjectObserver projectObserver;
public final SpringPropertyIndexProvider indexProvider;
- public final SpringPropertyIndexProvider adHocIndexProvider;
//Boot Properies
public final TypeUtilProvider typeUtilProvider;
@@ -72,7 +70,6 @@ public class BootLanguageServerParams {
JavaProjectFinder projectFinder,
ProjectObserver projectObserver,
SpringPropertyIndexProvider indexProvider,
- SpringPropertyIndexProvider adHocIndexProvider,
TypeUtilProvider typeUtilProvider,
RunningAppProvider runningAppProvider,
Duration watchDogInterval
@@ -82,28 +79,25 @@ public class BootLanguageServerParams {
this.projectFinder = projectFinder;
this.projectObserver = projectObserver;
this.indexProvider = indexProvider;
- this.adHocIndexProvider = adHocIndexProvider;
this.typeUtilProvider = typeUtilProvider;
this.runningAppProvider = runningAppProvider;
this.watchDogInterval = watchDogInterval;
}
- public static BootLanguageServerParams createDefault(SimpleLanguageServer server) {
+ public static BootLanguageServerParams createDefault(SimpleLanguageServer server, ValueProviderRegistry valueProviders) {
// Initialize project finders, project caches and project observers
JavaProjectsService jdtProjectCache = new JavaProjectsServiceWithFallback(
server,
new JdtLsProjectCache(server),
() -> createFallbackProjectCache(server)
);
- DefaultSpringPropertyIndexProvider indexProvider = new DefaultSpringPropertyIndexProvider(jdtProjectCache, jdtProjectCache);
- SpringPropertyIndexProvider adHocProvider = new AdHocSpringPropertyIndexProvider(jdtProjectCache, jdtProjectCache, server.getWorkspaceService().getFileObserver());
+ DefaultSpringPropertyIndexProvider indexProvider = new DefaultSpringPropertyIndexProvider(jdtProjectCache, jdtProjectCache, valueProviders);
indexProvider.setProgressService(server.getProgressService());
return new BootLanguageServerParams(
jdtProjectCache.filter(BootProjectUtil::isBootProject),
jdtProjectCache,
indexProvider,
- adHocProvider,
(IDocument doc) -> new TypeUtil(jdtProjectCache.find(new TextDocumentIdentifier(doc.getUri()))),
RunningAppProvider.createDefault(server),
SpringLiveHoverWatchdog.DEFAULT_INTERVAL
@@ -147,7 +141,7 @@ public class BootLanguageServerParams {
};
}
- public static BootLanguageServerParams createTestDefault(SimpleLanguageServer server) {
+ public static BootLanguageServerParams createTestDefault(SimpleLanguageServer server, ValueProviderRegistry valueProviders) {
// Initialize project finders, project caches and project observers
CompositeJavaProjectFinder javaProjectFinder = new CompositeJavaProjectFinder();
MavenProjectCache mavenProjectCache = new MavenProjectCache(server, MavenCore.getDefault(), false, null, (uri, cpe) -> JavaDocProviders.createFor(cpe));
@@ -160,14 +154,13 @@ public class BootLanguageServerParams {
CompositeProjectOvserver projectObserver = new CompositeProjectOvserver(Arrays.asList(mavenProjectCache, gradleProjectCache));
- DefaultSpringPropertyIndexProvider indexProvider = new DefaultSpringPropertyIndexProvider(javaProjectFinder, projectObserver);
+ DefaultSpringPropertyIndexProvider indexProvider = new DefaultSpringPropertyIndexProvider(javaProjectFinder, projectObserver, valueProviders);
indexProvider.setProgressService(server.getProgressService());
return new BootLanguageServerParams(
javaProjectFinder.filter(BootProjectUtil::isBootProject),
projectObserver,
indexProvider,
- (doc) -> SpringPropertyIndex.EMPTY_INDEX,
(IDocument doc) -> new TypeUtil(javaProjectFinder.find(new TextDocumentIdentifier(doc.getUri()))),
RunningAppProvider.NULL,
SpringLiveHoverWatchdog.DEFAULT_INTERVAL
diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/common/CommonLanguageTools.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/common/CommonLanguageTools.java
index fb37add51..1330c8db8 100644
--- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/common/CommonLanguageTools.java
+++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/common/CommonLanguageTools.java
@@ -33,6 +33,7 @@ import org.springframework.ide.vscode.commons.util.Log;
import org.springframework.ide.vscode.commons.util.text.DocumentRegion;
import org.springframework.ide.vscode.commons.util.text.LanguageId;
import org.springframework.ide.vscode.commons.util.text.TextDocument;
+import org.springframework.ide.vscode.commons.yaml.path.YamlPathSegment;
public class CommonLanguageTools {
@@ -83,7 +84,16 @@ public class CommonLanguageTools {
{
PropertyInfo prop = index.findLongestCommonPrefixEntry(propertyName);
if (prop!=null) {
- HintProvider hintProvider = prop.getHints(typeUtil, false);
+ HintProvider hintProvider = prop.getHints(typeUtil);
+ if (prop.getId().length() providers = new HashMap<>();
- providers.put(org.springframework.ide.vscode.boot.java.scope.Constants.SPRING_SCOPE, new ScopeCompletionProcessor());
- providers.put(org.springframework.ide.vscode.boot.java.value.Constants.SPRING_VALUE, new ValueCompletionProcessor(indexProvider, adHocIndexProvider));
+ providers.put(org.springframework.ide.vscode.boot.java.scope.Constants.SPRING_SCOPE,
+ new ScopeCompletionProcessor());
+ providers.put(org.springframework.ide.vscode.boot.java.value.Constants.SPRING_VALUE,
+ new ValueCompletionProcessor(javaProjectFinder, indexProvider, adHocIndexProvider));
providers.put(Annotations.REPOSITORY, new DataRepositoryCompletionProcessor());
JavaSnippetManager snippetManager = new JavaSnippetManager(server::createSnippetBuilder);
diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/value/ValueCompletionProcessor.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/value/ValueCompletionProcessor.java
index a9b0d522d..3b93cadb8 100644
--- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/value/ValueCompletionProcessor.java
+++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/value/ValueCompletionProcessor.java
@@ -15,6 +15,7 @@ import static org.springframework.ide.vscode.commons.util.StringUtil.camelCaseTo
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
+import java.util.Optional;
import java.util.Set;
import org.eclipse.jdt.core.dom.ASTNode;
@@ -24,11 +25,15 @@ import org.eclipse.jdt.core.dom.MemberValuePair;
import org.eclipse.jdt.core.dom.SimpleName;
import org.eclipse.jdt.core.dom.StringLiteral;
import org.eclipse.lsp4j.InsertTextFormat;
+import org.eclipse.lsp4j.TextDocumentIdentifier;
import org.springframework.ide.vscode.boot.java.handlers.CompletionProvider;
+import org.springframework.ide.vscode.boot.metadata.ProjectBasedPropertyIndexProvider;
import org.springframework.ide.vscode.boot.metadata.PropertyInfo;
import org.springframework.ide.vscode.boot.metadata.SpringPropertyIndexProvider;
+import org.springframework.ide.vscode.commons.java.IJavaProject;
import org.springframework.ide.vscode.commons.languageserver.completion.DocumentEdits;
import org.springframework.ide.vscode.commons.languageserver.completion.ICompletionProposal;
+import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder;
import org.springframework.ide.vscode.commons.util.BadLocationException;
import org.springframework.ide.vscode.commons.util.FuzzyMap;
import org.springframework.ide.vscode.commons.util.FuzzyMap.Match;
@@ -40,9 +45,11 @@ import org.springframework.ide.vscode.commons.util.text.IDocument;
public class ValueCompletionProcessor implements CompletionProvider {
private final SpringPropertyIndexProvider indexProvider;
- private SpringPropertyIndexProvider adHocIndexProvider;
+ private final ProjectBasedPropertyIndexProvider adHocIndexProvider;
+ private final JavaProjectFinder projectFinder;
- public ValueCompletionProcessor(SpringPropertyIndexProvider indexProvider, SpringPropertyIndexProvider adHocIndexProvider) {
+ public ValueCompletionProcessor(JavaProjectFinder projectFinder, SpringPropertyIndexProvider indexProvider, ProjectBasedPropertyIndexProvider adHocIndexProvider) {
+ this.projectFinder = projectFinder;
this.indexProvider = indexProvider;
this.adHocIndexProvider = adHocIndexProvider;
}
@@ -205,10 +212,13 @@ public class ValueCompletionProcessor implements CompletionProvider {
}
//Then also add 'ad-hoc' properties (see https://www.pivotaltracker.com/story/show/153107266).
- index = adHocIndexProvider.getIndex(doc);
- for (Match m : index.find(prefix)) {
- if (suggestedKeys.add(m.data.getId())) {
- matches.add(m);
+ Optional p = projectFinder.find(new TextDocumentIdentifier(doc.getUri()));
+ if (p.isPresent()) {
+ index = adHocIndexProvider.getIndex(p.get());
+ for (Match m : index.find(prefix)) {
+ if (suggestedKeys.add(m.data.getId())) {
+ matches.add(m);
+ }
}
}
return matches;
diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/metadata/AdHocSpringPropertyIndexProvider.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/metadata/AdHocSpringPropertyIndexProvider.java
index cc719a092..611e7a9ac 100644
--- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/metadata/AdHocSpringPropertyIndexProvider.java
+++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/metadata/AdHocSpringPropertyIndexProvider.java
@@ -12,12 +12,9 @@ package org.springframework.ide.vscode.boot.metadata;
import java.io.File;
import java.io.FileInputStream;
-import java.io.FileReader;
-import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
-import java.util.Optional;
import java.util.Properties;
import java.util.concurrent.ExecutionException;
@@ -28,9 +25,10 @@ import org.springframework.ide.vscode.commons.java.IClasspathUtil;
import org.springframework.ide.vscode.commons.java.IJavaProject;
import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder;
import org.springframework.ide.vscode.commons.languageserver.java.ProjectObserver;
+import org.springframework.ide.vscode.commons.languageserver.util.DocumentEventListenerManager;
import org.springframework.ide.vscode.commons.util.FileObserver;
import org.springframework.ide.vscode.commons.util.FuzzyMap;
-import org.springframework.ide.vscode.commons.util.text.IDocument;
+import org.springframework.ide.vscode.commons.util.text.LanguageId;
import org.springframework.ide.vscode.commons.yaml.ast.NodeUtil;
import org.yaml.snakeyaml.Yaml;
import org.yaml.snakeyaml.nodes.MappingNode;
@@ -42,7 +40,7 @@ import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.google.common.collect.ImmutableList;
-public class AdHocSpringPropertyIndexProvider implements SpringPropertyIndexProvider {
+public class AdHocSpringPropertyIndexProvider implements ProjectBasedPropertyIndexProvider {
private static final Logger log = LoggerFactory.getLogger(AdHocSpringPropertyIndexProvider.class);
@@ -54,10 +52,8 @@ public class AdHocSpringPropertyIndexProvider implements SpringPropertyIndexProv
}
private Cache indexes;
- final private JavaProjectFinder projectFinder;
- public AdHocSpringPropertyIndexProvider(JavaProjectFinder projectFinder, ProjectObserver projectObserver, FileObserver fileObserver) {
- this.projectFinder = projectFinder;
+ public AdHocSpringPropertyIndexProvider(JavaProjectFinder projectFinder, ProjectObserver projectObserver, FileObserver fileObserver, DocumentEventListenerManager documents) {
this.indexes = CacheBuilder.newBuilder().build();
if (projectObserver != null) {
projectObserver.addListener(ProjectObserver.onAny(project -> indexes.invalidate(project)));
@@ -74,35 +70,35 @@ public class AdHocSpringPropertyIndexProvider implements SpringPropertyIndexProv
});
});
}
+ if (documents!=null) {
+ documents.onDidSave(saveEvent -> {
+ LanguageId language = saveEvent.getDocument().getLanguageId();
+ if (language.equals(LanguageId.BOOT_PROPERTIES) || language.equals(LanguageId.BOOT_PROPERTIES_YAML)) {
+ indexes.invalidateAll();
+ }
+ });
+ }
}
-
@Override
- public FuzzyMap getIndex(IDocument doc) {
- Optional jp = projectFinder.find(new TextDocumentIdentifier(doc.getUri()));
- if (jp.isPresent()) {
- return getIndex(jp.get());
+ public FuzzyMap getIndex(IJavaProject jp) {
+ if (jp!=null) {
+ try {
+ return indexes.get(jp, () -> {
+ SimplePropertyIndex index = new SimplePropertyIndex();
+ IClasspathUtil.getSourceFolders(jp.getClasspath()).forEach(sourceFolder -> {
+ processFile(this::parseProperties, new File(sourceFolder, "application.properties"), index);
+ processFile(this::parseYaml, new File(sourceFolder, "application.yml"), index);
+ });
+ return index;
+ });
+ } catch (ExecutionException e) {
+ log.error("", e);
+ }
}
return SpringPropertyIndex.EMPTY_INDEX;
}
-
- private FuzzyMap getIndex(IJavaProject jp) {
- try {
- return indexes.get(jp, () -> {
- SimplePropertyIndex index = new SimplePropertyIndex();
- IClasspathUtil.getSourceFolders(jp.getClasspath()).forEach(sourceFolder -> {
- processFile(this::parseProperties, new File(sourceFolder, "application.properties"), index);
- processFile(this::parseYaml, new File(sourceFolder, "application.yml"), index);
- });
- return index;
- });
- } catch (ExecutionException e) {
- log.error("", e);
- }
- return null;
- }
-
private void processFile(Function parserFunction, File file, SimplePropertyIndex index) {
Properties props = parserFunction.apply(file);
if (props!=null) {
@@ -146,7 +142,6 @@ public class AdHocSpringPropertyIndexProvider implements SpringPropertyIndexProv
return null;
}
-
private void flattenProperties(String prefix, Node node, Properties props) {
switch (node.getNodeId()) {
case mapping:
@@ -166,6 +161,9 @@ public class AdHocSpringPropertyIndexProvider implements SpringPropertyIndexProv
props.put(prefix, NodeUtil.asScalar(node));
break;
default:
+ if (!prefix.isEmpty()) {
+ props.put(prefix, "