match,
+ TypeUtil typeUtil) {
+ super(doc, applier);
+ this.typeUtil = typeUtil;
+ this.match = match;
+ if (match.data.isDeprecated()) {
+ deprecate();
+ }
+ }
+
+// @Override
+// public HoverInfo getAdditionalProposalInfo(IProgressMonitor monitor) {
+// return new SpringPropertyHoverInfo(documentContextFinder.getJavaProject(fDoc), match.data);
+// }
+
+ @Override
+ protected String getBaseDisplayString() {
+ return match.data.getId();
+ }
+
+ @Override
+ public double getBaseScore() {
+ return match.score;
+ }
+
+ @Override
+ protected Type getType() {
+ if (type==null) {
+ type = TypeParser.parse(match.data.getType());
+ }
+ return type;
+ }
+
+ @Override
+ protected String getHighlightPattern() {
+ return match.getPattern();
+ }
+
+ @Override
+ protected String niceTypeName(YType type) {
+ return typeUtil.niceTypeName(((Type)type));
+ }
+ }
+
+}
diff --git a/vscode-extensions/commons/application-properties-metadata/src/main/java/org/springframework/ide/vscode/application/properties/metadata/completions/RelaxedNameConfig.java b/vscode-extensions/commons/application-properties-metadata/src/main/java/org/springframework/ide/vscode/application/properties/metadata/completions/RelaxedNameConfig.java
new file mode 100644
index 000000000..1518e8be2
--- /dev/null
+++ b/vscode-extensions/commons/application-properties-metadata/src/main/java/org/springframework/ide/vscode/application/properties/metadata/completions/RelaxedNameConfig.java
@@ -0,0 +1,42 @@
+package org.springframework.ide.vscode.application.properties.metadata.completions;
+
+import org.springframework.ide.vscode.application.properties.metadata.types.TypeUtil.BeanPropertyNameMode;
+import org.springframework.ide.vscode.application.properties.metadata.types.TypeUtil.EnumCaseMode;
+
+/**
+ * Config object that determines some aspects of how the freedom of 'relaxed name binding'
+ * are taken into account when generating content-assist completions.
+ *
+ * @author Kris De Volder
+ */
+public class RelaxedNameConfig {
+
+ public static final RelaxedNameConfig ALIASSED = new RelaxedNameConfig(EnumCaseMode.ALIASED, BeanPropertyNameMode.ALIASED);
+ public static final RelaxedNameConfig COMPLETION_DEFAULTS = new RelaxedNameConfig(EnumCaseMode.LOWER_CASE, BeanPropertyNameMode.HYPHENATED);
+
+ private EnumCaseMode enumMode = EnumCaseMode.LOWER_CASE;
+ private BeanPropertyNameMode beanMode = BeanPropertyNameMode.HYPHENATED;
+
+ public RelaxedNameConfig(EnumCaseMode enumMode, BeanPropertyNameMode beanMode) {
+ this.enumMode = enumMode;
+ this.beanMode = beanMode;
+ }
+ public EnumCaseMode getEnumMode() {
+ return enumMode;
+ }
+ public void setEnumMode(EnumCaseMode preferredEnumCompletions) {
+ this.enumMode = preferredEnumCompletions;
+ }
+ public BeanPropertyNameMode getBeanMode() {
+ return beanMode;
+ }
+ public void setBeanMode(BeanPropertyNameMode preferredBeanCompletions) {
+ this.beanMode = preferredBeanCompletions;
+ }
+
+ @Override
+ public String toString() {
+ return "RelaxedNameConfig("+enumMode+", "+beanMode+")";
+ }
+
+}
diff --git a/vscode-extensions/commons/application-properties-metadata/src/main/java/org/springframework/ide/vscode/application/properties/metadata/hints/BasicHintProvider.java b/vscode-extensions/commons/application-properties-metadata/src/main/java/org/springframework/ide/vscode/application/properties/metadata/hints/BasicHintProvider.java
new file mode 100644
index 000000000..82f17bf54
--- /dev/null
+++ b/vscode-extensions/commons/application-properties-metadata/src/main/java/org/springframework/ide/vscode/application/properties/metadata/hints/BasicHintProvider.java
@@ -0,0 +1,85 @@
+/*******************************************************************************
+ * Copyright (c) 2016 Pivotal, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Pivotal, Inc. - initial API and implementation
+ *******************************************************************************/
+package org.springframework.ide.vscode.application.properties.metadata.hints;
+
+import java.util.Collection;
+import java.util.List;
+
+import org.springframework.boot.configurationmetadata.ValueHint;
+import org.springframework.ide.vscode.application.properties.metadata.ValueProviderRegistry.ValueProviderStrategy;
+import org.springframework.ide.vscode.application.properties.metadata.types.TypedProperty;
+import org.springframework.ide.vscode.commons.java.IJavaProject;
+import org.springframework.ide.vscode.commons.util.CollectionUtil;
+import org.springframework.ide.vscode.commons.yaml.path.YamlPathSegment;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableList.Builder;
+
+/**
+ * A single hint provider that combines the two kinds of 'hint' metadata that spring boot
+ * may contain (namely 'values' data and 'valueProvider' data).
+ *
+ * This basic hint provider is not context-aware and returns the same value hints regardless of the
+ * yaml context.
+ *
+ * This hint provider doesn't provide 'property' hints because property hints typically require
+ * context information (i.e the type of the parent context).
+ *
+ * To make this provider 'context aware' it can be wrapped in an adapter created by calling
+ * one of the static methods in the {@link HintProviders} class.
+ *
+ * @author Kris De Volder
+ */
+public class BasicHintProvider implements HintProvider {
+
+ private IJavaProject javaProject;
+ private ImmutableList valueHints;
+ private ValueProviderStrategy valueProvider;
+
+ public BasicHintProvider(IJavaProject javaProject,
+ ImmutableList valueHints,
+ ValueProviderStrategy valueProvider) {
+ this.javaProject = javaProject;
+ this.valueHints = valueHints;
+ this.valueProvider = valueProvider;
+ }
+
+ @Override
+ public HintProvider traverse(YamlPathSegment s) throws Exception {
+ //since this provider is not context sensitive it just returns itself (So hints provides in 'sub-contexts'
+ // are exaclty the same as hints in the parent context.
+ return this;
+ }
+
+ @Override
+ public List getValueHints(String query) {
+ Builder builder = ImmutableList.builder();
+ if (CollectionUtil.hasElements(valueHints)) {
+ for (ValueHint hint : valueHints) {
+ builder.add(StsValueHint.create(hint));
+ }
+ }
+ if (valueProvider!=null) {
+ Collection provided = valueProvider.getValuesNow(javaProject, query);
+ if (CollectionUtil.hasElements(provided)) {
+ builder.addAll(provided);
+ }
+ }
+ return builder.build();
+ }
+
+ @Override
+ public List getPropertyHints(String query) {
+ return ImmutableList.of();
+ }
+
+
+}
diff --git a/vscode-extensions/commons/application-properties-metadata/src/main/java/org/springframework/ide/vscode/application/properties/metadata/hints/HintProvider.java b/vscode-extensions/commons/application-properties-metadata/src/main/java/org/springframework/ide/vscode/application/properties/metadata/hints/HintProvider.java
new file mode 100644
index 000000000..4613057d5
--- /dev/null
+++ b/vscode-extensions/commons/application-properties-metadata/src/main/java/org/springframework/ide/vscode/application/properties/metadata/hints/HintProvider.java
@@ -0,0 +1,24 @@
+/*******************************************************************************
+ * Copyright (c) 2016 Pivotal, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Pivotal, Inc. - initial API and implementation
+ *******************************************************************************/
+package org.springframework.ide.vscode.application.properties.metadata.hints;
+
+import java.util.List;
+
+import org.springframework.ide.vscode.application.properties.metadata.types.TypedProperty;
+import org.springframework.ide.vscode.commons.yaml.path.YamlNavigable;
+
+/**
+ * @author Kris De Volder
+ */
+public interface HintProvider extends YamlNavigable {
+ List getValueHints(String query);
+ List getPropertyHints(String query);
+}
diff --git a/vscode-extensions/commons/application-properties-metadata/src/main/java/org/springframework/ide/vscode/application/properties/metadata/hints/HintProviders.java b/vscode-extensions/commons/application-properties-metadata/src/main/java/org/springframework/ide/vscode/application/properties/metadata/hints/HintProviders.java
new file mode 100644
index 000000000..897e55c67
--- /dev/null
+++ b/vscode-extensions/commons/application-properties-metadata/src/main/java/org/springframework/ide/vscode/application/properties/metadata/hints/HintProviders.java
@@ -0,0 +1,222 @@
+/*******************************************************************************
+ * Copyright (c) 2016 Pivotal, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Pivotal, Inc. - initial API and implementation
+ *******************************************************************************/
+package org.springframework.ide.vscode.application.properties.metadata.hints;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.springframework.boot.configurationmetadata.ValueHint;
+import org.springframework.ide.vscode.application.properties.metadata.ValueProviderRegistry.ValueProviderStrategy;
+import org.springframework.ide.vscode.application.properties.metadata.types.Type;
+import org.springframework.ide.vscode.application.properties.metadata.types.TypedProperty;
+import org.springframework.ide.vscode.commons.java.IJavaProject;
+import org.springframework.ide.vscode.commons.util.CollectionUtil;
+import org.springframework.ide.vscode.commons.yaml.path.YamlPathSegment;
+
+import com.google.common.collect.ImmutableList;
+
+/**
+ * Methods for creating hints providers that provide hint in specific kind of context.
+ *
+ * @author Kris De Volder
+ */
+public class HintProviders {
+
+ /**
+ * HintProvider that never returns any hints. This should be used
+ * instead of null pointer.
+ */
+ public static final HintProvider NULL = new HintProvider() {
+
+ @Override
+ public HintProvider traverse(YamlPathSegment s) throws Exception {
+ return NULL;
+ }
+
+ @Override
+ public List getValueHints(String query) {
+ return ImmutableList.of();
+ }
+
+ @Override
+ public List getPropertyHints(String query) {
+ return ImmutableList.of();
+ }
+ };
+
+ /**
+ * Creates a non-context-aware hint provider. Typically a hint provider is created by composing the result of
+ * this with one or more of the other methods in this class to wrap the basic provider so it becomes context-aware.
+ */
+ public static HintProvider basic(IJavaProject jp, final ImmutableList valueHints, final ValueProviderStrategy valueProvider) {
+ if (!CollectionUtil.hasElements(valueHints) && valueProvider==null) {
+ return NULL;
+ }
+ return new BasicHintProvider(jp, valueHints, valueProvider);
+ }
+
+ /**
+ * Create a hint provider that will return the given hints in the context following
+ * a traversal that goes down into a 'domain of' context a given number of times.
+ */
+ public static HintProvider forDomainAt(final HintProvider valueHints, final int dim) {
+ if (isNull(valueHints)) {
+ return NULL;
+ }
+ if (dim==0) {
+ return forHere(valueHints);
+ }
+ return new HintProvider() {
+ public HintProvider traverse(YamlPathSegment s) throws Exception {
+ switch (s.getType()) {
+ case VAL_AT_INDEX:
+ case VAL_AT_KEY:
+ return forDomainAt(valueHints, dim-1);
+ default:
+ return NULL;
+ }
+ }
+
+ public List getValueHints(String query) {
+ return ImmutableList.of();
+ }
+
+ @Override
+ public List getPropertyHints(String query) {
+ return ImmutableList.of();
+ }
+ };
+ }
+
+ /**
+ * Only returns the given hints in this context but not one of its 'sub contexts'.
+ */
+ public static HintProvider forHere(final HintProvider valueHints) {
+ if (isNull(valueHints)) {
+ return NULL;
+ }
+ return new HintProvider() {
+
+ @Override
+ public HintProvider traverse(YamlPathSegment s) throws Exception {
+ return NULL;
+ }
+
+ @Override
+ public List getValueHints(String query) {
+ return valueHints.getValueHints(query);
+ }
+
+ @Override
+ public List getPropertyHints(String query) {
+ return ImmutableList.of();
+ }
+ };
+ }
+
+ /**
+ * REturns the given hints in this context and any of its subcontexts that expect values.
+ */
+ public static HintProvider forAllValueContexts(final HintProvider valueProvider) {
+ if (isNull(valueProvider)) {
+ return NULL;
+ }
+ return new HintProvider() {
+ @Override
+ public HintProvider traverse(YamlPathSegment s) throws Exception {
+ switch (s.getType()) {
+ case VAL_AT_INDEX:
+ case VAL_AT_KEY:
+ return this;
+ default:
+ return NULL;
+ }
+ }
+
+ @Override
+ public List getValueHints(String query) {
+ return valueProvider.getValueHints(query);
+ }
+
+ @Override
+ public List getPropertyHints(String query) {
+ return ImmutableList.of();
+ }
+ };
+ }
+
+ public static boolean isNull(HintProvider p) {
+ //If everyone is nice and doesn't ever use null pointers then the p==null check is
+ // not needed. But just in case.
+ return p == NULL || p==null;
+ }
+
+ public static HintProvider forMap(HintProvider _keyProvider, HintProvider _valueProvider, final Type valueType, final boolean dimensionAware) {
+ final HintProvider keyProvider = notNull(_keyProvider);
+ final HintProvider valueProvider = notNull(_valueProvider);
+ if (isNull(keyProvider) && isNull(valueProvider)) {
+ return NULL;
+ }
+ return new HintProvider() {
+
+ @Override
+ public HintProvider traverse(YamlPathSegment s) throws Exception {
+ switch (s.getType()) {
+ case VAL_AT_INDEX:
+ case VAL_AT_KEY:
+ if (dimensionAware) {
+ return forHere(valueProvider);
+ } else {
+ return forAllValueContexts(valueProvider);
+ }
+ default:
+ return NULL;
+ }
+ }
+
+ @Override
+ public List getValueHints(String query) {
+ if (dimensionAware) {
+ //pickier, completions only suggested in the domain of map, but not for map itself.
+ return ImmutableList.of();
+ } else {
+ return valueProvider.getValueHints(query);
+ }
+ }
+
+ @Override
+ public List getPropertyHints(String query) {
+ List keyHints = keyProvider.getValueHints(query);
+ if (CollectionUtil.hasElements(keyHints)) {
+ List props = new ArrayList<>(keyHints.size());
+ for (StsValueHint keyHint : keyHints) {
+ Object key = keyHint.getValue();
+ if (key instanceof String) {
+ props.add(new TypedProperty((String)key, valueType, null));
+ }
+ }
+ return props;
+ }
+ return ImmutableList.of();
+ }
+ };
+ }
+
+ /**
+ * Protection against bad code passing us null pointers.
+ */
+ private static HintProvider notNull(HintProvider p) {
+ if (p==null) {
+ return NULL;
+ }
+ return p;
+ }
+}
diff --git a/vscode-extensions/commons/application-properties-metadata/src/main/java/org/springframework/ide/vscode/application/properties/metadata/types/StsValueHint.java b/vscode-extensions/commons/application-properties-metadata/src/main/java/org/springframework/ide/vscode/application/properties/metadata/hints/StsValueHint.java
similarity index 97%
rename from vscode-extensions/commons/application-properties-metadata/src/main/java/org/springframework/ide/vscode/application/properties/metadata/types/StsValueHint.java
rename to vscode-extensions/commons/application-properties-metadata/src/main/java/org/springframework/ide/vscode/application/properties/metadata/hints/StsValueHint.java
index cd325ad4a..7d5909824 100644
--- a/vscode-extensions/commons/application-properties-metadata/src/main/java/org/springframework/ide/vscode/application/properties/metadata/types/StsValueHint.java
+++ b/vscode-extensions/commons/application-properties-metadata/src/main/java/org/springframework/ide/vscode/application/properties/metadata/hints/StsValueHint.java
@@ -1,4 +1,4 @@
-package org.springframework.ide.vscode.application.properties.metadata.types;
+package org.springframework.ide.vscode.application.properties.metadata.hints;
import static org.springframework.ide.vscode.application.properties.metadata.util.DeprecationUtil.*;
@@ -6,6 +6,7 @@ import javax.inject.Provider;
import org.springframework.boot.configurationmetadata.Deprecation;
import org.springframework.boot.configurationmetadata.ValueHint;
+import org.springframework.ide.vscode.application.properties.metadata.types.TypeUtil;
import org.springframework.ide.vscode.application.properties.metadata.util.DeprecationUtil;
import org.springframework.ide.vscode.commons.java.IJavaElement;
import org.springframework.ide.vscode.commons.java.IJavaProject;
diff --git a/vscode-extensions/commons/application-properties-metadata/src/main/java/org/springframework/ide/vscode/application/properties/metadata/hints/ValueHintHoverInfo.java b/vscode-extensions/commons/application-properties-metadata/src/main/java/org/springframework/ide/vscode/application/properties/metadata/hints/ValueHintHoverInfo.java
new file mode 100644
index 000000000..3bfb87b07
--- /dev/null
+++ b/vscode-extensions/commons/application-properties-metadata/src/main/java/org/springframework/ide/vscode/application/properties/metadata/hints/ValueHintHoverInfo.java
@@ -0,0 +1,9 @@
+package org.springframework.ide.vscode.application.properties.metadata.hints;
+
+public class ValueHintHoverInfo {
+
+ public ValueHintHoverInfo(StsValueHint hint) {
+ // TODO Auto-generated constructor stub
+ }
+
+}
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 5b1abb140..62a6950ee 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
@@ -27,6 +27,7 @@ import javax.inject.Provider;
import org.springframework.boot.configurationmetadata.Deprecation;
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;
import org.springframework.ide.vscode.commons.java.Flags;
import org.springframework.ide.vscode.commons.java.IField;
diff --git a/vscode-extensions/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/completion/DocumentEdits.java b/vscode-extensions/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/completion/DocumentEdits.java
index 876b7b720..5a667bba7 100644
--- a/vscode-extensions/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/completion/DocumentEdits.java
+++ b/vscode-extensions/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/completion/DocumentEdits.java
@@ -16,6 +16,7 @@ import org.springframework.ide.vscode.commons.languageserver.util.BadLocationExc
import org.springframework.ide.vscode.commons.languageserver.util.IDocument;
import org.springframework.ide.vscode.commons.languageserver.util.IRegion;
import org.springframework.ide.vscode.commons.languageserver.util.Region;
+import org.springframework.ide.vscode.commons.languageserver.util.TextDocument;
import org.springframework.ide.vscode.commons.util.Assert;
import io.typefox.lsapi.TextEdit;
@@ -322,12 +323,12 @@ public class DocumentEdits implements ProposalApplier {
return null;
}
- public TextReplace asReplacement(IDocument doc) throws BadLocationException {
+ public TextReplace asReplacement(TextDocument doc) throws BadLocationException {
if (!edits.isEmpty()) {
int start = edits.stream().mapToInt(Edit::getStart).min().getAsInt();
int end = edits.stream().mapToInt(Edit::getEnd).max().getAsInt();
- DocumentState state = new DocumentState(doc);
+ DocumentState state = new DocumentState(doc.copy());
for (Edit edit : edits) {
edit.apply(state);
}
diff --git a/vscode-extensions/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/completion/ScoreableProposal.java b/vscode-extensions/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/completion/ScoreableProposal.java
new file mode 100644
index 000000000..95eaa314d
--- /dev/null
+++ b/vscode-extensions/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/completion/ScoreableProposal.java
@@ -0,0 +1,105 @@
+package org.springframework.ide.vscode.commons.languageserver.completion;
+
+import java.util.Comparator;
+
+public abstract class ScoreableProposal implements ICompletionProposal {
+ private static final double DEEMP_VALUE = 100000; // should be large enough to move deemphasized stuff to bottom of list.
+
+ private double deemphasizedBy = 0.0;
+
+ /**
+ * A sorter suitable for sorting ScoreableProposals based on their score.
+ */
+ public static final Comparator COMPARATOR = new Comparator() {
+ public int compare(ICompletionProposal p1, ICompletionProposal p2) {
+ if (p1 instanceof ScoreableProposal && p2 instanceof ScoreableProposal) {
+ double s1 = ((ScoreableProposal)p1).getScore();
+ double s2 = ((ScoreableProposal)p2).getScore();
+ if (s1==s2) {
+ String name1 = ((ScoreableProposal)p1).getLabel();
+ String name2 = ((ScoreableProposal)p2).getLabel();
+ return name1.compareTo(name2);
+ } else {
+ return Double.compare(s2, s1);
+ }
+ }
+ return 0;
+ }
+ };
+ public abstract double getBaseScore();
+ public final double getScore() {
+ return getBaseScore() - deemphasizedBy;
+ }
+ public ScoreableProposal deemphasize() {
+ deemphasizedBy+= DEEMP_VALUE;
+ return this;
+ }
+ public boolean isDeemphasized() {
+ return deemphasizedBy > 0;
+ }
+
+// @Override
+// public boolean isAutoInsertable() {
+// return !isDeemphasized();
+// }
+
+// public StyledString getStyledDisplayString() {
+// StyledString result = new StyledString();
+// highlightPattern(getHighlightPattern(), getBaseDisplayString(), result);
+// return result;
+// }
+
+// private void highlightPattern(String pattern, String data, StyledString result) {
+// Styler highlightStyle = CompletionFactory.HIGHLIGHT;
+// Styler plainStyle = isDeemphasized()?CompletionFactory.DEEMPHASIZE:CompletionFactory.NULL_STYLER;
+// if (isDeprecated()) {
+// highlightStyle = CompletionFactory.compose(highlightStyle, CompletionFactory.DEPRECATE);
+// plainStyle = CompletionFactory.compose(plainStyle, CompletionFactory.DEPRECATE);
+// }
+// if (StringUtils.hasText(pattern)) {
+// int dataPos = 0; int dataLen = data.length();
+// int patternPos = 0; int patternLen = pattern.length();
+//
+// while (dataPos completions = new ArrayList<>(engine.getCompletions(doc, offset));
- Collections.sort(completions, DefaultCompletionFactory.COMPARATOR);
+ Collections.sort(completions, ScoreableProposal.COMPARATOR);
CompletionListImpl list = new CompletionListImpl();
list.setIncomplete(false);
List items = new ArrayList<>(completions.size());
SortKeys sortkeys = new SortKeys();
+ int count = 0;
for (ICompletionProposal c : completions) {
+ count++;
+ if (count>MAX_COMPLETIONS) {
+ list.setIncomplete(true);
+ break;
+ }
try {
items.add(adaptItem(doc, c, sortkeys));
} catch (Exception e) {
@@ -105,7 +110,7 @@ public class VscodeCompletionEngineAdapter implements VscodeCompletionEngine {
//Vscode applies some magic indent to a multi-line edit text. We do everything ourself so we have adjust for the magic
// and do some kind of 'inverse magic' here.
int vscodeMagicIndent = start.getCharacter();
- return YamlStructureParser.stripIndentation(vscodeMagicIndent, newText);
+ return StringUtil.stripIndentation(vscodeMagicIndent, newText);
}
@Override
@@ -115,5 +120,4 @@ public class VscodeCompletionEngineAdapter implements VscodeCompletionEngine {
//The tricky part is that we have to probably remember infos about the unresolved elements somehow so we can resolve later.
return Futures.of(unresolved);
}
-
}
diff --git a/vscode-extensions/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/hover/HoverInfo.java b/vscode-extensions/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/hover/HoverInfo.java
new file mode 100644
index 000000000..3673eb44a
--- /dev/null
+++ b/vscode-extensions/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/hover/HoverInfo.java
@@ -0,0 +1,8 @@
+package org.springframework.ide.vscode.commons.languageserver.hover;
+
+/**
+ * Placeholder. Still need to figure out what exactly we should do with this in vscode.
+ */
+public interface HoverInfo {
+
+}
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 686413344..29eeaa5c8 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
@@ -133,6 +133,7 @@ public class SimpleTextDocumentService implements TextDocumentService {
@Override
public void didClose(DidCloseTextDocumentParams params) {
+ System.out.println("closing: "+params.getTextDocument().getUri());
String url = params.getTextDocument().getUri();
if (url!=null) {
documents.remove(url);
diff --git a/vscode-extensions/vscode-manifest-yaml/src/main/java/org/springframework/ide/vscode/manifest/yaml/SortKeys.java b/vscode-extensions/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/util/SortKeys.java
similarity index 89%
rename from vscode-extensions/vscode-manifest-yaml/src/main/java/org/springframework/ide/vscode/manifest/yaml/SortKeys.java
rename to vscode-extensions/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/util/SortKeys.java
index 80c3e782d..7cf2128d0 100644
--- a/vscode-extensions/vscode-manifest-yaml/src/main/java/org/springframework/ide/vscode/manifest/yaml/SortKeys.java
+++ b/vscode-extensions/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/util/SortKeys.java
@@ -1,4 +1,4 @@
-package org.springframework.ide.vscode.manifest.yaml;
+package org.springframework.ide.vscode.commons.languageserver.util;
import java.util.Iterator;
diff --git a/vscode-extensions/commons/commons-util/src/main/java/org/springframework/ide/vscode/commons/util/StringUtil.java b/vscode-extensions/commons/commons-util/src/main/java/org/springframework/ide/vscode/commons/util/StringUtil.java
index 7583d37a1..ff14493f8 100644
--- a/vscode-extensions/commons/commons-util/src/main/java/org/springframework/ide/vscode/commons/util/StringUtil.java
+++ b/vscode-extensions/commons/commons-util/src/main/java/org/springframework/ide/vscode/commons/util/StringUtil.java
@@ -131,4 +131,48 @@ public class StringUtil {
return f.format(d);
}
+ private static final Pattern NEWLINE = Pattern.compile("(\\n|\\r)+");
+
+ /**
+ * Removes a given number of spaces from all lines of text in a String,
+ * except for the first line.
+ *
+ * Note: this method only deals with spaces its not suitable for strings
+ * which use tabs for indentation.
+ */
+ public static String stripIndentation(int indent, String indentedText) {
+ StringBuilder out = new StringBuilder();
+ boolean first = true;
+ Matcher matcher = NEWLINE.matcher(indentedText);
+ int pos = 0;
+ while (matcher.find()) {
+ int newline = matcher.start();
+ int newline_end = matcher.end();
+ String line = indentedText.substring(pos, newline);
+ if (first) {
+ first = false;
+ } else {
+ line = stripIndentationFromLine(indent, line);
+ }
+ out.append(line);
+ out.append(indentedText.substring(newline, newline_end));
+ pos = newline_end;
+ }
+ String line = indentedText.substring(pos);
+ if (!first) {
+ line = stripIndentationFromLine(indent, line);
+ }
+ out.append(line);
+ return out.toString();
+ }
+
+ public static String stripIndentationFromLine(int indent, String line) {
+ int start = 0;
+ while (start COMPARATOR = new Comparator() {
- public int compare(ICompletionProposal p1, ICompletionProposal p2) {
- if (p1 instanceof ScoreableProposal && p2 instanceof ScoreableProposal) {
- double s1 = ((ScoreableProposal)p1).getScore();
- double s2 = ((ScoreableProposal)p2).getScore();
- if (s1==s2) {
- String name1 = ((ScoreableProposal)p1).getLabel();
- String name2 = ((ScoreableProposal)p2).getLabel();
- return name1.compareTo(name2);
- } else {
- return Double.compare(s2, s1);
- }
- }
- return 0;
- }
- };
-
-
- public static abstract class ScoreableProposal implements ICompletionProposal {
- private static final double DEEMP_VALUE = 100000; // should be large enough to move deemphasized stuff to bottom of list.
-
- private double deemphasizedBy = 0.0;
- public abstract double getBaseScore();
- public final double getScore() {
- return getBaseScore() - deemphasizedBy;
- }
- public ScoreableProposal deemphasize() {
- deemphasizedBy+= DEEMP_VALUE;
- return this;
- }
- public boolean isDeemphasized() {
- return deemphasizedBy > 0;
- }
-
-// @Override
-// public boolean isAutoInsertable() {
-// return !isDeemphasized();
-// }
-
-// public StyledString getStyledDisplayString() {
-// StyledString result = new StyledString();
-// highlightPattern(getHighlightPattern(), getBaseDisplayString(), result);
-// return result;
-// }
-
-// private void highlightPattern(String pattern, String data, StyledString result) {
-// Styler highlightStyle = CompletionFactory.HIGHLIGHT;
-// Styler plainStyle = isDeemphasized()?CompletionFactory.DEEMPHASIZE:CompletionFactory.NULL_STYLER;
-// if (isDeprecated()) {
-// highlightStyle = CompletionFactory.compose(highlightStyle, CompletionFactory.DEPRECATE);
-// plainStyle = CompletionFactory.compose(plainStyle, CompletionFactory.DEPRECATE);
-// }
-// if (StringUtils.hasText(pattern)) {
-// int dataPos = 0; int dataLen = data.length();
-// int patternPos = 0; int patternLen = pattern.length();
-//
-// while (dataPos0) {
- return stripIndentation(indent, indentedText);
+ return StringUtil.stripIndentation(indent, indentedText);
}
return indentedText;
}
@@ -702,39 +701,4 @@ public class YamlStructureParser {
return keyAliases.getKeyAliases(key);
}
- public static String stripIndentation(int indent, String indentedText) {
- StringBuilder out = new StringBuilder();
- Pattern NEWLINE = Pattern.compile("(\\n|\\r)+");
- boolean first = true;
- Matcher matcher = NEWLINE.matcher(indentedText);
- int pos = 0;
- while (matcher.find()) {
- int newline = matcher.start();
- int newline_end = matcher.end();
- String line = indentedText.substring(pos, newline);
- if (first) {
- first = false;
- } else {
- line = stripIndentationFromLine(indent, line);
- }
- out.append(line);
- out.append(indentedText.substring(newline, newline_end));
- pos = newline_end;
- }
- String line = indentedText.substring(pos);
- if (!first) {
- line = stripIndentationFromLine(indent, line);
- }
- out.append(line);
- return out.toString();
- }
-
- private static String stripIndentationFromLine(int indent, String line) {
- int start = 0;
- while (start completions = editor.getCompletions();
+ assertNotNull(completions);
+ assertFalse(completions.isEmpty());
CompletionItem completion = editor.getFirstCompletion();
editor.apply(completion);
assertEquals(expectTextAfter, editor.getText());
diff --git a/vscode-extensions/commons/properties-editor-test-harness/src/main/java/org/springframework/ide/vscode/properties/editor/test/harness/AbstractPropsEditorTest.java b/vscode-extensions/commons/properties-editor-test-harness/src/main/java/org/springframework/ide/vscode/properties/editor/test/harness/AbstractPropsEditorTest.java
index 6c1751821..15a4813f6 100644
--- a/vscode-extensions/commons/properties-editor-test-harness/src/main/java/org/springframework/ide/vscode/properties/editor/test/harness/AbstractPropsEditorTest.java
+++ b/vscode-extensions/commons/properties-editor-test-harness/src/main/java/org/springframework/ide/vscode/properties/editor/test/harness/AbstractPropsEditorTest.java
@@ -14,6 +14,7 @@ import org.springframework.ide.vscode.application.properties.metadata.SpringProp
import org.springframework.ide.vscode.application.properties.metadata.types.TypeUtil;
import org.springframework.ide.vscode.application.properties.metadata.types.TypeUtilProvider;
import org.springframework.ide.vscode.commons.java.IJavaProject;
+import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder;
import org.springframework.ide.vscode.commons.languageserver.util.IDocument;
import org.springframework.ide.vscode.commons.languageserver.util.SimpleLanguageServer;
import org.springframework.ide.vscode.commons.maven.java.MavenJavaProject;
@@ -32,6 +33,8 @@ public abstract class AbstractPropsEditorTest {
private ProjectsHarness projects = ProjectsHarness.INSTANCE;
protected PropertyIndexHarness md;
+ protected final JavaProjectFinder javaProjectFinder = (doc) -> getTestProject();
+
private LanguageServerHarness harness;
private IJavaProject testProject;
private TypeUtil typeUtil;
@@ -47,6 +50,10 @@ public abstract class AbstractPropsEditorTest {
return harness.newEditor(contents);
}
+ private IJavaProject getTestProject() {
+ return testProject;
+ }
+
@Before
public void setup() throws Exception {
md = new PropertyIndexHarness();
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 f26f2ae5f..0f81bb463 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
@@ -24,6 +24,7 @@ import org.springframework.ide.vscode.application.properties.metadata.DefaultSpr
import org.springframework.ide.vscode.application.properties.metadata.SpringPropertyIndexProvider;
import org.springframework.ide.vscode.application.properties.metadata.types.TypeUtil;
import org.springframework.ide.vscode.application.properties.metadata.types.TypeUtilProvider;
+import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder;
import org.springframework.ide.vscode.commons.languageserver.util.IDocument;
import org.springframework.ide.vscode.commons.languageserver.util.LoggingFormat;
@@ -130,9 +131,9 @@ public class Main {
* When the request stream is closed, wait for 5s for all outstanding responses to compute, then return.
*/
public static void run(Connection connection) {
- SpringPropertyIndexProvider indexProvider = new DefaultSpringPropertyIndexProvider();
- TypeUtil typeUtil = new TypeUtil(null);
- TypeUtilProvider typeUtilProvider = (IDocument doc) -> typeUtil;
+ JavaProjectFinder javaProjectFinder = JavaProjectFinder.DEFAULT;
+ SpringPropertyIndexProvider indexProvider = new DefaultSpringPropertyIndexProvider(javaProjectFinder);
+ TypeUtilProvider typeUtilProvider = (IDocument doc) -> new TypeUtil(javaProjectFinder.find(doc));
ApplicationPropertiesLanguageServer server = new ApplicationPropertiesLanguageServer(indexProvider, typeUtilProvider);
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 a8b451889..cbc075b41 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
@@ -1,27 +1,24 @@
package org.springframework.ide.vscode.application.yaml;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.CompletableFuture;
-
import org.springframework.ide.vscode.application.properties.metadata.SpringPropertyIndexProvider;
+import org.springframework.ide.vscode.application.properties.metadata.completions.RelaxedNameConfig;
import org.springframework.ide.vscode.application.properties.metadata.types.TypeUtilProvider;
+import org.springframework.ide.vscode.application.yaml.completions.ApplicationYamlCompletionEngine;
+import org.springframework.ide.vscode.application.yaml.completions.ApplicationYamlStructureProvider;
import org.springframework.ide.vscode.application.yaml.reconcile.ApplicationYamlReconcileEngine;
+import org.springframework.ide.vscode.commons.languageserver.completion.VscodeCompletionEngine;
+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.reconcile.IReconcileEngine;
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;
-import org.springframework.ide.vscode.commons.util.Futures;
import org.springframework.ide.vscode.commons.yaml.ast.YamlASTProvider;
import org.springframework.ide.vscode.commons.yaml.ast.YamlParser;
+import org.springframework.ide.vscode.commons.yaml.completion.YamlCompletionEngine;
import org.yaml.snakeyaml.Yaml;
-import io.typefox.lsapi.CompletionItem;
-import io.typefox.lsapi.CompletionItemKind;
-import io.typefox.lsapi.CompletionList;
import io.typefox.lsapi.TextDocumentSyncKind;
-import io.typefox.lsapi.impl.CompletionItemImpl;
-import io.typefox.lsapi.impl.CompletionListImpl;
import io.typefox.lsapi.impl.CompletionOptionsImpl;
import io.typefox.lsapi.impl.ServerCapabilitiesImpl;
@@ -32,7 +29,7 @@ public class ApplicationYamlLanguageServer extends SimpleLanguageServer {
private SpringPropertyIndexProvider indexProvider;
private TypeUtilProvider typeUtilProvider;
- public ApplicationYamlLanguageServer(SpringPropertyIndexProvider indexProvider, TypeUtilProvider typeUtilProvider) {
+ public ApplicationYamlLanguageServer(SpringPropertyIndexProvider indexProvider, TypeUtilProvider typeUtilProvider, JavaProjectFinder javaProjectFinder) {
this.indexProvider = indexProvider;
this.typeUtilProvider = typeUtilProvider;
SimpleTextDocumentService documents = getTextDocumentService();
@@ -54,54 +51,16 @@ public class ApplicationYamlLanguageServer extends SimpleLanguageServer {
// }
// });
- documents.onCompletion(params -> {
- CompletableFuture promise = new CompletableFuture<>();
- CompletionListImpl completions = new CompletionListImpl();
- completions.setIncomplete(false);
- List items = new ArrayList<>();
- {
-// {
-// label: 'TypeScript',
-// kind: CompletionItemKind.Text,
-// data: 1
-// },
- CompletionItemImpl item = new CompletionItemImpl();
- item.setLabel("TypeScript");
- item.setKind(CompletionItemKind.Text);
- item.setData(1);
- items.add(item);
- }
-
- {
-// {
-// label: 'JavaScript',
-// kind: CompletionItemKind.Text,
-// data: 2
-// }
- CompletionItemImpl item = new CompletionItemImpl();
- item.setLabel("JavaScript");
- item.setKind(CompletionItemKind.Text);
- item.setData(2);
- items.add(item);
- }
- completions.setItems(items);
-
- promise.complete(completions);
- return promise;
- });
-
- documents.onCompletionResolve((_item) -> {
- CompletionItemImpl item = (CompletionItemImpl) _item;
- Object data = item.getData();
- if (Integer.valueOf(1).equals(data)) {
- item.setDetail("TypeScript details");
- item.setDocumentation("TypeScript docs");
- } else {
- item.setDetail("JavaScript details");
- item.setDocumentation("JavaScript docs");
- }
- return Futures.of((CompletionItem)item);
- });
+ YamlCompletionEngine yamlCompletionEngine = ApplicationYamlCompletionEngine.create(
+ indexProvider,
+ javaProjectFinder,
+ ApplicationYamlStructureProvider.INSTANCE,
+ typeUtilProvider,
+ RelaxedNameConfig.COMPLETION_DEFAULTS
+ );
+ VscodeCompletionEngine completionEngine = new VscodeCompletionEngineAdapter(this, yamlCompletionEngine);
+ documents.onCompletion(completionEngine::getCompletions);
+ documents.onCompletionResolve(completionEngine::resolveCompletion);
}
protected IReconcileEngine getReconcileEngine() {
@@ -115,7 +74,7 @@ public class ApplicationYamlLanguageServer extends SimpleLanguageServer {
c.setTextDocumentSync(TextDocumentSyncKind.Full);
CompletionOptionsImpl completionProvider = new CompletionOptionsImpl();
- completionProvider.setResolveProvider(true);
+ completionProvider.setResolveProvider(false);
c.setCompletionProvider(completionProvider);
return c;
diff --git a/vscode-extensions/vscode-application-yaml/src/main/java/org/springframework/ide/vscode/application/yaml/Main.java b/vscode-extensions/vscode-application-yaml/src/main/java/org/springframework/ide/vscode/application/yaml/Main.java
index 970377472..97c853dac 100644
--- a/vscode-extensions/vscode-application-yaml/src/main/java/org/springframework/ide/vscode/application/yaml/Main.java
+++ b/vscode-extensions/vscode-application-yaml/src/main/java/org/springframework/ide/vscode/application/yaml/Main.java
@@ -13,6 +13,7 @@ import org.springframework.ide.vscode.application.properties.metadata.DefaultSpr
import org.springframework.ide.vscode.application.properties.metadata.SpringPropertyIndexProvider;
import org.springframework.ide.vscode.application.properties.metadata.types.TypeUtil;
import org.springframework.ide.vscode.application.properties.metadata.types.TypeUtilProvider;
+import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder;
import org.springframework.ide.vscode.commons.languageserver.util.IDocument;
import org.springframework.ide.vscode.commons.languageserver.util.LoggingFormat;
@@ -83,14 +84,14 @@ public class Main {
* When the request stream is closed, wait for 5s for all outstanding responses to compute, then return.
*/
public static void run(Connection connection) {
- //TODO: proper TypeUtilProvider and IndexProvider that somehow determine classpath that should be
+ JavaProjectFinder javaProjectFinder = JavaProjectFinder.DEFAULT;
+ //TODO: proper TypeUtilProvider and IndexProvider that somehow determine classpath that should be
// in effect for given IDocument and provide TypeUtil or SpringPropertyIndex parsed from that classpath.
// Note that the provider is responsible for doing some kind of sensible caching so that indexes are not
// rebuilt every time the index is being used.
- SpringPropertyIndexProvider indexProvider = new DefaultSpringPropertyIndexProvider();
- TypeUtil typeUtil = new TypeUtil(null);
- TypeUtilProvider typeUtilProvider = (IDocument doc) -> typeUtil;
- ApplicationYamlLanguageServer server = new ApplicationYamlLanguageServer(indexProvider, typeUtilProvider);
+ SpringPropertyIndexProvider indexProvider = new DefaultSpringPropertyIndexProvider(javaProjectFinder);
+ TypeUtilProvider typeUtilProvider = (IDocument doc) -> new TypeUtil(javaProjectFinder.find(doc));
+ ApplicationYamlLanguageServer server = new ApplicationYamlLanguageServer(indexProvider, typeUtilProvider, javaProjectFinder);
LoggingJsonAdapter jsonServer = new LoggingJsonAdapter(server);
jsonServer.setMessageLog(new PrintWriter(System.out));
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
new file mode 100644
index 000000000..5bdbb3fb6
--- /dev/null
+++ b/vscode-extensions/vscode-application-yaml/src/main/java/org/springframework/ide/vscode/application/yaml/completions/ApplicationYamlAssistContext.java
@@ -0,0 +1,509 @@
+/*******************************************************************************
+ * Copyright (c) 2015, 2016 Pivotal, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Pivotal, Inc. - initial API and implementation
+ *******************************************************************************/
+package org.springframework.ide.vscode.application.yaml.completions;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.springframework.ide.vscode.application.properties.metadata.IndexNavigator;
+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.completions.RelaxedNameConfig;
+import org.springframework.ide.vscode.application.properties.metadata.hints.HintProvider;
+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.commons.languageserver.completion.DocumentEdits;
+import org.springframework.ide.vscode.commons.languageserver.completion.ICompletionProposal;
+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;
+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.commons.util.StringUtil;
+import org.springframework.ide.vscode.commons.yaml.completion.AbstractYamlAssistContext;
+import org.springframework.ide.vscode.commons.yaml.completion.TopLevelAssistContext;
+import org.springframework.ide.vscode.commons.yaml.completion.YamlAssistContext;
+import org.springframework.ide.vscode.commons.yaml.completion.YamlPathEdits;
+import org.springframework.ide.vscode.commons.yaml.path.YamlPath;
+import org.springframework.ide.vscode.commons.yaml.path.YamlPathSegment;
+import org.springframework.ide.vscode.commons.yaml.path.YamlPathSegment.YamlPathSegmentType;
+import org.springframework.ide.vscode.commons.yaml.structure.YamlDocument;
+import org.springframework.ide.vscode.commons.yaml.structure.YamlStructureParser.SChildBearingNode;
+import org.springframework.ide.vscode.commons.yaml.structure.YamlStructureParser.SKeyNode;
+import org.springframework.ide.vscode.commons.yaml.structure.YamlStructureParser.SNode;
+import org.springframework.ide.vscode.commons.yaml.util.YamlIndentUtil;
+import org.springframework.ide.vscode.commons.yaml.util.YamlUtil;
+
+/**
+ * Represents a context insied a "application.yml" file relative to which we can provide
+ * content assistance.
+ */
+public abstract class ApplicationYamlAssistContext extends AbstractYamlAssistContext {
+
+ protected final RelaxedNameConfig conf;
+
+// This may prove useful later but we don't need it for now
+ // /**
+ // * AssistContextKind is an classification of the different kinds of
+ // * syntactic context that CA can be invoked from.
+ // */
+ // public static enum Kind {
+ // SKEY_KEY, /* CA called from a SKeyNode and node.isInKey(cursor)==true */
+ // SKEY_VALUE, /* CA called from a SKeyNode and node.isInKey(cursor)==false */
+ // SRAW /* CA called from a SRawNode */
+ // }
+ // protected final Kind contextKind;
+
+ public final TypeUtil typeUtil;
+
+ public ApplicationYamlAssistContext(int documentSelector, YamlPath contextPath, TypeUtil typeUtil, RelaxedNameConfig conf) {
+ super(documentSelector, contextPath);
+ this.typeUtil = typeUtil;
+ this.conf = conf;
+ }
+
+ /**
+ * Computes the text that should be appended at the end of a completion
+ * proposal depending on what type of value is expected.
+ */
+ protected String appendTextFor(Type type) {
+ //Note that proper indentation after each \n" is added automatically
+ //so the strings created here do not need to contain indentation spaces
+ if (TypeUtil.isMap(type)) {
+ //ready to enter nested map key on next line
+ return "\n"+YamlIndentUtil.INDENT_STR;
+ } if (TypeUtil.isSequencable(type)) {
+ //ready to enter sequence element on next line
+ return "\n- ";
+ } else if (typeUtil.isAtomic(type)) {
+ //ready to enter whatever on the same line
+ return " ";
+ } else {
+ //Assume its some kind of pojo bean
+ return "\n"+YamlIndentUtil.INDENT_STR;
+ }
+ }
+
+ /**
+ * @return the type expected at this context, may return null if unknown.
+ */
+ protected abstract Type getType();
+
+ public static ApplicationYamlAssistContext subdocument(int documentSelector, FuzzyMap index, PropertyCompletionFactory completionFactory, TypeUtil typeUtil, RelaxedNameConfig conf) {
+ return new IndexContext(documentSelector, YamlPath.EMPTY, IndexNavigator.with(index), completionFactory, typeUtil, conf);
+ }
+
+ public static YamlAssistContext forPath(YamlPath contextPath, FuzzyMap index, PropertyCompletionFactory completionFactory, TypeUtil typeUtil, RelaxedNameConfig conf) {
+ try {
+ YamlPathSegment documentSelector = contextPath.getSegment(0);
+ if (documentSelector!=null) {
+ contextPath = contextPath.dropFirst(1);
+ YamlAssistContext context = ApplicationYamlAssistContext.subdocument(documentSelector.toIndex(), index, completionFactory, typeUtil, conf);
+ for (YamlPathSegment s : contextPath.getSegments()) {
+ if (context==null) return null;
+ context = context.traverse(s);
+ }
+ return context;
+ }
+ } catch (Exception e) {
+ Log.log(e);
+ }
+ return null;
+ }
+
+ @Override
+ abstract public YamlAssistContext traverse(YamlPathSegment s) throws Exception;
+
+ private static class TypeContext extends ApplicationYamlAssistContext {
+
+ private PropertyCompletionFactory completionFactory;
+ private Type type;
+ private ApplicationYamlAssistContext parent;
+ private HintProvider hints;
+
+ public TypeContext(ApplicationYamlAssistContext parent, YamlPath contextPath, Type type,
+ PropertyCompletionFactory completionFactory, TypeUtil typeUtil, RelaxedNameConfig conf, HintProvider hints) {
+ super(parent.documentSelector, contextPath, typeUtil, conf);
+ this.parent = parent;
+ this.completionFactory = completionFactory;
+ this.type = type;
+ this.hints = hints;
+ }
+
+ private HintProvider getHintProvider() {
+ return hints;
+ }
+
+ @Override
+ public Collection getCompletions(YamlDocument doc, SNode node, int offset) throws Exception {
+ String query = getPrefix(doc, node, offset);
+ EnumCaseMode enumCaseMode = enumCaseMode(query);
+ BeanPropertyNameMode beanMode = conf.getBeanMode();
+ List valueCompletions = getValueCompletions(doc, offset, query, enumCaseMode);
+ if (!valueCompletions.isEmpty()) {
+ return valueCompletions;
+ }
+ return getKeyCompletions(doc, offset, query, enumCaseMode, beanMode);
+ }
+
+ private EnumCaseMode enumCaseMode(String query) {
+ if (query.isEmpty()) {
+ return conf.getEnumMode();
+ } else {
+ return EnumCaseMode.ALIASED; // will match candidates from both lower and original based on what user typed
+ }
+ }
+
+ public List getKeyCompletions(YamlDocument doc, int offset, String query,
+ EnumCaseMode enumCaseMode, BeanPropertyNameMode beanMode) throws Exception {
+ int queryOffset = offset - query.length();
+ List properties = getProperties(query, enumCaseMode, beanMode);
+ if (CollectionUtil.hasElements(properties)) {
+ ArrayList proposals = new ArrayList(properties.size());
+ SNode contextNode = getContextNode(doc);
+ Set definedProps = getDefinedProperties(contextNode);
+ for (TypedProperty p : properties) {
+ String name = p.getName();
+ double score = FuzzyMatcher.matchScore(query, name);
+ if (score!=0) {
+ YamlPath relativePath = YamlPath.fromSimpleProperty(name);
+ YamlPathEdits edits = new YamlPathEdits(doc);
+ if (!definedProps.contains(name)) {
+ //property not yet defined
+ Type type = p.getType();
+ edits.delete(queryOffset, query);
+ edits.createPathInPlace(contextNode, relativePath, queryOffset, appendTextFor(type));
+ proposals.add(completionFactory.beanProperty(doc.getDocument(),
+ contextPath.toPropString(), getType(),
+ query, p, score, edits, typeUtil)
+ );
+ } else {
+ //property already defined
+ // instead of filtering, navigate to the place where its defined.
+ deleteQueryAndLine(doc, query, queryOffset, edits);
+ //Cast to SChildBearingNode cannot fail because otherwise definedProps would be the empty set.
+ edits.createPath((SChildBearingNode) contextNode, relativePath, "");
+ proposals.add(
+ completionFactory.beanProperty(doc.getDocument(),
+ contextPath.toPropString(), getType(),
+ query, p, score, edits, typeUtil)
+ .deemphasize() //deemphasize because it already exists
+ );
+ }
+ }
+ }
+ return proposals;
+ }
+ return Collections.emptyList();
+ }
+
+ protected List getProperties(String query, EnumCaseMode enumCaseMode, BeanPropertyNameMode beanMode) {
+ ArrayList props = new ArrayList<>();
+ List fromType = typeUtil.getProperties(type, enumCaseMode, beanMode);
+ if (CollectionUtil.hasElements(fromType)) {
+ props.addAll(fromType);
+ }
+ HintProvider hints = getHintProvider();
+ if (hints!=null) {
+ List fromHints = hints.getPropertyHints(query);
+ if (CollectionUtil.hasElements(fromHints)) {
+ props.addAll(fromHints);
+ }
+ }
+ return props;
+ }
+
+ private Set getDefinedProperties(SNode contextNode) {
+ try {
+ if (contextNode instanceof SChildBearingNode) {
+ List children = ((SChildBearingNode)contextNode).getChildren();
+ if (CollectionUtil.hasElements(children)) {
+ Set keys = new HashSet(children.size());
+ for (SNode c : children) {
+ if (c instanceof SKeyNode) {
+ keys.add(((SKeyNode) c).getKey());
+ }
+ }
+ return keys;
+ }
+ }
+ } catch (Exception e) {
+ Log.log(e);
+ }
+ return Collections.emptySet();
+ }
+
+ private List getValueCompletions(YamlDocument doc, int offset, String query, EnumCaseMode enumCaseMode) {
+ Collection hints = getHintValues(query, doc, offset, enumCaseMode);
+ if (hints!=null) {
+ ArrayList completions = new ArrayList();
+ for (StsValueHint hint : hints) {
+ String value = hint.getValue();
+ double score = FuzzyMatcher.matchScore(query, value);
+ if (score!=0 && !value.equals(query)) {
+ DocumentEdits edits = new DocumentEdits(doc.getDocument());
+ int valueStart = offset-query.length();
+ edits.delete(valueStart, offset);
+ if (doc.getChar(valueStart-1)==':') {
+ edits.insert(offset, " ");
+ }
+ edits.insert(offset, YamlUtil.stringEscape(value));
+ completions.add(completionFactory.valueProposal(value, query, type, score, edits, new ValueHintHoverInfo(hint)));
+ }
+ }
+ return completions;
+ }
+ return Collections.emptyList();
+ }
+
+// @Override
+// public HoverInfo getValueHoverInfo(YamlDocument doc, DocumentRegion valueRegion) {
+// String value = valueRegion.toString();
+//
+// if (TypeUtil.isClass(type)) {
+// //Special case. We want hovers/hyperlinks even if the class is not a valid hint (as long as it is a class)
+// StsValueHint hint = StsValueHint.className(value.toString(), typeUtil);
+// if (hint!=null) {
+// return new ValueHintHoverInfo(hint);
+// }
+// }
+//
+// Collection hints = getHintValues(value, doc, valueRegion.getEnd(), EnumCaseMode.ALIASED);
+// //The hints where found by fuzzy match so they may not actually match exactly!
+// for (StsValueHint h : hints) {
+// if (value.equals(h.getValue())) {
+// return new ValueHintHoverInfo(h);
+// }
+// }
+// return super.getValueHoverInfo(doc, valueRegion);
+// }
+
+ protected Collection getHintValues(
+ String query,
+ YamlDocument doc, int offset,
+ EnumCaseMode enumCaseMode
+ ) {
+ Collection allHints = new ArrayList<>();
+ {
+ Collection hints = typeUtil.getHintValues(type, query, enumCaseMode);
+ if (CollectionUtil.hasElements(hints)) {
+ allHints.addAll(hints);
+ }
+ }
+ {
+ HintProvider hintProvider = getHintProvider();
+ if (hintProvider!=null) {
+ allHints.addAll(hintProvider.getValueHints(query));
+ }
+ }
+ return allHints;
+ }
+
+ @Override
+ public YamlAssistContext traverse(YamlPathSegment s) {
+ if (s.getType()==YamlPathSegmentType.VAL_AT_KEY) {
+ if (TypeUtil.isSequencable(type) || TypeUtil.isMap(type)) {
+ return contextWith(s, TypeUtil.getDomainType(type));
+ }
+ String key = s.toPropString();
+ Map subproperties = typeUtil.getPropertiesMap(type, EnumCaseMode.ALIASED, BeanPropertyNameMode.ALIASED);
+ if (subproperties!=null) {
+ return contextWith(s, TypedProperty.typeOf(subproperties.get(key)));
+ }
+ } else if (s.getType()==YamlPathSegmentType.VAL_AT_INDEX) {
+ if (TypeUtil.isSequencable(type)) {
+ return contextWith(s, TypeUtil.getDomainType(type));
+ }
+ }
+ return null;
+ }
+
+ private AbstractYamlAssistContext contextWith(YamlPathSegment s, Type nextType) {
+ if (nextType!=null) {
+ return new TypeContext(this, contextPath.append(s), nextType, completionFactory, typeUtil, conf,
+ new YamlPath(s).traverse(hints));
+ }
+ return null;
+ }
+
+
+ @Override
+ public String toString() {
+ return "TypeContext("+contextPath.toPropString()+"::"+type+")";
+ }
+
+
+// @Override
+// public HoverInfo getHoverInfo() {
+// if (parent instanceof IndexContext) {
+// //this context is in fact an 'alias' of its parent, representing the
+// // point in the context hierarchy where a we transition from navigating
+// // the index to navigating type/bean properties
+// return parent.getHoverInfo();
+// } else {
+// return new JavaTypeNavigationHoverInfo(contextPath.toPropString(), contextPath.getBeanPropertyName(), parent.getType(), getType(), typeUtil);
+// }
+// }
+
+ @Override
+ protected Type getType() {
+ return type;
+ }
+
+ }
+
+ private static class IndexContext extends ApplicationYamlAssistContext {
+
+ private IndexNavigator indexNav;
+ PropertyCompletionFactory completionFactory;
+
+ public IndexContext(int documentSelector, YamlPath contextPath, IndexNavigator indexNav,
+ PropertyCompletionFactory completionFactory, TypeUtil typeUtil, RelaxedNameConfig conf) {
+ super(documentSelector, contextPath, typeUtil, conf);
+ this.indexNav = indexNav;
+ this.completionFactory = completionFactory;
+ }
+
+ @Override
+ public Collection getCompletions(YamlDocument doc, SNode node, int offset) throws Exception {
+ String query = getPrefix(doc, node, offset);
+ Collection> matchingProps = indexNav.findMatching(query);
+ if (!matchingProps.isEmpty()) {
+ ArrayList completions = new ArrayList();
+ for (Match match : matchingProps) {
+ DocumentEdits edits = createEdits(doc, offset, query, match);
+ ScoreableProposal completion = completionFactory.property(
+ doc.getDocument(), edits, match, typeUtil
+ );
+ if (getContextRoot(doc).exists(YamlPath.fromProperty(match.data.getId()))) {
+ completion.deemphasize();
+ }
+ completions.add(completion);
+ }
+ return completions;
+ }
+ return Collections.emptyList();
+ }
+
+ protected DocumentEdits createEdits(final YamlDocument file,
+ final int offset, final String query, final Match match)
+ throws Exception {
+ //Edits created lazyly as they are somwehat expensive to compute and mostly
+ // we need only the edits for the one proposal that user picks.
+ return LazyProposalApplier.from(() -> {
+ YamlPathEdits edits = new YamlPathEdits(file);
+
+ int queryOffset = offset-query.length();
+ edits.delete(queryOffset, query);
+
+ YamlPath propertyPath = YamlPath.fromProperty(match.data.getId());
+ YamlPath relativePath = propertyPath.dropFirst(contextPath.size());
+ YamlPathSegment nextSegment = relativePath.getSegment(0);
+ SNode contextNode = getContextNode(file);
+ //To determine if this completion is 'in place' or needs to be inserted
+ // elsewhere in the tree, we check whether a node already exists in our
+ // context. If it doesn't we can create it as any child of the context
+ // so that includes, right at place the user is typing now.
+ SNode existingNode = contextNode.traverse(nextSegment);
+ String appendText = appendTextFor(TypeParser.parse(match.data.getType()));
+ if (existingNode==null) {
+ edits.createPathInPlace(contextNode, relativePath, queryOffset, appendText);
+ } else {
+ String wholeLine = file.getLineTextAtOffset(queryOffset);
+ if (wholeLine.trim().equals(query.trim())) {
+ edits.deleteLineBackwardAtOffset(queryOffset);
+ }
+ edits.createPath(getContextRoot(file), YamlPath.fromProperty(match.data.getId()), appendText);
+ }
+ return edits;
+ });
+ }
+
+ @Override
+ public AbstractYamlAssistContext traverse(YamlPathSegment s) {
+ if (s.getType()==YamlPathSegmentType.VAL_AT_KEY) {
+ String key = s.toPropString();
+ IndexNavigator subIndex = indexNav.selectSubProperty(key);
+ if (subIndex.isEmpty()) {
+ //Nothing found for actual key... maybe its a 'camelCased' alias of real key?
+ String keyAlias = StringUtil.camelCaseToHyphens(key);
+ if (!keyAlias.equals(key)) { // no point checking alias is the same (likely key was not camelCased)
+ IndexNavigator aliasedSubIndex = indexNav.selectSubProperty(keyAlias);
+ if (!aliasedSubIndex.isEmpty()) {
+ subIndex = aliasedSubIndex;
+ }
+ }
+ }
+ if (subIndex.getExtensionCandidate()!=null) {
+ return new IndexContext(documentSelector, contextPath.append(s), subIndex, completionFactory, typeUtil, conf);
+ } else if (subIndex.getExactMatch()!=null) {
+ IndexContext asIndexContext = new IndexContext(documentSelector, contextPath.append(s), subIndex, completionFactory, typeUtil, conf);
+ PropertyInfo prop = subIndex.getExactMatch();
+ return new TypeContext(asIndexContext, contextPath.append(s), TypeParser.parse(prop.getType()), completionFactory, typeUtil, conf, prop.getHints(typeUtil, true));
+ }
+ }
+ //Unsuported navigation => no context for assist
+ return null;
+ }
+
+ @Override
+ public String toString() {
+ return "YamlAssistIndexContext("+indexNav+")";
+ }
+
+ @Override
+ protected Type getType() {
+ PropertyInfo match = indexNav.getExactMatch();
+ if (match!=null) {
+ return TypeParser.parse(match.getType());
+ }
+ return null;
+ }
+
+// @Override
+// public HoverInfo getHoverInfo() {
+// PropertyInfo prop = indexNav.getExactMatch();
+// if (prop!=null) {
+// return new SpringPropertyHoverInfo(typeUtil.getJavaProject(), prop);
+// }
+// return null;
+// }
+ }
+
+// public abstract HoverInfo getHoverInfo();
+// public HoverInfo getHoverInfo(YamlPathSegment s) {
+// //ApplicationYamlAssistContext implements getHoverInfo directly. so this is not needed.
+// return null;
+// }
+
+ public static YamlAssistContext global(final FuzzyMap index, final PropertyCompletionFactory completionFactory, final TypeUtil typeUtil, final RelaxedNameConfig conf) {
+ return new TopLevelAssistContext() {
+ @Override
+ protected YamlAssistContext getDocumentContext(int documentSelector) {
+ return subdocument(documentSelector, index, completionFactory, typeUtil, conf);
+ }
+ };
+ }
+}
diff --git a/vscode-extensions/vscode-application-yaml/src/main/java/org/springframework/ide/vscode/application/yaml/completions/ApplicationYamlCompletionEngine.java b/vscode-extensions/vscode-application-yaml/src/main/java/org/springframework/ide/vscode/application/yaml/completions/ApplicationYamlCompletionEngine.java
new file mode 100644
index 000000000..3d351aac9
--- /dev/null
+++ b/vscode-extensions/vscode-application-yaml/src/main/java/org/springframework/ide/vscode/application/yaml/completions/ApplicationYamlCompletionEngine.java
@@ -0,0 +1,49 @@
+/*******************************************************************************
+ * Copyright (c) 2015 Pivotal, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Pivotal, Inc. - initial API and implementation
+ *******************************************************************************/
+package org.springframework.ide.vscode.application.yaml.completions;
+
+import org.springframework.ide.vscode.application.properties.metadata.PropertyInfo;
+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.completions.RelaxedNameConfig;
+import org.springframework.ide.vscode.application.properties.metadata.types.TypeUtilProvider;
+import org.springframework.ide.vscode.application.properties.metadata.util.FuzzyMap;
+import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder;
+import org.springframework.ide.vscode.commons.languageserver.util.IDocument;
+import org.springframework.ide.vscode.commons.yaml.completion.YamlAssistContext;
+import org.springframework.ide.vscode.commons.yaml.completion.YamlAssistContextProvider;
+import org.springframework.ide.vscode.commons.yaml.completion.YamlCompletionEngine;
+import org.springframework.ide.vscode.commons.yaml.structure.YamlDocument;
+import org.springframework.ide.vscode.commons.yaml.structure.YamlStructureProvider;
+
+/**
+ * @author Kris De Volder
+ */
+public class ApplicationYamlCompletionEngine {
+ public static YamlCompletionEngine create(
+ final SpringPropertyIndexProvider indexProvider,
+ final JavaProjectFinder documentContextFinder,
+ final YamlStructureProvider structureProvider,
+ final TypeUtilProvider typeUtilProvider,
+ final RelaxedNameConfig conf
+ ) {
+ final PropertyCompletionFactory completionFactory = new PropertyCompletionFactory(documentContextFinder);
+ YamlAssistContextProvider contextProvider = new YamlAssistContextProvider() {
+ @Override
+ public YamlAssistContext getGlobalAssistContext(YamlDocument ydoc) {
+ IDocument doc = ydoc.getDocument();
+ FuzzyMap index = indexProvider.getIndex(doc);
+ return ApplicationYamlAssistContext.global(index, completionFactory, typeUtilProvider.getTypeUtil(doc), conf);
+ }
+ };
+ return new YamlCompletionEngine(structureProvider, contextProvider);
+ }
+}
diff --git a/vscode-extensions/vscode-application-yaml/src/main/java/org/springframework/ide/vscode/application/yaml/completions/ApplicationYamlStructureProvider.java b/vscode-extensions/vscode-application-yaml/src/main/java/org/springframework/ide/vscode/application/yaml/completions/ApplicationYamlStructureProvider.java
new file mode 100644
index 000000000..7505635a3
--- /dev/null
+++ b/vscode-extensions/vscode-application-yaml/src/main/java/org/springframework/ide/vscode/application/yaml/completions/ApplicationYamlStructureProvider.java
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * Copyright (c) 2015, 2016 Pivotal, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Pivotal, Inc. - initial API and implementation
+ *******************************************************************************/
+package org.springframework.ide.vscode.application.yaml.completions;
+
+import java.util.Collections;
+
+import org.springframework.ide.vscode.commons.util.StringUtil;
+import org.springframework.ide.vscode.commons.yaml.path.KeyAliases;
+import org.springframework.ide.vscode.commons.yaml.structure.YamlStructureProvider;
+
+public class ApplicationYamlStructureProvider {
+
+ private static final KeyAliases KEY_ALIASES = new KeyAliases() {
+ @Override
+ public Iterable getKeyAliases(String base) {
+ String camelCased = StringUtil.hyphensToCamelCase(base, false);
+ if (!camelCased.equals(base)) {
+ return Collections.singletonList(camelCased);
+ }
+ return Collections.emptyList();
+ }
+ };
+
+ public static final YamlStructureProvider INSTANCE = YamlStructureProvider.withAliases(KEY_ALIASES);
+
+}
diff --git a/vscode-extensions/vscode-application-yaml/src/main/java/org/springframework/ide/vscode/application/yaml/completions/LazyProposalApplier.java b/vscode-extensions/vscode-application-yaml/src/main/java/org/springframework/ide/vscode/application/yaml/completions/LazyProposalApplier.java
new file mode 100644
index 000000000..fc655926e
--- /dev/null
+++ b/vscode-extensions/vscode-application-yaml/src/main/java/org/springframework/ide/vscode/application/yaml/completions/LazyProposalApplier.java
@@ -0,0 +1,21 @@
+package org.springframework.ide.vscode.application.yaml.completions;
+
+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
+ * that the edits are not computed until a completion is being resolved.
+ *
+ * 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/vscode-application-yaml/src/main/java/org/springframework/ide/vscode/application/yaml/ApplicationYamlProblems.java b/vscode-extensions/vscode-application-yaml/src/main/java/org/springframework/ide/vscode/application/yaml/reconcile/ApplicationYamlProblems.java
similarity index 94%
rename from vscode-extensions/vscode-application-yaml/src/main/java/org/springframework/ide/vscode/application/yaml/ApplicationYamlProblems.java
rename to vscode-extensions/vscode-application-yaml/src/main/java/org/springframework/ide/vscode/application/yaml/reconcile/ApplicationYamlProblems.java
index 5436fe9a0..5df78ecef 100644
--- a/vscode-extensions/vscode-application-yaml/src/main/java/org/springframework/ide/vscode/application/yaml/ApplicationYamlProblems.java
+++ b/vscode-extensions/vscode-application-yaml/src/main/java/org/springframework/ide/vscode/application/yaml/reconcile/ApplicationYamlProblems.java
@@ -1,4 +1,4 @@
-package org.springframework.ide.vscode.application.yaml;
+package org.springframework.ide.vscode.application.yaml.reconcile;
import static org.springframework.ide.vscode.commons.languageserver.reconcile.ProblemSeverity.ERROR;
diff --git a/vscode-extensions/vscode-application-yaml/src/main/java/org/springframework/ide/vscode/application/yaml/reconcile/ApplicationYamlReconcileEngine.java b/vscode-extensions/vscode-application-yaml/src/main/java/org/springframework/ide/vscode/application/yaml/reconcile/ApplicationYamlReconcileEngine.java
index 5c82c9350..fc7258adf 100644
--- a/vscode-extensions/vscode-application-yaml/src/main/java/org/springframework/ide/vscode/application/yaml/reconcile/ApplicationYamlReconcileEngine.java
+++ b/vscode-extensions/vscode-application-yaml/src/main/java/org/springframework/ide/vscode/application/yaml/reconcile/ApplicationYamlReconcileEngine.java
@@ -10,14 +10,13 @@
*******************************************************************************/
package org.springframework.ide.vscode.application.yaml.reconcile;
-import static org.springframework.ide.vscode.application.yaml.ApplicationYamlProblems.Type.YAML_SYNTAX_ERROR;
+import static org.springframework.ide.vscode.application.yaml.reconcile.ApplicationYamlProblems.Type.YAML_SYNTAX_ERROR;
import org.springframework.ide.vscode.application.properties.metadata.IndexNavigator;
import org.springframework.ide.vscode.application.properties.metadata.PropertyInfo;
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.metadata.util.FuzzyMap;
-import org.springframework.ide.vscode.application.yaml.ApplicationYamlProblems;
import org.springframework.ide.vscode.commons.languageserver.reconcile.IProblemCollector;
import org.springframework.ide.vscode.commons.languageserver.reconcile.ReconcileProblem;
import org.springframework.ide.vscode.commons.languageserver.util.IDocument;
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 97cf6d76b..0405fa5ba 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
@@ -21,6 +21,7 @@ import org.junit.Test;
import org.springframework.ide.vscode.application.properties.metadata.CachingValueProvider;
import org.springframework.ide.vscode.application.properties.metadata.PropertyInfo;
import org.springframework.ide.vscode.commons.java.IJavaProject;
+import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder;
import org.springframework.ide.vscode.commons.languageserver.util.SimpleLanguageServer;
import org.springframework.ide.vscode.commons.util.StringUtil;
import org.springframework.ide.vscode.languageserver.testharness.Editor;
@@ -41,6 +42,8 @@ public class ApplicationYamlEditorTest extends AbstractPropsEditorTest {
////////////////////////////////////////////////////////////////////////////////////////
+ private JavaProjectFinder javaProjectFinder;
+
@Test public void linterRunsOnDocumentOpenAndChange() throws Exception {
Editor editor = newEditor(
"somemap: val\n"+
@@ -716,7 +719,7 @@ public class ApplicationYamlEditorTest extends AbstractPropsEditorTest {
);
}
- @Ignore @Test public void testContentAssistSimple() throws Exception {
+ @Test public void testContentAssistSimple() throws Exception {
defaultTestData();
assertCompletion("port<*>",
"server:\n"+
@@ -3529,7 +3532,7 @@ public class ApplicationYamlEditorTest extends AbstractPropsEditorTest {
@Override
protected SimpleLanguageServer newLanguageServer() {
- return new ApplicationYamlLanguageServer(md.getIndexProvider(), typeUtilProvider);
+ return new ApplicationYamlLanguageServer(md.getIndexProvider(), typeUtilProvider, javaProjectFinder);
}
}
diff --git a/vscode-extensions/vscode-application-yaml/src/test/java/org/springframework/ide/vscode/application/yaml/ApplicationYamlLanguageServerTests.java b/vscode-extensions/vscode-application-yaml/src/test/java/org/springframework/ide/vscode/application/yaml/ApplicationYamlLanguageServerTests.java
index 883b73ab2..5d6cc2a5e 100644
--- a/vscode-extensions/vscode-application-yaml/src/test/java/org/springframework/ide/vscode/application/yaml/ApplicationYamlLanguageServerTests.java
+++ b/vscode-extensions/vscode-application-yaml/src/test/java/org/springframework/ide/vscode/application/yaml/ApplicationYamlLanguageServerTests.java
@@ -22,7 +22,7 @@ public class ApplicationYamlLanguageServerTests {
}
private LanguageServerHarness newHarness() throws Exception {
- Callable extends LanguageServer> f = () -> new ApplicationYamlLanguageServer((d) -> null, (d) -> null);
+ Callable extends LanguageServer> f = () -> new ApplicationYamlLanguageServer((d) -> null, (d) -> null, (d) -> null);
return new LanguageServerHarness(f);
}
diff --git a/vscode-extensions/vscode-manifest-yaml/src/main/java/org/springframework/ide/vscode/manifest/yaml/ManifestYamlLanguageServer.java b/vscode-extensions/vscode-manifest-yaml/src/main/java/org/springframework/ide/vscode/manifest/yaml/ManifestYamlLanguageServer.java
index 26c4e0845..4fc912c15 100644
--- a/vscode-extensions/vscode-manifest-yaml/src/main/java/org/springframework/ide/vscode/manifest/yaml/ManifestYamlLanguageServer.java
+++ b/vscode-extensions/vscode-manifest-yaml/src/main/java/org/springframework/ide/vscode/manifest/yaml/ManifestYamlLanguageServer.java
@@ -4,6 +4,8 @@ import java.util.Collection;
import javax.inject.Provider;
+import org.springframework.ide.vscode.commons.languageserver.completion.VscodeCompletionEngine;
+import org.springframework.ide.vscode.commons.languageserver.completion.VscodeCompletionEngineAdapter;
import org.springframework.ide.vscode.commons.languageserver.reconcile.IReconcileEngine;
import org.springframework.ide.vscode.commons.languageserver.util.SimpleLanguageServer;
import org.springframework.ide.vscode.commons.languageserver.util.SimpleTextDocumentService;
diff --git a/vscode-extensions/vscode-manifest-yaml/src/test/java/org/springframework/ide/vscode/manifest/yaml/ManifestYamlEditorTest.java b/vscode-extensions/vscode-manifest-yaml/src/test/java/org/springframework/ide/vscode/manifest/yaml/ManifestYamlEditorTest.java
index ed15d4f96..7762209b2 100644
--- a/vscode-extensions/vscode-manifest-yaml/src/test/java/org/springframework/ide/vscode/manifest/yaml/ManifestYamlEditorTest.java
+++ b/vscode-extensions/vscode-manifest-yaml/src/test/java/org/springframework/ide/vscode/manifest/yaml/ManifestYamlEditorTest.java
@@ -13,6 +13,7 @@ package org.springframework.ide.vscode.manifest.yaml;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
+import org.springframework.ide.vscode.commons.languageserver.completion.VscodeCompletionEngineAdapter;
import org.springframework.ide.vscode.languageserver.testharness.Editor;
import org.springframework.ide.vscode.languageserver.testharness.LanguageServerHarness;
import org.springframework.ide.vscode.manifest.yaml.ManifestYamlLanguageServer;