Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Report only XML syntax error for *.exsd files #1308

Merged
merged 1 commit into from
Oct 11, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,10 @@ private static XMLValidationFilter[] createDefaultFilters() {
List<XMLValidationFilter> filters = new ArrayList<>();
// Ignore validation for Eclipse '*.exsd' files
XMLValidationFilter filter = new XMLValidationFilter();
filter.setEnabled(false);
filter.setNoGrammar("ignore");
XMLSchemaSettings schema = new XMLSchemaSettings();
schema.setEnabled(SchemaEnabled.never);
filter.setSchema(schema);
filter.setPattern("**.exsd");
filters.add(filter);
// Don't warn that XML file have no grammar for Eclipse '.project',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,34 +34,36 @@
*
* @see https://wiki.xmldation.com/Support/Validator
*
* All error code types and messages can be found in the Xerces library
* https://github.com/apache/xerces2-j/blob/trunk/src/org/apache/xerces/impl/msg/XMLSchemaMessages.properties
* All error code types and messages can be found in the Xerces library
* https://github.com/apache/xerces2-j/blob/trunk/src/org/apache/xerces/impl/msg/XMLSchemaMessages.properties
*
*/
public enum XSDErrorCode implements IXMLErrorCode {

cos_all_limited_2("cos-all-limited.2"),
ct_props_correct_3("ct-props-correct.3"),
p_props_correct_2_1("p-props-correct.2.1"),
cos_all_limited_2("cos-all-limited.2"), //
ct_props_correct_3("ct-props-correct.3"), //
p_props_correct_2_1("p-props-correct.2.1"), //
s4s_elt_invalid_content_1("s4s-elt-invalid-content.1"), //
s4s_elt_must_match_1("s4s-elt-must-match.1"), //
s4s_elt_must_match_2("s4s-elt-must-match.2"),
s4s_elt_must_match_2("s4s-elt-must-match.2"), //
s4s_att_must_appear("s4s-att-must-appear"), //
s4s_elt_invalid_content_2("s4s-elt-invalid-content.2"), //
s4s_att_not_allowed("s4s-att-not-allowed"), //
s4s_att_invalid_value("s4s-att-invalid-value"), //
s4s_elt_character("s4s-elt-character"), //
s4s_elt_invalid_content_3("s4s-elt-invalid-content.3"), //
sch_props_correct_2("sch-props-correct.2"),
sch_props_correct_2("sch-props-correct.2"), //
schema_reference_4("schema_reference.4"), //
src_ct_1("src-ct.1"),
src_import_1_2("src-import.1.2"),
src_element_3("src-element.3"),
src_ct_1("src-ct.1"), //
src_import_1_2("src-import.1.2"), //
src_element_3("src-element.3"), //
src_resolve_4_2("src-resolve.4.2"), //
src_resolve("src-resolve"), src_element_2_1("src-element.2.1"),
EmptyTargetNamespace("EmptyTargetNamespace"),
src_import_3_1("src-import.3.1"),
src_import_3_2("src-import.3.2");
src_resolve("src-resolve"), //
src_element_2_1("src-element.2.1"), //
EmptyTargetNamespace("EmptyTargetNamespace"), //
src_import_3_1("src-import.3.1"), //
src_import_3_2("src-import.3.2"), //
src_annotation("src-annotation");

private final String code;

Expand Down Expand Up @@ -166,20 +168,24 @@ public static Range toLSPRange(XMLLocator location, XSDErrorCode code, Object[]
case schema_reference_4: {
return XMLPositionUtility.selectAttributeValueAt(XSDUtils.SCHEMA_LOCATION_ATTR, offset, true, document);
}
case EmptyTargetNamespace :
case EmptyTargetNamespace:
return XMLPositionUtility.selectAttributeValueAt(XSDUtils.TARGET_NAMESPACE_ATTR, offset, document);
case src_import_3_1: {
// If the imported file of `schemaLocation` contains at least a doctype and 'xs:schema' with at least one `xs:element`,
// then the `xs:import` line will be highlighted, otherwise the `xs:schema` line will be highlighted
// If the imported file of `schemaLocation` contains at least a doctype and
// 'xs:schema' with at least one `xs:element`,
// then the `xs:import` line will be highlighted, otherwise the `xs:schema` line
// will be highlighted
DOMNode elementHighlighted = document.findNodeAt(offset);
if (elementHighlighted.getNodeName().equals(XSDUtils.XS_SCHEMA_TAG)) { // `xs:schema` line is highlighted
return XMLPositionUtility.selectChildNodeAttributeValueFromGivenNameAt(XSDUtils.XS_IMPORT_TAG, XSDUtils.NAMESPACE_ATTR, offset, document);
return XMLPositionUtility.selectChildNodeAttributeValueFromGivenNameAt(XSDUtils.XS_IMPORT_TAG,
XSDUtils.NAMESPACE_ATTR, offset, document);
} else { // `xs:import` line is highlighted
return XMLPositionUtility.selectAttributeValueAt(XSDUtils.NAMESPACE_ATTR, offset, document);
}
}
case src_import_3_2:
return XMLPositionUtility.selectChildNodeAttributeValueFromGivenNameAt(XSDUtils.XS_IMPORT_TAG, XSDUtils.SCHEMA_LOCATION_ATTR, offset, document);
return XMLPositionUtility.selectChildNodeAttributeValueFromGivenNameAt(XSDUtils.XS_IMPORT_TAG,
XSDUtils.SCHEMA_LOCATION_ATTR, offset, document);
}

return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@

import org.apache.xerces.xni.parser.XMLEntityResolver;
import org.eclipse.lemminx.dom.DOMDocument;
import org.eclipse.lemminx.extensions.contentmodel.model.ContentModelManager;
import org.eclipse.lemminx.extensions.contentmodel.participants.diagnostics.XMLValidator;
import org.eclipse.lemminx.extensions.contentmodel.settings.SchemaEnabled;
import org.eclipse.lemminx.extensions.contentmodel.settings.XMLSchemaSettings;
import org.eclipse.lemminx.extensions.contentmodel.settings.XMLValidationSettings;
import org.eclipse.lemminx.extensions.xerces.LSPXMLEntityResolver;
import org.eclipse.lemminx.extensions.xsd.XSDPlugin;
Expand All @@ -39,20 +43,40 @@ public XSDDiagnosticsParticipant(XSDPlugin xsdPlugin) {

@Override
public void doDiagnostics(DOMDocument xmlDocument, List<Diagnostic> diagnostics,
XMLValidationSettings validationSettings, CancelChecker cancelChecker) {
XMLValidationSettings validationSettings, CancelChecker monitor) {
if (!DOMUtils.isXSD(xmlDocument)) {
// Don't use the XSD validator, if the XML document is not a XML Schema.
return;
}

// Get entity resolver (XML catalog resolver, XML schema from the file
// associations settings., ...)
XMLEntityResolver entityResolver = xmlDocument.getResolverExtensionManager();
LSPXMLEntityResolver entityResolverWrapper = new LSPXMLEntityResolver(entityResolver,
(DiagnosticsResult) diagnostics);
ContentModelManager contentModelManager = xsdPlugin.getContentModelManager();
if (!isSchemaEnabled(validationSettings)) {
// Validate only XML syntax for XSD
// Process validation
XMLValidator.doDiagnostics(xmlDocument, entityResolverWrapper, diagnostics, validationSettings,
contentModelManager, monitor);
return;
}

// Process validation
// Process XSD validation
XSDValidator.doDiagnostics(xmlDocument, entityResolverWrapper, diagnostics, validationSettings,
xsdPlugin.getContentModelManager(), cancelChecker);
xsdPlugin.getContentModelManager(), monitor);
}

private static boolean isSchemaEnabled(XMLValidationSettings validationSettings) {
if (validationSettings == null) {
return true;
}
XMLSchemaSettings schemaSettings = validationSettings.getSchema();
if (schemaSettings == null) {
return true;
}
return !SchemaEnabled.never.equals(schemaSettings.getEnabled());
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,11 @@
import org.eclipse.lemminx.AbstractCacheBasedTest;
import org.eclipse.lemminx.XMLAssert;
import org.eclipse.lemminx.extensions.contentmodel.participants.XMLSyntaxErrorCode;
import org.eclipse.lemminx.extensions.contentmodel.settings.SchemaEnabled;
import org.eclipse.lemminx.extensions.contentmodel.settings.XMLSchemaSettings;
import org.eclipse.lemminx.extensions.contentmodel.settings.XMLValidationFilter;
import org.eclipse.lemminx.extensions.contentmodel.settings.XMLValidationRootSettings;
import org.eclipse.lemminx.extensions.xsd.participants.XSDErrorCode;
import org.eclipse.lemminx.services.XMLLanguageService;
import org.eclipse.lsp4j.Diagnostic;
import org.eclipse.lsp4j.DiagnosticSeverity;
Expand Down Expand Up @@ -58,26 +61,6 @@ public void disableValidationFilter() throws Exception {
XMLAssert.testPublishDiagnosticsFor(xml, fileURI, validation, ls, pd(fileURI));
}

@Test
public void defaultDisableValidationFilter() throws Exception {

String xml = "<foo";
XMLValidationRootSettings validation = new XMLValidationRootSettings();
XMLLanguageService ls = new XMLLanguageService();

String fileURI = "file:///home/test.xml";
// test.xml doesn't matches the validation filter
XMLAssert.testPublishDiagnosticsFor(xml, fileURI, validation, ls, pd(fileURI,
new Diagnostic(r(0, 1, 0, 4), "No grammar constraints (DTD or XML Schema).", DiagnosticSeverity.Hint,
"xml", XMLSyntaxErrorCode.NoGrammarConstraints.getCode()), //
new Diagnostic(r(0, 1, 0, 4), "XML document structures must start and end within the same entity.",
DiagnosticSeverity.Error, "xml", XMLSyntaxErrorCode.MarkupEntityMismatch.getCode())));

// test.exsd matches the validation filter
fileURI = "file:///home/test.exsd";
XMLAssert.testPublishDiagnosticsFor(xml, fileURI, validation, ls, pd(fileURI));
}

@Test
public void noGrammarFilter() throws Exception {

Expand Down Expand Up @@ -130,6 +113,82 @@ public void defaultDisableNoGrammarFilter() throws Exception {
XMLAssert.testPublishDiagnosticsFor(xml, fileURI, validation, ls, pd(fileURI));
fileURI = "file:///home/foo.product";
XMLAssert.testPublishDiagnosticsFor(xml, fileURI, validation, ls, pd(fileURI));
}

@Test
public void disableXMLSchemaValidationFilter() throws Exception {
String xml = "<schema xmlns=\"http://www.w3.org/2001/XMLSchema\">\r\n" + //
" <annotation>\r\n" + //
" <appInfo>\r\n" + // <-- XSD error here, it should be appinfo
" </appInfo>\r\n" + //
" </annotation>\r\n" + //
"</schema>";

XMLValidationRootSettings validation = new XMLValidationRootSettings();
XMLValidationFilter filter = new XMLValidationFilter();
filter.setEnabled(true);
filter.setNoGrammar("ignore");
XMLSchemaSettings schemaSettings = new XMLSchemaSettings();
schemaSettings.setEnabled(SchemaEnabled.never);
filter.setSchema(schemaSettings);
filter.setPattern("**.myxsd");
validation.setFilters(Arrays.asList(filter).toArray(new XMLValidationFilter[0]));
XMLLanguageService ls = new XMLLanguageService();

String fileURI = "file:///home/test.xsd";
// test.xsd doesn't matches the validation filter
XMLAssert.testPublishDiagnosticsFor(xml, fileURI, validation, ls, pd(fileURI, //
// XML schema error code
new Diagnostic(r(2, 15, 2, 15),
"src-annotation: <annotation> elements can only contain <appinfo> and <documentation> elements, but 'appInfo' was found.",
DiagnosticSeverity.Error, "xsd", XSDErrorCode.src_annotation.getCode())));

// test.exsd matches the validation filter
// XSD error should not reported
fileURI = "file:///home/test.myxsd";
XMLAssert.testPublishDiagnosticsFor(xml, fileURI, validation, ls, pd(fileURI));

// Only XML syntax error must be reported
xml = "<schema xmlns=\"http://www.w3.org/2001/XMLSchema\">\r\n" + //
" <annotation>\r\n" + // <-- annotation is not closed
"</schema>";
XMLAssert.testPublishDiagnosticsFor(xml, fileURI, validation, ls, pd(fileURI, //
new Diagnostic(r(1, 5, 1, 15),
"The element type \"annotation\" must be terminated by the matching end-tag \"</annotation>\".",
DiagnosticSeverity.Error, "xml", XMLSyntaxErrorCode.ETagRequired.getCode())));
}

@Test
public void defaultDisableXMLSchemaValidationFilter() throws Exception {
String xml = "<schema xmlns=\"http://www.w3.org/2001/XMLSchema\">\r\n" + //
" <annotation>\r\n" + //
" <appInfo>\r\n" + // <-- XSD error here, it should be appinfo
" </appInfo>\r\n" + //
" </annotation>\r\n" + //
"</schema>";
XMLValidationRootSettings validation = new XMLValidationRootSettings();
XMLLanguageService ls = new XMLLanguageService();

String fileURI = "file:///home/test.xsd";
// test.xsd doesn't matches the validation filter
XMLAssert.testPublishDiagnosticsFor(xml, fileURI, validation, ls, pd(fileURI, //
// XML schema error code
new Diagnostic(r(2, 15, 2, 15),
"src-annotation: <annotation> elements can only contain <appinfo> and <documentation> elements, but 'appInfo' was found.",
DiagnosticSeverity.Error, "xsd", XSDErrorCode.src_annotation.getCode())));

// test.exsd matches the validation filter
// XSD error should not reported for *.exsd files
fileURI = "file:///home/test.exsd";
XMLAssert.testPublishDiagnosticsFor(xml, fileURI, validation, ls, pd(fileURI));

// Only XML syntax error must be reported for *.exsd files
xml = "<schema xmlns=\"http://www.w3.org/2001/XMLSchema\">\r\n" + //
" <annotation>\r\n" + // <-- annotation is not closed
"</schema>";
XMLAssert.testPublishDiagnosticsFor(xml, fileURI, validation, ls, pd(fileURI, //
new Diagnostic(r(1, 5, 1, 15),
"The element type \"annotation\" must be terminated by the matching end-tag \"</annotation>\".",
DiagnosticSeverity.Error, "xml", XMLSyntaxErrorCode.ETagRequired.getCode())));
}
}