diff --git a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/dom/DOMDocument.java b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/dom/DOMDocument.java index 2dafad2b2..3e57f3942 100644 --- a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/dom/DOMDocument.java +++ b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/dom/DOMDocument.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018 Angelo ZERR. + * Copyright (c) 2018-2020 Angelo ZERR. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v2.0 * which accompanies this distribution, and is available at @@ -305,7 +305,7 @@ private NoNamespaceSchemaLocation createNoNamespaceSchemaLocation(DOMNode root, if (attr == null || attr.getValue() == null) { return null; } - return new NoNamespaceSchemaLocation(root.getOwnerDocument().getDocumentURI(), attr); + return new NoNamespaceSchemaLocation(attr); } // -------------------------- Grammar with DTD diff --git a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/dom/NoNamespaceSchemaLocation.java b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/dom/NoNamespaceSchemaLocation.java index 490837b4e..ee89b0d7d 100644 --- a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/dom/NoNamespaceSchemaLocation.java +++ b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/dom/NoNamespaceSchemaLocation.java @@ -12,21 +12,15 @@ */ package org.eclipse.lemminx.dom; -import org.apache.xerces.impl.XMLEntityManager; -import org.apache.xerces.util.URI.MalformedURIException; - /** * * The declared "xsi:noNamespaceSchemaLocation" */ public class NoNamespaceSchemaLocation { - private final String documentURI; - private final DOMAttr attr; - public NoNamespaceSchemaLocation(String documentURI, DOMAttr attr) { - this.documentURI = documentURI; + public NoNamespaceSchemaLocation(DOMAttr attr) { this.attr = attr; } @@ -45,21 +39,4 @@ public String getLocation() { return attr.getValue(); } - /** - * Returns the expanded system location - * - * @return the expanded system location - */ - public String getResolvedLocation() { - return getResolvedLocation(documentURI, getLocation()); - } - - private String getResolvedLocation(String documentURI, String location) { - try { - return XMLEntityManager.expandSystemId(location, documentURI, false); - } catch (MalformedURIException e) { - return location; - } - } - } diff --git a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/contentmodel/participants/ContentModelDocumentLinkParticipant.java b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/contentmodel/participants/ContentModelDocumentLinkParticipant.java index 87d3f92d3..5993a8918 100644 --- a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/contentmodel/participants/ContentModelDocumentLinkParticipant.java +++ b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/contentmodel/participants/ContentModelDocumentLinkParticipant.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018 Angelo ZERR + * Copyright (c) 2018-2020 Angelo ZERR * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v2.0 * which accompanies this distribution, and is available at @@ -14,31 +14,81 @@ import java.util.List; +import org.apache.xerces.impl.XMLEntityManager; +import org.apache.xerces.util.URI.MalformedURIException; import org.eclipse.lemminx.commons.BadLocationException; import org.eclipse.lemminx.dom.DOMDocument; +import org.eclipse.lemminx.dom.DOMDocumentType; import org.eclipse.lemminx.dom.DOMNode; +import org.eclipse.lemminx.dom.DOMRange; import org.eclipse.lemminx.dom.NoNamespaceSchemaLocation; import org.eclipse.lemminx.services.extensions.IDocumentLinkParticipant; import org.eclipse.lsp4j.DocumentLink; import org.eclipse.lsp4j.Position; import org.eclipse.lsp4j.Range; +/** + * Document link for : + * + * + * + * @author Angelo ZERR + * + */ public class ContentModelDocumentLinkParticipant implements IDocumentLinkParticipant { @Override public void findDocumentLinks(DOMDocument document, List links) { + // Document link for xsi:noNamespaceSchemaLocation NoNamespaceSchemaLocation noNamespaceSchemaLocation = document.getNoNamespaceSchemaLocation(); if (noNamespaceSchemaLocation != null) { try { - String location = noNamespaceSchemaLocation.getResolvedLocation(); - DOMNode attrValue = noNamespaceSchemaLocation.getAttr().getNodeAttrValue(); - Position start = document.positionAt(attrValue.getStart() + 1); - Position end = document.positionAt(attrValue.getEnd() - 1); - links.add(new DocumentLink(new Range(start, end), location)); + String location = getResolvedLocation(document.getDocumentURI(), + noNamespaceSchemaLocation.getLocation()); + if (location != null) { + DOMNode attrValue = noNamespaceSchemaLocation.getAttr().getNodeAttrValue(); + Position start = document.positionAt(attrValue.getStart() + 1); + Position end = document.positionAt(attrValue.getEnd() - 1); + links.add(new DocumentLink(new Range(start, end), location)); + } } catch (BadLocationException e) { // Do nothing } } + // Document link for DTD + DOMDocumentType docType = document.getDoctype(); + if (docType != null) { + String location = getResolvedLocation(document.getDocumentURI(), docType.getSystemIdWithoutQuotes()); + if (location != null) { + try { + DOMRange sytemIdRange = docType.getSystemIdNode(); + Position start = document.positionAt(sytemIdRange.getStart() + 1); + Position end = document.positionAt(sytemIdRange.getEnd() - 1); + links.add(new DocumentLink(new Range(start, end), location)); + } catch (BadLocationException e) { + // Do nothing + } + } + } + } + + /** + * Returns the expanded system location + * + * @return the expanded system location + */ + private static String getResolvedLocation(String documentURI, String location) { + if (location == null) { + return null; + } + try { + return XMLEntityManager.expandSystemId(location, documentURI, false); + } catch (MalformedURIException e) { + return location; + } } } 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 new file mode 100644 index 000000000..ae95d9b01 --- /dev/null +++ b/org.eclipse.lemminx/src/test/java/org/eclipse/lemminx/extensions/contentmodel/DTDDocumentLinkTest.java @@ -0,0 +1,58 @@ +/******************************************************************************* +* Copyright (c) 2020 Red Hat Inc. and others. +* All rights reserved. This program and the accompanying materials +* which accompanies this distribution, and is available at +* http://www.eclipse.org/legal/epl-v20.html +* +* SPDX-License-Identifier: EPL-2.0 +* +* Contributors: +* Red Hat Inc. - initial API and implementation +*******************************************************************************/ +package org.eclipse.lemminx.extensions.contentmodel; + +import static org.eclipse.lemminx.XMLAssert.dl; +import static org.eclipse.lemminx.XMLAssert.r; + +import org.eclipse.lemminx.XMLAssert; +import org.eclipse.lemminx.commons.BadLocationException; +import org.junit.jupiter.api.Test; + +/** + * DTD document links tests + * + */ +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")); + } + + @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")); + } + + @Test + public void noLinks() throws BadLocationException { + String xml = "\r\n" + // + "\r\n" + // + ""; + XMLAssert.testDocumentLinkFor(xml, "src/test/resources/xml/base.xml"); + } +} diff --git a/org.eclipse.lemminx/src/test/resources/dtd/base.dtd b/org.eclipse.lemminx/src/test/resources/dtd/base.dtd new file mode 100644 index 000000000..7f12a37b1 --- /dev/null +++ b/org.eclipse.lemminx/src/test/resources/dtd/base.dtd @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/org.eclipse.lemminx/src/test/resources/xml/base-public.xml b/org.eclipse.lemminx/src/test/resources/xml/base-public.xml new file mode 100644 index 000000000..fb5161365 --- /dev/null +++ b/org.eclipse.lemminx/src/test/resources/xml/base-public.xml @@ -0,0 +1,5 @@ + + + \ No newline at end of file diff --git a/org.eclipse.lemminx/src/test/resources/xml/base.xml b/org.eclipse.lemminx/src/test/resources/xml/base.xml new file mode 100644 index 000000000..2ce75a3f9 --- /dev/null +++ b/org.eclipse.lemminx/src/test/resources/xml/base.xml @@ -0,0 +1,5 @@ + + + \ No newline at end of file