Merge branch 'master' into javadoc

# Conflicts:
#	vscode-extensions/commons/application-properties-metadata/src/main/java/org/springframework/ide/vscode/application/properties/metadata/hints/StsValueHint.java
This commit is contained in:
BoykoAlex
2016-11-18 20:42:43 -05:00
59 changed files with 1105 additions and 298 deletions

View File

@@ -1,9 +1,5 @@
package org.springframework.ide.vscode.application.properties.metadata.hints;
import static org.springframework.ide.vscode.application.properties.metadata.util.DeprecationUtil.*;
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;
@@ -11,10 +7,13 @@ import org.springframework.ide.vscode.application.properties.metadata.util.Depre
import org.springframework.ide.vscode.commons.java.IJavaElement;
import org.springframework.ide.vscode.commons.java.IJavaProject;
import org.springframework.ide.vscode.commons.java.IType;
import org.springframework.ide.vscode.commons.javadoc.IJavadoc;
import org.springframework.ide.vscode.commons.languageserver.hover.HoverInfo;
import org.springframework.ide.vscode.commons.util.Assert;
import org.springframework.ide.vscode.commons.util.HtmlSnippet;
import org.springframework.ide.vscode.commons.util.HtmlBuffer;
import org.springframework.ide.vscode.commons.util.Log;
import org.springframework.ide.vscode.commons.util.StringUtil;
import org.springframework.ide.vscode.commons.yaml.util.DescriptionProviders;
/**
* Sts version of {@link ValueHint} contains similar data, but accomoates
@@ -28,12 +27,9 @@ import org.springframework.ide.vscode.commons.util.StringUtil;
*/
public class StsValueHint {
private static final HtmlSnippet EMPTY_DESCRIPTION = HtmlSnippet.italic("No description");
private static final Provider<HtmlSnippet> EMPTY_DESCRIPTION_PROVIDER = () -> EMPTY_DESCRIPTION;
private final String value;
private final Provider<HtmlSnippet> description;
private final HoverInfo description;
private final Deprecation deprecation;
/**
@@ -42,7 +38,7 @@ public class StsValueHint {
* This constructor is private. Use one of the provided
* static 'create' methods instead.
*/
private StsValueHint(String value, Provider<HtmlSnippet> description, Deprecation deprecation) {
private StsValueHint(String value, HoverInfo description, Deprecation deprecation) {
this.value = value==null?"null":value.toString();
Assert.isLegal(!this.value.startsWith("StsValueHint"));
this.description = description;
@@ -62,7 +58,7 @@ public class StsValueHint {
}
public static StsValueHint create(String value) {
return new StsValueHint(value, EMPTY_DESCRIPTION_PROVIDER, null);
return new StsValueHint(value, DescriptionProviders.NO_DESCRIPTION, null);
}
public static StsValueHint create(ValueHint hint) {
@@ -96,36 +92,46 @@ public class StsValueHint {
/**
* Create a html snippet from a text snippet.
*/
private static Provider<HtmlSnippet> textSnippet(String description) {
private static HoverInfo textSnippet(String description) {
if (StringUtil.hasText(description)) {
return () -> HtmlSnippet.text(description);
return DescriptionProviders.text(description);
}
return EMPTY_DESCRIPTION_PROVIDER;
return DescriptionProviders.NO_DESCRIPTION;
}
public String getValue() {
return value;
}
public HtmlSnippet getDescription() {
return description.get();
public HoverInfo getDescription() {
return description;
}
public Provider<HtmlSnippet> getDescriptionProvider() {
public HoverInfo getDescriptionProvider() {
return description;
}
public static Provider<HtmlSnippet> javaDocSnippet(IJavaElement je) {
return () -> {
try {
HtmlSnippet jdoc = HtmlSnippet.raw(je.getJavaDoc().html());
if (jdoc!=null) {
return jdoc;
}
} catch (Exception e) {
Log.log(e);
public static HoverInfo javaDocSnippet(IJavaElement je) {
try {
IJavadoc jdoc = je.getJavaDoc();
if (jdoc != null) {
return new HoverInfo() {
@Override
public void renderAsMarkdown(StringBuilder buffer) {
// TODO not correct md
buffer.append(jdoc.markdown());
}
@Override
public void renderAsHtml(HtmlBuffer buffer) {
buffer.raw(jdoc.html());
}
};
}
return EMPTY_DESCRIPTION;
};
} catch (Exception e) {
Log.log(e);
}
return DescriptionProviders.NO_DESCRIPTION;
}
@Override

View File

@@ -3,7 +3,7 @@ package org.springframework.ide.vscode.application.properties.metadata.types;
import javax.inject.Provider;
import org.springframework.boot.configurationmetadata.Deprecation;
import org.springframework.ide.vscode.commons.util.HtmlSnippet;
import org.springframework.ide.vscode.commons.languageserver.hover.HoverInfo;
import org.springframework.ide.vscode.commons.yaml.schema.YTypedProperty;
import org.springframework.ide.vscode.commons.yaml.util.DescriptionProviders;
@@ -27,7 +27,7 @@ public class TypedProperty implements YTypedProperty {
/**
* Provides a description for this property.
*/
private final Provider<HtmlSnippet> descriptionProvider;
private final HoverInfo descriptionProvider;
private final Deprecation deprecation;
@@ -35,7 +35,7 @@ public class TypedProperty implements YTypedProperty {
this(name, type, DescriptionProviders.NO_DESCRIPTION, deprecation);
}
public TypedProperty(String name, Type type, Provider<HtmlSnippet> descriptionProvider, Deprecation deprecation) {
public TypedProperty(String name, Type type, HoverInfo descriptionProvider, Deprecation deprecation) {
this.name = name;
this.type = type;
this.descriptionProvider = descriptionProvider;
@@ -56,14 +56,14 @@ public class TypedProperty implements YTypedProperty {
}
@Override
public HtmlSnippet getDescription() {
public HoverInfo getDescription() {
//TODO: real implementation that somehow gets this from somewhere (i.e. the JavaDoc)
// Note that presently the application.yml and application.properties editor do not actually
// use this description provider but produce hover infos in a different way (so this is only
// used in Schema-based content assist, reconciling and hovering.
//So in that sense putting a good implementation here is kind of pointless right now.
//More refactoring needs to be done to also make use of this.
return descriptionProvider.get();
return descriptionProvider;
}
public static Type typeOf(TypedProperty typedProperty) {

View File

@@ -60,7 +60,11 @@
<artifactId>jackson-datatype-jdk8</artifactId>
<version>${jackson-2-version}</version>
</dependency>
<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-core</artifactId>
<version>${reactor-version}</version>
</dependency>
<!-- testing -->
<dependency>
<groupId>org.springframework.ide.vscode</groupId>

View File

@@ -147,6 +147,7 @@ public abstract class LaunguageServerApp {
Function<MessageConsumer, MessageConsumer> wrapper = (MessageConsumer consumer) -> {
return (msg) -> {
try {
LOG.info(""+msg);
consumer.consume(msg);
} catch (UnsupportedOperationException e) {
//log a warning and ignore. We are getting some messages from vsCode the server doesn't know about

View File

@@ -10,15 +10,27 @@
*******************************************************************************/
package org.springframework.ide.vscode.commons.languageserver.hover;
import org.springframework.ide.vscode.commons.util.HtmlBuffer;
/**
* Placeholder. Still need to figure out what exactly we should do with this in vscode.
* Placeholder. Still need to figure out what exactly we should do with this in
* vscode. TODO: rename to Renderable
*/
public interface HoverInfo {
String renderAsText();
void renderAsHtml(HtmlBuffer buffer);
String renderAsHtml();
void renderAsMarkdown(StringBuilder buffer);
String renderAsMarkdown();
default String toMarkdown() {
StringBuilder buffer = new StringBuilder();
renderAsMarkdown(buffer);
return buffer.toString();
}
default String toHtml() {
HtmlBuffer buffer = new HtmlBuffer();
renderAsHtml(buffer);
return buffer.toString();
}
}

View File

@@ -11,9 +11,12 @@
package org.springframework.ide.vscode.commons.languageserver.hover;
import org.springframework.ide.vscode.commons.languageserver.util.IDocument;
import org.springframework.ide.vscode.commons.languageserver.util.IRegion;
public interface IHoverEngine {
import reactor.util.function.Tuple2;
HoverInfo getHover(IDocument document, int offset) throws Exception;
public interface HoverInfoProvider {
Tuple2<HoverInfo, IRegion> getHoverInfo(IDocument document, int offset) throws Exception;
}

View File

@@ -14,23 +14,27 @@ import java.util.Collections;
import java.util.concurrent.CompletableFuture;
import org.eclipse.lsp4j.Hover;
import org.eclipse.lsp4j.Range;
import org.eclipse.lsp4j.TextDocumentPositionParams;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.ide.vscode.commons.languageserver.util.IRegion;
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 reactor.util.function.Tuple2;
public class VscodeHoverEngineAdapter implements VscodeHoverEngine {
private IHoverEngine engine;
private HoverInfoProvider hoverInfoProvider;
private SimpleLanguageServer server;
final static Logger logger = LoggerFactory.getLogger(VscodeHoverEngineAdapter.class);
public VscodeHoverEngineAdapter(SimpleLanguageServer server, IHoverEngine engine) {
this.engine = engine;
public VscodeHoverEngineAdapter(SimpleLanguageServer server, HoverInfoProvider hoverInfoProvider) {
this.hoverInfoProvider = hoverInfoProvider;
this.server = server;
}
@@ -44,16 +48,17 @@ public class VscodeHoverEngineAdapter implements VscodeHoverEngine {
TextDocument doc = documents.get(params);
if (doc!=null) {
int offset = doc.toOffset(params.getPosition());
HoverInfo hoverInfo = engine.getHover(doc, offset);
if (hoverInfo != null) {
Hover hover = new Hover();
hover.setContents(Collections.singletonList(hoverInfo.renderAsMarkdown()));
Tuple2<HoverInfo, IRegion> hoverTuple = hoverInfoProvider.getHoverInfo(doc, offset);
if (hoverTuple != null) {
HoverInfo hoverInfo = hoverTuple.getT1();
IRegion region = hoverTuple.getT2();
Range range = doc.toRange(region.getOffset(), region.getLength());
Hover hover = new Hover(Collections.singletonList(hoverInfo.toMarkdown()), range);
return Futures.of(hover);
}
else{
return Futures.of(null);
}
}
} catch (Exception e) {
logger.error("error computing hover", e);

View File

@@ -20,12 +20,8 @@ import java.net.URLEncoder;
*/
public class HtmlBuffer {
private StringBuffer buffer = new StringBuffer();
private boolean epilogAdded = false; //to ensure only added once.
private StringBuilder buffer = new StringBuilder();
public HtmlBuffer() {
this.buffer = new StringBuffer();
}
/**
* Append text, applies escaping to the text as needed.
@@ -38,9 +34,6 @@ public class HtmlBuffer {
* Append 'raw' text. Doesn't apply any escaping.
*/
public void raw(String rawText) {
if (epilogAdded) {
throw new IllegalStateException("Can not append more text after epilog was added");
}
buffer.append(rawText);
}
@@ -57,10 +50,7 @@ public class HtmlBuffer {
public String toString() {
if (!epilogAdded && buffer.length()>0) {
epilogAdded = true;
addPrologAndEpilog();
}
return buffer.toString();
}

View File

@@ -12,9 +12,13 @@ package org.springframework.ide.vscode.commons.util;
/**
* A snippet that can be rendered into html.
* <p/>
* Deprecated. Use DescriptionProviders instead.
*
* @author Kris De Volder
*
*/
@Deprecated
public abstract class HtmlSnippet {
public abstract void render(HtmlBuffer html);

View File

@@ -0,0 +1,21 @@
/*******************************************************************************
* 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.commons.util;
public class HtmlUtil {
public static String text2html(String s) {
HtmlBuffer buf = new HtmlBuffer();
buf.text(s);
return buf.toString();
}
}

View File

@@ -14,6 +14,8 @@ import java.util.Collection;
import java.util.Collections;
import org.springframework.ide.vscode.commons.languageserver.completion.ICompletionProposal;
import org.springframework.ide.vscode.commons.languageserver.hover.HoverInfo;
import org.springframework.ide.vscode.commons.languageserver.util.DocumentRegion;
import org.springframework.ide.vscode.commons.yaml.path.YamlPathSegment;
import org.springframework.ide.vscode.commons.yaml.structure.YamlDocument;
import org.springframework.ide.vscode.commons.yaml.structure.YamlStructureParser.SNode;
@@ -49,19 +51,20 @@ public abstract class TopLevelAssistContext implements YamlAssistContext {
return Collections.emptyList();
}
// @Override
// public HoverInfo getHoverInfo() {
// return null;
// }
//
// public HoverInfo getHoverInfo(YamlPathSegment lastSegment) {
// return null;
// }
//
// @Override
// public HoverInfo getValueHoverInfo(YamlDocument doc, DocumentRegion documentRegion) {
// return null;
// }
@Override
public HoverInfo getHoverInfo() {
return null;
}
@Override
public HoverInfo getHoverInfo(YamlPathSegment lastSegment) {
return null;
}
@Override
public HoverInfo getValueHoverInfo(YamlDocument doc, DocumentRegion documentRegion) {
return null;
}
protected abstract YamlAssistContext getDocumentContext(int documentSelector);
}

View File

@@ -22,8 +22,11 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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.hover.HoverInfo;
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.yaml.hover.YPropertyHoverInfo;
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;
@@ -215,35 +218,42 @@ public class YTypeAssistContext extends AbstractYamlAssistContext {
}
// @Override
// public HoverInfo getHoverInfo() {
// if (parent!=null) {
// return parent.getHoverInfo(contextPath.getLastSegment());
// }
// return null;
// }
//
@Override
public HoverInfo getHoverInfo() {
if (parent!=null) {
return parent.getHoverInfo(contextPath.getLastSegment());
}
return null;
}
public YType getType() {
return type;
}
//
// @Override
// public HoverInfo getHoverInfo(YamlPathSegment lastSegment) {
// //Hoverinfo is only attached to YTypedProperties so...
// switch (lastSegment.getType()) {
// case VAL_AT_KEY:
// case KEY_AT_KEY:
// YTypedProperty prop = getProperty(lastSegment.toPropString());
// if (prop!=null) {
// return new YPropertyHoverInfo(contextPath.toPropString(), getType(), prop);
// }
// break;
// default:
// }
// return null;
// }
// private YTypedProperty getProperty(String name) {
// return typeUtil.getPropertiesMap(getType()).get(name);
// }
@Override
public HoverInfo getHoverInfo(YamlPathSegment lastSegment) {
//Hoverinfo is only attached to YTypedProperties so...
switch (lastSegment.getType()) {
case VAL_AT_KEY:
case KEY_AT_KEY:
YTypedProperty prop = getProperty(lastSegment.toPropString());
if (prop!=null) {
return YPropertyHoverInfo.create(contextPath.toPropString(), getType(), prop);
}
break;
default:
}
return null;
}
@Override
public HoverInfo getValueHoverInfo(YamlDocument doc, DocumentRegion documentRegion) {
//By default we don't provide value-specific hover, so just show the same hover
// as the assistContext the value is in. This is likely more interesting than showing nothing at all.
return getHoverInfo();
}
private YTypedProperty getProperty(String name) {
return typeUtil.getPropertiesMap(getType()).get(name);
}
}

View File

@@ -13,7 +13,10 @@ package org.springframework.ide.vscode.commons.yaml.completion;
import java.util.Collection;
import org.springframework.ide.vscode.commons.languageserver.completion.ICompletionProposal;
import org.springframework.ide.vscode.commons.languageserver.hover.HoverInfo;
import org.springframework.ide.vscode.commons.languageserver.util.DocumentRegion;
import org.springframework.ide.vscode.commons.yaml.path.YamlNavigable;
import org.springframework.ide.vscode.commons.yaml.path.YamlPathSegment;
import org.springframework.ide.vscode.commons.yaml.structure.YamlDocument;
import org.springframework.ide.vscode.commons.yaml.structure.YamlStructureParser.SNode;
@@ -25,8 +28,8 @@ public interface YamlAssistContext extends YamlNavigable<YamlAssistContext> {
//TODO: conceptually... the right thing would be to only implement the second of these
// two methods and get rid of the first one.
// HoverInfo getHoverInfo();
// HoverInfo getHoverInfo(YamlPathSegment lastSegment);
//
// HoverInfo getValueHoverInfo(YamlDocument doc, DocumentRegion documentRegion);
HoverInfo getHoverInfo();
HoverInfo getHoverInfo(YamlPathSegment lastSegment);
HoverInfo getValueHoverInfo(YamlDocument doc, DocumentRegion documentRegion);
}

View File

@@ -0,0 +1,60 @@
/*******************************************************************************
* 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.commons.yaml.hover;
import static org.springframework.ide.vscode.commons.yaml.util.DescriptionProviders.bold;
import static org.springframework.ide.vscode.commons.yaml.util.DescriptionProviders.concat;
import static org.springframework.ide.vscode.commons.yaml.util.DescriptionProviders.lineBreak;
import static org.springframework.ide.vscode.commons.yaml.util.DescriptionProviders.link;
import static org.springframework.ide.vscode.commons.yaml.util.DescriptionProviders.text;
import org.springframework.ide.vscode.commons.languageserver.hover.HoverInfo;
import org.springframework.ide.vscode.commons.util.StringUtil;
import org.springframework.ide.vscode.commons.yaml.schema.YType;
import org.springframework.ide.vscode.commons.yaml.schema.YTypedProperty;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableList.Builder;
/**
* Nicely formatted hover info for a {@link YTypedProperty}
*
* @author Kris De Volder
*/
public class YPropertyHoverInfo {
public static HoverInfo create(String contextProperty, YType contextType, YTypedProperty prop) {
Builder<HoverInfo> html = ImmutableList.builder();
if (StringUtil.hasText(contextProperty)) {
html.add(text(contextProperty));
html.add(text("."));
}
html.add(bold(text(prop.getName())));
html.add(lineBreak());
YType type = prop.getType();
if (type != null) {
html.add(link(type.toString(), /* no URL */ null));
}
HoverInfo description = prop.getDescription();
if (description != null) {
html.add(lineBreak());
html.add(description);
}
return concat(html.build());
}
}

View File

@@ -0,0 +1,117 @@
/*******************************************************************************
* 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.commons.yaml.hover;
import java.util.List;
import org.springframework.ide.vscode.commons.languageserver.hover.HoverInfo;
import org.springframework.ide.vscode.commons.languageserver.hover.HoverInfoProvider;
import org.springframework.ide.vscode.commons.languageserver.util.DocumentRegion;
import org.springframework.ide.vscode.commons.languageserver.util.IDocument;
import org.springframework.ide.vscode.commons.languageserver.util.IRegion;
import org.springframework.ide.vscode.commons.languageserver.util.Region;
import org.springframework.ide.vscode.commons.util.Assert;
import org.springframework.ide.vscode.commons.yaml.ast.NodeRef;
import org.springframework.ide.vscode.commons.yaml.ast.YamlASTProvider;
import org.springframework.ide.vscode.commons.yaml.ast.YamlFileAST;
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.path.YamlPath;
import org.springframework.ide.vscode.commons.yaml.path.YamlPathSegment;
import org.springframework.ide.vscode.commons.yaml.structure.YamlDocument;
import org.springframework.ide.vscode.commons.yaml.structure.YamlStructureProvider;
import org.yaml.snakeyaml.nodes.Node;
import org.yaml.snakeyaml.nodes.NodeId;
import org.yaml.snakeyaml.parser.ParserException;
import org.yaml.snakeyaml.scanner.ScannerException;
import reactor.util.function.Tuple2;
import reactor.util.function.Tuples;
/**
* Implements {@link HoverInfoProvider} for Yaml files based on
* {@link YamlAssistContext}.
*
* @author Kris De Volder
*/
public class YamlHoverInfoProvider implements HoverInfoProvider {
private YamlASTProvider astProvider;
private YamlAssistContextProvider assistContextProvider;
private YamlStructureProvider structureProvider;
public YamlHoverInfoProvider(YamlASTProvider astProvider, YamlStructureProvider structureProvider,
YamlAssistContextProvider assistContextProvider) {
Assert.isNotNull(astProvider);
Assert.isNotNull(structureProvider);
Assert.isNotNull(assistContextProvider);
this.astProvider = astProvider;
this.structureProvider = structureProvider;
this.assistContextProvider = assistContextProvider;
}
@Override
public Tuple2<HoverInfo, IRegion> getHoverInfo(IDocument doc, int offset) throws Exception {
YamlFileAST ast = getAst(doc);
if (ast != null) {
IRegion region = getHoverRegion(ast, offset);
YamlDocument ymlDoc = new YamlDocument(doc, structureProvider);
YamlAssistContext assistContext = assistContextProvider.getGlobalAssistContext(ymlDoc);
if (assistContext != null) {
List<NodeRef<?>> astPath = ast.findPath(offset);
final YamlPath path = YamlPath.fromASTPath(astPath);
if (path != null) {
YamlPath assistPath = path;
if (assistPath.pointsAtKey()) {
// When a path points at a key we must tramsform it to a
// 'value-terminating path'
// to be able to reuse the 'getHoverInfo' method on
// YamlAssistContext (as navigation
// into 'key' is not defined for YamlAssistContext.
String key = path.getLastSegment().toPropString();
assistPath = path.dropLast().append(YamlPathSegment.valueAt(key));
}
assistContext = assistPath.traverse(assistContext);
if (assistContext != null) {
if (path.pointsAtValue()) {
HoverInfo info = assistContext.getValueHoverInfo(ymlDoc, new DocumentRegion(doc, region));
return Tuples.of(info, region);
}
HoverInfo info = assistContext.getHoverInfo();
return Tuples.of(info, region);
}
}
}
}
return null;
}
private IRegion getHoverRegion(YamlFileAST ast, int offset) {
if (ast != null) {
Node n = ast.findNode(offset);
if (n != null && n.getNodeId() == NodeId.scalar) {
int start = n.getStartMark().getIndex();
int end = n.getEndMark().getIndex();
return new Region(start, end - start);
}
}
return null;
}
private YamlFileAST getAst(IDocument doc) throws Exception {
try {
return astProvider.getAST(doc);
} catch (ParserException | ScannerException e) {
// ignore, the user just typed some crap
}
return null;
}
}

View File

@@ -21,8 +21,8 @@ import java.util.Set;
import javax.inject.Provider;
import org.springframework.ide.vscode.commons.languageserver.hover.HoverInfo;
import org.springframework.ide.vscode.commons.util.EnumValueParser;
import org.springframework.ide.vscode.commons.util.HtmlSnippet;
import org.springframework.ide.vscode.commons.util.ValueParser;
import org.springframework.ide.vscode.commons.yaml.util.DescriptionProviders;
@@ -193,7 +193,7 @@ public class YTypeFactory {
propertyList.add(p);
}
public void addProperty(String name, YType type, Provider<HtmlSnippet> description) {
public void addProperty(String name, YType type, HoverInfo description) {
YTypedPropertyImpl prop;
addProperty(prop = new YTypedPropertyImpl(name, type));
prop.setDescriptionProvider(description);
@@ -314,7 +314,7 @@ public class YTypeFactory {
final private String name;
final private YType type;
private Provider<HtmlSnippet> descriptionProvider = DescriptionProviders.NO_DESCRIPTION;
private HoverInfo description = DescriptionProviders.NO_DESCRIPTION;
private YTypedPropertyImpl(String name, YType type) {
this.name = name;
@@ -337,14 +337,13 @@ public class YTypeFactory {
}
@Override
public HtmlSnippet getDescription() {
return descriptionProvider.get();
public HoverInfo getDescription() {
return description;
}
public void setDescriptionProvider(Provider<HtmlSnippet> descriptionProvider) {
this.descriptionProvider = descriptionProvider;
public void setDescriptionProvider(HoverInfo description) {
this.description = description;
}
}
public YAtomicType yatomic(String name) {

View File

@@ -10,7 +10,7 @@
*******************************************************************************/
package org.springframework.ide.vscode.commons.yaml.schema;
import org.springframework.ide.vscode.commons.util.HtmlSnippet;
import org.springframework.ide.vscode.commons.languageserver.hover.HoverInfo;
/**
* @author Kris De Volder
@@ -18,5 +18,5 @@ import org.springframework.ide.vscode.commons.util.HtmlSnippet;
public interface YTypedProperty {
String getName();
YType getType();
HtmlSnippet getDescription();
HoverInfo getDescription();
}

View File

@@ -10,26 +10,32 @@
*******************************************************************************/
package org.springframework.ide.vscode.commons.yaml.util;
import static org.springframework.ide.vscode.commons.util.HtmlSnippet.*;
import java.io.InputStream;
import java.util.List;
import javax.inject.Provider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.ide.vscode.commons.languageserver.hover.HoverInfo;
import org.springframework.ide.vscode.commons.util.HtmlBuffer;
import org.springframework.ide.vscode.commons.util.HtmlSnippet;
import com.google.common.collect.ImmutableList;
/**
* Static methods and convenience constants for creating some 'description providers'.
* Static methods and convenience constants for creating some 'description
* providers'.
*
* @author Kris De Volder
*/
public class DescriptionProviders {
private static final String NO_DESCRIPTION_TEXT = "no description";
final static Logger logger = LoggerFactory.getLogger(DescriptionProviders.class);
public static final Provider<HtmlSnippet> NO_DESCRIPTION = () -> italic(text("no description"));
public static final HoverInfo NO_DESCRIPTION = italic(text(NO_DESCRIPTION_TEXT));
public static Provider<HtmlSnippet> snippet(final HtmlSnippet snippet) {
return new Provider<HtmlSnippet>() {
@@ -37,6 +43,7 @@ public class DescriptionProviders {
public String toString() {
return snippet.toString();
}
@Override
public HtmlSnippet get() {
return snippet;
@@ -44,24 +51,179 @@ public class DescriptionProviders {
};
}
public static Provider<HtmlSnippet> fromClasspath(final Class<?> klass, final String resourcePath) {
return new Provider<HtmlSnippet>() {
public static HoverInfo concat(HoverInfo... pieces) {
return concat(ImmutableList.copyOf(pieces));
}
public static HoverInfo concat(List<HoverInfo> pieces) {
if (pieces == null || pieces.size() == 0) {
throw new IllegalArgumentException("At least one hover information is required for concat");
} else if (pieces.size() == 1) {
return pieces.get(0);
} else {
return new ConcatHoverInfo(pieces);
}
}
public static HoverInfo italic(HoverInfo text) {
return new HoverInfo() {
@Override
public String toString() {
return "DescriptionFromClassPth(class="+klass.getSimpleName()+", "+resourcePath+")";
public void renderAsMarkdown(StringBuilder buffer) {
buffer.append("*");
text.renderAsMarkdown(buffer);
buffer.append("*");
}
@Override
public HtmlSnippet get() {
try {
InputStream stream = klass.getResourceAsStream(resourcePath);
if (stream!=null) {
return HtmlSnippet.text(IOUtil.toString(stream));
}
} catch (Exception e) {
logger.error("Error", e);;
}
return NO_DESCRIPTION.get();
public void renderAsHtml(HtmlBuffer buffer) {
buffer.raw("<i>");
text.renderAsHtml(buffer);
buffer.raw("</i>");
}
};
}
public static HoverInfo link(String text, String url) {
return new HoverInfo() {
@Override
public void renderAsMarkdown(StringBuilder buffer) {
buffer.append('[');
buffer.append(text);
buffer.append(']');
if (url != null) {
buffer.append('(');
buffer.append(url);
buffer.append(')');
}
}
@Override
public void renderAsHtml(HtmlBuffer buffer) {
buffer.raw("<a href=\"");
buffer.url("" + url);
buffer.raw("\">");
buffer.text(text);
buffer.raw("</a>");
}
};
}
public static HoverInfo lineBreak() {
return new HoverInfo() {
@Override
public void renderAsMarkdown(StringBuilder buffer) {
buffer.append("\n\n");
}
@Override
public void renderAsHtml(HtmlBuffer buffer) {
buffer.raw("<br>");
}
};
}
public static HoverInfo bold(HoverInfo text) {
return new HoverInfo() {
@Override
public void renderAsMarkdown(StringBuilder buffer) {
buffer.append("**");
text.renderAsMarkdown(buffer);
buffer.append("**");
}
@Override
public void renderAsHtml(HtmlBuffer buffer) {
buffer.raw("<b>");
text.renderAsHtml(buffer);
buffer.raw("</b>");
}
};
}
public static HoverInfo text(String text) {
return new HoverInfo() {
@Override
public void renderAsMarkdown(StringBuilder buffer) {
// TODO: handle escaping
buffer.append(text);
}
@Override
public void renderAsHtml(HtmlBuffer buffer) {
buffer.text(text);
}
};
}
public static HoverInfo fromClasspath(final Class<?> klass, final String resourcePath) {
return new HoverInfo() {
@Override
public void renderAsMarkdown(StringBuilder buffer) {
String extension = ".md";
String value = getText(klass, resourcePath, extension);
if (value != null) {
buffer.append(value);
} else {
NO_DESCRIPTION.renderAsMarkdown(buffer);
}
}
@Override
public void renderAsHtml(HtmlBuffer buffer) {
String extension = ".html";
String value = getText(klass, resourcePath, extension);
if (value != null) {
buffer.raw(value);
} else {
NO_DESCRIPTION.renderAsHtml(buffer);
}
}
private String getText(final Class<?> klass, final String resourcePath, String extension) {
try {
InputStream stream = klass.getResourceAsStream(resourcePath + extension);
if (stream != null) {
return IOUtil.toString(stream);
}
} catch (Exception e) {
logger.error("Error", e);
}
return null;
}
};
}
private static class ConcatHoverInfo implements HoverInfo {
private HoverInfo[] pieces;
ConcatHoverInfo(HoverInfo[] pieces) {
this.pieces = pieces;
}
public ConcatHoverInfo(List<HoverInfo> pieces) {
this(pieces.toArray(new HoverInfo[pieces.size()]));
}
@Override
public void renderAsHtml(HtmlBuffer buffer) {
for (HoverInfo hoverInfo : pieces) {
hoverInfo.renderAsHtml(buffer);
}
}
@Override
public void renderAsMarkdown(StringBuilder buffer) {
for (HoverInfo hoverInfo : pieces) {
hoverInfo.renderAsMarkdown(buffer);
}
}
}
}

View File

@@ -2,6 +2,7 @@ package org.springframework.ide.vscode.languageserver.testharness;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
import static org.springframework.ide.vscode.languageserver.testharness.TestAsserts.*;
import java.util.ArrayList;
import java.util.Collections;
@@ -16,6 +17,7 @@ import javax.swing.text.BadLocationException;
import org.eclipse.lsp4j.CompletionItem;
import org.eclipse.lsp4j.CompletionList;
import org.eclipse.lsp4j.Diagnostic;
import org.eclipse.lsp4j.Hover;
import org.eclipse.lsp4j.Position;
import org.eclipse.lsp4j.PublishDiagnosticsParams;
import org.eclipse.lsp4j.Range;
@@ -307,13 +309,16 @@ public class Editor {
return document.toPosition(selectionStart);
}
public void assertIsHoverRegion(String string) {
throw new UnsupportedOperationException("Not implemented yet!");
public void assertIsHoverRegion(String string) throws Exception {
int hoverPosition = getRawText().indexOf(string) + string.length() / 2;
Hover hover = harness.getHover(document, document.toPosition(hoverPosition));
assertEquals(string, getText(hover.getRange()));
}
public void assertHoverContains(String string, String string2) {
throw new UnsupportedOperationException("Not implemented yet!");
}
public void assertHoverContains(String hoverOver, String snippet) throws Exception {
int hoverPosition = getRawText().indexOf(hoverOver) + hoverOver.length() / 2;
Hover hover = harness.getHover(document, document.toPosition(hoverPosition));
assertContains(snippet, hover.getContents().toString()); }
public void assertNoHover(String string) {
throw new UnsupportedOperationException("Not implemented yet!");

View File

@@ -24,6 +24,7 @@ import org.eclipse.lsp4j.Diagnostic;
import org.eclipse.lsp4j.DiagnosticSeverity;
import org.eclipse.lsp4j.DidChangeTextDocumentParams;
import org.eclipse.lsp4j.DidOpenTextDocumentParams;
import org.eclipse.lsp4j.Hover;
import org.eclipse.lsp4j.InitializeParams;
import org.eclipse.lsp4j.InitializeResult;
import org.eclipse.lsp4j.MessageParams;
@@ -242,6 +243,15 @@ public class LanguageServerHarness {
return server.getTextDocumentService().completion(params).get();
}
public Hover getHover(TextDocumentInfo document, Position cursor) throws Exception {
TextDocumentPositionParams params = new TextDocumentPositionParams();
params.setPosition(cursor);
params.setTextDocument(document.getId());
return server.getTextDocumentService().hover(params ).get();
}
private CompletionItem resolveCompletionItem(CompletionItem unresolved) {
try {
return server.getTextDocumentService().resolveCompletionItem(unresolved).get();
@@ -313,5 +323,4 @@ public class LanguageServerHarness {
CompletionItem completion = editor.getFirstCompletion();
assertEquals(expected, completion.getLabel());
}
}

View File

@@ -1,4 +1,4 @@
package org.springframework.ide.vscode.project.harness;
package org.springframework.ide.vscode.languageserver.testharness;
import static org.junit.Assert.fail;