diff --git a/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/impl/XsltAttributeFilter.java b/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/impl/XsltAttributeFilter.java deleted file mode 100644 index 4fcdbc1c838c..000000000000 --- a/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/impl/XsltAttributeFilter.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright 2005 Sascha Weinreuter - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.intellij.lang.xpath.xslt.impl; - -import org.intellij.lang.xpath.xslt.XsltSupport; - -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiFile; -import com.intellij.psi.filters.ElementFilter; -import com.intellij.psi.xml.XmlAttribute; - -class XsltAttributeFilter implements ElementFilter { - public boolean isAcceptable(Object object, PsiElement element) { - if (!(object instanceof PsiElement)) return false; - - final PsiFile containingFile = ((PsiElement)object).getContainingFile(); - if (containingFile == null) return false; - - if (!XsltSupport.isXsltFile(containingFile)) return false; - - PsiElement psielement1 = ((PsiElement)object).getParent(); - if (psielement1 instanceof XmlAttribute || (psielement1 = psielement1.getParent()) instanceof XmlAttribute) { - final XmlAttribute xmlattribute = (XmlAttribute)psielement1; - if (XsltSupport.isTemplateCallName(xmlattribute)) { - return true; - } - if (XsltSupport.isTemplateCallParamName(xmlattribute)) { - return true; - } - if (XsltSupport.isVariableOrParamName(xmlattribute) || XsltSupport.isTemplateName(xmlattribute)) { - return true; - } - if (XsltSupport.isIncludeOrImportHref(xmlattribute)) { - return true; - } - if (XsltSupport.isMode(xmlattribute)) { - return true; - } - if (XsltSupport.isFunctionName(xmlattribute)) { - return true; - } - } - return false; - } - - @SuppressWarnings({"RawUseOfParameterizedType"}) - public boolean isClassAcceptable(Class aClass) { - return true; - } -} diff --git a/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/impl/XsltReferenceContributor.java b/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/impl/XsltReferenceContributor.java index 91a4b0977403..991300aefce4 100644 --- a/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/impl/XsltReferenceContributor.java +++ b/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/impl/XsltReferenceContributor.java @@ -18,7 +18,6 @@ package org.intellij.lang.xpath.xslt.impl; import com.intellij.patterns.PlatformPatterns; import com.intellij.patterns.XmlPatterns; import com.intellij.psi.*; -import com.intellij.psi.filters.position.FilterPattern; import com.intellij.psi.xml.XmlAttribute; import com.intellij.psi.xml.XmlAttributeValue; import com.intellij.util.ProcessingContext; @@ -28,6 +27,7 @@ import org.intellij.lang.xpath.xslt.impl.references.PrefixReference; import org.intellij.lang.xpath.xslt.impl.references.XsltReferenceProvider; import org.jetbrains.annotations.NotNull; +import static com.intellij.patterns.StandardPatterns.string; import static com.intellij.patterns.XmlPatterns.xmlAttribute; import static com.intellij.patterns.XmlPatterns.xmlTag; @@ -37,7 +37,9 @@ import static com.intellij.patterns.XmlPatterns.xmlTag; public class XsltReferenceContributor extends PsiReferenceContributor { public void registerReferenceProviders(PsiReferenceRegistrar registrar) { registrar.registerReferenceProvider( - PlatformPatterns.psiElement(XmlAttributeValue.class).and(new FilterPattern(new XsltAttributeFilter())), + PlatformPatterns.psiElement(XmlAttributeValue.class).withParent(xmlAttribute().withLocalName(string().oneOf( + "name", "href", "mode", "elements", "exclude-result-prefixes", "extension-element-prefixes", "stylesheet-prefix" + )).withParent(xmlTag().withNamespace(XsltSupport.XSLT_NS))), new XsltReferenceProvider(registrar.getProject())); // TODO: 1. SchemaReferencesProvider doesn't know about "as" attribute / 2. what to do with non-schema types (xs:yearMonthDuretion, xs:dayTimeDuration)? diff --git a/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/impl/references/PrefixReference.java b/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/impl/references/PrefixReference.java index dac2ba876d4d..837350475d81 100644 --- a/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/impl/references/PrefixReference.java +++ b/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/impl/references/PrefixReference.java @@ -25,8 +25,17 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; public class PrefixReference extends SimpleAttributeReference implements EmptyResolveMessageProvider { + + private final TextRange myRange; + public PrefixReference(XmlAttribute attribute) { super(attribute); + myRange = getPrefixRange(myAttribute); + } + + public PrefixReference(XmlAttribute attribute, TextRange range) { + super(attribute); + myRange = range; } public static TextRange getPrefixRange(XmlAttribute attribute) { @@ -52,7 +61,7 @@ public class PrefixReference extends SimpleAttributeReference implements EmptyRe @Override @NotNull protected TextRange getTextRange() { - return getPrefixRange(myAttribute); + return myRange; } @Override diff --git a/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/impl/references/XsltReferenceProvider.java b/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/impl/references/XsltReferenceProvider.java index e1601fa35fdb..566d44eeac27 100644 --- a/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/impl/references/XsltReferenceProvider.java +++ b/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/impl/references/XsltReferenceProvider.java @@ -4,6 +4,7 @@ import com.intellij.javaee.ExternalResourceManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.Key; +import com.intellij.openapi.util.TextRange; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiReference; import com.intellij.psi.PsiReferenceProvider; @@ -19,6 +20,7 @@ import com.intellij.psi.xml.XmlTag; import com.intellij.util.ArrayUtil; import com.intellij.util.IncorrectOperationException; import com.intellij.util.ProcessingContext; +import com.intellij.util.SmartList; import org.intellij.lang.xpath.psi.impl.ResolveUtil; import org.intellij.lang.xpath.xslt.XsltSupport; import org.intellij.lang.xpath.xslt.impl.XsltIncludeIndex; @@ -26,12 +28,19 @@ import org.intellij.lang.xpath.xslt.psi.*; import org.intellij.lang.xpath.xslt.util.*; import org.jetbrains.annotations.NotNull; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + public class XsltReferenceProvider extends PsiReferenceProvider { private static final Key> CACHED_XSLT_REFS = Key.create("CACHED_XSLT_REFS"); private final CachedValuesManager myCacheManager; private final XsltElementFactory myXsltElementFactory = XsltElementFactory.getInstance(); + private static final Pattern ELEMENT_PATTERN = Pattern.compile("(?:(\\w+):)?(?:\\w+|\\*)"); + private static final Pattern PREFIX_PATTERN = Pattern.compile("(?:^|\\s)(\\w+)"); + public XsltReferenceProvider(Project project) { myCacheManager = CachedValuesManager.getManager(project); } @@ -128,6 +137,17 @@ public class XsltReferenceProvider extends PsiReferenceProvider { } } else if (XsltSupport.isMode(attribute)) { psiReferences = ModeReference.create(attribute, XsltSupport.isTemplate(tag, false)); + } else if ((attribute.getLocalName().equals("extension-element-prefixes") || + attribute.getLocalName().equals("exclude-result-prefixes")) && XsltSupport.isXsltRootTag(tag)) { + psiReferences = createPrefixReferences(attribute, PREFIX_PATTERN); + } else if (attribute.getLocalName().equals("stylesheet-prefix") && tag.getLocalName().equals("namespace-alias")) { + psiReferences = createPrefixReferences(attribute, PREFIX_PATTERN); + } else if ("elements".equals(attribute.getLocalName())) { + if (("strip-space".equals(tag.getLocalName()) || "preserve-space".equals(tag.getLocalName()))) { + psiReferences = createPrefixReferences(attribute, ELEMENT_PATTERN); + } else { + psiReferences = PsiReference.EMPTY_ARRAY; + } } else { psiReferences = PsiReference.EMPTY_ARRAY; } @@ -194,6 +214,24 @@ public class XsltReferenceProvider extends PsiReferenceProvider { } } + private static PsiReference[] createPrefixReferences(XmlAttribute attribute, Pattern pattern) { + final Matcher matcher = pattern.matcher(attribute.getValue()); + + if (matcher.find()) { + final List refs = new SmartList(); + do { + final int start = matcher.start(1); + if (start >= 0) { + refs.add(new PrefixReference(attribute, TextRange.create(start, matcher.end(1)))); + } + } + while (matcher.find()); + + return refs.toArray(new PsiReference[refs.size()]); + } + return PsiReference.EMPTY_ARRAY; + } + private static boolean isInsideUnnamedTemplate(XmlTag tag) { final XmlTag t = XsltCodeInsightUtil.getTemplateTag(tag, false, false); return t != null && t.getAttribute("name", null) == null;