diff options
author | Konstantin Marmalyukov | 2015-12-16 14:14:19 +0000 |
---|---|---|
committer | Victor Rubezhny | 2016-03-05 02:25:58 +0000 |
commit | 5497b3a7e599091d1e9a78605cb43ddf5aedae7b (patch) | |
tree | 10a0fa5201f7ae6d8f00461eec5dee2bda517f8b | |
parent | 0ebaf5532473572bc45e448280baec4cf18b63cf (diff) | |
download | webtools.sourceediting-5497b3a7e599091d1e9a78605cb43ddf5aedae7b.tar.gz webtools.sourceediting-5497b3a7e599091d1e9a78605cb43ddf5aedae7b.tar.xz webtools.sourceediting-5497b3a7e599091d1e9a78605cb43ddf5aedae7b.zip |
[443097]Ignore undefined HTML attributes, elements validation with extension point
Change-Id: Ie25514a2c27e599dab0bbc3083daadc19d7d3e35
Signed-off-by: Konstantin Marmalyukov <kmarmaliykov@exadel.com>
Signed-off-by: Victor Rubezhny <vrubezhny@exadel.com>
29 files changed, 1039 insertions, 200 deletions
diff --git a/bundles/org.eclipse.jst.jsp.core/META-INF/MANIFEST.MF b/bundles/org.eclipse.jst.jsp.core/META-INF/MANIFEST.MF index e179847600..f62777c25a 100644 --- a/bundles/org.eclipse.jst.jsp.core/META-INF/MANIFEST.MF +++ b/bundles/org.eclipse.jst.jsp.core/META-INF/MANIFEST.MF @@ -54,7 +54,7 @@ Require-Bundle: org.eclipse.core.runtime;bundle-version="[3.12.0,4.0.0)", org.eclipse.wst.sse.core;bundle-version="[1.1.900,1.2.0)", org.eclipse.wst.xml.core;bundle-version="[1.1.1000,1.2.0)", org.eclipse.wst.css.core;bundle-version="[1.1.800,1.2.0)", - org.eclipse.wst.html.core;bundle-version="[1.1.800,1.2.0)", + org.eclipse.wst.html.core;bundle-version="[1.1.800,1.3.0)", org.eclipse.wst.validation;bundle-version="[1.2.700,1.3.0)", org.eclipse.core.filesystem;bundle-version="1.6.0", org.eclipse.osgi.services;bundle-version="3.5.0", diff --git a/bundles/org.eclipse.jst.jsp.ui/META-INF/MANIFEST.MF b/bundles/org.eclipse.jst.jsp.ui/META-INF/MANIFEST.MF index 6265dbad9a..5b11c31ea6 100644 --- a/bundles/org.eclipse.jst.jsp.ui/META-INF/MANIFEST.MF +++ b/bundles/org.eclipse.jst.jsp.ui/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: %pluginName Bundle-SymbolicName: org.eclipse.jst.jsp.ui; singleton:=true -Bundle-Version: 1.1.1000.qualifier +Bundle-Version: 1.1.1010.qualifier Bundle-Activator: org.eclipse.jst.jsp.ui.internal.JSPUIPlugin Bundle-Vendor: %providerName Bundle-Localization: plugin @@ -47,7 +47,7 @@ Require-Bundle: org.eclipse.ui.ide;bundle-version="[3.5.0,4.0.0)", org.eclipse.wst.css.ui;bundle-version="[1.0.500,1.1.0)", org.eclipse.wst.xml.ui;bundle-version="[1.1.100,1.2.0)", org.eclipse.jst.jsp.core;bundle-version="[1.2.401,1.3.0)", - org.eclipse.wst.html.core;bundle-version="[1.1.400,1.2.0)", + org.eclipse.wst.html.core;bundle-version="[1.1.400,1.3.0)", org.eclipse.wst.css.core;bundle-version="[1.1.300,1.2.0)", org.eclipse.wst.xml.core;bundle-version="[1.1.500,1.2.0)", org.eclipse.wst.sse.core;bundle-version="[1.1.500,1.2.0)", diff --git a/bundles/org.eclipse.jst.jsp.ui/pom.xml b/bundles/org.eclipse.jst.jsp.ui/pom.xml index d8ef8c11bd..249b9c6974 100644 --- a/bundles/org.eclipse.jst.jsp.ui/pom.xml +++ b/bundles/org.eclipse.jst.jsp.ui/pom.xml @@ -21,6 +21,6 @@ <groupId>org.eclipse.webtools.sourceediting</groupId> <artifactId>org.eclipse.jst.jsp.ui</artifactId> - <version>1.1.1000-SNAPSHOT</version> + <version>1.1.1010-SNAPSHOT</version> <packaging>eclipse-plugin</packaging> </project> diff --git a/bundles/org.eclipse.wst.css.ui/META-INF/MANIFEST.MF b/bundles/org.eclipse.wst.css.ui/META-INF/MANIFEST.MF index f460646c5d..1f3aa08623 100644 --- a/bundles/org.eclipse.wst.css.ui/META-INF/MANIFEST.MF +++ b/bundles/org.eclipse.wst.css.ui/META-INF/MANIFEST.MF @@ -41,7 +41,7 @@ Require-Bundle: org.eclipse.ui.ide;bundle-version="[3.12.0,4.0.0)", org.eclipse.wst.sse.ui;bundle-version="[1.3.500,1.4.0)", org.eclipse.wst.css.core;bundle-version="[1.1.800,1.2.0)", org.eclipse.wst.sse.core;bundle-version="[1.1.900,1.2.0)", - org.eclipse.wst.html.core;bundle-version="[1.1.800,1.2.0)", + org.eclipse.wst.html.core;bundle-version="[1.1.800,1.3.0)", org.eclipse.wst.xml.core;bundle-version="[1.1.1000,1.2.0)", org.eclipse.core.resources;bundle-version="[3.5.0,4.0.0)", org.eclipse.core.runtime;bundle-version="[3.12.0,4.0.0)", diff --git a/bundles/org.eclipse.wst.html.core/.classpath b/bundles/org.eclipse.wst.html.core/.classpath index 2c6f8c1f34..e84b6cc469 100644 --- a/bundles/org.eclipse.wst.html.core/.classpath +++ b/bundles/org.eclipse.wst.html.core/.classpath @@ -7,6 +7,6 @@ <accessrule kind="accessible" pattern="org/eclipse/wst/**"/> </accessrules> </classpathentry> - <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.4"/> + <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/> <classpathentry kind="output" path="bin"/> </classpath> diff --git a/bundles/org.eclipse.wst.html.core/.settings/org.eclipse.jdt.core.prefs b/bundles/org.eclipse.wst.html.core/.settings/org.eclipse.jdt.core.prefs index 0667e35a52..3990c17f1c 100644 --- a/bundles/org.eclipse.wst.html.core/.settings/org.eclipse.jdt.core.prefs +++ b/bundles/org.eclipse.wst.html.core/.settings/org.eclipse.jdt.core.prefs @@ -1,4 +1,3 @@ -#Wed Mar 28 03:23:07 EDT 2007 eclipse.preferences.version=1 org.eclipse.jdt.core.builder.cleanOutputFolder=clean org.eclipse.jdt.core.builder.duplicateResourceTask=warning @@ -7,24 +6,24 @@ org.eclipse.jdt.core.builder.resourceCopyExclusionFilter=*.launch org.eclipse.jdt.core.circularClasspath=error org.eclipse.jdt.core.classpath.exclusionPatterns=enabled org.eclipse.jdt.core.classpath.multipleOutputLocations=enabled -org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=disabled -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.2 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5 org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve -org.eclipse.jdt.core.compiler.compliance=1.4 +org.eclipse.jdt.core.compiler.compliance=1.5 org.eclipse.jdt.core.compiler.debug.lineNumber=generate org.eclipse.jdt.core.compiler.debug.localVariable=generate org.eclipse.jdt.core.compiler.debug.sourceFile=generate org.eclipse.jdt.core.compiler.doc.comment.support=enabled org.eclipse.jdt.core.compiler.maxProblemPerUnit=100 org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning -org.eclipse.jdt.core.compiler.problem.assertIdentifier=warning +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error org.eclipse.jdt.core.compiler.problem.autoboxing=ignore org.eclipse.jdt.core.compiler.problem.deprecation=ignore org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=enabled org.eclipse.jdt.core.compiler.problem.discouragedReference=warning org.eclipse.jdt.core.compiler.problem.emptyStatement=warning -org.eclipse.jdt.core.compiler.problem.enumIdentifier=warning +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error org.eclipse.jdt.core.compiler.problem.fieldHiding=ignore org.eclipse.jdt.core.compiler.problem.finalParameterBound=ignore org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=error @@ -74,6 +73,6 @@ org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=di org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=error org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning -org.eclipse.jdt.core.compiler.source=1.3 +org.eclipse.jdt.core.compiler.source=1.5 org.eclipse.jdt.core.incompatibleJDKLevel=ignore org.eclipse.jdt.core.incompleteClasspath=error diff --git a/bundles/org.eclipse.wst.html.core/META-INF/MANIFEST.MF b/bundles/org.eclipse.wst.html.core/META-INF/MANIFEST.MF index d422f231d9..09017dd48f 100644 --- a/bundles/org.eclipse.wst.html.core/META-INF/MANIFEST.MF +++ b/bundles/org.eclipse.wst.html.core/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: %pluginName Bundle-SymbolicName: org.eclipse.wst.html.core; singleton:=true -Bundle-Version: 1.1.802.qualifier +Bundle-Version: 1.2.0.qualifier Bundle-Activator: org.eclipse.wst.html.core.internal.HTMLCorePlugin Bundle-Vendor: %providerName Bundle-Localization: plugin @@ -27,7 +27,8 @@ Export-Package: org.eclipse.wst.html.core.internal;x-internal:=true, org.eclipse.wst.html.core.internal.text;x-internal:=true, org.eclipse.wst.html.core.internal.validate;x-internal:=true, org.eclipse.wst.html.core.internal.validation;x-internal:=true, - org.eclipse.wst.html.core.text + org.eclipse.wst.html.core.text, + org.eclipse.wst.html.core.validate.extension Import-Package: com.ibm.icu.util; version="3.8" Require-Bundle: org.eclipse.core.resources;bundle-version="[3.5.0,4.0.0)", org.eclipse.core.runtime;bundle-version="[3.5.0,4.0.0)", @@ -39,4 +40,4 @@ Require-Bundle: org.eclipse.core.resources;bundle-version="[3.5.0,4.0.0)", org.eclipse.wst.common.modulecore;bundle-version="[1.2.0,2.0.0)";resolution:=optional, org.eclipse.wst.validation;bundle-version="[1.2.100,1.3.0)" Bundle-ActivationPolicy: lazy;exclude:="org.eclipse.wst.html.core.internal.contenttype,org.eclipse.wst.html.core.internal.provisional.contenttype" -Bundle-RequiredExecutionEnvironment: J2SE-1.4 +Bundle-RequiredExecutionEnvironment: J2SE-1.5 diff --git a/bundles/org.eclipse.wst.html.core/plugin.properties b/bundles/org.eclipse.wst.html.core/plugin.properties index 02144aae5d..602719c441 100644 --- a/bundles/org.eclipse.wst.html.core/plugin.properties +++ b/bundles/org.eclipse.wst.html.core/plugin.properties @@ -14,4 +14,6 @@ Structured_HTML_Document_Factory_Extension.name=Structured HTML Document Factory HTML_Content_Type_Extension_Element.name=HTML _taskMarker.name=HTML Task _validationMarker.name=HTML Problem -HTML_Syntax_Validator.name=HTML Syntax Validator
\ No newline at end of file +HTML_Syntax_Validator.name=HTML Syntax Validator +CustomHtmlTagValidator.name=External Validator For Custom HTML Tags +CustomHtmlAttributeValidator.name=External Validator For Custom HTML Attributes diff --git a/bundles/org.eclipse.wst.html.core/plugin.xml b/bundles/org.eclipse.wst.html.core/plugin.xml index d554b56d92..df9e8d268c 100644 --- a/bundles/org.eclipse.wst.html.core/plugin.xml +++ b/bundles/org.eclipse.wst.html.core/plugin.xml @@ -1,6 +1,8 @@ <?xml version="1.0" encoding="UTF-8"?> <?eclipse version="3.0"?> <plugin> + <extension-point id="customTagValidator" name="%CustomHtmlTagValidator.name" schema="schema/customTagValidator.exsd"/> + <extension-point id="customAttributeValidator" name="%CustomHtmlAttributeValidator.name" schema="schema/customAttributeValidator.exsd"/> <extension point="org.eclipse.wst.sse.core.modelHandler"> <modelHandler diff --git a/bundles/org.eclipse.wst.html.core/pom.xml b/bundles/org.eclipse.wst.html.core/pom.xml index 3e76832e81..e60bc75b2a 100644 --- a/bundles/org.eclipse.wst.html.core/pom.xml +++ b/bundles/org.eclipse.wst.html.core/pom.xml @@ -21,6 +21,6 @@ <groupId>org.eclipse.webtools.sourceediting</groupId> <artifactId>org.eclipse.wst.html.core</artifactId> - <version>1.1.802-SNAPSHOT</version> + <version>1.2.0-SNAPSHOT</version> <packaging>eclipse-plugin</packaging> </project> diff --git a/bundles/org.eclipse.wst.html.core/schema/customAttributeValidator.exsd b/bundles/org.eclipse.wst.html.core/schema/customAttributeValidator.exsd new file mode 100644 index 0000000000..b4a15da9f7 --- /dev/null +++ b/bundles/org.eclipse.wst.html.core/schema/customAttributeValidator.exsd @@ -0,0 +1,136 @@ +<?xml version='1.0' encoding='UTF-8'?> +<!-- Schema file written by PDE --> +<schema targetNamespace="org.eclipse.wst.html.core" xmlns="http://www.w3.org/2001/XMLSchema"> +<annotation> + <appInfo> + <meta.schema plugin="org.eclipse.wst.html.core" id="syntaxValidator" name="Validator"/> + </appInfo> + <documentation> + Extension point which allows to add external validators for HTML5-like attributes. + </documentation> + </annotation> + + <element name="extension"> + <annotation> + <appInfo> + <meta.element /> + </appInfo> + </annotation> + <complexType> + <sequence minOccurs="1" maxOccurs="unbounded"> + <element ref="validator" minOccurs="1" maxOccurs="unbounded"/> + </sequence> + <attribute name="point" type="string" use="required"> + <annotation> + <documentation> + + </documentation> + </annotation> + </attribute> + <attribute name="id" type="string"> + <annotation> + <documentation> + + </documentation> + </annotation> + </attribute> + <attribute name="name" type="string"> + <annotation> + <documentation> + + </documentation> + <appInfo> + <meta.attribute translatable="true"/> + </appInfo> + </annotation> + </attribute> + </complexType> + </element> + + <element name="validator"> + <complexType> + <attribute name="class" type="string" use="required"> + <annotation> + <documentation> + + </documentation> + <appInfo> + <meta.attribute kind="java" basedOn="org.eclipse.wst.html.core.internal.validate.extension.IHTMLCustomAttributeValidator:"/> + </appInfo> + </annotation> + </attribute> + </complexType> + </element> + + <annotation> + <appInfo> + <meta.section type="since"/> + </appInfo> + <documentation> + [Enter the first release in which this extension point appears.] + </documentation> + </annotation> + + <annotation> + <appInfo> + <meta.section type="examples"/> + </appInfo> + <documentation> + Extension point for validating custom html attributes. Only one error message will be displayed for each validated attribute. +<pre> + <extension point="org.eclipse.wst.html.core.syntaxValidator"> + <validator class="org.package.YourValidator"></validator> + </extension> +</pre> + +YourValidator should implement IHTMLCustomAttributeValidator + +<pre> +public class YourValidator impements IHTMLCustomAttributeValidator{ + + public boolean canValidate(IDOMElement target) { + if (target.getLocalName().startsWith("tag")) { + return true; + } + return false; + } + + public void init() { + //called only once while validator was loaded + } + + public ValidationMessage validateAttribute(IDOMElement target, String attrName) { + String tagName = target.getLocalName(); + if ("tag".equals(tagName)) { + if (attrName.startsWith("attr")) { + Segment segment = CustomValidatorUtil.getAttributeSegment((IDOMNode)target.getAttributeNode(attrName), ATTR_REGION_NAME); + return new ValidationMessage("Attribute started with attr is not allowed", segment.getOffset(), segment.getLength(), ValidationMessage.ERROR); + } + } + return null; +} +} +</pre> + </documentation> + </annotation> + + <annotation> + <appInfo> + <meta.section type="apiinfo"/> + </appInfo> + <documentation> + [Enter API information here.] + </documentation> + </annotation> + + <annotation> + <appInfo> + <meta.section type="implementation"/> + </appInfo> + <documentation> + [Enter information about supplied implementation of this extension point.] + </documentation> + </annotation> + + +</schema> diff --git a/bundles/org.eclipse.wst.html.core/schema/customTagValidator.exsd b/bundles/org.eclipse.wst.html.core/schema/customTagValidator.exsd new file mode 100644 index 0000000000..303c55a79d --- /dev/null +++ b/bundles/org.eclipse.wst.html.core/schema/customTagValidator.exsd @@ -0,0 +1,134 @@ +<?xml version='1.0' encoding='UTF-8'?> +<!-- Schema file written by PDE --> +<schema targetNamespace="org.eclipse.wst.html.core" xmlns="http://www.w3.org/2001/XMLSchema"> +<annotation> + <appInfo> + <meta.schema plugin="org.eclipse.wst.html.core" id="syntaxValidator" name="Validator"/> + </appInfo> + <documentation> + Extension point which allows to add external validators for HTML5-like tags. + </documentation> + </annotation> + + <element name="extension"> + <annotation> + <appInfo> + <meta.element /> + </appInfo> + </annotation> + <complexType> + <sequence minOccurs="1" maxOccurs="unbounded"> + <element ref="validator" minOccurs="1" maxOccurs="unbounded"/> + </sequence> + <attribute name="point" type="string" use="required"> + <annotation> + <documentation> + + </documentation> + </annotation> + </attribute> + <attribute name="id" type="string"> + <annotation> + <documentation> + + </documentation> + </annotation> + </attribute> + <attribute name="name" type="string"> + <annotation> + <documentation> + + </documentation> + <appInfo> + <meta.attribute translatable="true"/> + </appInfo> + </annotation> + </attribute> + </complexType> + </element> + + <element name="validator"> + <complexType> + <attribute name="class" type="string" use="required"> + <annotation> + <documentation> + + </documentation> + <appInfo> + <meta.attribute kind="java" basedOn="org.eclipse.wst.html.core.internal.validate.extension.IHTMLCustomTagValidator:"/> + </appInfo> + </annotation> + </attribute> + </complexType> + </element> + + <annotation> + <appInfo> + <meta.section type="since"/> + </appInfo> + <documentation> + [Enter the first release in which this extension point appears.] + </documentation> + </annotation> + + <annotation> + <appInfo> + <meta.section type="examples"/> + </appInfo> + <documentation> + Extension point for validating custom html tags. Only one error message will be displayed for each validated tag. +<pre> + <extension point="org.eclipse.wst.html.core.syntaxValidator"> + <validator class="org.package.YourValidator"></validator> + </extension> +</pre> + +YourValidator should implement IHTMLCustomTagValidator + +<pre> +public class YourValidator impements IHTMLCustomTagValidator{ + + public boolean canValidate(IDOMElement target) { + if (target.getLocalName().startsWith("tag")) { + return true; + } + return false; + } + + public void init() { + //called only once while validator was loaded + } + + public ValidationMessage validateTag(IDOMElement target) { + String tagName = target.getLocalName(); + if (tagName.contains("error")) { + Segment segment = CustomValidatorUtil.getTagSegment(target, SEG_START_TAG_NAME); + return new ValidationMessage("This is error tag", segment.getOffset(), segment.getLength(), ValidationMessage.ERROR); + } + return null; + } +} +</pre> + </documentation> + </annotation> + + <annotation> + <appInfo> + <meta.section type="apiinfo"/> + </appInfo> + <documentation> + [Enter API information here.] + </documentation> + </annotation> + + <annotation> + <appInfo> + <meta.section type="implementation"/> + </appInfo> + <documentation> + [Enter information about supplied implementation of this extension point.] + </documentation> + </annotation> + + +</schema> diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/validate/CustomHTMLAttributeValidatorExtensionLoader.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/validate/CustomHTMLAttributeValidatorExtensionLoader.java new file mode 100644 index 0000000000..e900ee4a1e --- /dev/null +++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/validate/CustomHTMLAttributeValidatorExtensionLoader.java @@ -0,0 +1,41 @@ +/******************************************************************************* + * Copyright (c) 2016 Red Hat, Inc. + * 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat, Inc. - initial API and implementation + *******************************************************************************/ +package org.eclipse.wst.html.core.internal.validate; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.core.runtime.IConfigurationElement; +import org.eclipse.core.runtime.Platform; + +public class CustomHTMLAttributeValidatorExtensionLoader { +private List<IConfigurationElement> validators; + + public List<IConfigurationElement> getValidators() { + return validators; + } + + private CustomHTMLAttributeValidatorExtensionLoader() { + validators = new ArrayList<IConfigurationElement>(); + IConfigurationElement[] configurationElements = Platform.getExtensionRegistry().getConfigurationElementsFor("org.eclipse.wst.html.core.customAttributeValidator"); + for (IConfigurationElement e : configurationElements) { + validators.add(e); + } + } + + private static class UnknownValidatorExtensionLoaderHolder { + public static final CustomHTMLAttributeValidatorExtensionLoader instance = new CustomHTMLAttributeValidatorExtensionLoader(); + } + + public static CustomHTMLAttributeValidatorExtensionLoader getInstance() { + return UnknownValidatorExtensionLoaderHolder.instance; + } +} diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/validate/CustomHTMLTagValidatorExtensionLoader.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/validate/CustomHTMLTagValidatorExtensionLoader.java new file mode 100644 index 0000000000..6c6c4301fd --- /dev/null +++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/validate/CustomHTMLTagValidatorExtensionLoader.java @@ -0,0 +1,41 @@ +/******************************************************************************* + * Copyright (c) 2016 Red Hat, Inc. + * 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat, Inc. - initial API and implementation + *******************************************************************************/ +package org.eclipse.wst.html.core.internal.validate; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.core.runtime.IConfigurationElement; +import org.eclipse.core.runtime.Platform; + +public class CustomHTMLTagValidatorExtensionLoader { + private List<IConfigurationElement> validators; + + public List<IConfigurationElement> getValidators() { + return validators; + } + + private CustomHTMLTagValidatorExtensionLoader() { + validators = new ArrayList<IConfigurationElement>(); + IConfigurationElement[] configurationElements = Platform.getExtensionRegistry().getConfigurationElementsFor("org.eclipse.wst.html.core.customTagValidator"); + for (IConfigurationElement e : configurationElements) { + validators.add(e); + } + } + + private static class UnknownValidatorExtensionLoaderHolder { + public static final CustomHTMLTagValidatorExtensionLoader instance = new CustomHTMLTagValidatorExtensionLoader(); + } + + public static CustomHTMLTagValidatorExtensionLoader getInstance() { + return UnknownValidatorExtensionLoaderHolder.instance; + } +} diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/validate/FMUtil.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/validate/FMUtil.java index f3ee02a826..433c4bb223 100644 --- a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/validate/FMUtil.java +++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/validate/FMUtil.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2004, 2008 IBM Corporation and others. + * Copyright (c) 2004, 2016 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 @@ -19,7 +19,7 @@ import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegionList; import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode; import org.eclipse.wst.xml.core.internal.regions.DOMRegionContext; -final class FMUtil { +public final class FMUtil { public final static int SEG_NONE = 0; public final static int SEG_WHOLE_TAG = 1; 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 1e200cc208..d58e883285 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, 2014 IBM Corporation and others. + * Copyright (c) 2004, 2016 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,9 +7,11 @@ * * Contributors: * IBM Corporation - initial API and implementation + * Red Hat, Inc. - external validator extension *******************************************************************************/ package org.eclipse.wst.html.core.internal.validate; +import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; @@ -23,7 +25,9 @@ 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.CoreException; import org.eclipse.core.runtime.IAdaptable; +import org.eclipse.core.runtime.IConfigurationElement; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.Platform; @@ -32,14 +36,18 @@ 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.Logger; import org.eclipse.wst.html.core.internal.document.HTMLDocumentTypeConstants; import org.eclipse.wst.html.core.internal.preferences.HTMLCorePreferenceNames; +import org.eclipse.wst.html.core.validate.extension.IHTMLCustomAttributeValidator; 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.IStructuredDocument; import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion; import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion; import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegionContainer; import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegionList; +import org.eclipse.wst.sse.core.internal.validate.ValidationMessage; import org.eclipse.wst.xml.core.internal.contentmodel.CMAttributeDeclaration; import org.eclipse.wst.xml.core.internal.contentmodel.CMDataType; import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration; @@ -58,8 +66,8 @@ import org.w3c.dom.NamedNodeMap; public class HTMLAttributeValidator extends PrimeValidator { private static final String JAVASCRIPT_PREFIX = "javascript:"; //$NON-NLS-1$ - private static final int REGION_NAME = 1; - private static final int REGION_VALUE = 2; + public static final int REGION_NAME = 1; + public static final int REGION_VALUE = 2; // <<D210422 private static final char SINGLE_QUOTE = '\''; private static final char DOUBLE_QUOTE = '\"'; @@ -81,6 +89,7 @@ public class HTMLAttributeValidator extends PrimeValidator { private static final String ATTR_NAME_WAI_ARIA = "aria-"; //$NON-NLS-1$ private static final int ATTR_NAME_WAI_ARIA_LENGTH = ATTR_NAME_WAI_ARIA.length(); + private List<IHTMLCustomAttributeValidator> externalValidators; /** * HTMLAttributeValidator constructor comment. @@ -92,7 +101,7 @@ public class HTMLAttributeValidator extends PrimeValidator { /** */ - private Segment getErrorSegment(IDOMNode errorNode, int regionType) { + public static Segment getErrorSegment(IDOMNode errorNode, int regionType) { ITextRegion rgn = null; switch (regionType) { case REGION_NAME : @@ -137,212 +146,266 @@ public class HTMLAttributeValidator extends PrimeValidator { if (CMUtil.isForeign(target)) return; CMElementDeclaration edec = CMUtil.getDeclaration(target); - if (edec == null) - return; - CMNamedNodeMap declarations = edec.getAttributes(); - - List modelQueryNodes = null; - NamedNodeMap attrs = target.getAttributes(); - for (int i = 0; i < attrs.getLength(); i++) { - int rgnType = REGION_NAME; - int state = ErrorState.NONE_ERROR; - Attr a = (Attr) attrs.item(i); - // D203637; If the target attr has prefix, the validator should - // not - // warn about it. That is, just ignore. It is able to check - // whether - // an attr has prefix or not by calling XMLAttr#isGlobalAttr(). - // When a attr has prefix (not global), it returns false. - boolean isXMLAttr = a instanceof IDOMAttr; - if (isXMLAttr) { - IDOMAttr xmlattr = (IDOMAttr) a; - if (!xmlattr.isGlobalAttr() || xmlattr.getNameRegion() instanceof ITextRegionContainer) - continue; // skip futher validation and begin next loop. - } - - CMAttributeDeclaration adec = (CMAttributeDeclaration) declarations.getNamedItem(a.getName()); - final String attrName = a.getName().toLowerCase(Locale.US); - /* 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); - - - 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 (edec == null) { + NamedNodeMap attrs = target.getAttributes(); + // unknown tag - go to validators from extension point + for (int i = 0; i < attrs.getLength(); i++) { + Attr a = (Attr) attrs.item(i); + final String attrName = a.getName().toLowerCase(Locale.US); + // Check for user-defined exclusions + if (shouldValidateAttributeName(target, attrName)) { + validateWithExtension(target, a, attrName); } } - - 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) || - (attrName.startsWith(ATTR_NAME_WAI_ARIA) && attrName.length() > ATTR_NAME_WAI_ARIA_LENGTH)) { - if (isHTML5(target)) - continue; - } - // Check for user-defined exclusions - 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 - // region - if (!hasNestedRegion(((IDOMNode) a).getNameRegion())) { - rgnType = REGION_NAME; - state = ErrorState.UNDEFINED_NAME_ERROR; + } else { + CMNamedNodeMap declarations = edec.getAttributes(); + + List modelQueryNodes = null; + NamedNodeMap attrs = target.getAttributes(); + for (int i = 0; i < attrs.getLength(); i++) { + int rgnType = REGION_NAME; + int state = ErrorState.NONE_ERROR; + Attr a = (Attr) attrs.item(i); + // D203637; If the target attr has prefix, the validator should + // not + // warn about it. That is, just ignore. It is able to check + // whether + // an attr has prefix or not by calling XMLAttr#isGlobalAttr(). + // When a attr has prefix (not global), it returns false. + boolean isXMLAttr = a instanceof IDOMAttr; + if (isXMLAttr) { + IDOMAttr xmlattr = (IDOMAttr) a; + if (!xmlattr.isGlobalAttr() || xmlattr.getNameRegion() instanceof ITextRegionContainer) + continue; // skip futher validation and begin next loop. } - } else { - // The attr declaration was found. - // At 1st, the name should be checked. - if (CMUtil.isObsolete(adec)){ - state = ErrorState.OBSOLETE_ATTR_NAME_ERROR; + + CMAttributeDeclaration adec = (CMAttributeDeclaration) declarations.getNamedItem(a.getName()); + final String attrName = a.getName().toLowerCase(Locale.US); + /* 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); + + + 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 (CMUtil.isHTML(edec) && (!CMUtil.isXHTML(edec))) { - // If the target element is pure HTML (not XHTML), some - // attributes - // might be written in boolean format. It should be check - // specifically. - if (CMUtil.isBooleanAttr(adec) && ((IDOMAttr) a).hasNameOnly()) - continue; // OK, keep going. No more check is needed - // against this attr. + + 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) || + (attrName.startsWith(ATTR_NAME_WAI_ARIA) && attrName.length() > ATTR_NAME_WAI_ARIA_LENGTH)) { + if (isHTML5(target)) + continue; + } + // Check for user-defined exclusions + 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 + // region + + // Then look into extension point for external validator + validateWithExtension(target, a, attrName); } else { - // If the target is other than pure HTML (JSP or XHTML), - // the name - // must be checked exactly (ie in case sensitive way). - String actual = a.getName(); - String desired = adec.getAttrName(); - if (!actual.equals(desired)) { // case mismatch - rgnType = REGION_NAME; - state = ErrorState.MISMATCHED_ERROR; + // The attr declaration was found. + // At 1st, the name should be checked. + if (CMUtil.isObsolete(adec)){ + state = ErrorState.OBSOLETE_ATTR_NAME_ERROR; } - } - // Then, the value must be checked. - if (state == ErrorState.NONE_ERROR) { // Need more check. - // Now, the value should be checked, if the type is ENUM. - CMDataType attrType = adec.getAttrType(); - if (a instanceof IDOMAttr) { - final ITextRegion region = ((IDOMAttr) a).getEqualRegion(); - if (region == null) { + if (CMUtil.isHTML(edec) && (!CMUtil.isXHTML(edec))) { + // If the target element is pure HTML (not XHTML), some + // attributes + // might be written in boolean format. It should be check + // specifically. + if (CMUtil.isBooleanAttr(adec) && ((IDOMAttr) a).hasNameOnly()) + continue; // OK, keep going. No more check is needed + // against this attr. + } else { + // If the target is other than pure HTML (JSP or XHTML), + // the name + // must be checked exactly (ie in case sensitive way). + String actual = a.getName(); + String desired = adec.getAttrName(); + if (!actual.equals(desired)) { // case mismatch rgnType = REGION_NAME; - state = ErrorState.MISSING_ATTR_VALUE_EQUALS_ERROR; + state = ErrorState.MISMATCHED_ERROR; } } - String actualValue = a.getValue(); - if (attrType.getImpliedValueKind() == CMDataType.IMPLIED_VALUE_FIXED) { - // Check FIXED value. - String validValue = attrType.getImpliedValue(); - if (!actualValue.equals(validValue)) { - rgnType = REGION_VALUE; - state = ErrorState.UNDEFINED_VALUE_ERROR; + // Then, the value must be checked. + if (state == ErrorState.NONE_ERROR) { // Need more check. + // Now, the value should be checked, if the type is ENUM. + CMDataType attrType = adec.getAttrType(); + if (a instanceof IDOMAttr) { + final ITextRegion region = ((IDOMAttr) a).getEqualRegion(); + if (region == null) { + rgnType = REGION_NAME; + state = ErrorState.MISSING_ATTR_VALUE_EQUALS_ERROR; + } } - } - else if (CMDataType.URI.equals(attrType.getDataTypeName())) { - if (actualValue.indexOf('#') < 0 && actualValue.indexOf(":/") < 0 && !actualValue.toLowerCase(Locale.ENGLISH).startsWith(JAVASCRIPT_PREFIX) && CMUtil.isHTML(edec)) { //$NON-NLS-1$ //$NON-NLS-2$ - IStructuredDocumentRegion start = ((IDOMNode) node).getStartStructuredDocumentRegion(); - // roundabout start tag check - if (start != null && start.getFirstRegion().getTextLength() == 1) { - // only check when we have a way to set dependencies - Collection dependencies = (Collection) ((IDOMNode) ((IDOMNode) node).getOwnerDocument()).getUserData(HTMLValidationAdapterFactory.DEPENDENCIES); - if (dependencies != null) { - IPath basePath = new Path(((IDOMNode) node).getModel().getBaseLocation()); - if (basePath.segmentCount() > 1) { - IPath path = ModuleCoreSupport.resolve(basePath, actualValue); - IResource found = ResourcesPlugin.getWorkspace().getRoot().findMember(path); - if (found != null) { - dependencies.add(found); - } - } - } + String actualValue = a.getValue(); + if (attrType.getImpliedValueKind() == CMDataType.IMPLIED_VALUE_FIXED) { + // Check FIXED value. + String validValue = attrType.getImpliedValue(); + if (!actualValue.equals(validValue)) { + rgnType = REGION_VALUE; + state = ErrorState.UNDEFINED_VALUE_ERROR; } } - } - else if (CMDataType.ENUM.equals(attrType.getDataTypeName())) { - /* - * Check current value is valid among a known list. - * There may be enumerated values provided even when - * the datatype is not ENUM, but we'll only validate - * against that list if the type matches. - */ - String[] enumeratedValues = attrType.getEnumeratedValues(); - // several candidates are found. - boolean found = false; - for (int j = 0; j < enumeratedValues.length; j++) { - // At 1st, compare ignoring case. - if (actualValue.equalsIgnoreCase(enumeratedValues[j])) { - found = true; - if (CMUtil.isCaseSensitive(edec) && (!actualValue.equals(enumeratedValues[j]))) { - rgnType = REGION_VALUE; - state = ErrorState.MISMATCHED_VALUE_ERROR; + else if (CMDataType.URI.equals(attrType.getDataTypeName())) { + if (actualValue.indexOf('#') < 0 && actualValue.indexOf(":/") < 0 && !actualValue.toLowerCase(Locale.ENGLISH).startsWith(JAVASCRIPT_PREFIX) && CMUtil.isHTML(edec)) { //$NON-NLS-1$ //$NON-NLS-2$ + IStructuredDocumentRegion start = ((IDOMNode) node).getStartStructuredDocumentRegion(); + // roundabout start tag check + if (start != null && start.getFirstRegion().getTextLength() == 1) { + // only check when we have a way to set dependencies + Collection dependencies = (Collection) ((IDOMNode) ((IDOMNode) node).getOwnerDocument()).getUserData(HTMLValidationAdapterFactory.DEPENDENCIES); + if (dependencies != null) { + IPath basePath = new Path(((IDOMNode) node).getModel().getBaseLocation()); + if (basePath.segmentCount() > 1) { + IPath path = ModuleCoreSupport.resolve(basePath, actualValue); + IResource found = ResourcesPlugin.getWorkspace().getRoot().findMember(path); + if (found != null) { + dependencies.add(found); + } + } + } } - break; // exit the loop. } } - if (!found) { - // retrieve and check extended values (retrieval can call extensions, which may take longer) - String[] modelQueryExtensionValues = ModelQueryUtil.getModelQuery(target.getOwnerDocument()).getPossibleDataTypeValues((Element) node, adec); - // copied loop from above - for (int j = 0; j < modelQueryExtensionValues.length; j++) { + else if (CMDataType.ENUM.equals(attrType.getDataTypeName())) { + /* + * Check current value is valid among a known list. + * There may be enumerated values provided even when + * the datatype is not ENUM, but we'll only validate + * against that list if the type matches. + */ + String[] enumeratedValues = attrType.getEnumeratedValues(); + // several candidates are found. + boolean found = false; + for (int j = 0; j < enumeratedValues.length; j++) { // At 1st, compare ignoring case. - if (actualValue.equalsIgnoreCase(modelQueryExtensionValues[j])) { + if (actualValue.equalsIgnoreCase(enumeratedValues[j])) { found = true; - if (CMUtil.isCaseSensitive(edec) && (!actualValue.equals(modelQueryExtensionValues[j]))) { + if (CMUtil.isCaseSensitive(edec) && (!actualValue.equals(enumeratedValues[j]))) { rgnType = REGION_VALUE; state = ErrorState.MISMATCHED_VALUE_ERROR; } break; // exit the loop. } } - // No candidate was found. That is, - // actualValue is invalid. - // but not regard it as undefined value if it - // includes nested region. - if (!hasNestedRegion(((IDOMNode) a).getValueRegion())) { - rgnType = REGION_VALUE; - state = ErrorState.UNDEFINED_VALUE_ERROR; + if (!found) { + // retrieve and check extended values (retrieval can call extensions, which may take longer) + String[] modelQueryExtensionValues = ModelQueryUtil.getModelQuery(target.getOwnerDocument()).getPossibleDataTypeValues((Element) node, adec); + // copied loop from above + for (int j = 0; j < modelQueryExtensionValues.length; j++) { + // At 1st, compare ignoring case. + if (actualValue.equalsIgnoreCase(modelQueryExtensionValues[j])) { + found = true; + if (CMUtil.isCaseSensitive(edec) && (!actualValue.equals(modelQueryExtensionValues[j]))) { + rgnType = REGION_VALUE; + state = ErrorState.MISMATCHED_VALUE_ERROR; + } + break; // exit the loop. + } + } + // No candidate was found. That is, + // actualValue is invalid. + // but not regard it as undefined value if it + // includes nested region. + if (!hasNestedRegion(((IDOMNode) a).getValueRegion())) { + rgnType = REGION_VALUE; + state = ErrorState.UNDEFINED_VALUE_ERROR; + } } } } - } - // <<D210422 - if (state == ErrorState.NONE_ERROR) { // Need more check. - if (isXMLAttr) { - String source = ((IDOMAttr) a).getValueRegionText(); - if (source != null) { - char firstChar = source.charAt(0); - char lastChar = source.charAt(source.length() - 1); - boolean unclosedAttr = false; - if (isQuote(firstChar) || isQuote(lastChar)) { - if (lastChar != firstChar) { - unclosedAttr = true; + // <<D210422 + if (state == ErrorState.NONE_ERROR) { // Need more check. + if (isXMLAttr) { + String source = ((IDOMAttr) a).getValueRegionText(); + if (source != null) { + char firstChar = source.charAt(0); + char lastChar = source.charAt(source.length() - 1); + boolean unclosedAttr = false; + if (isQuote(firstChar) || isQuote(lastChar)) { + if (lastChar != firstChar) { + unclosedAttr = true; + } } - } - else{ - if (CMUtil.isXHTML(edec)){ - unclosedAttr = true; + else{ + if (CMUtil.isXHTML(edec)){ + unclosedAttr = true; + } + } + if (unclosedAttr){ + rgnType = REGION_VALUE; + state = ErrorState.UNCLOSED_ATTR_VALUE; } - } - if (unclosedAttr){ - rgnType = REGION_VALUE; - state = ErrorState.UNCLOSED_ATTR_VALUE; } } } + // D210422 + } + if (state != ErrorState.NONE_ERROR) { + Segment seg = getErrorSegment((IDOMNode) a, rgnType); + if (seg != null) + reporter.report(new ErrorInfoImpl(state, seg, a)); + } + } + } + } + + private void initValidators(IStructuredDocument doc) { + externalValidators = new ArrayList<IHTMLCustomAttributeValidator>(); + for (IConfigurationElement e : CustomHTMLAttributeValidatorExtensionLoader.getInstance().getValidators()) { + IHTMLCustomAttributeValidator validator; + try { + validator = (IHTMLCustomAttributeValidator) e.createExecutableExtension("class"); + validator.init(doc); + externalValidators.add(validator); + } catch (CoreException e1) { + Logger.logException(e1); + } + } + } + + private void validateWithExtension(Element target, Attr a, String attrName) { + boolean validated = false; + if (externalValidators == null) { + initValidators(((IDOMElement)target).getStructuredDocument()); + } + + for (IHTMLCustomAttributeValidator v : externalValidators) { + try { + if (v.canValidate((IDOMElement) target, attrName)) { + validated = true; + ValidationMessage result = v.validateAttribute((IDOMElement) target, attrName); + if (result != null) { + // report only one validation result or nothing if all reports are null + reporter.report(result); + break; + } } - // D210422 + } catch (Throwable t) { + Logger.logException(t); } - if (state != ErrorState.NONE_ERROR) { - Segment seg = getErrorSegment((IDOMNode) a, rgnType); + } + if (!validated) { + if (!hasNestedRegion(((IDOMNode) a).getNameRegion())) { + Segment seg = getErrorSegment((IDOMNode) a, REGION_NAME); if (seg != null) - reporter.report(new ErrorInfoImpl(state, seg, a)); + reporter.report(new ErrorInfoImpl(ErrorState.UNDEFINED_NAME_ERROR, seg, a)); } } } - + /** * True if container has nested regions, meaning container is probably too * complicated (like JSP regions) to validate with this validator. diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/validate/SyntaxValidator.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/validate/SyntaxValidator.java index 7023e2c2b4..73413f4227 100644 --- a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/validate/SyntaxValidator.java +++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/internal/validate/SyntaxValidator.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2004, 2014 IBM Corporation and others. + * Copyright (c) 2004, 2016 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,36 +7,45 @@ * * Contributors: * IBM Corporation - initial API and implementation + * Red Hat, Inc. - external validator extension *******************************************************************************/ package org.eclipse.wst.html.core.internal.validate; +import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; +import java.util.List; 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.runtime.CoreException; import org.eclipse.core.runtime.IAdaptable; +import org.eclipse.core.runtime.IConfigurationElement; 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.Logger; import org.eclipse.wst.html.core.internal.contentmodel.HTMLElementDeclaration; import org.eclipse.wst.html.core.internal.contentmodel.HTMLPropertyDeclaration; import org.eclipse.wst.html.core.internal.document.HTMLDocumentTypeEntry; import org.eclipse.wst.html.core.internal.document.HTMLDocumentTypeRegistry; import org.eclipse.wst.html.core.internal.preferences.HTMLCorePreferenceNames; import org.eclipse.wst.html.core.internal.provisional.HTML50Namespace; +import org.eclipse.wst.html.core.validate.extension.IHTMLCustomTagValidator; import org.eclipse.wst.sse.core.internal.provisional.IndexedRegion; +import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument; import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion; import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion; import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegionList; import org.eclipse.wst.sse.core.internal.validate.ErrorInfo; +import org.eclipse.wst.sse.core.internal.validate.ValidationMessage; import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration; import org.eclipse.wst.xml.core.internal.document.InvalidCharacterException; import org.eclipse.wst.xml.core.internal.document.SourceValidator; @@ -53,7 +62,8 @@ import org.w3c.dom.Node; class SyntaxValidator extends PrimeValidator implements ErrorState { private IPreferencesService fPreferenceService; private static Map fIgnorePatterns = new HashMap(); // A storage for ignore patterns (instances of StringMatcher) - + private List<IHTMLCustomTagValidator> externalValidators; + static private boolean isValidRegion(ITextRegion rgn) { String type = rgn.getType(); if (type == null) @@ -324,8 +334,31 @@ class SyntaxValidator extends PrimeValidator implements ErrorState { } else { if (shouldValidateElementName(info.target)) { - Segment errorSeg = FMUtil.getSegment(info.target, FMUtil.SEG_START_TAG_NAME); - report(UNDEFINED_NAME_ERROR, errorSeg, info.target); + // not excluded in preferences - check for extension point + boolean validated = false; + + if (externalValidators == null) { + initValidators(info.target.getStructuredDocument()); + } + for (IHTMLCustomTagValidator v : externalValidators) { + try { + if (v.canValidate(info.target)) { + validated = true; + ValidationMessage result = v.validateTag(info.target); + if(result != null) { + // report only one validation result or nothing if all reports are null + reporter.report(result); + break; + } + } + } catch (Throwable t) { + Logger.logException(t); + } + } + if (!validated) { + Segment errorSeg = FMUtil.getSegment(info.target, FMUtil.SEG_START_TAG_NAME); + report(UNDEFINED_NAME_ERROR, errorSeg, info.target); + } } } } @@ -339,6 +372,20 @@ class SyntaxValidator extends PrimeValidator implements ErrorState { } } + private void initValidators(IStructuredDocument doc) { + externalValidators = new ArrayList<IHTMLCustomTagValidator>(); + for (IConfigurationElement e : CustomHTMLTagValidatorExtensionLoader.getInstance().getValidators()) { + IHTMLCustomTagValidator validator; + try { + validator = (IHTMLCustomTagValidator) e.createExecutableExtension("class"); + validator.init(doc); + externalValidators.add(validator); + } catch (CoreException e1) { + Logger.logException(e1); + } + } + } + private boolean shouldValidateElementName(Element target) { Object adapter = (target instanceof IAdaptable ? ((IAdaptable)target).getAdapter(IResource.class) : null); IProject project = (adapter instanceof IResource ? ((IResource)adapter).getProject() : null); diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/validate/extension/CustomValidatorUtil.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/validate/extension/CustomValidatorUtil.java new file mode 100644 index 0000000000..ce400b2679 --- /dev/null +++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/validate/extension/CustomValidatorUtil.java @@ -0,0 +1,53 @@ +/******************************************************************************* + * Copyright (c) 2016 Red Hat, Inc. + * 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat, Inc. - initial API and implementation + *******************************************************************************/ +package org.eclipse.wst.html.core.validate.extension; + +import org.eclipse.wst.html.core.internal.validate.FMUtil; +import org.eclipse.wst.html.core.internal.validate.HTMLAttributeValidator; +import org.eclipse.wst.html.core.internal.validate.Segment; +import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode; + +/** + * @since 1.2 + */ +public class CustomValidatorUtil { + public static final int ATTR_REGION_NAME = HTMLAttributeValidator.REGION_NAME; + public static final int ATTR_REGION_VALUE = HTMLAttributeValidator.REGION_VALUE; + + public final static int TAG_SEG_NONE = FMUtil.SEG_NONE; + public final static int SEG_WHOLE_TAG = FMUtil.SEG_WHOLE_TAG; + public final static int SEG_START_TAG = FMUtil.SEG_START_TAG; + public final static int SEG_END_TAG = FMUtil.SEG_END_TAG; + public final static int SEG_START_TAG_NAME = FMUtil.SEG_START_TAG_NAME; + public final static int SEG_END_TAG_NAME = FMUtil.SEG_END_TAG_NAME; + + /** + * Error segment for attribute validation + * + * @param errorNode attribute with error + * @param regionType type of region where error marker should be placed + * @return {@link Segment} which determines error marker location + */ + public final static Segment getAttributeSegment(IDOMNode errorNode, int regionType) { + return HTMLAttributeValidator.getErrorSegment(errorNode, regionType); + } + + /** + * Error segment for tag validation + * + * @param target tag with error + * @param segType type of segment where error marker should be placed + * @return {@link Segment} which determines error marker location + */ + public final static Segment getTagSegment(IDOMNode target, int segType) { + return FMUtil.getSegment(target, segType); + } +} diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/validate/extension/IHTMLCustomAttributeValidator.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/validate/extension/IHTMLCustomAttributeValidator.java new file mode 100644 index 0000000000..ba4894bc16 --- /dev/null +++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/validate/extension/IHTMLCustomAttributeValidator.java @@ -0,0 +1,42 @@ +/******************************************************************************* + * Copyright (c) 2016 Red Hat, Inc. + * 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat, Inc. - initial API and implementation + *******************************************************************************/ +package org.eclipse.wst.html.core.validate.extension; + +import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument; +import org.eclipse.wst.sse.core.internal.validate.ValidationMessage; +import org.eclipse.wst.xml.core.internal.provisional.document.IDOMElement; + +/** + * @since 1.2 + */ +public interface IHTMLCustomAttributeValidator { + /** + * Validator initialization. This method is called before validator loading. + * + * @param doc validated document + */ + public void init(IStructuredDocument doc); + + /** + * + * @param target tag to be validated + * @return <code>true</code> if validator can validate tag + */ + public boolean canValidate(IDOMElement target, String attrName); + + /**Validates specified attribute of specified tag + * + * @param target tag to be validated + * @param attrName attribute to be validated + * @return <code>null</code> if no error happens or {@link ValidationMessage} with error message and error region + */ + public ValidationMessage validateAttribute(IDOMElement target, String attrName); +} diff --git a/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/validate/extension/IHTMLCustomTagValidator.java b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/validate/extension/IHTMLCustomTagValidator.java new file mode 100644 index 0000000000..f132f4f680 --- /dev/null +++ b/bundles/org.eclipse.wst.html.core/src/org/eclipse/wst/html/core/validate/extension/IHTMLCustomTagValidator.java @@ -0,0 +1,41 @@ +/******************************************************************************* + * Copyright (c) 2016 Red Hat, Inc. + * 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat, Inc. - initial API and implementation + *******************************************************************************/ +package org.eclipse.wst.html.core.validate.extension; + +import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument; +import org.eclipse.wst.sse.core.internal.validate.ValidationMessage; +import org.eclipse.wst.xml.core.internal.provisional.document.IDOMElement; + +/** + * @since 1.2 + */ +public interface IHTMLCustomTagValidator { + /** + * Validator initialization. This method is called only once during validator loading. + * + * @param doc validated document + */ + public void init(IStructuredDocument doc); + + /** + * + * @param target tag to be validated + * @return <code>true</code> if validator can validate tag + */ + public boolean canValidate(IDOMElement target); + + /**Validate specified tag + * + * @param target tag to be validated + * @return <code>null</code> if no error happens or {@link ValidationMessage} with error message and error region + */ + public ValidationMessage validateTag(IDOMElement target); +} diff --git a/bundles/org.eclipse.wst.html.ui/META-INF/MANIFEST.MF b/bundles/org.eclipse.wst.html.ui/META-INF/MANIFEST.MF index ac6978c871..2cadaf3d13 100644 --- a/bundles/org.eclipse.wst.html.ui/META-INF/MANIFEST.MF +++ b/bundles/org.eclipse.wst.html.ui/META-INF/MANIFEST.MF @@ -41,7 +41,7 @@ Require-Bundle: org.eclipse.ui.ide;bundle-version="[3.12.0,4.0.0)", org.eclipse.wst.css.ui;bundle-version="[1.0.1000,1.1.0)", org.eclipse.wst.sse.core;bundle-version="[1.1.900,1.2.0)", org.eclipse.wst.css.core;bundle-version="[1.1.800,1.2.0)", - org.eclipse.wst.html.core;bundle-version="[1.1.800,1.2.0)", + org.eclipse.wst.html.core;bundle-version="[1.1.800,1.3.0)", org.eclipse.wst.xml.core;bundle-version="[1.1.1000,1.2.0)", org.eclipse.core.resources;bundle-version="[3.11.0,4.0.0)", org.eclipse.core.runtime;bundle-version="[3.12.0,4.0.0)", diff --git a/tests/org.eclipse.wst.html.ui.tests/plugin.xml b/tests/org.eclipse.wst.html.ui.tests/plugin.xml index ff9dcb36f1..016dc5121b 100644 --- a/tests/org.eclipse.wst.html.ui.tests/plugin.xml +++ b/tests/org.eclipse.wst.html.ui.tests/plugin.xml @@ -11,5 +11,13 @@ id="org.eclipse.wst.html.ui.tests.viewer.ViewerTestHTML"> </view> </extension> - + <extension point="org.eclipse.wst.html.core.customTagValidator"> + <validator class="org.eclipse.wst.html.ui.tests.validation.CustomExtendedTagValidator"></validator> + </extension> + <extension point="org.eclipse.wst.html.core.customAttributeValidator"> + <validator class="org.eclipse.wst.html.ui.tests.validation.CustomExtendedAttributeValidator"></validator> + </extension> + <extension point="org.eclipse.wst.html.core.customAttributeValidator"> + <validator class="org.eclipse.wst.html.ui.tests.validation.CustomExtendedAttributeValidator2"></validator> + </extension> </plugin> diff --git a/tests/org.eclipse.wst.html.ui.tests/src/org/eclipse/wst/html/ui/tests/validation/CustomExtendedAttributeValidator.java b/tests/org.eclipse.wst.html.ui.tests/src/org/eclipse/wst/html/ui/tests/validation/CustomExtendedAttributeValidator.java new file mode 100644 index 0000000000..b99d857361 --- /dev/null +++ b/tests/org.eclipse.wst.html.ui.tests/src/org/eclipse/wst/html/ui/tests/validation/CustomExtendedAttributeValidator.java @@ -0,0 +1,47 @@ +/******************************************************************************* + * Copyright (c) 2016 Red Hat, Inc. + * 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat, Inc. - initial API and implementation + *******************************************************************************/ +package org.eclipse.wst.html.ui.tests.validation; + +import org.eclipse.wst.html.core.internal.validate.Segment; +import org.eclipse.wst.html.core.validate.extension.CustomValidatorUtil; +import org.eclipse.wst.html.core.validate.extension.IHTMLCustomAttributeValidator; +import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument; +import org.eclipse.wst.sse.core.internal.validate.ValidationMessage; +import org.eclipse.wst.xml.core.internal.provisional.document.IDOMElement; +import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode; + +public class CustomExtendedAttributeValidator implements IHTMLCustomAttributeValidator { + + public void init(IStructuredDocument doc) { + // do nothing + } + + public boolean canValidate(IDOMElement target, String attrName) { + if (target.getLocalName().startsWith("eclipse")) { + return true; + } + return false; + } + + + public ValidationMessage validateAttribute(IDOMElement target, String attrName) { + if ("plugins".equals(attrName)) { + try { + String attrValue = target.getAttribute(attrName); + Integer.parseInt(attrValue); + } catch (NumberFormatException e) { + Segment segment = CustomValidatorUtil.getAttributeSegment((IDOMNode)target.getAttributeNode(attrName), CustomValidatorUtil.ATTR_REGION_NAME); + return new ValidationMessage("Attribute should be integer", segment.getOffset(), segment.getLength(), ValidationMessage.ERROR); + } + } + return null; + } +} diff --git a/tests/org.eclipse.wst.html.ui.tests/src/org/eclipse/wst/html/ui/tests/validation/CustomExtendedAttributeValidator2.java b/tests/org.eclipse.wst.html.ui.tests/src/org/eclipse/wst/html/ui/tests/validation/CustomExtendedAttributeValidator2.java new file mode 100644 index 0000000000..123e966a10 --- /dev/null +++ b/tests/org.eclipse.wst.html.ui.tests/src/org/eclipse/wst/html/ui/tests/validation/CustomExtendedAttributeValidator2.java @@ -0,0 +1,39 @@ +/******************************************************************************* + * Copyright (c) 2016 Red Hat, Inc. + * 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat, Inc. - initial API and implementation + *******************************************************************************/ +package org.eclipse.wst.html.ui.tests.validation; + +import org.eclipse.wst.html.core.internal.validate.Segment; +import org.eclipse.wst.html.core.validate.extension.CustomValidatorUtil; +import org.eclipse.wst.html.core.validate.extension.IHTMLCustomAttributeValidator; +import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument; +import org.eclipse.wst.sse.core.internal.validate.ValidationMessage; +import org.eclipse.wst.xml.core.internal.provisional.document.IDOMElement; +import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode; + +public class CustomExtendedAttributeValidator2 implements IHTMLCustomAttributeValidator { + + public void init(IStructuredDocument doc) { + // do nothing + } + + public boolean canValidate(IDOMElement target, String attrName) { + return attrName.startsWith("pr-") ? true : false; + } + + public ValidationMessage validateAttribute(IDOMElement target, String attrName) { + if (attrName.startsWith("pr-")) { + return null; + } + Segment segment = CustomValidatorUtil.getAttributeSegment((IDOMNode)target.getAttributeNode(attrName), CustomValidatorUtil.ATTR_REGION_NAME); + return new ValidationMessage("Undefined attribute name", segment.getOffset(), segment.getLength(), ValidationMessage.WARNING); + } + +} diff --git a/tests/org.eclipse.wst.html.ui.tests/src/org/eclipse/wst/html/ui/tests/validation/CustomExtendedTagValidator.java b/tests/org.eclipse.wst.html.ui.tests/src/org/eclipse/wst/html/ui/tests/validation/CustomExtendedTagValidator.java new file mode 100644 index 0000000000..688656e39b --- /dev/null +++ b/tests/org.eclipse.wst.html.ui.tests/src/org/eclipse/wst/html/ui/tests/validation/CustomExtendedTagValidator.java @@ -0,0 +1,64 @@ +/******************************************************************************* + * Copyright (c) 2016 Red Hat, Inc. + * 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat, Inc. - initial API and implementation + *******************************************************************************/ +package org.eclipse.wst.html.ui.tests.validation; + +import org.eclipse.jface.text.IDocument; +import org.eclipse.wst.html.core.internal.validate.Segment; +import org.eclipse.wst.html.core.validate.extension.CustomValidatorUtil; +import org.eclipse.wst.html.core.validate.extension.IHTMLCustomTagValidator; +import org.eclipse.wst.sse.core.StructuredModelManager; +import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel; +import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument; +import org.eclipse.wst.sse.core.internal.validate.ValidationMessage; +import org.eclipse.wst.xml.core.internal.provisional.document.IDOMElement; +import org.junit.Assert; + +public class CustomExtendedTagValidator implements IHTMLCustomTagValidator{ + private String currentFileLocation; + + public boolean canValidate(IDOMElement target) { + if (target.getLocalName().startsWith("eclipse")) { + return true; + } + return false; + } + + public void init(IStructuredDocument doc) { + currentFileLocation = getResource(doc); + } + + public ValidationMessage validateTag(IDOMElement target) { + Assert.assertEquals(currentFileLocation, getResource(target.getStructuredDocument())); + String tagName = target.getLocalName(); + if (tagName.contains("thym")) { + Segment segment = CustomValidatorUtil.getTagSegment(target, CustomValidatorUtil.SEG_START_TAG_NAME); + return new ValidationMessage("Thym is available only with external installation", segment.getOffset(), segment.getLength(), ValidationMessage.ERROR); + } + return null; + } + + private String getResource(IDocument document) { + if (document == null) return null; + IStructuredModel sModel = StructuredModelManager.getModelManager().getExistingModelForRead(document); + try { + if (sModel != null) { + return sModel.getBaseLocation(); + } + } + finally { + if (sModel != null) { + sModel.releaseFromRead(); + } + } + + return null; + } +} diff --git a/tests/org.eclipse.wst.html.ui.tests/src/org/eclipse/wst/html/ui/tests/validation/TestHTMLValidator.java b/tests/org.eclipse.wst.html.ui.tests/src/org/eclipse/wst/html/ui/tests/validation/TestHTMLValidator.java index a9c9626bc6..09ef15ceef 100644 --- a/tests/org.eclipse.wst.html.ui.tests/src/org/eclipse/wst/html/ui/tests/validation/TestHTMLValidator.java +++ b/tests/org.eclipse.wst.html.ui.tests/src/org/eclipse/wst/html/ui/tests/validation/TestHTMLValidator.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009, 2011 IBM Corporation and others. + * Copyright (c) 2009, 2016 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,10 +7,12 @@ * * Contributors: * IBM Corporation - initial API and implementation + * Red Hat, Inc. - test for external validator *******************************************************************************/ package org.eclipse.wst.html.ui.tests.validation; +import java.io.IOException; import java.util.ArrayList; import java.util.List; @@ -21,6 +23,7 @@ import junit.framework.TestSuite; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.wst.html.core.internal.validation.HTMLValidator; import org.eclipse.wst.html.ui.tests.ProjectUtil; @@ -142,6 +145,46 @@ public class TestHTMLValidator extends TestCase { } } + public void testExtendedValidator() throws Exception{ + IFile testFile = fProject.getFile("validCustomTags.html"); + performExternalValidatorTest(testFile, false); + testFile = fProject.getFile("customTags.html"); + performExternalValidatorTest(testFile, true); + testFile = fProject.getFile("invalidAttrTestFile.html"); + performExternalValidatorTest(testFile, true); + } + + private void performExternalValidatorTest(IFile testFile, boolean errorExpected) throws IOException, CoreException { + IStructuredModel model = null; + + try { + assertTrue("Test file " + testFile + " does not exist", testFile.exists()); + + //get the document + model = StructuredModelManager.getModelManager().getModelForEdit(testFile); + + //set up for fValidator + WorkbenchContext context = new WorkbenchContext(); + List fileList = new ArrayList(); + fileList.add(testFile.getFullPath().toPortableString()); + context.setValidationFileURIs(fileList); + + //validate clean file + TestReporter reporter = new TestReporter(); + fValidator.validate(context, reporter); + if (errorExpected) { + assertTrue("There should be validation errors on " + testFile, reporter.isMessageReported()); + } else { + assertFalse("There should be no validation errors on " + testFile, reporter.isMessageReported()); + } + + } finally { + if(model != null) { + model.releaseFromEdit(); + } + } + } + /** * Regression test for Bug 298472 * diff --git a/tests/org.eclipse.wst.html.ui.tests/testresources/TestHTMLValidator/customTags.html b/tests/org.eclipse.wst.html.ui.tests/testresources/TestHTMLValidator/customTags.html new file mode 100644 index 0000000000..8848937030 --- /dev/null +++ b/tests/org.eclipse.wst.html.ui.tests/testresources/TestHTMLValidator/customTags.html @@ -0,0 +1,14 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="ISO-8859-1"> +<title>Eclipse</title> +</head> +<body> + <eclipse> + <eclipse-wtp plugins="900"/> + <eclipse-jsdt plugins="www"/> + <eclipse-thym plugins="8"/> + </eclipse> +</body> +</html>
\ No newline at end of file diff --git a/tests/org.eclipse.wst.html.ui.tests/testresources/TestHTMLValidator/invalidAttrTestFile.html b/tests/org.eclipse.wst.html.ui.tests/testresources/TestHTMLValidator/invalidAttrTestFile.html new file mode 100644 index 0000000000..0736811194 --- /dev/null +++ b/tests/org.eclipse.wst.html.ui.tests/testresources/TestHTMLValidator/invalidAttrTestFile.html @@ -0,0 +1,9 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="ISO-8859-1"> +<title>Eclipse</title> +</head> +<body attr="qqq"> +</body> +</html>
\ No newline at end of file diff --git a/tests/org.eclipse.wst.html.ui.tests/testresources/TestHTMLValidator/validCustomTags.html b/tests/org.eclipse.wst.html.ui.tests/testresources/TestHTMLValidator/validCustomTags.html new file mode 100644 index 0000000000..1d61e7ef67 --- /dev/null +++ b/tests/org.eclipse.wst.html.ui.tests/testresources/TestHTMLValidator/validCustomTags.html @@ -0,0 +1,13 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="ISO-8859-1"> +<title>Eclipse</title> +</head> +<body pr-a="qqq"> + <eclipse> + <eclipse-jdt plugins="900"/> + <eclipse-m2e/> + </eclipse> +</body> +</html>
\ No newline at end of file |