245532 HTML Validator Performance Impacted by Model Query Extension
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/validate/HTMLAttributeValidator.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/validate/HTMLAttributeValidator.java
index a4a0279..c86a52f 100644
--- a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/validate/HTMLAttributeValidator.java
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/validate/HTMLAttributeValidator.java
@@ -12,10 +12,8 @@
-import java.util.HashMap;
import java.util.List;
import java.util.Locale;
-import java.util.Map;
import org.eclipse.wst.sse.core.internal.provisional.IndexedRegion;
import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion;
@@ -26,7 +24,6 @@
import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
import org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap;
import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
-import org.eclipse.wst.xml.core.internal.contentmodel.basic.CMNamedNodeMapImpl;
import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.ModelQuery;
import org.eclipse.wst.xml.core.internal.modelquery.ModelQueryUtil;
import org.eclipse.wst.xml.core.internal.provisional.document.IDOMAttr;
@@ -99,38 +96,7 @@
return;
CMNamedNodeMap declarations = edec.getAttributes();
- CMNamedNodeMapImpl allAttributes = new CMNamedNodeMapImpl(declarations) {
- private Map caseInsensitive;
-
- private Map getCaseInsensitiveMap() {
- if(caseInsensitive == null)
- caseInsensitive = new HashMap();
- return caseInsensitive;
- }
-
- public CMNode getNamedItem(String name) {
- CMNode node = super.getNamedItem(name);
- if (node == null) {
- node = (CMNode) getCaseInsensitiveMap().get(name.toLowerCase(Locale.US));
- }
- return node;
- }
-
- public void put(CMNode cmNode) {
- super.put(cmNode);
- getCaseInsensitiveMap().put(cmNode.getNodeName().toLowerCase(Locale.US), cmNode);
- }
- };
-
- List nodes = ModelQueryUtil.getModelQuery(target.getOwnerDocument()).getAvailableContent((Element) node, edec, ModelQuery.INCLUDE_ATTRIBUTES);
- for (int k = 0; k < nodes.size(); k++) {
- CMNode cmnode = (CMNode) nodes.get(k);
- if (cmnode.getNodeType() == CMNode.ATTRIBUTE_DECLARATION) {
- allAttributes.put(cmnode);
- }
- }
- declarations = allAttributes;
-
+ List modelQueryNodes = null;
NamedNodeMap attrs = target.getAttributes();
for (int i = 0; i < attrs.getLength(); i++) {
int rgnType = REGION_NAME;
@@ -150,6 +116,22 @@
}
CMAttributeDeclaration adec = (CMAttributeDeclaration) declarations.getNamedItem(a.getName());
+
+ /* Check the modelquery if nothing is declared by the element declaration */
+ if (adec == null) {
+ if (modelQueryNodes == null)
+ modelQueryNodes = ModelQueryUtil.getModelQuery(target.getOwnerDocument()).getAvailableContent((Element) node, edec, ModelQuery.INCLUDE_ATTRIBUTES);
+
+ String attrName = a.getName().toLowerCase(Locale.US);
+ for (int k = 0; k < modelQueryNodes.size(); k++) {
+ CMNode cmnode = (CMNode) modelQueryNodes.get(k);
+ if (cmnode.getNodeType() == CMNode.ATTRIBUTE_DECLARATION && cmnode.getNodeName().toLowerCase(Locale.US).equals(attrName)) {
+ adec = (CMAttributeDeclaration) cmnode;
+ break;
+ }
+ }
+ }
+
if (adec == null) {
// No attr declaration was found. That is, the attr name is
// undefined.
diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/validate/HTMLElementContentValidator.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/validate/HTMLElementContentValidator.java
index 9041574..39fe3fe 100644
--- a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/validate/HTMLElementContentValidator.java
+++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/validate/HTMLElementContentValidator.java
@@ -59,28 +59,11 @@
if(ed == null || ed.getContentType() == CMElementDeclaration.ANY)
return;
- /*
- * https://bugs.eclipse.org/bugs/show_bug.cgi?id=218143 -
- * ModelQuery use not pervasive enough
- */
- List availableChildElementDeclarations = ModelQueryUtil.getModelQuery(parent.getOwnerDocument()).getAvailableContent(parent, ed, ModelQuery.INCLUDE_CHILD_NODES);
- /*
- * Retrieve and set aside just the element names for faster checking
- * later.
- */
- int availableChildCount = availableChildElementDeclarations.size();
- List availableChildElementLowercaseNames = new ArrayList(availableChildCount);
- for (int i = 0; i < availableChildCount; i++) {
- CMNode cmnode = (CMNode) availableChildElementDeclarations.get(i);
- if (cmnode.getNodeType() == CMNode.ELEMENT_DECLARATION) {
- availableChildElementLowercaseNames.add(cmnode.getNodeName().toLowerCase(Locale.US));
- }
- }
- Object[] availableChildElementLowercaseNamesArray = availableChildElementLowercaseNames.toArray();
-
+ List extendedContentHolder = new ArrayList();
+ boolean[] extendedContentRetrieved = new boolean[1];
while (child != null) {
// perform actual validation
- validateNode(parent, child, ed, availableChildElementLowercaseNamesArray);
+ validateNode(parent, child, ed, extendedContentHolder, extendedContentRetrieved);
child = child.getNextSibling();
}
}
@@ -109,17 +92,17 @@
// return 1;
// }
- private boolean containsName(String name, Object[] possible) {
- if (name != null && possible != null) {
- for (int i = 0; i < possible.length; i++) {
- if(name.equals(possible[i]))
- return true;
- }
- }
- return false;
- }
+// private boolean containsName(String name, Object[] possible) {
+// if (name != null && possible != null) {
+// for (int i = 0; i < possible.length; i++) {
+// if(name.equals(possible[i]))
+// return true;
+// }
+// }
+// return false;
+// }
- private void validateNode(Element target, Node child, CMElementDeclaration edec, Object[] availableLowercaseChildElementNames) {
+ private void validateNode(Element target, Node child, CMElementDeclaration edec, List extendedContent, boolean[] extendedContentInitialized) {
// NOTE: If the target element is 'UNKNOWN', that is, it has no
// element declaration, the content type of the element should be
// regarded as 'ANY'. -- 9/10/2001
@@ -144,7 +127,7 @@
// Defect 186774: If a child is not one of HTML elements,
// it should be regarded as a valid child regardless the
// type of the parent content model. -- 10/12/2001
- if (ced == null || CMUtil.isSSI(ced) || (!CMUtil.isHTML(ced)) || containsName(ced.getElementName().toLowerCase(Locale.US), availableLowercaseChildElementNames))
+ if (ced == null || CMUtil.isSSI(ced) || (!CMUtil.isHTML(ced)))
return;
switch (contentType) {
@@ -165,6 +148,30 @@
if (CMUtil.isValidInclusion(ced, target))
return;
}
+
+ /*
+ * https://bugs.eclipse.org/bugs/show_bug.cgi?id=218143 -
+ * ModelQuery use not pervasive enough
+ */
+ if (!extendedContentInitialized[0]) {
+ extendedContent.addAll(ModelQueryUtil.getModelQuery(target.getOwnerDocument()).getAvailableContent(target, edec, ModelQuery.INCLUDE_CHILD_NODES));
+ extendedContentInitialized[0] = true;
+ }
+
+ List availableChildElementDeclarations = extendedContent;
+ /*
+ * Retrieve and set aside just the element names for faster checking
+ * later.
+ */
+ int availableChildCount = availableChildElementDeclarations.size();
+ String elementName = ced.getElementName().toLowerCase(Locale.US);
+ for (int i = 0; i < availableChildCount; i++) {
+ CMNode cmnode = (CMNode) availableChildElementDeclarations.get(i);
+ if (cmnode.getNodeType() == CMNode.ELEMENT_DECLARATION && cmnode.getNodeName().toLowerCase(Locale.US).equals(elementName)) {
+ return;
+ }
+ }
+
error = ErrorState.INVALID_CONTENT_ERROR;
break;
default :