diff --git a/org.eclipse.lsp4xml/src/main/java/org/eclipse/lsp4xml/extensions/contentmodel/model/CMDocument.java b/org.eclipse.lsp4xml/src/main/java/org/eclipse/lsp4xml/extensions/contentmodel/model/CMDocument.java index 7f15d7b93..1164bc86f 100644 --- a/org.eclipse.lsp4xml/src/main/java/org/eclipse/lsp4xml/extensions/contentmodel/model/CMDocument.java +++ b/org.eclipse.lsp4xml/src/main/java/org/eclipse/lsp4xml/extensions/contentmodel/model/CMDocument.java @@ -32,4 +32,6 @@ public interface CMDocument { */ CMElementDeclaration findCMElement(DOMElement element, String namespace); + String getURI(); + } diff --git a/org.eclipse.lsp4xml/src/main/java/org/eclipse/lsp4xml/extensions/contentmodel/participants/ContentModelCompletionParticipant.java b/org.eclipse.lsp4xml/src/main/java/org/eclipse/lsp4xml/extensions/contentmodel/participants/ContentModelCompletionParticipant.java index ddc046895..1ef078882 100644 --- a/org.eclipse.lsp4xml/src/main/java/org/eclipse/lsp4xml/extensions/contentmodel/participants/ContentModelCompletionParticipant.java +++ b/org.eclipse.lsp4xml/src/main/java/org/eclipse/lsp4xml/extensions/contentmodel/participants/ContentModelCompletionParticipant.java @@ -10,6 +10,8 @@ */ package org.eclipse.lsp4xml.extensions.contentmodel.participants; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.Collection; import org.eclipse.lsp4j.CompletionItem; @@ -31,6 +33,7 @@ import org.eclipse.lsp4xml.services.extensions.ICompletionResponse; import org.eclipse.lsp4xml.settings.SharedSettings; import org.eclipse.lsp4xml.uriresolver.CacheResourceDownloadingException; +import org.eclipse.lsp4xml.utils.StringUtils; /** * Extension to support XML completion based on content model (XML Schema @@ -42,26 +45,34 @@ public class ContentModelCompletionParticipant extends CompletionParticipantAdap public void onTagOpen(ICompletionRequest request, ICompletionResponse response) throws Exception { try { DOMDocument document = request.getXMLDocument(); + String schemaURI; + String fileURI; ContentModelManager contentModelManager = request.getComponent(ContentModelManager.class); DOMElement parentElement = request.getParentElement(); + CMDocument cmDocument; if (parentElement == null) { // XML is empty, in case of XML file associations, a XMl Schema/DTD can be bound // check if it's root element (in the case of XML file associations, the link to // XML Schema is done with pattern and not with XML root element) - CMDocument cmDocument = contentModelManager.findCMDocument(document, null); + cmDocument = contentModelManager.findCMDocument(document, null); if (cmDocument != null) { - fillWithChildrenElementDeclaration(null, cmDocument.getElements(), null, false, request, response); + schemaURI = cmDocument.getURI(); + fillWithChildrenElementDeclaration(null, cmDocument.getElements(), null, false, request, response, schemaURI); } return; } // Try to retrieve XML Schema/DTD element declaration for the parent element // where completion was triggered. + cmDocument = contentModelManager.findCMDocument(parentElement, parentElement.getNamespaceURI()); + + schemaURI = cmDocument != null ? cmDocument.getURI() : null; CMElementDeclaration cmElement = contentModelManager.findCMElement(parentElement); String defaultPrefix = null; + if (cmElement != null) { defaultPrefix = parentElement.getPrefix(); fillWithChildrenElementDeclaration(parentElement, cmElement.getElements(), defaultPrefix, false, - request, response); + request, response, schemaURI); } if (parentElement.isDocumentElement()) { // root document element @@ -71,10 +82,10 @@ public void onTagOpen(ICompletionRequest request, ICompletionResponse response) continue; } String namespaceURI = parentElement.getNamespaceURI(prefix); - CMDocument cmDocument = contentModelManager.findCMDocument(parentElement, namespaceURI); + cmDocument = contentModelManager.findCMDocument(parentElement, namespaceURI); if (cmDocument != null) { fillWithChildrenElementDeclaration(parentElement, cmDocument.getElements(), prefix, true, - request, response); + request, response, cmDocument.getURI()); } } } @@ -84,7 +95,7 @@ public void onTagOpen(ICompletionRequest request, ICompletionResponse response) if (cmInternalElement != null) { defaultPrefix = parentElement.getPrefix(); fillWithChildrenElementDeclaration(parentElement, cmInternalElement.getElements(), defaultPrefix, false, - request, response); + request, response, schemaURI); } } catch (CacheResourceDownloadingException e) { // XML Schema, DTD is loading, ignore this error @@ -92,7 +103,7 @@ public void onTagOpen(ICompletionRequest request, ICompletionResponse response) } private void fillWithChildrenElementDeclaration(DOMElement element, Collection cmElements, - String p, boolean forceUseOfPrefix, ICompletionRequest request, ICompletionResponse response) + String p, boolean forceUseOfPrefix, ICompletionRequest request, ICompletionResponse response, String schemaURI) throws BadLocationException { XMLGenerator generator = request.getXMLGenerator(); for (CMElementDeclaration child : cmElements) { @@ -101,9 +112,26 @@ private void fillWithChildrenElementDeclaration(DOMElement element, Collection elements; private DTDGrammar grammar; private Set hierarchies; + private String uri; + + public CMDTDDocument() {} + + public CMDTDDocument(String uri) { + this.uri = uri; + } @Override public Collection getElements() { @@ -60,6 +67,16 @@ public Collection getElements() { return elements; } + + /** + * Returns the URI of this document, is none was provided this + * returns null. + */ + @Override + public String getURI() { + return uri; + } + @Override public CMElementDeclaration findCMElement(DOMElement element, String namespace) { List paths = new ArrayList<>(); diff --git a/org.eclipse.lsp4xml/src/main/java/org/eclipse/lsp4xml/extensions/xsd/contentmodel/CMXSDContentModelProvider.java b/org.eclipse.lsp4xml/src/main/java/org/eclipse/lsp4xml/extensions/xsd/contentmodel/CMXSDContentModelProvider.java index f8951dde9..1ce365a70 100644 --- a/org.eclipse.lsp4xml/src/main/java/org/eclipse/lsp4xml/extensions/xsd/contentmodel/CMXSDContentModelProvider.java +++ b/org.eclipse.lsp4xml/src/main/java/org/eclipse/lsp4xml/extensions/xsd/contentmodel/CMXSDContentModelProvider.java @@ -73,7 +73,7 @@ public CMDocument createCMDocument(String key) { XSModel model = getLoader().loadURI(key); if (model != null) { // XML Schema can be loaded - return new CMXSDDocument(model); + return new CMXSDDocument(model, key); } return null; } diff --git a/org.eclipse.lsp4xml/src/main/java/org/eclipse/lsp4xml/extensions/xsd/contentmodel/CMXSDDocument.java b/org.eclipse.lsp4xml/src/main/java/org/eclipse/lsp4xml/extensions/xsd/contentmodel/CMXSDDocument.java index 5f8ed0232..6ba9538fe 100644 --- a/org.eclipse.lsp4xml/src/main/java/org/eclipse/lsp4xml/extensions/xsd/contentmodel/CMXSDDocument.java +++ b/org.eclipse.lsp4xml/src/main/java/org/eclipse/lsp4xml/extensions/xsd/contentmodel/CMXSDDocument.java @@ -43,11 +43,23 @@ public class CMXSDDocument implements CMDocument { private Collection elements; + private String uri; + public CMXSDDocument(XSModel model) { this.model = model; this.elementMappings = new HashMap<>(); } + public CMXSDDocument(XSModel model, String uri) { + this(model); + this.uri = uri; + } + + @Override + public String getURI() { + return uri; + } + @Override public Collection getElements() { if (elements == null) { diff --git a/org.eclipse.lsp4xml/src/test/java/org/eclipse/lsp4xml/XMLAssert.java b/org.eclipse.lsp4xml/src/test/java/org/eclipse/lsp4xml/XMLAssert.java index 4b3520c70..cfd25f41b 100644 --- a/org.eclipse.lsp4xml/src/test/java/org/eclipse/lsp4xml/XMLAssert.java +++ b/org.eclipse.lsp4xml/src/test/java/org/eclipse/lsp4xml/XMLAssert.java @@ -205,6 +205,19 @@ private static void assertCompletion(CompletionList completions, CompletionItem Assert.assertEquals(expected.getFilterText(), match.getFilterText()); } + if(expected.getDetail() != null) { + Assert.assertEquals(expected.getDetail(), match.getDetail()); + } + + } + + public static CompletionItem c(String label, TextEdit textEdit, String filterText, String detail) { + CompletionItem item = new CompletionItem(); + item.setLabel(label); + item.setFilterText(filterText); + item.setTextEdit(textEdit); + item.setDetail(detail); + return item; } public static CompletionItem c(String label, TextEdit textEdit, String filterText) { diff --git a/org.eclipse.lsp4xml/src/test/java/org/eclipse/lsp4xml/extensions/contentmodel/DTDCompletionExtensionsTest.java b/org.eclipse.lsp4xml/src/test/java/org/eclipse/lsp4xml/extensions/contentmodel/DTDCompletionExtensionsTest.java index 4cffb2e7a..1cccbddc1 100644 --- a/org.eclipse.lsp4xml/src/test/java/org/eclipse/lsp4xml/extensions/contentmodel/DTDCompletionExtensionsTest.java +++ b/org.eclipse.lsp4xml/src/test/java/org/eclipse/lsp4xml/extensions/contentmodel/DTDCompletionExtensionsTest.java @@ -44,6 +44,18 @@ public void completionWithChoiceAttribute() throws BadLocationException { testCompletionFor(xml, c("prefer", te(5, 11, 5, 11, "prefer=\"${1|system,public|}\"$0"), "prefer")); } + @Test + public void testCompletionDetailWithSource() throws BadLocationException { + // completion on <| + String xml = "\r\n" + // + " \r\n" + // + "\r\n" + // + " <|"; + testCompletionFor(xml, c("catalog", te(5, 2, 5, 3, "$1$0"), ""), "xs:attribute")); } + @Test + public void completionWithSourceDetail() throws BadLocationException { + // completion on | + String xml = "\r\n" + + " \r\n" + + // + "|"; + testCompletionFor(xml, c("xs:annotation", te(2, 0, 2, 0, ""), "xs:annotation", "Source: XMLSchema.xsd"), + c("xs:attribute", te(2, 0, 2, 0, ""), "xs:attribute", "Source: XMLSchema.xsd")); + } + + @Test + public void completionWithSourceDescriptionAndDetail() throws BadLocationException { + String xml = "\r\n" + // + "\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, ""), "")); + } + private void testCompletionFor(String xml, CompletionItem... expectedItems) throws BadLocationException { XMLAssert.testCompletionFor(xml, null, expectedItems); } diff --git a/org.eclipse.lsp4xml/src/test/resources/xsd/invoice.xsd b/org.eclipse.lsp4xml/src/test/resources/xsd/invoice.xsd index 90c751070..38c246bdd 100644 --- a/org.eclipse.lsp4xml/src/test/resources/xsd/invoice.xsd +++ b/org.eclipse.lsp4xml/src/test/resources/xsd/invoice.xsd @@ -8,9 +8,13 @@ An invoice type... - - - + + + Date Description + + + +