key = key(javaProject, query);
-// CacheEntry cached = cache.get(key);
-// if (cached==null) {
-// cache.put(key, cached = new CacheEntry(query, getValuesIncremental(javaProject, query)));
-// }
-// return cached.values;
-// }
-//
-// /**
-// * Tries to use an already cached, complete result for a query that is a prefix of the current query to speed things up.
-// *
-// * Falls back on doing a full-blown search if there's no usable 'prefix-query' in the cache.
-// */
-// private Flux getValuesIncremental(IJavaProject javaProject, String query) {
-//// debug("trying to solve "+query+" incrementally");
-// String subquery = query;
-// while (subquery.length()>=1) {
-// subquery = subquery.substring(0, subquery.length()-1);
-// CacheEntry cached = cache.get(key(javaProject, subquery));
-// if (cached!=null) {
-// System.out.println("cached "+subquery+": "+cached);
-// if (cached.isComplete) {
-//// debug("filtering "+subquery+" -> "+query);
-// return cached.values
-//// .doOnNext((hint) -> debug("filter["+query+"]: "+hint.getValue()))
-// .filter((hint) -> 0!=FuzzyMatcher.matchScore(query, hint.getValue().toString()));
-// } else {
-//// debug("subquery "+subquery+" cached but is incomplete");
-// }
-// }
-// }
-//// debug("full search for: "+query);
-// return getValuesAsycn(javaProject, query);
-// }
-//
-// protected abstract Flux getValuesAsycn(IJavaProject javaProject, String query);
-//
-// private Tuple2 key(IJavaProject javaProject, String query) {
-// return Tuples.of(javaProject==null?null:javaProject.getElementName(), query);
-// }
-//
-// protected Cache createCache() {
-// return new LimitedTimeCache<>(Duration.ofMinutes(1));
-// }
+ private Cache, CacheEntry> cache = createCache();
+
+ private class CacheEntry {
+ boolean isComplete = false;
+ int count = 0;
+ Flux values;
+
+ public CacheEntry(String query, Flux producer) {
+ values = producer
+ .take(MAX_RESULTS)
+ .cache(MAX_RESULTS);
+ values.subscribe(); // create infinite demand so that we actually force cache entries to be fetched upto the max.
+ }
+
+ @Override
+ public String toString() {
+ return "CacheEntry [isComplete=" + isComplete + ", count=" + count + "]";
+ }
+
+ }
+
+ @Override
+ public final Flux getValues(IJavaProject javaProject, String query) {
+ Tuple2 key = key(javaProject, query);
+ CacheEntry cached = null;
+ try {
+ cached = cache.get(key, () -> new CacheEntry(query, getValuesIncremental(javaProject, query)));
+ } catch (ExecutionException e) {
+ Log.log(e);
+ }
+ return cached.values;
+ }
+
+ /**
+ * Tries to use an already cached, complete result for a query that is a prefix of the current query to speed things up.
+ *
+ * Falls back on doing a full-blown search if there's no usable 'prefix-query' in the cache.
+ */
+ private Flux getValuesIncremental(IJavaProject javaProject, String query) {
+// debug("trying to solve "+query+" incrementally");
+ String subquery = query;
+ while (subquery.length()>=1) {
+ subquery = subquery.substring(0, subquery.length()-1);
+ CacheEntry cached = null;
+ try {
+ cached = cache.get(key(javaProject, subquery), () -> null);
+ } catch (ExecutionException | InvalidCacheLoadException e) {
+// Log.log(e);
+ }
+ if (cached!=null) {
+ System.out.println("cached "+subquery+": "+cached);
+ if (cached.isComplete) {
+ return cached.values
+// .doOnNext((hint) -> debug("filter["+query+"]: "+hint.getValue()))
+ .filter((hint) -> 0!=FuzzyMatcher.matchScore(query, hint.getValue().toString()));
+ } else {
+// debug("subquery "+subquery+" cached but is incomplete");
+ }
+ }
+ }
+// debug("full search for: "+query);
+ return getValuesAsycn(javaProject, query);
+ }
+
+ protected abstract Flux getValuesAsycn(IJavaProject javaProject, String query);
+
+ private Tuple2 key(IJavaProject javaProject, String query) {
+ return Tuples.of(javaProject==null?null:javaProject.getElementName(), query);
+ }
+
+ protected Cache createCache() {
+ return CacheBuilder.newBuilder().expireAfterWrite(1, TimeUnit.MINUTES).build();
+ }
public static void restoreDefaults() {
TIMEOUT = DEFAULT_TIMEOUT;
diff --git a/vscode-extensions/commons/application-properties-metadata/src/main/java/org/springframework/ide/vscode/application/properties/metadata/ResourceHintProvider.java b/vscode-extensions/commons/application-properties-metadata/src/main/java/org/springframework/ide/vscode/application/properties/metadata/ResourceHintProvider.java
new file mode 100644
index 000000000..3200b2a01
--- /dev/null
+++ b/vscode-extensions/commons/application-properties-metadata/src/main/java/org/springframework/ide/vscode/application/properties/metadata/ResourceHintProvider.java
@@ -0,0 +1,60 @@
+package org.springframework.ide.vscode.application.properties.metadata;
+
+import java.util.Arrays;
+import java.util.stream.Collectors;
+
+import org.springframework.ide.vscode.application.properties.metadata.ValueProviderRegistry.ValueProviderStrategy;
+import org.springframework.ide.vscode.application.properties.metadata.hints.StsValueHint;
+import org.springframework.ide.vscode.commons.java.IJavaProject;
+
+import com.google.common.collect.ImmutableList;
+
+import reactor.core.publisher.Flux;
+
+/**
+ * @author Kris De Volder
+ */
+public class ResourceHintProvider implements ValueProviderStrategy {
+
+ private static String[] CLASSPATH_PREFIXES = {
+ "classpath:",
+ "classpath*:"
+ };
+
+ private static final String[] URL_PREFIXES = new String[] {
+ "classpath:",
+ "classpath*:",
+ "file:",
+ "http://",
+ "https://"
+ };
+
+ @Override
+ public Flux getValues(IJavaProject javaProject, String query) {
+ for (String prefix : CLASSPATH_PREFIXES) {
+ if (query.startsWith(prefix)) {
+ return classpathHints
+ .getValues(javaProject, query.substring(prefix.length()))
+ .map((hint) -> hint.prefixWith(prefix));
+ }
+ }
+ return Flux.fromIterable(urlPrefixHints);
+ }
+
+ final private ImmutableList urlPrefixHints = ImmutableList.copyOf(
+ Arrays.stream(URL_PREFIXES)
+ .map(StsValueHint::create)
+ .collect(Collectors.toList())
+ );
+
+ private ClasspathHints classpathHints = new ClasspathHints();
+
+ private static class ClasspathHints extends CachingValueProvider {
+ @Override
+ protected Flux getValuesAsycn(IJavaProject javaProject, String query) {
+ return Flux.fromStream(javaProject.getClasspath().getClasspathResources().distinct().map(StsValueHint::create));
+ }
+ }
+
+
+}
diff --git a/vscode-extensions/commons/application-properties-metadata/src/main/java/org/springframework/ide/vscode/application/properties/metadata/completions/PropertyCompletionFactory.java b/vscode-extensions/commons/application-properties-metadata/src/main/java/org/springframework/ide/vscode/application/properties/metadata/completions/PropertyCompletionFactory.java
index 360aedab3..87c75fde5 100644
--- a/vscode-extensions/commons/application-properties-metadata/src/main/java/org/springframework/ide/vscode/application/properties/metadata/completions/PropertyCompletionFactory.java
+++ b/vscode-extensions/commons/application-properties-metadata/src/main/java/org/springframework/ide/vscode/application/properties/metadata/completions/PropertyCompletionFactory.java
@@ -97,6 +97,11 @@ public class PropertyCompletionFactory {
return typeUtil.niceTypeName((Type) type);
}
+ @Override
+ public String getLabel() {
+ return getBaseDisplayString() + " : " + typeUtil.niceTypeName(getType());
+ }
+
};
if (property.isDeprecated()) {
proposal.deprecate();
@@ -157,6 +162,12 @@ public class PropertyCompletionFactory {
protected String niceTypeName(YType type) {
return typeUtil.niceTypeName(((Type)type));
}
+
+ @Override
+ public String getLabel() {
+ return getBaseDisplayString() + " : " + typeUtil.niceTypeName(getType());
+ }
+
}
}
diff --git a/vscode-extensions/commons/application-properties-metadata/src/main/java/org/springframework/ide/vscode/application/properties/metadata/types/TypeUtil.java b/vscode-extensions/commons/application-properties-metadata/src/main/java/org/springframework/ide/vscode/application/properties/metadata/types/TypeUtil.java
index 62a6950ee..e538f7519 100644
--- a/vscode-extensions/commons/application-properties-metadata/src/main/java/org/springframework/ide/vscode/application/properties/metadata/types/TypeUtil.java
+++ b/vscode-extensions/commons/application-properties-metadata/src/main/java/org/springframework/ide/vscode/application/properties/metadata/types/TypeUtil.java
@@ -26,6 +26,7 @@ import java.util.stream.Stream;
import javax.inject.Provider;
import org.springframework.boot.configurationmetadata.Deprecation;
+import org.springframework.ide.vscode.application.properties.metadata.ResourceHintProvider;
import org.springframework.ide.vscode.application.properties.metadata.ValueProviderRegistry.ValueProviderStrategy;
import org.springframework.ide.vscode.application.properties.metadata.hints.StsValueHint;
import org.springframework.ide.vscode.application.properties.metadata.util.DeprecationUtil;
@@ -577,7 +578,7 @@ public class TypeUtil {
return null;
}
});
-// valueHints("org.springframework.core.io.Resource", new ResourceHintProvider());
+ valueHints("org.springframework.core.io.Resource", new ResourceHintProvider());
}
/**
diff --git a/vscode-extensions/commons/application-properties-metadata/src/test/java/org/springframework/ide/vscode/boot/properties/metadata/PropertiesMetadataTestData.java b/vscode-extensions/commons/application-properties-metadata/src/test/java/org/springframework/ide/vscode/boot/properties/metadata/PropertiesMetadataTestData.java
index d12569ed3..94d366581 100644
--- a/vscode-extensions/commons/application-properties-metadata/src/test/java/org/springframework/ide/vscode/boot/properties/metadata/PropertiesMetadataTestData.java
+++ b/vscode-extensions/commons/application-properties-metadata/src/test/java/org/springframework/ide/vscode/boot/properties/metadata/PropertiesMetadataTestData.java
@@ -90,6 +90,12 @@ public class PropertiesMetadataTestData {
public Stream getClasspathEntries() throws Exception {
return Stream.empty();
}
+
+ @Override
+ public Stream getClasspathResources() {
+ return Stream.empty();
+ }
+
});
for (ConfigurationMetadataProperty propertyInfo : datas.values()) {
index.add(propertyInfo);
diff --git a/vscode-extensions/commons/commons-java/src/main/java/org/springframework/ide/vscode/commons/jandex/Wrappers.java b/vscode-extensions/commons/commons-java/src/main/java/org/springframework/ide/vscode/commons/jandex/Wrappers.java
index 8ec628f0c..333d897ff 100644
--- a/vscode-extensions/commons/commons-java/src/main/java/org/springframework/ide/vscode/commons/jandex/Wrappers.java
+++ b/vscode-extensions/commons/commons-java/src/main/java/org/springframework/ide/vscode/commons/jandex/Wrappers.java
@@ -16,6 +16,7 @@ import org.jboss.jandex.MethodInfo;
import org.jboss.jandex.PrimitiveType;
import org.jboss.jandex.Type;
import org.jboss.jandex.Type.Kind;
+import org.springframework.ide.vscode.commons.java.Flags;
import org.springframework.ide.vscode.commons.java.IAnnotation;
import org.springframework.ide.vscode.commons.java.IField;
import org.springframework.ide.vscode.commons.java.IJavaType;
@@ -28,8 +29,6 @@ import org.springframework.ide.vscode.commons.util.HtmlSnippet;
public class Wrappers {
- private static final int AccEnum = 0x4000;
-
public static IType wrap(IndexView index, ClassInfo info) {
if (info == null) {
return null;
@@ -75,7 +74,7 @@ public class Wrappers {
@Override
public boolean isEnum() {
- return (info.flags() & AccEnum) != 0;
+ return Flags.isEnum(info.flags());
}
@Override
@@ -161,7 +160,7 @@ public class Wrappers {
@Override
public boolean isEnumConstant() {
- return (field.flags() & AccEnum) != 0;
+ return Flags.isEnum(field.flags());
}
@Override
diff --git a/vscode-extensions/commons/commons-java/src/main/java/org/springframework/ide/vscode/commons/java/IClasspath.java b/vscode-extensions/commons/commons-java/src/main/java/org/springframework/ide/vscode/commons/java/IClasspath.java
index 5f4f1dbd6..81ef98d3a 100644
--- a/vscode-extensions/commons/commons-java/src/main/java/org/springframework/ide/vscode/commons/java/IClasspath.java
+++ b/vscode-extensions/commons/commons-java/src/main/java/org/springframework/ide/vscode/commons/java/IClasspath.java
@@ -30,4 +30,10 @@ public interface IClasspath {
*/
Stream getClasspathEntries() throws Exception;
+ /**
+ * Classpath resources paths relative to the source folder path
+ * @return classpath resource relative paths
+ */
+ Stream getClasspathResources();
+
}
diff --git a/vscode-extensions/vscode-application-yaml/src/main/java/org/springframework/ide/vscode/application/yaml/completions/LazyProposalApplier.java b/vscode-extensions/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/completion/LazyProposalApplier.java
similarity index 72%
rename from vscode-extensions/vscode-application-yaml/src/main/java/org/springframework/ide/vscode/application/yaml/completions/LazyProposalApplier.java
rename to vscode-extensions/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/completion/LazyProposalApplier.java
index fc655926e..85be1d905 100644
--- a/vscode-extensions/vscode-application-yaml/src/main/java/org/springframework/ide/vscode/application/yaml/completions/LazyProposalApplier.java
+++ b/vscode-extensions/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/completion/LazyProposalApplier.java
@@ -1,10 +1,7 @@
-package org.springframework.ide.vscode.application.yaml.completions;
+package org.springframework.ide.vscode.commons.languageserver.completion;
import java.util.concurrent.Callable;
-import org.springframework.ide.vscode.commons.languageserver.completion.DocumentEdits;
-import org.springframework.ide.vscode.commons.util.Log;
-
/**
* Temprary placeholder which sort of replaces the LazyProposalApplier from old STS.
* It really does nothing right now. Somehow this should be tied into LS protocol so
@@ -13,7 +10,7 @@ import org.springframework.ide.vscode.commons.util.Log;
* Right now this is not lazy at all and the completion edits are just computed immediatly.
*/
public class LazyProposalApplier {
-
+
public static DocumentEdits from(Callable createEdits) throws Exception {
return createEdits.call();
}
diff --git a/vscode-extensions/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/completion/VscodeCompletionEngineAdapter.java b/vscode-extensions/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/completion/VscodeCompletionEngineAdapter.java
index afc487c0d..8e62f6268 100644
--- a/vscode-extensions/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/completion/VscodeCompletionEngineAdapter.java
+++ b/vscode-extensions/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/completion/VscodeCompletionEngineAdapter.java
@@ -27,6 +27,8 @@ public class VscodeCompletionEngineAdapter implements VscodeCompletionEngine {
private final static int MAX_COMPLETIONS = 20;
+ private int maxCompletions = MAX_COMPLETIONS;
+
final static Logger logger = LoggerFactory.getLogger(VscodeCompletionEngineAdapter.class);
public static final String VS_CODE_CURSOR_MARKER = "{{}}";
@@ -39,6 +41,10 @@ public class VscodeCompletionEngineAdapter implements VscodeCompletionEngine {
this.engine = engine;
}
+ public void setMaxCompletionsNumber(int maxCompletions) {
+ this.maxCompletions = maxCompletions;
+ }
+
@Override
public CompletableFuture getCompletions(TextDocumentPositionParams params) {
//TODO: This returns a CompletableFuture which suggests we should try to do expensive work asyncly.
@@ -58,7 +64,7 @@ public class VscodeCompletionEngineAdapter implements VscodeCompletionEngine {
int count = 0;
for (ICompletionProposal c : completions) {
count++;
- if (count>MAX_COMPLETIONS) {
+ if (maxCompletions > 0 && count>maxCompletions) {
list.setIsIncomplete(true);
break;
}
diff --git a/vscode-extensions/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/java/DefaultJavaProjectFinder.java b/vscode-extensions/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/java/DefaultJavaProjectFinder.java
index 8503c514d..e4257b169 100644
--- a/vscode-extensions/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/java/DefaultJavaProjectFinder.java
+++ b/vscode-extensions/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/java/DefaultJavaProjectFinder.java
@@ -7,8 +7,8 @@ import org.springframework.ide.vscode.commons.util.Log;
public class DefaultJavaProjectFinder implements JavaProjectFinder {
private final IJavaProjectFinderStrategy[] STRATEGIES = new IJavaProjectFinderStrategy[] {
- new JavaProjectWithClasspathFileFinderStrategy(),
- new MavenProjectFinderStrategy()
+ new MavenProjectFinderStrategy(),
+ new JavaProjectWithClasspathFileFinderStrategy()
};
@Override
diff --git a/vscode-extensions/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/java/JavaProjectWithClasspathFileFinderStrategy.java b/vscode-extensions/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/java/JavaProjectWithClasspathFileFinderStrategy.java
index 9851272d0..2227eaf51 100644
--- a/vscode-extensions/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/java/JavaProjectWithClasspathFileFinderStrategy.java
+++ b/vscode-extensions/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/java/JavaProjectWithClasspathFileFinderStrategy.java
@@ -35,12 +35,14 @@ public class JavaProjectWithClasspathFileFinderStrategy implements IJavaProjectF
URI uri = new URI(uriStr);
// TODO: This only work with File uri. Should it work with others
// too?
- File file = toFile(uri);
- File cpFile = FileUtils.findFile(file, MavenCore.CLASSPATH_TXT);
- if (cpFile != null) {
- return cache.get(cpFile, () -> {
- return new JavaProjectWithClasspathFile(cpFile);
- });
+ if (uri.getScheme().equalsIgnoreCase("file")) {
+ File file = toFile(uri);
+ File cpFile = FileUtils.findFile(file, MavenCore.CLASSPATH_TXT);
+ if (cpFile != null) {
+ return cache.get(cpFile, () -> {
+ return new JavaProjectWithClasspathFile(cpFile);
+ });
+ }
}
}
return null;
diff --git a/vscode-extensions/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/java/MavenProjectFinderStrategy.java b/vscode-extensions/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/java/MavenProjectFinderStrategy.java
index 8f5c85429..50e74d57b 100644
--- a/vscode-extensions/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/java/MavenProjectFinderStrategy.java
+++ b/vscode-extensions/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/java/MavenProjectFinderStrategy.java
@@ -41,12 +41,14 @@ public class MavenProjectFinderStrategy implements IJavaProjectFinderStrategy {
URI uri = new URI(uriStr);
// TODO: This only work with File uri. Should it work with others
// too?
- File file = new File(uri).getAbsoluteFile();
- File pomFile = FileUtils.findFile(file, MavenCore.POM_XML);
- if (pomFile != null) {
- return cache.get(pomFile, () -> {
- return new MavenJavaProject(pomFile);
- });
+ if (uri.getScheme().equalsIgnoreCase("file")) {
+ File file = new File(uri).getAbsoluteFile();
+ File pomFile = FileUtils.findFile(file, MavenCore.POM_XML);
+ if (pomFile != null) {
+ return cache.get(pomFile, () -> {
+ return new MavenJavaProject(pomFile);
+ });
+ }
}
}
return null;
diff --git a/vscode-extensions/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/util/SimpleTextDocumentService.java b/vscode-extensions/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/util/SimpleTextDocumentService.java
index 1afe6bb6d..f76fdf3e9 100644
--- a/vscode-extensions/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/util/SimpleTextDocumentService.java
+++ b/vscode-extensions/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/util/SimpleTextDocumentService.java
@@ -182,80 +182,66 @@ public class SimpleTextDocumentService implements TextDocumentService {
@Override
public CompletableFuture hover(TextDocumentPositionParams position) {
- // TODO Auto-generated method stub
- return null;
+ return Futures.of(null);
}
@Override
public CompletableFuture signatureHelp(TextDocumentPositionParams position) {
- // TODO Auto-generated method stub
- return null;
+ return Futures.of(null);
}
@Override
public CompletableFuture> definition(TextDocumentPositionParams position) {
- // TODO Auto-generated method stub
- return null;
+ return Futures.of(Collections.emptyList());
}
@Override
public CompletableFuture> references(ReferenceParams params) {
- // TODO Auto-generated method stub
- return null;
+ return Futures.of(Collections.emptyList());
}
@Override
public CompletableFuture> documentSymbol(DocumentSymbolParams params) {
- // TODO Auto-generated method stub
- return null;
+ return Futures.of(Collections.emptyList());
}
@Override
public CompletableFuture> codeAction(CodeActionParams params) {
- // TODO Auto-generated method stub
- return null;
+ return Futures.of(Collections.emptyList());
}
@Override
public CompletableFuture> codeLens(CodeLensParams params) {
- // TODO Auto-generated method stub
- return null;
+ return Futures.of(Collections.emptyList());
}
@Override
public CompletableFuture resolveCodeLens(CodeLens unresolved) {
- // TODO Auto-generated method stub
- return null;
+ return Futures.of(null);
}
@Override
public CompletableFuture> formatting(DocumentFormattingParams params) {
- // TODO Auto-generated method stub
- return null;
+ return Futures.of(Collections.emptyList());
}
@Override
public CompletableFuture> rangeFormatting(DocumentRangeFormattingParams params) {
- // TODO Auto-generated method stub
- return null;
+ return Futures.of(Collections.emptyList());
}
@Override
public CompletableFuture> onTypeFormatting(DocumentOnTypeFormattingParams params) {
- // TODO Auto-generated method stub
- return null;
+ return Futures.of(Collections.emptyList());
}
@Override
public CompletableFuture rename(RenameParams params) {
- // TODO Auto-generated method stub
- return null;
+ return Futures.of(null);
}
@Override
public void didSave(DidSaveTextDocumentParams params) {
- // TODO Auto-generated method stub
-
}
public void publishDiagnostics(TextDocument doc, List diagnostics) {
@@ -274,8 +260,7 @@ public class SimpleTextDocumentService implements TextDocumentService {
@Override
public CompletableFuture> documentHighlight(TextDocumentPositionParams position) {
- // TODO Auto-generated method stub
- return null;
+ return Futures.of(Collections.emptyList());
}
}
diff --git a/vscode-extensions/commons/commons-maven/src/main/java/org/springframework/ide/vscode/commons/maven/java/MavenProjectClasspath.java b/vscode-extensions/commons/commons-maven/src/main/java/org/springframework/ide/vscode/commons/maven/java/MavenProjectClasspath.java
index 074f59a5a..6d18e39d8 100644
--- a/vscode-extensions/commons/commons-maven/src/main/java/org/springframework/ide/vscode/commons/maven/java/MavenProjectClasspath.java
+++ b/vscode-extensions/commons/commons-maven/src/main/java/org/springframework/ide/vscode/commons/maven/java/MavenProjectClasspath.java
@@ -13,9 +13,11 @@ package org.springframework.ide.vscode.commons.maven.java;
import java.io.File;
import java.nio.file.Path;
import java.nio.file.Paths;
+import java.util.Arrays;
import java.util.stream.Stream;
import org.apache.maven.project.MavenProject;
+import org.codehaus.plexus.util.DirectoryScanner;
import org.springframework.ide.vscode.commons.jandex.JandexIndex;
import org.springframework.ide.vscode.commons.java.IClasspath;
import org.springframework.ide.vscode.commons.java.IType;
@@ -70,5 +72,22 @@ public class MavenProjectClasspath implements IClasspath {
private File findIndexFile(File jarFile) {
return new File(maven.getIndexFolder().toString(), jarFile.getName() + "-" + jarFile.lastModified() + ".jdx");
}
-
+
+ @Override
+ public Stream getClasspathResources() {
+ return project.getBuild().getResources().stream().flatMap(resource -> {
+ DirectoryScanner scanner = new DirectoryScanner();
+ scanner.setBasedir(resource.getDirectory());
+ if (resource.getIncludes() != null && !resource.getIncludes().isEmpty()) {
+ scanner.setIncludes(resource.getIncludes().toArray(new String[resource.getIncludes().size()]));
+ }
+ if (resource.getExcludes() != null && !resource.getExcludes().isEmpty()) {
+ scanner.setExcludes(resource.getExcludes().toArray(new String[resource.getExcludes().size()]));
+ }
+ scanner.setCaseSensitive(false);
+ scanner.scan();
+ return Arrays.stream(scanner.getIncludedFiles());
+ });
+ }
+
}
diff --git a/vscode-extensions/commons/commons-maven/src/main/java/org/springframework/ide/vscode/commons/maven/java/classpathfile/FileClasspath.java b/vscode-extensions/commons/commons-maven/src/main/java/org/springframework/ide/vscode/commons/maven/java/classpathfile/FileClasspath.java
index 732d4c45a..c71005ded 100644
--- a/vscode-extensions/commons/commons-maven/src/main/java/org/springframework/ide/vscode/commons/maven/java/classpathfile/FileClasspath.java
+++ b/vscode-extensions/commons/commons-maven/src/main/java/org/springframework/ide/vscode/commons/maven/java/classpathfile/FileClasspath.java
@@ -37,4 +37,9 @@ public class FileClasspath implements IClasspath {
classpathFilePath.getParent().resolve("target/test-classes")));
}
+ @Override
+ public Stream getClasspathResources() {
+ return Stream.empty();
+ }
+
}
diff --git a/vscode-extensions/commons/java-properties/resources/JavaProperties.g4 b/vscode-extensions/commons/java-properties/resources/JavaProperties.g4
index 3ebd00c38..8407fb934 100644
--- a/vscode-extensions/commons/java-properties/resources/JavaProperties.g4
+++ b/vscode-extensions/commons/java-properties/resources/JavaProperties.g4
@@ -52,7 +52,7 @@ keyChar
;
separatorAndValue
- : (Space | Colon | Equals) valueChar+
+ : (Space | Colon | Equals) valueChar*
;
valueChar
diff --git a/vscode-extensions/commons/java-properties/src/main/java/org/springframework/ide/vscode/java/properties/antlr/parser/AntlrParser.java b/vscode-extensions/commons/java-properties/src/main/java/org/springframework/ide/vscode/java/properties/antlr/parser/AntlrParser.java
index 579eb0772..1fecb4e1a 100644
--- a/vscode-extensions/commons/java-properties/src/main/java/org/springframework/ide/vscode/java/properties/antlr/parser/AntlrParser.java
+++ b/vscode-extensions/commons/java-properties/src/main/java/org/springframework/ide/vscode/java/properties/antlr/parser/AntlrParser.java
@@ -12,10 +12,12 @@ package org.springframework.ide.vscode.java.properties.antlr.parser;
import java.util.ArrayList;
import java.util.BitSet;
+import java.util.List;
import org.antlr.v4.runtime.ANTLRErrorListener;
import org.antlr.v4.runtime.ANTLRInputStream;
import org.antlr.v4.runtime.CommonTokenStream;
+import org.antlr.v4.runtime.ConsoleErrorListener;
import org.antlr.v4.runtime.ParserRuleContext;
import org.antlr.v4.runtime.RecognitionException;
import org.antlr.v4.runtime.Recognizer;
@@ -23,6 +25,7 @@ import org.antlr.v4.runtime.Token;
import org.antlr.v4.runtime.atn.ATNConfigSet;
import org.antlr.v4.runtime.dfa.DFA;
import org.springframework.ide.vscode.java.properties.antlr.parser.JavaPropertiesParser.CommentLineContext;
+import org.springframework.ide.vscode.java.properties.antlr.parser.JavaPropertiesParser.EmptyLineContext;
import org.springframework.ide.vscode.java.properties.antlr.parser.JavaPropertiesParser.KeyContext;
import org.springframework.ide.vscode.java.properties.antlr.parser.JavaPropertiesParser.PropertyLineContext;
import org.springframework.ide.vscode.java.properties.antlr.parser.JavaPropertiesParser.SeparatorAndValueContext;
@@ -53,6 +56,9 @@ public class AntlrParser implements Parser {
CommonTokenStream tokens = new CommonTokenStream(lexer);
JavaPropertiesParser parser = new JavaPropertiesParser(tokens);
+ // To avoid printing parse errors in the console
+ parser.removeErrorListener(ConsoleErrorListener.INSTANCE);
+
// Add listener to collect various parser errors
parser.addErrorListener(new ANTLRErrorListener() {
@@ -90,7 +96,9 @@ public class AntlrParser implements Parser {
@Override
public void exitPropertyLine(PropertyLineContext ctx) {
- astNodes.add(new KeyValuePair(ctx, key, value));
+ KeyValuePair pair = new KeyValuePair(ctx, key, value);
+ key.parent = value.parent = pair;
+ astNodes.add(pair);
key = null;
value = null;
}
@@ -110,8 +118,13 @@ public class AntlrParser implements Parser {
value = new Value(ctx);
}
+ @Override
+ public void exitEmptyLine(EmptyLineContext ctx) {
+ astNodes.add(new EmptyLine(ctx));
+ }
+
});
-
+
parser.parse();
// Collect and return parse results
@@ -156,6 +169,9 @@ public class AntlrParser implements Parser {
private static abstract class Node implements PropertiesAst.Node {
+ Node parent;
+ List children;
+
abstract protected ParserRuleContext getContext();
@Override
@@ -167,14 +183,40 @@ public class AntlrParser implements Parser {
public int getLength() {
return getContext().getStop().getStartIndex() - getOffset() + 1;
}
+
+ @Override
+ public Node getParent() {
+ return parent;
+ }
+
+ @Override
+ public List getChildren() {
+ return children;
+ }
}
- private static class Comment implements PropertiesAst.Comment {
+ private static class EmptyLine extends Node implements PropertiesAst.EmptyLine {
+
+ private EmptyLineContext context;
+
+ public EmptyLine(EmptyLineContext context) {
+ super();
+ this.context = context;
+ }
+
+ @Override
+ protected EmptyLineContext getContext() {
+ return context;
+ }
+ }
+
+ private static class Comment extends Node implements PropertiesAst.Comment {
private CommentLineContext context;
public Comment(CommentLineContext context) {
+ super();
this.context = context;
}
@@ -190,6 +232,11 @@ public class AntlrParser implements Parser {
public int getLength() {
return context.getStop().getStartIndex() - getOffset() + 1;
}
+
+ @Override
+ protected CommentLineContext getContext() {
+ return context;
+ }
}
@@ -200,9 +247,11 @@ public class AntlrParser implements Parser {
private Value value;
public KeyValuePair(PropertyLineContext context, Key key, Value value) {
+ super();
this.context = context;
this.key = key;
this.value = value;
+ this.children = ImmutableList.of(key, value);
}
protected PropertyLineContext getContext() {
@@ -218,6 +267,18 @@ public class AntlrParser implements Parser {
public Value getValue() {
return value;
}
+
+ @Override
+ public int getLength() {
+ // Exclude the line break at the end
+ int length = super.getLength();
+ String text = getContext().getText();
+ if (text.charAt(getContext().getStop().getStartIndex() - getOffset()) == '\n') {
+ length--;
+ }
+ return length;
+ }
+
}
private static class Key extends Node implements PropertiesAst.Key {
@@ -241,6 +302,11 @@ public class AntlrParser implements Parser {
return context.getText().replace("\\:", ":").replace("\\=", "=");
}
}
+
+ @Override
+ public KeyValuePair getParent() {
+ return (KeyValuePair) super.getParent();
+ }
}
@@ -257,9 +323,9 @@ public class AntlrParser implements Parser {
private void init() {
// Remove the separator, if it exists
- value = context.getText().replaceAll("^\\s*[:=]?\\s*", "");
+ value = context.getText().replaceAll("^\\s*[:=]?", "");
// Remove all escaped line breaks with trailing spaces
- decoded = value.replaceAll("\\\\(\r?\n|\r)[ \t\f]*", "");
+ decoded = value.replaceAll("^\\s*", "").replaceAll("\\\\(\r?\n|\r)[ \t\f]*", "");
try {
decoded = PropertiesFileEscapes.unescape(decoded);
} catch (Exception e) {
@@ -283,6 +349,10 @@ public class AntlrParser implements Parser {
return context.getStart().getStartIndex() + (context.getText().length() - value.length());
}
+ @Override
+ public KeyValuePair getParent() {
+ return (KeyValuePair) super.getParent();
+ }
}
}
diff --git a/vscode-extensions/commons/java-properties/src/main/java/org/springframework/ide/vscode/java/properties/antlr/parser/JavaPropertiesParser.java b/vscode-extensions/commons/java-properties/src/main/java/org/springframework/ide/vscode/java/properties/antlr/parser/JavaPropertiesParser.java
index 486720d91..29d083bea 100644
--- a/vscode-extensions/commons/java-properties/src/main/java/org/springframework/ide/vscode/java/properties/antlr/parser/JavaPropertiesParser.java
+++ b/vscode-extensions/commons/java-properties/src/main/java/org/springframework/ide/vscode/java/properties/antlr/parser/JavaPropertiesParser.java
@@ -623,20 +623,20 @@ public class JavaPropertiesParser extends Parser {
} else {
consume();
}
- setState(80);
+ setState(82);
_errHandler.sync(this);
_la = _input.LA(1);
- do {
+ while ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << Backslash) | (1L << Colon) | (1L << Equals) | (1L << Exclamation) | (1L << Number) | (1L << Space) | (1L << IdentifierChar))) != 0)) {
{
{
setState(79);
valueChar();
}
}
- setState(82);
+ setState(84);
_errHandler.sync(this);
_la = _input.LA(1);
- } while ( (((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << Backslash) | (1L << Colon) | (1L << Equals) | (1L << Exclamation) | (1L << Number) | (1L << Space) | (1L << IdentifierChar))) != 0) );
+ }
}
}
catch (RecognitionException re) {
@@ -677,56 +677,56 @@ public class JavaPropertiesParser extends Parser {
ValueCharContext _localctx = new ValueCharContext(_ctx, getState());
enterRule(_localctx, 18, RULE_valueChar);
try {
- setState(92);
+ setState(93);
switch (_input.LA(1)) {
case IdentifierChar:
enterOuterAlt(_localctx, 1);
{
- setState(84);
+ setState(85);
match(IdentifierChar);
}
break;
case Exclamation:
enterOuterAlt(_localctx, 2);
{
- setState(85);
+ setState(86);
match(Exclamation);
}
break;
case Number:
enterOuterAlt(_localctx, 3);
{
- setState(86);
+ setState(87);
match(Number);
}
break;
case Space:
enterOuterAlt(_localctx, 4);
{
- setState(87);
+ setState(88);
match(Space);
}
break;
case Backslash:
enterOuterAlt(_localctx, 5);
{
- setState(88);
- match(Backslash);
setState(89);
+ match(Backslash);
+ setState(90);
match(LineBreak);
}
break;
case Equals:
enterOuterAlt(_localctx, 6);
{
- setState(90);
+ setState(91);
match(Equals);
}
break;
case Colon:
enterOuterAlt(_localctx, 7);
{
- setState(91);
+ setState(92);
match(Colon);
}
break;
@@ -746,31 +746,31 @@ public class JavaPropertiesParser extends Parser {
}
public static final String _serializedATN =
- "\3\u0430\ud6d1\u8206\uad2d\u4417\uaef1\u8d80\uaadd\3\na\4\2\t\2\4\3\t"+
+ "\3\u0430\ud6d1\u8206\uad2d\u4417\uaef1\u8d80\uaadd\3\nb\4\2\t\2\4\3\t"+
"\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7\4\b\t\b\4\t\t\t\4\n\t\n\4\13\t\13\3"+
"\2\7\2\30\n\2\f\2\16\2\33\13\2\3\2\3\2\3\3\3\3\3\3\5\3\"\n\3\3\4\7\4%"+
"\n\4\f\4\16\4(\13\4\3\4\3\4\3\5\7\5-\n\5\f\5\16\5\60\13\5\3\5\3\5\7\5"+
"\64\n\5\f\5\16\5\67\13\5\3\5\3\5\3\6\7\6<\n\6\f\6\16\6?\13\6\3\6\3\6\3"+
- "\7\3\7\3\7\3\7\3\b\6\bH\n\b\r\b\16\bI\3\t\3\t\3\t\5\tO\n\t\3\n\3\n\6\n"+
- "S\n\n\r\n\16\nT\3\13\3\13\3\13\3\13\3\13\3\13\3\13\3\13\5\13_\n\13\3\13"+
- "\2\2\f\2\4\6\b\n\f\16\20\22\24\2\7\3\2\6\7\3\2\b\b\3\3\b\b\3\2\4\5\4\2"+
- "\4\5\t\tf\2\31\3\2\2\2\4!\3\2\2\2\6&\3\2\2\2\b.\3\2\2\2\n=\3\2\2\2\fB"+
- "\3\2\2\2\16G\3\2\2\2\20N\3\2\2\2\22P\3\2\2\2\24^\3\2\2\2\26\30\5\4\3\2"+
- "\27\26\3\2\2\2\30\33\3\2\2\2\31\27\3\2\2\2\31\32\3\2\2\2\32\34\3\2\2\2"+
- "\33\31\3\2\2\2\34\35\7\2\2\3\35\3\3\2\2\2\36\"\5\6\4\2\37\"\5\b\5\2 \""+
- "\5\n\6\2!\36\3\2\2\2!\37\3\2\2\2! \3\2\2\2\"\5\3\2\2\2#%\7\t\2\2$#\3\2"+
- "\2\2%(\3\2\2\2&$\3\2\2\2&\'\3\2\2\2\')\3\2\2\2(&\3\2\2\2)*\5\f\7\2*\7"+
- "\3\2\2\2+-\7\t\2\2,+\3\2\2\2-\60\3\2\2\2.,\3\2\2\2./\3\2\2\2/\61\3\2\2"+
- "\2\60.\3\2\2\2\61\65\t\2\2\2\62\64\n\3\2\2\63\62\3\2\2\2\64\67\3\2\2\2"+
- "\65\63\3\2\2\2\65\66\3\2\2\2\668\3\2\2\2\67\65\3\2\2\289\t\4\2\29\t\3"+
- "\2\2\2:<\7\t\2\2;:\3\2\2\2\3\2\2\2=;\3\2\2\2=>\3\2\2\2>@\3\2\2\2?=\3"+
- "\2\2\2@A\7\b\2\2A\13\3\2\2\2BC\5\16\b\2CD\5\22\n\2DE\t\4\2\2E\r\3\2\2"+
- "\2FH\5\20\t\2GF\3\2\2\2HI\3\2\2\2IG\3\2\2\2IJ\3\2\2\2J\17\3\2\2\2KO\7"+
- "\n\2\2LM\7\3\2\2MO\t\5\2\2NK\3\2\2\2NL\3\2\2\2O\21\3\2\2\2PR\t\6\2\2Q"+
- "S\5\24\13\2RQ\3\2\2\2ST\3\2\2\2TR\3\2\2\2TU\3\2\2\2U\23\3\2\2\2V_\7\n"+
- "\2\2W_\7\6\2\2X_\7\7\2\2Y_\7\t\2\2Z[\7\3\2\2[_\7\b\2\2\\_\7\5\2\2]_\7"+
- "\4\2\2^V\3\2\2\2^W\3\2\2\2^X\3\2\2\2^Y\3\2\2\2^Z\3\2\2\2^\\\3\2\2\2^]"+
- "\3\2\2\2_\25\3\2\2\2\f\31!&.\65=INT^";
+ "\7\3\7\3\7\3\7\3\b\6\bH\n\b\r\b\16\bI\3\t\3\t\3\t\5\tO\n\t\3\n\3\n\7\n"+
+ "S\n\n\f\n\16\nV\13\n\3\13\3\13\3\13\3\13\3\13\3\13\3\13\3\13\5\13`\n\13"+
+ "\3\13\2\2\f\2\4\6\b\n\f\16\20\22\24\2\7\3\2\6\7\3\2\b\b\3\3\b\b\3\2\4"+
+ "\5\4\2\4\5\t\tg\2\31\3\2\2\2\4!\3\2\2\2\6&\3\2\2\2\b.\3\2\2\2\n=\3\2\2"+
+ "\2\fB\3\2\2\2\16G\3\2\2\2\20N\3\2\2\2\22P\3\2\2\2\24_\3\2\2\2\26\30\5"+
+ "\4\3\2\27\26\3\2\2\2\30\33\3\2\2\2\31\27\3\2\2\2\31\32\3\2\2\2\32\34\3"+
+ "\2\2\2\33\31\3\2\2\2\34\35\7\2\2\3\35\3\3\2\2\2\36\"\5\6\4\2\37\"\5\b"+
+ "\5\2 \"\5\n\6\2!\36\3\2\2\2!\37\3\2\2\2! \3\2\2\2\"\5\3\2\2\2#%\7\t\2"+
+ "\2$#\3\2\2\2%(\3\2\2\2&$\3\2\2\2&\'\3\2\2\2\')\3\2\2\2(&\3\2\2\2)*\5\f"+
+ "\7\2*\7\3\2\2\2+-\7\t\2\2,+\3\2\2\2-\60\3\2\2\2.,\3\2\2\2./\3\2\2\2/\61"+
+ "\3\2\2\2\60.\3\2\2\2\61\65\t\2\2\2\62\64\n\3\2\2\63\62\3\2\2\2\64\67\3"+
+ "\2\2\2\65\63\3\2\2\2\65\66\3\2\2\2\668\3\2\2\2\67\65\3\2\2\289\t\4\2\2"+
+ "9\t\3\2\2\2:<\7\t\2\2;:\3\2\2\2\3\2\2\2=;\3\2\2\2=>\3\2\2\2>@\3\2\2"+
+ "\2?=\3\2\2\2@A\7\b\2\2A\13\3\2\2\2BC\5\16\b\2CD\5\22\n\2DE\t\4\2\2E\r"+
+ "\3\2\2\2FH\5\20\t\2GF\3\2\2\2HI\3\2\2\2IG\3\2\2\2IJ\3\2\2\2J\17\3\2\2"+
+ "\2KO\7\n\2\2LM\7\3\2\2MO\t\5\2\2NK\3\2\2\2NL\3\2\2\2O\21\3\2\2\2PT\t\6"+
+ "\2\2QS\5\24\13\2RQ\3\2\2\2SV\3\2\2\2TR\3\2\2\2TU\3\2\2\2U\23\3\2\2\2V"+
+ "T\3\2\2\2W`\7\n\2\2X`\7\6\2\2Y`\7\7\2\2Z`\7\t\2\2[\\\7\3\2\2\\`\7\b\2"+
+ "\2]`\7\5\2\2^`\7\4\2\2_W\3\2\2\2_X\3\2\2\2_Y\3\2\2\2_Z\3\2\2\2_[\3\2\2"+
+ "\2_]\3\2\2\2_^\3\2\2\2`\25\3\2\2\2\f\31!&.\65=INT_";
public static final ATN _ATN =
new ATNDeserializer().deserialize(_serializedATN.toCharArray());
static {
diff --git a/vscode-extensions/commons/java-properties/src/main/java/org/springframework/ide/vscode/java/properties/parser/PropertiesAst.java b/vscode-extensions/commons/java-properties/src/main/java/org/springframework/ide/vscode/java/properties/parser/PropertiesAst.java
index 0f8f7830e..3fb65b328 100644
--- a/vscode-extensions/commons/java-properties/src/main/java/org/springframework/ide/vscode/java/properties/parser/PropertiesAst.java
+++ b/vscode-extensions/commons/java-properties/src/main/java/org/springframework/ide/vscode/java/properties/parser/PropertiesAst.java
@@ -31,7 +31,7 @@ public final class PropertiesAst {
* Retrieves all AST nodes
* @return List of AST nodes sorted by line number
*/
- public List extends Node> getAllNodes() {
+ public List getAllNodes() {
return nodes;
}
@@ -48,6 +48,52 @@ public final class PropertiesAst {
return (List) l;
}
+ /**
+ * Find node in AST corresponding to offset position
+ * @param offset Position in the text
+ * @return AST node corresponding to the offset position
+ */
+ public Node findNode(int offset) {
+ return findNode(nodes, offset, 0, nodes.size() - 1);
+ }
+
+ private Node findNode(List extends Node> nodes, int offset, int start, int end) {
+ if (nodes == null) {
+ return null;
+ }
+ if (start == end) {
+ Node node = nodes.get(start);
+ if (node.getOffset() <= offset && offset <= node.getOffset() + node.getLength()) {
+ Node found = findChildNode(node, offset);
+ return found == null ? node : found;
+ } else {
+ return null;
+ }
+ } else if (start < end ) {
+ int pivotIndex = (start + end) / 2;
+ Node node = nodes.get(pivotIndex);
+ if (node.getOffset() > offset) {
+ return findNode(nodes, offset, start, pivotIndex - 1);
+ } else if (offset > node.getOffset() + node.getLength()) {
+ return findNode(nodes, offset, pivotIndex + 1, end);
+ } else {
+ Node found = findChildNode(node, offset);
+ return found == null ? node : found;
+ }
+ } else {
+ return null;
+ }
+ }
+
+ private Node findChildNode(Node node, int offset) {
+ if (node.getChildren() == null) {
+ return null;
+ } else {
+ return findNode(node.getChildren(), offset, 0, node.getChildren().size() - 1);
+ }
+ }
+
+
/**
* Java Properties AST node
*/
@@ -65,6 +111,18 @@ public final class PropertiesAst {
*/
int getLength();
+ /**
+ * Node's parent
+ * @return parent node
+ */
+ Node getParent();
+
+ /**
+ * Node's children
+ * @return children nodes
+ */
+ List extends Node> getChildren();
+
}
/**
@@ -72,6 +130,13 @@ public final class PropertiesAst {
*/
public interface Comment extends Node {
+ }
+
+ /**
+ * AST node for empty line
+ */
+ public interface EmptyLine extends Node {
+
}
/**
@@ -103,6 +168,8 @@ public final class PropertiesAst {
* @return Decoded property name
*/
String decode();
+
+ KeyValuePair getParent();
}
@@ -117,6 +184,7 @@ public final class PropertiesAst {
*/
String decode();
+ KeyValuePair getParent();
}
}
diff --git a/vscode-extensions/commons/java-properties/src/test/java/org/springframework/ide/vscode/java/properties/parser/test/PropertiesAntlrParserTest.java b/vscode-extensions/commons/java-properties/src/test/java/org/springframework/ide/vscode/java/properties/parser/test/PropertiesAntlrParserTest.java
index 18ceb84e5..ca1247a8a 100644
--- a/vscode-extensions/commons/java-properties/src/test/java/org/springframework/ide/vscode/java/properties/parser/test/PropertiesAntlrParserTest.java
+++ b/vscode-extensions/commons/java-properties/src/test/java/org/springframework/ide/vscode/java/properties/parser/test/PropertiesAntlrParserTest.java
@@ -83,34 +83,6 @@ public class PropertiesAntlrParserTest {
testCommentLine(" # This is comment = ", "# This is comment = ");
}
- @Test
- public void testLines1() throws Exception {
- ParseResults results = parser.parse("# Comment\n\n \t \t \n\t\t\n");
- assertTrue(results.syntaxErrors.isEmpty());
- assertTrue(results.problems.isEmpty());
- assertEquals(1, results.ast.getAllNodes().size());
- assertEquals(1, results.ast.getNodes(Comment.class).size());
- }
-
- @Test
- public void testLines2() throws Exception {
- ParseResults results = parser.parse("\n\n \t \t \n# Comment\n\t\t\n");
- assertTrue(results.syntaxErrors.isEmpty());
- assertTrue(results.problems.isEmpty());
- assertEquals(1, results.ast.getAllNodes().size());
- assertEquals(1, results.ast.getNodes(Comment.class).size());
- }
-
- @Test
- public void testLines3() throws Exception {
- ParseResults results = parser.parse("# Comment\n\nkey = value 1 \n \t \t \n\t\t\n");
- assertTrue(results.syntaxErrors.isEmpty());
- assertTrue(results.problems.isEmpty());
- assertEquals(2, results.ast.getAllNodes().size());
- assertEquals(1, results.ast.getNodes(Comment.class).size());
- assertEquals(1, results.ast.getNodes(KeyValuePair.class).size());
- }
-
@Test
public void testPropertyWithEqualsSeparator() throws Exception {
testPropertyLine("key=value", "key", "key", "value", "value");
@@ -118,7 +90,7 @@ public class PropertiesAntlrParserTest {
@Test
public void testPropertyWithEqualsSeparatorAndSpaces() throws Exception {
- testPropertyLine("key \t = \t \tvalue", "key", "key", "value", "value");
+ testPropertyLine("key \t = \t \tvalue", "key", "key", "value", " \t \tvalue");
}
@Test
@@ -128,7 +100,7 @@ public class PropertiesAntlrParserTest {
@Test
public void testPropertyWithColonSeparatorAndSpaces() throws Exception {
- testPropertyLine("key \t : \t \tvalue", "key", "key", "value", "value");
+ testPropertyLine("key \t : \t \tvalue", "key", "key", "value", " \t \tvalue");
}
@Test
@@ -168,17 +140,17 @@ public class PropertiesAntlrParserTest {
@Test
public void testEqualsValueSeparatedWithEqualsAndSpace() throws Exception {
- testPropertyLine("key7 = =", "key7", "key7", "=", "=");
+ testPropertyLine("key7 = =", "key7", "key7", "=", " =");
}
@Test
public void testValueWithTrailingSpaces() throws Exception {
- testPropertyLine("key = value 1 ", "key", "key", "value 1 ", "value 1 ");
+ testPropertyLine("key = value 1 ", "key", "key", "value 1 ", " value 1 ");
}
@Test
public void testUnodeCharKeyAndValue() throws Exception {
- testPropertyLine("k\u2b22ey\u2b28 = val\u2b24ue 1\u2b24 ", "k\u2b22ey\u2b28", "k\u2b22ey\u2b28", "val\u2b24ue 1\u2b24 ", "val\u2b24ue 1\u2b24 ");
+ testPropertyLine("k\u2b22ey\u2b28 = val\u2b24ue 1\u2b24 ", "k\u2b22ey\u2b28", "k\u2b22ey\u2b28", "val\u2b24ue 1\u2b24 ", " val\u2b24ue 1\u2b24 ");
}
@Test
diff --git a/vscode-extensions/commons/java-properties/src/test/java/org/springframework/ide/vscode/java/properties/parser/test/PropertiesAstTest.java b/vscode-extensions/commons/java-properties/src/test/java/org/springframework/ide/vscode/java/properties/parser/test/PropertiesAstTest.java
new file mode 100644
index 000000000..aeb07ea22
--- /dev/null
+++ b/vscode-extensions/commons/java-properties/src/test/java/org/springframework/ide/vscode/java/properties/parser/test/PropertiesAstTest.java
@@ -0,0 +1,159 @@
+package org.springframework.ide.vscode.java.properties.parser.test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+import org.springframework.ide.vscode.java.properties.antlr.parser.AntlrParser;
+import org.springframework.ide.vscode.java.properties.parser.ParseResults;
+import org.springframework.ide.vscode.java.properties.parser.Parser;
+import org.springframework.ide.vscode.java.properties.parser.PropertiesAst.Comment;
+import org.springframework.ide.vscode.java.properties.parser.PropertiesAst.EmptyLine;
+import org.springframework.ide.vscode.java.properties.parser.PropertiesAst.Key;
+import org.springframework.ide.vscode.java.properties.parser.PropertiesAst.KeyValuePair;
+import org.springframework.ide.vscode.java.properties.parser.PropertiesAst.Node;
+import org.springframework.ide.vscode.java.properties.parser.PropertiesAst.Value;
+
+public class PropertiesAstTest {
+
+ Parser parser = new AntlrParser();
+
+ @Test
+ public void testLines1() throws Exception {
+ ParseResults results = parser.parse("# Comment\n\n \t \t \n\t\t\n");
+ assertTrue(results.syntaxErrors.isEmpty());
+ assertTrue(results.problems.isEmpty());
+ assertEquals(4, results.ast.getAllNodes().size());
+ assertEquals(1, results.ast.getNodes(Comment.class).size());
+ assertEquals(3, results.ast.getNodes(EmptyLine.class).size());
+ }
+
+ @Test
+ public void testLines2() throws Exception {
+ ParseResults results = parser.parse("\n\n \t \t \n# Comment\n\t\t\n");
+ assertTrue(results.syntaxErrors.isEmpty());
+ assertTrue(results.problems.isEmpty());
+ assertEquals(5, results.ast.getAllNodes().size());
+ assertEquals(1, results.ast.getNodes(Comment.class).size());
+ assertEquals(4, results.ast.getNodes(EmptyLine.class).size());
+ }
+
+ @Test
+ public void testLines3() throws Exception {
+ ParseResults results = parser.parse("# Comment\n\nkey = value 1 \n \t \t \n\t\t\n");
+ assertTrue(results.syntaxErrors.isEmpty());
+ assertTrue(results.problems.isEmpty());
+ assertEquals(5, results.ast.getAllNodes().size());
+ assertEquals(1, results.ast.getNodes(Comment.class).size());
+ assertEquals(1, results.ast.getNodes(KeyValuePair.class).size());
+ assertEquals(3, results.ast.getNodes(EmptyLine.class).size());
+ }
+
+ @Test
+ public void testLines4() throws Exception {
+ ParseResults results = parser.parse("# Comment-1\n\nkey = value 1 \n# Comment-2");
+ assertEquals(4, results.ast.getAllNodes().size());
+ assertEquals(2, results.ast.getNodes(Comment.class).size());
+ assertEquals(1, results.ast.getNodes(KeyValuePair.class).size());
+ assertEquals(1, results.ast.getNodes(EmptyLine.class).size());
+ }
+
+ @Test
+ public void testLines5() throws Exception {
+ ParseResults results = parser.parse("#comment\nliquibase.enabled=\n#comment");
+ assertEquals(3, results.ast.getAllNodes().size());
+ assertEquals(2, results.ast.getNodes(Comment.class).size());
+ assertEquals(1, results.ast.getNodes(KeyValuePair.class).size());
+ }
+
+ @Test
+ public void positionComment() throws Exception {
+ ParseResults results = parser.parse("# Comment\n" + "key = value\n");
+
+ Node node = results.ast.findNode(7);
+ assertTrue(node instanceof Comment);
+ assertTrue(node.getOffset() <= 7 && 7 <= node.getOffset() + node.getLength());
+
+ node = results.ast.findNode(9);
+ assertTrue(node instanceof Comment);
+ assertTrue(node.getOffset() <= 9 && 9 <= node.getOffset() + node.getLength());
+
+ node = results.ast.findNode(0);
+ assertTrue(node instanceof Comment);
+ assertTrue(node.getOffset() <= 0 && 0 <= node.getOffset() + node.getLength());
+ }
+
+ @Test
+ public void positionEmptyLine() throws Exception {
+ ParseResults results = parser.parse("# Comment\n" + "key = value\n" + "\t\n");
+ Node node = results.ast.findNode(23);
+ assertTrue(node instanceof EmptyLine);
+ assertTrue(node.getOffset() <= 23 && 23 <= node.getOffset() + node.getLength());
+
+ node = results.ast.findNode(24);
+ assertTrue(node instanceof EmptyLine);
+ assertTrue(node.getOffset() <= 24 && 24 <= node.getOffset() + node.getLength());
+ }
+
+ @Test
+ public void positionKey() throws Exception {
+ ParseResults results = parser.parse("# Comment\n" + "key = value\n" + "\t\n");
+ Node node = results.ast.findNode(10);
+ assertTrue(node instanceof Key);
+ assertTrue(node.getOffset() <= 10 && 10 <= node.getOffset() + node.getLength());
+
+ node = results.ast.findNode(12);
+ assertTrue(node instanceof Key);
+ assertTrue(node.getOffset() <= 12 && 12 <= node.getOffset() + node.getLength());
+
+ node = results.ast.findNode(13);
+ assertTrue(node instanceof Key);
+ assertTrue(node.getOffset() <= 13 && 13 <= node.getOffset() + node.getLength());
+
+ }
+
+ @Test
+ public void positionPair() throws Exception {
+ ParseResults results = parser.parse("# Comment\n" + "key = value\n" + "\t\n");
+ Node node = results.ast.findNode(15);
+ assertTrue(node instanceof KeyValuePair);
+ assertTrue(node.getOffset() <= 15 && 15 <= node.getOffset() + node.getLength());
+ }
+
+ @Test
+ public void positionValue() throws Exception {
+ ParseResults results = parser.parse("# Comment\n" + "key = value\n");
+ Node node = results.ast.findNode(17);
+ assertTrue(node instanceof Value);
+ assertTrue(node.getOffset() <= 17 && 17 <= node.getOffset() + node.getLength());
+
+ node = results.ast.findNode(22);
+ assertTrue(node instanceof Value);
+ assertTrue(node.getOffset() <= 22 && 22 <= node.getOffset() + node.getLength());
+
+ node = results.ast.findNode(16);
+ assertTrue(node instanceof Value);
+ assertTrue(node.getOffset() <= 16 && 16 <= node.getOffset() + node.getLength());
+ }
+
+ @Test
+ public void positionValueEofAtEnd() throws Exception {
+ ParseResults results = parser.parse("# Comment\n" + "key = value");
+ Node node = results.ast.findNode(22);
+ assertTrue(node instanceof Value);
+ assertTrue(node.getOffset() <= 22 && 22 <= node.getOffset() + node.getLength());
+
+ node = results.ast.findNode(16);
+ assertTrue(node instanceof Value);
+ assertTrue(node.getOffset() <= 16 && 16 <= node.getOffset() + node.getLength());
+ }
+
+ @Test
+ public void positionEmptyValue() throws Exception {
+ ParseResults results = parser.parse("# Comment\n" + "key =");
+ Node node = results.ast.findNode(16);
+ assertTrue(node instanceof Value);
+ assertTrue(node.getOffset() <= 16 && 16 <= node.getOffset() + node.getLength());
+ }
+
+}
diff --git a/vscode-extensions/commons/project-test-harness/.classpath b/vscode-extensions/commons/project-test-harness/.classpath
new file mode 100644
index 000000000..8620f6a2b
--- /dev/null
+++ b/vscode-extensions/commons/project-test-harness/.classpath
@@ -0,0 +1,31 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/vscode-extensions/commons/project-test-harness/.gitignore b/vscode-extensions/commons/project-test-harness/.gitignore
index 36dc59cb6..ca0618fbd 100644
--- a/vscode-extensions/commons/project-test-harness/.gitignore
+++ b/vscode-extensions/commons/project-test-harness/.gitignore
@@ -1,5 +1,5 @@
-/.classpath
/.project
+**/.classpath
**/classpath.txt
**/.project
**/.settings/*.*
diff --git a/vscode-extensions/commons/project-test-harness/pom.xml b/vscode-extensions/commons/project-test-harness/pom.xml
index 75b41d4fd..6706409e1 100644
--- a/vscode-extensions/commons/project-test-harness/pom.xml
+++ b/vscode-extensions/commons/project-test-harness/pom.xml
@@ -37,4 +37,11 @@
${junit-version}
+
+
+
+ test-projects
+
+
+
\ No newline at end of file
diff --git a/vscode-extensions/commons/project-test-harness/src/main/java/org/springframework/ide/vscode/project/harness/ProjectsHarness.java b/vscode-extensions/commons/project-test-harness/src/main/java/org/springframework/ide/vscode/project/harness/ProjectsHarness.java
index 02b9efb6b..81c7ba423 100644
--- a/vscode-extensions/commons/project-test-harness/src/main/java/org/springframework/ide/vscode/project/harness/ProjectsHarness.java
+++ b/vscode-extensions/commons/project-test-harness/src/main/java/org/springframework/ide/vscode/project/harness/ProjectsHarness.java
@@ -10,10 +10,21 @@
*******************************************************************************/
package org.springframework.ide.vscode.project.harness;
+import java.io.File;
+import java.io.IOException;
+import java.net.URI;
import java.net.URISyntaxException;
-import java.net.URL;
+import java.nio.file.CopyOption;
+import java.nio.file.FileSystem;
+import java.nio.file.FileSystems;
+import java.nio.file.FileVisitResult;
+import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
+import java.nio.file.SimpleFileVisitor;
+import java.nio.file.StandardCopyOption;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.util.Collections;
import org.springframework.ide.vscode.commons.java.IJavaProject;
import org.springframework.ide.vscode.commons.maven.MavenCore;
@@ -33,7 +44,7 @@ public class ProjectsHarness {
public static final ProjectsHarness INSTANCE = new ProjectsHarness();;
- public Cache cache = CacheBuilder.newBuilder().build();
+ public Cache cache = CacheBuilder.newBuilder().concurrencyLevel(1).build();
private enum ProjectType {
MAVEN,
@@ -59,10 +70,94 @@ public class ProjectsHarness {
});
}
- protected Path getProjectPath(String name) throws URISyntaxException {
- URL sourceLocation = ProjectsHarness.class.getProtectionDomain().getCodeSource().getLocation();
+ protected Path getProjectPath(String name) throws URISyntaxException, IOException {
+ URI sourceLocation = ProjectsHarness.class.getProtectionDomain().getCodeSource().getLocation().toURI();
// file:/Users/aboyko/git/sts4/vscode-extensions/commons/project-test-harness/target/project-test-harness-0.0.1-SNAPSHOT.jar
- return Paths.get(sourceLocation.toURI()).getParent().getParent().resolve("test-projects").resolve(name);
+ Path testProjectsPath = Paths.get(sourceLocation).getParent().getParent().resolve("test-projects").resolve(name);
+ if (Files.exists(testProjectsPath)) {
+ return testProjectsPath;
+ } else {
+ /*
+ * If "test-projects" folder is not found then extract test project
+ * from the jar's "test-projects" folder and copy it in the temp
+ * folder
+ */
+ return getProjectPathFromClasspath(name);
+ }
+ }
+
+ private Path getProjectPathFromClasspath(String name) throws URISyntaxException, IOException {
+ URI resource = ProjectsHarness.class.getResource("/" + name).toURI();
+ if (resource.getScheme().equalsIgnoreCase("jar")) {
+ return getProjectPathFromJar(resource);
+ } else {
+ return Paths.get(resource);
+ }
+ }
+
+ private Path getProjectPathFromJar(URI jar) throws IOException {
+ final String[] array = jar.toString().split("!");
+ URI firstHalf = URI.create(array[0]);
+ Path tempFolderPath = Paths.get(new File(System.getProperty(MavenCore.JAVA_IO_TMPDIR)).toURI());
+ FileSystem fs = FileSystems.newFileSystem(firstHalf, Collections.emptyMap());
+ try {
+ Path path = fs.getPath(array[1]);
+ Path projectCopyPath = tempFolderPath.resolve(path.getFileName().toString());
+ if (Files.exists(projectCopyPath)) {
+ recursiveDelete(projectCopyPath);
+ }
+ recursiveCopy(path, tempFolderPath, StandardCopyOption.REPLACE_EXISTING);
+ System.out.println("Copied test project to: " + projectCopyPath);
+ return projectCopyPath;
+ } finally {
+ fs.close();
+ }
+ }
+
+ private static void recursiveCopy(Path source, Path target, CopyOption... options) throws IOException {
+ Files.walkFileTree(source, new SimpleFileVisitor() {
+
+ Path destination = target;
+
+ @Override
+ public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
+ destination = destination.resolve(dir.getFileName().toString());
+ Files.copy(dir, destination, options);
+ return super.preVisitDirectory(dir, attrs);
+ }
+
+ @Override
+ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
+ Path newFile = destination.resolve(file.getFileName().toString());
+ Files.copy(file, newFile, options);
+ return super.visitFile(file, attrs);
+ }
+
+ @Override
+ public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
+ destination = destination.getParent();
+ return super.postVisitDirectory(dir, exc);
+ }
+
+ });
+ }
+
+ private static void recursiveDelete(Path path) throws IOException {
+ Files.walkFileTree(path, new SimpleFileVisitor() {
+
+ @Override
+ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
+ Files.delete(file);
+ return super.visitFile(file, attrs);
+ }
+
+ @Override
+ public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
+ Files.delete(dir);
+ return super.postVisitDirectory(dir, exc);
+ }
+
+ });
}
public MavenJavaProject mavenProject(String name) throws Exception {
diff --git a/vscode-extensions/commons/properties-editor-test-harness/.classpath b/vscode-extensions/commons/properties-editor-test-harness/.classpath
new file mode 100644
index 000000000..af1430be1
--- /dev/null
+++ b/vscode-extensions/commons/properties-editor-test-harness/.classpath
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/vscode-extensions/vscode-application-properties/lib/Main.ts b/vscode-extensions/vscode-application-properties/lib/Main.ts
index 68c369e38..9a6140921 100644
--- a/vscode-extensions/vscode-application-properties/lib/Main.ts
+++ b/vscode-extensions/vscode-application-properties/lib/Main.ts
@@ -49,7 +49,8 @@ export function activate(context: VSCode.ExtensionContext) {
// TODO: Remove cast ones https://github.com/Microsoft/vscode-languageserver-node/issues/9 is resolved
documentSelector: [
{language: 'ini', pattern: '**/application*.properties'},
- {language: 'java-properties', pattern: '**/application*.properties'}
+ {language: 'java-properties', pattern: '**/application*.properties'},
+ {language: 'properties', pattern: '**/application*.properties'}
],
synchronize: {
// Synchronize the setting section to the server:
diff --git a/vscode-extensions/vscode-application-properties/package.json b/vscode-extensions/vscode-application-properties/package.json
index 5306985ca..86779d2bc 100644
--- a/vscode-extensions/vscode-application-properties/package.json
+++ b/vscode-extensions/vscode-application-properties/package.json
@@ -22,7 +22,8 @@
],
"activationEvents": [
"onLanguage:ini",
- "onLanguage:java-properties"
+ "onLanguage:java-properties",
+ "onLanguage:properties"
],
"main": "./out/lib/Main",
"files": [
diff --git a/vscode-extensions/vscode-application-properties/src/main/java/org/springframework/ide/vscode/application/properties/ApplicationPropertiesLanguageServer.java b/vscode-extensions/vscode-application-properties/src/main/java/org/springframework/ide/vscode/application/properties/ApplicationPropertiesLanguageServer.java
index 7a57f8e5d..55814e5f1 100644
--- a/vscode-extensions/vscode-application-properties/src/main/java/org/springframework/ide/vscode/application/properties/ApplicationPropertiesLanguageServer.java
+++ b/vscode-extensions/vscode-application-properties/src/main/java/org/springframework/ide/vscode/application/properties/ApplicationPropertiesLanguageServer.java
@@ -10,12 +10,15 @@
*******************************************************************************/
package org.springframework.ide.vscode.application.properties;
+import org.eclipse.lsp4j.CompletionOptions;
import org.eclipse.lsp4j.ServerCapabilities;
import org.eclipse.lsp4j.TextDocumentSyncKind;
+import org.springframework.ide.vscode.application.properties.completions.SpringPropertiesCompletionEngine;
import org.springframework.ide.vscode.application.properties.metadata.SpringPropertyIndexProvider;
import org.springframework.ide.vscode.application.properties.metadata.types.TypeUtilProvider;
import org.springframework.ide.vscode.application.properties.reconcile.SpringPropertiesReconcileEngine;
-import org.springframework.ide.vscode.commons.languageserver.reconcile.IReconcileEngine;
+import org.springframework.ide.vscode.commons.languageserver.completion.VscodeCompletionEngineAdapter;
+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;
import org.springframework.ide.vscode.commons.languageserver.util.TextDocument;
@@ -30,18 +33,39 @@ public class ApplicationPropertiesLanguageServer extends SimpleLanguageServer {
private SpringPropertyIndexProvider indexProvider;
private TypeUtilProvider typeUtilProvider;
+ private VscodeCompletionEngineAdapter completionEngine;
+ private SpringPropertiesReconcileEngine reconcileEngine;
- public ApplicationPropertiesLanguageServer(SpringPropertyIndexProvider indexProvider, TypeUtilProvider typeUtilProvider) {
+ public ApplicationPropertiesLanguageServer(SpringPropertyIndexProvider indexProvider, TypeUtilProvider typeUtilProvider, JavaProjectFinder javaProjectFinder) {
this.indexProvider = indexProvider;
this.typeUtilProvider = typeUtilProvider;
SimpleTextDocumentService documents = getTextDocumentService();
- IReconcileEngine reconcileEngine = getReconcileEngine();
+ reconcileEngine = getReconcileEngine();
documents.onDidChangeContent(params -> {
TextDocument doc = params.getDocument();
validateWith(doc, reconcileEngine);
});
+
+ SpringPropertiesCompletionEngine propertiesCompletionEngine = new SpringPropertiesCompletionEngine(
+ indexProvider,
+ typeUtilProvider,
+ javaProjectFinder
+ );
+ completionEngine = new VscodeCompletionEngineAdapter(this, propertiesCompletionEngine);
+ completionEngine.setMaxCompletionsNumber(-1);
+ documents.onCompletion(completionEngine::getCompletions);
+ documents.onCompletionResolve(completionEngine::resolveCompletion);
+
+ }
+
+ public void setMaxCompletionsNumber(int number) {
+ completionEngine.setMaxCompletionsNumber(number);
+ }
+
+ public void setRecordSyntaxErrors(boolean record) {
+ reconcileEngine.setRecordSyntaxErrors(record);
}
@Override
@@ -50,10 +74,14 @@ public class ApplicationPropertiesLanguageServer extends SimpleLanguageServer {
c.setTextDocumentSync(TextDocumentSyncKind.Full);
+ CompletionOptions completionProvider = new CompletionOptions();
+ completionProvider.setResolveProvider(false);
+ c.setCompletionProvider(completionProvider);
+
return c;
}
- protected IReconcileEngine getReconcileEngine() {
+ protected SpringPropertiesReconcileEngine getReconcileEngine() {
return new SpringPropertiesReconcileEngine(indexProvider, typeUtilProvider);
}
diff --git a/vscode-extensions/vscode-application-properties/src/main/java/org/springframework/ide/vscode/application/properties/Main.java b/vscode-extensions/vscode-application-properties/src/main/java/org/springframework/ide/vscode/application/properties/Main.java
index 0ccbe37f1..b30f7fc22 100644
--- a/vscode-extensions/vscode-application-properties/src/main/java/org/springframework/ide/vscode/application/properties/Main.java
+++ b/vscode-extensions/vscode-application-properties/src/main/java/org/springframework/ide/vscode/application/properties/Main.java
@@ -11,7 +11,6 @@
package org.springframework.ide.vscode.application.properties;
import java.io.IOException;
-import java.util.logging.Logger;
import org.eclipse.lsp4j.services.LanguageServer;
import org.springframework.ide.vscode.application.properties.metadata.DefaultSpringPropertyIndexProvider;
@@ -36,7 +35,7 @@ public class Main {
JavaProjectFinder javaProjectFinder = JavaProjectFinder.DEFAULT;
SpringPropertyIndexProvider indexProvider = new DefaultSpringPropertyIndexProvider(javaProjectFinder);
TypeUtilProvider typeUtilProvider = (IDocument doc) -> new TypeUtil(javaProjectFinder.find(doc));
- LanguageServer server = new ApplicationPropertiesLanguageServer(indexProvider, typeUtilProvider);
+ LanguageServer server = new ApplicationPropertiesLanguageServer(indexProvider, typeUtilProvider, javaProjectFinder);
return server;
});
}
diff --git a/vscode-extensions/vscode-application-properties/src/main/java/org/springframework/ide/vscode/application/properties/completions/PropertiesCompletionProposalsCalculator.java b/vscode-extensions/vscode-application-properties/src/main/java/org/springframework/ide/vscode/application/properties/completions/PropertiesCompletionProposalsCalculator.java
new file mode 100644
index 000000000..c267e465e
--- /dev/null
+++ b/vscode-extensions/vscode-application-properties/src/main/java/org/springframework/ide/vscode/application/properties/completions/PropertiesCompletionProposalsCalculator.java
@@ -0,0 +1,582 @@
+package org.springframework.ide.vscode.application.properties.completions;
+
+import static org.springframework.ide.vscode.commons.util.StringUtil.camelCaseToHyphens;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.regex.Pattern;
+
+import org.springframework.ide.vscode.application.properties.metadata.PropertyInfo;
+import org.springframework.ide.vscode.application.properties.metadata.completions.PropertyCompletionFactory;
+import org.springframework.ide.vscode.application.properties.metadata.hints.HintProvider;
+import org.springframework.ide.vscode.application.properties.metadata.hints.HintProviders;
+import org.springframework.ide.vscode.application.properties.metadata.hints.StsValueHint;
+import org.springframework.ide.vscode.application.properties.metadata.hints.ValueHintHoverInfo;
+import org.springframework.ide.vscode.application.properties.metadata.types.Type;
+import org.springframework.ide.vscode.application.properties.metadata.types.TypeParser;
+import org.springframework.ide.vscode.application.properties.metadata.types.TypeUtil;
+import org.springframework.ide.vscode.application.properties.metadata.types.TypeUtil.BeanPropertyNameMode;
+import org.springframework.ide.vscode.application.properties.metadata.types.TypeUtil.EnumCaseMode;
+import org.springframework.ide.vscode.application.properties.metadata.types.TypedProperty;
+import org.springframework.ide.vscode.application.properties.metadata.util.FuzzyMap;
+import org.springframework.ide.vscode.application.properties.metadata.util.FuzzyMap.Match;
+import org.springframework.ide.vscode.application.properties.reconcile.PropertyNavigator;
+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.completion.LazyProposalApplier;
+import org.springframework.ide.vscode.commons.languageserver.util.BadLocationException;
+import org.springframework.ide.vscode.commons.languageserver.util.DocumentRegion;
+import org.springframework.ide.vscode.commons.languageserver.util.IDocument;
+import org.springframework.ide.vscode.commons.languageserver.util.PrefixFinder;
+import org.springframework.ide.vscode.commons.languageserver.util.TextDocument;
+import org.springframework.ide.vscode.commons.util.CollectionUtil;
+import org.springframework.ide.vscode.commons.util.FuzzyMatcher;
+import org.springframework.ide.vscode.commons.util.Log;
+import org.springframework.ide.vscode.java.properties.antlr.parser.AntlrParser;
+import org.springframework.ide.vscode.java.properties.parser.ParseResults;
+import org.springframework.ide.vscode.java.properties.parser.PropertiesAst.EmptyLine;
+import org.springframework.ide.vscode.java.properties.parser.PropertiesAst.Key;
+import org.springframework.ide.vscode.java.properties.parser.PropertiesAst.Node;
+import org.springframework.ide.vscode.java.properties.parser.PropertiesAst.Value;
+
+import com.google.common.collect.ImmutableList;
+
+class PropertiesCompletionProposalsCalculator {
+
+ private static final Pattern SPACES = Pattern.compile(
+ "(\\s|\\\\\\s)*"
+ );
+
+ private static boolean isValuePrefixChar(char c) {
+ return !Character.isWhitespace(c) && c!=',';
+ }
+
+ private static final PrefixFinder valuePrefixFinder = new PrefixFinder() {
+ protected boolean isPrefixChar(char c) {
+ return isValuePrefixChar(c);
+ }
+
+ };
+
+ private static final PrefixFinder fuzzySearchPrefix = new PrefixFinder() {
+ protected boolean isPrefixChar(char c) {
+ return !Character.isWhitespace(c);
+ }
+ };
+
+ private static final PrefixFinder navigationPrefixFinder = new PrefixFinder() {
+ public String getPrefix(IDocument doc, int offset) {
+ String prefix = super.getPrefix(doc, offset);
+ //Check if character before looks like 'navigation'.. otherwise don't
+ // return a navigationPrefix.
+ char charBefore = getCharBefore(doc, prefix, offset);
+ if (charBefore=='.' || charBefore==']') {
+ return prefix;
+ }
+ return null;
+ }
+ private char getCharBefore(IDocument doc, String prefix, int offset) {
+ try {
+ if (prefix!=null) {
+ int offsetBefore = offset-prefix.length()-1;
+ if (offsetBefore>=0) {
+ return doc.getChar(offsetBefore);
+ }
+ }
+ } catch (BadLocationException e) {
+ //ignore
+ }
+ return 0;
+ }
+ protected boolean isPrefixChar(char c) {
+ return !Character.isWhitespace(c) && c!=']' && c!=']' && c!='.';
+ }
+ };
+
+ private FuzzyMap index;
+ private TypeUtil typeUtil;
+ private PropertyCompletionFactory completionFactory;
+ private IDocument doc;
+ private int offset;
+ private boolean preferLowerCaseEnums;
+ private AntlrParser parser;
+
+ PropertiesCompletionProposalsCalculator(FuzzyMap index, TypeUtil typeUtil, PropertyCompletionFactory completionFactory, IDocument doc, int offset, boolean preferLowerCaseEnums) {
+ this.index = index;
+ this.typeUtil = typeUtil;
+ this.completionFactory = completionFactory;
+ this.doc = doc;
+ this.offset = offset;
+ this.preferLowerCaseEnums = preferLowerCaseEnums;
+ this.parser = new AntlrParser();
+ }
+
+ /**
+ * Create completions proposals in the context of a properties text editor.
+ */
+ public Collection calculate() throws BadLocationException {
+ ParseResults parseResults = parser.parse(doc.get());
+ Node node = parseResults.ast.findNode(offset);
+ if (node instanceof Value) {
+ return getValueCompletions((Value)node);
+ } else if (node instanceof Key || node instanceof EmptyLine || node == null) {
+ return getPropertyCompletions();
+ }
+ return Collections.emptyList();
+ }
+
+ private Collection getNavigationProposals() {
+ String navPrefix = navigationPrefixFinder.getPrefix(doc, offset);
+ try {
+ if (navPrefix!=null) {
+ int navOffset = offset-navPrefix.length()-1; //offset of 'nav' operator char (i.e. '.' or ']').
+ navPrefix = fuzzySearchPrefix.getPrefix(doc, navOffset);
+ if (navPrefix!=null && !navPrefix.isEmpty()) {
+ PropertyInfo prop = findLongestValidProperty(index, navPrefix);
+ if (prop!=null) {
+ int regionStart = navOffset-navPrefix.length();
+ Collection hintProposals = getKeyHintProposals(prop, navOffset);
+ if (CollectionUtil.hasElements(hintProposals)) {
+ return hintProposals;
+ }
+ PropertyNavigator navigator = new PropertyNavigator(doc, null, typeUtil, new DocumentRegion(doc, regionStart, navOffset));
+ Type type = navigator.navigate(regionStart+prop.getId().length(), TypeParser.parse(prop.getType()));
+ if (type!=null) {
+ return getNavigationProposals(type, navOffset);
+ }
+ }
+ }
+ }
+ } catch (Exception e) {
+ Log.log(e);
+ }
+ return Collections.emptyList();
+ }
+
+ private Collection getKeyHintProposals(PropertyInfo prop, int navOffset) {
+ HintProvider hintProvider = prop.getHints(typeUtil, false);
+ if (!HintProviders.isNull(hintProvider)) {
+ String query = textBetween(doc, navOffset+1, offset);
+ List hintProperties = hintProvider.getPropertyHints(query);
+ if (CollectionUtil.hasElements(hintProperties)) {
+ return createPropertyProposals(TypeParser.parse(prop.getType()), navOffset, query, hintProperties);
+ }
+ }
+ return ImmutableList.of();
+ }
+
+ private String textBetween(IDocument doc, int start, int end) {
+ if (end > doc.getLength()) {
+ end = doc.getLength();
+ }
+ if (start>doc.getLength()) {
+ start = doc.getLength();
+ }
+ if (start<0) {
+ start = 0;
+ }
+ if (end < 0) {
+ end = 0;
+ }
+ if (start getNavigationProposals(Type type, int navOffset) {
+ try {
+ char navOp = doc.getChar(navOffset);
+ if (navOp=='.') {
+ String prefix = doc.get(navOffset+1, offset-(navOffset+1));
+ EnumCaseMode caseMode = caseMode(prefix);
+ List objectProperties = typeUtil.getProperties(type, caseMode, BeanPropertyNameMode.HYPHENATED);
+ //Note: properties editor itself deals with relaxed names. So it expects the properties here to be returned in hyphenated form only.
+ if (objectProperties!=null && !objectProperties.isEmpty()) {
+ return createPropertyProposals(type, navOffset, prefix, objectProperties);
+ }
+ } else {
+ //TODO: other cases ']' or '[' ?
+ }
+ } catch (Exception e) {
+ Log.log(e);
+ }
+ return Collections.emptyList();
+ }
+
+ protected Collection createPropertyProposals(Type type, int navOffset,
+ String prefix, List objectProperties) {
+ ArrayList proposals = new ArrayList();
+ for (TypedProperty prop : objectProperties) {
+ double score = FuzzyMatcher.matchScore(prefix, prop.getName());
+ if (score!=0) {
+ Type valueType = prop.getType();
+ String postFix = propertyCompletionPostfix(typeUtil, valueType);
+ DocumentEdits edits = new DocumentEdits(doc);
+ edits.delete(navOffset+1, offset);
+ edits.insert(offset, prop.getName()+postFix);
+ proposals.add(
+ completionFactory.beanProperty(doc, null, type, prefix, prop, score, edits, typeUtil)
+ );
+ }
+ }
+ return proposals;
+ }
+
+ /**
+ * Determines the EnumCaseMode used to generate completion candidates based on prefix.
+ */
+ protected EnumCaseMode caseMode(String prefix) {
+ EnumCaseMode caseMode;
+ if ("".equals(prefix)) {
+ caseMode = preferLowerCaseEnums?EnumCaseMode.LOWER_CASE:EnumCaseMode.ORIGNAL;
+ } else {
+ caseMode = Character.isLowerCase(prefix.charAt(0))?EnumCaseMode.LOWER_CASE:EnumCaseMode.ORIGNAL;
+ }
+ return caseMode;
+ }
+
+ protected static String propertyCompletionPostfix(TypeUtil typeUtil, Type type) {
+ String postfix = "";
+ if (type!=null) {
+ if (typeUtil.isAssignableType(type)) {
+ postfix = "=";
+ } else if (TypeUtil.isBracketable(type)) {
+ postfix = "[";
+ } else if (typeUtil.isDotable(type)) {
+ postfix = ".";
+ }
+ }
+ return postfix;
+ }
+
+// public static boolean isAssign(char assign) {
+// return assign==':'||assign=='=';
+// }
+//
+// private KeyValuePair getAstNodeLine(IDocument doc, int offset) {
+// List pairs = parser.parse(doc.get()).ast.getNodes(KeyValuePair.class);
+// return findPair(pairs, offset, 0, pairs.size() - 1);
+// }
+//
+// private KeyValuePair findPair(List pairs, int offset, int start, int end) {
+// if (start == end) {
+// KeyValuePair pair = pairs.get(start);
+// if (pair.getOffset() <= offset && offset <= pair.getOffset() + pair.getLength()) {
+// return pair;
+// } else {
+// return null;
+// }
+// } else if (start < end ) {
+// int pivotIndex = (start + end) / 2;
+// KeyValuePair pair = pairs.get(pivotIndex);
+// if (pair.getOffset() > offset) {
+// return findPair(pairs, offset, start, pivotIndex - 1);
+// } else if (offset > pair.getOffset() + pair.getLength()) {
+// return findPair(pairs, offset, pivotIndex + 1, end);
+// } else {
+// return pair;
+// }
+// } else {
+// return null;
+// }
+// }
+
+// private HoverInfo getValueHoverInfo(DocumentRegion value) {
+// try {
+// String valueString = value.toString();
+// IDocument doc = value.getDocument();
+// ITypedRegion valuePartition = getPartition(value.getDocument(), value.getStart());
+// int valuePartitionStart = valuePartition.getOffset();
+// String propertyName = fuzzySearchPrefix.getPrefix(doc, valuePartitionStart); //note: no need to skip whitespace backwards.
+// //because value partition includes whitespace around the assignment
+//
+// Type type = getValueType(propertyName);
+// if (TypeUtil.isArray(type) || TypeUtil.isList(type)) {
+// //It is useful to provide content assist for the values in the list when entering a list
+// type = TypeUtil.getDomainType(type);
+// }
+// if (TypeUtil.isClass(type)) {
+// //Special case. We want to provide hoverinfos more liberally than what's suggested for completions (i.e. even class names
+// //that are not suggested by the hints because they do not meet subtyping constraints should be hoverable and linkable!
+// StsValueHint hint = StsValueHint.className(valueString, typeUtil);
+// if (hint!=null) {
+// return new ValueHintHoverInfo(hint);
+// }
+// }
+// //Hack: pretend to invoke content-assist at the end of the value text. This should provide hints applicable to that value
+// // then show hoverinfo based on that. That way we can avoid duplication a lot of similar logic to compute hoverinfos and hyperlinks.
+// Collection hints = getValueHints(valueString, propertyName, EnumCaseMode.ALIASED);
+// if (hints!=null) {
+// for (StsValueHint h : hints) {
+// if (valueString.equals(h.getValue())) {
+// return new ValueHintHoverInfo(h);
+// }
+// }
+// }
+// } catch (BadLocationException e) {
+// Log.log(e);
+// }
+// return null;
+// }
+
+ private Collection getValueCompletions(Value value) {
+ DocumentRegion valueRegion = createRegion(doc, value).trimStart(SPACES).trimEnd(SPACES);
+ 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();
+ // because value partition includes whitespace around the assignment
+ if (propertyName != null) {
+ Collection valueCompletions = getValueHints(query, propertyName, caseMode);
+ if (valueCompletions != null && !valueCompletions.isEmpty()) {
+ ArrayList proposals = new ArrayList();
+ for (StsValueHint hint : valueCompletions) {
+ String valueCandidate = hint.getValue();
+ double score = FuzzyMatcher.matchScore(query, valueCandidate);
+ if (score != 0) {
+ DocumentEdits edits = new DocumentEdits(doc);
+ edits.delete(startOfValue, offset);
+ edits.insert(offset, valueCandidate);
+ proposals.add(completionFactory.valueProposal(valueCandidate, query, getValueType(propertyName),
+ score, edits, new ValueHintHoverInfo(hint))
+ // new ValueProposal(startOfValue, valuePrefix,
+ // valueCandidate, i)
+ );
+ }
+ }
+ return proposals;
+ }
+ }
+ return Collections.emptyList();
+ }
+
+ private DocumentRegion createRegion(IDocument doc, Node value) {
+ // Trim trailing spaces (there is no leading white space already)
+ int length = value.getLength();
+ try {
+ length = doc.get(value.getOffset(), value.getLength()).trim().length();
+ } catch (BadLocationException e) {
+ // ignore
+ }
+ return new DocumentRegion(doc, value.getOffset(), value.getOffset() + length);
+ }
+
+ private Collection getValueHints(String query, String propertyName, EnumCaseMode caseMode) {
+ Type type = getValueType(propertyName);
+ if (TypeUtil.isArray(type) || TypeUtil.isList(type)) {
+ //It is useful to provide content assist for the values in the list when entering a list
+ type = TypeUtil.getDomainType(type);
+ }
+ List allHints = new ArrayList<>();
+ {
+ Collection hints = typeUtil.getHintValues(type, query, caseMode);
+ if (CollectionUtil.hasElements(hints)) {
+ allHints.addAll(hints);
+ }
+ }
+ {
+ PropertyInfo prop = index.findLongestCommonPrefixEntry(propertyName);
+ if (prop!=null) {
+ HintProvider hintProvider = prop.getHints(typeUtil, false);
+ if (!HintProviders.isNull(hintProvider)) {
+ allHints.addAll(hintProvider.getValueHints(query));
+ }
+ }
+ }
+ return allHints;
+ }
+
+ /**
+ * Determine the value type for a give propertyName.
+ */
+ protected Type getValueType(String propertyName) {
+ try {
+ PropertyInfo prop = index.get(propertyName);
+ if (prop!=null) {
+ return TypeParser.parse(prop.getType());
+ } else {
+ prop = findLongestValidProperty(index, propertyName);
+ if (prop!=null) {
+ TextDocument doc = new TextDocument(null);
+ doc.setText(propertyName);
+ PropertyNavigator navigator = new PropertyNavigator(doc, null, typeUtil, new DocumentRegion(doc, 0, doc.getLength()));
+ return navigator.navigate(prop.getId().length(), TypeParser.parse(prop.getType()));
+ }
+ }
+ } catch (Exception e) {
+ Log.log(e);
+ }
+ return null;
+ }
+
+ private List> findMatches(String prefix) {
+ List> matches = index.find(camelCaseToHyphens(prefix));
+ return matches;
+ }
+
+ private Collection getPropertyCompletions() throws BadLocationException {
+ Collection navProposals = getNavigationProposals();
+ if (!navProposals.isEmpty()) {
+ return navProposals;
+ }
+ return getFuzzyCompletions();
+ }
+
+ protected Collection getFuzzyCompletions() {
+ final String prefix = fuzzySearchPrefix.getPrefix(doc, offset);
+ if (prefix != null) {
+ Collection> matches = findMatches(prefix);
+ if (matches!=null && !matches.isEmpty()) {
+ ArrayList proposals = new ArrayList(matches.size());
+ for (final Match match : matches) {
+ DocumentEdits docEdits;
+ try {
+ docEdits = LazyProposalApplier.from(() -> {
+ Type type = TypeParser.parse(match.data.getType());
+ DocumentEdits edits = new DocumentEdits(doc);
+ edits.delete(offset-prefix.length(), offset);
+ edits.insert(offset, match.data.getId() + propertyCompletionPostfix(typeUtil, type));
+ return edits;
+ });
+ proposals.add(completionFactory.property(doc, docEdits, match, typeUtil));
+ } catch (Exception e) {
+ Log.log(e);
+ }
+ }
+ return proposals;
+ }
+ }
+ return Collections.emptyList();
+ }
+
+// public HoverInfo getHoverInfo(IDocument doc, IRegion _region) {
+// debug("getHoverInfo("+_region+")");
+//
+// //The delegate 'getHoverRegion' for spring propery editor will return smaller word regions.
+// // we must ensure to use our own region finder to identify correct property name.
+// ITypedRegion region = getHoverRegion(doc, _region.getOffset());
+// if (region!=null) {
+// String contentType = region.getType();
+// try {
+// if (contentType.equals(IDocument.DEFAULT_CONTENT_TYPE)) {
+// debug("hoverRegion = "+region);
+// PropertyInfo best = findBestHoverMatch(doc.get(region.getOffset(), region.getLength()).trim());
+// if (best!=null) {
+// return new SpringPropertyHoverInfo(documentContextFinder.getJavaProject(doc), best);
+// }
+// } else if (contentType.equals(IPropertiesFilePartitions.PROPERTY_VALUE)) {
+// return getValueHoverInfo(new DocumentRegion(doc, region));
+// }
+// } catch (Exception e) {
+// SpringPropertiesEditorPlugin.log(e);
+// }
+// }
+// return null;
+// }
+//
+// public ITypedRegion getHoverRegion(IDocument document, int offset) {
+// try {
+// ITypedRegion candidate = getPartition(document, offset);
+// if (candidate!=null) {
+// String type = candidate.getType();
+// if (IDocument.DEFAULT_CONTENT_TYPE.equals(type)) {
+// return candidate;
+// } else if (IPropertiesFilePartitions.PROPERTY_VALUE.equals(type)) {
+// DocumentRegion valueRegion = new DocumentRegion(document, candidate).trimStart(ASSIGN);
+// return getValueHoverRegion(valueRegion, valueRegion.toRelative(offset));
+// }
+// }
+// } catch (Exception e) {
+// SpringPropertiesEditorPlugin.log(e);
+// }
+// return null;
+// }
+//
+// private ITypedRegion getValueHoverRegion(DocumentRegion r, int offset) {
+// int len = r.length();
+// if (offset>=0 && offset<=len) {
+// int start = offset;
+// while (start>0 && isValuePrefixChar(r.charAt(start-1))) {
+// start--;
+// }
+// int end = offset;
+// while (endbestCommonPrefixLen // it has a longer common prefix
+// || commonPrefixLen==bestCommonPrefixLen && extraLen index, String name) {
+ int bracketPos = name.indexOf('[');
+ int endPos = bracketPos>=0?bracketPos:name.length();
+ PropertyInfo prop = null;
+ String prefix = null;
+ while (endPos>0 && prop==null) {
+ prefix = name.substring(0, endPos);
+ String canonicalPrefix = camelCaseToHyphens(prefix);
+ prop = index.get(canonicalPrefix);
+ if (prop==null) {
+ endPos = name.lastIndexOf('.', endPos-1);
+ }
+ }
+ if (prop!=null) {
+ //We should meet caller's expectation that matched properties returned by this method
+ // match the names exactly even if we found them using relaxed name matching.
+ return prop.withId(prefix);
+ }
+ return null;
+ }
+
+
+}
diff --git a/vscode-extensions/vscode-application-properties/src/main/java/org/springframework/ide/vscode/application/properties/completions/SpringPropertiesCompletionEngine.java b/vscode-extensions/vscode-application-properties/src/main/java/org/springframework/ide/vscode/application/properties/completions/SpringPropertiesCompletionEngine.java
new file mode 100644
index 000000000..9f48cd85e
--- /dev/null
+++ b/vscode-extensions/vscode-application-properties/src/main/java/org/springframework/ide/vscode/application/properties/completions/SpringPropertiesCompletionEngine.java
@@ -0,0 +1,51 @@
+package org.springframework.ide.vscode.application.properties.completions;
+
+import java.util.Collection;
+
+import org.springframework.ide.vscode.application.properties.metadata.SpringPropertyIndexProvider;
+import org.springframework.ide.vscode.application.properties.metadata.completions.PropertyCompletionFactory;
+import org.springframework.ide.vscode.application.properties.metadata.types.TypeUtilProvider;
+import org.springframework.ide.vscode.commons.languageserver.completion.ICompletionEngine;
+import org.springframework.ide.vscode.commons.languageserver.completion.ICompletionProposal;
+import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder;
+import org.springframework.ide.vscode.commons.languageserver.util.BadLocationException;
+import org.springframework.ide.vscode.commons.languageserver.util.IDocument;;
+
+/**
+ * @author Kris De Volder
+ */
+public class SpringPropertiesCompletionEngine implements ICompletionEngine {
+
+ private boolean preferLowerCaseEnums = true; //might make sense to make this user configurable
+
+ private SpringPropertyIndexProvider indexProvider;
+ private TypeUtilProvider typeUtilProvider;
+ private PropertyCompletionFactory completionFactory = null;
+
+ /**
+ * Constructor used in 'production'. Wires up stuff properly for running inside a normal
+ * Eclipse runtime.
+ */
+ public SpringPropertiesCompletionEngine(SpringPropertyIndexProvider indexProvider, TypeUtilProvider typeUtilProvider, JavaProjectFinder projectFinder) {
+ this.indexProvider = indexProvider;
+ this.typeUtilProvider = typeUtilProvider;
+ this.completionFactory = new PropertyCompletionFactory(projectFinder);
+ }
+
+ /**
+ * Create completions proposals in the context of a properties text editor.
+ */
+ public Collection getCompletions(IDocument doc, int offset) throws BadLocationException {
+ return new PropertiesCompletionProposalsCalculator(indexProvider.getIndex(doc),
+ typeUtilProvider.getTypeUtil(doc), completionFactory, doc, offset, preferLowerCaseEnums).calculate();
+ }
+
+ public boolean getPreferLowerCaseEnums() {
+ return preferLowerCaseEnums;
+ }
+
+ public void setPreferLowerCaseEnums(boolean preferLowerCaseEnums) {
+ this.preferLowerCaseEnums = preferLowerCaseEnums;
+ }
+
+}
\ No newline at end of file
diff --git a/vscode-extensions/vscode-application-properties/src/main/java/org/springframework/ide/vscode/application/properties/reconcile/SpringPropertiesReconcileEngine.java b/vscode-extensions/vscode-application-properties/src/main/java/org/springframework/ide/vscode/application/properties/reconcile/SpringPropertiesReconcileEngine.java
index ea75dd9c1..bd76e8b84 100644
--- a/vscode-extensions/vscode-application-properties/src/main/java/org/springframework/ide/vscode/application/properties/reconcile/SpringPropertiesReconcileEngine.java
+++ b/vscode-extensions/vscode-application-properties/src/main/java/org/springframework/ide/vscode/application/properties/reconcile/SpringPropertiesReconcileEngine.java
@@ -69,7 +69,7 @@ public class SpringPropertiesReconcileEngine implements IReconcileEngine {
private final DelimitedListReconciler commaListReconciler = new DelimitedListReconciler(COMMA, this::reconcileType);
private Parser parser = new AntlrParser();
- private boolean recordSyntaxErrors = false;
+ private boolean recordSyntaxErrors;
public SpringPropertiesReconcileEngine(SpringPropertyIndexProvider provider, TypeUtilProvider typeUtilProvider) {
this(provider, typeUtilProvider, true);
@@ -103,8 +103,6 @@ public class SpringPropertiesReconcileEngine implements IReconcileEngine {
}
results.ast.getNodes(KeyValuePair.class).forEach(pair -> {
-// Key fullName = pair.getKey();
-// String keyName = fullName.decode();
try {
DocumentRegion propertyNameRegion = createRegion(doc, pair.getKey());
String keyName = PropertiesFileEscapes.unescape(propertyNameRegion.toString());
@@ -184,7 +182,7 @@ public class SpringPropertiesReconcileEngine implements IReconcileEngine {
// Trim trailing spaces (there is no leading white space already)
int length = value.getLength();
try {
- length = doc.get(value.getOffset(), value.getLength()).trim().length();
+ length = doc.get(value.getOffset(), value.getLength()).length();
} catch (BadLocationException e) {
// ignore
}
diff --git a/vscode-extensions/vscode-application-properties/src/test/java/org/springframework/ide/vscode/application/properties/test/ApplicationPropertiesEditorTest.java b/vscode-extensions/vscode-application-properties/src/test/java/org/springframework/ide/vscode/application/properties/test/ApplicationPropertiesEditorTest.java
index c8571ea06..c4a291a4f 100644
--- a/vscode-extensions/vscode-application-properties/src/test/java/org/springframework/ide/vscode/application/properties/test/ApplicationPropertiesEditorTest.java
+++ b/vscode-extensions/vscode-application-properties/src/test/java/org/springframework/ide/vscode/application/properties/test/ApplicationPropertiesEditorTest.java
@@ -27,6 +27,7 @@ import org.springframework.ide.vscode.application.properties.metadata.CachingVal
import org.springframework.ide.vscode.application.properties.metadata.PropertiesLoader;
import org.springframework.ide.vscode.commons.java.IJavaProject;
import org.springframework.ide.vscode.commons.java.IType;
+import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder;
import org.springframework.ide.vscode.commons.languageserver.util.SimpleLanguageServer;
import org.springframework.ide.vscode.commons.maven.java.MavenJavaProject;
import org.springframework.ide.vscode.languageserver.testharness.Editor;
@@ -47,6 +48,8 @@ import org.eclipse.lsp4j.Diagnostic;
*/
public class ApplicationPropertiesEditorTest extends AbstractPropsEditorTest {
+ private JavaProjectFinder javaProjectFinder;
+
@Test public void testReconcileCatchesParseError() throws Exception {
Editor editor = newEditor("key\n");
editor.assertProblems("key|extraneous input");
@@ -66,28 +69,28 @@ public class ApplicationPropertiesEditorTest extends AbstractPropsEditorTest {
editor.assertProblems("problem|extraneous input", "another|mismatched input");
}
- @Ignore @Test public void testServerPortCompletion() throws Exception {
+ @Test public void testServerPortCompletion() throws Exception {
data("server.port", INTEGER, 8080, "Port where server listens for http.");
assertCompletion("ser<*>", "server.port=<*>");
assertCompletionDisplayString("ser<*>", "server.port : int");
}
- @Ignore @Test public void testLoggingLevelCompletion() throws Exception {
+ @Test public void testLoggingLevelCompletion() throws Exception {
data("logging.level", "java.util.Map", null, "Logging level per package.");
assertCompletion("lolev<*>","logging.level.<*>");
}
- @Ignore @Test public void testListCompletion() throws Exception {
+ @Test public void testListCompletion() throws Exception {
data("foo.bars", "java.util.List", null, "List of bars in foo.");
assertCompletion("foba<*>","foo.bars=<*>");
}
- @Ignore @Test public void testInetAddresCompletion() throws Exception {
+ @Test public void testInetAddresCompletion() throws Exception {
defaultTestData();
assertCompletion("server.add<*>", "server.address=<*>");
}
- @Ignore @Test public void testStringArrayCompletion() throws Exception {
+ @Test public void testStringArrayCompletion() throws Exception {
data("spring.freemarker.view-names", "java.lang.String[]", null, "White list of view names that can be resolved.");
data("some.defaulted.array", "java.lang.String[]", new String[] {"a", "b", "c"} , "Stuff.");
@@ -95,7 +98,7 @@ public class ApplicationPropertiesEditorTest extends AbstractPropsEditorTest {
assertCompletion("some.d.a<*>", "some.defaulted.array=<*>");
}
- @Ignore @Test public void testEmptyPrefixProposalsSortedAlpabetically() throws Exception {
+ @Test public void testEmptyPrefixProposalsSortedAlpabetically() throws Exception {
defaultTestData();
Editor editor = newEditor("");
List completions = editor.getCompletions();
@@ -110,7 +113,7 @@ public class ApplicationPropertiesEditorTest extends AbstractPropsEditorTest {
}
}
- @Ignore @Test public void testValueCompletion() throws Exception {
+ @Test public void testValueCompletion() throws Exception {
defaultTestData();
assertCompletionsVariations("liquibase.enabled=<*>",
"liquibase.enabled=false<*>",
@@ -310,7 +313,7 @@ public class ApplicationPropertiesEditorTest extends AbstractPropsEditorTest {
);
}
- @Ignore @Test public void testPojoArrayCompletions() throws Exception {
+ @Test public void testPojoArrayCompletions() throws Exception {
IJavaProject p = createPredefinedMavenProject("boot-1.2.1-app-properties-list-of-pojo");
useProject(p);
@@ -395,7 +398,7 @@ public class ApplicationPropertiesEditorTest extends AbstractPropsEditorTest {
);
}
- @Ignore @Test public void testRelaxedNameContentAssist() throws Exception {
+ @Test public void testRelaxedNameContentAssist() throws Exception {
data("foo-bar-zor.enabled", "java.lang.Boolean", null, null);
assertCompletion("fooBar<*>", "foo-bar-zor.enabled=<*>");
}
@@ -458,7 +461,7 @@ public class ApplicationPropertiesEditorTest extends AbstractPropsEditorTest {
);
}
- @Ignore @Test public void testEnumPropertyCompletionInsideCommaSeparateList() throws Exception {
+ @Test public void testEnumPropertyCompletionInsideCommaSeparateList() throws Exception {
IJavaProject p = createPredefinedMavenProject("enums-boot-1.3.2-app");
useProject(p);
@@ -481,7 +484,7 @@ public class ApplicationPropertiesEditorTest extends AbstractPropsEditorTest {
assertCompletion("foo.colors=RED,B<*>", "foo.colors=RED,BLUE<*>");
}
- @Ignore @Test public void testEnumPropertyCompletion() throws Exception {
+ @Test public void testEnumPropertyCompletion() throws Exception {
IJavaProject p = createPredefinedMavenProject("enums-boot-1.3.2-app");
useProject(p);
@@ -523,7 +526,7 @@ public class ApplicationPropertiesEditorTest extends AbstractPropsEditorTest {
);
}
- @Ignore @Test public void testEnumMapValueCompletion() throws Exception {
+ @Test public void testEnumMapValueCompletion() throws Exception {
IJavaProject p = createPredefinedMavenProject("enums-boot-1.3.2-app");
useProject(p);
@@ -559,7 +562,7 @@ public class ApplicationPropertiesEditorTest extends AbstractPropsEditorTest {
);
}
- @Ignore @Test public void testEnumMapKeyCompletion() throws Exception {
+ @Test public void testEnumMapKeyCompletion() throws Exception {
IJavaProject p = createPredefinedMavenProject("enums-boot-1.3.2-app");
useProject(p);
@@ -617,7 +620,7 @@ public class ApplicationPropertiesEditorTest extends AbstractPropsEditorTest {
);
}
- @Ignore @Test public void testPojoCompletions() throws Exception {
+ @Test public void testPojoCompletions() throws Exception {
IJavaProject p = createPredefinedMavenProject("enums-boot-1.3.2-app");
useProject(p);
@@ -629,11 +632,11 @@ public class ApplicationPropertiesEditorTest extends AbstractPropsEditorTest {
assertCompletionsDisplayString("foo.data.",
"wavelen : double",
"name : String",
- "next : demo.Color[RED, GREEN, BLUE]",
+ "next : demo.Color[BLUE, GREEN, RED]",
"nested : demo.ColorData",
"children : List",
"mapped-children : Map",
- "color-children : Map",
+ "color-children : Map",
"tags : List",
"funky : boolean"
);
@@ -675,7 +678,7 @@ public class ApplicationPropertiesEditorTest extends AbstractPropsEditorTest {
);
}
- @Ignore @Test public void testListOfAtomicCompletions() throws Exception {
+ @Test public void testListOfAtomicCompletions() throws Exception {
data("foo.slist", "java.util.List", null, "list of strings");
data("foo.ulist", "java.util.List", null, "list of strings");
data("foo.dlist", "java.util.List", null, "list of doubles");
@@ -684,7 +687,7 @@ public class ApplicationPropertiesEditorTest extends AbstractPropsEditorTest {
assertCompletionsVariations("foo.sl<*>", "foo.slist=<*>");
}
- @Ignore @Test public void testMapKeyDotInterpretation() throws Exception {
+ @Test public void testMapKeyDotInterpretation() throws Exception {
//Interpretation of '.' changes depending on the domain type (i.e. when domain type is
//is a simple type got which '.' navigation is invalid then the '.' is 'eaten' by the key.
@@ -724,7 +727,7 @@ public class ApplicationPropertiesEditorTest extends AbstractPropsEditorTest {
);
}
- @Ignore @Test public void testMapKeyDotInterpretationInPojo() throws Exception {
+ @Test public void testMapKeyDotInterpretationInPojo() throws Exception {
//Similar to testMapKeyDotInterpretation but this time maps are not attached to property
// directly but via a pojo property
@@ -797,7 +800,7 @@ public class ApplicationPropertiesEditorTest extends AbstractPropsEditorTest {
);
}
- @Ignore @Test public void testEnumsInLowerCaseContentAssist() throws Exception {
+ @Test public void testEnumsInLowerCaseContentAssist() throws Exception {
IJavaProject p = createPredefinedMavenProject("enums-boot-1.3.2-app");
useProject(p);
@@ -840,7 +843,7 @@ public class ApplicationPropertiesEditorTest extends AbstractPropsEditorTest {
assertCompletionsVariations("foo.color-data.red.na<*>", "foo.color-data.red.name=<*>");
}
- @Ignore @Test public void testNavigationProposalAfterRelaxedPropertyName() throws Exception {
+ @Test public void testNavigationProposalAfterRelaxedPropertyName() throws Exception {
IJavaProject p = createPredefinedMavenProject("enums-boot-1.3.2-app");
useProject(p);
@@ -849,7 +852,7 @@ public class ApplicationPropertiesEditorTest extends AbstractPropsEditorTest {
assertCompletionsVariations("foo.colorData.red.na<*>", "foo.colorData.red.name=<*>");
}
- @Ignore @Test public void testValueProposalAssignedToRelaxedPropertyName() throws Exception {
+ @Test public void testValueProposalAssignedToRelaxedPropertyName() throws Exception {
IJavaProject p = createPredefinedMavenProject("enums-boot-1.3.2-app");
useProject(p);
@@ -983,7 +986,7 @@ public class ApplicationPropertiesEditorTest extends AbstractPropsEditorTest {
);
}
- @Ignore @Test public void testCharsetCompletions() throws Exception {
+ @Test public void testCharsetCompletions() throws Exception {
data("foobar.encoding", "java.nio.charset.Charset", null, "The charset-encoding to use for foobars");
assertCompletions(
@@ -1001,7 +1004,7 @@ public class ApplicationPropertiesEditorTest extends AbstractPropsEditorTest {
);
}
- @Ignore @Test public void testLocaleCompletions() throws Exception {
+ @Test public void testLocaleCompletions() throws Exception {
data("foobar.locale", "java.util.Locale", null, "Yada yada");
assertCompletions(
@@ -1019,7 +1022,7 @@ public class ApplicationPropertiesEditorTest extends AbstractPropsEditorTest {
);
}
- @Ignore @Test public void testPropertyValueHintCompletions() throws Exception {
+ @Test public void testPropertyValueHintCompletions() throws Exception {
//Test that 'value hints' work when property name is associated with 'value' hints.
// via boot metadata.
@@ -1037,7 +1040,7 @@ public class ApplicationPropertiesEditorTest extends AbstractPropsEditorTest {
);
}
- @Ignore @Test public void testPropertyListHintCompletions() throws Exception {
+ @Test public void testPropertyListHintCompletions() throws Exception {
useProject(createPredefinedMavenProject("empty-boot-1.3.0-app"));
assertCompletion(
@@ -1065,7 +1068,7 @@ public class ApplicationPropertiesEditorTest extends AbstractPropsEditorTest {
);
}
- @Ignore @Test public void testPropertyMapValueCompletions() throws Exception {
+ @Test public void testPropertyMapValueCompletions() throws Exception {
useProject(createPredefinedMavenProject("empty-boot-1.3.0-app"));
assertCompletionsDisplayString(
@@ -1093,7 +1096,7 @@ public class ApplicationPropertiesEditorTest extends AbstractPropsEditorTest {
);
}
- @Ignore @Test public void testPropertyMapKeyCompletions() throws Exception {
+ @Test public void testPropertyMapKeyCompletions() throws Exception {
useProject(createPredefinedMavenProject("empty-boot-1.3.0-app"));
assertCompletionWithLabel(
"logging.level.<*>"
@@ -1120,7 +1123,7 @@ public class ApplicationPropertiesEditorTest extends AbstractPropsEditorTest {
);
}
- @Ignore @Test public void testHandleAsResourceContentAssist() throws Exception {
+ @Test public void testHandleAsResourceContentAssist() throws Exception {
//"name": "my.terms-and-conditions",
// "providers": [
// {
@@ -1144,7 +1147,7 @@ public class ApplicationPropertiesEditorTest extends AbstractPropsEditorTest {
);
}
- @Ignore @Test public void testHandleAsListContentAssist() throws Exception {
+ @Test public void testHandleAsListContentAssist() throws Exception {
data("my.tosses", "String[]", null, "A sequence of coin tosses")
.provider("handle-as", "target", "java.lang.Boolean[]");
@@ -1179,7 +1182,7 @@ public class ApplicationPropertiesEditorTest extends AbstractPropsEditorTest {
}
- @Ignore @Test public void test_STS_3335_completions_list_nested_in_Map_of_String() throws Exception {
+ @Test public void test_STS_3335_completions_list_nested_in_Map_of_String() throws Exception {
useProject(createPredefinedMavenProject("boot-1.3.3-sts-4335"));
assertCompletions(
@@ -1201,7 +1204,7 @@ public class ApplicationPropertiesEditorTest extends AbstractPropsEditorTest {
);
}
- @Ignore @Test public void testSimpleResourceCompletion() throws Exception {
+ @Test public void testSimpleResourceCompletion() throws Exception {
CachingValueProvider.TIMEOUT = Duration.ofSeconds(20);
useProject(createPredefinedMavenProject("empty-boot-1.3.0-app"));
@@ -1225,7 +1228,7 @@ public class ApplicationPropertiesEditorTest extends AbstractPropsEditorTest {
);
}
- @Ignore @Test public void testClasspathResourceCompletion() throws Exception {
+ @Test public void testClasspathResourceCompletion() throws Exception {
CachingValueProvider.TIMEOUT = Duration.ofSeconds(20);
useProject(createPredefinedMavenProject("empty-boot-1.3.0-app"));
@@ -1295,7 +1298,7 @@ public class ApplicationPropertiesEditorTest extends AbstractPropsEditorTest {
);
}
- @Ignore @Test public void testClasspathResourceCompletionInCommaList() throws Exception {
+ @Test public void testClasspathResourceCompletionInCommaList() throws Exception {
CachingValueProvider.TIMEOUT = Duration.ofSeconds(20);
useProject(createPredefinedMavenProject("empty-boot-1.3.0-app"));
@@ -1490,7 +1493,7 @@ public class ApplicationPropertiesEditorTest extends AbstractPropsEditorTest {
);
}
- @Ignore @Test public void test_PT_119352965() throws Exception {
+ @Test public void test_PT_119352965() throws Exception {
data("some.property", "java.lang.String", null, "Some property to test stuff")
.valueHint("SOMETHING", "A value for something")
.valueHint("ALTERNATE", "An alternative value");
@@ -1558,17 +1561,9 @@ public class ApplicationPropertiesEditorTest extends AbstractPropsEditorTest {
@Override
protected SimpleLanguageServer newLanguageServer() {
- return new ApplicationPropertiesLanguageServer(md.getIndexProvider(), typeUtilProvider);
-// return new ApplicationPropertiesLanguageServer(md.getIndexProvider(), typeUtilProvider) {
-//
-// @Override
-// protected IReconcileEngine getReconcileEngine() {
-// SpringPropertiesReconcileEngine reconcileEngine = (SpringPropertiesReconcileEngine) super.getReconcileEngine();
-// reconcileEngine.setRecordSyntaxErrors(false);
-// return reconcileEngine;
-// }
-//
-// };
+ ApplicationPropertiesLanguageServer server = new ApplicationPropertiesLanguageServer(md.getIndexProvider(), typeUtilProvider, javaProjectFinder);
+ server.setMaxCompletionsNumber(-1);
+ return server;
}
/**
diff --git a/vscode-extensions/vscode-application-properties/src/test/java/org/springframework/ide/vscode/application/properties/test/ApplicationPropertiesLanguageServerTest.java b/vscode-extensions/vscode-application-properties/src/test/java/org/springframework/ide/vscode/application/properties/test/ApplicationPropertiesLanguageServerTest.java
index c59cfa767..5f911a0f4 100644
--- a/vscode-extensions/vscode-application-properties/src/test/java/org/springframework/ide/vscode/application/properties/test/ApplicationPropertiesLanguageServerTest.java
+++ b/vscode-extensions/vscode-application-properties/src/test/java/org/springframework/ide/vscode/application/properties/test/ApplicationPropertiesLanguageServerTest.java
@@ -37,7 +37,7 @@ public class ApplicationPropertiesLanguageServerTest {
}
private LanguageServerHarness newHarness() throws Exception {
- Callable extends LanguageServer> f = () -> new ApplicationPropertiesLanguageServer((d) -> null, (d) -> null);
+ Callable extends LanguageServer> f = () -> new ApplicationPropertiesLanguageServer((d) -> null, (d) -> null, (d) -> null);
return new LanguageServerHarness(f);
}
diff --git a/vscode-extensions/vscode-application-yaml/package.json b/vscode-extensions/vscode-application-yaml/package.json
index 6e2628671..0834ba4d1 100644
--- a/vscode-extensions/vscode-application-yaml/package.json
+++ b/vscode-extensions/vscode-application-yaml/package.json
@@ -49,8 +49,7 @@
},
"dependencies": {
"portfinder": "^0.4.0",
- "vscode-languageclient": "2.5.x",
- "commons-vscode": "0.1.x"
+ "vscode-languageclient": "2.5.x"
},
"devDependencies": {
"typescript": "^1.8.5",
diff --git a/vscode-extensions/vscode-application-yaml/src/main/java/org/springframework/ide/vscode/application/yaml/ApplicationYamlLanguageServer.java b/vscode-extensions/vscode-application-yaml/src/main/java/org/springframework/ide/vscode/application/yaml/ApplicationYamlLanguageServer.java
index d2603823e..e2d398328 100644
--- a/vscode-extensions/vscode-application-yaml/src/main/java/org/springframework/ide/vscode/application/yaml/ApplicationYamlLanguageServer.java
+++ b/vscode-extensions/vscode-application-yaml/src/main/java/org/springframework/ide/vscode/application/yaml/ApplicationYamlLanguageServer.java
@@ -27,6 +27,7 @@ public class ApplicationYamlLanguageServer extends SimpleLanguageServer {
private YamlASTProvider parser = new YamlParser(yaml);
private SpringPropertyIndexProvider indexProvider;
private TypeUtilProvider typeUtilProvider;
+ private VscodeCompletionEngineAdapter completionEngine;
public ApplicationYamlLanguageServer(SpringPropertyIndexProvider indexProvider, TypeUtilProvider typeUtilProvider, JavaProjectFinder javaProjectFinder) {
this.indexProvider = indexProvider;
@@ -57,10 +58,14 @@ public class ApplicationYamlLanguageServer extends SimpleLanguageServer {
typeUtilProvider,
RelaxedNameConfig.COMPLETION_DEFAULTS
);
- VscodeCompletionEngine completionEngine = new VscodeCompletionEngineAdapter(this, yamlCompletionEngine);
+ completionEngine = new VscodeCompletionEngineAdapter(this, yamlCompletionEngine);
documents.onCompletion(completionEngine::getCompletions);
documents.onCompletionResolve(completionEngine::resolveCompletion);
}
+
+ public void setMaxCompletionsNumber(int number) {
+ completionEngine.setMaxCompletionsNumber(number);
+ }
protected IReconcileEngine getReconcileEngine() {
return new ApplicationYamlReconcileEngine(parser, indexProvider, typeUtilProvider);
diff --git a/vscode-extensions/vscode-application-yaml/src/main/java/org/springframework/ide/vscode/application/yaml/completions/ApplicationYamlAssistContext.java b/vscode-extensions/vscode-application-yaml/src/main/java/org/springframework/ide/vscode/application/yaml/completions/ApplicationYamlAssistContext.java
index 5bdbb3fb6..607f4dd54 100644
--- a/vscode-extensions/vscode-application-yaml/src/main/java/org/springframework/ide/vscode/application/yaml/completions/ApplicationYamlAssistContext.java
+++ b/vscode-extensions/vscode-application-yaml/src/main/java/org/springframework/ide/vscode/application/yaml/completions/ApplicationYamlAssistContext.java
@@ -35,6 +35,7 @@ import org.springframework.ide.vscode.application.properties.metadata.util.Fuzzy
import org.springframework.ide.vscode.application.properties.metadata.util.FuzzyMap.Match;
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.completion.LazyProposalApplier;
import org.springframework.ide.vscode.commons.languageserver.completion.ProposalApplier;
import org.springframework.ide.vscode.commons.languageserver.completion.ScoreableProposal;
import org.springframework.ide.vscode.commons.languageserver.util.DocumentRegion;
diff --git a/vscode-extensions/vscode-application-yaml/src/test/java/org/springframework/ide/vscode/application/yaml/ApplicationYamlEditorTest.java b/vscode-extensions/vscode-application-yaml/src/test/java/org/springframework/ide/vscode/application/yaml/ApplicationYamlEditorTest.java
index 28868452f..3fcc4048c 100644
--- a/vscode-extensions/vscode-application-yaml/src/test/java/org/springframework/ide/vscode/application/yaml/ApplicationYamlEditorTest.java
+++ b/vscode-extensions/vscode-application-yaml/src/test/java/org/springframework/ide/vscode/application/yaml/ApplicationYamlEditorTest.java
@@ -2987,7 +2987,7 @@ public class ApplicationYamlEditorTest extends AbstractPropsEditorTest {
);
}
- @Ignore @Test public void testPropertyMapKeyCompletions() throws Exception {
+ @Test public void testPropertyMapKeyCompletions() throws Exception {
useProject(createPredefinedMavenProject("empty-boot-1.3.0-app"));
assertCompletionWithLabel(
"logging:\n" +
@@ -3090,7 +3090,7 @@ public class ApplicationYamlEditorTest extends AbstractPropsEditorTest {
);
}
- @Ignore @Test public void testSimpleResourceCompletion() throws Exception {
+ @Test public void testSimpleResourceCompletion() throws Exception {
CachingValueProvider.TIMEOUT = Duration.ofSeconds(20);
useProject(createPredefinedMavenProject("empty-boot-1.3.0-app"));
@@ -3134,7 +3134,7 @@ public class ApplicationYamlEditorTest extends AbstractPropsEditorTest {
}
- @Ignore @Test public void testClasspathResourceCompletion() throws Exception {
+ @Test public void testClasspathResourceCompletion() throws Exception {
CachingValueProvider.TIMEOUT = Duration.ofSeconds(20);
useProject(createPredefinedMavenProject("empty-boot-1.3.0-app"));
@@ -3388,7 +3388,7 @@ public class ApplicationYamlEditorTest extends AbstractPropsEditorTest {
);
}
- @Ignore @Test public void testHandleAsResourceContentAssist() throws Exception {
+ @Test public void testHandleAsResourceContentAssist() throws Exception {
//"name": "my.terms-and-conditions",
// "providers": [
// {
@@ -3413,7 +3413,7 @@ public class ApplicationYamlEditorTest extends AbstractPropsEditorTest {
);
}
- @Ignore @Test public void testBootBug5905() throws Exception {
+ @Test public void testBootBug5905() throws Exception {
useProject(createPredefinedMavenProject("boot-1.3.3-app-with-resource-prop"));
//Check the metadata reflects the 'handle-as':
@@ -3542,7 +3542,9 @@ public class ApplicationYamlEditorTest extends AbstractPropsEditorTest {
@Override
protected SimpleLanguageServer newLanguageServer() {
- return new ApplicationYamlLanguageServer(md.getIndexProvider(), typeUtilProvider, javaProjectFinder);
+ ApplicationYamlLanguageServer server = new ApplicationYamlLanguageServer(md.getIndexProvider(), typeUtilProvider, javaProjectFinder);
+ server.setMaxCompletionsNumber(-1);
+ return server;
}
}