Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/validate/HTMLAttributeValidator.java')
-rw-r--r--bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/validate/HTMLAttributeValidator.java91
1 files changed, 86 insertions, 5 deletions
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 c4d794fb81..9acadf0f0a 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
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2004, 2013 IBM Corporation and others.
+ * Copyright (c) 2004, 2014 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -7,18 +7,35 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
+ * Red Hat, Inc. - Bug #426939 - [validator] HTML5 attribute validator
+ * marks ng-app AngularJS attributes as undefined
*******************************************************************************/
package org.eclipse.wst.html.core.internal.validate;
import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
import java.util.List;
import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
+import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.ProjectScope;
import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.preferences.DefaultScope;
+import org.eclipse.core.runtime.preferences.IPreferencesService;
+import org.eclipse.core.runtime.preferences.IScopeContext;
+import org.eclipse.core.runtime.preferences.InstanceScope;
+import org.eclipse.wst.html.core.internal.HTMLCorePlugin;
import org.eclipse.wst.html.core.internal.document.HTMLDocumentTypeConstants;
+import org.eclipse.wst.html.core.internal.preferences.HTMLCorePreferenceNames;
import org.eclipse.wst.sse.core.internal.provisional.INodeNotifier;
import org.eclipse.wst.sse.core.internal.provisional.IndexedRegion;
import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion;
@@ -49,6 +66,9 @@ public class HTMLAttributeValidator extends PrimeValidator {
private static final char SINGLE_QUOTE = '\'';
private static final char DOUBLE_QUOTE = '\"';
+ private IPreferencesService fPreferenceService;
+ private static Map fIgnorePatterns = new HashMap(); // A storage for ignore patterns (instances of StringMatcher)
+
// HTML(5) data attributes
private static final String ATTR_NAME_DATA = "data-"; //$NON-NLS-1$
private static final int ATTR_NAME_DATA_LENGTH = ATTR_NAME_DATA.length();
@@ -63,6 +83,7 @@ public class HTMLAttributeValidator extends PrimeValidator {
*/
public HTMLAttributeValidator() {
super();
+ fPreferenceService = Platform.getPreferencesService();
}
/**
@@ -153,11 +174,15 @@ public class HTMLAttributeValidator extends PrimeValidator {
}
if (adec == null) {
- if ((attrName.startsWith(ATTR_NAME_DATA) && attrName.length() > ATTR_NAME_DATA_LENGTH) || (attrName.startsWith(ATTR_NAME_USER_AGENT_FEATURE) && attrName.length() > ATTR_NAME_USER_AGENT_FEATURE_LENGTH)) {
- DocumentTypeAdapter documentTypeAdapter = (DocumentTypeAdapter) ((INodeNotifier) target.getOwnerDocument()).getAdapterFor(DocumentTypeAdapter.class);
- if (documentTypeAdapter != null && documentTypeAdapter.hasFeature(HTMLDocumentTypeConstants.HTML5))
+ if ((attrName.startsWith(ATTR_NAME_DATA) && attrName.length() > ATTR_NAME_DATA_LENGTH) ||
+ (attrName.startsWith(ATTR_NAME_USER_AGENT_FEATURE) && attrName.length() > ATTR_NAME_USER_AGENT_FEATURE_LENGTH)) {
+ if (isHTML5(target))
continue;
- }
+ }
+ // Check for user-defined exclusions for HTML5 attribute names
+ if (!shouldValidateAttributeName(target, attrName))
+ continue;
+
// No attr declaration was found. That is, the attr name is
// undefined.
// but not regard it as undefined name if it includes nested
@@ -333,4 +358,60 @@ public class HTMLAttributeValidator extends PrimeValidator {
return (c == SINGLE_QUOTE) || (c == DOUBLE_QUOTE);
}
// D210422
+
+ private boolean isHTML5(Element target) {
+ DocumentTypeAdapter documentTypeAdapter = (DocumentTypeAdapter) ((INodeNotifier) target.getOwnerDocument()).getAdapterFor(DocumentTypeAdapter.class);
+ return (documentTypeAdapter != null &&
+ documentTypeAdapter.hasFeature(HTMLDocumentTypeConstants.HTML5));
+ }
+
+ private boolean shouldValidateAttributeName(Element target, String attrName) {
+ if (!isHTML5(target)) return true;
+
+ Object adapter = (target instanceof IAdaptable ? ((IAdaptable)target).getAdapter(IResource.class) : null);
+ IProject project = (adapter instanceof IResource ? ((IResource)adapter).getProject() : null);
+
+ Iterator excludedAttributes = getExcludedAttributeNames(project).iterator();
+ while (excludedAttributes.hasNext()) {
+ String excluded = (String)excludedAttributes.next();
+ StringMatcher strMatcher = (StringMatcher)fIgnorePatterns.get(excluded);
+ if (strMatcher == null) {
+ strMatcher = new StringMatcher(excluded);
+ fIgnorePatterns.put(excluded, strMatcher);
+ }
+ if (strMatcher.match(attrName))
+ return false;
+ }
+
+ return true;
+ }
+
+ private Set getExcludedAttributeNames(IProject project) {
+ IScopeContext[] fLookupOrder = new IScopeContext[] {new InstanceScope(), new DefaultScope()};
+ if (project != null) {
+ ProjectScope projectScope = new ProjectScope(project);
+ if(projectScope.getNode(HTMLCorePlugin.getDefault().getBundle().getSymbolicName()).getBoolean(HTMLCorePreferenceNames.USE_PROJECT_SETTINGS, false))
+ fLookupOrder = new IScopeContext[] {projectScope, new InstanceScope(), new DefaultScope()};
+ }
+
+ Set result = new HashSet();
+ if (fPreferenceService.getBoolean(HTMLCorePlugin.getDefault().getBundle().getSymbolicName(),
+ HTMLCorePreferenceNames.IGNORE_ATTRIBUTE_NAMES, HTMLCorePreferenceNames.IGNORE_ATTRIBUTE_NAMES_DEFAULT,
+ fLookupOrder)) {
+ String ignoreList = fPreferenceService.getString(HTMLCorePlugin.getDefault().getBundle().getSymbolicName(),
+ HTMLCorePreferenceNames.ATTRIBUTE_NAMES_TO_IGNORE, HTMLCorePreferenceNames.ATTRIBUTE_NAMES_TO_IGNORE_DEFAULT,
+ fLookupOrder);
+
+ if (ignoreList.trim().isEmpty())
+ return result;
+
+ String[] names = ignoreList.split(","); //$NON-NLS-1$
+ for (int i = 0; names != null && i < names.length; i++) {
+ String name = names[i] == null ? null : names[i].trim();
+ if (name != null && !name.isEmpty())
+ result.add(name.toLowerCase());
+ }
+ }
+ return result;
+ }
}

Back to the top