Skip to content

Commit

Permalink
Completion should support markdown for documentation
Browse files Browse the repository at this point in the history
Fix #526

Signed-off-by: azerr <[email protected]>
  • Loading branch information
angelozerr committed Jul 22, 2019
1 parent c06e99c commit f20eb3e
Show file tree
Hide file tree
Showing 8 changed files with 148 additions and 29 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import org.eclipse.lsp4j.CompletionItem;
import org.eclipse.lsp4j.CompletionItemKind;
import org.eclipse.lsp4j.InsertTextFormat;
import org.eclipse.lsp4j.MarkupKind;
import org.eclipse.lsp4j.Range;
import org.eclipse.lsp4j.TextEdit;
import org.eclipse.lsp4xml.commons.BadLocationException;
Expand Down Expand Up @@ -68,8 +69,9 @@ public void onTagOpen(ICompletionRequest request, ICompletionResponse response)

if (cmElement != null) {
defaultPrefix = parentElement.getPrefix();
fillWithChildrenElementDeclaration(parentElement, cmElement.getPossibleElements(parentElement, request.getOffset()),
defaultPrefix, false, request, response, schemaURI);
fillWithChildrenElementDeclaration(parentElement,
cmElement.getPossibleElements(parentElement, request.getOffset()), defaultPrefix, false,
request, response, schemaURI);
}
if (parentElement.isDocumentElement()) {
// completion on root document element
Expand All @@ -96,8 +98,8 @@ public void onTagOpen(ICompletionRequest request, ICompletionResponse response)
if (cmInternalElement != null) {
defaultPrefix = parentElement.getPrefix();
fillWithChildrenElementDeclaration(parentElement,
cmInternalElement.getPossibleElements(parentElement, request.getOffset()), defaultPrefix, false, request,
response, schemaURI);
cmInternalElement.getPossibleElements(parentElement, request.getOffset()), defaultPrefix, false,
request, response, schemaURI);
}
} catch (CacheResourceDownloadingException e) {
// XML Schema, DTD is loading, ignore this error
Expand All @@ -114,10 +116,9 @@ private void fillWithChildrenElementDeclaration(DOMElement element, Collection<C
CompletionItem item = new CompletionItem(label);
item.setFilterText(request.getFilterForStartTagName(label));
item.setKind(CompletionItemKind.Property);
String detail = XMLGenerator.generateDocumentation(child.getDocumentation(), schemaURI);
if (detail != null) {
item.setDetail(detail);
}
String documentation = XMLGenerator.generateDocumentation(child.getDocumentation(), schemaURI,
request.canSupportMarkupKind(MarkupKind.MARKDOWN));
updateDocumentation(item, documentation, request);
String xml = generator.generate(child, prefix);
item.setTextEdit(new TextEdit(request.getReplaceRange(), xml));
item.setInsertTextFormat(InsertTextFormat.Snippet);
Expand All @@ -141,19 +142,19 @@ public void onAttributeName(boolean generateValue, ICompletionRequest request, I
// Completion on attribute based on external grammar
CMElementDeclaration cmElement = contentModelManager.findCMElement(parentElement);
fillAttributesWithCMAttributeDeclarations(parentElement, fullRange, cmElement, canSupportSnippet,
generateValue, response, formattingSettings);
generateValue, request, response, formattingSettings);
// Completion on attribute based on internal grammar
cmElement = contentModelManager.findInternalCMElement(parentElement);
fillAttributesWithCMAttributeDeclarations(parentElement, fullRange, cmElement, canSupportSnippet,
generateValue, response, formattingSettings);
generateValue, request, response, formattingSettings);
} catch (CacheResourceDownloadingException e) {
// XML Schema, DTD is loading, ignore this error
}
}

private void fillAttributesWithCMAttributeDeclarations(DOMElement parentElement, Range fullRange,
CMElementDeclaration cmElement, boolean canSupportSnippet, boolean generateValue,
ICompletionResponse response, XMLFormattingOptions formattingOptions) {
ICompletionRequest request, ICompletionResponse response, XMLFormattingOptions formattingOptions) {
if (cmElement == null) {
return;
}
Expand All @@ -167,9 +168,7 @@ private void fillAttributesWithCMAttributeDeclarations(DOMElement parentElement,
CompletionItem item = new AttributeCompletionItem(attrName, canSupportSnippet, fullRange, generateValue,
cmAttribute.getDefaultValue(), cmAttribute.getEnumerationValues(), formattingOptions);
String documentation = cmAttribute.getDocumentation();
if (documentation != null) {
item.setDetail(documentation);
}
updateDocumentation(item, documentation, request);
response.addCompletionAttribute(item);
}
}
Expand Down Expand Up @@ -217,4 +216,7 @@ private void fillAttributeValuesWithCMAttributeDeclarations(CMElementDeclaration
}
}

}
private static void updateDocumentation(CompletionItem item, String documentation, ICompletionRequest request) {
item.setDocumentation(request.createMarkupContent(documentation, MarkupKind.MARKDOWN));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -223,15 +223,21 @@ public static String generateAttributeValue(String defaultValue, Collection<Stri
* @param schemaURI
* @return
*/
public static String generateDocumentation(String documentation, String schemaURI) {
public static String generateDocumentation(String documentation, String schemaURI, boolean html) {
StringBuilder doc = new StringBuilder(documentation != null ? documentation : "");
if (schemaURI != null) {
if (doc.length() != 0) {
doc.append(System.lineSeparator());
doc.append(System.lineSeparator());
}
if (html) {
doc.append("<p>");
}
doc.append("Source: ");
doc.append(getFileName(schemaURI));
if (html) {
doc.append("</p>");
}
}
return doc.length() > 0 ? doc.toString() : null;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
*/
package org.eclipse.lsp4xml.services;

import org.eclipse.lsp4j.MarkupContent;
import org.eclipse.lsp4j.MarkupKind;
import org.eclipse.lsp4j.Position;
import org.eclipse.lsp4j.Range;
import org.eclipse.lsp4xml.commons.BadLocationException;
Expand All @@ -21,6 +23,7 @@
import org.eclipse.lsp4xml.services.extensions.XMLExtensionsRegistry;
import org.eclipse.lsp4xml.settings.SharedSettings;
import org.eclipse.lsp4xml.settings.XMLFormattingOptions;
import org.eclipse.lsp4xml.utils.MarkdownConverter;
import org.eclipse.lsp4xml.utils.StringUtils;

/**
Expand Down Expand Up @@ -122,4 +125,27 @@ private String getQuotation() {
String quotation = formattingSettings != null ? formattingSettings.getQuotationAsString() : null;
return StringUtils.isEmpty(quotation) ? XMLFormattingOptions.DEFAULT_QUOTATION : quotation;
}
}

@Override
public boolean canSupportMarkupKind(String kind) {
return completionSettings != null && completionSettings.getCompletionCapabilities() != null
&& completionSettings.getCompletionCapabilities().getCompletionItem() != null
&& completionSettings.getCompletionCapabilities().getCompletionItem().getDocumentationFormat() != null
&& completionSettings.getCompletionCapabilities().getCompletionItem().getDocumentationFormat()
.contains(kind);
}

@Override
public MarkupContent createMarkupContent(String value, String kind) {
MarkupContent content = new MarkupContent();
if (MarkupKind.MARKDOWN.equals(kind) && canSupportMarkupKind(kind)) {
String markdown = MarkdownConverter.convert(value);
content.setValue(markdown);
content.setKind(MarkupKind.MARKDOWN);
} else {
content.setValue(value);
content.setKind(MarkupKind.PLAINTEXT);
}
return content;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
*/
package org.eclipse.lsp4xml.services.extensions;

import org.eclipse.lsp4j.MarkupContent;
import org.eclipse.lsp4j.MarkupKind;
import org.eclipse.lsp4j.Range;
import org.eclipse.lsp4xml.commons.BadLocationException;
import org.eclipse.lsp4xml.extensions.contentmodel.utils.XMLGenerator;
Expand All @@ -33,4 +35,24 @@ public interface ICompletionRequest extends IPositionRequest {

String getInsertAttrValue(String value);

}
/**
* Returns <code>true</code> if the client can support the given Markup kind for
* documentation and <code>false</code> otherwise.
*
* @param kind the markup kind
* @return <code>true</code> if the client can support the given Markup kind for
* documentation and <code>false</code> otherwise.
*/
boolean canSupportMarkupKind(String kind);

/**
* Create the markup content according the given markup kind and the capability
* of the client.
*
* @param value the documentation value
* @param kind the {@link MarkupKind}
* @return the markup content according the given markup kind and the capability
* of the client.
*/
MarkupContent createMarkupContent(String value, String kind);
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
import org.eclipse.lsp4j.LocationLink;
import org.eclipse.lsp4j.MarkedString;
import org.eclipse.lsp4j.MarkupContent;
import org.eclipse.lsp4j.MarkupKind;
import org.eclipse.lsp4j.Position;
import org.eclipse.lsp4j.PublishDiagnosticsParams;
import org.eclipse.lsp4j.Range;
Expand Down Expand Up @@ -217,18 +218,27 @@ private static void assertCompletion(CompletionList completions, CompletionItem
Assert.assertEquals(expected.getFilterText(), match.getFilterText());
}

if (expected.getDetail() != null) {
Assert.assertEquals(expected.getDetail(), match.getDetail());
if (expected.getDocumentation() != null) {
Assert.assertEquals(expected.getDocumentation(), match.getDocumentation());
}

}

public static CompletionItem c(String label, TextEdit textEdit, String filterText, String detail) {
public static CompletionItem c(String label, TextEdit textEdit, String filterText, String documentation) {
return c(label, textEdit, filterText, documentation, null);
}

public static CompletionItem c(String label, TextEdit textEdit, String filterText, String documentation,
String kind) {
CompletionItem item = new CompletionItem();
item.setLabel(label);
item.setFilterText(filterText);
item.setTextEdit(textEdit);
item.setDetail(detail);
if (kind == null) {
item.setDocumentation(documentation);
} else {
item.setDocumentation(new MarkupContent(kind, documentation));
}
return item;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import org.eclipse.lsp4j.CompletionCapabilities;
import org.eclipse.lsp4j.CompletionItem;
import org.eclipse.lsp4j.CompletionItemCapabilities;
import org.eclipse.lsp4j.MarkupKind;
import org.eclipse.lsp4xml.XMLAssert;
import org.eclipse.lsp4xml.commons.BadLocationException;
import org.eclipse.lsp4xml.services.XMLLanguageService;
Expand Down Expand Up @@ -45,15 +46,15 @@ public void completionWithChoiceAttribute() throws BadLocationException {
}

@Test
public void testCompletionDetailWithSource() throws BadLocationException {
public void testCompletionDocumentationWithSource() throws BadLocationException {
// completion on <|
String xml = "<?xml version=\"1.0\"?>\r\n" + //
" <!DOCTYPE catalog\r\n" + //
" PUBLIC \"-//OASIS//DTD Entity Resolution XML Catalog V1.0//EN\"\r\n" + //
" \"http://www.oasis-open.org/committees/entity/release/1.0/catalog.dtd\">\r\n" + //
"\r\n" + //
" <|";
testCompletionFor(xml, c("catalog", te(5, 2, 5, 3, "<catalog>$1</catalog>$0"), "<catalog", "Source: catalog.dtd"));
testCompletionFor(xml, c("catalog", te(5, 2, 5, 3, "<catalog>$1</catalog>$0"), "<catalog", "Source: catalog.dtd", MarkupKind.PLAINTEXT));
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,16 @@
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;

import org.eclipse.lsp4j.CompletionCapabilities;
import org.eclipse.lsp4j.CompletionItem;
import org.eclipse.lsp4j.CompletionItemCapabilities;
import org.eclipse.lsp4j.MarkupKind;
import org.eclipse.lsp4xml.XMLAssert;
import org.eclipse.lsp4xml.commons.BadLocationException;
import org.eclipse.lsp4xml.services.XMLLanguageService;
import org.eclipse.lsp4xml.services.extensions.CompletionSettings;
import org.junit.Test;

/**
Expand Down Expand Up @@ -782,7 +787,53 @@ public void tag() throws BadLocationException {

}

@Test
public void documentationAsPlainText() throws BadLocationException {
String xml = "<project xmlns=\"http://maven.apache.org/POM/4.0.0\"\r\n" + //
" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\r\n" + //
" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\r\n"
+ //
" <|" + //
"</project>";
testCompletionFor(xml, c("groupId", te(3, 1, 3, 2, "<groupId></groupId>"), "<groupId",
"A universally unique identifier for a project. It is normal to use a fully-qualified package name to distinguish it from other projects with a similar name "
+ "(eg. <code>org.apache.maven</code>)." + //
System.lineSeparator() + //
System.lineSeparator() + //
"Source: maven-4.0.0.xsd",
MarkupKind.PLAINTEXT));

}

@Test
public void documentationAsMarkdown() throws BadLocationException {
String xml = "<project xmlns=\"http://maven.apache.org/POM/4.0.0\"\r\n" + //
" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\r\n" + //
" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\r\n"
+ //
" <|" + //
"</project>";
testCompletionMarkdownSupporytFor(xml, c("groupId", te(3, 1, 3, 2, "<groupId></groupId>"), "<groupId",
"A universally unique identifier for a project. It is normal to use a fully-qualified package name to distinguish it from other projects with a similar name "
+ "(eg. `org.apache.maven`)." + //
System.lineSeparator() + //
System.lineSeparator() + //
"Source: maven-4.0.0.xsd",
MarkupKind.MARKDOWN));
}

private void testCompletionFor(String xml, CompletionItem... expectedItems) throws BadLocationException {
XMLAssert.testCompletionFor(xml, "src/test/resources/catalogs/catalog.xml", expectedItems);
}

private void testCompletionMarkdownSupporytFor(String xml, CompletionItem... expectedItems) throws BadLocationException {
CompletionSettings completionSettings = new CompletionSettings();
CompletionCapabilities completionCapabilities = new CompletionCapabilities();
CompletionItemCapabilities completionItem = new CompletionItemCapabilities(false);
completionItem.setDocumentationFormat(Arrays.asList(MarkupKind.MARKDOWN));
completionCapabilities.setCompletionItem(completionItem);
completionSettings.setCapabilities(completionCapabilities);
XMLAssert.testCompletionFor(new XMLLanguageService(), xml, "src/test/resources/catalogs/catalog.xml", null,
null, null, completionSettings, expectedItems);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import static org.eclipse.lsp4xml.XMLAssert.te;

import org.eclipse.lsp4j.CompletionItem;
import org.eclipse.lsp4j.MarkupKind;
import org.eclipse.lsp4xml.XMLAssert;
import org.eclipse.lsp4xml.commons.BadLocationException;
import org.junit.Test;
Expand All @@ -36,29 +37,29 @@ public void completion() throws BadLocationException {
}

@Test
public void completionWithSourceDetail() throws BadLocationException {
public void completionWithSourceDocumentation() throws BadLocationException {
// completion on |
String xml = "<?xml version=\"1.1\"?>\r\n"
+ "<xs:schema xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" elementFormDefault=\"qualified\" attributeFormDefault=\"unqualified\"> \r\n"
+ //
"|";
testCompletionFor(xml,
c("xs:annotation", te(2, 0, 2, 0, "<xs:annotation></xs:annotation>"), "xs:annotation",
"Source: XMLSchema.xsd"),
"Source: XMLSchema.xsd", MarkupKind.PLAINTEXT),
c("xs:attribute", te(2, 0, 2, 0, "<xs:attribute name=\"\"></xs:attribute>"), "xs:attribute",
"Source: XMLSchema.xsd"));
"Source: XMLSchema.xsd", MarkupKind.PLAINTEXT));
}

@Test
public void completionWithSourceDescriptionAndDetail() throws BadLocationException {
public void completionWithSourceDescriptionAndDocumentation() throws BadLocationException {
String xml = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n" + //
"<invoice xmlns=\"http://invoice\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\r\n"
+ " xsi:schemaLocation=\"http://invoice xsd/invoice.xsd \">\r\n" + //
" <|";
String lineSeparator = System.getProperty("line.separator");
XMLAssert.testCompletionFor(xml, null, "src/test/resources/invoice.xml", null,
c("date", te(3, 2, 3, 3, "<date></date>"), "<date",
"Date Description" + lineSeparator + lineSeparator + "Source: invoice.xsd"));
"Date Description" + lineSeparator + lineSeparator + "Source: invoice.xsd", MarkupKind.PLAINTEXT));
}

@Test
Expand Down

0 comments on commit f20eb3e

Please sign in to comment.