more xpath visitor stuff

This commit is contained in:
sweinreuter
2011-04-11 19:31:55 +02:00
parent 35674f88df
commit e592896a4e
4 changed files with 60 additions and 38 deletions
@@ -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);
}
}
}
@@ -30,4 +30,6 @@ public interface XPathElement extends PsiElement {
ContextProvider getXPathContext();
XPathVersion getXPathVersion();
void accept(XPathElementVisitor visitor);
}
@@ -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);
}
}
@@ -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 '&lt;' 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 '&lt;' in XSLT documents");
ann.registerFix(new ConvertToEntityFix(token));
ann.registerFix(new FlipOperandsFix(token));
}
}
}
}