Merge branch 'master' into spring-data-content-assist

This commit is contained in:
Martin Lippert
2018-11-16 12:30:45 +01:00
49 changed files with 1101 additions and 305 deletions

View File

@@ -1,2 +1,2 @@
bin.includes = feature.xml,\
p2.inf
bin.includes = feature.xml
includeLaunchers=false

View File

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

View File

@@ -47,7 +47,7 @@
</plugins>
<features>
<feature id="org.eclipse.platform" installMode="root"/>
<feature id="org.eclipse.platform"/>
<feature id="org.eclipse.pde" installMode="root"/>
<feature id="org.eclipse.buildship" installMode="root"/>
@@ -88,7 +88,7 @@
<feature id="org.springsource.ide.eclipse.commons.quicksearch.feature" installMode="root"/>
<feature id="org.springframework.ide.eclipse.boot.dash.feature" installMode="root"/>
<feature id="org.springframework.boot.ide.branding.feature" installMode="root"/>
<feature id="org.springframework.boot.ide.branding.feature"/>
<feature id="org.springframework.boot.ide.main.feature" installMode="root"/>
<feature id="org.springframework.tooling.boot.ls.feature" installMode="root"/>
@@ -100,11 +100,17 @@
<feature id="org.springframework.tooling.concourse.ls.feature" installMode="root"/>
</features>
<configurations>
<property name="eclipse.buildId" value="${unqualifiedVersion}.${buildQualifier}"/>
<property name="osgi.instance.area.default" value="@user.home/Documents/workspace-spring-tool-suite-4-${unqualifiedVersion}.${p2.qualifier}"/>
<plugin id="org.eclipse.equinox.simpleconfigurator" autoStart="true" startLevel="1" />
<plugin id="org.eclipse.core.runtime" autoStart="true" startLevel="4" />
<plugin id="org.eclipse.equinox.common" autoStart="true" startLevel="2" />
<plugin id="org.eclipse.equinox.event" autoStart="true" startLevel="2" />
<plugin id="org.apache.felix.scr" autoStart="true" startLevel="2" />
<plugin id="org.eclipse.equinox.p2.reconciler.dropins" autoStart="true" startLevel="4" />
<plugin id="org.eclipse.update.configurator" autoStart="false" startLevel="4" />
</configurations>
</product>

View File

@@ -61,7 +61,7 @@
<springide-p2-repo>http://dist.springframework.org/release/IDE/3.9.6.RELEASE</springide-p2-repo> -->
<sts4-language-servers-p2-repo>http://dist.springsource.com/${dist.type}/TOOLS/sts4-language-server-integrations/${sts4-language-servers-version}</sts4-language-servers-p2-repo>
<tycho-version>1.1.0</tycho-version>
<tycho-version>1.2.0</tycho-version>
<encoding>UTF-8</encoding>
</properties>

View File

@@ -36,7 +36,8 @@
</content-type>
<file-association
content-type="org.springframework.boot.ide.properties.application.properties"
file-names="application.properties,application-dev.properties">
file-names="application.properties,application-dev.properties"
file-patterns="application-*.properties">
</file-association>
</extension>
@@ -50,7 +51,8 @@
</content-type>
<file-association
content-type="org.springframework.boot.ide.properties.application.yml"
file-names="application.yml,bootstrap.yml,application-dev.yml">
file-names="application.yml,bootstrap.yml,application-dev.yml"
file-patterns="application-*.yml">
</file-association>
</extension>

View File

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

View File

@@ -25,9 +25,9 @@ import org.springframework.ide.vscode.commons.java.IJavaProject;
* @author Kris De Volder
*/
public interface JavaProjectFinder {
Optional<IJavaProject> find(TextDocumentIdentifier doc);
default JavaProjectFinder filter(Predicate<IJavaProject> acceptWhen) {
return doc -> this.find(doc).flatMap(jp -> {
if (acceptWhen.test(jp)) {

View File

@@ -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<TextDocumentSaveChange> l);
// add more 'onDidXXX' if needed/useful.
}

View File

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

View File

@@ -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<String, TrackedDocument> documents = new HashMap<>();
@@ -85,7 +86,7 @@ public class SimpleTextDocumentService implements TextDocumentService {
private CodeLensHandler codeLensHandler;
private CodeLensResolveHandler codeLensResolveHandler;
private Consumer<TextDocumentSaveChange> documentSaveListener;
private List<Consumer<TextDocumentSaveChange>> 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<TextDocumentSaveChange> l) {
documentSaveListener=l;
ImmutableList.Builder<Consumer<TextDocumentSaveChange>> 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<TextDocumentSaveChange> l : documentSaveListeners) {
l.accept(new TextDocumentSaveChange(doc));
}
}
}
});

View File

@@ -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<E> implements Iterable<E> {
return entries.size();
}
public TreeMap<String, E> getTreeMap() {
return entries;
}
}

View File

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

View File

@@ -1,5 +1,4 @@
<factorypath>
<factorypathentry kind="VARJAR" id="M2_REPO/org/springframework/ide/vscode/language-server-starter/1.1.0-SNAPSHOT/language-server-starter-1.1.0-SNAPSHOT.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/org/springframework/boot/spring-boot-starter/2.0.5.RELEASE/spring-boot-starter-2.0.5.RELEASE.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/org/springframework/boot/spring-boot-autoconfigure/2.0.5.RELEASE/spring-boot-autoconfigure-2.0.5.RELEASE.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/org/springframework/boot/spring-boot-starter-logging/2.0.5.RELEASE/spring-boot-starter-logging-2.0.5.RELEASE.jar" enabled="true" runInBatchMode="false"/>
@@ -10,8 +9,6 @@
<factorypathentry kind="VARJAR" id="M2_REPO/org/slf4j/jul-to-slf4j/1.7.25/jul-to-slf4j-1.7.25.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/javax/annotation/javax.annotation-api/1.3.2/javax.annotation-api-1.3.2.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/org/springframework/ide/eclipse/org.json/1.0/org.json-1.0.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/org/springframework/ide/vscode/java-properties/1.1.0-SNAPSHOT/java-properties-1.1.0-SNAPSHOT.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/org/springframework/ide/vscode/commons-util/1.1.0-SNAPSHOT/commons-util-1.1.0-SNAPSHOT.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/org/javolution/javolution-core-java/6.0.0/javolution-core-java-6.0.0.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/cglib/cglib/3.2.7/cglib-3.2.7.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/org/apache/ant/ant/1.10.3/ant-1.10.3.jar" enabled="true" runInBatchMode="false"/>
@@ -20,7 +17,6 @@
<factorypathentry kind="VARJAR" id="M2_REPO/org/jsoup/jsoup/1.9.2/jsoup-1.9.2.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/com/google/guava/guava/19.0/guava-19.0.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/org/antlr/antlr4-runtime/4.5.3/antlr4-runtime-4.5.3.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/org/springframework/ide/vscode/commons-maven/1.1.0-SNAPSHOT/commons-maven-1.1.0-SNAPSHOT.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/org/apache/maven/maven-core/3.3.9/maven-core-3.3.9.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/org/apache/maven/maven-model/3.3.9/maven-model-3.3.9.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/org/apache/maven/maven-settings/3.3.9/maven-settings-3.3.9.jar" enabled="true" runInBatchMode="false"/>
@@ -61,11 +57,8 @@
<factorypathentry kind="VARJAR" id="M2_REPO/org/apache/maven/wagon/wagon-file/2.10/wagon-file-2.10.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/commons-lang/commons-lang/2.6/commons-lang-2.6.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/org/apache/maven/wagon/wagon-provider-api/2.10/wagon-provider-api-2.10.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/org/springframework/ide/vscode/commons-java/1.1.0-SNAPSHOT/commons-java-1.1.0-SNAPSHOT.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/org/jboss/jandex/2.0.5.Final/jandex-2.0.5.Final.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/org/springframework/ide/vscode/commons-gradle/1.1.0-SNAPSHOT/commons-gradle-1.1.0-SNAPSHOT.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/org/gradle/gradle-tooling-api/4.3/gradle-tooling-api-4.3.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/org/springframework/ide/vscode/commons-language-server/1.1.0-SNAPSHOT/commons-language-server-1.1.0-SNAPSHOT.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/org/springframework/boot/spring-boot/2.0.5.RELEASE/spring-boot-2.0.5.RELEASE.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/org/springframework/spring-context/5.0.9.RELEASE/spring-context-5.0.9.RELEASE.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/org/springframework/spring-aop/5.0.9.RELEASE/spring-aop-5.0.9.RELEASE.jar" enabled="true" runInBatchMode="false"/>
@@ -73,10 +66,8 @@
<factorypathentry kind="VARJAR" id="M2_REPO/org/springframework/spring-expression/5.0.9.RELEASE/spring-expression-5.0.9.RELEASE.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/io/projectreactor/reactor-core/3.1.9.RELEASE/reactor-core-3.1.9.RELEASE.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/org/reactivestreams/reactive-streams/1.0.2/reactive-streams-1.0.2.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/org/springframework/ide/vscode/commons-yaml/1.1.0-SNAPSHOT/commons-yaml-1.1.0-SNAPSHOT.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/org/yaml/snakeyaml/1.19/snakeyaml-1.19.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/javax/inject/javax.inject/1/javax.inject-1.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/org/springframework/ide/vscode/commons-boot-app-cli/1.1.0-SNAPSHOT/commons-boot-app-cli-1.1.0-SNAPSHOT.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/org/json/json/20160810/json-20160810.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/commons-codec/commons-codec/1.11/commons-codec-1.11.jar" enabled="true" runInBatchMode="false"/>
<factorypathentry kind="VARJAR" id="M2_REPO/org/ow2/asm/asm/6.1.1/asm-6.1.1.jar" enabled="true" runInBatchMode="false"/>

View File

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

View File

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

View File

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

View File

@@ -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()<propertyName.length()) {
//true prefix
//TODO: properly process remaining portion of property name
try {
hintProvider = hintProvider.traverse(YamlPathSegment.valueAt(0));
} catch (Exception e) {
Log.log(e);
}
}
if (!HintProviders.isNull(hintProvider)) {
allHints.addAll(hintProvider.getValueHints(query));
}

View File

@@ -64,6 +64,8 @@ import org.springframework.ide.vscode.boot.java.utils.SpringLiveHoverWatchdog;
import org.springframework.ide.vscode.boot.java.value.ValueCompletionProcessor;
import org.springframework.ide.vscode.boot.java.value.ValueHoverProvider;
import org.springframework.ide.vscode.boot.java.value.ValuePropertyReferencesProvider;
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.commons.languageserver.completion.ICompletionEngine;
import org.springframework.ide.vscode.commons.languageserver.composable.LanguageServerComponents;
@@ -97,7 +99,7 @@ public class BootJavaLanguageServerComponents implements LanguageServerComponent
private final BootLanguageServerParams serverParams;
private final SpringIndexer indexer;
private final SpringPropertyIndexProvider propertyIndexProvider;
private final SpringPropertyIndexProvider adHocPropertyIndexProvider;
private final ProjectBasedPropertyIndexProvider adHocPropertyIndexProvider;
private final SpringLiveHoverWatchdog liveHoverWatchdog;
private final SpringLiveChangeDetectionWatchdog liveChangeDetectionWatchdog;
private final ProjectObserver projectObserver;
@@ -109,7 +111,13 @@ public class BootJavaLanguageServerComponents implements LanguageServerComponent
private CodeLensHandler codeLensHandler;
private DocumentHighlightHandler highlightsEngine;
public BootJavaLanguageServerComponents(SimpleLanguageServer server, BootLanguageServerParams serverParams, SourceLinks sourceLinks, CompilationUnitCache cuCache) {
public BootJavaLanguageServerComponents(
SimpleLanguageServer server,
BootLanguageServerParams serverParams,
SourceLinks sourceLinks,
CompilationUnitCache cuCache,
ProjectBasedPropertyIndexProvider adHocIndexProvider
) {
this.server = server;
this.serverParams = serverParams;
@@ -120,7 +128,7 @@ public class BootJavaLanguageServerComponents implements LanguageServerComponent
this.cuCache = cuCache;
propertyIndexProvider = serverParams.indexProvider;
adHocPropertyIndexProvider = serverParams.adHocIndexProvider;
this.adHocPropertyIndexProvider = adHocIndexProvider;
SimpleWorkspaceService workspaceService = server.getWorkspaceService();
SimpleTextDocumentService documents = server.getTextDocumentService();
@@ -258,11 +266,13 @@ public class BootJavaLanguageServerComponents implements LanguageServerComponent
protected ICompletionEngine createCompletionEngine(
JavaProjectFinder javaProjectFinder,
SpringPropertyIndexProvider indexProvider,
SpringPropertyIndexProvider adHocIndexProvider)
{
ProjectBasedPropertyIndexProvider adHocIndexProvider) {
Map<String, CompletionProvider> 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);

View File

@@ -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<PropertyInfo> m : index.find(prefix)) {
if (suggestedKeys.add(m.data.getId())) {
matches.add(m);
Optional<IJavaProject> p = projectFinder.find(new TextDocumentIdentifier(doc.getUri()));
if (p.isPresent()) {
index = adHocIndexProvider.getIndex(p.get());
for (Match<PropertyInfo> m : index.find(prefix)) {
if (suggestedKeys.add(m.data.getId())) {
matches.add(m);
}
}
}
return matches;

View File

@@ -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<IJavaProject, SimplePropertyIndex> 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<PropertyInfo> getIndex(IDocument doc) {
Optional<IJavaProject> jp = projectFinder.find(new TextDocumentIdentifier(doc.getUri()));
if (jp.isPresent()) {
return getIndex(jp.get());
public FuzzyMap<PropertyInfo> 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<PropertyInfo> 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<File, Properties> 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, "<object>");
}
//Ignore other cases, might implement later if it makes sense.
break;
}

View File

@@ -62,7 +62,7 @@ public class ClassReferenceProvider extends CachingValueProvider {
return UNTARGETTED_INSTANCE;
}
);
private static <K,V> Function<K,V> applyOn(long duration, TimeUnit unit, Function<K,V> func) {
Cache<K,V> cache = CacheBuilder.newBuilder().expireAfterAccess(duration, unit).expireAfterWrite(duration, unit).build();
return (k) -> {

View File

@@ -22,17 +22,17 @@ import org.springframework.ide.vscode.commons.util.FuzzyMap;
import org.springframework.ide.vscode.commons.util.text.IDocument;
public class DefaultSpringPropertyIndexProvider implements SpringPropertyIndexProvider {
private JavaProjectFinder javaProjectFinder;
private SpringPropertiesIndexManager indexManager;
private ProgressService progressService = (id, msg) -> { /*ignore*/ };
public DefaultSpringPropertyIndexProvider(JavaProjectFinder javaProjectFinder, ProjectObserver projectObserver) {
public DefaultSpringPropertyIndexProvider(JavaProjectFinder javaProjectFinder, ProjectObserver projectObserver, ValueProviderRegistry valueProviders) {
this.javaProjectFinder = javaProjectFinder;
this.indexManager = new SpringPropertiesIndexManager(ValueProviderRegistry.getDefault(), projectObserver);
this.indexManager = new SpringPropertiesIndexManager(valueProviders, projectObserver);
}
@Override
public FuzzyMap<PropertyInfo> getIndex(IDocument doc) {
Optional<IJavaProject> jp = javaProjectFinder.find(new TextDocumentIdentifier(doc.getUri()));

View File

@@ -11,12 +11,19 @@
package org.springframework.ide.vscode.boot.metadata;
import java.util.Collection;
import java.util.Map;
import java.util.SortedMap;
import java.util.function.Function;
import java.util.function.Predicate;
import org.springframework.ide.vscode.boot.metadata.ValueProviderRegistry.ValueProviderStrategy;
import org.springframework.ide.vscode.boot.metadata.hints.StsValueHint;
import org.springframework.ide.vscode.commons.java.IJavaProject;
import org.springframework.ide.vscode.commons.util.FuzzyMatcher;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSet.Builder;
import reactor.core.publisher.Flux;
import reactor.util.function.Tuples;
@@ -30,13 +37,42 @@ import reactor.util.function.Tuples;
* @author Alex Boyko
*/
public class LoggerNameProvider extends CachingValueProvider {
private static final ValueProviderStrategy INSTANCE = new LoggerNameProvider();
public static final Function<Map<String, Object>, ValueProviderStrategy> FACTORY = (params) -> INSTANCE;
private static final String LOGGING_GROUPS_PREFIX = "logging.group.";
private final ProjectBasedPropertyIndexProvider adhocProperties;
public LoggerNameProvider(ProjectBasedPropertyIndexProvider adhocProperties) {
this.adhocProperties = adhocProperties;
}
public final Function<Map<String, Object>, ValueProviderStrategy> FACTORY = (params) -> this;
Collection<String> loggerGroupNames(IJavaProject jp) {
Builder<String> builder = ImmutableSet.builder();
if (adhocProperties!=null) {
SortedMap<String, PropertyInfo> index = adhocProperties.getIndex(jp).getTreeMap();
index = index.subMap(LOGGING_GROUPS_PREFIX, LOGGING_GROUPS_PREFIX+Character.MAX_VALUE);
for (String prop : index.keySet()) {
if (prop.startsWith(LOGGING_GROUPS_PREFIX)) {
String groupName = prop.substring(LOGGING_GROUPS_PREFIX.length());
int bracket = groupName.indexOf('[');
if (bracket>=0) {
groupName = groupName.substring(0, bracket);
}
builder.add(groupName);
}
}
}
return builder.build();
}
@Override
protected Flux<StsValueHint> getValuesAsync(IJavaProject javaProject, String query) {
return Flux.concat(
Flux.fromIterable(loggerGroupNames(javaProject))
.map(loggerName -> Tuples.of(StsValueHint.create(loggerName), FuzzyMatcher.matchScore(query, loggerName)))
.filter(t -> t.getT2()!=0.0),
javaProject.getIndex()
.fuzzySearchPackages(query)
.map(t -> Tuples.of(StsValueHint.create(t.getT1()), t.getT2())),
@@ -46,7 +82,8 @@ public class LoggerNameProvider extends CachingValueProvider {
)
.collectSortedList((o1, o2) -> o2.getT2().compareTo(o1.getT2()))
.flatMapIterable(l -> l)
.map(t -> t.getT1());
.map(t -> t.getT1())
.distinct(h -> h.getValue());
}
}

View File

@@ -0,0 +1,19 @@
/*******************************************************************************
* 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.boot.metadata;
import org.springframework.ide.vscode.commons.java.IJavaProject;
import org.springframework.ide.vscode.commons.util.FuzzyMap;
@FunctionalInterface
public interface ProjectBasedPropertyIndexProvider {
FuzzyMap<PropertyInfo> getIndex(IJavaProject jp);
}

View File

@@ -142,20 +142,12 @@ public class PropertyInfo {
return description;
}
public HintProvider getHints(TypeUtil typeUtil, boolean dimensionAware) {
public HintProvider getHints(TypeUtil typeUtil) {
Type type = TypeParser.parse(this.type);
if (TypeUtil.isMap(type)) {
return HintProviders.forMap(keyHints(typeUtil), valueHints(typeUtil), TypeUtil.getDomainType(type), dimensionAware);
return HintProviders.forMap(keyHints(typeUtil), valueHints(typeUtil), TypeUtil.getDomainType(type));
} else if (TypeUtil.isSequencable(type)) {
if (dimensionAware) {
if (TypeUtil.isSequencable(type)) {
return HintProviders.forDomainAt(valueHints(typeUtil), TypeUtil.getDimensionality(type));
} else {
return HintProviders.forHere(valueHints(typeUtil));
}
} else {
return HintProviders.forAllValueContexts(valueHints(typeUtil));
}
return HintProviders.forAllValueContexts(valueHints(typeUtil));
} else {
return HintProviders.forHere(valueHints(typeUtil));
}

View File

@@ -32,26 +32,6 @@ import reactor.core.publisher.Flux;
*/
public class ValueProviderRegistry {
private static ValueProviderRegistry DEFAULT;
/**
* Creates a default {@link ValueProviderRegistry} which is initialized with all the known
* providers. (This is the one production code should use, test code might make use
* something else for mocking purposes).
*/
public synchronized static ValueProviderRegistry getDefault() {
if (DEFAULT==null) {
DEFAULT = new ValueProviderRegistry();
DEFAULT.initializeDefaults(DEFAULT);
}
return DEFAULT;
}
protected void initializeDefaults(ValueProviderRegistry r) {
def("logger-name", LoggerNameProvider.FACTORY);
def("class-reference", ClassReferenceProvider.FACTORY);
}
private Map<String, Function<Map<String, Object>, ValueProviderStrategy>> registry = new HashMap<>();
public interface ValueProviderStrategy {

View File

@@ -50,6 +50,11 @@ public class HintProviders {
public List<TypedProperty> getPropertyHints(String query) {
return ImmutableList.of();
}
@Override
public String toString() {
return "HintProvider.NULL";
}
};
/**
@@ -161,7 +166,7 @@ public class HintProviders {
return p == NULL || p==null;
}
public static HintProvider forMap(HintProvider _keyProvider, HintProvider _valueProvider, final Type valueType, final boolean dimensionAware) {
public static HintProvider forMap(HintProvider _keyProvider, HintProvider _valueProvider, final Type valueType) {
final HintProvider keyProvider = notNull(_keyProvider);
final HintProvider valueProvider = notNull(_valueProvider);
if (isNull(keyProvider) && isNull(valueProvider)) {
@@ -174,11 +179,7 @@ public class HintProviders {
switch (s.getType()) {
case VAL_AT_INDEX:
case VAL_AT_KEY:
if (dimensionAware) {
return forHere(valueProvider);
} else {
return forAllValueContexts(valueProvider);
}
return forAllValueContexts(valueProvider);
default:
return NULL;
}
@@ -186,12 +187,7 @@ public class HintProviders {
@Override
public List<StsValueHint> getValueHints(String query) {
if (dimensionAware) {
//pickier, completions only suggested in the domain of map, but not for map itself.
return ImmutableList.of();
} else {
return valueProvider.getValueHints(query);
}
return ImmutableList.of();
}
@Override

View File

@@ -60,6 +60,7 @@ import com.google.common.collect.ImmutableList;
public class PropertiesCompletionProposalsCalculator {
private static final PrefixFinder valuePrefixFinder = new PrefixFinder() {
@Override
protected boolean isPrefixChar(char c) {
return isValuePrefixChar(c);
}
@@ -67,12 +68,14 @@ public class PropertiesCompletionProposalsCalculator {
};
private static final PrefixFinder fuzzySearchPrefix = new PrefixFinder() {
@Override
protected boolean isPrefixChar(char c) {
return !Character.isWhitespace(c);
}
};
private static final PrefixFinder navigationPrefixFinder = new PrefixFinder() {
@Override
public String getPrefix(IDocument doc, int offset) {
String prefix = super.getPrefix(doc, offset);
//Check if character before looks like 'navigation'.. otherwise don't
@@ -96,11 +99,12 @@ public class PropertiesCompletionProposalsCalculator {
}
return 0;
}
@Override
protected boolean isPrefixChar(char c) {
return !Character.isWhitespace(c) && c!=']' && c!=']' && c!='.';
}
};
private FuzzyMap<PropertyInfo> index;
private TypeUtil typeUtil;
private PropertyCompletionFactory completionFactory;
@@ -108,7 +112,7 @@ public class PropertiesCompletionProposalsCalculator {
private int offset;
private boolean preferLowerCaseEnums;
private AntlrParser parser;
public PropertiesCompletionProposalsCalculator(FuzzyMap<PropertyInfo> index, TypeUtil typeUtil, PropertyCompletionFactory completionFactory, IDocument doc, int offset, boolean preferLowerCaseEnums) {
this.index = index;
this.typeUtil = typeUtil;
@@ -118,7 +122,7 @@ public class PropertiesCompletionProposalsCalculator {
this.preferLowerCaseEnums = preferLowerCaseEnums;
this.parser = new AntlrParser();
}
/**
* Create completions proposals in the context of a properties text editor.
*/
@@ -162,7 +166,7 @@ public class PropertiesCompletionProposalsCalculator {
}
private Collection<ICompletionProposal> getKeyHintProposals(PropertyInfo prop, int navOffset) {
HintProvider hintProvider = prop.getHints(typeUtil, false);
HintProvider hintProvider = prop.getHints(typeUtil);
if (!HintProviders.isNull(hintProvider)) {
String query = textBetween(doc, navOffset+1, offset);
List<TypedProperty> hintProperties = hintProvider.getPropertyHints(query);
@@ -271,9 +275,9 @@ public class PropertiesCompletionProposalsCalculator {
String query = valuePrefixFinder.getPrefix(doc, offset, valueRegion.getStart());
int startOfValue = offset - query.length();
EnumCaseMode caseMode = caseMode(query);
// note: no need to skip whitespace backwards.
String propertyName = /*fuzzySearchPrefix.getPrefix(doc, pair.getOffset())*/value.getParent().getKey().decode();
String propertyName = /*fuzzySearchPrefix.getPrefix(doc, pair.getOffset())*/value.getParent().getKey().decode();
// because value partition includes whitespace around the assignment
if (propertyName != null) {
Collection<StsValueHint> valueCompletions = getValueHints(index, typeUtil, query, propertyName, caseMode);
@@ -307,7 +311,7 @@ public class PropertiesCompletionProposalsCalculator {
length = doc.get(value.getOffset(), value.getLength()).trim().length();
} catch (BadLocationException e) {
// ignore
}
}
return new DocumentRegion(doc, value.getOffset(), value.getOffset() + length);
}

View File

@@ -515,7 +515,7 @@ public abstract class ApplicationYamlAssistContext extends AbstractYamlAssistCon
} else if (subIndex.getExactMatch()!=null) {
IndexContext asIndexContext = new IndexContext(getDocument(), documentSelector, contextPath.append(s), subIndex, completionFactory, typeUtil, conf, javaElementLocationProvider);
PropertyInfo prop = subIndex.getExactMatch();
return new TypeContext(asIndexContext, contextPath.append(s), TypeParser.parse(prop.getType()), completionFactory, typeUtil, conf, prop.getHints(typeUtil, true), javaElementLocationProvider);
return new TypeContext(asIndexContext, contextPath.append(s), TypeParser.parse(prop.getType()), completionFactory, typeUtil, conf, prop.getHints(typeUtil), javaElementLocationProvider);
}
}
//Unsuported navigation => no context for assist

View File

@@ -0,0 +1,28 @@
/*******************************************************************************
* 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.boot.bootiful;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.ide.vscode.boot.editor.harness.AdHocPropertyHarness;
import org.springframework.ide.vscode.boot.metadata.ProjectBasedPropertyIndexProvider;
import org.springframework.ide.vscode.boot.metadata.SpringPropertyIndexProvider;
@Configuration
public class AdHocPropertyHarnessTestConf {
@Bean AdHocPropertyHarness adHocPropertyHarness() {
return new AdHocPropertyHarness();
}
@Bean ProjectBasedPropertyIndexProvider adHocProperties(AdHocPropertyHarness adHocProperties) {
return adHocProperties.getIndexProvider();
}
}

View File

@@ -29,7 +29,7 @@ import org.springframework.test.annotation.DirtiesContext.ClassMode;
@OverrideAutoConfiguration(enabled=false)
@ImportAutoConfiguration(classes=LanguageServerAutoConf.class)
@SpringBootTest(classes={
BootLanguagServerBootApp.class,
BootLanguagServerBootApp.class
})
@DirtiesContext(classMode=ClassMode.AFTER_EACH_TEST_METHOD)
public @interface BootLanguageServerTest {

View File

@@ -1,13 +1,25 @@
/*******************************************************************************
* 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.boot.bootiful;
import java.time.Duration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.ide.vscode.boot.app.BootLanguageServerParams;
import org.springframework.ide.vscode.boot.editor.harness.PropertyIndexHarness;
import org.springframework.ide.vscode.boot.java.links.SourceLinkFactory;
import org.springframework.ide.vscode.boot.java.links.SourceLinks;
import org.springframework.ide.vscode.boot.metadata.ValueProviderRegistry;
import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder;
import org.springframework.ide.vscode.commons.languageserver.util.SimpleLanguageServer;
import org.springframework.ide.vscode.commons.util.text.LanguageId;
@@ -15,10 +27,11 @@ import org.springframework.ide.vscode.project.harness.BootLanguageServerHarness;
import org.springframework.ide.vscode.project.harness.MockRunningAppProvider;
@Configuration
@Import(AdHocPropertyHarnessTestConf.class)
public class HoverTestConf {
@Bean PropertyIndexHarness indexHarness() {
return new PropertyIndexHarness();
@Bean PropertyIndexHarness indexHarness(ValueProviderRegistry valueProviders) {
return new PropertyIndexHarness(valueProviders);
}
@Bean MockRunningAppProvider mockAppsHarness() {
@@ -33,13 +46,12 @@ public class HoverTestConf {
return Duration.ofMillis(100);
}
@Bean BootLanguageServerParams serverParams(SimpleLanguageServer server) {
BootLanguageServerParams testDefaults = BootLanguageServerParams.createTestDefault(server);
@Bean BootLanguageServerParams serverParams(SimpleLanguageServer server, ValueProviderRegistry valueProviders, PropertyIndexHarness indexHarness) {
BootLanguageServerParams testDefaults = BootLanguageServerParams.createTestDefault(server, valueProviders);
return new BootLanguageServerParams(
indexHarness().getProjectFinder(),
indexHarness.getProjectFinder(),
testDefaults.projectObserver,
indexHarness().getIndexProvider(),
indexHarness().getAdHocIndexProvider(),
indexHarness.getIndexProvider(),
testDefaults.typeUtilProvider,
mockAppsHarness().provider,
watchDogInterval()
@@ -53,5 +65,4 @@ public class HoverTestConf {
@Bean SourceLinks sourceLinks() {
return SourceLinkFactory.NO_SOURCE_LINKS;
}
}

View File

@@ -14,6 +14,7 @@ import org.eclipse.lsp4j.TextDocumentIdentifier;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.ide.vscode.boot.app.BootLanguageServerParams;
import org.springframework.ide.vscode.boot.editor.harness.PropertyIndexHarness;
import org.springframework.ide.vscode.boot.java.links.JavaDocumentUriProvider;
@@ -21,6 +22,7 @@ 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.java.utils.SpringLiveHoverWatchdog;
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.boot.test.DefinitionLinkAsserts;
@@ -32,10 +34,12 @@ import org.springframework.ide.vscode.commons.util.text.LanguageId;
import org.springframework.ide.vscode.project.harness.BootLanguageServerHarness;
import org.springframework.ide.vscode.project.harness.MockRunningAppProvider;
@Configuration public class PropertyEditorTestConf {
@Configuration
@Import(AdHocPropertyHarnessTestConf.class)
public class PropertyEditorTestConf {
@Bean PropertyIndexHarness indexHarness() {
return new PropertyIndexHarness();
@Bean PropertyIndexHarness indexHarness(ValueProviderRegistry valueProviders) {
return new PropertyIndexHarness(valueProviders);
}
@Bean MockRunningAppProvider mockAppsHarness() {
@@ -53,15 +57,14 @@ import org.springframework.ide.vscode.project.harness.MockRunningAppProvider;
return new BootLanguageServerHarness(server, serverParams, indexHarness, projectFinder, defaultLanguageId, defaultFileExtension);
}
@Bean BootLanguageServerParams serverParams(SimpleLanguageServer server) {
JavaProjectFinder projectFinder = indexHarness().getProjectFinder();
@Bean BootLanguageServerParams serverParams(SimpleLanguageServer server, PropertyIndexHarness indexHarness) {
JavaProjectFinder projectFinder = indexHarness.getProjectFinder();
TypeUtilProvider typeUtilProvider = (IDocument doc) -> new TypeUtil(projectFinder.find(new TextDocumentIdentifier(doc.getUri())));
return new BootLanguageServerParams(
projectFinder,
ProjectObserver.NULL,
indexHarness().getIndexProvider(),
indexHarness().getAdHocIndexProvider(),
indexHarness.getIndexProvider(),
typeUtilProvider,
mockAppsHarness().provider,
SpringLiveHoverWatchdog.DEFAULT_INTERVAL

View File

@@ -1,24 +1,40 @@
/*******************************************************************************
* 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.boot.bootiful;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.ide.vscode.boot.app.BootLanguageServerInitializer;
import org.springframework.ide.vscode.boot.app.BootLanguageServerParams;
import org.springframework.ide.vscode.boot.editor.harness.AdHocPropertyHarness;
import org.springframework.ide.vscode.boot.editor.harness.PropertyIndexHarness;
import org.springframework.ide.vscode.boot.java.BootJavaLanguageServerComponents;
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.SpringIndexer;
import org.springframework.ide.vscode.boot.metadata.DefaultSpringPropertyIndexProvider;
import org.springframework.ide.vscode.boot.metadata.SpringPropertyIndexProvider;
import org.springframework.ide.vscode.boot.metadata.ValueProviderRegistry;
import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder;
import org.springframework.ide.vscode.commons.languageserver.util.SimpleLanguageServer;
import org.springframework.ide.vscode.commons.util.text.LanguageId;
import org.springframework.ide.vscode.project.harness.BootLanguageServerHarness;
@Configuration public class SymbolProviderTestConf {
@Configuration
@Import(AdHocPropertyHarnessTestConf.class)
public class SymbolProviderTestConf {
@Bean PropertyIndexHarness indexHarness() {
return new PropertyIndexHarness();
@Bean PropertyIndexHarness indexHarness(ValueProviderRegistry valueProviders) {
return new PropertyIndexHarness(valueProviders);
}
@Bean JavaProjectFinder projectFinder(BootLanguageServerParams serverParams) {
@@ -29,8 +45,8 @@ import org.springframework.ide.vscode.project.harness.BootLanguageServerHarness;
return new BootLanguageServerHarness(server, serverParams, indexHarness, projectFinder, LanguageId.JAVA, ".java");
}
@Bean BootLanguageServerParams serverParams(SimpleLanguageServer server) {
return BootLanguageServerParams.createTestDefault(server);
@Bean BootLanguageServerParams serverParams(SimpleLanguageServer server, ValueProviderRegistry valueProviders) {
return BootLanguageServerParams.createTestDefault(server, valueProviders);
}
@Bean SpringIndexer springIndexer(BootLanguageServerInitializer serverInit) {

View File

@@ -14,6 +14,7 @@ import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
@@ -149,15 +150,22 @@ public abstract class AbstractPropsEditorTest {
private CompletionItem assertCompletionWithLabel(String expectLabel, List<CompletionItem> completions) {
StringBuilder found = new StringBuilder();
List<CompletionItem> matching = new ArrayList<CompletionItem>();
for (CompletionItem c : completions) {
String actualLabel = c.getLabel();
found.append(actualLabel+"\n");
if (actualLabel.equals(expectLabel)) {
return c;
matching.add(c);
}
}
fail("No completion found with label '"+expectLabel+"' in:\n"+found);
return null; //unreachable, but compiler doesn't know that.
if (matching.isEmpty()) {
fail("No completion found with label '"+expectLabel+"' in:\n"+found);
} else if (matching.size() > 1) {
fail("Multiple completion found with identical label '"+expectLabel+"' in:\n"+found);
} else {
return matching.get(0);
}
return null;
}
public void assertCompletionCount(int expected, String editorText) throws Exception {

View File

@@ -0,0 +1,36 @@
/*******************************************************************************
* 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.boot.editor.harness;
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.util.FuzzyMap;
public class AdHocPropertyHarness {
private FuzzyMap<PropertyInfo> adHocProperties = new FuzzyMap<PropertyInfo>() {
@Override
protected String getKey(PropertyInfo entry) {
return entry.getId();
}
};
protected final ProjectBasedPropertyIndexProvider adHocIndexProvider = project -> adHocProperties;
public ProjectBasedPropertyIndexProvider getIndexProvider() {
return adHocIndexProvider;
}
public void add(String adHocPropertyId) {
adHocProperties.add(new PropertyInfo(adHocPropertyId, null, null, null, null, null, null, null, null, null, null));
}
}

View File

@@ -34,15 +34,9 @@ import org.springframework.ide.vscode.commons.util.text.IDocument;
*/
public class PropertyIndexHarness {
private final ValueProviderRegistry valueProviders;
private Map<String, ConfigurationMetadataProperty> datas = new LinkedHashMap<>();
private ValueProviderRegistry valueProviders = ValueProviderRegistry.getDefault();
private SpringPropertyIndex index = null;
private FuzzyMap<PropertyInfo> adHocProperties = new FuzzyMap<PropertyInfo>() {
@Override
protected String getKey(PropertyInfo entry) {
return entry.getId();
}
};
private IJavaProject testProject = null;
protected final SpringPropertyIndexProvider indexProvider = new SpringPropertyIndexProvider() {
@@ -60,9 +54,11 @@ public class PropertyIndexHarness {
}
}
};
protected final SpringPropertyIndexProvider adHocIndexProvider = doc -> adHocProperties;
public PropertyIndexHarness(ValueProviderRegistry valueProviders) {
this.valueProviders = valueProviders;
}
public synchronized void useProject(IJavaProject p) throws Exception {
index = null;
this.testProject = p;
@@ -572,18 +568,10 @@ public class PropertyIndexHarness {
return indexProvider;
}
public SpringPropertyIndexProvider getAdHocIndexProvider() {
return adHocIndexProvider;
}
public JavaProjectFinder getProjectFinder() {
return (doc) -> Optional.ofNullable(testProject);
}
public void adHoc(String adHocPropertyId) {
adHocProperties.add(new PropertyInfo(adHocPropertyId, null, null, null, null, null, null, null, null, null, null));
}
public IJavaProject getTestProject() {
return testProject;
}

View File

@@ -40,14 +40,16 @@ public class RequestMappingLiveHoverTestWithContextPath {
}
@Test
public void testActuatorEnvOrderedPropertySourceCamelCase() throws Exception {
// Tests an actuator env json that contains camel case context path in command line arg and application config.
public void testBoot1xActualActuatorEnvProp() throws Exception {
File directory = new File(
ProjectsHarness.class.getResource("/test-projects/test-request-mapping-live-hover/").toURI());
String docUri = directory.toPath().resolve("src/main/java/example/HelloWorldController.java").toUri()
.toString();
String bootVersion = "1.x";
// Build a mock running boot app
mockAppProvider.builder()
.isSpringBootApp(true)
@@ -59,7 +61,7 @@ public class RequestMappingLiveHoverTestWithContextPath {
// mock app to return realistic results if possible
.requestMappingsJson(
"{\"/webjars/**\":{\"bean\":\"resourceHandlerMapping\"},\"/**\":{\"bean\":\"resourceHandlerMapping\"},\"/**/favicon.ico\":{\"bean\":\"faviconHandlerMapping\"},\"{[/hello-world],methods=[GET]}\":{\"bean\":\"requestMappingHandlerMapping\",\"method\":\"public example.Greeting example.HelloWorldController.sayHello(java.lang.String)\"},\"{[/goodbye]}\":{\"bean\":\"requestMappingHandlerMapping\",\"method\":\"public java.lang.String example.RestApi.goodbye()\"},\"{[/hello]}\":{\"bean\":\"requestMappingHandlerMapping\",\"method\":\"public java.lang.String example.RestApi.hello()\"},\"{[/error]}\":{\"bean\":\"requestMappingHandlerMapping\",\"method\":\"public org.springframework.http.ResponseEntity<java.util.Map<java.lang.String, java.lang.Object>> org.springframework.boot.autoconfigure.web.BasicErrorController.error(javax.servlet.http.HttpServletRequest)\"},\"{[/error],produces=[text/html]}\":{\"bean\":\"requestMappingHandlerMapping\",\"method\":\"public org.springframework.web.servlet.ModelAndView org.springframework.boot.autoconfigure.web.BasicErrorController.errorHtml(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse)\"}}")
.contextPathEnvJson("2.x", AcuatorEnvTestConstants.BOOT_2x_ENV_CONTEXT_PATH_CAMEL_CASE)
.contextPathEnvJson(bootVersion, AcuatorEnvTestConstants.BOOT_1x_ENV)
.build();
harness.intialize(directory);
@@ -67,23 +69,23 @@ public class RequestMappingLiveHoverTestWithContextPath {
Editor editor = harness.newEditorFromFileUri(docUri, LanguageId.JAVA);
editor.assertHighlights("@RequestMapping(method=RequestMethod.GET)");
// test that the command line arg context path appears
editor.assertHoverContains("@RequestMapping(method=RequestMethod.GET)", "[http://cfapps.io:1111/pathfromcommandlineargs/hello-world](http://cfapps.io:1111/pathfromcommandlineargs/hello-world) \n" +
editor.assertHoverContains("@RequestMapping(method=RequestMethod.GET)", "[http://cfapps.io:1111/fromEnv/hello-world](http://cfapps.io:1111/fromEnv/hello-world) \n" +
"\n" +
"Process [PID=22022, name=`test-request-mapping-live-hover`]");
}
@Test
public void testActuatorEnvOrderedPropertySourceKebabCase() throws Exception {
public void testBoot1xActualActuatorCommandArgCamel() throws Exception {
// Tests an actuator env json that contains kebab case context path in command line arg and application config.
File directory = new File(
ProjectsHarness.class.getResource("/test-projects/test-request-mapping-live-hover/").toURI());
String docUri = directory.toPath().resolve("src/main/java/example/HelloWorldController.java").toUri()
.toString();
String bootVersion = "1.x";
// Build a mock running boot app
mockAppProvider.builder()
.isSpringBootApp(true)
@@ -95,7 +97,7 @@ public class RequestMappingLiveHoverTestWithContextPath {
// mock app to return realistic results if possible
.requestMappingsJson(
"{\"/webjars/**\":{\"bean\":\"resourceHandlerMapping\"},\"/**\":{\"bean\":\"resourceHandlerMapping\"},\"/**/favicon.ico\":{\"bean\":\"faviconHandlerMapping\"},\"{[/hello-world],methods=[GET]}\":{\"bean\":\"requestMappingHandlerMapping\",\"method\":\"public example.Greeting example.HelloWorldController.sayHello(java.lang.String)\"},\"{[/goodbye]}\":{\"bean\":\"requestMappingHandlerMapping\",\"method\":\"public java.lang.String example.RestApi.goodbye()\"},\"{[/hello]}\":{\"bean\":\"requestMappingHandlerMapping\",\"method\":\"public java.lang.String example.RestApi.hello()\"},\"{[/error]}\":{\"bean\":\"requestMappingHandlerMapping\",\"method\":\"public org.springframework.http.ResponseEntity<java.util.Map<java.lang.String, java.lang.Object>> org.springframework.boot.autoconfigure.web.BasicErrorController.error(javax.servlet.http.HttpServletRequest)\"},\"{[/error],produces=[text/html]}\":{\"bean\":\"requestMappingHandlerMapping\",\"method\":\"public org.springframework.web.servlet.ModelAndView org.springframework.boot.autoconfigure.web.BasicErrorController.errorHtml(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse)\"}}")
.contextPathEnvJson("2.x", AcuatorEnvTestConstants.BOOT_2x_ENV_CONTEXT_PATH_KEBAB_CASE)
.contextPathEnvJson(bootVersion, AcuatorEnvTestConstants.BOOT_1x_COMMAND_LINE_ARG_CAMEL_CASE)
.build();
harness.intialize(directory);
@@ -103,13 +105,346 @@ public class RequestMappingLiveHoverTestWithContextPath {
Editor editor = harness.newEditorFromFileUri(docUri, LanguageId.JAVA);
editor.assertHighlights("@RequestMapping(method=RequestMethod.GET)");
// test that the command line arg context path appears
editor.assertHoverContains("@RequestMapping(method=RequestMethod.GET)", "[http://cfapps.io:1111/pathfromcommandlineargs/hello-world](http://cfapps.io:1111/pathfromcommandlineargs/hello-world) \n" +
editor.assertHoverContains("@RequestMapping(method=RequestMethod.GET)", "[http://cfapps.io:1111/fromlaunchconfig/hello-world](http://cfapps.io:1111/fromlaunchconfig/hello-world) \n" +
"\n" +
"Process [PID=22022, name=`test-request-mapping-live-hover`]");
}
@Test
public void testBoot1xActualActuatorCommandArgKebab() throws Exception {
File directory = new File(
ProjectsHarness.class.getResource("/test-projects/test-request-mapping-live-hover/").toURI());
String docUri = directory.toPath().resolve("src/main/java/example/HelloWorldController.java").toUri()
.toString();
String bootVersion = "1.x";
// Build a mock running boot app
mockAppProvider.builder()
.isSpringBootApp(true)
.port("1111")
.processId("22022")
.host("cfapps.io")
.processName("test-request-mapping-live-hover")
// Ugly, but this is real JSON copied from a real live running app. We want the
// mock app to return realistic results if possible
.requestMappingsJson(
"{\"/webjars/**\":{\"bean\":\"resourceHandlerMapping\"},\"/**\":{\"bean\":\"resourceHandlerMapping\"},\"/**/favicon.ico\":{\"bean\":\"faviconHandlerMapping\"},\"{[/hello-world],methods=[GET]}\":{\"bean\":\"requestMappingHandlerMapping\",\"method\":\"public example.Greeting example.HelloWorldController.sayHello(java.lang.String)\"},\"{[/goodbye]}\":{\"bean\":\"requestMappingHandlerMapping\",\"method\":\"public java.lang.String example.RestApi.goodbye()\"},\"{[/hello]}\":{\"bean\":\"requestMappingHandlerMapping\",\"method\":\"public java.lang.String example.RestApi.hello()\"},\"{[/error]}\":{\"bean\":\"requestMappingHandlerMapping\",\"method\":\"public org.springframework.http.ResponseEntity<java.util.Map<java.lang.String, java.lang.Object>> org.springframework.boot.autoconfigure.web.BasicErrorController.error(javax.servlet.http.HttpServletRequest)\"},\"{[/error],produces=[text/html]}\":{\"bean\":\"requestMappingHandlerMapping\",\"method\":\"public org.springframework.web.servlet.ModelAndView org.springframework.boot.autoconfigure.web.BasicErrorController.errorHtml(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse)\"}}")
.contextPathEnvJson(bootVersion, AcuatorEnvTestConstants.BOOT_1x_COMMAND_LINE_ARG_KEBAB_CASE)
.build();
harness.intialize(directory);
Editor editor = harness.newEditorFromFileUri(docUri, LanguageId.JAVA);
editor.assertHighlights("@RequestMapping(method=RequestMethod.GET)");
editor.assertHoverContains("@RequestMapping(method=RequestMethod.GET)", "[http://cfapps.io:1111/fromlaunchconfig/hello-world](http://cfapps.io:1111/fromlaunchconfig/hello-world) \n" +
"\n" +
"Process [PID=22022, name=`test-request-mapping-live-hover`]");
}
@Test
public void testBoot1xActualActuatorAppConfigFileKebab() throws Exception {
File directory = new File(
ProjectsHarness.class.getResource("/test-projects/test-request-mapping-live-hover/").toURI());
String docUri = directory.toPath().resolve("src/main/java/example/HelloWorldController.java").toUri()
.toString();
String bootVersion = "1.x";
// Build a mock running boot app
mockAppProvider.builder()
.isSpringBootApp(true)
.port("1111")
.processId("22022")
.host("cfapps.io")
.processName("test-request-mapping-live-hover")
// Ugly, but this is real JSON copied from a real live running app. We want the
// mock app to return realistic results if possible
.requestMappingsJson(
"{\"/webjars/**\":{\"bean\":\"resourceHandlerMapping\"},\"/**\":{\"bean\":\"resourceHandlerMapping\"},\"/**/favicon.ico\":{\"bean\":\"faviconHandlerMapping\"},\"{[/hello-world],methods=[GET]}\":{\"bean\":\"requestMappingHandlerMapping\",\"method\":\"public example.Greeting example.HelloWorldController.sayHello(java.lang.String)\"},\"{[/goodbye]}\":{\"bean\":\"requestMappingHandlerMapping\",\"method\":\"public java.lang.String example.RestApi.goodbye()\"},\"{[/hello]}\":{\"bean\":\"requestMappingHandlerMapping\",\"method\":\"public java.lang.String example.RestApi.hello()\"},\"{[/error]}\":{\"bean\":\"requestMappingHandlerMapping\",\"method\":\"public org.springframework.http.ResponseEntity<java.util.Map<java.lang.String, java.lang.Object>> org.springframework.boot.autoconfigure.web.BasicErrorController.error(javax.servlet.http.HttpServletRequest)\"},\"{[/error],produces=[text/html]}\":{\"bean\":\"requestMappingHandlerMapping\",\"method\":\"public org.springframework.web.servlet.ModelAndView org.springframework.boot.autoconfigure.web.BasicErrorController.errorHtml(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse)\"}}")
.contextPathEnvJson(bootVersion, AcuatorEnvTestConstants.BOOT_1x_APP_CONFIG_FILE_KEBAB_CASE)
.build();
harness.intialize(directory);
Editor editor = harness.newEditorFromFileUri(docUri, LanguageId.JAVA);
editor.assertHighlights("@RequestMapping(method=RequestMethod.GET)");
editor.assertHoverContains("@RequestMapping(method=RequestMethod.GET)", "[http://cfapps.io:1111/frompropsfile/hello-world](http://cfapps.io:1111/frompropsfile/hello-world) \n" +
"\n" +
"Process [PID=22022, name=`test-request-mapping-live-hover`]");
}
@Test
public void testBoot1xActualActuatorAppConfigFileCamel() throws Exception {
File directory = new File(
ProjectsHarness.class.getResource("/test-projects/test-request-mapping-live-hover/").toURI());
String docUri = directory.toPath().resolve("src/main/java/example/HelloWorldController.java").toUri()
.toString();
String bootVersion = "1.x";
// Build a mock running boot app
mockAppProvider.builder()
.isSpringBootApp(true)
.port("1111")
.processId("22022")
.host("cfapps.io")
.processName("test-request-mapping-live-hover")
// Ugly, but this is real JSON copied from a real live running app. We want the
// mock app to return realistic results if possible
.requestMappingsJson(
"{\"/webjars/**\":{\"bean\":\"resourceHandlerMapping\"},\"/**\":{\"bean\":\"resourceHandlerMapping\"},\"/**/favicon.ico\":{\"bean\":\"faviconHandlerMapping\"},\"{[/hello-world],methods=[GET]}\":{\"bean\":\"requestMappingHandlerMapping\",\"method\":\"public example.Greeting example.HelloWorldController.sayHello(java.lang.String)\"},\"{[/goodbye]}\":{\"bean\":\"requestMappingHandlerMapping\",\"method\":\"public java.lang.String example.RestApi.goodbye()\"},\"{[/hello]}\":{\"bean\":\"requestMappingHandlerMapping\",\"method\":\"public java.lang.String example.RestApi.hello()\"},\"{[/error]}\":{\"bean\":\"requestMappingHandlerMapping\",\"method\":\"public org.springframework.http.ResponseEntity<java.util.Map<java.lang.String, java.lang.Object>> org.springframework.boot.autoconfigure.web.BasicErrorController.error(javax.servlet.http.HttpServletRequest)\"},\"{[/error],produces=[text/html]}\":{\"bean\":\"requestMappingHandlerMapping\",\"method\":\"public org.springframework.web.servlet.ModelAndView org.springframework.boot.autoconfigure.web.BasicErrorController.errorHtml(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse)\"}}")
.contextPathEnvJson(bootVersion, AcuatorEnvTestConstants.BOOT_1x_APP_CONFIG_FILE_CAMEL_CASE)
.build();
harness.intialize(directory);
Editor editor = harness.newEditorFromFileUri(docUri, LanguageId.JAVA);
editor.assertHighlights("@RequestMapping(method=RequestMethod.GET)");
editor.assertHoverContains("@RequestMapping(method=RequestMethod.GET)", "[http://cfapps.io:1111/frompropsfile/hello-world](http://cfapps.io:1111/frompropsfile/hello-world) \n" +
"\n" +
"Process [PID=22022, name=`test-request-mapping-live-hover`]");
}
@Test
public void testBoot2xActualActuatorEnvProp() throws Exception {
File directory = new File(
ProjectsHarness.class.getResource("/test-projects/test-request-mapping-live-hover/").toURI());
String docUri = directory.toPath().resolve("src/main/java/example/HelloWorldController.java").toUri()
.toString();
String bootVersion = "2.x";
// Build a mock running boot app
mockAppProvider.builder()
.isSpringBootApp(true)
.port("1111")
.processId("22022")
.host("cfapps.io")
.processName("test-request-mapping-live-hover")
// Ugly, but this is real JSON copied from a real live running app. We want the
// mock app to return realistic results if possible
.requestMappingsJson(
"{\"/webjars/**\":{\"bean\":\"resourceHandlerMapping\"},\"/**\":{\"bean\":\"resourceHandlerMapping\"},\"/**/favicon.ico\":{\"bean\":\"faviconHandlerMapping\"},\"{[/hello-world],methods=[GET]}\":{\"bean\":\"requestMappingHandlerMapping\",\"method\":\"public example.Greeting example.HelloWorldController.sayHello(java.lang.String)\"},\"{[/goodbye]}\":{\"bean\":\"requestMappingHandlerMapping\",\"method\":\"public java.lang.String example.RestApi.goodbye()\"},\"{[/hello]}\":{\"bean\":\"requestMappingHandlerMapping\",\"method\":\"public java.lang.String example.RestApi.hello()\"},\"{[/error]}\":{\"bean\":\"requestMappingHandlerMapping\",\"method\":\"public org.springframework.http.ResponseEntity<java.util.Map<java.lang.String, java.lang.Object>> org.springframework.boot.autoconfigure.web.BasicErrorController.error(javax.servlet.http.HttpServletRequest)\"},\"{[/error],produces=[text/html]}\":{\"bean\":\"requestMappingHandlerMapping\",\"method\":\"public org.springframework.web.servlet.ModelAndView org.springframework.boot.autoconfigure.web.BasicErrorController.errorHtml(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse)\"}}")
.contextPathEnvJson(bootVersion, AcuatorEnvTestConstants.BOOT_2x_ENV)
.build();
harness.intialize(directory);
Editor editor = harness.newEditorFromFileUri(docUri, LanguageId.JAVA);
editor.assertHighlights("@RequestMapping(method=RequestMethod.GET)");
editor.assertHoverContains("@RequestMapping(method=RequestMethod.GET)", "[http://cfapps.io:1111/fromenvironment/hello-world](http://cfapps.io:1111/fromenvironment/hello-world) \n" +
"\n" +
"Process [PID=22022, name=`test-request-mapping-live-hover`]");
}
@Test
public void testBoot2xActualActuatorCommandArgCamel() throws Exception {
File directory = new File(
ProjectsHarness.class.getResource("/test-projects/test-request-mapping-live-hover/").toURI());
String docUri = directory.toPath().resolve("src/main/java/example/HelloWorldController.java").toUri()
.toString();
String bootVersion = "2.x";
// Build a mock running boot app
mockAppProvider.builder()
.isSpringBootApp(true)
.port("1111")
.processId("22022")
.host("cfapps.io")
.processName("test-request-mapping-live-hover")
// Ugly, but this is real JSON copied from a real live running app. We want the
// mock app to return realistic results if possible
.requestMappingsJson(
"{\"/webjars/**\":{\"bean\":\"resourceHandlerMapping\"},\"/**\":{\"bean\":\"resourceHandlerMapping\"},\"/**/favicon.ico\":{\"bean\":\"faviconHandlerMapping\"},\"{[/hello-world],methods=[GET]}\":{\"bean\":\"requestMappingHandlerMapping\",\"method\":\"public example.Greeting example.HelloWorldController.sayHello(java.lang.String)\"},\"{[/goodbye]}\":{\"bean\":\"requestMappingHandlerMapping\",\"method\":\"public java.lang.String example.RestApi.goodbye()\"},\"{[/hello]}\":{\"bean\":\"requestMappingHandlerMapping\",\"method\":\"public java.lang.String example.RestApi.hello()\"},\"{[/error]}\":{\"bean\":\"requestMappingHandlerMapping\",\"method\":\"public org.springframework.http.ResponseEntity<java.util.Map<java.lang.String, java.lang.Object>> org.springframework.boot.autoconfigure.web.BasicErrorController.error(javax.servlet.http.HttpServletRequest)\"},\"{[/error],produces=[text/html]}\":{\"bean\":\"requestMappingHandlerMapping\",\"method\":\"public org.springframework.web.servlet.ModelAndView org.springframework.boot.autoconfigure.web.BasicErrorController.errorHtml(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse)\"}}")
.contextPathEnvJson(bootVersion, AcuatorEnvTestConstants.BOOT_2x_COMMAND_LINE_ARG_CAMEL_CASE)
.build();
harness.intialize(directory);
Editor editor = harness.newEditorFromFileUri(docUri, LanguageId.JAVA);
editor.assertHighlights("@RequestMapping(method=RequestMethod.GET)");
editor.assertHoverContains("@RequestMapping(method=RequestMethod.GET)", "[http://cfapps.io:1111/fromlaunchconfig/hello-world](http://cfapps.io:1111/fromlaunchconfig/hello-world) \n" +
"\n" +
"Process [PID=22022, name=`test-request-mapping-live-hover`]");
}
@Test
public void testBoot2xActualActuatorCommandArgKebab() throws Exception {
File directory = new File(
ProjectsHarness.class.getResource("/test-projects/test-request-mapping-live-hover/").toURI());
String docUri = directory.toPath().resolve("src/main/java/example/HelloWorldController.java").toUri()
.toString();
String bootVersion = "2.x";
// Build a mock running boot app
mockAppProvider.builder()
.isSpringBootApp(true)
.port("1111")
.processId("22022")
.host("cfapps.io")
.processName("test-request-mapping-live-hover")
// Ugly, but this is real JSON copied from a real live running app. We want the
// mock app to return realistic results if possible
.requestMappingsJson(
"{\"/webjars/**\":{\"bean\":\"resourceHandlerMapping\"},\"/**\":{\"bean\":\"resourceHandlerMapping\"},\"/**/favicon.ico\":{\"bean\":\"faviconHandlerMapping\"},\"{[/hello-world],methods=[GET]}\":{\"bean\":\"requestMappingHandlerMapping\",\"method\":\"public example.Greeting example.HelloWorldController.sayHello(java.lang.String)\"},\"{[/goodbye]}\":{\"bean\":\"requestMappingHandlerMapping\",\"method\":\"public java.lang.String example.RestApi.goodbye()\"},\"{[/hello]}\":{\"bean\":\"requestMappingHandlerMapping\",\"method\":\"public java.lang.String example.RestApi.hello()\"},\"{[/error]}\":{\"bean\":\"requestMappingHandlerMapping\",\"method\":\"public org.springframework.http.ResponseEntity<java.util.Map<java.lang.String, java.lang.Object>> org.springframework.boot.autoconfigure.web.BasicErrorController.error(javax.servlet.http.HttpServletRequest)\"},\"{[/error],produces=[text/html]}\":{\"bean\":\"requestMappingHandlerMapping\",\"method\":\"public org.springframework.web.servlet.ModelAndView org.springframework.boot.autoconfigure.web.BasicErrorController.errorHtml(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse)\"}}")
.contextPathEnvJson(bootVersion, AcuatorEnvTestConstants.BOOT_2x_COMMAND_LINE_ARG_KEBAB_CASE)
.build();
harness.intialize(directory);
Editor editor = harness.newEditorFromFileUri(docUri, LanguageId.JAVA);
editor.assertHighlights("@RequestMapping(method=RequestMethod.GET)");
editor.assertHoverContains("@RequestMapping(method=RequestMethod.GET)", "[http://cfapps.io:1111/fromlaunchconfig/hello-world](http://cfapps.io:1111/fromlaunchconfig/hello-world) \n" +
"\n" +
"Process [PID=22022, name=`test-request-mapping-live-hover`]");
}
@Test
public void testBoot2xActualActuatorAppConfigFileKebab() throws Exception {
File directory = new File(
ProjectsHarness.class.getResource("/test-projects/test-request-mapping-live-hover/").toURI());
String docUri = directory.toPath().resolve("src/main/java/example/HelloWorldController.java").toUri()
.toString();
String bootVersion = "2.x";
// Build a mock running boot app
mockAppProvider.builder()
.isSpringBootApp(true)
.port("1111")
.processId("22022")
.host("cfapps.io")
.processName("test-request-mapping-live-hover")
// Ugly, but this is real JSON copied from a real live running app. We want the
// mock app to return realistic results if possible
.requestMappingsJson(
"{\"/webjars/**\":{\"bean\":\"resourceHandlerMapping\"},\"/**\":{\"bean\":\"resourceHandlerMapping\"},\"/**/favicon.ico\":{\"bean\":\"faviconHandlerMapping\"},\"{[/hello-world],methods=[GET]}\":{\"bean\":\"requestMappingHandlerMapping\",\"method\":\"public example.Greeting example.HelloWorldController.sayHello(java.lang.String)\"},\"{[/goodbye]}\":{\"bean\":\"requestMappingHandlerMapping\",\"method\":\"public java.lang.String example.RestApi.goodbye()\"},\"{[/hello]}\":{\"bean\":\"requestMappingHandlerMapping\",\"method\":\"public java.lang.String example.RestApi.hello()\"},\"{[/error]}\":{\"bean\":\"requestMappingHandlerMapping\",\"method\":\"public org.springframework.http.ResponseEntity<java.util.Map<java.lang.String, java.lang.Object>> org.springframework.boot.autoconfigure.web.BasicErrorController.error(javax.servlet.http.HttpServletRequest)\"},\"{[/error],produces=[text/html]}\":{\"bean\":\"requestMappingHandlerMapping\",\"method\":\"public org.springframework.web.servlet.ModelAndView org.springframework.boot.autoconfigure.web.BasicErrorController.errorHtml(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse)\"}}")
.contextPathEnvJson(bootVersion, AcuatorEnvTestConstants.BOOT_2x_APP_CONFIG_FILE_KEBAB_CASE)
.build();
harness.intialize(directory);
Editor editor = harness.newEditorFromFileUri(docUri, LanguageId.JAVA);
editor.assertHighlights("@RequestMapping(method=RequestMethod.GET)");
editor.assertHoverContains("@RequestMapping(method=RequestMethod.GET)", "[http://cfapps.io:1111/frompropsfile/hello-world](http://cfapps.io:1111/frompropsfile/hello-world) \n" +
"\n" +
"Process [PID=22022, name=`test-request-mapping-live-hover`]");
}
@Test
public void testBoot2xActualActuatorAppConfigFileCamel() throws Exception {
File directory = new File(
ProjectsHarness.class.getResource("/test-projects/test-request-mapping-live-hover/").toURI());
String docUri = directory.toPath().resolve("src/main/java/example/HelloWorldController.java").toUri()
.toString();
String bootVersion = "2.x";
// Build a mock running boot app
mockAppProvider.builder()
.isSpringBootApp(true)
.port("1111")
.processId("22022")
.host("cfapps.io")
.processName("test-request-mapping-live-hover")
// Ugly, but this is real JSON copied from a real live running app. We want the
// mock app to return realistic results if possible
.requestMappingsJson(
"{\"/webjars/**\":{\"bean\":\"resourceHandlerMapping\"},\"/**\":{\"bean\":\"resourceHandlerMapping\"},\"/**/favicon.ico\":{\"bean\":\"faviconHandlerMapping\"},\"{[/hello-world],methods=[GET]}\":{\"bean\":\"requestMappingHandlerMapping\",\"method\":\"public example.Greeting example.HelloWorldController.sayHello(java.lang.String)\"},\"{[/goodbye]}\":{\"bean\":\"requestMappingHandlerMapping\",\"method\":\"public java.lang.String example.RestApi.goodbye()\"},\"{[/hello]}\":{\"bean\":\"requestMappingHandlerMapping\",\"method\":\"public java.lang.String example.RestApi.hello()\"},\"{[/error]}\":{\"bean\":\"requestMappingHandlerMapping\",\"method\":\"public org.springframework.http.ResponseEntity<java.util.Map<java.lang.String, java.lang.Object>> org.springframework.boot.autoconfigure.web.BasicErrorController.error(javax.servlet.http.HttpServletRequest)\"},\"{[/error],produces=[text/html]}\":{\"bean\":\"requestMappingHandlerMapping\",\"method\":\"public org.springframework.web.servlet.ModelAndView org.springframework.boot.autoconfigure.web.BasicErrorController.errorHtml(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse)\"}}")
.contextPathEnvJson(bootVersion, AcuatorEnvTestConstants.BOOT_2x_APP_CONFIG_FILE_CAMEL_CASE)
.build();
harness.intialize(directory);
Editor editor = harness.newEditorFromFileUri(docUri, LanguageId.JAVA);
editor.assertHighlights("@RequestMapping(method=RequestMethod.GET)");
editor.assertHoverContains("@RequestMapping(method=RequestMethod.GET)", "[http://cfapps.io:1111/frompropsfile/hello-world](http://cfapps.io:1111/frompropsfile/hello-world) \n" +
"\n" +
"Process [PID=22022, name=`test-request-mapping-live-hover`]");
}
@Test
public void testBoot2xActualActuatorPropertySourcePriority() throws Exception {
// Test that for Boot 2.x, if context path property appears in three different sources:
// env var, command line arg, and app config file, that the highest priority source is read, in this case command line arg
File directory = new File(
ProjectsHarness.class.getResource("/test-projects/test-request-mapping-live-hover/").toURI());
String docUri = directory.toPath().resolve("src/main/java/example/HelloWorldController.java").toUri()
.toString();
String bootVersion = "2.x";
// Build a mock running boot app
mockAppProvider.builder()
.isSpringBootApp(true)
.port("1111")
.processId("22022")
.host("cfapps.io")
.processName("test-request-mapping-live-hover")
// Ugly, but this is real JSON copied from a real live running app. We want the
// mock app to return realistic results if possible
.requestMappingsJson(
"{\"/webjars/**\":{\"bean\":\"resourceHandlerMapping\"},\"/**\":{\"bean\":\"resourceHandlerMapping\"},\"/**/favicon.ico\":{\"bean\":\"faviconHandlerMapping\"},\"{[/hello-world],methods=[GET]}\":{\"bean\":\"requestMappingHandlerMapping\",\"method\":\"public example.Greeting example.HelloWorldController.sayHello(java.lang.String)\"},\"{[/goodbye]}\":{\"bean\":\"requestMappingHandlerMapping\",\"method\":\"public java.lang.String example.RestApi.goodbye()\"},\"{[/hello]}\":{\"bean\":\"requestMappingHandlerMapping\",\"method\":\"public java.lang.String example.RestApi.hello()\"},\"{[/error]}\":{\"bean\":\"requestMappingHandlerMapping\",\"method\":\"public org.springframework.http.ResponseEntity<java.util.Map<java.lang.String, java.lang.Object>> org.springframework.boot.autoconfigure.web.BasicErrorController.error(javax.servlet.http.HttpServletRequest)\"},\"{[/error],produces=[text/html]}\":{\"bean\":\"requestMappingHandlerMapping\",\"method\":\"public org.springframework.web.servlet.ModelAndView org.springframework.boot.autoconfigure.web.BasicErrorController.errorHtml(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse)\"}}")
.contextPathEnvJson(bootVersion, AcuatorEnvTestConstants.BOOT_2x_PROPERTY_SOURCE_PRIORITY)
.build();
harness.intialize(directory);
Editor editor = harness.newEditorFromFileUri(docUri, LanguageId.JAVA);
editor.assertHighlights("@RequestMapping(method=RequestMethod.GET)");
editor.assertHoverContains("@RequestMapping(method=RequestMethod.GET)", "[http://cfapps.io:1111/fromlaunchconfig/hello-world](http://cfapps.io:1111/fromlaunchconfig/hello-world) \n" +
"\n" +
"Process [PID=22022, name=`test-request-mapping-live-hover`]");
}
@Test
public void testWithMockedContextPath() throws Exception {
@@ -125,7 +460,7 @@ public class RequestMappingLiveHoverTestWithContextPath {
.port("1111")
.processId("22022")
.host("cfapps.io")
.contextPath("/adifferentpath")
.contextPath("/mockedpath")
.processName("test-request-mapping-live-hover")
// Ugly, but this is real JSON copied from a real live running app. We want the
// mock app to return realistic results if possible
@@ -137,7 +472,7 @@ public class RequestMappingLiveHoverTestWithContextPath {
Editor editor = harness.newEditorFromFileUri(docUri, LanguageId.JAVA);
editor.assertHighlights("@RequestMapping(method=RequestMethod.GET)");
editor.assertHoverContains("@RequestMapping(method=RequestMethod.GET)", "[http://cfapps.io:1111/adifferentpath/hello-world](http://cfapps.io:1111/adifferentpath/hello-world) \n" +
editor.assertHoverContains("@RequestMapping(method=RequestMethod.GET)", "[http://cfapps.io:1111/mockedpath/hello-world](http://cfapps.io:1111/mockedpath/hello-world) \n" +
"\n" +
"Process [PID=22022, name=`test-request-mapping-live-hover`]");
@@ -158,7 +493,7 @@ public class RequestMappingLiveHoverTestWithContextPath {
.port("999")
.processId("76543")
.host("cfapps.io")
.contextPath("/differentPaath")
.contextPath("/mockedpath")
.processName("test-request-mapping-live-hover")
// Ugly, but this is real JSON copied from a real live running app. We want the
// mock app to return realistic results if possible
@@ -185,8 +520,8 @@ public class RequestMappingLiveHoverTestWithContextPath {
"}",
docUri);
editor.assertHoverContains("@RequestMapping(value={\"/greetings\", \"/hello\"}, method=GET)", "[http://cfapps.io:999/differentPaath/greetings](http://cfapps.io:999/differentPaath/greetings) \n" +
"[http://cfapps.io:999/differentPaath/hello](http://cfapps.io:999/differentPaath/hello) \n" +
editor.assertHoverContains("@RequestMapping(value={\"/greetings\", \"/hello\"}, method=GET)", "[http://cfapps.io:999/mockedpath/greetings](http://cfapps.io:999/mockedpath/greetings) \n" +
"[http://cfapps.io:999/mockedpath/hello](http://cfapps.io:999/mockedpath/hello) \n" +
"\n" +
"Process [PID=76543, name=`test-request-mapping-live-hover`]");

View File

@@ -27,8 +27,10 @@ import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.ide.vscode.boot.app.BootLanguageServerInitializer;
import org.springframework.ide.vscode.boot.app.BootLanguageServerParams;
import org.springframework.ide.vscode.boot.bootiful.AdHocPropertyHarnessTestConf;
import org.springframework.ide.vscode.boot.bootiful.BootLanguageServerTest;
import org.springframework.ide.vscode.boot.editor.harness.PropertyIndexHarness;
import org.springframework.ide.vscode.boot.java.BootJavaLanguageServerComponents;
@@ -36,6 +38,7 @@ import org.springframework.ide.vscode.boot.java.handlers.RunningAppProvider;
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.ValueProviderRegistry;
import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder;
import org.springframework.ide.vscode.commons.languageserver.util.SimpleLanguageServer;
import org.springframework.ide.vscode.commons.languageserver.util.SimpleTextDocumentService;
@@ -67,10 +70,11 @@ public class CompilationUnitCacheTest {
@Autowired
private MockProjectObserver projectObserver;
@Import(AdHocPropertyHarnessTestConf.class)
@Configuration static class TestConf {
@Bean PropertyIndexHarness indexHarness() {
return new PropertyIndexHarness();
@Bean PropertyIndexHarness indexHarness(ValueProviderRegistry valueProviders) {
return new PropertyIndexHarness(valueProviders);
}
@Bean JavaProjectFinder projectFinder(BootLanguageServerParams serverParams) {
@@ -85,13 +89,12 @@ public class CompilationUnitCacheTest {
return new BootLanguageServerHarness(server, serverParams, indexHarness, projectFinder, LanguageId.JAVA, ".java");
}
@Bean BootLanguageServerParams serverParams(SimpleLanguageServer server, MockProjectObserver projectObserver) {
BootLanguageServerParams testDefaults = BootLanguageServerParams.createTestDefault(server);
@Bean BootLanguageServerParams serverParams(SimpleLanguageServer server, MockProjectObserver projectObserver, ValueProviderRegistry valueProviders, PropertyIndexHarness indexHarness) {
BootLanguageServerParams testDefaults = BootLanguageServerParams.createTestDefault(server, valueProviders);
return new BootLanguageServerParams(
indexHarness().getProjectFinder(),
indexHarness.getProjectFinder(),
projectObserver,
indexHarness().getIndexProvider(),
indexHarness().getAdHocIndexProvider(),
indexHarness.getIndexProvider(),
testDefaults.typeUtilProvider,
RunningAppProvider.NULL,
null

View File

@@ -12,10 +12,14 @@ package org.springframework.ide.vscode.boot.java.value.test;
import static org.junit.Assert.assertEquals;
import java.io.File;
import org.junit.Test;
import org.springframework.ide.vscode.boot.java.value.test.MockProjects.MockProject;
import org.springframework.ide.vscode.boot.metadata.AdHocSpringPropertyIndexProvider;
import org.springframework.ide.vscode.boot.metadata.PropertyInfo;
import org.springframework.ide.vscode.commons.languageserver.util.SimpleTextDocumentService;
import org.springframework.ide.vscode.commons.languageserver.util.TextDocumentSaveChange;
import org.springframework.ide.vscode.commons.util.FuzzyMap;
import org.springframework.ide.vscode.commons.util.text.LanguageId;
import org.springframework.ide.vscode.commons.util.text.TextDocument;
@@ -23,6 +27,7 @@ import org.springframework.ide.vscode.commons.util.text.TextDocument;
public class AdHocSpringPropertyIndexProviderTest {
private MockProjects projects = new MockProjects();
private MockDocumentEvents documents = new MockDocumentEvents();
@Test
public void parseProperties() throws Exception {
@@ -31,29 +36,45 @@ public class AdHocSpringPropertyIndexProviderTest {
"some-adhoc-foo=somefoo\n" +
"some-adhoc-bar=somebar\n"
);
AdHocSpringPropertyIndexProvider indexer = new AdHocSpringPropertyIndexProvider(projects.finder, projects.observer, null);
AdHocSpringPropertyIndexProvider indexer = new AdHocSpringPropertyIndexProvider(projects.finder, projects.observer, null, documents);
TextDocument doc = new TextDocument(project.uri("src/main/java/SomeClass.java"), LanguageId.JAVA);
assertProperties(indexer.getIndex(doc),
assertProperties(indexer.getIndex(project),
//alphabetic order
"some-adhoc-bar",
"some-adhoc-foo"
);
}
@Test
public void parseYamlWithList() throws Exception {
//Note: the LoggerNameProvider implementation relies on this behavior
MockProject project = projects.create("test-project");
project.ensureFile("src/main/resources/application.yml",
"from-yaml:\n" +
" adhoc:\n" +
" - one\n" +
" - two\n"
);
AdHocSpringPropertyIndexProvider indexer = new AdHocSpringPropertyIndexProvider(projects.finder, projects.observer, null, documents);
assertProperties(indexer.getIndex(project),
"from-yaml.adhoc"
);
}
@Test
public void parseYaml() throws Exception {
MockProject project = projects.create("test-project");
project.ensureFile("src/main/resources/application.yml",
"from-yaml:\n" +
" adhoc:\n" +
" foo: somefoo\n" +
" bar: somebar\n"
" adhoc:\n" +
" foo: somefoo\n" +
" bar: somebar\n"
);
AdHocSpringPropertyIndexProvider indexer = new AdHocSpringPropertyIndexProvider(projects.finder, projects.observer, null);
AdHocSpringPropertyIndexProvider indexer = new AdHocSpringPropertyIndexProvider(projects.finder, projects.observer, null, documents);
TextDocument doc = new TextDocument(project.uri("src/main/java/SomeClass.java"), LanguageId.JAVA);
assertProperties(indexer.getIndex(doc),
assertProperties(indexer.getIndex(project),
//alphabetic order
"from-yaml.adhoc.bar",
"from-yaml.adhoc.foo"
@@ -67,20 +88,19 @@ public class AdHocSpringPropertyIndexProviderTest {
"initial-property=somefoo\n"
);
AdHocSpringPropertyIndexProvider indexer = new AdHocSpringPropertyIndexProvider(projects.finder, projects.observer, null);
TextDocument doc = new TextDocument(project.uri("src/main/java/SomeClass.java"), LanguageId.JAVA);
AdHocSpringPropertyIndexProvider indexer = new AdHocSpringPropertyIndexProvider(projects.finder, projects.observer, null, documents);
assertProperties(indexer.getIndex(doc),
assertProperties(indexer.getIndex(project),
"initial-property"
);
project.ensureFile("new-sourcefolder/application.properties", "new-property=whatever");
assertProperties(indexer.getIndex(doc),
assertProperties(indexer.getIndex(project),
"initial-property"
);
project.createSourceFolder("new-sourcefolder");
assertProperties(indexer.getIndex(doc),
assertProperties(indexer.getIndex(project),
"initial-property",
"new-property"
);
@@ -93,20 +113,52 @@ public class AdHocSpringPropertyIndexProviderTest {
"initial-property=somefoo\n"
);
AdHocSpringPropertyIndexProvider indexer = new AdHocSpringPropertyIndexProvider(projects.finder, projects.observer, projects.fileObserver);
TextDocument doc = new TextDocument(project.uri("src/main/java/SomeClass.java"), LanguageId.JAVA);
AdHocSpringPropertyIndexProvider indexer = new AdHocSpringPropertyIndexProvider(projects.finder, projects.observer, projects.fileObserver, documents);
assertProperties(indexer.getIndex(doc),
assertProperties(indexer.getIndex(project),
"initial-property"
);
project.ensureFile("src/main/resources/application.properties", "from-properties=whatever");
assertProperties(indexer.getIndex(doc),
assertProperties(indexer.getIndex(project),
"from-properties"
);
project.ensureFile("src/main/resources/application.yml", "from-yaml: whatever");
assertProperties(indexer.getIndex(doc),
assertProperties(indexer.getIndex(project),
"from-properties",
"from-yaml"
);
}
@Test
public void respondsToDocumentSave() throws Exception {
MockProject project = projects.create("test-project");
project.ensureFile("src/main/resources/application.properties",
"initial-property=somefoo\n"
);
AdHocSpringPropertyIndexProvider indexer = new AdHocSpringPropertyIndexProvider(projects.finder, projects.observer, projects.fileObserver, documents);
assertProperties(indexer.getIndex(project),
"initial-property"
);
File propsFile = project.ensureFileNoEvents("src/main/resources/application.properties", "from-properties=whatever");
assertProperties(indexer.getIndex(project),
"initial-property" //not changed yet because didn't fire change events.
);
documents.fire(new TextDocumentSaveChange(new TextDocument(propsFile.toURI().toString(), LanguageId.BOOT_PROPERTIES)));
assertProperties(indexer.getIndex(project),
"from-properties"
);
project.ensureFileNoEvents("src/main/resources/application.yml", "from-yaml: whatever");
assertProperties(indexer.getIndex(project),
"from-properties"
);
documents.fire(new TextDocumentSaveChange(new TextDocument(propsFile.toURI().toString(), LanguageId.BOOT_PROPERTIES_YAML)));
assertProperties(indexer.getIndex(project),
"from-properties",
"from-yaml"
);

View File

@@ -0,0 +1,25 @@
package org.springframework.ide.vscode.boot.java.value.test;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
import org.springframework.ide.vscode.commons.languageserver.util.DocumentEventListenerManager;
import org.springframework.ide.vscode.commons.languageserver.util.TextDocumentSaveChange;
public class MockDocumentEvents implements DocumentEventListenerManager {
List<Consumer<TextDocumentSaveChange>> saveHandlers = new ArrayList<Consumer<TextDocumentSaveChange>>();
@Override
public void onDidSave(Consumer<TextDocumentSaveChange> h) {
saveHandlers.add(h);
}
public void fire(TextDocumentSaveChange e) {
saveHandlers.forEach(h -> {
h.accept(e);
});
}
}

View File

@@ -153,15 +153,26 @@ public class MockProjects {
return root.isDirectory();
}
public void ensureFile(String projectRelativePath, String contents) throws Exception {
public File ensureFileNoEvents(String projectRelativePath, String contents) throws Exception {
return ensureFile(false, projectRelativePath, contents);
}
private File ensureFile(boolean fireEvents, String projectRelativePath, String contents) throws Exception {
File target = new File(root, projectRelativePath);
boolean existed = target.exists();
IOUtil.pipe(new ByteArrayInputStream(contents.getBytes("UTF8")), target);
if (existed) {
fileObserver.fileChanged(target);
} else {
fileObserver.fileCreated(target);
if (fireEvents) {
if (existed) {
fileObserver.fileChanged(target);
} else {
fileObserver.fileCreated(target);
}
}
return target;
}
public void ensureFile(String projectRelativePath, String contents) throws Exception {
ensureFile(true, projectRelativePath, contents);
}
public String uri(String projectRelativePath) {

View File

@@ -19,20 +19,27 @@ import java.util.Optional;
import org.apache.commons.io.IOUtils;
import org.eclipse.lsp4j.CompletionItem;
import org.eclipse.xtend.lib.annotations.Accessors;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.ide.vscode.boot.app.BootLanguageServerParams;
import org.springframework.ide.vscode.boot.bootiful.AdHocPropertyHarnessTestConf;
import org.springframework.ide.vscode.boot.bootiful.BootLanguageServerTest;
import org.springframework.ide.vscode.boot.editor.harness.AdHocPropertyHarness;
import org.springframework.ide.vscode.boot.editor.harness.PropertyIndexHarness;
import org.springframework.ide.vscode.boot.java.handlers.RunningAppProvider;
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.java.value.ValueCompletionProcessor;
import org.springframework.ide.vscode.boot.metadata.AdHocSpringPropertyIndexProvider;
import org.springframework.ide.vscode.boot.metadata.SpringPropertyIndexProvider;
import org.springframework.ide.vscode.boot.metadata.ValueProviderRegistry;
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;
@@ -54,12 +61,16 @@ public class ValueCompletionTest {
@Autowired private BootLanguageServerHarness harness;
@Autowired private IJavaProject testProject;
@Autowired private JavaProjectFinder projectFinder;
private Editor editor;
@Autowired private PropertyIndexHarness indexHarness;
@Autowired private AdHocPropertyHarness adHocProperties;
@Configuration static class TestConf {
@Configuration
@Import(AdHocPropertyHarnessTestConf.class)
static class TestConf {
//Somewhat strange test setup, test provides a specific test project.
//The project finder finds this test project,
@@ -70,8 +81,8 @@ public class ValueCompletionTest {
return ProjectsHarness.INSTANCE.mavenProject("test-annotations");
}
@Bean PropertyIndexHarness indexHarness() {
return new PropertyIndexHarness();
@Bean PropertyIndexHarness indexHarness(ValueProviderRegistry valueProviders) {
return new PropertyIndexHarness(valueProviders);
}
@Bean JavaProjectFinder projectFinder(MavenJavaProject testProject) {
@@ -82,13 +93,12 @@ public class ValueCompletionTest {
return new BootLanguageServerHarness(server, serverParams, indexHarness, projectFinder, LanguageId.JAVA, ".java");
}
@Bean BootLanguageServerParams serverParams(SimpleLanguageServer server, JavaProjectFinder projectFinder) {
BootLanguageServerParams testDefaults = BootLanguageServerParams.createTestDefault(server);
@Bean BootLanguageServerParams serverParams(SimpleLanguageServer server, JavaProjectFinder projectFinder, ValueProviderRegistry valueProviders, PropertyIndexHarness indexHarness) {
BootLanguageServerParams testDefaults = BootLanguageServerParams.createTestDefault(server, valueProviders);
return new BootLanguageServerParams(
projectFinder,
ProjectObserver.NULL,
indexHarness().getIndexProvider(),
indexHarness().getAdHocIndexProvider(),
indexHarness.getIndexProvider(),
testDefaults.typeUtilProvider,
RunningAppProvider.NULL,
null
@@ -112,7 +122,7 @@ public class ValueCompletionTest {
@Test
public void testPrefixIdentification() {
ValueCompletionProcessor processor = new ValueCompletionProcessor(null, null);
ValueCompletionProcessor processor = new ValueCompletionProcessor(projectFinder, null, null);
assertEquals("pre", processor.identifyPropertyPrefix("pre", 3));
assertEquals("pre", processor.identifyPropertyPrefix("prefix", 3));
@@ -336,9 +346,9 @@ public class ValueCompletionTest {
"${spring.prop1}<*>"
);
indexHarness.adHoc("spring.ad-hoc.thingy");
indexHarness.adHoc("spring.ad-hoc.other-thingy");
indexHarness.adHoc("spring.prop1"); //should not suggest this twice!
adHocProperties.add("spring.ad-hoc.thingy");
adHocProperties.add("spring.ad-hoc.other-thingy");
adHocProperties.add("spring.prop1"); //should not suggest this twice!
editor.assertContextualCompletions(
"<*>"
, //==>

View File

@@ -18,7 +18,7 @@ import org.springframework.ide.vscode.boot.editor.harness.PropertyIndexHarness;
/**
* Index Navigation tests.
*
*
* @author Kris De Volder
* @author Alex Boyko
*
@@ -27,7 +27,7 @@ public class IndexNavigatorTest {
@Test
public void testSimple() throws Exception {
PropertyIndexHarness harness = new PropertyIndexHarness();
PropertyIndexHarness harness = indexHarness();
harness.defaultTestData();
start(harness);
@@ -43,9 +43,13 @@ public class IndexNavigatorTest {
assertEmpty();
}
private PropertyIndexHarness indexHarness() {
return new PropertyIndexHarness(new ValueProviderRegistry());
}
@Test
public void testPartialName() throws Exception {
PropertyIndexHarness harness = new PropertyIndexHarness();
PropertyIndexHarness harness = indexHarness();
harness.defaultTestData();
start(harness);
@@ -60,7 +64,7 @@ public class IndexNavigatorTest {
@Test
public void testAmbiguous() throws Exception {
PropertyIndexHarness harness = new PropertyIndexHarness();
PropertyIndexHarness harness = indexHarness();
harness.defaultTestData();
harness.data("foo.bar", "java.lang.String", null, "Foo dot bar");
@@ -130,7 +134,7 @@ public class IndexNavigatorTest {
public void navigate(String propName) {
navigator = navigator.selectSubProperty(propName);
}
}

View File

@@ -52,7 +52,7 @@ public class LoggerNameProviderTest {
"org.springframework.instrument.classloading.jboss.JBossMCTranslatorAdapter", //11
"org.springframework.instrument.classloading.jboss.JBossModulesAdapter" //12
};
private ProjectsHarness projects = ProjectsHarness.INSTANCE;
private MavenJavaProject project;
@@ -69,7 +69,7 @@ public class LoggerNameProviderTest {
@Test
public void directResults() throws Exception {
LoggerNameProvider p = new LoggerNameProvider();
LoggerNameProvider p = new LoggerNameProvider(null);
String query = "jboss";
List<String> directQueryResults = getResults(p, query);
@@ -84,7 +84,7 @@ public class LoggerNameProviderTest {
@Test
public void cachedResults() throws Exception {
LoggerNameProvider p = new LoggerNameProvider();
LoggerNameProvider p = new LoggerNameProvider(null);
for (int i = 0; i < 10; i++) {
long startTime = System.currentTimeMillis();
String query = "jboss";
@@ -105,7 +105,7 @@ public class LoggerNameProviderTest {
public void incrementalResults() throws Exception {
String fullQuery = "jboss";
CachingValueProvider p = new LoggerNameProvider();
CachingValueProvider p = new LoggerNameProvider(null);
for (int i = 0; i <= fullQuery.length(); i++) {
String query = fullQuery.substring(0, i);
List<String> results = getResults(p, query);

View File

@@ -22,21 +22,21 @@ import org.springframework.ide.vscode.project.harness.ProjectsHarness;
/**
* Sanity test the boot properties index
*
*
* @author Alex Boyko
*
*/
public class PropertiesIndexTest {
private static final String CUSTOM_PROPERTIES_PROJECT = "custom-properties-boot-project";
private ProjectsHarness projects = ProjectsHarness.INSTANCE;
private ProgressService progressService = (id, msg) -> { /*ignore*/ };
@Test
public void springStandardPropertyPresent_Maven() throws Exception {
SpringPropertiesIndexManager indexManager = new SpringPropertiesIndexManager(
ValueProviderRegistry.getDefault(), null);
new ValueProviderRegistry(), null);
IJavaProject mavenProject = projects.mavenProject(CUSTOM_PROPERTIES_PROJECT);
FuzzyMap<PropertyInfo> index = indexManager.get(mavenProject, progressService);
PropertyInfo propertyInfo = index.get("server.port");
@@ -48,7 +48,7 @@ public class PropertiesIndexTest {
@Test
public void customPropertyPresent_Maven() throws Exception {
SpringPropertiesIndexManager indexManager = new SpringPropertiesIndexManager(
ValueProviderRegistry.getDefault(), null);
new ValueProviderRegistry(), null);
IJavaProject mavenProject = projects.mavenProject(CUSTOM_PROPERTIES_PROJECT);
FuzzyMap<PropertyInfo> index = indexManager.get(mavenProject, progressService);
PropertyInfo propertyInfo = index.get("demo.settings.user");
@@ -60,7 +60,7 @@ public class PropertiesIndexTest {
@Test
public void propertyNotPresent_Maven() throws Exception {
SpringPropertiesIndexManager indexManager = new SpringPropertiesIndexManager(
ValueProviderRegistry.getDefault(), null);
new ValueProviderRegistry(), null);
IJavaProject mavenProject = projects.mavenProject(CUSTOM_PROPERTIES_PROJECT);
FuzzyMap<PropertyInfo> index = indexManager.get(mavenProject, progressService);
PropertyInfo propertyInfo = index.get("my.server.port");

View File

@@ -10,6 +10,7 @@
*******************************************************************************/
package org.springframework.ide.vscode.boot.test;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.springframework.ide.vscode.boot.properties.reconcile.ApplicationPropertiesProblemType.PROP_DUPLICATE_KEY;
@@ -35,6 +36,7 @@ import org.springframework.context.annotation.Import;
import org.springframework.ide.vscode.boot.bootiful.BootLanguageServerTest;
import org.springframework.ide.vscode.boot.bootiful.PropertyEditorTestConf;
import org.springframework.ide.vscode.boot.editor.harness.AbstractPropsEditorTest;
import org.springframework.ide.vscode.boot.editor.harness.AdHocPropertyHarness;
import org.springframework.ide.vscode.boot.editor.harness.StyledStringMatcher;
import org.springframework.ide.vscode.boot.metadata.CachingValueProvider;
import org.springframework.ide.vscode.boot.metadata.PropertiesLoader;
@@ -59,8 +61,9 @@ import com.google.common.io.Files;
@Import(PropertyEditorTestConf.class)
public class ApplicationPropertiesEditorTest extends AbstractPropsEditorTest {
@Autowired
private DefinitionLinkAsserts definitionLinkAsserts;
@Autowired DefinitionLinkAsserts definitionLinkAsserts;
@Autowired AdHocPropertyHarness adHocProperties;
@Configuration static class TestConf {
@Bean LanguageId defaultLanguageId() {
@@ -1148,6 +1151,68 @@ public class ApplicationPropertiesEditorTest extends AbstractPropsEditorTest {
);
}
@Test public void userDefinedLoggingGroups() throws Exception {
useProject(createPredefinedMavenProject("empty-boot-2.1.0-app"));
adHocProperties.add("logging.group.foobar");
adHocProperties.add("logging.group.user-defined");
adHocProperties.add("logging.group.indexed[0]");
adHocProperties.add("logging.group.indexed[0]");
assertCompletionWithLabel(
"logging.level.<*>"
, //==============
"user-defined",
//=>
"logging.level.user-defined=<*>"
);
assertCompletionWithLabel(
"logging.level.<*>"
, //==============
"foobar",
//=>
"logging.level.foobar=<*>"
);
assertCompletionWithLabel(
"logging.level.<*>"
, //==============
"indexed",
//=>
"logging.level.indexed=<*>"
);
}
@Test public void userDefinedLoggingGroupsValueCompletions() throws Exception {
useProject(createPredefinedMavenProject("empty-boot-2.1.0-app"));
assertCompletionWithLabel(
"logging.group.whatever=demo<*>"
, //==============
"com.example.demo",
//=>
"logging.group.whatever=com.example.demo<*>"
);
assertCompletionWithLabel(
"logging.group.whatever=stuff,demo<*>"
, //==============
"com.example.demo",
//=>
"logging.group.whatever=stuff,com.example.demo<*>"
);
assertCompletionWithLabel(
"logging.group.whatever[0]=demo<*>"
, //==============
"com.example.demo",
//=>
"logging.group.whatever[0]=com.example.demo<*>"
);
}
@Test public void testPropertyMapKeyCompletions() throws Exception {
useProject(createPredefinedMavenProject("empty-boot-2.1.0-app"));
assertCompletionWithLabel(

View File

@@ -256,6 +256,48 @@ public class ApplicationYamlEditorTest extends AbstractPropsEditorTest {
);
}
@Test public void userDefinedLoggingGroupsValueCompletions() throws Exception {
useProject(createPredefinedMavenProject("empty-boot-2.1.0-app"));
assertCompletionWithLabel(
"logging:\n" +
" group:\n"+
" whatever:\n" +
" - demo<*>"
, //==============
"com.example.demo",
//=>
"logging:\n" +
" group:\n"+
" whatever:\n" +
" - com.example.demo<*>"
);
assertCompletionWithLabel(
"logging:\n" +
" group:\n"+
" whatever: demo<*>"
, //==============
"com.example.demo",
//=>
"logging:\n" +
" group:\n"+
" whatever: com.example.demo<*>"
);
assertCompletionWithLabel(
"logging:\n" +
" group:\n"+
" whatever: stuff,demo<*>"
, //==============
"com.example.demo",
//=>
"logging:\n" +
" group:\n"+
" whatever: stuff,com.example.demo<*>"
);
}
///////////////////// ported tests from old STS code base ////////////////////////////////////////////////
@Test public void testHovers() throws Exception {