IDEA-68188 XSLT: usages of namespace prefix are not found in preserve-space and strip-space elements

This commit is contained in:
sweinreuter
2011-04-19 19:59:05 +02:00
parent fcef6786cc
commit a265976562
4 changed files with 52 additions and 66 deletions
@@ -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;
}
}
@@ -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)?
@@ -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
@@ -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<CachedValue<PsiReference[]>> 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<PsiReference> refs = new SmartList<PsiReference>();
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;