Skip to content

Commit

Permalink
Manage namespaces / prefix validation with a settings
Browse files Browse the repository at this point in the history
Fixes #960

Signed-off-by: azerr <[email protected]>
  • Loading branch information
angelozerr authored and datho7561 committed Jan 18, 2021
1 parent 6e5a906 commit 5488280
Show file tree
Hide file tree
Showing 6 changed files with 223 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,9 @@
import org.eclipse.lemminx.dom.SchemaLocationHint;
import org.eclipse.lemminx.extensions.contentmodel.model.ContentModelManager;
import org.eclipse.lemminx.extensions.contentmodel.participants.XMLSyntaxErrorCode;
import org.eclipse.lemminx.extensions.contentmodel.settings.NamespacesEnabled;
import org.eclipse.lemminx.extensions.contentmodel.settings.SchemaEnabled;
import org.eclipse.lemminx.extensions.contentmodel.settings.XMLNamespacesSettings;
import org.eclipse.lemminx.extensions.contentmodel.settings.XMLSchemaSettings;
import org.eclipse.lemminx.extensions.contentmodel.settings.XMLValidationSettings;
import org.eclipse.lemminx.services.extensions.diagnostics.LSPContentHandler;
Expand Down Expand Up @@ -111,6 +113,10 @@ && isSchemaValidationEnabled(document, validationSettings)
}
parser.setFeature("http://xml.org/sax/features/validation", hasGrammar); //$NON-NLS-1$

boolean namespacesValidationEnabled = isNamespacesValidationEnabled(document, validationSettings);
parser.setFeature("http://xml.org/sax/features/namespace-prefixes", namespacesValidationEnabled); //$NON-NLS-1$
parser.setFeature("http://xml.org/sax/features/namespaces", namespacesValidationEnabled); //$NON-NLS-1$

// Parse XML
String content = document.getText();
String uri = document.getDocumentURI();
Expand All @@ -127,6 +133,28 @@ && isSchemaValidationEnabled(document, validationSettings)
}
}

private static boolean isNamespacesValidationEnabled(DOMDocument document,
XMLValidationSettings validationSettings) {
if (validationSettings == null) {
return true;
}
NamespacesEnabled enabled = NamespacesEnabled.always;
XMLNamespacesSettings namespacesSettings = validationSettings.getNamespaces();
if (namespacesSettings != null && namespacesSettings.getEnabled() != null) {
enabled = namespacesSettings.getEnabled();
}
switch (enabled) {
case always:
return true;
case never:
return false;
case onNamespaceEncountered:
return document.hasNamespaces();
default:
return true;
}
}

private static boolean isSchemaValidationEnabled(DOMDocument document, XMLValidationSettings validationSettings) {
if (validationSettings == null) {
return true;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/**
* Copyright (c) 2021 Red Hat Inc. and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* which accompanies this distribution, and is available at
* 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.settings;

public enum NamespacesEnabled {
always, never, onNamespaceEncountered;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/**
* Copyright (c) 2021 Red Hat Inc. and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* which accompanies this distribution, and is available at
* 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.settings;

/**
* XML Namespaces settings.
*
*/
public class XMLNamespacesSettings {

public XMLNamespacesSettings() {
setEnabled(NamespacesEnabled.always);
}

private NamespacesEnabled enabled;

public void setEnabled(NamespacesEnabled enabled) {
this.enabled = enabled;
}

@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((enabled == null) ? 0 : enabled.hashCode());
return result;
}

@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
XMLNamespacesSettings other = (XMLNamespacesSettings) obj;
if (enabled != other.enabled)
return false;
return true;
}

public NamespacesEnabled getEnabled() {
return enabled;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,12 @@
*/
public class XMLValidationSettings {

private XMLSchemaSettings schema;

private Boolean enabled;

private XMLNamespacesSettings namespaces;

private XMLSchemaSettings schema;

private boolean disallowDocTypeDecl;

private boolean resolveExternalEntities;
Expand All @@ -46,19 +48,41 @@ public XMLValidationSettings() {
}

/**
* @return the syntax
* Returns true if the validation is enabled and false otherwise.
*
* @return true if the validation is enabled and false otherwise.
*/
public boolean isEnabled() {
return enabled;
}

/**
* @param syntax the syntax to set
* Set true if the validation is enabled and false otherwise.
*
* @param enabled true if the validation is enabled and false otherwise.
*/
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}

/**
* Returns the XML Namespaces validation settings.
*
* @return the XML Namespaces validation settings.
*/
public XMLNamespacesSettings getNamespaces() {
return namespaces;
}

/**
* Set the XML Namespaces validation settings.
*
* @param namespaces the XML Namespaces validation settings.
*/
public void setNamespaces(XMLNamespacesSettings namespaces) {
this.namespaces = namespaces;
}

/**
* Returns the XML Schema validation settings.
*
Expand All @@ -69,7 +93,9 @@ public XMLSchemaSettings getSchema() {
}

/**
* @param schema the schema to set
* Set the XML Schema validation settings.
*
* @param schema the XML Schema validation settings.
*/
public void setSchema(XMLSchemaSettings schema) {
this.schema = schema;
Expand Down Expand Up @@ -151,6 +177,7 @@ public static DiagnosticSeverity getNoGrammarSeverity(XMLValidationSettings vali

public XMLValidationSettings merge(XMLValidationSettings settings) {
if (settings != null) {
this.namespaces = settings.namespaces;
this.schema = settings.schema;
this.enabled = settings.enabled;
this.disallowDocTypeDecl = settings.disallowDocTypeDecl;
Expand All @@ -174,6 +201,7 @@ public int hashCode() {
int result = 1;
result = prime * result + (disallowDocTypeDecl ? 1231 : 1237);
result = prime * result + ((enabled == null) ? 0 : enabled.hashCode());
result = prime * result + ((namespaces == null) ? 0 : namespaces.hashCode());
result = prime * result + ((noGrammar == null) ? 0 : noGrammar.hashCode());
result = prime * result + (resolveExternalEntities ? 1231 : 1237);
result = prime * result + ((schema == null) ? 0 : schema.hashCode());
Expand All @@ -196,6 +224,11 @@ public boolean equals(Object obj) {
return false;
} else if (!enabled.equals(other.enabled))
return false;
if (namespaces == null) {
if (other.namespaces != null)
return false;
} else if (!namespaces.equals(other.namespaces))
return false;
if (noGrammar == null) {
if (other.noGrammar != null)
return false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -285,8 +285,21 @@
"parameterTypes": []
}]
},
{
"name": "org.eclipse.lemminx.extensions.contentmodel.settings.XMLNamespacesSettings",
"allDeclaredFields": true,
"methods": [{
"name": "<init>",
"parameterTypes": []
}]
},
{
"name": "org.eclipse.lemminx.extensions.contentmodel.settings.NamespacesEnabled",
"allDeclaredFields": true
},
{
"name": "org.eclipse.lemminx.extensions.contentmodel.settings.XMLSchemaSettings",
"allDeclaredFields": true,
"methods": [{
"name": "<init>",
"parameterTypes": []
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,10 @@

import org.eclipse.lemminx.XMLAssert;
import org.eclipse.lemminx.extensions.contentmodel.participants.XMLSyntaxErrorCode;
import org.eclipse.lemminx.extensions.contentmodel.settings.ContentModelSettings;
import org.eclipse.lemminx.extensions.contentmodel.settings.NamespacesEnabled;
import org.eclipse.lemminx.extensions.contentmodel.settings.SchemaEnabled;
import org.eclipse.lemminx.extensions.contentmodel.settings.XMLNamespacesSettings;
import org.eclipse.lemminx.settings.EnforceQuoteStyle;
import org.eclipse.lemminx.settings.QuoteStyle;
import org.eclipse.lemminx.settings.SharedSettings;
Expand Down Expand Up @@ -632,8 +635,8 @@ public void testMissingQuotesForAttributeSingleQuotes() throws Exception {
public void testOpenQuoteExpectedDisabledPreference() throws Exception {
String xml = " <InstdAmt Ccy==\"JPY\">10000000</InstdAmt>";
testDiagnosticsFor(xml, null, null, null, true, XMLAssert.getContentModelSettings(false, SchemaEnabled.always)); // validation
// is
// disabled
// is
// disabled
}

@Test
Expand Down Expand Up @@ -781,4 +784,70 @@ public void closeTag() throws Exception {
testDiagnosticsFor(xml, d);
testCodeActionsFor(xml, d, ca(d, te(0, 5, 0, 5, "a>")));
}

@Test
public void namespacesSettingsWithoutXMLNS() throws Exception {
String xml = "<foo>\r\n" + //
" <p:bar />\r\n" + //
"</foo>";
// always
ContentModelSettings settings = getSettingsForNamespaces(NamespacesEnabled.always);
testDiagnosticsFor(xml, null, null, null, true, settings, //
d(1, 2, 1, 7, XMLSyntaxErrorCode.ElementPrefixUnbound));

// never
settings = getSettingsForNamespaces(NamespacesEnabled.never);
testDiagnosticsFor(xml, null, null, null, true, settings);

// onNamespaceEncountered
settings = getSettingsForNamespaces(NamespacesEnabled.onNamespaceEncountered);
testDiagnosticsFor(xml, null, null, null, true, settings);
}

@Test
public void namespacesSettingsWithUnvalidXMLNS() throws Exception {
String xml = "<foo xmlns=\"http:foo\" >\r\n" + //
" <p:bar />\r\n" + //
"</foo>";
// always
ContentModelSettings settings = getSettingsForNamespaces(NamespacesEnabled.always);
testDiagnosticsFor(xml, null, null, null, true, settings, //
d(1, 2, 1, 7, XMLSyntaxErrorCode.ElementPrefixUnbound));

// never
settings = getSettingsForNamespaces(NamespacesEnabled.never);
testDiagnosticsFor(xml, null, null, null, true, settings);

// onNamespaceEncountered
settings = getSettingsForNamespaces(NamespacesEnabled.onNamespaceEncountered);
testDiagnosticsFor(xml, null, null, null, true, settings, //
d(1, 2, 1, 7, XMLSyntaxErrorCode.ElementPrefixUnbound));
}

@Test
public void namespacesSettingsWithValidXMLNS() throws Exception {
String xml = "<foo xmlns:p=\"http:foo\" >\r\n" + //
" <p:bar />\r\n" + //
"</foo>";
// always
ContentModelSettings settings = getSettingsForNamespaces(NamespacesEnabled.always);
testDiagnosticsFor(xml, null, null, null, true, settings);

// never
settings = getSettingsForNamespaces(NamespacesEnabled.never);
testDiagnosticsFor(xml, null, null, null, true, settings);

// onNamespaceEncountered
settings = getSettingsForNamespaces(NamespacesEnabled.onNamespaceEncountered);
testDiagnosticsFor(xml, null, null, null, true, settings);
}

private static ContentModelSettings getSettingsForNamespaces(NamespacesEnabled namespacesEnabled) {
ContentModelSettings settings = XMLAssert.getContentModelSettings(true, SchemaEnabled.never);
settings.getValidation().setNoGrammar("ignore");
XMLNamespacesSettings namespaces = new XMLNamespacesSettings();
namespaces.setEnabled(namespacesEnabled);
settings.getValidation().setNamespaces(namespaces);
return settings;
}
}

0 comments on commit 5488280

Please sign in to comment.