diff --git a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/contentmodel/model/ContentModelManager.java b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/contentmodel/model/ContentModelManager.java index f56e63a5d2..705b58ab88 100644 --- a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/contentmodel/model/ContentModelManager.java +++ b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/contentmodel/model/ContentModelManager.java @@ -23,6 +23,7 @@ import org.apache.xerces.xni.grammars.XMLGrammarPool; import org.eclipse.lemminx.dom.DOMDocument; import org.eclipse.lemminx.dom.DOMElement; +import org.eclipse.lemminx.extensions.contentmodel.model.ContentModelProvider.Identifier; import org.eclipse.lemminx.extensions.contentmodel.participants.diagnostics.LSPXMLGrammarPool; import org.eclipse.lemminx.extensions.contentmodel.settings.XMLFileAssociation; import org.eclipse.lemminx.extensions.contentmodel.uriresolver.XMLCacheResolverExtension; @@ -116,10 +117,12 @@ public Collection findCMDocument(DOMDocument xmlDocument, String nam // The content model provider can collect the system ids // ex for systemIds = modelProvider.getSystemIds(xmlDocument, namespaceURI); - for (String systemId : systemIds) { + Collection identifiers = modelProvider.getIdentifiers(xmlDocument, namespaceURI); + for (Identifier identifier : identifiers) { + String systemId = identifier.getSystemId(); + String publicId = identifier.getPublicId() != null ? identifier.getPublicId() : namespaceURI; // get the content model document from the current system id - CMDocument cmDocument = findCMDocument(xmlDocument.getDocumentURI(), namespaceURI, systemId, + CMDocument cmDocument = findCMDocument(xmlDocument.getDocumentURI(), publicId, systemId, modelProvider); if (cmDocument != null) { documents.add(cmDocument); @@ -151,9 +154,11 @@ public boolean dependsOnGrammar(DOMDocument document, String grammarURI) { } for (ContentModelProvider modelProvider : modelProviders) { if (modelProvider.adaptFor(document, false)) { - Collection systemIds = modelProvider.getSystemIds(document, document.getNamespaceURI()); - for (String systemId : systemIds) { - String key = resolverManager.resolve(document.getDocumentURI(), null, systemId); + Collection identifiers = modelProvider.getIdentifiers(document, document.getNamespaceURI()); + for (Identifier identifier : identifiers) { + String publicId = identifier.getPublicId(); + String systemId = identifier.getSystemId(); + String key = resolverManager.resolve(document.getDocumentURI(), publicId, systemId); if (grammarURI.equals(key)) { return true; } diff --git a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/contentmodel/model/ContentModelProvider.java b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/contentmodel/model/ContentModelProvider.java index aedf00aeee..1c241fcc75 100644 --- a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/contentmodel/model/ContentModelProvider.java +++ b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/contentmodel/model/ContentModelProvider.java @@ -22,13 +22,34 @@ */ public interface ContentModelProvider { + public class Identifier { + + private final String publicId; + + private final String systemId; + + public Identifier(String publicId, String systemId) { + this.publicId = publicId; + this.systemId = systemId; + } + + public String getPublicId() { + return publicId; + } + + public String getSystemId() { + return systemId; + } + + } + /** * Returns the content model provider by using standard association * (xsi:schemaLocation, xsi:noNamespaceSchemaLocation, doctype) an dnull * otherwise. * * @param document - * @param internal + * @param internal * @return the content model provider by using standard association * (xsi:schemaLocation, xsi:noNamespaceSchemaLocation, doctype) an dnull * otherwise. @@ -37,7 +58,7 @@ public interface ContentModelProvider { boolean adaptFor(String uri); - Collection getSystemIds(DOMDocument xmlDocument, String namespaceURI); + Collection getIdentifiers(DOMDocument xmlDocument, String namespaceURI); CMDocument createCMDocument(String key); diff --git a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/dtd/contentmodel/CMDTDContentModelProvider.java b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/dtd/contentmodel/CMDTDContentModelProvider.java index 2988f68749..1d94fed5e9 100644 --- a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/dtd/contentmodel/CMDTDContentModelProvider.java +++ b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/dtd/contentmodel/CMDTDContentModelProvider.java @@ -72,14 +72,15 @@ public boolean adaptFor(String uri) { } @Override - public Collection getSystemIds(DOMDocument xmlDocument, String namespaceURI) { + public Collection getIdentifiers(DOMDocument xmlDocument, String namespaceURI) { /* * */ DOMDocumentType documentType = xmlDocument.getDoctype(); - return Collections.singleton(documentType.getSystemIdWithoutQuotes()); + return Collections.singleton( + new Identifier(documentType.getPublicIdWithoutQuotes(), documentType.getSystemIdWithoutQuotes())); } @Override diff --git a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xmlmodel/contentmodel/CMXMLModelContentModelProvider.java b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xmlmodel/contentmodel/CMXMLModelContentModelProvider.java index 72b0ca15da..6fcd412ab0 100644 --- a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xmlmodel/contentmodel/CMXMLModelContentModelProvider.java +++ b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xmlmodel/contentmodel/CMXMLModelContentModelProvider.java @@ -47,9 +47,12 @@ public boolean adaptFor(String uri) { } @Override - public Collection getSystemIds(DOMDocument xmlDocument, String namespaceURI) { - return xmlDocument.getXMLModels().stream().map(node -> node.getHref()) - .filter(href -> !StringUtils.isEmpty(href)).collect(Collectors.toList()); + public Collection getIdentifiers(DOMDocument xmlDocument, String namespaceURI) { + return xmlDocument.getXMLModels().stream() // + .map(node -> node.getHref()) // + .filter(href -> !StringUtils.isEmpty(href)) // + .map(href -> new Identifier(null, href)) // + .collect(Collectors.toList()); } @Override diff --git a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xsd/contentmodel/CMXSDContentModelProvider.java b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xsd/contentmodel/CMXSDContentModelProvider.java index 2cc67927bf..e7e44dcab2 100644 --- a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xsd/contentmodel/CMXSDContentModelProvider.java +++ b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xsd/contentmodel/CMXSDContentModelProvider.java @@ -55,13 +55,13 @@ public boolean adaptFor(String uri) { } @Override - public Collection getSystemIds(DOMDocument xmlDocument, String namespaceURI) { - Collection systemIds = new ArrayList<>(); + public Collection getIdentifiers(DOMDocument xmlDocument, String namespaceURI) { + Collection identifiers = new ArrayList<>(); SchemaLocation schemaLocation = xmlDocument.getSchemaLocation(); if (schemaLocation != null) { String location = schemaLocation.getLocationHint(namespaceURI); if (!StringUtils.isEmpty(location)) { - systemIds.add(location); + identifiers.add(new Identifier(null, location)); } } else { NoNamespaceSchemaLocation noNamespaceSchemaLocation = xmlDocument.getNoNamespaceSchemaLocation(); @@ -70,12 +70,12 @@ public Collection getSystemIds(DOMDocument xmlDocument, String namespace // xsi:noNamespaceSchemaLocation doesn't define namespaces String location = noNamespaceSchemaLocation.getLocation(); if (!StringUtils.isEmpty(location)) { - systemIds.add(location); + identifiers.add(new Identifier(null, location)); } } } } - return systemIds; + return identifiers; } @Override @@ -94,7 +94,7 @@ public CMDocument createInternalCMDocument(DOMDocument xmlDocument) { return null; } - public XSLoaderImpl getLoader() { + public XSLoaderImpl getLoader() { XSLoaderImpl loader = new XSLoaderImpl(); loader.setParameter("http://apache.org/xml/properties/internal/entity-resolver", resolverExtensionManager); loader.setParameter(Constants.DOM_ERROR_HANDLER, new DOMErrorHandler() { diff --git a/org.eclipse.lemminx/src/test/java/org/eclipse/lemminx/extensions/contentmodel/DTDCompletionExtensionsTest.java b/org.eclipse.lemminx/src/test/java/org/eclipse/lemminx/extensions/contentmodel/DTDCompletionExtensionsTest.java index bbcd39a68b..d2b0f61a45 100644 --- a/org.eclipse.lemminx/src/test/java/org/eclipse/lemminx/extensions/contentmodel/DTDCompletionExtensionsTest.java +++ b/org.eclipse.lemminx/src/test/java/org/eclipse/lemminx/extensions/contentmodel/DTDCompletionExtensionsTest.java @@ -11,9 +11,9 @@ *******************************************************************************/ package org.eclipse.lemminx.extensions.contentmodel; +import static org.eclipse.lemminx.XMLAssert.CDATA_SNIPPETS; import static org.eclipse.lemminx.XMLAssert.COMMENT_SNIPPETS; import static org.eclipse.lemminx.XMLAssert.DTDNODE_SNIPPETS; -import static org.eclipse.lemminx.XMLAssert.CDATA_SNIPPETS; import static org.eclipse.lemminx.XMLAssert.PROCESSING_INSTRUCTION_SNIPPETS; import static org.eclipse.lemminx.XMLAssert.c; import static org.eclipse.lemminx.XMLAssert.te; @@ -241,12 +241,34 @@ public void attributeCompletionWithDoctypeSubsetWithNoElements() throws BadLocat "xmlns:xsi")); } + @Test + public void completionWithCatalogAndPublic() throws Exception { + // This test uses the local DTD with catalog-public.xml by using the PUBLIC ID + // -//Sun Microsystems, Inc.//DTD Web Application 2.3//EN + // + String xml = " \r\n" + // + "\r\n" + // + "\r\n" + // + "|"; + testCompletionFor(xml, true, null, "catalog-public.xml", + c("icon", te(5, 9, 5, 9, "$1$0"), "icon"), // + c("display-name", te(5, 9, 5, 9, "$1$0"), "display-name")); + } + private void testCompletionFor(String xml, CompletionItem... expectedItems) throws BadLocationException { testCompletionFor(xml, true, null, expectedItems); } private void testCompletionFor(String xml, boolean isSnippetsSupported, Integer expectedCount, CompletionItem... expectedItems) throws BadLocationException { + testCompletionFor(xml, isSnippetsSupported, expectedCount, "catalog.xml", expectedItems); + } + + private void testCompletionFor(String xml, boolean isSnippetsSupported, Integer expectedCount, String catalog, + CompletionItem... expectedItems) throws BadLocationException { CompletionCapabilities completionCapabilities = new CompletionCapabilities(); CompletionItemCapabilities completionItem = new CompletionItemCapabilities(isSnippetsSupported); // activate // snippets @@ -254,7 +276,7 @@ private void testCompletionFor(String xml, boolean isSnippetsSupported, Integer SharedSettings sharedSettings = new SharedSettings(); sharedSettings.getCompletionSettings().setCapabilities(completionCapabilities); - XMLAssert.testCompletionFor(new XMLLanguageService(), xml, "src/test/resources/catalogs/catalog.xml", null, - null, expectedCount, sharedSettings, expectedItems); + XMLAssert.testCompletionFor(new XMLLanguageService(), xml, "src/test/resources/catalogs/" + catalog, null, null, + expectedCount, sharedSettings, expectedItems); } }