From b5aa3ac5413f491dc94ba4b7d8d627eb6595b03a Mon Sep 17 00:00:00 2001 From: David Thompson Date: Tue, 13 Sep 2022 15:22:06 -0400 Subject: [PATCH 01/15] WIP I am reparsing in order to validate, very bad Signed-off-by: David Thompson --- org.eclipse.lemminx/pom.xml | 9 +- .../xerces/AbstractLSPErrorReporter.java | 72 +++-- .../xerces/xmlmodel/XMLModelDTDValidator.java | 3 +- .../xerces/xmlmodel/XMLModelHandler.java | 7 +- .../xmlmodel/XMLModelRelaxNGValidator.java | 251 ++++++++++++++++++ .../xmlmodel/XMLModelSchemaValidator.java | 3 +- .../xerces/xmlmodel/XMLModelValidator.java | 2 +- 7 files changed, 325 insertions(+), 22 deletions(-) create mode 100644 org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xerces/xmlmodel/XMLModelRelaxNGValidator.java diff --git a/org.eclipse.lemminx/pom.xml b/org.eclipse.lemminx/pom.xml index 268360f96..6652ac88b 100644 --- a/org.eclipse.lemminx/pom.xml +++ b/org.eclipse.lemminx/pom.xml @@ -171,7 +171,7 @@ --enable-http --enable-https ${graalvm.static} - + @@ -240,6 +240,11 @@ jsoup 1.14.2 + + net.java.dev.msv + msv-core + 2022.7 + xml-resolver xml-resolver @@ -268,4 +273,4 @@ test - + \ No newline at end of file diff --git a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xerces/AbstractLSPErrorReporter.java b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xerces/AbstractLSPErrorReporter.java index 040000b6d..d3b506b83 100644 --- a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xerces/AbstractLSPErrorReporter.java +++ b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xerces/AbstractLSPErrorReporter.java @@ -28,12 +28,14 @@ import org.apache.xerces.util.MessageFormatter; import org.apache.xerces.xni.XMLLocator; import org.apache.xerces.xni.XNIException; +import org.apache.xerces.xni.parser.XMLErrorHandler; import org.apache.xerces.xni.parser.XMLParseException; import org.eclipse.lemminx.commons.BadLocationException; import org.eclipse.lemminx.commons.TextDocument; import org.eclipse.lemminx.dom.DOMDocument; import org.eclipse.lemminx.extensions.contentmodel.participants.AggregateRelatedInfoFinder; import org.eclipse.lemminx.extensions.xerces.xmlmodel.msg.XMLModelMessageFormatter; +import org.eclipse.lemminx.utils.XMLPositionUtility; import org.eclipse.lsp4j.Diagnostic; import org.eclipse.lsp4j.DiagnosticRelatedInformation; import org.eclipse.lsp4j.DiagnosticSeverity; @@ -87,7 +89,7 @@ public String reportError(XMLLocator location, String domain, String key, Object boolean fatalError = severity == SEVERITY_FATAL_ERROR; DiagnosticSeverity diagnosticSeverity = getSeverity(domain, key, arguments, severity, exception); Range adjustedRange = internalToLSPRange(location, key, arguments, message, diagnosticSeverity, fatalError, - xmlDocument); + xmlDocument, exception); List relatedInformations = null; if (adjustedRange == null || NO_RANGE.equals(adjustedRange)) { return null; @@ -119,25 +121,30 @@ protected DiagnosticSeverity getSeverity(String domain, String key, Object[] arg protected String getMessage(String domain, String key, Object[] arguments, Exception exception) { MessageFormatter messageFormatter = getMessageFormatter(domain); - String message; + String message = null; if (messageFormatter != null) { message = messageFormatter.formatMessage(fLocale, key, arguments); } else { - StringBuilder str = new StringBuilder(); - str.append(domain); - str.append('#'); - str.append(key); - int argCount = arguments != null ? arguments.length : 0; - if (argCount > 0) { - str.append('?'); - for (int i = 0; i < argCount; i++) { - str.append(arguments[i]); - if (i < argCount - 1) { - str.append('&'); + if (exception != null) { + message = exception.getMessage(); + } + if (message == null) { + StringBuilder str = new StringBuilder(); + str.append(domain); + str.append('#'); + str.append(key); + int argCount = arguments != null ? arguments.length : 0; + if (argCount > 0) { + str.append('?'); + for (int i = 0; i < argCount; i++) { + str.append(arguments[i]); + if (i < argCount - 1) { + str.append('&'); + } } } + message = str.toString(); } - message = str.toString(); } return message; } @@ -193,7 +200,19 @@ private static DiagnosticSeverity toLSPSeverity(int severity) { * @return the LSP range from the SAX error. */ private Range internalToLSPRange(XMLLocator location, String key, Object[] arguments, String message, - DiagnosticSeverity diagnosticSeverity, boolean fatalError, DOMDocument document) { + DiagnosticSeverity diagnosticSeverity, boolean fatalError, DOMDocument document, Exception exception) { + + if (exception instanceof XMLParseException) { + XMLParseException parseException = (XMLParseException)exception; + Position p = new Position(parseException.getLineNumber() - 1, parseException.getColumnNumber() - 1); + try { + int offset = document.offsetAt(p); + return XMLPositionUtility.selectStartTagName(offset, document); + } catch (Exception e) { + return new Range(p, new Position(p.getLine(), p.getCharacter() + 1)); + } + } + if (location == null) { Position start = toLSPPosition(0, location, document.getTextDocument()); Position end = toLSPPosition(0, location, document.getTextDocument()); @@ -296,6 +315,29 @@ public static boolean initializeReporter(XMLSchemaLoader schemaLoader, XMLErrorR public void setCurrentError(Exception currentError) { this.currentError = currentError; + } + @Override + public ErrorHandler getSAXErrorHandler() { + if (fErrorHandler == null) { + fErrorHandler = new XMLErrorHandler() { + + @Override + public void warning(String domain, String key, XMLParseException exception) throws XNIException { + reportError(domain, key, null, SEVERITY_WARNING, exception); + } + + @Override + public void fatalError(String domain, String key, XMLParseException exception) throws XNIException { + reportError(domain, key, null, SEVERITY_FATAL_ERROR, exception); + } + + @Override + public void error(String domain, String key, XMLParseException exception) throws XNIException { + reportError(domain, key, null, SEVERITY_ERROR, exception); + } + }; + } + return super.getSAXErrorHandler(); } } diff --git a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xerces/xmlmodel/XMLModelDTDValidator.java b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xerces/xmlmodel/XMLModelDTDValidator.java index 50c65342c..25891174b 100644 --- a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xerces/xmlmodel/XMLModelDTDValidator.java +++ b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xerces/xmlmodel/XMLModelDTDValidator.java @@ -12,10 +12,11 @@ package org.eclipse.lemminx.extensions.xerces.xmlmodel; import org.eclipse.lemminx.extensions.xerces.ExternalXMLDTDValidator; +import org.xml.sax.XMLReader; /** * XML model validator which process validation with DTD: - * + * *
  * 	<?xml-model href="http://java.sun.com/dtd/web-app_2_3.dtd"?>
  * 
diff --git a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xerces/xmlmodel/XMLModelHandler.java b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xerces/xmlmodel/XMLModelHandler.java index 4be79f190..a8889d5bd 100644 --- a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xerces/xmlmodel/XMLModelHandler.java +++ b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xerces/xmlmodel/XMLModelHandler.java @@ -30,18 +30,19 @@ import org.apache.xerces.xni.parser.XMLDocumentFilter; import org.apache.xerces.xni.parser.XMLDocumentSource; import org.eclipse.lemminx.utils.StringUtils; +import org.xml.sax.XMLReader; /** * Xerces component which associates a XML with several grammar (XML Schema, * DTD, ..) by using <?xml-model ?> processing instruction. - * + * *
  * 	<?xml-model href="http://www.docbook.org/xml/5.0/xsd/docbook.xsd"?>
  *	<book xmlns="http://docbook.org/ns/docbook">
  *		<title />
  *	</book>
  * 
- * + * * @see https://www.w3.org/TR/xml-model/ * */ @@ -124,6 +125,8 @@ private XMLModelValidator createValidator(XMLModelDeclaration model) { return new XMLModelSchemaValidator(); } else if (href.endsWith("dtd")) { return new XMLModelDTDValidator(); + } else if (href.endsWith("rng")) { + return new XMLModelRelaxNGValidator(); } return null; } diff --git a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xerces/xmlmodel/XMLModelRelaxNGValidator.java b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xerces/xmlmodel/XMLModelRelaxNGValidator.java new file mode 100644 index 000000000..38fbba321 --- /dev/null +++ b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xerces/xmlmodel/XMLModelRelaxNGValidator.java @@ -0,0 +1,251 @@ +package org.eclipse.lemminx.extensions.xerces.xmlmodel; + +import java.io.IOException; +import java.util.logging.Level; +import java.util.logging.Logger; + +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.parsers.SAXParserFactory; + +import org.apache.xerces.impl.Constants; +import org.apache.xerces.impl.XMLEntityManager; +import org.apache.xerces.impl.XMLErrorReporter; +import org.apache.xerces.xni.Augmentations; +import org.apache.xerces.xni.NamespaceContext; +import org.apache.xerces.xni.QName; +import org.apache.xerces.xni.XMLAttributes; +import org.apache.xerces.xni.XMLDocumentHandler; +import org.apache.xerces.xni.XMLLocator; +import org.apache.xerces.xni.XMLResourceIdentifier; +import org.apache.xerces.xni.XMLString; +import org.apache.xerces.xni.XNIException; +import org.apache.xerces.xni.parser.XMLComponentManager; +import org.apache.xerces.xni.parser.XMLConfigurationException; +import org.apache.xerces.xni.parser.XMLDocumentSource; +import org.apache.xerces.xni.parser.XMLEntityResolver; +import org.iso_relax.verifier.Verifier; +import org.iso_relax.verifier.VerifierConfigurationException; +import org.iso_relax.verifier.VerifierFactory; +import org.xml.sax.EntityResolver; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; +import org.xml.sax.XMLReader; + +public class XMLModelRelaxNGValidator implements XMLModelValidator { + + private static final Logger LOGGER = Logger.getLogger(XMLModelRelaxNGValidator.class.getName()); + + private XMLErrorReporter errorReporter; + private XMLEntityResolver entityResolver; + private String href; + private XMLLocator locator; + private boolean processed = false; + private VerifierFactory verifierFactory; + + public XMLModelRelaxNGValidator() { + verifierFactory = new com.sun.msv.verifier.jarv.TheFactoryImpl(); + } + + public static final String ERROR_REPORTER = Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_REPORTER_PROPERTY; + + protected static final String ENTITY_RESOLVER = Constants.XERCES_PROPERTY_PREFIX + + Constants.ENTITY_RESOLVER_PROPERTY; + + @Override + public void reset(XMLComponentManager componentManager) throws XMLConfigurationException { + // Get error reporter. + try { + errorReporter = (XMLErrorReporter) componentManager.getProperty(ERROR_REPORTER); + } catch (XMLConfigurationException e) { + errorReporter = null; + } + // Get error reporter. + try { + entityResolver = (XMLEntityResolver) componentManager.getProperty(ENTITY_RESOLVER); + } catch (XMLConfigurationException e) { + entityResolver = null; + } + } + + @Override + public String[] getRecognizedFeatures() { + // TODO Auto-generated method stub + return null; + } + + @Override + public void setFeature(String featureId, boolean state) throws XMLConfigurationException { + // TODO Auto-generated method stub + + } + + @Override + public String[] getRecognizedProperties() { + // TODO Auto-generated method stub + return null; + } + + @Override + public void setProperty(String propertyId, Object value) throws XMLConfigurationException { + // TODO Auto-generated method stub + + } + + @Override + public Boolean getFeatureDefault(String featureId) { + // TODO Auto-generated method stub + return null; + } + + @Override + public Object getPropertyDefault(String propertyId) { + // TODO Auto-generated method stub + return null; + } + + @Override + public void startDocument(XMLLocator locator, String encoding, NamespaceContext namespaceContext, + Augmentations augs) throws XNIException { + + } + + @Override + public void xmlDecl(String version, String encoding, String standalone, Augmentations augs) throws XNIException { + // TODO Auto-generated method stub + + } + + @Override + public void doctypeDecl(String rootElement, String publicId, String systemId, Augmentations augs) + throws XNIException { + // TODO Auto-generated method stub + + } + + @Override + public void comment(XMLString text, Augmentations augs) throws XNIException { + // TODO Auto-generated method stub + + } + + @Override + public void processingInstruction(String target, XMLString data, Augmentations augs) throws XNIException { + // TODO Auto-generated method stub + + } + + @Override + public void startElement(QName element, XMLAttributes attributes, Augmentations augs) throws XNIException { + if (!processed) { + try { + String expandedLoc = XMLEntityManager.expandSystemId(href, locator.getExpandedSystemId(), false); + Verifier verifier = verifierFactory.newVerifier(new InputSource(expandedLoc)); + verifier.setErrorHandler(errorReporter.getSAXErrorHandler()); + SAXParserFactory parserFactory = SAXParserFactory.newInstance(); + parserFactory.setNamespaceAware(true); + XMLReader xmlReader = parserFactory.newSAXParser().getXMLReader(); + xmlReader.setContentHandler(verifier.getVerifierHandler()); + xmlReader.parse(locator.getLiteralSystemId()); + processed = true; + } catch (VerifierConfigurationException | SAXException | IOException | ParserConfigurationException e) { + LOGGER.log(Level.SEVERE, "Something went wrong when validating useing relaxng:", e); + } + } + } + + @Override + public void emptyElement(QName element, XMLAttributes attributes, Augmentations augs) throws XNIException { + // TODO Auto-generated method stub + + } + + @Override + public void startGeneralEntity(String name, XMLResourceIdentifier identifier, String encoding, Augmentations augs) + throws XNIException { + // TODO Auto-generated method stub + + } + + @Override + public void textDecl(String version, String encoding, Augmentations augs) throws XNIException { + // TODO Auto-generated method stub + + } + + @Override + public void endGeneralEntity(String name, Augmentations augs) throws XNIException { + // TODO Auto-generated method stub + + } + + @Override + public void characters(XMLString text, Augmentations augs) throws XNIException { + // TODO Auto-generated method stub + + } + + @Override + public void ignorableWhitespace(XMLString text, Augmentations augs) throws XNIException { + // TODO Auto-generated method stub + + } + + @Override + public void endElement(QName element, Augmentations augs) throws XNIException { + // TODO Auto-generated method stub + + } + + @Override + public void startCDATA(Augmentations augs) throws XNIException { + // TODO Auto-generated method stub + + } + + @Override + public void endCDATA(Augmentations augs) throws XNIException { + // TODO Auto-generated method stub + + } + + @Override + public void endDocument(Augmentations augs) throws XNIException { + // TODO Auto-generated method stub + + } + + @Override + public void setDocumentSource(XMLDocumentSource source) { + // TODO Auto-generated method stub + + } + + @Override + public XMLDocumentSource getDocumentSource() { + // TODO Auto-generated method stub + return null; + } + + @Override + public void setDocumentHandler(XMLDocumentHandler handler) { + // TODO Auto-generated method stub + + } + + @Override + public XMLDocumentHandler getDocumentHandler() { + // TODO Auto-generated method stub + return null; + } + + @Override + public void setLocator(XMLLocator locator) { + this.locator = locator; + } + + @Override + public void setHref(String href) { + this.href = href; + } + +} diff --git a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xerces/xmlmodel/XMLModelSchemaValidator.java b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xerces/xmlmodel/XMLModelSchemaValidator.java index af792293c..193814e0e 100644 --- a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xerces/xmlmodel/XMLModelSchemaValidator.java +++ b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xerces/xmlmodel/XMLModelSchemaValidator.java @@ -24,10 +24,11 @@ import org.apache.xerces.xni.parser.XMLComponentManager; import org.apache.xerces.xni.parser.XMLConfigurationException; import org.eclipse.lemminx.utils.StringUtils; +import org.xml.sax.XMLReader; /** * XML model validator which process validation with XML Schema: - * + * *
  * 	<?xml-model href="http://www.docbook.org/xml/5.0/xsd/docbook.xsd"?>
  * 
diff --git a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xerces/xmlmodel/XMLModelValidator.java b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xerces/xmlmodel/XMLModelValidator.java index 09f3b9e3e..6d941026a 100644 --- a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xerces/xmlmodel/XMLModelValidator.java +++ b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xerces/xmlmodel/XMLModelValidator.java @@ -22,7 +22,7 @@ public interface XMLModelValidator extends XMLComponent, XMLDocumentFilter{ void setLocator(XMLLocator locator); - + void setHref(String href); } From 174a9f30c6fe539eeb32c1cdd60600fa3b8a78ac Mon Sep 17 00:00:00 2001 From: David Thompson Date: Tue, 13 Sep 2022 17:08:49 -0400 Subject: [PATCH 02/15] EOD sept 13, trying to directly wrap the MSV Validator object Signed-off-by: David Thompson --- .../diagnostics/MultipleContentHandler.java | 100 ++++++ .../diagnostics/XMLValidator.java | 21 +- .../xmlmodel/NewXMLModelRelaxNGValidator.java | 289 ++++++++++++++++++ .../xerces/xmlmodel/XMLModelHandler.java | 3 +- .../xmlmodel/XMLModelRelaxNGValidator.java | 1 - 5 files changed, 402 insertions(+), 12 deletions(-) create mode 100644 org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/contentmodel/participants/diagnostics/MultipleContentHandler.java create mode 100644 org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xerces/xmlmodel/NewXMLModelRelaxNGValidator.java diff --git a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/contentmodel/participants/diagnostics/MultipleContentHandler.java b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/contentmodel/participants/diagnostics/MultipleContentHandler.java new file mode 100644 index 000000000..690cfe0be --- /dev/null +++ b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/contentmodel/participants/diagnostics/MultipleContentHandler.java @@ -0,0 +1,100 @@ +package org.eclipse.lemminx.extensions.contentmodel.participants.diagnostics; + +import java.util.ArrayList; +import java.util.List; + +import org.xml.sax.Attributes; +import org.xml.sax.ContentHandler; +import org.xml.sax.Locator; +import org.xml.sax.SAXException; + +public class MultipleContentHandler implements ContentHandler { + + private final List handlers; + + public MultipleContentHandler() { + this.handlers = new ArrayList<>(); + } + + @Override + public void setDocumentLocator(Locator locator) { + for (ContentHandler contentHandler : handlers) { + contentHandler.setDocumentLocator(locator); + } + } + + @Override + public void startDocument() throws SAXException { + for (ContentHandler contentHandler : handlers) { + contentHandler.startDocument(); + } + } + + @Override + public void endDocument() throws SAXException { + for (ContentHandler contentHandler : handlers) { + contentHandler.endDocument(); + } + } + + @Override + public void startPrefixMapping(String prefix, String uri) throws SAXException { + for (ContentHandler contentHandler : handlers) { + contentHandler.startPrefixMapping(prefix, uri); + } + } + + @Override + public void endPrefixMapping(String prefix) throws SAXException { + for (ContentHandler contentHandler : handlers) { + contentHandler.endPrefixMapping(prefix); + } + } + + @Override + public void startElement(String uri, String localName, String qName, Attributes atts) throws SAXException { + for (ContentHandler contentHandler : handlers) { + contentHandler.startElement(uri, localName, qName, atts); + } + } + + @Override + public void endElement(String uri, String localName, String qName) throws SAXException { + for (ContentHandler contentHandler : handlers) { + contentHandler.endElement(uri, localName, qName); + } + } + + @Override + public void characters(char[] ch, int start, int length) throws SAXException { + for (ContentHandler contentHandler : handlers) { + contentHandler.characters(ch, start, length); + } + } + + @Override + public void ignorableWhitespace(char[] ch, int start, int length) throws SAXException { + for (ContentHandler contentHandler : handlers) { + contentHandler.ignorableWhitespace(ch, start, length); + } + } + + @Override + public void processingInstruction(String target, String data) throws SAXException { + for (ContentHandler contentHandler : handlers) { + contentHandler.processingInstruction(target, data); + } + } + + @Override + public void skippedEntity(String name) throws SAXException { + for (ContentHandler contentHandler : handlers) { + contentHandler.skippedEntity(name); + } + } + + public void addContentHandler(ContentHandler contentHandler) { + handlers.add(contentHandler); + } + +} \ No newline at end of file diff --git a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/contentmodel/participants/diagnostics/XMLValidator.java b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/contentmodel/participants/diagnostics/XMLValidator.java index 83778f49a..99cf18eab 100644 --- a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/contentmodel/participants/diagnostics/XMLValidator.java +++ b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/contentmodel/participants/diagnostics/XMLValidator.java @@ -95,8 +95,11 @@ public static void doDiagnostics(DOMDocument document, XMLEntityResolver entityR SAXParser parser = new LSPSAXParser(reporterForXML, configuration, grammarPool, document); + MultipleContentHandler multiContentHandler = new MultipleContentHandler(); // Add LSP content handler to stop XML parsing if monitor is canceled. - parser.setContentHandler(new LSPContentHandler(monitor)); + multiContentHandler.addContentHandler(new LSPContentHandler(monitor)); + + parser.setContentHandler(multiContentHandler); // warn if XML document is not bound to a grammar according the settings warnNoGrammar(document, diagnostics, validationSettings); @@ -188,15 +191,15 @@ private static boolean isSchemaValidationEnabled(DOMDocument document, XMLValida /** * Returns true if the given DOM document declares a xsi:schemaLocation hint for * the document root element is valid and false otherwise. - * + * * The xsi:schemaLocation is valid if: - * + * *
    *
  • xsi:schemaLocation defines an URI for the namespace of the document * element.
  • *
  • the URI can be opened
  • *
- * + * * @param document the DOM document. * @return true if the given DOM document declares a xsi:schemaLocation hint for * the document root element is valid and false otherwise. @@ -239,14 +242,14 @@ private static boolean isNoNamespaceSchemaValidationEnabled(DOMDocument document /** * Returns true if the given DOM document declares a * xsi:noNamespaceSchemaLocation which is valid and false otherwise. - * + * * The xsi:noNamespaceSchemaLocation is valid if: - * + * *
    *
  • xsi:noNamespaceSchemaLocation defines an URI.
  • *
  • the URI can be opened
  • *
- * + * * @param document the DOM document. * @return true if the given DOM document declares a xsi:schemaLocation hint for * the document root element is valid and false otherwise. @@ -304,7 +307,7 @@ private static void parseXML(String content, String uri, SAXParser parser) throw /** * Returns true is DTD validation must be disabled and false otherwise. - * + * * @param document the DOM document * @return true is DTD validation must be disabled and false otherwise. */ @@ -335,7 +338,7 @@ private static boolean isDisableOnlyDTDValidation(DOMDocument document) { /** * Warn if XML document is not bound to a grammar according the settings - * + * * @param document the XML document * @param diagnostics the diagnostics list to populate * @param validationSettings the settings to use to know the severity of warn. diff --git a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xerces/xmlmodel/NewXMLModelRelaxNGValidator.java b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xerces/xmlmodel/NewXMLModelRelaxNGValidator.java new file mode 100644 index 000000000..7474cc592 --- /dev/null +++ b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xerces/xmlmodel/NewXMLModelRelaxNGValidator.java @@ -0,0 +1,289 @@ +package org.eclipse.lemminx.extensions.xerces.xmlmodel; + +import java.io.IOException; + +import org.apache.xerces.impl.XMLEntityManager; +import org.apache.xerces.xni.Augmentations; +import org.apache.xerces.xni.NamespaceContext; +import org.apache.xerces.xni.QName; +import org.apache.xerces.xni.XMLAttributes; +import org.apache.xerces.xni.XMLDocumentHandler; +import org.apache.xerces.xni.XMLLocator; +import org.apache.xerces.xni.XMLResourceIdentifier; +import org.apache.xerces.xni.XMLString; +import org.apache.xerces.xni.XNIException; +import org.apache.xerces.xni.parser.XMLComponentManager; +import org.apache.xerces.xni.parser.XMLConfigurationException; +import org.apache.xerces.xni.parser.XMLDocumentSource; +import org.iso_relax.verifier.Verifier; +import org.iso_relax.verifier.VerifierConfigurationException; +import org.iso_relax.verifier.VerifierFactory; +import org.iso_relax.verifier.VerifierHandler; +import org.xml.sax.Attributes; +import org.xml.sax.SAXException; + +public class NewXMLModelRelaxNGValidator implements XMLModelValidator { + + private static final VerifierFactory VERIFIER_FACTORY = new com.sun.msv.verifier.jarv.TheFactoryImpl(); + + private String href; + private VerifierHandler verifierHandler; + + public NewXMLModelRelaxNGValidator(String href) { + this.href = href; + } + + private void createVerifier(XMLLocator locator) throws SAXException { + try { + String expandedLoc = XMLEntityManager.expandSystemId(href, locator.getExpandedSystemId(), false); + Verifier verifier = VERIFIER_FACTORY.newVerifier(expandedLoc); + verifierHandler = verifier.getVerifierHandler(); + } catch (VerifierConfigurationException | IOException e) { + // TODO: log severe + } + } + + @Override + public void reset(XMLComponentManager componentManager) throws XMLConfigurationException { + } + + @Override + public String[] getRecognizedFeatures() { + return null; + } + + @Override + public void setFeature(String featureId, boolean state) throws XMLConfigurationException { + } + + @Override + public String[] getRecognizedProperties() { + return null; + } + + @Override + public void setProperty(String propertyId, Object value) throws XMLConfigurationException { + // TODO Auto-generated method stub + + } + + @Override + public Boolean getFeatureDefault(String featureId) { + // TODO Auto-generated method stub + return null; + } + + @Override + public Object getPropertyDefault(String propertyId) { + // TODO Auto-generated method stub + return null; + } + + @Override + public void startDocument(XMLLocator locator, String encoding, NamespaceContext namespaceContext, + Augmentations augs) throws XNIException { + try { + if (verifierHandler == null) { + createVerifier(locator); + } + verifierHandler.startDocument(); + } catch (SAXException e) { + throw new XNIException(e); + } + } + + @Override + public void xmlDecl(String version, String encoding, String standalone, Augmentations augs) throws XNIException { + } + + @Override + public void doctypeDecl(String rootElement, String publicId, String systemId, Augmentations augs) + throws XNIException { + } + + @Override + public void comment(XMLString text, Augmentations augs) throws XNIException { + } + + @Override + public void processingInstruction(String target, XMLString data, Augmentations augs) throws XNIException { + try { + verifierHandler.processingInstruction(target, data.toString()); + } catch (SAXException e) { + throw new XNIException(e); + } + } + + @Override + public void startElement(QName element, XMLAttributes attributes, Augmentations augs) throws XNIException { + try { + if (verifierHandler == null) { + createVerifier();// TODO: + } + verifierHandler.startElement(element.uri, element.localpart, element.rawname, + new AttributesWrapper(attributes)); + } catch (SAXException e) { + throw new XNIException(e); + } + } + + @Override + public void emptyElement(QName element, XMLAttributes attributes, Augmentations augs) throws XNIException { + } + + @Override + public void startGeneralEntity(String name, XMLResourceIdentifier identifier, String encoding, Augmentations augs) + throws XNIException { + } + + @Override + public void textDecl(String version, String encoding, Augmentations augs) throws XNIException { + } + + @Override + public void endGeneralEntity(String name, Augmentations augs) throws XNIException { + } + + @Override + public void characters(XMLString text, Augmentations augs) throws XNIException { + try { + verifierHandler.characters(text.ch, text.offset, text.length); + } catch (SAXException e) { + throw new XNIException(e); + } + } + + @Override + public void ignorableWhitespace(XMLString text, Augmentations augs) throws XNIException { + try { + verifierHandler.ignorableWhitespace(text.ch, text.offset, text.length); + } catch (SAXException e) { + throw new XNIException(e); + } + } + + @Override + public void endElement(QName element, Augmentations augs) throws XNIException { + try { + verifierHandler.endElement(element.uri, element.localpart, element.rawname); + } catch (SAXException e) { + throw new XNIException(e); + } + } + + @Override + public void startCDATA(Augmentations augs) throws XNIException { + } + + @Override + public void endCDATA(Augmentations augs) throws XNIException { + } + + @Override + public void endDocument(Augmentations augs) throws XNIException { + try { + verifierHandler.endDocument(); + } catch (SAXException e) { + throw new XNIException(e); + } + } + + @Override + public void setDocumentSource(XMLDocumentSource source) { + // do nothing + } + + @Override + public XMLDocumentSource getDocumentSource() { + return null; + } + + @Override + public void setDocumentHandler(XMLDocumentHandler handler) { + // do nothing + } + + @Override + public XMLDocumentHandler getDocumentHandler() { + return this; // TODO: ?? + } + + @Override + public void setLocator(XMLLocator locator) { + // do nothing, instead just make sure the locator is passed to the methods that need it + } + + @Override + public void setHref(String href) { + // do nothing + } + + private final class AttributesWrapper implements Attributes { + private final XMLAttributes attributes; + + private AttributesWrapper(XMLAttributes attributes) { + this.attributes = attributes; + } + + @Override + public int getLength() { + return attributes.getLength(); + } + + @Override + public String getURI(int index) { + return attributes.getURI(index); + } + + @Override + public String getLocalName(int index) { + return attributes.getLocalName(index); + } + + @Override + public String getQName(int index) { + return attributes.getQName(index); + } + + @Override + public String getType(int index) { + return attributes.getType(index); + } + + @Override + public String getValue(int index) { + return attributes.getValue(index); + } + + @Override + public int getIndex(String uri, String localName) { + return attributes.getIndex(uri, localName); + } + + @Override + public int getIndex(String qName) { + return attributes.getIndex(qName); + } + + @Override + public String getType(String uri, String localName) { + return attributes.getType(uri, localName); + } + + @Override + public String getType(String qName) { + return attributes.getType(qName); + } + + @Override + public String getValue(String uri, String localName) { + return attributes.getValue(uri, localName); + } + + @Override + public String getValue(String qName) { + return attributes.getValue(qName); + } + } + +} diff --git a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xerces/xmlmodel/XMLModelHandler.java b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xerces/xmlmodel/XMLModelHandler.java index a8889d5bd..cef6bc32b 100644 --- a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xerces/xmlmodel/XMLModelHandler.java +++ b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xerces/xmlmodel/XMLModelHandler.java @@ -30,7 +30,6 @@ import org.apache.xerces.xni.parser.XMLDocumentFilter; import org.apache.xerces.xni.parser.XMLDocumentSource; import org.eclipse.lemminx.utils.StringUtils; -import org.xml.sax.XMLReader; /** * Xerces component which associates a XML with several grammar (XML Schema, @@ -126,7 +125,7 @@ private XMLModelValidator createValidator(XMLModelDeclaration model) { } else if (href.endsWith("dtd")) { return new XMLModelDTDValidator(); } else if (href.endsWith("rng")) { - return new XMLModelRelaxNGValidator(); + return new NewXMLModelRelaxNGValidator(href); } return null; } diff --git a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xerces/xmlmodel/XMLModelRelaxNGValidator.java b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xerces/xmlmodel/XMLModelRelaxNGValidator.java index 38fbba321..f0442660b 100644 --- a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xerces/xmlmodel/XMLModelRelaxNGValidator.java +++ b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xerces/xmlmodel/XMLModelRelaxNGValidator.java @@ -26,7 +26,6 @@ import org.iso_relax.verifier.Verifier; import org.iso_relax.verifier.VerifierConfigurationException; import org.iso_relax.verifier.VerifierFactory; -import org.xml.sax.EntityResolver; import org.xml.sax.InputSource; import org.xml.sax.SAXException; import org.xml.sax.XMLReader; From 1c0223b43e4990047ab05b3a09ec5307bcb3f03e Mon Sep 17 00:00:00 2001 From: David Thompson Date: Wed, 14 Sep 2022 10:02:23 -0400 Subject: [PATCH 03/15] Mostly working, also got error code working Signed-off-by: David Thompson --- .../xerces/AbstractLSPErrorReporter.java | 26 ++++++++--------- .../xmlmodel/NewXMLModelRelaxNGValidator.java | 29 ++++++++++++------- .../xerces/xmlmodel/XMLModelHandler.java | 2 +- 3 files changed, 33 insertions(+), 24 deletions(-) diff --git a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xerces/AbstractLSPErrorReporter.java b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xerces/AbstractLSPErrorReporter.java index d3b506b83..6fda90755 100644 --- a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xerces/AbstractLSPErrorReporter.java +++ b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xerces/AbstractLSPErrorReporter.java @@ -16,6 +16,7 @@ import java.util.logging.Level; import java.util.logging.Logger; +import com.sun.msv.verifier.ValidityViolation; import org.apache.xerces.impl.XMLEntityManager; import org.apache.xerces.impl.XMLErrorReporter; import org.apache.xerces.impl.msg.XMLMessageFormatter; @@ -35,7 +36,7 @@ import org.eclipse.lemminx.dom.DOMDocument; import org.eclipse.lemminx.extensions.contentmodel.participants.AggregateRelatedInfoFinder; import org.eclipse.lemminx.extensions.xerces.xmlmodel.msg.XMLModelMessageFormatter; -import org.eclipse.lemminx.utils.XMLPositionUtility; +import org.eclipse.lemminx.utils.StringUtils; import org.eclipse.lsp4j.Diagnostic; import org.eclipse.lsp4j.DiagnosticRelatedInformation; import org.eclipse.lsp4j.DiagnosticSeverity; @@ -150,7 +151,17 @@ protected String getMessage(String domain, String key, Object[] arguments, Excep } protected String getCode(String domain, String key, Object[] arguments, Exception exception) { - return key; + if (!StringUtils.isBlank(key)) { + return key; + } + if (exception instanceof XMLParseException) { + XMLParseException xmlParseException = ((XMLParseException)exception); + if (xmlParseException.getCause() instanceof ValidityViolation) { + ValidityViolation validityViolation = ((ValidityViolation)xmlParseException.getCause()); + return validityViolation.getErrorInfo().getClass().getSimpleName(); + } + } + return ""; } protected boolean isIgnoreFatalError(String key) { @@ -202,17 +213,6 @@ private static DiagnosticSeverity toLSPSeverity(int severity) { private Range internalToLSPRange(XMLLocator location, String key, Object[] arguments, String message, DiagnosticSeverity diagnosticSeverity, boolean fatalError, DOMDocument document, Exception exception) { - if (exception instanceof XMLParseException) { - XMLParseException parseException = (XMLParseException)exception; - Position p = new Position(parseException.getLineNumber() - 1, parseException.getColumnNumber() - 1); - try { - int offset = document.offsetAt(p); - return XMLPositionUtility.selectStartTagName(offset, document); - } catch (Exception e) { - return new Range(p, new Position(p.getLine(), p.getCharacter() + 1)); - } - } - if (location == null) { Position start = toLSPPosition(0, location, document.getTextDocument()); Position end = toLSPPosition(0, location, document.getTextDocument()); diff --git a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xerces/xmlmodel/NewXMLModelRelaxNGValidator.java b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xerces/xmlmodel/NewXMLModelRelaxNGValidator.java index 7474cc592..1866978ae 100644 --- a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xerces/xmlmodel/NewXMLModelRelaxNGValidator.java +++ b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xerces/xmlmodel/NewXMLModelRelaxNGValidator.java @@ -2,7 +2,9 @@ import java.io.IOException; +import org.apache.xerces.impl.Constants; import org.apache.xerces.impl.XMLEntityManager; +import org.apache.xerces.impl.XMLErrorReporter; import org.apache.xerces.xni.Augmentations; import org.apache.xerces.xni.NamespaceContext; import org.apache.xerces.xni.QName; @@ -15,6 +17,7 @@ import org.apache.xerces.xni.parser.XMLComponentManager; import org.apache.xerces.xni.parser.XMLConfigurationException; import org.apache.xerces.xni.parser.XMLDocumentSource; +import org.apache.xerces.xni.parser.XMLErrorHandler; import org.iso_relax.verifier.Verifier; import org.iso_relax.verifier.VerifierConfigurationException; import org.iso_relax.verifier.VerifierFactory; @@ -25,19 +28,20 @@ public class NewXMLModelRelaxNGValidator implements XMLModelValidator { private static final VerifierFactory VERIFIER_FACTORY = new com.sun.msv.verifier.jarv.TheFactoryImpl(); + public static final String ERROR_REPORTER = Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_REPORTER_PROPERTY; private String href; private VerifierHandler verifierHandler; + private XMLLocator locator; + private XMLErrorReporter errorReporter; - public NewXMLModelRelaxNGValidator(String href) { - this.href = href; - } - - private void createVerifier(XMLLocator locator) throws SAXException { + private void createVerifier() throws SAXException { try { - String expandedLoc = XMLEntityManager.expandSystemId(href, locator.getExpandedSystemId(), false); + String expandedLoc = XMLEntityManager.expandSystemId(href, locator.getBaseSystemId(), false); Verifier verifier = VERIFIER_FACTORY.newVerifier(expandedLoc); + verifier.setErrorHandler(errorReporter.getSAXErrorHandler()); verifierHandler = verifier.getVerifierHandler(); + verifierHandler.startDocument(); } catch (VerifierConfigurationException | IOException e) { // TODO: log severe } @@ -45,6 +49,11 @@ private void createVerifier(XMLLocator locator) throws SAXException { @Override public void reset(XMLComponentManager componentManager) throws XMLConfigurationException { + try { + errorReporter = (XMLErrorReporter) componentManager.getProperty(ERROR_REPORTER); + } catch (XMLConfigurationException e) { + errorReporter = null; + } } @Override @@ -84,7 +93,7 @@ public void startDocument(XMLLocator locator, String encoding, NamespaceContext Augmentations augs) throws XNIException { try { if (verifierHandler == null) { - createVerifier(locator); + createVerifier(); } verifierHandler.startDocument(); } catch (SAXException e) { @@ -118,7 +127,7 @@ public void processingInstruction(String target, XMLString data, Augmentations a public void startElement(QName element, XMLAttributes attributes, Augmentations augs) throws XNIException { try { if (verifierHandler == null) { - createVerifier();// TODO: + createVerifier(); } verifierHandler.startElement(element.uri, element.localpart, element.rawname, new AttributesWrapper(attributes)); @@ -210,12 +219,12 @@ public XMLDocumentHandler getDocumentHandler() { @Override public void setLocator(XMLLocator locator) { - // do nothing, instead just make sure the locator is passed to the methods that need it + this.locator = locator; } @Override public void setHref(String href) { - // do nothing + this.href = href; } private final class AttributesWrapper implements Attributes { diff --git a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xerces/xmlmodel/XMLModelHandler.java b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xerces/xmlmodel/XMLModelHandler.java index cef6bc32b..c319e59a1 100644 --- a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xerces/xmlmodel/XMLModelHandler.java +++ b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xerces/xmlmodel/XMLModelHandler.java @@ -125,7 +125,7 @@ private XMLModelValidator createValidator(XMLModelDeclaration model) { } else if (href.endsWith("dtd")) { return new XMLModelDTDValidator(); } else if (href.endsWith("rng")) { - return new NewXMLModelRelaxNGValidator(href); + return new NewXMLModelRelaxNGValidator(); } return null; } From d15b27b5bbf661efb7f46b6500f514989fbab3ff Mon Sep 17 00:00:00 2001 From: David Thompson Date: Wed, 14 Sep 2022 10:11:37 -0400 Subject: [PATCH 04/15] WIP clean up some code that wasn't used Signed-off-by: David Thompson --- .../xmlmodel/NewXMLModelRelaxNGValidator.java | 298 ------------------ .../xerces/xmlmodel/XMLModelHandler.java | 2 +- .../xmlmodel/XMLModelRelaxNGValidator.java | 204 +++++++----- 3 files changed, 128 insertions(+), 376 deletions(-) delete mode 100644 org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xerces/xmlmodel/NewXMLModelRelaxNGValidator.java diff --git a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xerces/xmlmodel/NewXMLModelRelaxNGValidator.java b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xerces/xmlmodel/NewXMLModelRelaxNGValidator.java deleted file mode 100644 index 1866978ae..000000000 --- a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xerces/xmlmodel/NewXMLModelRelaxNGValidator.java +++ /dev/null @@ -1,298 +0,0 @@ -package org.eclipse.lemminx.extensions.xerces.xmlmodel; - -import java.io.IOException; - -import org.apache.xerces.impl.Constants; -import org.apache.xerces.impl.XMLEntityManager; -import org.apache.xerces.impl.XMLErrorReporter; -import org.apache.xerces.xni.Augmentations; -import org.apache.xerces.xni.NamespaceContext; -import org.apache.xerces.xni.QName; -import org.apache.xerces.xni.XMLAttributes; -import org.apache.xerces.xni.XMLDocumentHandler; -import org.apache.xerces.xni.XMLLocator; -import org.apache.xerces.xni.XMLResourceIdentifier; -import org.apache.xerces.xni.XMLString; -import org.apache.xerces.xni.XNIException; -import org.apache.xerces.xni.parser.XMLComponentManager; -import org.apache.xerces.xni.parser.XMLConfigurationException; -import org.apache.xerces.xni.parser.XMLDocumentSource; -import org.apache.xerces.xni.parser.XMLErrorHandler; -import org.iso_relax.verifier.Verifier; -import org.iso_relax.verifier.VerifierConfigurationException; -import org.iso_relax.verifier.VerifierFactory; -import org.iso_relax.verifier.VerifierHandler; -import org.xml.sax.Attributes; -import org.xml.sax.SAXException; - -public class NewXMLModelRelaxNGValidator implements XMLModelValidator { - - private static final VerifierFactory VERIFIER_FACTORY = new com.sun.msv.verifier.jarv.TheFactoryImpl(); - public static final String ERROR_REPORTER = Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_REPORTER_PROPERTY; - - private String href; - private VerifierHandler verifierHandler; - private XMLLocator locator; - private XMLErrorReporter errorReporter; - - private void createVerifier() throws SAXException { - try { - String expandedLoc = XMLEntityManager.expandSystemId(href, locator.getBaseSystemId(), false); - Verifier verifier = VERIFIER_FACTORY.newVerifier(expandedLoc); - verifier.setErrorHandler(errorReporter.getSAXErrorHandler()); - verifierHandler = verifier.getVerifierHandler(); - verifierHandler.startDocument(); - } catch (VerifierConfigurationException | IOException e) { - // TODO: log severe - } - } - - @Override - public void reset(XMLComponentManager componentManager) throws XMLConfigurationException { - try { - errorReporter = (XMLErrorReporter) componentManager.getProperty(ERROR_REPORTER); - } catch (XMLConfigurationException e) { - errorReporter = null; - } - } - - @Override - public String[] getRecognizedFeatures() { - return null; - } - - @Override - public void setFeature(String featureId, boolean state) throws XMLConfigurationException { - } - - @Override - public String[] getRecognizedProperties() { - return null; - } - - @Override - public void setProperty(String propertyId, Object value) throws XMLConfigurationException { - // TODO Auto-generated method stub - - } - - @Override - public Boolean getFeatureDefault(String featureId) { - // TODO Auto-generated method stub - return null; - } - - @Override - public Object getPropertyDefault(String propertyId) { - // TODO Auto-generated method stub - return null; - } - - @Override - public void startDocument(XMLLocator locator, String encoding, NamespaceContext namespaceContext, - Augmentations augs) throws XNIException { - try { - if (verifierHandler == null) { - createVerifier(); - } - verifierHandler.startDocument(); - } catch (SAXException e) { - throw new XNIException(e); - } - } - - @Override - public void xmlDecl(String version, String encoding, String standalone, Augmentations augs) throws XNIException { - } - - @Override - public void doctypeDecl(String rootElement, String publicId, String systemId, Augmentations augs) - throws XNIException { - } - - @Override - public void comment(XMLString text, Augmentations augs) throws XNIException { - } - - @Override - public void processingInstruction(String target, XMLString data, Augmentations augs) throws XNIException { - try { - verifierHandler.processingInstruction(target, data.toString()); - } catch (SAXException e) { - throw new XNIException(e); - } - } - - @Override - public void startElement(QName element, XMLAttributes attributes, Augmentations augs) throws XNIException { - try { - if (verifierHandler == null) { - createVerifier(); - } - verifierHandler.startElement(element.uri, element.localpart, element.rawname, - new AttributesWrapper(attributes)); - } catch (SAXException e) { - throw new XNIException(e); - } - } - - @Override - public void emptyElement(QName element, XMLAttributes attributes, Augmentations augs) throws XNIException { - } - - @Override - public void startGeneralEntity(String name, XMLResourceIdentifier identifier, String encoding, Augmentations augs) - throws XNIException { - } - - @Override - public void textDecl(String version, String encoding, Augmentations augs) throws XNIException { - } - - @Override - public void endGeneralEntity(String name, Augmentations augs) throws XNIException { - } - - @Override - public void characters(XMLString text, Augmentations augs) throws XNIException { - try { - verifierHandler.characters(text.ch, text.offset, text.length); - } catch (SAXException e) { - throw new XNIException(e); - } - } - - @Override - public void ignorableWhitespace(XMLString text, Augmentations augs) throws XNIException { - try { - verifierHandler.ignorableWhitespace(text.ch, text.offset, text.length); - } catch (SAXException e) { - throw new XNIException(e); - } - } - - @Override - public void endElement(QName element, Augmentations augs) throws XNIException { - try { - verifierHandler.endElement(element.uri, element.localpart, element.rawname); - } catch (SAXException e) { - throw new XNIException(e); - } - } - - @Override - public void startCDATA(Augmentations augs) throws XNIException { - } - - @Override - public void endCDATA(Augmentations augs) throws XNIException { - } - - @Override - public void endDocument(Augmentations augs) throws XNIException { - try { - verifierHandler.endDocument(); - } catch (SAXException e) { - throw new XNIException(e); - } - } - - @Override - public void setDocumentSource(XMLDocumentSource source) { - // do nothing - } - - @Override - public XMLDocumentSource getDocumentSource() { - return null; - } - - @Override - public void setDocumentHandler(XMLDocumentHandler handler) { - // do nothing - } - - @Override - public XMLDocumentHandler getDocumentHandler() { - return this; // TODO: ?? - } - - @Override - public void setLocator(XMLLocator locator) { - this.locator = locator; - } - - @Override - public void setHref(String href) { - this.href = href; - } - - private final class AttributesWrapper implements Attributes { - private final XMLAttributes attributes; - - private AttributesWrapper(XMLAttributes attributes) { - this.attributes = attributes; - } - - @Override - public int getLength() { - return attributes.getLength(); - } - - @Override - public String getURI(int index) { - return attributes.getURI(index); - } - - @Override - public String getLocalName(int index) { - return attributes.getLocalName(index); - } - - @Override - public String getQName(int index) { - return attributes.getQName(index); - } - - @Override - public String getType(int index) { - return attributes.getType(index); - } - - @Override - public String getValue(int index) { - return attributes.getValue(index); - } - - @Override - public int getIndex(String uri, String localName) { - return attributes.getIndex(uri, localName); - } - - @Override - public int getIndex(String qName) { - return attributes.getIndex(qName); - } - - @Override - public String getType(String uri, String localName) { - return attributes.getType(uri, localName); - } - - @Override - public String getType(String qName) { - return attributes.getType(qName); - } - - @Override - public String getValue(String uri, String localName) { - return attributes.getValue(uri, localName); - } - - @Override - public String getValue(String qName) { - return attributes.getValue(qName); - } - } - -} diff --git a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xerces/xmlmodel/XMLModelHandler.java b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xerces/xmlmodel/XMLModelHandler.java index c319e59a1..5a02d16de 100644 --- a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xerces/xmlmodel/XMLModelHandler.java +++ b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xerces/xmlmodel/XMLModelHandler.java @@ -125,7 +125,7 @@ private XMLModelValidator createValidator(XMLModelDeclaration model) { } else if (href.endsWith("dtd")) { return new XMLModelDTDValidator(); } else if (href.endsWith("rng")) { - return new NewXMLModelRelaxNGValidator(); + return new XMLModelRelaxNGValidator(); } return null; } diff --git a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xerces/xmlmodel/XMLModelRelaxNGValidator.java b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xerces/xmlmodel/XMLModelRelaxNGValidator.java index f0442660b..5f9f0492f 100644 --- a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xerces/xmlmodel/XMLModelRelaxNGValidator.java +++ b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xerces/xmlmodel/XMLModelRelaxNGValidator.java @@ -4,9 +4,6 @@ import java.util.logging.Level; import java.util.logging.Logger; -import javax.xml.parsers.ParserConfigurationException; -import javax.xml.parsers.SAXParserFactory; - import org.apache.xerces.impl.Constants; import org.apache.xerces.impl.XMLEntityManager; import org.apache.xerces.impl.XMLErrorReporter; @@ -22,65 +19,56 @@ import org.apache.xerces.xni.parser.XMLComponentManager; import org.apache.xerces.xni.parser.XMLConfigurationException; import org.apache.xerces.xni.parser.XMLDocumentSource; -import org.apache.xerces.xni.parser.XMLEntityResolver; import org.iso_relax.verifier.Verifier; import org.iso_relax.verifier.VerifierConfigurationException; import org.iso_relax.verifier.VerifierFactory; -import org.xml.sax.InputSource; +import org.iso_relax.verifier.VerifierHandler; +import org.xml.sax.Attributes; import org.xml.sax.SAXException; -import org.xml.sax.XMLReader; public class XMLModelRelaxNGValidator implements XMLModelValidator { private static final Logger LOGGER = Logger.getLogger(XMLModelRelaxNGValidator.class.getName()); + private static final VerifierFactory VERIFIER_FACTORY = new com.sun.msv.verifier.jarv.TheFactoryImpl(); + public static final String ERROR_REPORTER = Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_REPORTER_PROPERTY; - private XMLErrorReporter errorReporter; - private XMLEntityResolver entityResolver; private String href; + private VerifierHandler verifierHandler; private XMLLocator locator; - private boolean processed = false; - private VerifierFactory verifierFactory; + private XMLErrorReporter errorReporter; - public XMLModelRelaxNGValidator() { - verifierFactory = new com.sun.msv.verifier.jarv.TheFactoryImpl(); + private void createVerifier() throws SAXException { + try { + String expandedLoc = XMLEntityManager.expandSystemId(href, locator.getBaseSystemId(), false); + Verifier verifier = VERIFIER_FACTORY.newVerifier(expandedLoc); + verifier.setErrorHandler(errorReporter.getSAXErrorHandler()); + verifierHandler = verifier.getVerifierHandler(); + verifierHandler.startDocument(); + } catch (VerifierConfigurationException | IOException e) { + LOGGER.log(Level.SEVERE, "Failed to create RelaxNG validator: ", e); + } } - public static final String ERROR_REPORTER = Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_REPORTER_PROPERTY; - - protected static final String ENTITY_RESOLVER = Constants.XERCES_PROPERTY_PREFIX - + Constants.ENTITY_RESOLVER_PROPERTY; - @Override public void reset(XMLComponentManager componentManager) throws XMLConfigurationException { - // Get error reporter. try { errorReporter = (XMLErrorReporter) componentManager.getProperty(ERROR_REPORTER); } catch (XMLConfigurationException e) { errorReporter = null; } - // Get error reporter. - try { - entityResolver = (XMLEntityResolver) componentManager.getProperty(ENTITY_RESOLVER); - } catch (XMLConfigurationException e) { - entityResolver = null; - } } @Override public String[] getRecognizedFeatures() { - // TODO Auto-generated method stub return null; } @Override public void setFeature(String featureId, boolean state) throws XMLConfigurationException { - // TODO Auto-generated method stub - } @Override public String[] getRecognizedProperties() { - // TODO Auto-generated method stub return null; } @@ -105,136 +93,130 @@ public Object getPropertyDefault(String propertyId) { @Override public void startDocument(XMLLocator locator, String encoding, NamespaceContext namespaceContext, Augmentations augs) throws XNIException { - + try { + if (verifierHandler == null) { + createVerifier(); + } + verifierHandler.startDocument(); + } catch (SAXException e) { + throw new XNIException(e); + } } @Override public void xmlDecl(String version, String encoding, String standalone, Augmentations augs) throws XNIException { - // TODO Auto-generated method stub - } @Override public void doctypeDecl(String rootElement, String publicId, String systemId, Augmentations augs) throws XNIException { - // TODO Auto-generated method stub - } @Override public void comment(XMLString text, Augmentations augs) throws XNIException { - // TODO Auto-generated method stub - } @Override public void processingInstruction(String target, XMLString data, Augmentations augs) throws XNIException { - // TODO Auto-generated method stub - + try { + verifierHandler.processingInstruction(target, data.toString()); + } catch (SAXException e) { + throw new XNIException(e); + } } @Override public void startElement(QName element, XMLAttributes attributes, Augmentations augs) throws XNIException { - if (!processed) { - try { - String expandedLoc = XMLEntityManager.expandSystemId(href, locator.getExpandedSystemId(), false); - Verifier verifier = verifierFactory.newVerifier(new InputSource(expandedLoc)); - verifier.setErrorHandler(errorReporter.getSAXErrorHandler()); - SAXParserFactory parserFactory = SAXParserFactory.newInstance(); - parserFactory.setNamespaceAware(true); - XMLReader xmlReader = parserFactory.newSAXParser().getXMLReader(); - xmlReader.setContentHandler(verifier.getVerifierHandler()); - xmlReader.parse(locator.getLiteralSystemId()); - processed = true; - } catch (VerifierConfigurationException | SAXException | IOException | ParserConfigurationException e) { - LOGGER.log(Level.SEVERE, "Something went wrong when validating useing relaxng:", e); + try { + if (verifierHandler == null) { + createVerifier(); } + verifierHandler.startElement(element.uri, element.localpart, element.rawname, + new AttributesWrapper(attributes)); + } catch (SAXException e) { + throw new XNIException(e); } } @Override public void emptyElement(QName element, XMLAttributes attributes, Augmentations augs) throws XNIException { - // TODO Auto-generated method stub - } @Override public void startGeneralEntity(String name, XMLResourceIdentifier identifier, String encoding, Augmentations augs) throws XNIException { - // TODO Auto-generated method stub - } @Override public void textDecl(String version, String encoding, Augmentations augs) throws XNIException { - // TODO Auto-generated method stub - } @Override public void endGeneralEntity(String name, Augmentations augs) throws XNIException { - // TODO Auto-generated method stub - } @Override public void characters(XMLString text, Augmentations augs) throws XNIException { - // TODO Auto-generated method stub - + try { + verifierHandler.characters(text.ch, text.offset, text.length); + } catch (SAXException e) { + throw new XNIException(e); + } } @Override public void ignorableWhitespace(XMLString text, Augmentations augs) throws XNIException { - // TODO Auto-generated method stub - + try { + verifierHandler.ignorableWhitespace(text.ch, text.offset, text.length); + } catch (SAXException e) { + throw new XNIException(e); + } } @Override public void endElement(QName element, Augmentations augs) throws XNIException { - // TODO Auto-generated method stub - + try { + verifierHandler.endElement(element.uri, element.localpart, element.rawname); + } catch (SAXException e) { + throw new XNIException(e); + } } @Override public void startCDATA(Augmentations augs) throws XNIException { - // TODO Auto-generated method stub - } @Override public void endCDATA(Augmentations augs) throws XNIException { - // TODO Auto-generated method stub - } @Override public void endDocument(Augmentations augs) throws XNIException { - // TODO Auto-generated method stub - + try { + verifierHandler.endDocument(); + } catch (SAXException e) { + throw new XNIException(e); + } } @Override public void setDocumentSource(XMLDocumentSource source) { - // TODO Auto-generated method stub - + // do nothing } @Override public XMLDocumentSource getDocumentSource() { - // TODO Auto-generated method stub return null; } @Override public void setDocumentHandler(XMLDocumentHandler handler) { - // TODO Auto-generated method stub - + // do nothing } @Override public XMLDocumentHandler getDocumentHandler() { - // TODO Auto-generated method stub - return null; + return this; // TODO: ?? } @Override @@ -247,4 +229,72 @@ public void setHref(String href) { this.href = href; } + private final class AttributesWrapper implements Attributes { + private final XMLAttributes attributes; + + private AttributesWrapper(XMLAttributes attributes) { + this.attributes = attributes; + } + + @Override + public int getLength() { + return attributes.getLength(); + } + + @Override + public String getURI(int index) { + return attributes.getURI(index); + } + + @Override + public String getLocalName(int index) { + return attributes.getLocalName(index); + } + + @Override + public String getQName(int index) { + return attributes.getQName(index); + } + + @Override + public String getType(int index) { + return attributes.getType(index); + } + + @Override + public String getValue(int index) { + return attributes.getValue(index); + } + + @Override + public int getIndex(String uri, String localName) { + return attributes.getIndex(uri, localName); + } + + @Override + public int getIndex(String qName) { + return attributes.getIndex(qName); + } + + @Override + public String getType(String uri, String localName) { + return attributes.getType(uri, localName); + } + + @Override + public String getType(String qName) { + return attributes.getType(qName); + } + + @Override + public String getValue(String uri, String localName) { + return attributes.getValue(uri, localName); + } + + @Override + public String getValue(String qName) { + return attributes.getValue(qName); + } + } + } From b61344998946b2b3e25a000b749ea77054a0b2d7 Mon Sep 17 00:00:00 2001 From: David Thompson Date: Wed, 14 Sep 2022 10:31:49 -0400 Subject: [PATCH 05/15] WIP error code to range mechanism Signed-off-by: David Thompson --- .../diagnostics/LSPErrorReporterForXML.java | 9 ++++++ .../diagnostics/RNGErrorCode.java | 31 +++++++++++++++++++ .../xerces/AbstractLSPErrorReporter.java | 4 +-- 3 files changed, 42 insertions(+), 2 deletions(-) create mode 100644 org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/contentmodel/participants/diagnostics/RNGErrorCode.java diff --git a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/contentmodel/participants/diagnostics/LSPErrorReporterForXML.java b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/contentmodel/participants/diagnostics/LSPErrorReporterForXML.java index d42fb0e4e..6806f629f 100644 --- a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/contentmodel/participants/diagnostics/LSPErrorReporterForXML.java +++ b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/contentmodel/participants/diagnostics/LSPErrorReporterForXML.java @@ -101,6 +101,15 @@ protected Range toLSPRange(XMLLocator location, String key, Object[] arguments, fatalError, document.getResolverExtensionManager(), null, null, null, xsdCode, documentOrGrammarURI); return NO_RANGE; + } else { + RNGErrorCode rngCode = RNGErrorCode.get(key); + if (rngCode != null) { + if (errorForDocument) { + // TODO: + } else { + // TODO: + } + } } } } diff --git a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/contentmodel/participants/diagnostics/RNGErrorCode.java b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/contentmodel/participants/diagnostics/RNGErrorCode.java new file mode 100644 index 000000000..a2b983474 --- /dev/null +++ b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/contentmodel/participants/diagnostics/RNGErrorCode.java @@ -0,0 +1,31 @@ +package org.eclipse.lemminx.extensions.contentmodel.participants.diagnostics; + +import java.util.HashMap; +import java.util.Map; + +import org.eclipse.lemminx.extensions.contentmodel.participants.DTDErrorCode; + +// TODO: move to correct package? +public enum RNGErrorCode { + + // TODO: fill out the codes + IncompleteContentModel; + + private static Map codes; + + static { + codes = new HashMap<>(); + for (RNGErrorCode errorCode : values()) { + codes.put(errorCode.getCode(), errorCode); + } + } + + public static RNGErrorCode get(String name) { + return codes.get(name); + } + + private String getCode() { + return null; // TODO: implement + } + +} diff --git a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xerces/AbstractLSPErrorReporter.java b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xerces/AbstractLSPErrorReporter.java index 6fda90755..b56e2562c 100644 --- a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xerces/AbstractLSPErrorReporter.java +++ b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xerces/AbstractLSPErrorReporter.java @@ -85,7 +85,8 @@ public String reportError(XMLLocator location, String domain, String key, Object currentError = null; } // format message - String message = getMessage(domain, key, arguments, exception); + String code = getCode(domain, key, arguments, exception); + String message = getMessage(domain, code, arguments, exception); boolean fatalError = severity == SEVERITY_FATAL_ERROR; DiagnosticSeverity diagnosticSeverity = getSeverity(domain, key, arguments, severity, exception); @@ -103,7 +104,6 @@ public String reportError(XMLLocator location, String domain, String key, Object LOGGER.severe("Passed bad Range: " + e); } } - String code = getCode(domain, key, arguments, exception); if (addDiagnostic(adjustedRange, message, diagnosticSeverity, code, relatedInformations) == null) { return null; } From 760eaa1ecce32fc166a837bf6bdae525f5437e2c Mon Sep 17 00:00:00 2001 From: David Thompson Date: Wed, 14 Sep 2022 16:23:02 -0400 Subject: [PATCH 06/15] Get some of the bassic error ranges and self-closing tags working Signed-off-by: David Thompson --- .../diagnostics/LSPErrorReporterForXML.java | 7 +- .../diagnostics/RNGErrorCode.java | 61 ++++++++- .../xerces/AbstractLSPErrorReporter.java | 6 +- .../xmlmodel/XMLModelRelaxNGValidator.java | 129 +++++++++++++++--- 4 files changed, 174 insertions(+), 29 deletions(-) diff --git a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/contentmodel/participants/diagnostics/LSPErrorReporterForXML.java b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/contentmodel/participants/diagnostics/LSPErrorReporterForXML.java index 6806f629f..a695c802f 100644 --- a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/contentmodel/participants/diagnostics/LSPErrorReporterForXML.java +++ b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/contentmodel/participants/diagnostics/LSPErrorReporterForXML.java @@ -105,9 +105,12 @@ protected Range toLSPRange(XMLLocator location, String key, Object[] arguments, RNGErrorCode rngCode = RNGErrorCode.get(key); if (rngCode != null) { if (errorForDocument) { - // TODO: + Range range = RNGErrorCode.toLSPRange(location, rngCode, message, arguments, document); + if (range != null) { + return range; + } } else { - // TODO: + // TODO: setup reporting errors on referenced RNG files } } } diff --git a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/contentmodel/participants/diagnostics/RNGErrorCode.java b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/contentmodel/participants/diagnostics/RNGErrorCode.java index a2b983474..bf25f59b4 100644 --- a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/contentmodel/participants/diagnostics/RNGErrorCode.java +++ b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/contentmodel/participants/diagnostics/RNGErrorCode.java @@ -2,16 +2,26 @@ import java.util.HashMap; import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; -import org.eclipse.lemminx.extensions.contentmodel.participants.DTDErrorCode; +import org.apache.xerces.xni.XMLLocator; +import org.eclipse.lemminx.dom.DOMDocument; +import org.eclipse.lemminx.services.extensions.diagnostics.IXMLErrorCode; +import org.eclipse.lemminx.utils.XMLPositionUtility; +import org.eclipse.lsp4j.Range; -// TODO: move to correct package? -public enum RNGErrorCode { +public enum RNGErrorCode implements IXMLErrorCode { // TODO: fill out the codes - IncompleteContentModel; + IncompleteContentModel, + BadTagName, + BadAttribute, + MissingAttribute, + InvalidRelaxNG; - private static Map codes; + private final String code; + private final static Map codes; static { codes = new HashMap<>(); @@ -20,12 +30,49 @@ public enum RNGErrorCode { } } + private RNGErrorCode() { + this(null); + } + + private RNGErrorCode(String code) { + this.code = code; + } + public static RNGErrorCode get(String name) { return codes.get(name); } - private String getCode() { - return null; // TODO: implement + @Override + public String getCode() { + if (code == null) { + return name(); + } + return code; + } + + // ------------------------------------------------------------------------- + + private static final Pattern BAD_ATTRIBUTE_ATTRIBUTE_EXTRACTOR = Pattern.compile("[^\"]+\"([^\"]*)\""); + + public static Range toLSPRange(XMLLocator location, RNGErrorCode code, String message, Object[] arguments, + DOMDocument document) { + int offset = location.getCharacterOffset() - 1; + switch (code) { + case BadTagName: + case MissingAttribute: + return XMLPositionUtility.selectStartTagName(offset, document); + case BadAttribute: { + Matcher m = BAD_ATTRIBUTE_ATTRIBUTE_EXTRACTOR.matcher(message); + m.find(); + String attrName = m.group(1); + return XMLPositionUtility.selectAttributeNameFromGivenNameAt(attrName, offset, document); + } + case InvalidRelaxNG: { + return XMLPositionUtility.selectRootStartTag(document); + } + default: + return null; + } } } diff --git a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xerces/AbstractLSPErrorReporter.java b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xerces/AbstractLSPErrorReporter.java index b56e2562c..ba67544b1 100644 --- a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xerces/AbstractLSPErrorReporter.java +++ b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xerces/AbstractLSPErrorReporter.java @@ -16,7 +16,6 @@ import java.util.logging.Level; import java.util.logging.Logger; -import com.sun.msv.verifier.ValidityViolation; import org.apache.xerces.impl.XMLEntityManager; import org.apache.xerces.impl.XMLErrorReporter; import org.apache.xerces.impl.msg.XMLMessageFormatter; @@ -44,6 +43,8 @@ import org.eclipse.lsp4j.Range; import org.xml.sax.ErrorHandler; +import com.sun.msv.verifier.ValidityViolation; + /** * The SAX {@link ErrorHandler} gives just information of the offset where there * is an error. To improve highlight XML error, this class extends the Xerces @@ -90,7 +91,7 @@ public String reportError(XMLLocator location, String domain, String key, Object boolean fatalError = severity == SEVERITY_FATAL_ERROR; DiagnosticSeverity diagnosticSeverity = getSeverity(domain, key, arguments, severity, exception); - Range adjustedRange = internalToLSPRange(location, key, arguments, message, diagnosticSeverity, fatalError, + Range adjustedRange = internalToLSPRange(location, code, arguments, message, diagnosticSeverity, fatalError, xmlDocument, exception); List relatedInformations = null; if (adjustedRange == null || NO_RANGE.equals(adjustedRange)) { @@ -329,6 +330,7 @@ public void warning(String domain, String key, XMLParseException exception) thro @Override public void fatalError(String domain, String key, XMLParseException exception) throws XNIException { + // Allow parser to continue under fatal error reportError(domain, key, null, SEVERITY_FATAL_ERROR, exception); } diff --git a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xerces/xmlmodel/XMLModelRelaxNGValidator.java b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xerces/xmlmodel/XMLModelRelaxNGValidator.java index 5f9f0492f..df8790c94 100644 --- a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xerces/xmlmodel/XMLModelRelaxNGValidator.java +++ b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xerces/xmlmodel/XMLModelRelaxNGValidator.java @@ -19,12 +19,19 @@ import org.apache.xerces.xni.parser.XMLComponentManager; import org.apache.xerces.xni.parser.XMLConfigurationException; import org.apache.xerces.xni.parser.XMLDocumentSource; +import org.eclipse.lemminx.extensions.contentmodel.participants.diagnostics.RNGErrorCode; import org.iso_relax.verifier.Verifier; import org.iso_relax.verifier.VerifierConfigurationException; import org.iso_relax.verifier.VerifierFactory; import org.iso_relax.verifier.VerifierHandler; import org.xml.sax.Attributes; +import org.xml.sax.ErrorHandler; +import org.xml.sax.Locator; import org.xml.sax.SAXException; +import org.xml.sax.SAXParseException; +import org.xml.sax.helpers.XMLFilterImpl; + +import com.sun.msv.verifier.ValidityViolation; public class XMLModelRelaxNGValidator implements XMLModelValidator { @@ -33,7 +40,7 @@ public class XMLModelRelaxNGValidator implements XMLModelValidator { public static final String ERROR_REPORTER = Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_REPORTER_PROPERTY; private String href; - private VerifierHandler verifierHandler; + private Interceptor interceptor; private XMLLocator locator; private XMLErrorReporter errorReporter; @@ -41,10 +48,16 @@ private void createVerifier() throws SAXException { try { String expandedLoc = XMLEntityManager.expandSystemId(href, locator.getBaseSystemId(), false); Verifier verifier = VERIFIER_FACTORY.newVerifier(expandedLoc); - verifier.setErrorHandler(errorReporter.getSAXErrorHandler()); - verifierHandler = verifier.getVerifierHandler(); - verifierHandler.startDocument(); - } catch (VerifierConfigurationException | IOException e) { + verifier.setErrorHandler(com.sun.msv.verifier.util.ErrorHandlerImpl.theInstance); + VerifierHandler verifierHandler = verifier.getVerifierHandler(); + interceptor = new Interceptor(); + interceptor.setErrorHandler(errorReporter.getSAXErrorHandler()); + interceptor.setContentHandler(verifierHandler); + interceptor.startDocument(); + } catch (VerifierConfigurationException vce) { + errorReporter.reportError("https://relaxng.org", RNGErrorCode.InvalidRelaxNG.getCode(), new Object[] {}, + XMLErrorReporter.SEVERITY_FATAL_ERROR); + } catch (IOException e) { LOGGER.log(Level.SEVERE, "Failed to create RelaxNG validator: ", e); } } @@ -74,19 +87,15 @@ public String[] getRecognizedProperties() { @Override public void setProperty(String propertyId, Object value) throws XMLConfigurationException { - // TODO Auto-generated method stub - } @Override public Boolean getFeatureDefault(String featureId) { - // TODO Auto-generated method stub return null; } @Override public Object getPropertyDefault(String propertyId) { - // TODO Auto-generated method stub return null; } @@ -94,10 +103,10 @@ public Object getPropertyDefault(String propertyId) { public void startDocument(XMLLocator locator, String encoding, NamespaceContext namespaceContext, Augmentations augs) throws XNIException { try { - if (verifierHandler == null) { + if (interceptor == null) { createVerifier(); } - verifierHandler.startDocument(); + interceptor.startDocument(); } catch (SAXException e) { throw new XNIException(e); } @@ -119,7 +128,7 @@ public void comment(XMLString text, Augmentations augs) throws XNIException { @Override public void processingInstruction(String target, XMLString data, Augmentations augs) throws XNIException { try { - verifierHandler.processingInstruction(target, data.toString()); + interceptor.processingInstruction(target, data.toString()); } catch (SAXException e) { throw new XNIException(e); } @@ -128,10 +137,10 @@ public void processingInstruction(String target, XMLString data, Augmentations a @Override public void startElement(QName element, XMLAttributes attributes, Augmentations augs) throws XNIException { try { - if (verifierHandler == null) { + if (interceptor == null) { createVerifier(); } - verifierHandler.startElement(element.uri, element.localpart, element.rawname, + interceptor.startElement(element.uri, element.localpart, element.rawname, new AttributesWrapper(attributes)); } catch (SAXException e) { throw new XNIException(e); @@ -140,6 +149,12 @@ public void startElement(QName element, XMLAttributes attributes, Augmentations @Override public void emptyElement(QName element, XMLAttributes attributes, Augmentations augs) throws XNIException { + try { + interceptor.startElement(element.uri, element.localpart, element.rawname, new AttributesWrapper(attributes)); + interceptor.endElement(element.uri, element.localpart, element.rawname); + } catch (SAXException e) { + throw new XNIException(e); + } } @Override @@ -158,7 +173,7 @@ public void endGeneralEntity(String name, Augmentations augs) throws XNIExceptio @Override public void characters(XMLString text, Augmentations augs) throws XNIException { try { - verifierHandler.characters(text.ch, text.offset, text.length); + interceptor.characters(text.ch, text.offset, text.length); } catch (SAXException e) { throw new XNIException(e); } @@ -167,7 +182,7 @@ public void characters(XMLString text, Augmentations augs) throws XNIException { @Override public void ignorableWhitespace(XMLString text, Augmentations augs) throws XNIException { try { - verifierHandler.ignorableWhitespace(text.ch, text.offset, text.length); + interceptor.ignorableWhitespace(text.ch, text.offset, text.length); } catch (SAXException e) { throw new XNIException(e); } @@ -176,7 +191,7 @@ public void ignorableWhitespace(XMLString text, Augmentations augs) throws XNIEx @Override public void endElement(QName element, Augmentations augs) throws XNIException { try { - verifierHandler.endElement(element.uri, element.localpart, element.rawname); + interceptor.endElement(element.uri, element.localpart, element.rawname); } catch (SAXException e) { throw new XNIException(e); } @@ -193,7 +208,7 @@ public void endCDATA(Augmentations augs) throws XNIException { @Override public void endDocument(Augmentations augs) throws XNIException { try { - verifierHandler.endDocument(); + interceptor.endDocument(); } catch (SAXException e) { throw new XNIException(e); } @@ -297,4 +312,82 @@ public String getValue(String qName) { } } + private final class LocatorWrapper implements Locator { + + private final XMLLocator xmlLocator; + + public LocatorWrapper(XMLLocator xmlLocator) { + this.xmlLocator = xmlLocator; + } + + @Override + public String getPublicId() { + return xmlLocator.getPublicId(); + } + + @Override + public String getSystemId() { + return xmlLocator.getLiteralSystemId(); + } + + @Override + public int getLineNumber() { + return xmlLocator.getLineNumber(); + } + + @Override + public int getColumnNumber() { + return xmlLocator.getColumnNumber(); + } + } + + /** + * Please refer to the MSV demo: + * + * https://github.com/xmlark/msv/blob/main/msv/examples/errorinfo/ErrorReporter.java + */ + private static class Interceptor extends XMLFilterImpl { + + private static final ErrorHandler IGNORE_ERROR_HANDLER = new ErrorHandler() { + + @Override + public void warning(SAXParseException exception) throws SAXException { + } + + @Override + public void error(SAXParseException exception) throws SAXException { + } + + @Override + public void fatalError(SAXParseException exception) throws SAXException { + } + + }; + + public Interceptor() { + super(); + setErrorHandler(IGNORE_ERROR_HANDLER); + } + + @Override + public void startElement( + String ns, String local, String qname, Attributes atts) + throws SAXException { + try { + super.startElement(ns, local, qname, atts); + } catch (ValidityViolation vv) { + this.getErrorHandler().error(vv); + } + } + + @Override + public void endElement(String ns, String local, String qname) throws SAXException { + try { + super.endElement(ns, local, qname); + } catch (ValidityViolation vv) { + this.getErrorHandler().error(vv); + } + } + } + } From b3313bda885880302fb5c383e123f650c38356d8 Mon Sep 17 00:00:00 2001 From: David Thompson Date: Wed, 14 Sep 2022 16:57:25 -0400 Subject: [PATCH 07/15] WIP cleanup code Signed-off-by: David Thompson --- .../diagnostics/MultipleContentHandler.java | 100 ------------------ .../diagnostics/RNGErrorCode.java | 18 +++- .../diagnostics/XMLValidator.java | 5 +- .../xerces/AbstractLSPErrorReporter.java | 17 ++- .../xerces/xmlmodel/XMLModelDTDValidator.java | 1 - .../xmlmodel/XMLModelRelaxNGValidator.java | 56 +++++----- .../xmlmodel/XMLModelSchemaValidator.java | 1 - 7 files changed, 50 insertions(+), 148 deletions(-) delete mode 100644 org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/contentmodel/participants/diagnostics/MultipleContentHandler.java diff --git a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/contentmodel/participants/diagnostics/MultipleContentHandler.java b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/contentmodel/participants/diagnostics/MultipleContentHandler.java deleted file mode 100644 index 690cfe0be..000000000 --- a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/contentmodel/participants/diagnostics/MultipleContentHandler.java +++ /dev/null @@ -1,100 +0,0 @@ -package org.eclipse.lemminx.extensions.contentmodel.participants.diagnostics; - -import java.util.ArrayList; -import java.util.List; - -import org.xml.sax.Attributes; -import org.xml.sax.ContentHandler; -import org.xml.sax.Locator; -import org.xml.sax.SAXException; - -public class MultipleContentHandler implements ContentHandler { - - private final List handlers; - - public MultipleContentHandler() { - this.handlers = new ArrayList<>(); - } - - @Override - public void setDocumentLocator(Locator locator) { - for (ContentHandler contentHandler : handlers) { - contentHandler.setDocumentLocator(locator); - } - } - - @Override - public void startDocument() throws SAXException { - for (ContentHandler contentHandler : handlers) { - contentHandler.startDocument(); - } - } - - @Override - public void endDocument() throws SAXException { - for (ContentHandler contentHandler : handlers) { - contentHandler.endDocument(); - } - } - - @Override - public void startPrefixMapping(String prefix, String uri) throws SAXException { - for (ContentHandler contentHandler : handlers) { - contentHandler.startPrefixMapping(prefix, uri); - } - } - - @Override - public void endPrefixMapping(String prefix) throws SAXException { - for (ContentHandler contentHandler : handlers) { - contentHandler.endPrefixMapping(prefix); - } - } - - @Override - public void startElement(String uri, String localName, String qName, Attributes atts) throws SAXException { - for (ContentHandler contentHandler : handlers) { - contentHandler.startElement(uri, localName, qName, atts); - } - } - - @Override - public void endElement(String uri, String localName, String qName) throws SAXException { - for (ContentHandler contentHandler : handlers) { - contentHandler.endElement(uri, localName, qName); - } - } - - @Override - public void characters(char[] ch, int start, int length) throws SAXException { - for (ContentHandler contentHandler : handlers) { - contentHandler.characters(ch, start, length); - } - } - - @Override - public void ignorableWhitespace(char[] ch, int start, int length) throws SAXException { - for (ContentHandler contentHandler : handlers) { - contentHandler.ignorableWhitespace(ch, start, length); - } - } - - @Override - public void processingInstruction(String target, String data) throws SAXException { - for (ContentHandler contentHandler : handlers) { - contentHandler.processingInstruction(target, data); - } - } - - @Override - public void skippedEntity(String name) throws SAXException { - for (ContentHandler contentHandler : handlers) { - contentHandler.skippedEntity(name); - } - } - - public void addContentHandler(ContentHandler contentHandler) { - handlers.add(contentHandler); - } - -} \ No newline at end of file diff --git a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/contentmodel/participants/diagnostics/RNGErrorCode.java b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/contentmodel/participants/diagnostics/RNGErrorCode.java index bf25f59b4..44d994dd8 100644 --- a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/contentmodel/participants/diagnostics/RNGErrorCode.java +++ b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/contentmodel/participants/diagnostics/RNGErrorCode.java @@ -1,3 +1,14 @@ +/******************************************************************************* +* Copyright (c) 2022 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.participants.diagnostics; import java.util.HashMap; @@ -11,9 +22,14 @@ import org.eclipse.lemminx.utils.XMLPositionUtility; import org.eclipse.lsp4j.Range; +/** + * Represents an error code generated by validating a document against a RelaxNG + * schema. + * + * @author datho7561 + */ public enum RNGErrorCode implements IXMLErrorCode { - // TODO: fill out the codes IncompleteContentModel, BadTagName, BadAttribute, diff --git a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/contentmodel/participants/diagnostics/XMLValidator.java b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/contentmodel/participants/diagnostics/XMLValidator.java index 99cf18eab..02c9614c2 100644 --- a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/contentmodel/participants/diagnostics/XMLValidator.java +++ b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/contentmodel/participants/diagnostics/XMLValidator.java @@ -95,11 +95,8 @@ public static void doDiagnostics(DOMDocument document, XMLEntityResolver entityR SAXParser parser = new LSPSAXParser(reporterForXML, configuration, grammarPool, document); - MultipleContentHandler multiContentHandler = new MultipleContentHandler(); // Add LSP content handler to stop XML parsing if monitor is canceled. - multiContentHandler.addContentHandler(new LSPContentHandler(monitor)); - - parser.setContentHandler(multiContentHandler); + parser.setContentHandler(new LSPContentHandler(monitor)); // warn if XML document is not bound to a grammar according the settings warnNoGrammar(document, diagnostics, validationSettings); diff --git a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xerces/AbstractLSPErrorReporter.java b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xerces/AbstractLSPErrorReporter.java index ba67544b1..c977e4a68 100644 --- a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xerces/AbstractLSPErrorReporter.java +++ b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xerces/AbstractLSPErrorReporter.java @@ -92,7 +92,7 @@ public String reportError(XMLLocator location, String domain, String key, Object boolean fatalError = severity == SEVERITY_FATAL_ERROR; DiagnosticSeverity diagnosticSeverity = getSeverity(domain, key, arguments, severity, exception); Range adjustedRange = internalToLSPRange(location, code, arguments, message, diagnosticSeverity, fatalError, - xmlDocument, exception); + xmlDocument); List relatedInformations = null; if (adjustedRange == null || NO_RANGE.equals(adjustedRange)) { return null; @@ -156,9 +156,9 @@ protected String getCode(String domain, String key, Object[] arguments, Exceptio return key; } if (exception instanceof XMLParseException) { - XMLParseException xmlParseException = ((XMLParseException)exception); + XMLParseException xmlParseException = ((XMLParseException) exception); if (xmlParseException.getCause() instanceof ValidityViolation) { - ValidityViolation validityViolation = ((ValidityViolation)xmlParseException.getCause()); + ValidityViolation validityViolation = ((ValidityViolation) xmlParseException.getCause()); return validityViolation.getErrorInfo().getClass().getSimpleName(); } } @@ -191,10 +191,10 @@ public Diagnostic addDiagnostic(Range adjustedRange, String message, DiagnosticS */ private static DiagnosticSeverity toLSPSeverity(int severity) { switch (severity) { - case SEVERITY_WARNING: - return DiagnosticSeverity.Warning; - default: - return DiagnosticSeverity.Error; + case SEVERITY_WARNING: + return DiagnosticSeverity.Warning; + default: + return DiagnosticSeverity.Error; } } @@ -212,8 +212,7 @@ private static DiagnosticSeverity toLSPSeverity(int severity) { * @return the LSP range from the SAX error. */ private Range internalToLSPRange(XMLLocator location, String key, Object[] arguments, String message, - DiagnosticSeverity diagnosticSeverity, boolean fatalError, DOMDocument document, Exception exception) { - + DiagnosticSeverity diagnosticSeverity, boolean fatalError, DOMDocument document) { if (location == null) { Position start = toLSPPosition(0, location, document.getTextDocument()); Position end = toLSPPosition(0, location, document.getTextDocument()); diff --git a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xerces/xmlmodel/XMLModelDTDValidator.java b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xerces/xmlmodel/XMLModelDTDValidator.java index 25891174b..df5bcad28 100644 --- a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xerces/xmlmodel/XMLModelDTDValidator.java +++ b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xerces/xmlmodel/XMLModelDTDValidator.java @@ -12,7 +12,6 @@ package org.eclipse.lemminx.extensions.xerces.xmlmodel; import org.eclipse.lemminx.extensions.xerces.ExternalXMLDTDValidator; -import org.xml.sax.XMLReader; /** * XML model validator which process validation with DTD: diff --git a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xerces/xmlmodel/XMLModelRelaxNGValidator.java b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xerces/xmlmodel/XMLModelRelaxNGValidator.java index df8790c94..7c8d338ec 100644 --- a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xerces/xmlmodel/XMLModelRelaxNGValidator.java +++ b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xerces/xmlmodel/XMLModelRelaxNGValidator.java @@ -1,3 +1,14 @@ +/******************************************************************************* +* Copyright (c) 2022 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.xerces.xmlmodel; import java.io.IOException; @@ -33,6 +44,11 @@ import com.sun.msv.verifier.ValidityViolation; +/** + * Validates a document against a RelaxNG schema using MSV. + * + * @auhtor datho7561 + */ public class XMLModelRelaxNGValidator implements XMLModelValidator { private static final Logger LOGGER = Logger.getLogger(XMLModelRelaxNGValidator.class.getName()); @@ -150,7 +166,8 @@ public void startElement(QName element, XMLAttributes attributes, Augmentations @Override public void emptyElement(QName element, XMLAttributes attributes, Augmentations augs) throws XNIException { try { - interceptor.startElement(element.uri, element.localpart, element.rawname, new AttributesWrapper(attributes)); + interceptor.startElement(element.uri, element.localpart, element.rawname, + new AttributesWrapper(attributes)); interceptor.endElement(element.uri, element.localpart, element.rawname); } catch (SAXException e) { throw new XNIException(e); @@ -244,6 +261,10 @@ public void setHref(String href) { this.href = href; } + /** + * Wraps {@link org.apache.xerces.xni.XMLAttributes} to + * {@link org.xml.sax.Attributes}. + */ private final class AttributesWrapper implements Attributes { private final XMLAttributes attributes; @@ -312,38 +333,9 @@ public String getValue(String qName) { } } - private final class LocatorWrapper implements Locator { - - private final XMLLocator xmlLocator; - - public LocatorWrapper(XMLLocator xmlLocator) { - this.xmlLocator = xmlLocator; - } - - @Override - public String getPublicId() { - return xmlLocator.getPublicId(); - } - - @Override - public String getSystemId() { - return xmlLocator.getLiteralSystemId(); - } - - @Override - public int getLineNumber() { - return xmlLocator.getLineNumber(); - } - - @Override - public int getColumnNumber() { - return xmlLocator.getColumnNumber(); - } - } - /** - * Please refer to the MSV demo: - * + * Used to prevent a the schema validator from stopping on the first error it + * encounters. Please refer to the MSV demo: * https://github.com/xmlark/msv/blob/main/msv/examples/errorinfo/ErrorReporter.java */ private static class Interceptor extends XMLFilterImpl { diff --git a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xerces/xmlmodel/XMLModelSchemaValidator.java b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xerces/xmlmodel/XMLModelSchemaValidator.java index 193814e0e..45b6d19e4 100644 --- a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xerces/xmlmodel/XMLModelSchemaValidator.java +++ b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xerces/xmlmodel/XMLModelSchemaValidator.java @@ -24,7 +24,6 @@ import org.apache.xerces.xni.parser.XMLComponentManager; import org.apache.xerces.xni.parser.XMLConfigurationException; import org.eclipse.lemminx.utils.StringUtils; -import org.xml.sax.XMLReader; /** * XML model validator which process validation with XML Schema: From 3e2977931566cf857565480d4b81694c3b8e9e0b Mon Sep 17 00:00:00 2001 From: David Thompson Date: Thu, 15 Sep 2022 11:00:25 -0400 Subject: [PATCH 08/15] WIP fix the unit tests Signed-off-by: David Thompson --- .../xerces/AbstractLSPErrorReporter.java | 33 +++++++++++++------ .../lemminx/AbstractCacheBasedTest.java | 1 - 2 files changed, 23 insertions(+), 11 deletions(-) diff --git a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xerces/AbstractLSPErrorReporter.java b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xerces/AbstractLSPErrorReporter.java index c977e4a68..eaa894821 100644 --- a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xerces/AbstractLSPErrorReporter.java +++ b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xerces/AbstractLSPErrorReporter.java @@ -87,11 +87,11 @@ public String reportError(XMLLocator location, String domain, String key, Object } // format message String code = getCode(domain, key, arguments, exception); - String message = getMessage(domain, code, arguments, exception); + String message = getMessage(domain, key, arguments, exception); boolean fatalError = severity == SEVERITY_FATAL_ERROR; DiagnosticSeverity diagnosticSeverity = getSeverity(domain, key, arguments, severity, exception); - Range adjustedRange = internalToLSPRange(location, code, arguments, message, diagnosticSeverity, fatalError, + Range adjustedRange = internalToLSPRange(location, key, arguments, message, diagnosticSeverity, fatalError, xmlDocument); List relatedInformations = null; if (adjustedRange == null || NO_RANGE.equals(adjustedRange)) { @@ -155,13 +155,6 @@ protected String getCode(String domain, String key, Object[] arguments, Exceptio if (!StringUtils.isBlank(key)) { return key; } - if (exception instanceof XMLParseException) { - XMLParseException xmlParseException = ((XMLParseException) exception); - if (xmlParseException.getCause() instanceof ValidityViolation) { - ValidityViolation validityViolation = ((ValidityViolation) xmlParseException.getCause()); - return validityViolation.getErrorInfo().getClass().getSimpleName(); - } - } return ""; } @@ -324,17 +317,37 @@ public ErrorHandler getSAXErrorHandler() { @Override public void warning(String domain, String key, XMLParseException exception) throws XNIException { + if (StringUtils.isBlank(key) && exception instanceof XMLParseException) { + XMLParseException xmlParseException = ((XMLParseException) exception); + if (xmlParseException.getCause() instanceof ValidityViolation) { + ValidityViolation validityViolation = ((ValidityViolation) xmlParseException.getCause()); + key = validityViolation.getErrorInfo().getClass().getSimpleName(); + } + } reportError(domain, key, null, SEVERITY_WARNING, exception); } @Override public void fatalError(String domain, String key, XMLParseException exception) throws XNIException { - // Allow parser to continue under fatal error + if (StringUtils.isBlank(key) && exception instanceof XMLParseException) { + XMLParseException xmlParseException = ((XMLParseException) exception); + if (xmlParseException.getCause() instanceof ValidityViolation) { + ValidityViolation validityViolation = ((ValidityViolation) xmlParseException.getCause()); + key = validityViolation.getErrorInfo().getClass().getSimpleName(); + } + } reportError(domain, key, null, SEVERITY_FATAL_ERROR, exception); } @Override public void error(String domain, String key, XMLParseException exception) throws XNIException { + if (StringUtils.isBlank(key) && exception instanceof XMLParseException) { + XMLParseException xmlParseException = ((XMLParseException) exception); + if (xmlParseException.getCause() instanceof ValidityViolation) { + ValidityViolation validityViolation = ((ValidityViolation) xmlParseException.getCause()); + key = validityViolation.getErrorInfo().getClass().getSimpleName(); + } + } reportError(domain, key, null, SEVERITY_ERROR, exception); } }; diff --git a/org.eclipse.lemminx/src/test/java/org/eclipse/lemminx/AbstractCacheBasedTest.java b/org.eclipse.lemminx/src/test/java/org/eclipse/lemminx/AbstractCacheBasedTest.java index 47ff2f058..101f2f8b5 100644 --- a/org.eclipse.lemminx/src/test/java/org/eclipse/lemminx/AbstractCacheBasedTest.java +++ b/org.eclipse.lemminx/src/test/java/org/eclipse/lemminx/AbstractCacheBasedTest.java @@ -45,7 +45,6 @@ public abstract class AbstractCacheBasedTest { @BeforeEach public final void setupCache() throws Exception { - System.out.println(this.getClass().getName() + ": " + uuid); clearCache(); FilesUtils.resetDeployPath(); Assertions.assertNotNull(parentDir); From 31e1e61a5c365b74beacfc7fc38ddb5666370f0b Mon Sep 17 00:00:00 2001 From: David Thompson Date: Thu, 15 Sep 2022 11:42:29 -0400 Subject: [PATCH 09/15] WIP fix the invalid schema error message * Put it on the xml-model tag Signed-off-by: David Thompson --- .../diagnostics/RNGErrorCode.java | 6 +++ .../xerces/AbstractLSPErrorReporter.java | 1 + .../xerces/RNGMessageFormatter.java | 48 +++++++++++++++++++ .../xmlmodel/XMLModelRelaxNGValidator.java | 5 +- 4 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xerces/RNGMessageFormatter.java diff --git a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/contentmodel/participants/diagnostics/RNGErrorCode.java b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/contentmodel/participants/diagnostics/RNGErrorCode.java index 44d994dd8..445433d6c 100644 --- a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/contentmodel/participants/diagnostics/RNGErrorCode.java +++ b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/contentmodel/participants/diagnostics/RNGErrorCode.java @@ -18,6 +18,7 @@ import org.apache.xerces.xni.XMLLocator; import org.eclipse.lemminx.dom.DOMDocument; +import org.eclipse.lemminx.dom.XMLModel; import org.eclipse.lemminx.services.extensions.diagnostics.IXMLErrorCode; import org.eclipse.lemminx.utils.XMLPositionUtility; import org.eclipse.lsp4j.Range; @@ -84,6 +85,11 @@ public static Range toLSPRange(XMLLocator location, RNGErrorCode code, String me return XMLPositionUtility.selectAttributeNameFromGivenNameAt(attrName, offset, document); } case InvalidRelaxNG: { + for (XMLModel xmlModel : document.getXMLModels()) { + if (message.contains(xmlModel.getHref())) { + return XMLPositionUtility.createRange(xmlModel.getHrefNode()); + } + } return XMLPositionUtility.selectRootStartTag(document); } default: diff --git a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xerces/AbstractLSPErrorReporter.java b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xerces/AbstractLSPErrorReporter.java index eaa894821..99cad96a4 100644 --- a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xerces/AbstractLSPErrorReporter.java +++ b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xerces/AbstractLSPErrorReporter.java @@ -76,6 +76,7 @@ public AbstractLSPErrorReporter(String source, DOMDocument xmlDocument, List Date: Thu, 15 Sep 2022 12:33:18 -0400 Subject: [PATCH 10/15] WIP use relaxng.rng for validating *.rng * kind of broken, since XSD thinks it can try to validate the document Signed-off-by: David Thompson --- .../{diagnostics => }/RNGErrorCode.java | 2 +- .../diagnostics/LSPErrorReporterForXML.java | 1 + .../lemminx/extensions/rng/RNGPlugin.java | 59 +++ .../rng/RNGURIResolverExtension.java | 53 +++ .../xerces/RNGMessageFormatter.java | 2 +- .../xmlmodel/XMLModelRelaxNGValidator.java | 3 +- .../org/eclipse/lemminx/utils/DOMUtils.java | 26 +- ....lemminx.services.extensions.IXMLExtension | 1 + .../main/resources/schemas/rng/relaxng.rng | 330 +++++++++++++++++ .../main/resources/schemas/rng/relaxng.xsd | 344 ++++++++++++++++++ 10 files changed, 809 insertions(+), 12 deletions(-) rename org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/contentmodel/participants/{diagnostics => }/RNGErrorCode.java (99%) create mode 100644 org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/rng/RNGPlugin.java create mode 100644 org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/rng/RNGURIResolverExtension.java create mode 100644 org.eclipse.lemminx/src/main/resources/schemas/rng/relaxng.rng create mode 100644 org.eclipse.lemminx/src/main/resources/schemas/rng/relaxng.xsd diff --git a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/contentmodel/participants/diagnostics/RNGErrorCode.java b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/contentmodel/participants/RNGErrorCode.java similarity index 99% rename from org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/contentmodel/participants/diagnostics/RNGErrorCode.java rename to org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/contentmodel/participants/RNGErrorCode.java index 445433d6c..77fd5a966 100644 --- a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/contentmodel/participants/diagnostics/RNGErrorCode.java +++ b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/contentmodel/participants/RNGErrorCode.java @@ -9,7 +9,7 @@ * Contributors: * Red Hat Inc. - initial API and implementation *******************************************************************************/ -package org.eclipse.lemminx.extensions.contentmodel.participants.diagnostics; +package org.eclipse.lemminx.extensions.contentmodel.participants; import java.util.HashMap; import java.util.Map; diff --git a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/contentmodel/participants/diagnostics/LSPErrorReporterForXML.java b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/contentmodel/participants/diagnostics/LSPErrorReporterForXML.java index a695c802f..383077c13 100644 --- a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/contentmodel/participants/diagnostics/LSPErrorReporterForXML.java +++ b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/contentmodel/participants/diagnostics/LSPErrorReporterForXML.java @@ -22,6 +22,7 @@ import org.eclipse.lemminx.extensions.contentmodel.model.ContentModelManager; import org.eclipse.lemminx.extensions.contentmodel.model.ReferencedGrammarInfo; import org.eclipse.lemminx.extensions.contentmodel.participants.DTDErrorCode; +import org.eclipse.lemminx.extensions.contentmodel.participants.RNGErrorCode; import org.eclipse.lemminx.extensions.contentmodel.participants.XMLSchemaErrorCode; import org.eclipse.lemminx.extensions.contentmodel.participants.XMLSyntaxErrorCode; import org.eclipse.lemminx.extensions.xerces.AbstractReferencedGrammarLSPErrorReporter; diff --git a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/rng/RNGPlugin.java b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/rng/RNGPlugin.java new file mode 100644 index 000000000..d2c7deb4a --- /dev/null +++ b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/rng/RNGPlugin.java @@ -0,0 +1,59 @@ +/******************************************************************************* +* Copyright (c) 2022 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.rng; + +import org.eclipse.lemminx.dom.DOMDocument; +import org.eclipse.lemminx.extensions.contentmodel.model.ContentModelManager; +import org.eclipse.lemminx.services.extensions.IXMLExtension; +import org.eclipse.lemminx.services.extensions.XMLExtensionsRegistry; +import org.eclipse.lemminx.services.extensions.save.ISaveContext; +import org.eclipse.lemminx.utils.DOMUtils; +import org.eclipse.lsp4j.InitializeParams; + +/** + * Plugin to help with editing RelaxNG grammars (in XML form). + * + * @author datho7561 + */ +public class RNGPlugin implements IXMLExtension { + + private RNGURIResolverExtension uriResolver; + private ContentModelManager contentModelManager; + + public RNGPlugin() { + + } + + @Override + public void doSave(ISaveContext context) { + String documentURI = context.getUri(); + if (DOMUtils.isRNG(documentURI)) { + context.collectDocumentToValidate(d -> { + DOMDocument xml = context.getDocument(d.getDocumentURI()); + return contentModelManager.dependsOnGrammar(xml, context.getUri()); + }); + } + } + + @Override + public void start(InitializeParams params, XMLExtensionsRegistry registry) { + uriResolver = new RNGURIResolverExtension(registry.getDocumentProvider()); + registry.getResolverExtensionManager().registerResolver(uriResolver); + contentModelManager = registry.getComponent(ContentModelManager.class); + } + + @Override + public void stop(XMLExtensionsRegistry registry) { + registry.getResolverExtensionManager().unregisterResolver(uriResolver); + } + +} diff --git a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/rng/RNGURIResolverExtension.java b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/rng/RNGURIResolverExtension.java new file mode 100644 index 000000000..fe3b390d8 --- /dev/null +++ b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/rng/RNGURIResolverExtension.java @@ -0,0 +1,53 @@ +/******************************************************************************* +* Copyright (c) 2022 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.rng; + +import java.io.IOException; + +import org.eclipse.lemminx.services.IXMLDocumentProvider; +import org.eclipse.lemminx.uriresolver.CacheResourcesManager; +import org.eclipse.lemminx.uriresolver.CacheResourcesManager.ResourceToDeploy; +import org.eclipse.lemminx.uriresolver.URIResolverExtension; +import org.eclipse.lemminx.utils.DOMUtils; + +/** + * Resolves all *.rng files to use the relaxng.rng schema + * + * @author datho7561 + */ +public class RNGURIResolverExtension implements URIResolverExtension { + + private static final ResourceToDeploy RNG_RNG = new ResourceToDeploy("http://relaxng.org/relaxng.rng", "schemas/rng/relaxng.rng"); + + + public RNGURIResolverExtension(IXMLDocumentProvider documentProvider) { + + } + + public String getName() { + return "embedded relaxng.rng"; + } + + @Override + public String resolve(String baseLocation, String publicId, String systemId) { + if (DOMUtils.isRNG(baseLocation)) { + try { + CacheResourcesManager.getResourceCachePath(RNG_RNG); + return RNG_RNG.getDeployedPath().toFile().toURI().toString(); + } catch (IOException e) { + // do nothing + } + } + return null; + } + +} diff --git a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xerces/RNGMessageFormatter.java b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xerces/RNGMessageFormatter.java index e9229a553..aa7678315 100644 --- a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xerces/RNGMessageFormatter.java +++ b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xerces/RNGMessageFormatter.java @@ -16,7 +16,7 @@ import java.util.MissingResourceException; import org.apache.xerces.util.MessageFormatter; -import org.eclipse.lemminx.extensions.contentmodel.participants.diagnostics.RNGErrorCode; +import org.eclipse.lemminx.extensions.contentmodel.participants.RNGErrorCode; /** * Formats messages generated by the RelaxNG schema formatter. diff --git a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xerces/xmlmodel/XMLModelRelaxNGValidator.java b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xerces/xmlmodel/XMLModelRelaxNGValidator.java index b41c40d90..2428c3aa8 100644 --- a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xerces/xmlmodel/XMLModelRelaxNGValidator.java +++ b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xerces/xmlmodel/XMLModelRelaxNGValidator.java @@ -30,14 +30,13 @@ import org.apache.xerces.xni.parser.XMLComponentManager; import org.apache.xerces.xni.parser.XMLConfigurationException; import org.apache.xerces.xni.parser.XMLDocumentSource; -import org.eclipse.lemminx.extensions.contentmodel.participants.diagnostics.RNGErrorCode; +import org.eclipse.lemminx.extensions.contentmodel.participants.RNGErrorCode; import org.iso_relax.verifier.Verifier; import org.iso_relax.verifier.VerifierConfigurationException; import org.iso_relax.verifier.VerifierFactory; import org.iso_relax.verifier.VerifierHandler; import org.xml.sax.Attributes; import org.xml.sax.ErrorHandler; -import org.xml.sax.Locator; import org.xml.sax.SAXException; import org.xml.sax.SAXParseException; import org.xml.sax.helpers.XMLFilterImpl; diff --git a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/utils/DOMUtils.java b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/utils/DOMUtils.java index b24d1a7de..f360bf680 100644 --- a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/utils/DOMUtils.java +++ b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/utils/DOMUtils.java @@ -52,7 +52,7 @@ private DOMUtils() { /** * Returns true if the XML document is a XML Schema and false otherwise. - * + * * @return true if the XML document is a XML Schema and false otherwise. */ public static boolean isXSD(DOMDocument document) { @@ -70,7 +70,7 @@ public static boolean isXSD(DOMDocument document) { /** * Returns true if the given URI is a XML Schema and false otherwise. - * + * * @param uri the URI to check * @return true if the given URI is a XML Schema and false otherwise. */ @@ -80,7 +80,7 @@ public static boolean isXSD(String uri) { /** * Returns true if the XML document is a XML Catalog and false otherwise. - * + * * @return true if the XML document is a XML Catalog and false otherwise. */ public static boolean isCatalog(DOMDocument document) { @@ -92,7 +92,7 @@ public static boolean isCatalog(DOMDocument document) { /** * Returns true if the document element root is bound to the given namespace and * false otherwise. - * + * * @param document * @param namespace * @return true if the document element root is bound to the given namespace and @@ -105,7 +105,7 @@ private static boolean checkRootNamespace(DOMDocument document, String namespace /** * Returns true if the given URI is a DTD and false otherwise. - * + * * @param uri the URI to check * @return true if the given URI is a DTD and false otherwise. */ @@ -116,7 +116,7 @@ public static boolean isDTD(String uri) { /** * Returns true if element contains only DOMText and false otherwise. - * + * * @return true if element contains only DOMText and false otherwise. */ public static boolean containsTextOnly(DOMElement element) { @@ -125,7 +125,7 @@ public static boolean containsTextOnly(DOMElement element) { /** * Returns the DOM document from the given XML Schema uri. - * + * * @param documentURI the schema URI * @param resolverExtensionManager * @return the DOM document from the given XML Schema uri. @@ -143,7 +143,7 @@ public static DOMDocument loadDocument(String documentURI, URIResolverExtensionM /** * Returns an instance of SAX parser factory by disabling external entities * declarations. - * + * * @return an instance of SAX parser factory by disabling external entities * declarations. * @throws SAXNotRecognizedException @@ -157,4 +157,14 @@ public static SAXParserFactory newSAXParserFactory() factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); return factory; } + + /** + * Returns true if the given uri points to a .rng file (XML syntax only). + * + * @param uri the uri to check + * @return true if the given uri points to a .rng file (XML syntax only) + */ + public static boolean isRNG(String uri) { + return uri.endsWith(".rng"); + } } diff --git a/org.eclipse.lemminx/src/main/resources/META-INF/services/org.eclipse.lemminx.services.extensions.IXMLExtension b/org.eclipse.lemminx/src/main/resources/META-INF/services/org.eclipse.lemminx.services.extensions.IXMLExtension index f7d3982e3..3a5586d69 100644 --- a/org.eclipse.lemminx/src/main/resources/META-INF/services/org.eclipse.lemminx.services.extensions.IXMLExtension +++ b/org.eclipse.lemminx/src/main/resources/META-INF/services/org.eclipse.lemminx.services.extensions.IXMLExtension @@ -2,6 +2,7 @@ org.eclipse.lemminx.extensions.contentmodel.ContentModelPlugin org.eclipse.lemminx.extensions.references.XMLReferencesPlugin org.eclipse.lemminx.extensions.xsd.XSDPlugin org.eclipse.lemminx.extensions.dtd.DTDPlugin +org.eclipse.lemminx.extensions.rng.RNGPlugin org.eclipse.lemminx.extensions.xsl.XSLPlugin org.eclipse.lemminx.extensions.catalog.XMLCatalogPlugin org.eclipse.lemminx.extensions.xsi.XSISchemaPlugin diff --git a/org.eclipse.lemminx/src/main/resources/schemas/rng/relaxng.rng b/org.eclipse.lemminx/src/main/resources/schemas/rng/relaxng.rng new file mode 100644 index 000000000..5b16d1287 --- /dev/null +++ b/org.eclipse.lemminx/src/main/resources/schemas/rng/relaxng.rng @@ -0,0 +1,330 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + choice + interleave + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/org.eclipse.lemminx/src/main/resources/schemas/rng/relaxng.xsd b/org.eclipse.lemminx/src/main/resources/schemas/rng/relaxng.xsd new file mode 100644 index 000000000..8e1a5308a --- /dev/null +++ b/org.eclipse.lemminx/src/main/resources/schemas/rng/relaxng.xsd @@ -0,0 +1,344 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 3009452da58c42872686adededd7f2776a75ec2c Mon Sep 17 00:00:00 2001 From: David Thompson Date: Fri, 16 Sep 2022 15:00:38 -0400 Subject: [PATCH 11/15] WIP fix support for *.rng validation, use relaxng.xsd Signed-off-by: David Thompson --- .../org/eclipse/lemminx/dom/DOMDocument.java | 112 +++--- .../diagnostics/XMLValidator.java | 22 +- .../rng/RNGURIResolverExtension.java | 31 +- .../main/resources/schemas/rng/relaxng.rng | 330 ------------------ 4 files changed, 90 insertions(+), 405 deletions(-) delete mode 100644 org.eclipse.lemminx/src/main/resources/schemas/rng/relaxng.rng 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 28d785af3..1177c571b 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 @@ -115,7 +115,7 @@ public LineIndentInfo getLineIndentInfo(int lineNumber) throws BadLocationExcept /** * Returns the element name on the left of the given position and null * otherwise. - * + * * @param textOffset * @return the element name on the left of the given position and null * otherwise. @@ -133,7 +133,7 @@ public String getNamespaceURI() { /** * Returns the text content of the XML document. - * + * * @return the text content of the XML document. */ public String getText() { @@ -146,7 +146,7 @@ public TextDocument getTextDocument() { /** * Returns true if the document is bound to a grammar and false otherwise. - * + * * @return true if the document is bound to a grammar and false otherwise. */ public boolean hasGrammar() { @@ -158,7 +158,7 @@ public boolean hasGrammar() { /** * Returns the declared "xsi:schemaLocation" and null otherwise. - * + * * @return the declared "xsi:schemaLocation" and null otherwise. */ public SchemaLocation getSchemaLocation() { @@ -169,7 +169,7 @@ public SchemaLocation getSchemaLocation() { /** * Returns true if XML root element declares a "xsi:schemaLocation" and false * otherwise. - * + * * @return true if XML root element declares a "xsi:schemaLocation" and false * otherwise. */ @@ -179,7 +179,7 @@ public boolean hasSchemaLocation() { /** * Returns the declared "xsi:noNamespaceSchemaLocation" and null otherwise. - * + * * @return the declared "xsi:noNamespaceSchemaLocation" and null otherwise. */ public NoNamespaceSchemaLocation getNoNamespaceSchemaLocation() { @@ -190,7 +190,7 @@ public NoNamespaceSchemaLocation getNoNamespaceSchemaLocation() { /** * Returns true if XML root element declares a "xsi:noNamespaceSchemaLocation" * and false otherwise. - * + * * @return true if XML root element declares a "xsi:noNamespaceSchemaLocation" * and false otherwise. */ @@ -200,7 +200,7 @@ public boolean hasNoNamespaceSchemaLocation() { /** * Returns true if document defines namespaces (with xmlns) and false otherwise. - * + * * @return true if document defines namespaces (with xmlns) and false otherwise. */ public boolean hasNamespaces() { @@ -210,7 +210,7 @@ public boolean hasNamespaces() { /** * Returns the (xsi) schema instance prefix and null otherwise. - * + * * @return the (xsi) schema instance prefix and null otherwise. */ public String getSchemaInstancePrefix() { @@ -220,7 +220,7 @@ public String getSchemaInstancePrefix() { /** * Returns true if (xsi) schema instance prefix exists. - * + * * @return true if (xsi) schema instance prefix exists. */ public boolean hasSchemaInstancePrefix() { @@ -287,7 +287,7 @@ private synchronized void initializeReferencedSchema() { /** * If document has {@code } - * + * * @return */ public boolean hasProlog() { @@ -297,7 +297,7 @@ public boolean hasProlog() { /** * If document has {@code }, return this prolog, null otherwise - * + * * @return prolog DOMNode, if the document has one, null otherwise */ public DOMNode getProlog() { @@ -311,7 +311,7 @@ public DOMNode getProlog() { /** * Returns true, if the given offset is before XML declaration * ({@code }), false otherwise. - * + * * @param offset the offset position in question * @return true, if before xml declaration; false otherwise */ @@ -341,7 +341,7 @@ private static NoNamespaceSchemaLocation createNoNamespaceSchemaLocation(DOMNode /** * Returns true if XML document has a DTD declaration and false otherwise. - * + * * @return true if XML document has a DTD declaration and false otherwise. */ public boolean hasDTD() { @@ -353,7 +353,7 @@ public boolean hasDTD() { /** * Returns true if XML document has a xml-model processing declaration and false * otherwise. - * + * * @return true if XML document has a xml-model processing declaration and false * otherwise. */ @@ -364,7 +364,7 @@ public boolean hasXMLModel() { /** * Returns the list of xml-model processing instruction declared in the * document. - * + * * @return the list of xml-model processing instruction declared in the * document. */ @@ -378,7 +378,7 @@ public List getXMLModels() { /** * Returns true if the document is bound to an external grammar (XML file * associations, XLM catalog) and false otherwise. - * + * * @return true if the document is bound to an external grammar (XML file * associations, XLM catalog) and false otherwise. */ @@ -389,7 +389,7 @@ public boolean hasExternalGrammar() { /** * Returns the external grammar location (XSD, DTD from xml file associations) * and null otherwise. - * + * * @return the external grammar location (XSD, DTD from xml file associations) * and null otherwise. */ @@ -401,7 +401,7 @@ public Map getExternalGrammarLocation() { /** * Returns the grammar location found by the namespace URI from the document * root element (ex : found with XML catalog) and null otherwise. - * + * * @return the grammar location found by the namespace URI from the document * root element (ex : found with XML catalog) and null otherwise. */ @@ -491,7 +491,7 @@ public DOMDocumentType createDocumentType(int start, int end) { /* * (non-Javadoc) - * + * * @see org.w3c.dom.Node#getNodeType() */ @Override @@ -501,7 +501,7 @@ public short getNodeType() { /* * (non-Javadoc) - * + * * @see org.w3c.dom.Node#getNodeName() */ @Override @@ -511,7 +511,7 @@ public String getNodeName() { /* * (non-Javadoc) - * + * * @see org.w3c.dom.Document#getDocumentElement() */ @Override @@ -529,7 +529,7 @@ public DOMElement getDocumentElement() { /* * (non-Javadoc) - * + * * @see org.w3c.dom.Document#getDoctype() */ @Override @@ -552,7 +552,7 @@ public DOMDocument getOwnerDocument() { /* * (non-Javadoc) - * + * * @see org.w3c.dom.Document#getDocumentURI() */ @Override @@ -562,7 +562,7 @@ public String getDocumentURI() { /* * (non-Javadoc) - * + * * @see org.w3c.dom.Document#setDocumentURI(java.lang.String) */ @Override @@ -572,7 +572,7 @@ public void setDocumentURI(String documentURI) { /* * (non-Javadoc) - * + * * @see org.w3c.dom.Document#adoptNode(org.w3c.dom.Node) */ @Override @@ -582,7 +582,7 @@ public DOMNode adoptNode(org.w3c.dom.Node source) throws DOMException { /* * (non-Javadoc) - * + * * @see org.w3c.dom.Document#createAttribute(java.lang.String) */ @Override @@ -592,7 +592,7 @@ public DOMAttr createAttribute(String name) throws DOMException { /* * (non-Javadoc) - * + * * @see org.w3c.dom.Document#createAttributeNS(java.lang.String, * java.lang.String) */ @@ -603,7 +603,7 @@ public DOMAttr createAttributeNS(String namespaceURI, String qualifiedName) thro /* * (non-Javadoc) - * + * * @see org.w3c.dom.Document#createCDATASection(java.lang.String) */ @Override @@ -613,7 +613,7 @@ public CDATASection createCDATASection(String data) throws DOMException { /* * (non-Javadoc) - * + * * @see org.w3c.dom.Document#createComment(java.lang.String) */ @Override @@ -623,7 +623,7 @@ public DOMComment createComment(String data) { /* * (non-Javadoc) - * + * * @see org.w3c.dom.Document#createDocumentFragment() */ @Override @@ -633,7 +633,7 @@ public DocumentFragment createDocumentFragment() { /* * (non-Javadoc) - * + * * @see org.w3c.dom.Document#createElement(java.lang.String) */ @Override @@ -643,7 +643,7 @@ public DOMElement createElement(String tagName) throws DOMException { /* * (non-Javadoc) - * + * * @see org.w3c.dom.Document#createElementNS(java.lang.String, java.lang.String) */ @Override @@ -653,7 +653,7 @@ public DOMElement createElementNS(String namespaceURI, String qualifiedName) thr /* * (non-Javadoc) - * + * * @see org.w3c.dom.Document#createEntityReference(java.lang.String) */ @Override @@ -663,7 +663,7 @@ public EntityReference createEntityReference(String name) throws DOMException { /* * (non-Javadoc) - * + * * @see org.w3c.dom.Document#createProcessingInstruction(java.lang.String, * java.lang.String) */ @@ -674,7 +674,7 @@ public DOMProcessingInstruction createProcessingInstruction(String target, Strin /* * (non-Javadoc) - * + * * @see org.w3c.dom.Document#createTextNode(java.lang.String) */ @Override @@ -684,7 +684,7 @@ public DOMText createTextNode(String data) { /* * (non-Javadoc) - * + * * @see org.w3c.dom.Document#getDomConfig() */ @Override @@ -694,7 +694,7 @@ public DOMConfiguration getDomConfig() { /* * (non-Javadoc) - * + * * @see org.w3c.dom.Document#getElementById(java.lang.String) */ @Override @@ -704,7 +704,7 @@ public DOMElement getElementById(String elementId) { /* * (non-Javadoc) - * + * * @see org.w3c.dom.Document#getElementsByTagName(java.lang.String) */ @Override @@ -714,7 +714,7 @@ public NodeList getElementsByTagName(String tagname) { /* * (non-Javadoc) - * + * * @see org.w3c.dom.Document#getElementsByTagNameNS(java.lang.String, * java.lang.String) */ @@ -725,7 +725,7 @@ public NodeList getElementsByTagNameNS(String namespaceURI, String localName) { /* * (non-Javadoc) - * + * * @see org.w3c.dom.Document#getImplementation() */ @Override @@ -735,7 +735,7 @@ public DOMImplementation getImplementation() { /* * (non-Javadoc) - * + * * @see org.w3c.dom.Document#getInputEncoding() */ @Override @@ -745,7 +745,7 @@ public String getInputEncoding() { /* * (non-Javadoc) - * + * * @see org.w3c.dom.Document#getStrictErrorChecking() */ @Override @@ -755,7 +755,7 @@ public boolean getStrictErrorChecking() { /* * (non-Javadoc) - * + * * @see org.w3c.dom.Document#getXmlEncoding() */ @Override @@ -765,7 +765,7 @@ public String getXmlEncoding() { /* * (non-Javadoc) - * + * * @see org.w3c.dom.Document#getXmlStandalone() */ @Override @@ -775,7 +775,7 @@ public boolean getXmlStandalone() { /* * (non-Javadoc) - * + * * @see org.w3c.dom.Document#getXmlVersion() */ @Override @@ -785,7 +785,7 @@ public String getXmlVersion() { /* * (non-Javadoc) - * + * * @see org.w3c.dom.Document#importNode(org.w3c.dom.Node, boolean) */ @Override @@ -795,7 +795,7 @@ public DOMNode importNode(org.w3c.dom.Node importedNode, boolean deep) throws DO /* * (non-Javadoc) - * + * * @see org.w3c.dom.Document#normalizeDocument() */ @Override @@ -805,7 +805,7 @@ public void normalizeDocument() { /* * (non-Javadoc) - * + * * @see org.w3c.dom.Document#renameNode(org.w3c.dom.Node, java.lang.String, * java.lang.String) */ @@ -816,7 +816,7 @@ public DOMNode renameNode(org.w3c.dom.Node n, String namespaceURI, String qualif /* * (non-Javadoc) - * + * * @see org.w3c.dom.Document#setStrictErrorChecking(boolean) */ @Override @@ -826,7 +826,7 @@ public void setStrictErrorChecking(boolean strictErrorChecking) { /* * (non-Javadoc) - * + * * @see org.w3c.dom.Document#setXmlStandalone(boolean) */ @Override @@ -836,7 +836,7 @@ public void setXmlStandalone(boolean xmlStandalone) throws DOMException { /* * (non-Javadoc) - * + * * @see org.w3c.dom.Document#setXmlVersion(java.lang.String) */ @Override @@ -858,7 +858,7 @@ public URIResolverExtensionManager getResolverExtensionManager() { /** * Returns true if the XML document is a DTD and false otherwise. - * + * * @return true if the XML document is a DTD and false otherwise. */ public boolean isDTD() { @@ -871,7 +871,7 @@ public boolean isDTD() { /** * Returns true if 'offset' is within an internal DOCTYPE dtd. Else false. - * + * * @param offset * @return */ @@ -914,7 +914,7 @@ public Range getTrimmedRange(int start, int end) { /** * Returns the DTD Attribute list for the given element name and empty * otherwise. - * + * * @param elementName * @return the DTD Attribute list for the given element name and empty * otherwise. @@ -931,7 +931,7 @@ public Collection findDTDAttrList(String elementName) { /** * Returns the XML Schema prefix (ex : 'xs' for * xmlns:xs="http://www.w3.org/2001/XMLSchema") - * + * * @return the XML Schema prefix (ex : 'xs' for * xmlns:xs="http://www.w3.org/2001/XMLSchema") */ diff --git a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/contentmodel/participants/diagnostics/XMLValidator.java b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/contentmodel/participants/diagnostics/XMLValidator.java index 02c9614c2..7d299e977 100644 --- a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/contentmodel/participants/diagnostics/XMLValidator.java +++ b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/contentmodel/participants/diagnostics/XMLValidator.java @@ -352,19 +352,17 @@ private static void warnNoGrammar(DOMDocument document, List diagnos // "ignore" settings return; } - if (!hasGrammar) { - // No grammar, add a warn diagnostic with the severity coming from the settings. - Range range = null; - DOMElement documentElement = document.getDocumentElement(); - if (documentElement != null) { - range = XMLPositionUtility.selectStartTagName(documentElement); - } - if (range == null) { - range = new Range(new Position(0, 0), new Position(0, 0)); - } - diagnostics.add(new Diagnostic(range, "No grammar constraints (DTD or XML Schema).", severity, - "xml", XMLSyntaxErrorCode.NoGrammarConstraints.name())); + // No grammar, add a warn diagnostic with the severity coming from the settings. + Range range = null; + DOMElement documentElement = document.getDocumentElement(); + if (documentElement != null) { + range = XMLPositionUtility.selectStartTagName(documentElement); + } + if (range == null) { + range = new Range(new Position(0, 0), new Position(0, 0)); } + diagnostics.add(new Diagnostic(range, "No grammar constraints (DTD or XML Schema).", severity, + "xml", XMLSyntaxErrorCode.NoGrammarConstraints.name())); } private static void updateExternalGrammarLocation(DOMDocument document, SAXParser reader) diff --git a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/rng/RNGURIResolverExtension.java b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/rng/RNGURIResolverExtension.java index fe3b390d8..107012c2a 100644 --- a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/rng/RNGURIResolverExtension.java +++ b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/rng/RNGURIResolverExtension.java @@ -12,37 +12,54 @@ package org.eclipse.lemminx.extensions.rng; import java.io.IOException; +import java.net.URI; +import java.util.HashMap; +import java.util.Map; import org.eclipse.lemminx.services.IXMLDocumentProvider; import org.eclipse.lemminx.uriresolver.CacheResourcesManager; import org.eclipse.lemminx.uriresolver.CacheResourcesManager.ResourceToDeploy; +import org.eclipse.lemminx.uriresolver.IExternalGrammarLocationProvider; import org.eclipse.lemminx.uriresolver.URIResolverExtension; import org.eclipse.lemminx.utils.DOMUtils; /** - * Resolves all *.rng files to use the relaxng.rng schema + * Resolves all *.rng files to use the relaxng.xsd schema * * @author datho7561 */ -public class RNGURIResolverExtension implements URIResolverExtension { - - private static final ResourceToDeploy RNG_RNG = new ResourceToDeploy("http://relaxng.org/relaxng.rng", "schemas/rng/relaxng.rng"); +public class RNGURIResolverExtension implements URIResolverExtension, IExternalGrammarLocationProvider { + private static final ResourceToDeploy RNG_RNG = new ResourceToDeploy("http://relaxng.org/relaxng.xsd", + "schemas/rng/relaxng.xsd"); public RNGURIResolverExtension(IXMLDocumentProvider documentProvider) { } public String getName() { - return "embedded relaxng.rng"; + return "embedded relaxng.xsd"; + } + + @Override + public Map getExternalGrammarLocation(URI fileURI) { + return resolve(fileURI.toString()); } @Override public String resolve(String baseLocation, String publicId, String systemId) { - if (DOMUtils.isRNG(baseLocation)) { + return resolve(baseLocation).get(IExternalGrammarLocationProvider.NO_NAMESPACE_SCHEMA_LOCATION); + } + + public Map resolve(String uri) { + if (DOMUtils.isRNG(uri)) { try { + // XXX: I think this triggers the download, but confirm if this is needed CacheResourcesManager.getResourceCachePath(RNG_RNG); - return RNG_RNG.getDeployedPath().toFile().toURI().toString(); + Map schema = new HashMap<>(); + schema.put(IExternalGrammarLocationProvider.NO_NAMESPACE_SCHEMA_LOCATION, + RNG_RNG.getDeployedPath().toFile().toURI().toString()); + return schema; } catch (IOException e) { // do nothing } diff --git a/org.eclipse.lemminx/src/main/resources/schemas/rng/relaxng.rng b/org.eclipse.lemminx/src/main/resources/schemas/rng/relaxng.rng deleted file mode 100644 index 5b16d1287..000000000 --- a/org.eclipse.lemminx/src/main/resources/schemas/rng/relaxng.rng +++ /dev/null @@ -1,330 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - choice - interleave - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file From 71e31285924c2699df622527e957b7255e3d8ee2 Mon Sep 17 00:00:00 2001 From: David Thompson Date: Fri, 16 Sep 2022 15:15:08 -0400 Subject: [PATCH 12/15] WIP fix NPE Signed-off-by: David Thompson --- .../rng/RNGURIResolverExtension.java | 19 ++++++++++++------- .../org/eclipse/lemminx/utils/DOMUtils.java | 2 +- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/rng/RNGURIResolverExtension.java b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/rng/RNGURIResolverExtension.java index 107012c2a..6399ef105 100644 --- a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/rng/RNGURIResolverExtension.java +++ b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/rng/RNGURIResolverExtension.java @@ -43,23 +43,28 @@ public String getName() { @Override public Map getExternalGrammarLocation(URI fileURI) { - return resolve(fileURI.toString()); + String schemaUri = resolve(fileURI.toString()); + if (schemaUri == null) { + return null; + } + + Map schemaMap = new HashMap<>(); + schemaMap.put(IExternalGrammarLocationProvider.NO_NAMESPACE_SCHEMA_LOCATION, + schemaUri); + return schemaMap; } @Override public String resolve(String baseLocation, String publicId, String systemId) { - return resolve(baseLocation).get(IExternalGrammarLocationProvider.NO_NAMESPACE_SCHEMA_LOCATION); + return resolve(baseLocation); } - public Map resolve(String uri) { + private String resolve(String uri) { if (DOMUtils.isRNG(uri)) { try { // XXX: I think this triggers the download, but confirm if this is needed CacheResourcesManager.getResourceCachePath(RNG_RNG); - Map schema = new HashMap<>(); - schema.put(IExternalGrammarLocationProvider.NO_NAMESPACE_SCHEMA_LOCATION, - RNG_RNG.getDeployedPath().toFile().toURI().toString()); - return schema; + return RNG_RNG.getDeployedPath().toFile().toURI().toString(); } catch (IOException e) { // do nothing } diff --git a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/utils/DOMUtils.java b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/utils/DOMUtils.java index f360bf680..394a40f3c 100644 --- a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/utils/DOMUtils.java +++ b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/utils/DOMUtils.java @@ -165,6 +165,6 @@ public static SAXParserFactory newSAXParserFactory() * @return true if the given uri points to a .rng file (XML syntax only) */ public static boolean isRNG(String uri) { - return uri.endsWith(".rng"); + return uri != null && uri.endsWith(".rng"); } } From daf5a1bb9b0be132bd2a838e36a77a0ac0616e1f Mon Sep 17 00:00:00 2001 From: David Thompson Date: Fri, 16 Sep 2022 17:03:28 -0400 Subject: [PATCH 13/15] WIP add unit tests Signed-off-by: David Thompson --- .../participants/RNGErrorCode.java | 4 + .../rng/RNGURIResolverExtension.java | 9 +- .../xmlmodel/XMLModelRelaxNGValidator.java | 2 +- .../validation/RelaxNGValidationTest.java | 119 ++++++++++++++++ .../extensions/rng/RNGUriResolverTest.java | 130 ++++++++++++++++++ .../src/test/resources/rng/broken.rng | 1 + .../src/test/resources/rng/dressSize.rng | 27 ++++ 7 files changed, 287 insertions(+), 5 deletions(-) create mode 100644 org.eclipse.lemminx/src/test/java/org/eclipse/lemminx/extensions/contentmodel/validation/RelaxNGValidationTest.java create mode 100644 org.eclipse.lemminx/src/test/java/org/eclipse/lemminx/extensions/rng/RNGUriResolverTest.java create mode 100644 org.eclipse.lemminx/src/test/resources/rng/broken.rng create mode 100644 org.eclipse.lemminx/src/test/resources/rng/dressSize.rng diff --git a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/contentmodel/participants/RNGErrorCode.java b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/contentmodel/participants/RNGErrorCode.java index 77fd5a966..0d55d68ad 100644 --- a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/contentmodel/participants/RNGErrorCode.java +++ b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/contentmodel/participants/RNGErrorCode.java @@ -34,6 +34,7 @@ public enum RNGErrorCode implements IXMLErrorCode { IncompleteContentModel, BadTagName, BadAttribute, + BadText, MissingAttribute, InvalidRelaxNG; @@ -84,6 +85,9 @@ public static Range toLSPRange(XMLLocator location, RNGErrorCode code, String me String attrName = m.group(1); return XMLPositionUtility.selectAttributeNameFromGivenNameAt(attrName, offset, document); } + case BadText: { + return XMLPositionUtility.selectContent(offset, document); + } case InvalidRelaxNG: { for (XMLModel xmlModel : document.getXMLModels()) { if (message.contains(xmlModel.getHref())) { diff --git a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/rng/RNGURIResolverExtension.java b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/rng/RNGURIResolverExtension.java index 6399ef105..9dd320b4e 100644 --- a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/rng/RNGURIResolverExtension.java +++ b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/rng/RNGURIResolverExtension.java @@ -30,9 +30,11 @@ */ public class RNGURIResolverExtension implements URIResolverExtension, IExternalGrammarLocationProvider { - private static final ResourceToDeploy RNG_RNG = new ResourceToDeploy("http://relaxng.org/relaxng.xsd", + private static final ResourceToDeploy RNG_XSD = new ResourceToDeploy("http://relaxng.org/relaxng.xsd", "schemas/rng/relaxng.xsd"); + // private static final String RELAXNG_NAMESPACE = "http://relaxng.org/ns/structure/1.0"; + public RNGURIResolverExtension(IXMLDocumentProvider documentProvider) { } @@ -62,9 +64,8 @@ public String resolve(String baseLocation, String publicId, String systemId) { private String resolve(String uri) { if (DOMUtils.isRNG(uri)) { try { - // XXX: I think this triggers the download, but confirm if this is needed - CacheResourcesManager.getResourceCachePath(RNG_RNG); - return RNG_RNG.getDeployedPath().toFile().toURI().toString(); + CacheResourcesManager.getResourceCachePath(RNG_XSD); + return RNG_XSD.getDeployedPath().toFile().toURI().toString(); } catch (IOException e) { // do nothing } diff --git a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xerces/xmlmodel/XMLModelRelaxNGValidator.java b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xerces/xmlmodel/XMLModelRelaxNGValidator.java index 2428c3aa8..14cbe346d 100644 --- a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xerces/xmlmodel/XMLModelRelaxNGValidator.java +++ b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xerces/xmlmodel/XMLModelRelaxNGValidator.java @@ -247,7 +247,7 @@ public void setDocumentHandler(XMLDocumentHandler handler) { @Override public XMLDocumentHandler getDocumentHandler() { - return this; // TODO: ?? + return this; } @Override diff --git a/org.eclipse.lemminx/src/test/java/org/eclipse/lemminx/extensions/contentmodel/validation/RelaxNGValidationTest.java b/org.eclipse.lemminx/src/test/java/org/eclipse/lemminx/extensions/contentmodel/validation/RelaxNGValidationTest.java new file mode 100644 index 000000000..8322a34ba --- /dev/null +++ b/org.eclipse.lemminx/src/test/java/org/eclipse/lemminx/extensions/contentmodel/validation/RelaxNGValidationTest.java @@ -0,0 +1,119 @@ +/******************************************************************************* +* Copyright (c) 2022 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.validation; + +import org.eclipse.lemminx.extensions.contentmodel.participants.RNGErrorCode; +import org.junit.jupiter.api.Test; +import static org.eclipse.lemminx.XMLAssert.d; +import static org.eclipse.lemminx.XMLAssert.testDiagnosticsFor; + +/** + * Test validating XML files against RelaxNG schemas + * + * @author datho7561 + */ +public class RelaxNGValidationTest { + + @Test + public void relaxNGWithBrokenRNG() throws Exception { + String xml = " \r\n" + // + "\r\n" + // + ""; + testDiagnosticsFor(xml, d(1, 17, 52, RNGErrorCode.InvalidRelaxNG)); + } + + @Test + public void relaxNGWithMissingAttributeValue() throws Exception { + String xml = " \r\n" + // + "\r\n" + // + ""; + testDiagnosticsFor(xml, d(2, 7, 11, RNGErrorCode.BadAttribute), + d(2, 23, 23, RNGErrorCode.IncompleteContentModel)); + } + + @Test + public void relaxNGWithBadAttributeValue() throws Exception { + String xml = " \r\n" + // + "\r\n" + // + ""; + testDiagnosticsFor(xml, d(2, 7, 11, RNGErrorCode.BadAttribute), + d(2, 31, 31, RNGErrorCode.IncompleteContentModel)); + } + + @Test + public void relaxNGWithUndefinedAttribute() throws Exception { + String xml = " \r\n" + // + "\r\n" + // + ""; + testDiagnosticsFor(xml, d(2, 20, 24, RNGErrorCode.BadAttribute), + d(2, 36, 36, RNGErrorCode.IncompleteContentModel)); + } + + @Test + public void relaxNGWithUndefinedElement() throws Exception { + String xml = " \r\n" + // + "\r\n" + // + ""; + testDiagnosticsFor(xml, d(2, 21,25, RNGErrorCode.BadTagName)); + } + + @Test + public void relaxNGWithInvalidElementContent() throws Exception { + String xml = " \r\n" + // + "\r\n" + // + "pant"; + testDiagnosticsFor(xml, d(2, 20,24, RNGErrorCode.BadText)); + } + + @Test + public void relaxNGElementTextContentDoesntMatchType() throws Exception { + String xml = " \r\n" + // + "\r\n" + // + "pant"; + // FIXME: only the innermost error should be reported + testDiagnosticsFor(xml, d(2, 13,17, RNGErrorCode.BadText), + d(2, 7, 24, RNGErrorCode.BadText)); + } + + @Test + public void relaxNGWithValidContent1() throws Exception { + String xml = " \r\n" + // + "\r\n" + // + ""; + testDiagnosticsFor(xml); + } + + @Test + public void relaxNGWithValidContent2() throws Exception { + String xml = " \r\n" + // + "\r\n" + // + ""; + testDiagnosticsFor(xml); + } + + @Test + public void relaxNGWithValidContent3() throws Exception { + String xml = " \r\n" + // + "\r\n" + // + "medium"; + testDiagnosticsFor(xml); + } + + @Test + public void relaxNGWithValidContent4() throws Exception { + String xml = " \r\n" + // + "\r\n" + // + "9000000"; + testDiagnosticsFor(xml); + } + +} diff --git a/org.eclipse.lemminx/src/test/java/org/eclipse/lemminx/extensions/rng/RNGUriResolverTest.java b/org.eclipse.lemminx/src/test/java/org/eclipse/lemminx/extensions/rng/RNGUriResolverTest.java new file mode 100644 index 000000000..38aa85498 --- /dev/null +++ b/org.eclipse.lemminx/src/test/java/org/eclipse/lemminx/extensions/rng/RNGUriResolverTest.java @@ -0,0 +1,130 @@ +/******************************************************************************* +* Copyright (c) 2022 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 +* +* Contributors: +* Red Hat Inc. - initial API and implementation +*******************************************************************************/ +package org.eclipse.lemminx.extensions.rng; + +import static org.eclipse.lemminx.XMLAssert.pd; +import static org.eclipse.lemminx.XMLAssert.r; + +import org.eclipse.lemminx.AbstractCacheBasedTest; +import org.eclipse.lemminx.XMLAssert; +import org.eclipse.lemminx.extensions.contentmodel.model.ContentModelManager; +import org.eclipse.lemminx.extensions.contentmodel.participants.XMLSchemaErrorCode; +import org.eclipse.lemminx.extensions.contentmodel.settings.XMLValidationRootSettings; +import org.eclipse.lemminx.services.XMLLanguageService; +import org.eclipse.lsp4j.Diagnostic; +import org.eclipse.lsp4j.DiagnosticSeverity; +import org.junit.jupiter.api.Test; + +/** + * Tests to make sure that *.rng associates with relaxng.xsd properly + * + * @author datho7561 + */ +public class RNGUriResolverTest extends AbstractCacheBasedTest { + + @Test + public void testValidatesRNGWithBadElement() throws Exception { + + XMLValidationRootSettings validation = new XMLValidationRootSettings(); + validation.setResolveExternalEntities(true); + + XMLLanguageService ls = new XMLLanguageService(); + ls.initializeIfNeeded(); + // Disable download + ContentModelManager contentModelManager = ls.getComponent(ContentModelManager.class); + contentModelManager.setDownloadExternalResources(false); + + String xsd = ""; + + String fileURI = "test.rng"; + Diagnostic d = new Diagnostic(r(0, 1, 0, 5), "cvc-elt.1.a: Cannot find the declaration of element 'asdf'.", + DiagnosticSeverity.Error, "xml", XMLSchemaErrorCode.cvc_elt_1_a.getCode()); + + XMLAssert.testPublishDiagnosticsFor(xsd, fileURI, validation, ls, pd(fileURI, d)); + } + + @Test + public void testValidatesRNGWithMissingNamespace() throws Exception { + + XMLValidationRootSettings validation = new XMLValidationRootSettings(); + validation.setResolveExternalEntities(true); + + XMLLanguageService ls = new XMLLanguageService(); + ls.initializeIfNeeded(); + // Disable download + ContentModelManager contentModelManager = ls.getComponent(ContentModelManager.class); + contentModelManager.setDownloadExternalResources(false); + + String xsd = ""; + + String fileURI = "test.rng"; + Diagnostic d1 = new Diagnostic(r(0, 1, 0, 8), + "TargetNamespace.2: Expecting no namespace, but the schema document has a target namespace of 'http://relaxng.org/ns/structure/1.0'.", + DiagnosticSeverity.Error, "xml", XMLSchemaErrorCode.TargetNamespace_2.getCode()); + + Diagnostic d2 = new Diagnostic(r(0, 1, 0, 8), "cvc-elt.1.a: Cannot find the declaration of element 'grammar'.", + DiagnosticSeverity.Error, "xml", XMLSchemaErrorCode.cvc_elt_1_a.getCode()); + + XMLAssert.testPublishDiagnosticsFor(xsd, fileURI, validation, ls, pd(fileURI, d1, d2)); + } + + @Test + public void testValidatesRNGThatsValid() throws Exception { + + XMLValidationRootSettings validation = new XMLValidationRootSettings(); + validation.setResolveExternalEntities(true); + + XMLLanguageService ls = new XMLLanguageService(); + ls.initializeIfNeeded(); + // Disable download + ContentModelManager contentModelManager = ls.getComponent(ContentModelManager.class); + contentModelManager.setDownloadExternalResources(false); + + String xsd = ""; + + String fileURI = "test.rng"; + + XMLAssert.testPublishDiagnosticsFor(xsd, fileURI, validation, ls, pd(fileURI)); + } + + @Test + public void testValidatesRNGThatsValidWithNamespaceInPrefix() throws Exception { + + XMLValidationRootSettings validation = new XMLValidationRootSettings(); + validation.setResolveExternalEntities(true); + + XMLLanguageService ls = new XMLLanguageService(); + ls.initializeIfNeeded(); + // Disable download + ContentModelManager contentModelManager = ls.getComponent(ContentModelManager.class); + contentModelManager.setDownloadExternalResources(false); + + // FIXME: namespace is not handled correctly + + // https://relaxng.org/tutorial-20011203.html + String xsd = "\n" + // + "" + // + "\n" + // + "\n" + // + "\n" + // + "\n" + // + "\n" + // + "\n" + // + "\n" + // + "\n" + // + "\n" + // + "\n"; + + String fileURI = "test.rng"; + + XMLAssert.testPublishDiagnosticsFor(xsd, fileURI, validation, ls, pd(fileURI)); + } + +} diff --git a/org.eclipse.lemminx/src/test/resources/rng/broken.rng b/org.eclipse.lemminx/src/test/resources/rng/broken.rng new file mode 100644 index 000000000..b2ed3ad6a --- /dev/null +++ b/org.eclipse.lemminx/src/test/resources/rng/broken.rng @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/org.eclipse.lemminx/src/test/resources/rng/dressSize.rng b/org.eclipse.lemminx/src/test/resources/rng/dressSize.rng new file mode 100644 index 000000000..0977e93ec --- /dev/null +++ b/org.eclipse.lemminx/src/test/resources/rng/dressSize.rng @@ -0,0 +1,27 @@ + + + + + + small + medium + large + x-large + + + + + + + + + + + + + + + + \ No newline at end of file From 7afeae3ce7b8e7f2e82dd15eb2c080f23b834c7a Mon Sep 17 00:00:00 2001 From: David Thompson Date: Fri, 23 Sep 2022 12:05:24 -0400 Subject: [PATCH 14/15] WIP put rng parsing exception into "invalid rng" diagnostic Signed-off-by: David Thompson --- .../eclipse/lemminx/extensions/xerces/RNGMessageFormatter.java | 2 +- .../extensions/xerces/xmlmodel/XMLModelRelaxNGValidator.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xerces/RNGMessageFormatter.java b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xerces/RNGMessageFormatter.java index aa7678315..61c1d02e9 100644 --- a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xerces/RNGMessageFormatter.java +++ b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xerces/RNGMessageFormatter.java @@ -27,7 +27,7 @@ public class RNGMessageFormatter implements MessageFormatter { public static final String RNG_DOMAIN = "https://relaxng.org"; - private static final String INVALID_RELAXNG_MESSAGE_TEMPLATE = "The RelaxNG schema {0} is invalid"; + private static final String INVALID_RELAXNG_MESSAGE_TEMPLATE = "The RelaxNG schema {0} is invalid: {1}"; @Override public String formatMessage(Locale locale, String key, Object[] arguments) throws MissingResourceException { diff --git a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xerces/xmlmodel/XMLModelRelaxNGValidator.java b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xerces/xmlmodel/XMLModelRelaxNGValidator.java index 14cbe346d..58188cdb7 100644 --- a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xerces/xmlmodel/XMLModelRelaxNGValidator.java +++ b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xerces/xmlmodel/XMLModelRelaxNGValidator.java @@ -70,7 +70,7 @@ private void createVerifier() throws SAXException { interceptor.setContentHandler(verifierHandler); interceptor.startDocument(); } catch (VerifierConfigurationException vce) { - errorReporter.reportError("https://relaxng.org", RNGErrorCode.InvalidRelaxNG.getCode(), new Object[] { href }, + errorReporter.reportError("https://relaxng.org", RNGErrorCode.InvalidRelaxNG.getCode(), new Object[] { href, vce }, XMLErrorReporter.SEVERITY_FATAL_ERROR); } catch (IOException e) { LOGGER.log(Level.SEVERE, "Failed to create RelaxNG validator: ", e); From 67a77c7925e93cbb4f8e824f5087028cd9d7e519 Mon Sep 17 00:00:00 2001 From: David Thompson Date: Fri, 23 Sep 2022 15:12:16 -0400 Subject: [PATCH 15/15] WIP use "RelaxNG" consistently (instead of RNG sometimes) Signed-off-by: David Thompson --- .../model/ContentModelProvider.java | 23 +-- ...NGErrorCode.java => RelaxNGErrorCode.java} | 14 +- .../diagnostics/LSPErrorReporterForXML.java | 10 +- .../CMRelaxNGAttributeDeclaration.java | 68 +++++++ .../CMRelaxNGContentModelProvider.java | 73 +++++++ .../extensions/relaxng/CMRelaxNGDocument.java | 130 ++++++++++++ .../relaxng/CMRelaxNGElementDeclaration.java | 187 ++++++++++++++++++ .../extensions/relaxng/RelaxNGConstants.java | 24 +++ .../RelaxNGPlugin.java} | 15 +- .../RelaxNGURIResolverExtension.java} | 20 +- .../xerces/AbstractLSPErrorReporter.java | 2 +- ...tter.java => RelaxNGMessageFormatter.java} | 8 +- .../xmlmodel/XMLModelRelaxNGValidator.java | 4 +- .../org/eclipse/lemminx/utils/DOMUtils.java | 2 +- ....lemminx.services.extensions.IXMLExtension | 2 +- .../schemas/{rng => relaxng}/relaxng.xsd | 0 .../validation/RelaxNGValidationTest.java | 26 +-- .../RelaxNGUriResolverTest.java} | 12 +- 18 files changed, 550 insertions(+), 70 deletions(-) rename org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/contentmodel/participants/{RNGErrorCode.java => RelaxNGErrorCode.java} (86%) create mode 100644 org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/relaxng/CMRelaxNGAttributeDeclaration.java create mode 100644 org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/relaxng/CMRelaxNGContentModelProvider.java create mode 100644 org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/relaxng/CMRelaxNGDocument.java create mode 100644 org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/relaxng/CMRelaxNGElementDeclaration.java create mode 100644 org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/relaxng/RelaxNGConstants.java rename org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/{rng/RNGPlugin.java => relaxng/RelaxNGPlugin.java} (76%) rename org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/{rng/RNGURIResolverExtension.java => relaxng/RelaxNGURIResolverExtension.java} (73%) rename org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xerces/{RNGMessageFormatter.java => RelaxNGMessageFormatter.java} (86%) rename org.eclipse.lemminx/src/main/resources/schemas/{rng => relaxng}/relaxng.xsd (100%) rename org.eclipse.lemminx/src/test/java/org/eclipse/lemminx/extensions/{rng/RNGUriResolverTest.java => relaxng/RelaxNGUriResolverTest.java} (91%) 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 9fec16ca5..ebf20d854 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 @@ -59,26 +59,21 @@ public String getKind() { } /** - * Returns the content model provider by using standard association - * (xsi:schemaLocation, xsi:noNamespaceSchemaLocation, doctype) and null - * otherwise. - * + * Returns true if the given document can be adapted for this content model + * and false otherwise. + * * @param document the DOM document. * @param internal true if it is an internal content model (ex : DOCCTYPE * subset) and false otherwise. - * - * @return the content model provider by using standard association - * (xsi:schemaLocation, xsi:noNamespaceSchemaLocation, doctype) and null - * otherwise. */ boolean adaptFor(DOMDocument document, boolean internal); /** * Returns true if the given resource uri can be adapted for this content model * and false otherwise. - * + * * o@param uri the resource Uri. - * + * * @return true if the given resource uri can be adapted for this content model * and false otherwise. */ @@ -86,10 +81,10 @@ public String getKind() { /** * Returns the identifiers list from the given document and namespace. - * + * * @param xmlDocument the DOM document. * @param namespaceURI the namespace. - * + * * @return the identifiers list from the given document and namespace. */ Collection getIdentifiers(DOMDocument xmlDocument, String namespaceURI); @@ -97,7 +92,7 @@ public String getKind() { /** * Create content model document (XSD, DTD, etc) from the given resource key and * null otherwise. - * + * * @param key the resource key. * @param resolveExternalEntities true if external entities can be resolved and * false otherwise. @@ -109,7 +104,7 @@ public String getKind() { /** * Create the internal content model (for DOCTYPE subset) from the given DOM * document. - * + * * @param xmlDocument the DOM document. * @param resolveExternalEntities true if external entities can be resolved and * false otherwise. diff --git a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/contentmodel/participants/RNGErrorCode.java b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/contentmodel/participants/RelaxNGErrorCode.java similarity index 86% rename from org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/contentmodel/participants/RNGErrorCode.java rename to org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/contentmodel/participants/RelaxNGErrorCode.java index 0d55d68ad..c4ee0cfc4 100644 --- a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/contentmodel/participants/RNGErrorCode.java +++ b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/contentmodel/participants/RelaxNGErrorCode.java @@ -29,7 +29,7 @@ * * @author datho7561 */ -public enum RNGErrorCode implements IXMLErrorCode { +public enum RelaxNGErrorCode implements IXMLErrorCode { IncompleteContentModel, BadTagName, @@ -39,24 +39,24 @@ public enum RNGErrorCode implements IXMLErrorCode { InvalidRelaxNG; private final String code; - private final static Map codes; + private final static Map codes; static { codes = new HashMap<>(); - for (RNGErrorCode errorCode : values()) { + for (RelaxNGErrorCode errorCode : values()) { codes.put(errorCode.getCode(), errorCode); } } - private RNGErrorCode() { + private RelaxNGErrorCode() { this(null); } - private RNGErrorCode(String code) { + private RelaxNGErrorCode(String code) { this.code = code; } - public static RNGErrorCode get(String name) { + public static RelaxNGErrorCode get(String name) { return codes.get(name); } @@ -72,7 +72,7 @@ public String getCode() { private static final Pattern BAD_ATTRIBUTE_ATTRIBUTE_EXTRACTOR = Pattern.compile("[^\"]+\"([^\"]*)\""); - public static Range toLSPRange(XMLLocator location, RNGErrorCode code, String message, Object[] arguments, + public static Range toLSPRange(XMLLocator location, RelaxNGErrorCode code, String message, Object[] arguments, DOMDocument document) { int offset = location.getCharacterOffset() - 1; switch (code) { diff --git a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/contentmodel/participants/diagnostics/LSPErrorReporterForXML.java b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/contentmodel/participants/diagnostics/LSPErrorReporterForXML.java index 383077c13..d0165db89 100644 --- a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/contentmodel/participants/diagnostics/LSPErrorReporterForXML.java +++ b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/contentmodel/participants/diagnostics/LSPErrorReporterForXML.java @@ -22,7 +22,7 @@ import org.eclipse.lemminx.extensions.contentmodel.model.ContentModelManager; import org.eclipse.lemminx.extensions.contentmodel.model.ReferencedGrammarInfo; import org.eclipse.lemminx.extensions.contentmodel.participants.DTDErrorCode; -import org.eclipse.lemminx.extensions.contentmodel.participants.RNGErrorCode; +import org.eclipse.lemminx.extensions.contentmodel.participants.RelaxNGErrorCode; import org.eclipse.lemminx.extensions.contentmodel.participants.XMLSchemaErrorCode; import org.eclipse.lemminx.extensions.contentmodel.participants.XMLSyntaxErrorCode; import org.eclipse.lemminx.extensions.xerces.AbstractReferencedGrammarLSPErrorReporter; @@ -103,15 +103,15 @@ protected Range toLSPRange(XMLLocator location, String key, Object[] arguments, documentOrGrammarURI); return NO_RANGE; } else { - RNGErrorCode rngCode = RNGErrorCode.get(key); - if (rngCode != null) { + RelaxNGErrorCode relaxNGCode = RelaxNGErrorCode.get(key); + if (relaxNGCode != null) { if (errorForDocument) { - Range range = RNGErrorCode.toLSPRange(location, rngCode, message, arguments, document); + Range range = RelaxNGErrorCode.toLSPRange(location, relaxNGCode, message, arguments, document); if (range != null) { return range; } } else { - // TODO: setup reporting errors on referenced RNG files + // TODO: setup reporting errors on referenced .rng files } } } diff --git a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/relaxng/CMRelaxNGAttributeDeclaration.java b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/relaxng/CMRelaxNGAttributeDeclaration.java new file mode 100644 index 000000000..652b625f6 --- /dev/null +++ b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/relaxng/CMRelaxNGAttributeDeclaration.java @@ -0,0 +1,68 @@ +package org.eclipse.lemminx.extensions.relaxng; + +import java.util.Collection; +import java.util.Collections; + +import org.eclipse.lemminx.extensions.contentmodel.model.CMAttributeDeclaration; +import org.eclipse.lemminx.services.extensions.ISharedSettingsRequest; + +import com.sun.msv.grammar.AttributeExp; +import com.sun.msv.grammar.SimpleNameClass; + +public class CMRelaxNGAttributeDeclaration implements CMAttributeDeclaration { + + private final AttributeExp exp; + + public CMRelaxNGAttributeDeclaration(AttributeExp exp) { + this.exp = exp; + } + + @Override + public String getName() { + if (!(exp.getNameClass() instanceof SimpleNameClass)) { + throw new RuntimeException("Cannot get the name of the element for the given RelaxNG element declaration"); + } + SimpleNameClass simpleNameClass = (SimpleNameClass) exp.getNameClass(); + return simpleNameClass.localName; + } + + @Override + public String getNamespace() { + if (!(exp.getNameClass() instanceof SimpleNameClass)) { + throw new RuntimeException("Cannot get the namespace of the element for the given RelaxNG element declaration"); + } + SimpleNameClass simpleNameClass = (SimpleNameClass) exp.getNameClass(); + return simpleNameClass.namespaceURI; + } + + @Override + public String getDefaultValue() { + // TODO Auto-generated method stub + return null; + } + + @Override + public Collection getEnumerationValues() { + // TODO fix + return Collections.emptyList(); + } + + @Override + public String getAttributeNameDocumentation(ISharedSettingsRequest request) { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getAttributeValueDocumentation(String value, ISharedSettingsRequest request) { + // TODO Auto-generated method stub + return null; + } + + @Override + public boolean isRequired() { + // TODO Auto-generated method stub + return false; + } + +} diff --git a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/relaxng/CMRelaxNGContentModelProvider.java b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/relaxng/CMRelaxNGContentModelProvider.java new file mode 100644 index 000000000..f52b38129 --- /dev/null +++ b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/relaxng/CMRelaxNGContentModelProvider.java @@ -0,0 +1,73 @@ +/******************************************************************************* +* Copyright (c) 2022 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 +* +* Contributors: +* Red Hat Inc. - initial API and implementation +*******************************************************************************/ +package org.eclipse.lemminx.extensions.relaxng; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; + +import org.eclipse.lemminx.dom.DOMDocument; +import org.eclipse.lemminx.dom.XMLModel; +import org.eclipse.lemminx.extensions.contentmodel.model.CMDocument; +import org.eclipse.lemminx.extensions.contentmodel.model.ContentModelProvider; +import org.eclipse.lemminx.utils.DOMUtils; +import org.eclipse.lemminx.utils.StringUtils; + +public class CMRelaxNGContentModelProvider implements ContentModelProvider { + + // TODO: should this be different for RelaxNG? + private static final String XML_MODEL_BINDING_KIND = "xml-model"; + + @Override + public boolean adaptFor(DOMDocument document, boolean internal) { + if (internal) { + return false; + } + return document.getXMLModels().stream().anyMatch(xmlModel -> DOMUtils.isRelaxNG(xmlModel.getHref())); + } + + @Override + public boolean adaptFor(String uri) { + return false; + } + + @Override + public Collection getIdentifiers(DOMDocument xmlDocument, String namespaceURI) { + List xmlModels = xmlDocument.getXMLModels(); + if (xmlModels.isEmpty()) { + return Collections.emptyList(); + } + Collection identifiers = new ArrayList<>(); + for (XMLModel xmlModel : xmlModels) { + String href = xmlModel.getHref(); + if (!StringUtils.isEmpty(href) && DOMUtils.isRelaxNG(href)) { + identifiers.add(new Identifier(null, href, xmlModel.getHrefNode(), XML_MODEL_BINDING_KIND)); + } + } + return identifiers; + } + + @Override + public CMDocument createCMDocument(String key, boolean resolveExternalEntities) { + try { + return new CMRelaxNGDocument(key); + } catch (Exception e) { + return null; + } + } + + @Override + public CMDocument createInternalCMDocument(DOMDocument xmlDocument, boolean resolveExternalEntities) { + // Not relevant for RelaxNG schemas, only works for .dtd + return null; + } + +} diff --git a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/relaxng/CMRelaxNGDocument.java b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/relaxng/CMRelaxNGDocument.java new file mode 100644 index 000000000..a40e356e0 --- /dev/null +++ b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/relaxng/CMRelaxNGDocument.java @@ -0,0 +1,130 @@ +/******************************************************************************* +* Copyright (c) 2022 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 +* +* Contributors: +* Red Hat Inc. - initial API and implementation +*******************************************************************************/ +package org.eclipse.lemminx.extensions.relaxng; + +import static org.eclipse.lemminx.extensions.relaxng.RelaxNGConstants.RELAXNG_NAMESPACE; + +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Objects; + +import javax.xml.parsers.ParserConfigurationException; + +import org.eclipse.lemminx.dom.DOMElement; +import org.eclipse.lemminx.dom.DOMNode; +import org.eclipse.lemminx.extensions.contentmodel.model.CMDocument; +import org.eclipse.lemminx.extensions.contentmodel.model.CMElementDeclaration; +import org.eclipse.lemminx.uriresolver.CacheResourcesManager; +import org.eclipse.lemminx.utils.URIUtils; +import org.eclipse.lsp4j.LocationLink; +import org.xml.sax.SAXException; + +import com.sun.msv.grammar.ElementExp; +import com.sun.msv.grammar.Grammar; +import com.sun.msv.grammar.util.ExpressionWalker; +import com.sun.msv.reader.util.GrammarLoader; + +public class CMRelaxNGDocument implements CMDocument { + + private final Grammar grammar; + + private transient List elementDeclarations; + + public CMRelaxNGDocument(String key) throws IOException, SAXException, ParserConfigurationException, URISyntaxException { + if (URIUtils.isFileResource(key) && Files.exists(Paths.get(new URI(key)))) { + grammar = GrammarLoader.loadSchema(key); + } else { + Path path = CacheResourcesManager.getResourceCachePath(key); + grammar = GrammarLoader.loadSchema(path.toUri().toString()); + } + } + + @Override + public boolean hasNamespace(String namespaceURI) { + return RELAXNG_NAMESPACE.equals(namespaceURI); + } + + @Override + public Collection getElements() { + collectElementsIfNeeded(); + return elementDeclarations; + } + + @Override + public CMElementDeclaration findCMElement(DOMElement element, String namespace) { + collectElementsIfNeeded(); + + // copied from XSD support + List paths = new ArrayList<>(); + while (element != null && (namespace == null || namespace.equals(element.getNamespaceURI()))) { + paths.add(0, element); + element = element.getParentNode() instanceof DOMElement ? (DOMElement) element.getParentNode() : null; + } + CMElementDeclaration declaration = null; + for (int i = 0; i < paths.size(); i++) { + DOMElement elt = paths.get(i); + if (i == 0) { + declaration = findElementDeclaration(elt.getLocalName(), namespace); + } else { + declaration = declaration.findCMElement(elt.getLocalName(), namespace); + } + if (declaration == null) { + break; + } + } + return declaration; + } + + private CMElementDeclaration findElementDeclaration(String localName, String namespace) { + for (CMElementDeclaration elementDeclaration : elementDeclarations) { + if (elementDeclaration.getName().equals(localName) + // FIXME: get namespaces working, then uncomment this line + // && Objects.equals(element.getNamespaceURI(), elementDeclaration.getNamespace()) + ) { + return elementDeclaration; + } + } + return null; + } + + @Override + public LocationLink findTypeLocation(DOMNode node) { + // TODO Auto-generated method stub + return null; + } + + @Override + public boolean isDirty() { + // TODO: manage correctly + return true; + } + + private void collectElementsIfNeeded() { + if (elementDeclarations != null) { + return; + } + elementDeclarations = new ArrayList<>(); + grammar.getTopLevel().visit(new ExpressionWalker() { + @Override + public void onElement(ElementExp exp) { + elementDeclarations.add(new CMRelaxNGElementDeclaration(exp)); + // do not recurse + } + }); + } + +} diff --git a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/relaxng/CMRelaxNGElementDeclaration.java b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/relaxng/CMRelaxNGElementDeclaration.java new file mode 100644 index 000000000..d1c940d5b --- /dev/null +++ b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/relaxng/CMRelaxNGElementDeclaration.java @@ -0,0 +1,187 @@ +package org.eclipse.lemminx.extensions.relaxng; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Objects; +import java.util.logging.Logger; + +import org.eclipse.lemminx.dom.DOMElement; +import org.eclipse.lemminx.extensions.contentmodel.model.CMAttributeDeclaration; +import org.eclipse.lemminx.extensions.contentmodel.model.CMElementDeclaration; +import org.eclipse.lemminx.services.extensions.ISharedSettingsRequest; + +import com.sun.msv.grammar.ElementExp; +import com.sun.msv.grammar.AttributeExp; +import com.sun.msv.grammar.SimpleNameClass; +import com.sun.msv.grammar.util.ExpressionWalker; + +public class CMRelaxNGElementDeclaration implements CMElementDeclaration { + + private static final Logger LOGGER = Logger.getLogger(CMRelaxNGElementDeclaration.class.getName()); + + private final ElementExp exp; + private List childElementDeclarations; + private transient List attributeDeclarations; + + public CMRelaxNGElementDeclaration(ElementExp exp) { + this.exp = exp; + } + + @Override + public String getName() { + if (!(exp.getNameClass() instanceof SimpleNameClass)) { + throw new RuntimeException("Cannot get the name of the element for the given RelaxNG element declaration"); + } + SimpleNameClass simpleNameClass = (SimpleNameClass) exp.getNameClass(); + return simpleNameClass.localName; + } + + @Override + public String getNamespace() { + if (!(exp.getNameClass() instanceof SimpleNameClass)) { + throw new RuntimeException("Cannot get the namespace of the element for the given RelaxNG element declaration"); + } + SimpleNameClass simpleNameClass = (SimpleNameClass) exp.getNameClass(); + return simpleNameClass.namespaceURI; + } + + @Override + public Collection getElements() { + collectChildElementsIfNeeded(); + return childElementDeclarations; + } + + @Override + public Collection getPossibleElements(DOMElement parentElement, int offset) { + collectChildElementsIfNeeded(); + return childElementDeclarations; + } + + @Override + public CMElementDeclaration findCMElement(String tag, String namespace) { + collectChildElementsIfNeeded(); + for (CMElementDeclaration elementDeclaration: childElementDeclarations) { + if (Objects.equals(elementDeclaration.getName(), tag) + // TODO: uncomment once namespaces are supported properly + // && Objects.equals(elementDeclaration.getNamespace(), namespace) + ) { + return elementDeclaration; + } + } + return null; + } + + private void collectChildElementsIfNeeded() { + if (childElementDeclarations != null) { + return; + } + childElementDeclarations = new ArrayList<>(); + exp.visit(new ExpressionWalker() { + + boolean hasVisitedParent = false; + @Override + public void onElement(ElementExp exp) { + if (!hasVisitedParent) { + // this is the current element + hasVisitedParent = true; + super.onElement(exp); + } else { + // do not recurse into grandchild elements + childElementDeclarations.add(new CMRelaxNGElementDeclaration(exp)); + } + } + }); + } + + @Override + public Collection getAttributes() { + collectAttributesIfNeeded(); + return attributeDeclarations; + } + + @Override + public CMAttributeDeclaration findCMAttribute(String attributeName) { + collectAttributesIfNeeded(); + for (CMAttributeDeclaration attributeDeclaration : attributeDeclarations) { + if (Objects.equals(attributeDeclaration.getName(), attributeName)) { + return attributeDeclaration; + } + } + return null; + } + + private void collectAttributesIfNeeded() { + if (attributeDeclarations != null) { + return; + } + attributeDeclarations = new ArrayList<>(); + exp.visit(new ExpressionWalker() { + + boolean visitedCurrentElement = false; + + @Override + public void onElement(ElementExp exp) { + if (!visitedCurrentElement) { + visitedCurrentElement = false; + super.onElement(exp); + } + } + + @Override + public void onAttribute(AttributeExp exp) { + attributeDeclarations.add(new CMRelaxNGAttributeDeclaration(exp)); + } + }); + } + + @Override + public String getDocumentation(ISharedSettingsRequest request) { + // TODO Auto-generated method stub + return null; + } + + @Override + public boolean isEmpty() { + // TODO Auto-generated method stub + return false; + } + + @Override + public Collection getEnumerationValues() { + // TODO Implement properly, an NPE is caused if this returns null + return Collections.emptyList(); + } + + @Override + public String getTextDocumentation(String value, ISharedSettingsRequest request) { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getDocumentURI() { + // TODO Auto-generated method stub + return null; + } + + @Override + public boolean isStringType() { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean isMixedContent() { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean isOptional(String childElementName) { + // TODO Auto-generated method stub + return false; + } + +} diff --git a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/relaxng/RelaxNGConstants.java b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/relaxng/RelaxNGConstants.java new file mode 100644 index 000000000..a1cc206f9 --- /dev/null +++ b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/relaxng/RelaxNGConstants.java @@ -0,0 +1,24 @@ +/******************************************************************************* +* Copyright (c) 2022 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 +* +* Contributors: +* Red Hat Inc. - initial API and implementation +*******************************************************************************/ +package org.eclipse.lemminx.extensions.relaxng; + +/** + * Contains constants related to RelaxNG, such as namespaces and document URIs. + * + * @author datho7561 + */ +public class RelaxNGConstants { + private RelaxNGConstants() { + } + + public static final String RELAXNG_NAMESPACE = "http://relaxng.org/ns/structure/1.0"; + public static final String RELAXNG_XSD_URI = "http://relaxng.org/relaxng.xsd"; + +} diff --git a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/rng/RNGPlugin.java b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/relaxng/RelaxNGPlugin.java similarity index 76% rename from org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/rng/RNGPlugin.java rename to org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/relaxng/RelaxNGPlugin.java index d2c7deb4a..59a6fd321 100644 --- a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/rng/RNGPlugin.java +++ b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/relaxng/RelaxNGPlugin.java @@ -9,10 +9,11 @@ * Contributors: * Red Hat Inc. - initial API and implementation *******************************************************************************/ -package org.eclipse.lemminx.extensions.rng; +package org.eclipse.lemminx.extensions.relaxng; import org.eclipse.lemminx.dom.DOMDocument; import org.eclipse.lemminx.extensions.contentmodel.model.ContentModelManager; +import org.eclipse.lemminx.extensions.contentmodel.model.ContentModelProvider; import org.eclipse.lemminx.services.extensions.IXMLExtension; import org.eclipse.lemminx.services.extensions.XMLExtensionsRegistry; import org.eclipse.lemminx.services.extensions.save.ISaveContext; @@ -24,19 +25,19 @@ * * @author datho7561 */ -public class RNGPlugin implements IXMLExtension { +public class RelaxNGPlugin implements IXMLExtension { - private RNGURIResolverExtension uriResolver; + private RelaxNGURIResolverExtension uriResolver; private ContentModelManager contentModelManager; - public RNGPlugin() { + public RelaxNGPlugin() { } @Override public void doSave(ISaveContext context) { String documentURI = context.getUri(); - if (DOMUtils.isRNG(documentURI)) { + if (DOMUtils.isRelaxNG(documentURI)) { context.collectDocumentToValidate(d -> { DOMDocument xml = context.getDocument(d.getDocumentURI()); return contentModelManager.dependsOnGrammar(xml, context.getUri()); @@ -46,9 +47,11 @@ public void doSave(ISaveContext context) { @Override public void start(InitializeParams params, XMLExtensionsRegistry registry) { - uriResolver = new RNGURIResolverExtension(registry.getDocumentProvider()); + uriResolver = new RelaxNGURIResolverExtension(registry.getDocumentProvider()); registry.getResolverExtensionManager().registerResolver(uriResolver); + ContentModelProvider modelProvider = new CMRelaxNGContentModelProvider(); contentModelManager = registry.getComponent(ContentModelManager.class); + contentModelManager.registerModelProvider(modelProvider); } @Override diff --git a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/rng/RNGURIResolverExtension.java b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/relaxng/RelaxNGURIResolverExtension.java similarity index 73% rename from org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/rng/RNGURIResolverExtension.java rename to org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/relaxng/RelaxNGURIResolverExtension.java index 9dd320b4e..a1277535e 100644 --- a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/rng/RNGURIResolverExtension.java +++ b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/relaxng/RelaxNGURIResolverExtension.java @@ -9,7 +9,9 @@ * Contributors: * Red Hat Inc. - initial API and implementation *******************************************************************************/ -package org.eclipse.lemminx.extensions.rng; +package org.eclipse.lemminx.extensions.relaxng; + +import static org.eclipse.lemminx.extensions.relaxng.RelaxNGConstants.RELAXNG_XSD_URI; import java.io.IOException; import java.net.URI; @@ -28,14 +30,12 @@ * * @author datho7561 */ -public class RNGURIResolverExtension implements URIResolverExtension, IExternalGrammarLocationProvider { - - private static final ResourceToDeploy RNG_XSD = new ResourceToDeploy("http://relaxng.org/relaxng.xsd", - "schemas/rng/relaxng.xsd"); +public class RelaxNGURIResolverExtension implements URIResolverExtension, IExternalGrammarLocationProvider { - // private static final String RELAXNG_NAMESPACE = "http://relaxng.org/ns/structure/1.0"; + private static final ResourceToDeploy RELAXNG_XSD = new ResourceToDeploy(RELAXNG_XSD_URI, + "schemas/relaxng/relaxng.xsd"); - public RNGURIResolverExtension(IXMLDocumentProvider documentProvider) { + public RelaxNGURIResolverExtension(IXMLDocumentProvider documentProvider) { } @@ -62,10 +62,10 @@ public String resolve(String baseLocation, String publicId, String systemId) { } private String resolve(String uri) { - if (DOMUtils.isRNG(uri)) { + if (DOMUtils.isRelaxNG(uri)) { try { - CacheResourcesManager.getResourceCachePath(RNG_XSD); - return RNG_XSD.getDeployedPath().toFile().toURI().toString(); + CacheResourcesManager.getResourceCachePath(RELAXNG_XSD); + return RELAXNG_XSD.getDeployedPath().toFile().toURI().toString(); } catch (IOException e) { // do nothing } diff --git a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xerces/AbstractLSPErrorReporter.java b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xerces/AbstractLSPErrorReporter.java index 99cad96a4..e31624a03 100644 --- a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xerces/AbstractLSPErrorReporter.java +++ b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xerces/AbstractLSPErrorReporter.java @@ -76,7 +76,7 @@ public AbstractLSPErrorReporter(String source, DOMDocument xmlDocument, List \r\n" + // "\r\n" + // ""; - testDiagnosticsFor(xml, d(1, 17, 52, RNGErrorCode.InvalidRelaxNG)); + testDiagnosticsFor(xml, d(1, 17, 52, RelaxNGErrorCode.InvalidRelaxNG)); } @Test @@ -36,8 +36,8 @@ public void relaxNGWithMissingAttributeValue() throws Exception { String xml = " \r\n" + // "\r\n" + // ""; - testDiagnosticsFor(xml, d(2, 7, 11, RNGErrorCode.BadAttribute), - d(2, 23, 23, RNGErrorCode.IncompleteContentModel)); + testDiagnosticsFor(xml, d(2, 7, 11, RelaxNGErrorCode.BadAttribute), + d(2, 23, 23, RelaxNGErrorCode.IncompleteContentModel)); } @Test @@ -45,8 +45,8 @@ public void relaxNGWithBadAttributeValue() throws Exception { String xml = " \r\n" + // "\r\n" + // ""; - testDiagnosticsFor(xml, d(2, 7, 11, RNGErrorCode.BadAttribute), - d(2, 31, 31, RNGErrorCode.IncompleteContentModel)); + testDiagnosticsFor(xml, d(2, 7, 11, RelaxNGErrorCode.BadAttribute), + d(2, 31, 31, RelaxNGErrorCode.IncompleteContentModel)); } @Test @@ -54,8 +54,8 @@ public void relaxNGWithUndefinedAttribute() throws Exception { String xml = " \r\n" + // "\r\n" + // ""; - testDiagnosticsFor(xml, d(2, 20, 24, RNGErrorCode.BadAttribute), - d(2, 36, 36, RNGErrorCode.IncompleteContentModel)); + testDiagnosticsFor(xml, d(2, 20, 24, RelaxNGErrorCode.BadAttribute), + d(2, 36, 36, RelaxNGErrorCode.IncompleteContentModel)); } @Test @@ -63,7 +63,7 @@ public void relaxNGWithUndefinedElement() throws Exception { String xml = " \r\n" + // "\r\n" + // ""; - testDiagnosticsFor(xml, d(2, 21,25, RNGErrorCode.BadTagName)); + testDiagnosticsFor(xml, d(2, 21,25, RelaxNGErrorCode.BadTagName)); } @Test @@ -71,7 +71,7 @@ public void relaxNGWithInvalidElementContent() throws Exception { String xml = " \r\n" + // "\r\n" + // "pant"; - testDiagnosticsFor(xml, d(2, 20,24, RNGErrorCode.BadText)); + testDiagnosticsFor(xml, d(2, 20,24, RelaxNGErrorCode.BadText)); } @Test @@ -80,8 +80,8 @@ public void relaxNGElementTextContentDoesntMatchType() throws Exception { "\r\n" + // "pant"; // FIXME: only the innermost error should be reported - testDiagnosticsFor(xml, d(2, 13,17, RNGErrorCode.BadText), - d(2, 7, 24, RNGErrorCode.BadText)); + testDiagnosticsFor(xml, d(2, 13,17, RelaxNGErrorCode.BadText), + d(2, 7, 24, RelaxNGErrorCode.BadText)); } @Test diff --git a/org.eclipse.lemminx/src/test/java/org/eclipse/lemminx/extensions/rng/RNGUriResolverTest.java b/org.eclipse.lemminx/src/test/java/org/eclipse/lemminx/extensions/relaxng/RelaxNGUriResolverTest.java similarity index 91% rename from org.eclipse.lemminx/src/test/java/org/eclipse/lemminx/extensions/rng/RNGUriResolverTest.java rename to org.eclipse.lemminx/src/test/java/org/eclipse/lemminx/extensions/relaxng/RelaxNGUriResolverTest.java index 38aa85498..40f7551f6 100644 --- a/org.eclipse.lemminx/src/test/java/org/eclipse/lemminx/extensions/rng/RNGUriResolverTest.java +++ b/org.eclipse.lemminx/src/test/java/org/eclipse/lemminx/extensions/relaxng/RelaxNGUriResolverTest.java @@ -7,7 +7,7 @@ * Contributors: * Red Hat Inc. - initial API and implementation *******************************************************************************/ -package org.eclipse.lemminx.extensions.rng; +package org.eclipse.lemminx.extensions.relaxng; import static org.eclipse.lemminx.XMLAssert.pd; import static org.eclipse.lemminx.XMLAssert.r; @@ -27,10 +27,10 @@ * * @author datho7561 */ -public class RNGUriResolverTest extends AbstractCacheBasedTest { +public class RelaxNGUriResolverTest extends AbstractCacheBasedTest { @Test - public void testValidatesRNGWithBadElement() throws Exception { + public void testValidatesRelaxNGSchemaWithBadElement() throws Exception { XMLValidationRootSettings validation = new XMLValidationRootSettings(); validation.setResolveExternalEntities(true); @@ -51,7 +51,7 @@ public void testValidatesRNGWithBadElement() throws Exception { } @Test - public void testValidatesRNGWithMissingNamespace() throws Exception { + public void testValidatesRelaxNGSchemaWithMissingNamespace() throws Exception { XMLValidationRootSettings validation = new XMLValidationRootSettings(); validation.setResolveExternalEntities(true); @@ -76,7 +76,7 @@ public void testValidatesRNGWithMissingNamespace() throws Exception { } @Test - public void testValidatesRNGThatsValid() throws Exception { + public void testValidatesRelaxNGSchemaThatsValid() throws Exception { XMLValidationRootSettings validation = new XMLValidationRootSettings(); validation.setResolveExternalEntities(true); @@ -95,7 +95,7 @@ public void testValidatesRNGThatsValid() throws Exception { } @Test - public void testValidatesRNGThatsValidWithNamespaceInPrefix() throws Exception { + public void testValidatesRelaxNGSchemaThatsValidWithNamespaceInPrefix() throws Exception { XMLValidationRootSettings validation = new XMLValidationRootSettings(); validation.setResolveExternalEntities(true);