diff --git a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/dom/DTDEntityDecl.java b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/dom/DTDEntityDecl.java index ff2eec25c..6541cc44b 100644 --- a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/dom/DTDEntityDecl.java +++ b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/dom/DTDEntityDecl.java @@ -114,7 +114,7 @@ public String getNotationName() { */ @Override public String getPublicId() { - return publicId != null ? publicId.getParameter() : null; + return publicId != null ? publicId.getParameterWithoutFirstAndLastChar() : null; } public void setPublicId(int start, int end) { @@ -128,7 +128,7 @@ public void setPublicId(int start, int end) { */ @Override public String getSystemId() { - return systemId != null ? systemId.getParameter() : null; + return systemId != null ? systemId.getParameterWithoutFirstAndLastChar() : null; } public void setSystemId(int start, int end) { diff --git a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/dom/DTDNotationDecl.java b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/dom/DTDNotationDecl.java index 869910e59..36131e152 100644 --- a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/dom/DTDNotationDecl.java +++ b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/dom/DTDNotationDecl.java @@ -54,7 +54,7 @@ void setPublicId(int start, int end) { } public String getPublicId() { - return publicId != null ? publicId.getParameter() : null; + return publicId != null ? publicId.getParameterWithoutFirstAndLastChar() : null; } void setSystemId(int start, int end) { @@ -62,7 +62,7 @@ void setSystemId(int start, int end) { } public String getSystemId() { - return systemId != null ? systemId.getParameter() : null; + return systemId != null ? systemId.getParameterWithoutFirstAndLastChar() : null; } @Override diff --git a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/dtd/contentmodel/CMDTDDocument.java b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/dtd/contentmodel/CMDTDDocument.java index 9da84dd67..4175415e8 100644 --- a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/dtd/contentmodel/CMDTDDocument.java +++ b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/dtd/contentmodel/CMDTDDocument.java @@ -28,6 +28,7 @@ import org.apache.xerces.impl.dtd.DTDGrammar; import org.apache.xerces.impl.dtd.XMLDTDLoader; import org.apache.xerces.xni.Augmentations; +import org.apache.xerces.xni.XMLResourceIdentifier; import org.apache.xerces.xni.XMLString; import org.apache.xerces.xni.XNIException; import org.apache.xerces.xni.grammars.Grammar; @@ -101,12 +102,28 @@ private static class ScannedDTDEntityDecl extends DTDEntityDecl { private final String entityName; private final String value; + private final DTDDeclParameter nameParameter; + private final String publicId; + + private final String systemId; + public ScannedDTDEntityDecl(String entityName, String value, ScannedEntity scannedEntity) { + this(entityName, value, null, scannedEntity); + } + + public ScannedDTDEntityDecl(String name, XMLResourceIdentifier identifier, ScannedEntity scannedEntity) { + this(name, null, identifier, scannedEntity); + } + + private ScannedDTDEntityDecl(String entityName, String value, XMLResourceIdentifier identifier, + ScannedEntity scannedEntity) { super(-1, -1); this.entityName = entityName; this.value = value; + this.publicId = identifier != null ? identifier.getPublicId() : null; + this.systemId = identifier != null ? identifier.getLiteralSystemId() : null; this.nameParameter = createNameParameter(entityName, scannedEntity); } @@ -130,6 +147,16 @@ public String getNotationName() { return value; } + @Override + public String getSystemId() { + return systemId; + } + + @Override + public String getPublicId() { + return publicId; + } + private static DTDDeclParameter createNameParameter(String name, ScannedEntity scannedEntity) { String systemId = scannedEntity.entityLocation.getExpandedSystemId(); int lineNumber = scannedEntity.lineNumber - 1; @@ -170,7 +197,8 @@ private static int getEntityNameStartColumnNumber(String entityName, ScannedEnti char[] ch = scannedEntity.ch; int wordIndex = entityName.length(); // int startEntityNameIndex = -1; - // Loop for characters from the end of the entity (>) to search the entity name start offset + // Loop for characters from the end of the entity (>) to search the entity name + // start offset // | for (int i = endEntityIndex; i >= 0; i--) { char c = ch[i]; @@ -292,6 +320,17 @@ public void internalEntityDecl(String name, XMLString text, XMLString nonNormali } } + @Override + public void externalEntityDecl(String name, XMLResourceIdentifier identifier, Augmentations augs) + throws XNIException { + super.externalEntityDecl(name, identifier, augs); + try { + entities.add(new ScannedDTDEntityDecl(name, identifier, fEntityManager.getCurrentEntity())); + } catch (Exception e) { + LOGGER.log(Level.SEVERE, "Error while extracting information for the external entity '" + name + "'", e); + } + } + @Override public void startContentModel(String elementName, Augmentations augs) throws XNIException { if (hierarchiesMap == null) { diff --git a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/entities/EntitiesDocumentationUtils.java b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/entities/EntitiesDocumentationUtils.java index ba1d022db..8f3e88b78 100644 --- a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/entities/EntitiesDocumentationUtils.java +++ b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/entities/EntitiesDocumentationUtils.java @@ -12,6 +12,7 @@ */ package org.eclipse.lemminx.extensions.entities; +import org.eclipse.lemminx.dom.DTDEntityDecl; import org.eclipse.lsp4j.MarkupContent; import org.eclipse.lsp4j.MarkupKind; @@ -64,6 +65,19 @@ public String getValue() { private EntitiesDocumentationUtils() { } + public static MarkupContent getDocumentation(String entityName, String entityValue, EntityOriginType type, + boolean markdown) { + return getDocumentation(entityName, entityValue, null, null, null, type, markdown); + } + + public static MarkupContent getDocumentation(DTDEntityDecl entity, EntityOriginType type, boolean markdown) { + String systemID = entity.getSystemId(); + String publicID = entity.getPublicId(); + String targetURI = entity.getNameParameter().getTargetURI(); + return getDocumentation(entity.getName(), entity.getNotationName(), systemID, publicID, targetURI, type, + markdown); + } + /** * Returns the entity documentation. * @@ -74,8 +88,8 @@ private EntitiesDocumentationUtils() { * false otherwise. * @return the entity documentation. */ - public static MarkupContent getDocumentation(String entityName, String entityValue, EntityOriginType type, - boolean markdown) { + public static MarkupContent getDocumentation(String entityName, String entityValue, String systemID, + String publicID, String targetURI, EntityOriginType type, boolean markdown) { StringBuilder documentation = new StringBuilder(); // Title @@ -88,15 +102,32 @@ public static MarkupContent getDocumentation(String entityName, String entityVal documentation.append("**"); } - if (entityValue != null && !entityValue.isEmpty()) { - addParameter("Value", entityValue, documentation, markdown); - } + addParameter("Value", entityValue, documentation, markdown); addParameter("Type", type.getLabel(), documentation, markdown); + addParameter("Public ID", publicID, documentation, markdown); + addParameter("System ID", systemID, documentation, markdown); + if (targetURI != null) { + documentation.append(System.lineSeparator()); + if (markdown) { + documentation.append(" * "); + } + documentation.append("Source: "); + if (markdown) { + documentation.append("["); + documentation.append(getFileName(targetURI)); + documentation.append("]"); + documentation.append("("); + } + documentation.append(targetURI); + if (markdown) { + documentation.append(")"); + } + } return new MarkupContent(markdown ? MarkupKind.MARKDOWN : MarkupKind.PLAINTEXT, documentation.toString()); } private static void addParameter(String name, String value, StringBuilder documentation, boolean markdown) { - if (value != null) { + if (value != null && !value.isEmpty()) { documentation.append(System.lineSeparator()); if (markdown) { documentation.append(" * "); @@ -113,4 +144,20 @@ private static void addParameter(String name, String value, StringBuilder docume } } + /** + * Returns the file name from the given schema URI + * + * @param schemaURI the schema URI + * @return the file name from the given schema URI + */ + private static String getFileName(String schemaURI) { + int index = schemaURI.lastIndexOf('/'); + if (index == -1) { + index = schemaURI.lastIndexOf('\\'); + } + if (index == -1) { + return schemaURI; + } + return schemaURI.substring(index + 1, schemaURI.length()); + } } diff --git a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/entities/participants/EntitiesCompletionParticipant.java b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/entities/participants/EntitiesCompletionParticipant.java index 9826a37d6..360906f21 100644 --- a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/entities/participants/EntitiesCompletionParticipant.java +++ b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/entities/participants/EntitiesCompletionParticipant.java @@ -17,6 +17,7 @@ import org.eclipse.lemminx.dom.DOMDocument; import org.eclipse.lemminx.dom.DOMDocumentType; +import org.eclipse.lemminx.dom.DTDEntityDecl; import org.eclipse.lemminx.extensions.contentmodel.model.CMDocument; import org.eclipse.lemminx.extensions.contentmodel.model.ContentModelManager; import org.eclipse.lemminx.extensions.entities.EntitiesDocumentationUtils; @@ -30,6 +31,7 @@ import org.eclipse.lsp4j.CompletionItem; import org.eclipse.lsp4j.CompletionItemKind; import org.eclipse.lsp4j.InsertTextFormat; +import org.eclipse.lsp4j.MarkupContent; import org.eclipse.lsp4j.MarkupKind; import org.eclipse.lsp4j.Range; import org.eclipse.lsp4j.TextEdit; @@ -78,8 +80,9 @@ private static void collectLocalEntityProposals(DOMDocument document, Range enti Entity entity = (Entity) entities.item(i); if (entity.getNodeName() != null) { // provide completion for the locally declared entity - fillCompletion(entity.getNodeName(), entity.getNotationName(), EntityOriginType.LOCAL, entityRange, - markdown, response); + MarkupContent documentation = EntitiesDocumentationUtils.getDocumentation((DTDEntityDecl) entity, + EntityOriginType.LOCAL, markdown); + fillCompletion(entity.getNodeName(), documentation, entityRange, response); } } } @@ -103,8 +106,9 @@ private static void collectExternalEntityProposals(DOMDocument document, Range e for (Entity entity : entities) { if (entity.getNodeName() != null) { // provide completion for the external declared entity - fillCompletion(entity.getNodeName(), entity.getNotationName(), EntityOriginType.EXTERNAL, - entityRange, markdown, response); + MarkupContent documentation = EntitiesDocumentationUtils.getDocumentation((DTDEntityDecl) entity, + EntityOriginType.EXTERNAL, markdown); + fillCompletion(entity.getNodeName(), documentation, entityRange, response); } } } @@ -123,13 +127,14 @@ private static void collectExternalEntityProposals(DOMDocument document, Range e private void collectPredefinedEntityProposals(Range entityRange, boolean markdown, ICompletionResponse response) { PredefinedEntity[] entities = PredefinedEntity.values(); for (PredefinedEntity entity : entities) { - fillCompletion(entity.getName(), entity.getValue(), EntityOriginType.PREDEFINED, entityRange, markdown, - response); + MarkupContent documentation = EntitiesDocumentationUtils.getDocumentation(entity.getName(), + entity.getValue(), EntityOriginType.PREDEFINED, markdown); + fillCompletion(entity.getName(), documentation, entityRange, response); } } - private static void fillCompletion(String name, String entityValue, EntityOriginType type, Range entityRange, - boolean markdown, ICompletionResponse response) { + private static void fillCompletion(String name, MarkupContent documentation, Range entityRange, + ICompletionResponse response) { String entityName = "&" + name + ";"; CompletionItem item = new CompletionItem(); item.setLabel(entityName); @@ -138,7 +143,7 @@ private static void fillCompletion(String name, String entityValue, EntityOrigin String insertText = entityName; item.setFilterText(insertText); item.setTextEdit(new TextEdit(entityRange, insertText)); - item.setDocumentation(EntitiesDocumentationUtils.getDocumentation(name, entityValue, type, markdown)); + item.setDocumentation(documentation); response.addCompletionItem(item); } diff --git a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/entities/participants/EntitiesHoverParticipant.java b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/entities/participants/EntitiesHoverParticipant.java index 33fa67b11..2af1232f1 100644 --- a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/entities/participants/EntitiesHoverParticipant.java +++ b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/entities/participants/EntitiesHoverParticipant.java @@ -136,8 +136,7 @@ private static MarkupContent searchInLocalEntities(String entityName, Range enti DTDEntityDecl entity = (DTDEntityDecl) entities.item(i); if (entityName.equals(entity.getName())) { boolean markdown = request.canSupportMarkupKind(MarkupKind.MARKDOWN); - return EntitiesDocumentationUtils.getDocumentation(entity.getName(), entity.getNotationName(), - EntityOriginType.LOCAL, markdown); + return EntitiesDocumentationUtils.getDocumentation(entity, EntityOriginType.LOCAL, markdown); } } return null; @@ -164,8 +163,7 @@ private static MarkupContent searchInExternalEntities(String entityName, Range e DTDEntityDecl entity = (DTDEntityDecl) ent; if (entityName.equals(entity.getName())) { boolean markdown = request.canSupportMarkupKind(MarkupKind.MARKDOWN); - return EntitiesDocumentationUtils.getDocumentation(entity.getName(), entity.getNotationName(), - EntityOriginType.EXTERNAL, markdown); + return EntitiesDocumentationUtils.getDocumentation(entity, EntityOriginType.EXTERNAL, markdown); } } } diff --git a/org.eclipse.lemminx/src/test/java/org/eclipse/lemminx/dom/DOMParserForInternalDTDTest.java b/org.eclipse.lemminx/src/test/java/org/eclipse/lemminx/dom/DOMParserForInternalDTDTest.java index b030f5ee4..82c382d38 100644 --- a/org.eclipse.lemminx/src/test/java/org/eclipse/lemminx/dom/DOMParserForInternalDTDTest.java +++ b/org.eclipse.lemminx/src/test/java/org/eclipse/lemminx/dom/DOMParserForInternalDTDTest.java @@ -514,8 +514,8 @@ public void entityDeclWithNameClosedAndParameters() { assertEquals("%", entityDecl.getPercent()); assertEquals("eName", entityDecl.getNodeName()); assertEquals("PUBLIC", entityDecl.getKind()); - assertEquals("\"publicId\"", entityDecl.getPublicId()); - assertEquals("\"systemId\"", entityDecl.getSystemId()); + assertEquals("publicId", entityDecl.getPublicId()); + assertEquals("systemId", entityDecl.getSystemId()); // element assertTrue(actual.getChild(1).isElement()); @@ -544,7 +544,7 @@ public void entityDeclWithNameClosedAndSomeParameters() { assertEquals("%", entityDecl.getPercent()); assertEquals("eName", entityDecl.getNodeName()); assertEquals("PUBLIC", entityDecl.getKind()); - assertEquals("\"publicId\"", entityDecl.getPublicId()); + assertEquals("publicId", entityDecl.getPublicId()); assertEquals(null, entityDecl.getSystemId()); // element @@ -772,8 +772,8 @@ public void dtdNotationComplete() { assertEquals(65, elementDecl.getEnd()); assertEquals("Name", elementDecl.getName()); assertEquals("PUBLIC", elementDecl.getKind()); - assertEquals("\"PublicID\"", elementDecl.getPublicId()); - assertEquals("\"SystemID\"", elementDecl.getSystemId()); + assertEquals("PublicID", elementDecl.getPublicId()); + assertEquals("SystemID", elementDecl.getSystemId()); assertTrue(elementDecl.isClosed()); } @@ -805,7 +805,7 @@ public void dtdNotationSYSTEMUnrecognizedParameter() { assertEquals(65, elementDecl.getEnd()); assertEquals("Name", elementDecl.getName()); assertEquals("SYSTEM", elementDecl.getKind()); - assertEquals("\"PublicID\"", elementDecl.getSystemId()); + assertEquals("PublicID", elementDecl.getSystemId()); assertEquals("\"SystemID\"", elementDecl.getUnrecognized()); assertTrue(elementDecl.isClosed()); diff --git a/org.eclipse.lemminx/src/test/java/org/eclipse/lemminx/extensions/contentmodel/DTDDocumentLinkTest.java b/org.eclipse.lemminx/src/test/java/org/eclipse/lemminx/extensions/contentmodel/DTDDocumentLinkTest.java index ae95d9b01..facf11a6d 100644 --- a/org.eclipse.lemminx/src/test/java/org/eclipse/lemminx/extensions/contentmodel/DTDDocumentLinkTest.java +++ b/org.eclipse.lemminx/src/test/java/org/eclipse/lemminx/extensions/contentmodel/DTDDocumentLinkTest.java @@ -27,29 +27,29 @@ public class DTDDocumentLinkTest { @Test public void docTypeSYSTEM() throws BadLocationException { String xml = "\r\n" + // - "\r\n" + // ""; XMLAssert.testDocumentLinkFor(xml, "src/test/resources/xml/base.xml", - dl(r(1, 31, 1, 46), "src/test/resources/dtd/base.dtd")); + dl(r(1, 31, 1, 55), "src/test/resources/dtd/entities/base.dtd")); } @Test public void docTypePUBLIC() throws BadLocationException { String xml = "\r\n" + // - "\r\n" + // ""; XMLAssert.testDocumentLinkFor(xml, "src/test/resources/xml/base.xml", - dl(r(1, 38, 1, 53), "src/test/resources/dtd/base.dtd")); + dl(r(1, 38, 1, 62), "src/test/resources/dtd/entities/base.dtd")); } @Test public void noLinks() throws BadLocationException { String xml = "\r\n" + // - "\r\n" + // ""; diff --git a/org.eclipse.lemminx/src/test/java/org/eclipse/lemminx/extensions/entities/EntitiesCompletionExtensionsTest.java b/org.eclipse.lemminx/src/test/java/org/eclipse/lemminx/extensions/entities/EntitiesCompletionExtensionsTest.java index b7b460c92..844855e0b 100644 --- a/org.eclipse.lemminx/src/test/java/org/eclipse/lemminx/extensions/entities/EntitiesCompletionExtensionsTest.java +++ b/org.eclipse.lemminx/src/test/java/org/eclipse/lemminx/extensions/entities/EntitiesCompletionExtensionsTest.java @@ -28,6 +28,21 @@ public class EntitiesCompletionExtensionsTest { // Test for local entities + @Test + public void localWithSYSTEM() throws BadLocationException { + // &| + String xml = "\r\n" + // + " \r\n" + // + " \r\n" + // + " ]>\r\n" + // + " &|"; + testCompletionFor(xml, 1 + // + 2 /* CDATA and Comments */ + // + PredefinedEntity.values().length /* predefined entities */, // + c("&c;", "&c;", r(5, 12, 5, 13), "&c;")); + } + @Test public void afterAmp() throws BadLocationException { // &| @@ -125,10 +140,11 @@ public void none() throws BadLocationException { } // Test for external entities + @Test public void external() throws BadLocationException { String xml = "\r\n" + // - "\r\n" + // "]>\r\n" + // "\r\n" + // @@ -141,12 +157,24 @@ public void external() throws BadLocationException { c("&foo;", "&foo;", r(6, 1, 6, 2), "&foo;")); } + @Test + public void externalWithSYSTEM() throws BadLocationException { + String xml = "\r\n" + // + "\r\n" + // + "&|"; + testCompletionFor(xml, null, "test.xml", 2 + // + 2 /* CDATA and Comments */ + // + PredefinedEntity.values().length /* predefined entities */, + c("&writer;", "&writer;", r(2, 8, 2, 9), "&writer;"), // + c("©right;", "©right;", r(2, 8, 2, 9), "©right;")); + } + @Test public void bug_vscode_xml_262() throws BadLocationException { // See // https://github.com/redhat-developer/vscode-xml/issues/262#issuecomment-634716408 String xml = "\r\n" + // - "\r\n" + "\r\n" + // "]>\r\n" + // "\r\n" + // diff --git a/org.eclipse.lemminx/src/test/java/org/eclipse/lemminx/extensions/entities/EntitiesDefinitionExtensionsTest.java b/org.eclipse.lemminx/src/test/java/org/eclipse/lemminx/extensions/entities/EntitiesDefinitionExtensionsTest.java index c05f8d6cf..d9c024f74 100644 --- a/org.eclipse.lemminx/src/test/java/org/eclipse/lemminx/extensions/entities/EntitiesDefinitionExtensionsTest.java +++ b/org.eclipse.lemminx/src/test/java/org/eclipse/lemminx/extensions/entities/EntitiesDefinitionExtensionsTest.java @@ -39,6 +39,17 @@ public void local() throws BadLocationException { testDefinitionFor(xml, "test.xml", ll("test.xml", r(5, 2, 5, 9), r(2, 11, 2, 16))); } + @Test + public void localWithSYSTEM() throws BadLocationException { + String xml = "\r\n" + // + " \r\n" + // + " \r\n" + // + " ]>\r\n" + // + " &|c;"; + testDefinitionFor(xml, "test.xml", ll("test.xml", r(5, 12, 5, 15), r(3, 12, 3, 13))); + } + @Test public void beforeAmp() throws BadLocationException { String xml = "\r\n" + // @@ -92,9 +103,9 @@ public void underscoreEntityName() throws BadLocationException { @Test public void externalWithIndent() throws BadLocationException, MalformedURIException { - String dtdFileURI = getDTDFileURI("src/test/resources/dtd/base.dtd"); + String dtdFileURI = getDTDFileURI("src/test/resources/dtd/entities/base.dtd"); String xml = "\r\n" + // - "\r\n" + // "]>\r\n" + // "\r\n" + // @@ -105,11 +116,11 @@ public void externalWithIndent() throws BadLocationException, MalformedURIExcept @Test public void externalWithDTDIndent() throws BadLocationException, MalformedURIException { - String dtdFileURI = getDTDFileURI("src/test/resources/dtd/base-indent.dtd"); + String dtdFileURI = getDTDFileURI("src/test/resources/dtd/entities/base-indent.dtd"); // &external3; String xml = "\r\n" + // - "\r\n" + // "]>\r\n" + // "\r\n" + // @@ -119,7 +130,7 @@ public void externalWithDTDIndent() throws BadLocationException, MalformedURIExc // &external5; xml = "\r\n" + // - "\r\n" + // "]>\r\n" + // "\r\n" + // @@ -129,7 +140,7 @@ public void externalWithDTDIndent() throws BadLocationException, MalformedURIExc // &external; xml = "\r\n" + // - "\r\n" + // "]>\r\n" + // "\r\n" + // @@ -139,7 +150,7 @@ public void externalWithDTDIndent() throws BadLocationException, MalformedURIExc // &external2; xml = "\r\n" + // - "\r\n" + // "]>\r\n" + // "\r\n" + // @@ -150,11 +161,11 @@ public void externalWithDTDIndent() throws BadLocationException, MalformedURIExc @Test public void externalWithDTDNoIndent() throws BadLocationException, MalformedURIException { - String dtdFileURI = getDTDFileURI("src/test/resources/dtd/base-no-indent.dtd"); + String dtdFileURI = getDTDFileURI("src/test/resources/dtd/entities/base-no-indent.dtd"); // &external3; String xml = "\r\n" + // - "\r\n" + // "]>\r\n" + // "\r\n" + // @@ -164,7 +175,7 @@ public void externalWithDTDNoIndent() throws BadLocationException, MalformedURIE // &external5; xml = "\r\n" + // - "\r\n" + // "]>\r\n" + // "\r\n" + // @@ -174,7 +185,7 @@ public void externalWithDTDNoIndent() throws BadLocationException, MalformedURIE // &external; xml = "\r\n" + // - "\r\n" + // "]>\r\n" + // "\r\n" + // @@ -184,7 +195,7 @@ public void externalWithDTDNoIndent() throws BadLocationException, MalformedURIE // &external2; xml = "\r\n" + // - "\r\n" + // "]>\r\n" + // "\r\n" + // @@ -193,6 +204,24 @@ public void externalWithDTDNoIndent() throws BadLocationException, MalformedURIE testDefinitionFor(xml, "test.xml", ll(dtdFileURI, r(6, 1, 6, 12), r(4, 9, 4, 18))); } + @Test + public void externalWithSYSTEM() throws BadLocationException, MalformedURIException { + String dtdFileURI = getDTDFileURI("src/test/resources/dtd/entities/base-system.dtd"); + + // &writer; + String xml = "\r\n" + // + "\r\n" + // + "&wr|iter;©right;"; + testDefinitionFor(xml, "test.xml", ll(dtdFileURI, r(2, 8, 2, 16), r(1, 9, 1, 15))); + + // ©right; + xml = "\r\n" + // + "\r\n" + // + "&writer;&cop|yright;"; + testDefinitionFor(xml, "test.xml", ll(dtdFileURI, r(2, 16, 2, 27), r(2, 9, 2, 18))); + + } + private static String getDTDFileURI(String dtdURI) throws MalformedURIException { return XMLEntityManager.expandSystemId(dtdURI, "test.xml", true).replace("///", "/"); } diff --git a/org.eclipse.lemminx/src/test/java/org/eclipse/lemminx/extensions/entities/EntitiesHoverExtensionsTest.java b/org.eclipse.lemminx/src/test/java/org/eclipse/lemminx/extensions/entities/EntitiesHoverExtensionsTest.java index 9eb9f3777..df2566b51 100644 --- a/org.eclipse.lemminx/src/test/java/org/eclipse/lemminx/extensions/entities/EntitiesHoverExtensionsTest.java +++ b/org.eclipse.lemminx/src/test/java/org/eclipse/lemminx/extensions/entities/EntitiesHoverExtensionsTest.java @@ -15,6 +15,8 @@ import static org.eclipse.lemminx.XMLAssert.assertHover; import static org.eclipse.lemminx.XMLAssert.r; +import org.apache.xerces.impl.XMLEntityManager; +import org.apache.xerces.util.URI.MalformedURIException; import org.eclipse.lemminx.commons.BadLocationException; import org.junit.jupiter.api.Test; @@ -35,33 +37,89 @@ public void local() throws BadLocationException { "\r\n" + // " &mdas|h;\r\n" + // <- here definition for mdash ""; - assertHover(xml, "**Entity mdash**" + // + assertHover(xml, "src/test/resources/test.xml", "**Entity mdash**" + // System.lineSeparator() + // " * Value: `—`" + // System.lineSeparator() + // - " * Type: `Local`", // + " * Type: `Local`" + // + System.lineSeparator() + // + " * Source: [test.xml](src/test/resources/test.xml)", // r(5, 2, 5, 9)); } + @Test + public void localWithSYSTEM() throws BadLocationException { + String xml = "\r\n" + // + " \r\n" + // + " \r\n" + // + " ]>\r\n" + // + " &|c;"; + assertHover(xml, "src/test/resources/test.xml", "**Entity c**" + // + System.lineSeparator() + // + " * Type: `Local`" + // + System.lineSeparator() + // + " * System ID: `http://www.xmlwriter.net/copyright.xml`" + // + System.lineSeparator() + // + " * Source: [test.xml](src/test/resources/test.xml)", // + r(5, 12, 5, 15)); + } + // Test for external entities @Test - public void external() throws BadLocationException { + public void external() throws Exception { + String baseDTDURI = getDTDFileURI("base.dtd"); String xml = "\r\n" + // - "\r\n" + // "]>\r\n" + // "\r\n" + // "\r\n &f|oo;" + // ""; - assertHover(xml, "test.xml", "**Entity foo**" + // + assertHover(xml, "src/test/resources/test.xml", "**Entity foo**" + // System.lineSeparator() + // " * Value: `bar`" + // System.lineSeparator() + // - " * Type: `External`", // + " * Type: `External`" + // + System.lineSeparator() + // + " * Source: [base.dtd](" + baseDTDURI + ")", // r(6, 1, 6, 6)); } + @Test + public void externalWithSYSTEM() throws Exception { + String baseDTDURI = getDTDFileURI("base-system.dtd"); + + // &writer; + String xml = "\r\n" + // + "\r\n" + // + "&wr|iter;©right;"; + assertHover(xml, "src/test/resources/test.xml", "**Entity writer**" + // + System.lineSeparator() + // + " * Type: `External`" + // + System.lineSeparator() + // + " * Public ID: `public id`" + // + System.lineSeparator() + // + " * System ID: `entity uri`" + // + System.lineSeparator() + // + " * Source: [base-system.dtd](" + baseDTDURI + ")", // + r(2, 8, 2, 16)); + + // ©right; + xml = "\r\n" + // + "\r\n" + // + "&writer;&cop|yright;"; + assertHover(xml, "src/test/resources/test.xml", "**Entity copyright**" + // + System.lineSeparator() + // + " * Type: `External`" + // + System.lineSeparator() + // + " * System ID: `uri`" + // + System.lineSeparator() + // + " * Source: [base-system.dtd](" + baseDTDURI + ")", // + r(2, 16, 2, 27)); + } + // Test for predefined entities @Test @@ -76,4 +134,8 @@ public void predefined() throws BadLocationException { " * Type: `Predefined`", // r(2, 2, 2, 7)); } + + private static String getDTDFileURI(String dtdURI) throws MalformedURIException { + return XMLEntityManager.expandSystemId("dtd/entities/" + dtdURI, "src/test/resources/test.xml", true); + } } diff --git a/org.eclipse.lemminx/src/test/resources/dtd/base-indent.dtd b/org.eclipse.lemminx/src/test/resources/dtd/entities/base-indent.dtd similarity index 100% rename from org.eclipse.lemminx/src/test/resources/dtd/base-indent.dtd rename to org.eclipse.lemminx/src/test/resources/dtd/entities/base-indent.dtd diff --git a/org.eclipse.lemminx/src/test/resources/dtd/base-no-indent.dtd b/org.eclipse.lemminx/src/test/resources/dtd/entities/base-no-indent.dtd similarity index 100% rename from org.eclipse.lemminx/src/test/resources/dtd/base-no-indent.dtd rename to org.eclipse.lemminx/src/test/resources/dtd/entities/base-no-indent.dtd diff --git a/org.eclipse.lemminx/src/test/resources/dtd/entities/base-system.dtd b/org.eclipse.lemminx/src/test/resources/dtd/entities/base-system.dtd new file mode 100644 index 000000000..7a09dc33c --- /dev/null +++ b/org.eclipse.lemminx/src/test/resources/dtd/entities/base-system.dtd @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/org.eclipse.lemminx/src/test/resources/dtd/base.dtd b/org.eclipse.lemminx/src/test/resources/dtd/entities/base.dtd similarity index 100% rename from org.eclipse.lemminx/src/test/resources/dtd/base.dtd rename to org.eclipse.lemminx/src/test/resources/dtd/entities/base.dtd diff --git a/org.eclipse.lemminx/src/test/resources/dtd/bug_vscode-xml_262.dtd b/org.eclipse.lemminx/src/test/resources/dtd/entities/bug_vscode-xml_262.dtd similarity index 100% rename from org.eclipse.lemminx/src/test/resources/dtd/bug_vscode-xml_262.dtd rename to org.eclipse.lemminx/src/test/resources/dtd/entities/bug_vscode-xml_262.dtd