Add 'hoverinfo' to completions in manfest.yml editor
This commit is contained in:
@@ -14,10 +14,18 @@ import org.eclipse.lsp4j.CompletionItemKind;
|
||||
import org.springframework.ide.vscode.commons.languageserver.completion.DocumentEdits;
|
||||
import org.springframework.ide.vscode.commons.languageserver.completion.ScoreableProposal;
|
||||
import org.springframework.ide.vscode.commons.languageserver.util.IDocument;
|
||||
import org.springframework.ide.vscode.commons.util.Renderable;
|
||||
import org.springframework.ide.vscode.commons.yaml.hover.YPropertyHoverInfo;
|
||||
import org.springframework.ide.vscode.commons.yaml.schema.YType;
|
||||
import org.springframework.ide.vscode.commons.yaml.schema.YTypeUtil;
|
||||
|
||||
public abstract class AbstractPropertyProposal extends ScoreableProposal {
|
||||
|
||||
@Override
|
||||
public String getDetail() {
|
||||
return niceTypeName(getType());
|
||||
}
|
||||
|
||||
protected final IDocument fDoc;
|
||||
private final DocumentEdits proposalApplier;
|
||||
private boolean isDeprecated = false;
|
||||
|
||||
@@ -23,11 +23,13 @@ import org.springframework.ide.vscode.commons.languageserver.completion.IComplet
|
||||
import org.springframework.ide.vscode.commons.languageserver.completion.ScoreableProposal;
|
||||
import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder;
|
||||
import org.springframework.ide.vscode.commons.languageserver.util.IDocument;
|
||||
import org.springframework.ide.vscode.commons.util.Renderable;
|
||||
import org.springframework.ide.vscode.commons.yaml.hover.YPropertyHoverInfo;
|
||||
import org.springframework.ide.vscode.commons.yaml.schema.YType;
|
||||
|
||||
public class PropertyCompletionFactory {
|
||||
|
||||
public ICompletionProposal valueProposal(String value, String query, Type type, double score, DocumentEdits edits, ValueHintHoverInfo info) {
|
||||
public ICompletionProposal valueProposal(String value, String query, String niceTypeName, double score, DocumentEdits edits, Renderable info) {
|
||||
return new ScoreableProposal() {
|
||||
|
||||
@Override
|
||||
@@ -49,6 +51,16 @@ public class PropertyCompletionFactory {
|
||||
public double getBaseScore() {
|
||||
return score;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDetail() {
|
||||
return niceTypeName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Renderable getDocumentation() {
|
||||
return info;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -59,17 +71,10 @@ public class PropertyCompletionFactory {
|
||||
public ScoreableProposal beanProperty(IDocument doc, final String contextProperty, final Type contextType, final String pattern, final TypedProperty property, final double score, DocumentEdits applier, final TypeUtil typeUtil) {
|
||||
AbstractPropertyProposal proposal = new AbstractPropertyProposal(doc, applier) {
|
||||
|
||||
// private HoverInfo hoverInfo;
|
||||
|
||||
|
||||
// @Override
|
||||
// public HoverInfo getAdditionalProposalInfo(IProgressMonitor monitor) {
|
||||
// if (hoverInfo==null) {
|
||||
// String prefix = contextProperty==null?"":contextProperty+".";
|
||||
// hoverInfo = new JavaTypeNavigationHoverInfo(prefix+property.getName(), property.getName(), contextType, property.getType(), typeUtil);
|
||||
// }
|
||||
// return hoverInfo;
|
||||
// }
|
||||
@Override
|
||||
public Renderable getDocumentation() {
|
||||
return YPropertyHoverInfo.create(contextProperty, contextType, property);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getBaseDisplayString() {
|
||||
@@ -100,6 +105,7 @@ public class PropertyCompletionFactory {
|
||||
public String getLabel() {
|
||||
return getBaseDisplayString() + " : " + typeUtil.niceTypeName(getType());
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
if (property.isDeprecated()) {
|
||||
@@ -166,6 +172,13 @@ public class PropertyCompletionFactory {
|
||||
public String getLabel() {
|
||||
return getBaseDisplayString() + " : " + typeUtil.niceTypeName(getType());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Renderable getDocumentation() {
|
||||
//TODO: See org.springframework.ide.eclipse.boot.properties.editor.completions.SpringPropertyHoverInfo in old code on how
|
||||
// this used to render docs.
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -105,10 +105,7 @@ public class StsValueHint {
|
||||
public Renderable getDescription() {
|
||||
return description;
|
||||
}
|
||||
public Renderable getDescriptionProvider() {
|
||||
return description;
|
||||
}
|
||||
|
||||
|
||||
private static Renderable javaDocSnippet(IJavaElement je) {
|
||||
return Renderables.lazy(() -> {
|
||||
IJavadoc jdoc = je.getJavaDoc();
|
||||
|
||||
@@ -1,9 +1,22 @@
|
||||
package org.springframework.ide.vscode.application.properties.metadata.hints;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.ide.vscode.commons.util.Renderable;
|
||||
import org.springframework.ide.vscode.commons.util.Renderables;
|
||||
|
||||
import static org.springframework.ide.vscode.commons.util.Renderables.*;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableList.Builder;
|
||||
|
||||
public class ValueHintHoverInfo {
|
||||
|
||||
public ValueHintHoverInfo(StsValueHint hint) {
|
||||
// TODO Auto-generated constructor stub
|
||||
public static Renderable create(StsValueHint hint) {
|
||||
Builder<Renderable> builder = ImmutableList.builder();
|
||||
builder.add(bold(""+hint.getValue()));
|
||||
builder.add(paragraph(hint.getDescription()));
|
||||
return concat(builder.build());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -610,7 +610,7 @@ public class TypeUtil {
|
||||
ArrayList<TypedProperty> properties = new ArrayList<>(keyHints.size());
|
||||
for (StsValueHint hint : keyHints) {
|
||||
String propName = hint.getValue();
|
||||
properties.add(new TypedProperty(propName, valueType, hint.getDescriptionProvider(), hint.getDeprecation()));
|
||||
properties.add(new TypedProperty(propName, valueType, hint.getDescription(), hint.getDeprecation()));
|
||||
}
|
||||
return properties;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package org.springframework.ide.vscode.commons.languageserver.completion;
|
||||
|
||||
import org.eclipse.lsp4j.CompletionItemKind;
|
||||
import org.springframework.ide.vscode.commons.util.Renderable;
|
||||
|
||||
/**
|
||||
* Replaces STS/Eclipse's ICompletionProposal
|
||||
@@ -16,4 +17,7 @@ public interface ICompletionProposal {
|
||||
CompletionItemKind getKind();
|
||||
DocumentEdits getTextEdit();
|
||||
|
||||
String getDetail();
|
||||
Renderable getDocumentation();
|
||||
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ import org.springframework.ide.vscode.commons.languageserver.util.SimpleTextDocu
|
||||
import org.springframework.ide.vscode.commons.languageserver.util.SortKeys;
|
||||
import org.springframework.ide.vscode.commons.languageserver.util.TextDocument;
|
||||
import org.springframework.ide.vscode.commons.util.Futures;
|
||||
import org.springframework.ide.vscode.commons.util.Renderable;
|
||||
import org.springframework.ide.vscode.commons.util.StringUtil;
|
||||
|
||||
import reactor.core.publisher.Mono;
|
||||
@@ -94,10 +95,19 @@ public class VscodeCompletionEngineAdapter implements VscodeCompletionEngine {
|
||||
item.setKind(completion.getKind());
|
||||
item.setSortText(sortkeys.next());
|
||||
item.setFilterText(completion.getLabel());
|
||||
item.setDetail(completion.getDetail());
|
||||
item.setDocumentation(toMarkdown(completion.getDocumentation()));
|
||||
adaptEdits(item, doc, completion.getTextEdit());
|
||||
return item;
|
||||
}
|
||||
|
||||
private String toMarkdown(Renderable r) {
|
||||
if (r!=null) {
|
||||
return r.toMarkdown();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void adaptEdits(CompletionItem item, TextDocument doc, DocumentEdits edits) throws Exception {
|
||||
TextReplace replaceEdit = edits.asReplacement(doc);
|
||||
if (replaceEdit==null) {
|
||||
|
||||
@@ -101,6 +101,13 @@ public class Renderables {
|
||||
|
||||
@Override
|
||||
public void renderAsMarkdown(StringBuilder buffer) {
|
||||
//TODO: This looks wrong. A paragraphs in markdown are created
|
||||
// by separating the text between them with TWO newlines. So this isn't
|
||||
// quite rigth as it provides no guarantees that there will be
|
||||
// two newlines before or after the paragraph's text.
|
||||
// The correct implementation should probably check wether text in buffer already
|
||||
// ends with newline(s) and add more only if needed. Then it should
|
||||
// also append double newline at its end.
|
||||
buffer.append("\n");
|
||||
text.renderAsMarkdown(buffer);
|
||||
buffer.append("\n");
|
||||
@@ -179,6 +186,10 @@ public class Renderables {
|
||||
};
|
||||
}
|
||||
|
||||
public static Renderable bold(String text) {
|
||||
return bold(text(text));
|
||||
}
|
||||
|
||||
public static Renderable bold(Renderable text) {
|
||||
|
||||
return new Renderable() {
|
||||
|
||||
@@ -12,6 +12,6 @@ public interface CompletionFactory {
|
||||
CompletionFactory DEFAULT = new DefaultCompletionFactory();
|
||||
|
||||
ICompletionProposal beanProperty(IDocument doc, String contextProperty, YType contextType, String query, YTypedProperty p, double score, DocumentEdits edits, YTypeUtil typeUtil);
|
||||
ICompletionProposal valueProposal(String value, String query, String label, YType type, double score, DocumentEdits edits);
|
||||
ICompletionProposal valueProposal(String value, String query, String label, YType type, double score, DocumentEdits edits, YTypeUtil typeUtil);
|
||||
|
||||
}
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
package org.springframework.ide.vscode.commons.yaml.completion;
|
||||
|
||||
import org.apache.commons.lang3.reflect.TypeUtils;
|
||||
import org.eclipse.lsp4j.CompletionItemKind;
|
||||
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.ScoreableProposal;
|
||||
import org.springframework.ide.vscode.commons.languageserver.util.IDocument;
|
||||
import org.springframework.ide.vscode.commons.util.Renderable;
|
||||
import org.springframework.ide.vscode.commons.yaml.hover.YPropertyHoverInfo;
|
||||
import org.springframework.ide.vscode.commons.yaml.schema.YType;
|
||||
import org.springframework.ide.vscode.commons.yaml.schema.YTypeUtil;
|
||||
import org.springframework.ide.vscode.commons.yaml.schema.YTypedProperty;
|
||||
@@ -53,6 +56,16 @@ public class DefaultCompletionFactory implements CompletionFactory {
|
||||
public DocumentEdits getTextEdit() {
|
||||
return edits;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDetail() {
|
||||
return typeUtil.niceTypeName(p.getType());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Renderable getDocumentation() {
|
||||
return YPropertyHoverInfo.create(contextProperty, contextType, p);
|
||||
}
|
||||
}
|
||||
|
||||
public class ValueProposal extends ScoreableProposal {
|
||||
@@ -63,14 +76,16 @@ public class DefaultCompletionFactory implements CompletionFactory {
|
||||
private YType type;
|
||||
private double baseScore;
|
||||
private DocumentEdits edits;
|
||||
private YTypeUtil typeUtil;
|
||||
|
||||
public ValueProposal(String value, String query, String label, YType type, double score, DocumentEdits edits) {
|
||||
public ValueProposal(String value, String query, String label, YType type, double score, DocumentEdits edits, YTypeUtil typeUtil) {
|
||||
this.value = value;
|
||||
this.query = query;
|
||||
this.label = label;
|
||||
this.type = type;
|
||||
this.baseScore = score;
|
||||
this.edits = edits;
|
||||
this.typeUtil = typeUtil;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -97,6 +112,16 @@ public class DefaultCompletionFactory implements CompletionFactory {
|
||||
public String toString() {
|
||||
return "ValueProposal("+value+")";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDetail() {
|
||||
return typeUtil.niceTypeName(type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Renderable getDocumentation() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -105,8 +130,8 @@ public class DefaultCompletionFactory implements CompletionFactory {
|
||||
}
|
||||
|
||||
@Override
|
||||
public ICompletionProposal valueProposal(String value, String query, String label, YType type, double score, DocumentEdits edits) {
|
||||
return new ValueProposal(value, query, label, type, score, edits);
|
||||
public ICompletionProposal valueProposal(String value, String query, String label, YType type, double score, DocumentEdits edits, YTypeUtil typeUtil) {
|
||||
return new ValueProposal(value, query, label, type, score, edits, typeUtil);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -170,7 +170,7 @@ public class YTypeAssistContext extends AbstractYamlAssistContext {
|
||||
DocumentEdits edits = new DocumentEdits(doc.getDocument());
|
||||
edits.delete(offset-query.length(), offset);
|
||||
edits.insert(offset, value.getValue());
|
||||
completions.add(completionFactory().valueProposal(value.getValue(), query, value.getLabel(), type, score, edits));
|
||||
completions.add(completionFactory().valueProposal(value.getValue(), query, value.getLabel(), type, score, edits, typeUtil));
|
||||
}
|
||||
}
|
||||
return completions;
|
||||
|
||||
@@ -24,8 +24,10 @@ import org.eclipse.lsp4j.PublishDiagnosticsParams;
|
||||
import org.eclipse.lsp4j.Range;
|
||||
import org.eclipse.lsp4j.TextEdit;
|
||||
import org.junit.Assert;
|
||||
import org.springframework.ide.vscode.commons.util.Log;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
import com.google.gson.internal.Streams;
|
||||
|
||||
public class Editor {
|
||||
|
||||
@@ -341,6 +343,22 @@ public class Editor {
|
||||
assertContains(expectSnippet, hover.getContents().toString());
|
||||
}
|
||||
|
||||
public void assertCompletionDetails(String expectLabel, String expectDetail, String expectDocSnippet) throws Exception {
|
||||
CompletionItem it = harness.resolveCompletionItem(assertCompletionWithLabel(expectLabel));
|
||||
if (expectDetail!=null) {
|
||||
assertEquals(expectDetail, it.getDetail());
|
||||
}
|
||||
assertContains(expectDocSnippet, it.getDocumentation());
|
||||
}
|
||||
|
||||
protected CompletionItem assertCompletionWithLabel(String expectLabel) throws Exception {
|
||||
return getCompletions().stream()
|
||||
.filter((item) -> item.getLabel().equals(expectLabel))
|
||||
.findFirst()
|
||||
.get();
|
||||
}
|
||||
|
||||
|
||||
public void setSelection(int start, int end) {
|
||||
Assert.assertTrue(start>=0);
|
||||
Assert.assertTrue(end>=start);
|
||||
|
||||
@@ -252,7 +252,7 @@ public class LanguageServerHarness {
|
||||
}
|
||||
|
||||
|
||||
private CompletionItem resolveCompletionItem(CompletionItem unresolved) {
|
||||
public CompletionItem resolveCompletionItem(CompletionItem unresolved) {
|
||||
try {
|
||||
return server.getTextDocumentService().resolveCompletionItem(unresolved).get();
|
||||
} catch (Exception e) {
|
||||
|
||||
@@ -109,9 +109,14 @@ public abstract class AbstractPropsEditorTest {
|
||||
/**
|
||||
* Checks that completions contains a completion with a given display string and that that completion
|
||||
* has a info hover that contains a given snippet of text.
|
||||
* <p>
|
||||
* Deprecated: use assertCompletionDetails instead and also check add an expected 'detail' text of
|
||||
* completion item.
|
||||
*/
|
||||
@Deprecated
|
||||
public void assertCompletionWithInfoHover(String editorText, String expectLabel, String expectInfoSnippet) throws Exception {
|
||||
notImplemented();
|
||||
Editor editor = newEditor(editorText);
|
||||
editor.assertCompletionDetails(expectLabel, null, expectInfoSnippet);
|
||||
}
|
||||
|
||||
public boolean isEmptyMetadata() {
|
||||
|
||||
@@ -271,8 +271,9 @@ public class PropertiesCompletionProposalsCalculator {
|
||||
DocumentEdits edits = new DocumentEdits(doc);
|
||||
edits.delete(startOfValue, offset);
|
||||
edits.insert(offset, valueCandidate);
|
||||
proposals.add(completionFactory.valueProposal(valueCandidate, query, getValueType(index, typeUtil, propertyName),
|
||||
score, edits, new ValueHintHoverInfo(hint))
|
||||
String valueTypeName = typeUtil.niceTypeName(getValueType(index, typeUtil, propertyName));
|
||||
proposals.add(completionFactory.valueProposal(valueCandidate, query, valueTypeName,
|
||||
score, edits, ValueHintHoverInfo.create(hint))
|
||||
// new ValueProposal(startOfValue, valuePrefix,
|
||||
// valueCandidate, i)
|
||||
);
|
||||
|
||||
@@ -14,6 +14,7 @@ import org.eclipse.lsp4j.CompletionItemKind;
|
||||
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.quickfix.ProblemFixer;
|
||||
import org.springframework.ide.vscode.commons.util.Renderable;
|
||||
|
||||
public class ReplaceDeprecatedPropertyQuickfix implements ICompletionProposal {
|
||||
|
||||
@@ -45,6 +46,14 @@ public class ReplaceDeprecatedPropertyQuickfix implements ICompletionProposal {
|
||||
public DocumentEdits getTextEdit() {
|
||||
throw new UnsupportedOperationException("Not yet implemented");
|
||||
}
|
||||
@Override
|
||||
public String getDetail() {
|
||||
throw new UnsupportedOperationException("Not yet implemented");
|
||||
}
|
||||
@Override
|
||||
public Renderable getDocumentation() {
|
||||
throw new UnsupportedOperationException("Not yet implemented");
|
||||
}
|
||||
|
||||
// private final QuickfixContext context;
|
||||
// private final SpringPropertyProblem problem;
|
||||
|
||||
@@ -272,7 +272,7 @@ public abstract class ApplicationYamlAssistContext extends AbstractYamlAssistCon
|
||||
edits.insert(offset, " ");
|
||||
}
|
||||
edits.insert(offset, YamlUtil.stringEscape(value));
|
||||
completions.add(completionFactory.valueProposal(value, query, type, score, edits, new ValueHintHoverInfo(hint)));
|
||||
completions.add(completionFactory.valueProposal(value, query, typeUtil.niceTypeName(type), score, edits, ValueHintHoverInfo.create(hint)));
|
||||
}
|
||||
}
|
||||
return completions;
|
||||
|
||||
@@ -14,6 +14,7 @@ import org.eclipse.lsp4j.CompletionItemKind;
|
||||
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.quickfix.ProblemFixer;
|
||||
import org.springframework.ide.vscode.commons.util.Renderable;
|
||||
|
||||
public class ReplaceDeprecatedYamlQuickfix implements ICompletionProposal {
|
||||
|
||||
@@ -45,6 +46,14 @@ public class ReplaceDeprecatedYamlQuickfix implements ICompletionProposal {
|
||||
public DocumentEdits getTextEdit() {
|
||||
throw new UnsupportedOperationException("Not yet implemented");
|
||||
}
|
||||
@Override
|
||||
public String getDetail() {
|
||||
throw new UnsupportedOperationException("Not yet implemented");
|
||||
}
|
||||
@Override
|
||||
public Renderable getDocumentation() {
|
||||
throw new UnsupportedOperationException("Not yet implemented");
|
||||
}
|
||||
|
||||
// private final QuickfixContext context;
|
||||
// private final SpringPropertyProblem problem;
|
||||
|
||||
@@ -343,6 +343,15 @@ public class ManifestYamlEditorTest {
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void completionDetailsAndDocs() throws Exception {
|
||||
Editor editor = harness.newEditor(
|
||||
"applications:\n" +
|
||||
"- build<*>"
|
||||
);
|
||||
editor.assertCompletionDetails("buildpack", "Buildpack", "If your application requires a custom buildpack");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void valueCompletions() throws Exception {
|
||||
assertCompletions("disk_quota: <*>",
|
||||
|
||||
Reference in New Issue
Block a user