diff --git a/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/XPathFile.java b/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/XPathFile.java index 35bc6753acbb..52a083995afe 100644 --- a/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/XPathFile.java +++ b/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/XPathFile.java @@ -18,9 +18,11 @@ package org.intellij.lang.xpath; import com.intellij.extapi.psi.PsiFileBase; import com.intellij.openapi.fileTypes.FileType; import com.intellij.psi.FileViewProvider; +import com.intellij.psi.PsiElementVisitor; import org.intellij.lang.xpath.context.ContextProvider; import org.intellij.lang.xpath.context.XPathVersion; import org.intellij.lang.xpath.psi.XPathElement; +import org.intellij.lang.xpath.psi.XPathElementVisitor; import org.intellij.lang.xpath.psi.XPathExpression; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -57,4 +59,18 @@ public final class XPathFile extends PsiFileBase implements XPathElement { public XPathVersion getXPathVersion() { return getLanguage() instanceof XPath2Language ? XPathVersion.V2 : XPathVersion.V1; } + + @Override + public void accept(XPathElementVisitor visitor) { + visitor.visitXPathFile(this); + } + + @Override + public final void accept(@NotNull PsiElementVisitor visitor) { + if (visitor instanceof XPathElementVisitor) { + accept((XPathElementVisitor)visitor); + } else { + super.accept(visitor); + } + } } diff --git a/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/psi/XPathElement.java b/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/psi/XPathElement.java index a0e224e579f7..fc991342dbc1 100644 --- a/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/psi/XPathElement.java +++ b/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/psi/XPathElement.java @@ -30,4 +30,6 @@ public interface XPathElement extends PsiElement { ContextProvider getXPathContext(); XPathVersion getXPathVersion(); + + void accept(XPathElementVisitor visitor); } \ No newline at end of file diff --git a/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/psi/XPathElementVisitor.java b/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/psi/XPathElementVisitor.java index 8ffbe7287b46..0d4e90c92a7f 100644 --- a/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/psi/XPathElementVisitor.java +++ b/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/psi/XPathElementVisitor.java @@ -16,6 +16,7 @@ package org.intellij.lang.xpath.psi; import com.intellij.psi.PsiElementVisitor; +import org.intellij.lang.xpath.XPathFile; /* * Created by IntelliJ IDEA. @@ -104,4 +105,8 @@ public class XPathElementVisitor extends PsiElementVisitor { public void visitXPathElement(XPathElement o) { visitElement(o); } + + public void visitXPathFile(XPathFile file) { + visitFile(file); + } } \ No newline at end of file diff --git a/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/validation/XsltAnnotator.java b/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/validation/XsltAnnotator.java index 47e5896c4f6b..b1b8ca108271 100644 --- a/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/validation/XsltAnnotator.java +++ b/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/validation/XsltAnnotator.java @@ -20,13 +20,12 @@ import com.intellij.lang.annotation.Annotation; import com.intellij.lang.annotation.AnnotationHolder; import com.intellij.lang.annotation.Annotator; import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiFile; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.xml.XmlAttribute; import org.intellij.lang.xpath.XPathFile; import org.intellij.lang.xpath.XPathTokenTypes; import org.intellij.lang.xpath.context.ContextProvider; -import org.intellij.lang.xpath.psi.XPathElement; +import org.intellij.lang.xpath.psi.XPath2ElementVisitor; import org.intellij.lang.xpath.psi.XPathToken; import org.intellij.lang.xpath.xslt.XsltSupport; import org.intellij.lang.xpath.xslt.context.XsltContextProviderBase; @@ -34,46 +33,46 @@ import org.intellij.lang.xpath.xslt.quickfix.ConvertToEntityFix; import org.intellij.lang.xpath.xslt.quickfix.FlipOperandsFix; import org.jetbrains.annotations.NotNull; -public class XsltAnnotator implements Annotator { +public class XsltAnnotator extends XPath2ElementVisitor implements Annotator { - public void annotate(@NotNull PsiElement psiElement, @NotNull AnnotationHolder holder) { - if (psiElement instanceof XPathElement) { - final boolean isXslt = ContextProvider.getContextProvider(psiElement) instanceof XsltContextProviderBase; - if (isXslt) { - annotateXPathElement(((XPathElement)psiElement), holder); - } - } - } + private AnnotationHolder myHolder; - public static void annotateXPathFile(PsiFile file, AnnotationHolder holder) { - final XmlAttribute context = PsiTreeUtil.getContextOfType(file, XmlAttribute.class, true); - if (context != null) { - if (XsltSupport.isPatternAttribute(context)) { - XsltPatternValidator.validate(holder, file); - } - if (XsltSupport.isXsltAttribute(context) && !XsltSupport.mayBeAVT(context)) { - final ASTNode node = file.getNode(); - if (node != null && node.findChildByType(XPathTokenTypes.LBRACE) != null) { - holder.createErrorAnnotation(file, "Attribute Value Template is not allowed here"); - } - } - } + public void annotate(@NotNull PsiElement psiElement, @NotNull AnnotationHolder holder) { + final boolean isXslt = ContextProvider.getContextProvider(psiElement) instanceof XsltContextProviderBase; + if (isXslt) { + try { + myHolder = holder; + psiElement.accept(this); + } finally { + myHolder = null; + } } + } - private static void annotateXPathElement(XPathElement psiElement, AnnotationHolder holder) { - if (psiElement instanceof XPathFile) { - annotateXPathFile((PsiFile)psiElement, holder); - } else { - if (psiElement instanceof XPathToken) { - final XPathToken token = (XPathToken)psiElement; - if (XPathTokenTypes.REL_OPS.contains(token.getTokenType())) { - if (token.textContains('<')) { - final Annotation ann = holder.createErrorAnnotation(token, "'<' must be escaped as '<' in XSLT documents"); - ann.registerFix(new ConvertToEntityFix(token)); - ann.registerFix(new FlipOperandsFix(token)); - } - } - } + @Override + public void visitXPathFile(XPathFile file) { + final XmlAttribute context = PsiTreeUtil.getContextOfType(file, XmlAttribute.class, true); + if (context != null) { + if (XsltSupport.isPatternAttribute(context)) { + XsltPatternValidator.validate(myHolder, file); + } + if (XsltSupport.isXsltAttribute(context) && !XsltSupport.mayBeAVT(context)) { + final ASTNode node = file.getNode(); + if (node != null && node.findChildByType(XPathTokenTypes.LBRACE) != null) { + myHolder.createErrorAnnotation(file, "Attribute Value Template is not allowed here"); } + } } + } + + @Override + public void visitXPathToken(XPathToken token) { + if (XPathTokenTypes.REL_OPS.contains(token.getTokenType())) { + if (token.textContains('<')) { + final Annotation ann = myHolder.createErrorAnnotation(token, "'<' must be escaped as '<' in XSLT documents"); + ann.registerFix(new ConvertToEntityFix(token)); + ann.registerFix(new FlipOperandsFix(token)); + } + } + } }