From 9dcf89ecbbc9bba0e80e5fa900dccb787bc80c0e Mon Sep 17 00:00:00 2001 From: sweinreuter Date: Thu, 14 Apr 2011 13:13:16 +0200 Subject: [PATCH] IDEA-67497 XSLT: "Unused XML schema declaration" inspection: false positive for namespace declaration used in stylesheet object qualified name --- .../xslt/impl/references/SelfReference.java | 9 +- .../references/XsltReferenceProvider.java | 467 +++++++++--------- 2 files changed, 243 insertions(+), 233 deletions(-) diff --git a/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/impl/references/SelfReference.java b/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/impl/references/SelfReference.java index 600699a6f0be..26f18d257c2b 100644 --- a/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/impl/references/SelfReference.java +++ b/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/impl/references/SelfReference.java @@ -37,7 +37,7 @@ class SelfReference implements PsiReference { myStartOffset = startOffset; } - public SelfReference(XmlAttribute element, PsiElement target) { + SelfReference(XmlAttribute element, PsiElement target) { this(element, target, 0); } @@ -79,4 +79,11 @@ class SelfReference implements PsiReference { public boolean isSoft() { return false; } + + public static SelfReference create(XmlAttribute element, PsiElement target) { + if (element.getValue().contains(":")) { + return new SelfReference(element, target, element.getValue().indexOf(':') + 1); + } + return new SelfReference(element, target); + } } 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 3972b2469771..e1601fa35fdb 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 @@ -1,4 +1,3 @@ - package org.intellij.lang.xpath.xslt.impl.references; import com.intellij.javaee.ExternalResourceManager; @@ -28,258 +27,262 @@ import org.intellij.lang.xpath.xslt.util.*; import org.jetbrains.annotations.NotNull; public class XsltReferenceProvider extends PsiReferenceProvider { - private static final Key> CACHED_XSLT_REFS = Key.create("CACHED_XSLT_REFS"); + private static final Key> CACHED_XSLT_REFS = Key.create("CACHED_XSLT_REFS"); - private final CachedValuesManager myCacheManager; - private final XsltElementFactory myXsltElementFactory = XsltElementFactory.getInstance(); + private final CachedValuesManager myCacheManager; + private final XsltElementFactory myXsltElementFactory = XsltElementFactory.getInstance(); - public XsltReferenceProvider(Project project) { - myCacheManager = CachedValuesManager.getManager(project); + public XsltReferenceProvider(Project project) { + myCacheManager = CachedValuesManager.getManager(project); + } + + @NotNull + public PsiReference[] getReferencesByElement(@NotNull PsiElement e, @NotNull ProcessingContext context) { + final PsiElement element = e.getParent(); + if (element instanceof XmlAttribute) { + final XmlAttribute attribute = (XmlAttribute)element; + + CachedValue cachedValue = attribute.getUserData(CACHED_XSLT_REFS); + if (cachedValue == null) { + cachedValue = myCacheManager.createCachedValue(new ReferenceProvider(attribute), false); + attribute.putUserData(CACHED_XSLT_REFS, cachedValue); + } + + final PsiReference[] value = cachedValue.getValue(); + assert value != null; + return value; + } else { + return PsiReference.EMPTY_ARRAY; + } + } + + private class ReferenceProvider implements CachedValueProvider { + private final XmlAttribute myAttribute; + + ReferenceProvider(XmlAttribute attribute) { + myAttribute = attribute; } - @NotNull - public PsiReference[] getReferencesByElement(@NotNull PsiElement e, @NotNull ProcessingContext context) { - final PsiElement element = e.getParent(); - if (element instanceof XmlAttribute) { - final XmlAttribute attribute = (XmlAttribute)element; + public Result compute() { + final PsiReference[] referencesImpl = getReferencesImpl(myAttribute); + final Object[] refs = new PsiElement[referencesImpl.length]; + for (int i = 0; i < refs.length; i++) { + refs[i] = referencesImpl[i].getElement(); + } + return new Result(referencesImpl, ArrayUtil.append(refs, myAttribute.getValueElement())); + } - CachedValue cachedValue = attribute.getUserData(CACHED_XSLT_REFS); - if (cachedValue == null) { - cachedValue = myCacheManager.createCachedValue(new ReferenceProvider(attribute), false); - attribute.putUserData(CACHED_XSLT_REFS, cachedValue); - } + private PsiReference[] getReferencesImpl(final XmlAttribute attribute) { + final PsiReference[] psiReferences; + final XmlTag tag = attribute.getParent(); - final PsiReference[] value = cachedValue.getValue(); - assert value != null; - return value; + if (XsltSupport.isTemplateCallName(attribute)) { + psiReferences = createReferencesWithPrefix(attribute, new TemplateReference(attribute)); + } else if (XsltSupport.isTemplateCallParamName(attribute)) { + final String paramName = attribute.getValue(); + final XmlTag templateCall = PsiTreeUtil.getParentOfType(tag, XmlTag.class); + + if (templateCall != null) { + if (XsltSupport.isTemplateCall(templateCall)) { + final XsltCallTemplate call = myXsltElementFactory.wrapElement(templateCall, XsltCallTemplate.class); + final ResolveUtil.Matcher matcher = new MyParamMatcher(paramName, call); + psiReferences = new PsiReference[]{ new AttributeReference(attribute, matcher, true) }; + } else if (XsltSupport.isApplyTemplates(templateCall)) { + final XsltApplyTemplates call = myXsltElementFactory.wrapElement(templateCall, XsltApplyTemplates.class); + final ResolveUtil.Matcher matcher = new MyParamMatcher2(paramName, call); + psiReferences = new PsiReference[]{ new ParamReference(attribute, matcher) }; + } else { + psiReferences = PsiReference.EMPTY_ARRAY; + } } else { - return PsiReference.EMPTY_ARRAY; + psiReferences = PsiReference.EMPTY_ARRAY; } + } else if (XsltSupport.isParam(attribute) && isInsideUnnamedTemplate(tag)) { + final XsltParameter myParam = myXsltElementFactory.wrapElement(tag, XsltParameter.class); + psiReferences = new PsiReference[]{ new MySelfReference(attribute, myParam) }; + } else if (XsltSupport.isVariableOrParamName(attribute) || XsltSupport.isTemplateName(attribute)) { + final XsltElement myElement = myXsltElementFactory.wrapElement(tag, XsltElement.class); + psiReferences = createReferencesWithPrefix(attribute, SelfReference.create(attribute, myElement)); + } else if (XsltSupport.isFunctionName(attribute)) { + final XsltFunction myElement = myXsltElementFactory.wrapElement(tag, XsltFunction.class); + psiReferences = createReferencesWithPrefix(attribute, SelfReference.create(attribute, myElement)); + } else if (XsltSupport.isIncludeOrImportHref(attribute)) { + final String href = attribute.getValue(); + final String resourceLocation = ExternalResourceManager.getInstance().getResourceLocation(href, attribute.getProject()); + //noinspection StringEquality + if (href == resourceLocation) { + // not a configured external resource + if (!href.contains("://")) { + // a local file reference + final FileReferenceSet filereferenceset = new FileReferenceSet( + href, + attribute.getValueElement(), 1, XsltReferenceProvider.this, true); + psiReferences = filereferenceset.getAllReferences(); + } else { + // external, but unknown resource + psiReferences = new PsiReference[]{ new ExternalResourceReference(attribute) }; + } + } else { + // external, known resource + psiReferences = new PsiReference[]{ new ExternalResourceReference(attribute) }; + } + } else if (XsltSupport.isMode(attribute)) { + psiReferences = ModeReference.create(attribute, XsltSupport.isTemplate(tag, false)); + } else { + psiReferences = PsiReference.EMPTY_ARRAY; + } + + return psiReferences; } - private class ReferenceProvider implements CachedValueProvider { - private final XmlAttribute myAttribute; - - ReferenceProvider(XmlAttribute attribute) { - myAttribute = attribute; - } - - public Result compute() { - final PsiReference[] referencesImpl = getReferencesImpl(myAttribute); - final Object[] refs = new PsiElement[referencesImpl.length]; - for (int i = 0; i < refs.length; i++) { - refs[i] = referencesImpl[i].getElement(); - } - return new Result(referencesImpl, ArrayUtil.append(refs, myAttribute.getValueElement())); - } - - private PsiReference[] getReferencesImpl(final XmlAttribute attribute) { - final PsiReference[] psiReferences; - final XmlTag tag = attribute.getParent(); - - if (XsltSupport.isTemplateCallName(attribute)) { - psiReferences = new PsiReference[]{ new TemplateReference(attribute) }; - } else if (XsltSupport.isTemplateCallParamName(attribute)) { - final String paramName = attribute.getValue(); - final XmlTag templateCall = PsiTreeUtil.getParentOfType(tag, XmlTag.class); - - if (templateCall != null) { - if (XsltSupport.isTemplateCall(templateCall)) { - final XsltCallTemplate call = myXsltElementFactory.wrapElement(templateCall, XsltCallTemplate.class); - final ResolveUtil.Matcher matcher = new MyParamMatcher(paramName, call); - psiReferences = new PsiReference[]{ new AttributeReference(attribute, matcher, true) }; - } else if (XsltSupport.isApplyTemplates(templateCall)) { - final XsltApplyTemplates call = myXsltElementFactory.wrapElement(templateCall, XsltApplyTemplates.class); - final ResolveUtil.Matcher matcher = new MyParamMatcher2(paramName, call); - psiReferences = new PsiReference[]{ new ParamReference(attribute, matcher) }; - } else { - psiReferences = PsiReference.EMPTY_ARRAY; - } - } else { - psiReferences = PsiReference.EMPTY_ARRAY; - } - } else if (XsltSupport.isParam(attribute) && isInsideUnnamedTemplate(tag)) { - final XsltParameter myParam = myXsltElementFactory.wrapElement(tag, XsltParameter.class); - psiReferences = new PsiReference[]{ new MySelfReference(attribute, myParam) }; - } else if (XsltSupport.isVariableOrParamName(attribute) || XsltSupport.isTemplateName(attribute)) { - final XsltElement myElement = myXsltElementFactory.wrapElement(tag, XsltElement.class); - psiReferences = new PsiReference[]{ new SelfReference(attribute, myElement) }; - } else if (XsltSupport.isFunctionName(attribute)) { - final XsltFunction myElement = myXsltElementFactory.wrapElement(tag, XsltFunction.class); - if (attribute.getValue().contains(":")) { - psiReferences = new PsiReference[]{ new PrefixReference(attribute), new SelfReference(attribute, myElement, attribute.getValue().indexOf(':') + 1) }; - } else { - psiReferences = new PsiReference[]{ new SelfReference(attribute, myElement) }; - } - } else if (XsltSupport.isIncludeOrImportHref(attribute)) { - final String href = attribute.getValue(); - final String resourceLocation = ExternalResourceManager.getInstance().getResourceLocation(href, attribute.getProject()); - //noinspection StringEquality - if (href == resourceLocation) { - // not a configured external resource - if (href.indexOf("://") == -1) { - // a local file reference - final FileReferenceSet filereferenceset = new FileReferenceSet( - href, - attribute.getValueElement(), 1, XsltReferenceProvider.this, true); - psiReferences = filereferenceset.getAllReferences(); - } else { - // external, but unknown resource - psiReferences = new PsiReference[]{ new ExternalResourceReference(attribute) }; - } - } else { - // external, known resource - psiReferences = new PsiReference[]{ new ExternalResourceReference(attribute) }; - } - } else if (XsltSupport.isMode(attribute)) { - psiReferences = ModeReference.create(attribute, XsltSupport.isTemplate(tag, false)); - } else { - psiReferences = PsiReference.EMPTY_ARRAY; - } - - return psiReferences; - } - - private class MySelfReference extends SelfReference { - private final XsltParameter myParam; - private final XmlTag myTag; - - public MySelfReference(XmlAttribute attribute, XsltParameter param) { - super(attribute, param); - myParam = param; - myTag = param.getTag(); + private PsiReference[] createReferencesWithPrefix(XmlAttribute attribute, PsiReference reference) { + if (attribute.getValue().contains(":")) { + return new PsiReference[]{ new PrefixReference(attribute), reference }; + } else { + return new PsiReference[]{ reference }; + } } + private class MySelfReference extends SelfReference { + private final XsltParameter myParam; + private final XmlTag myTag; - public PsiElement handleElementRename(String newElementName) throws IncorrectOperationException { - if (!newElementName.equals(myParam.getName())) { - myParam.setName(newElementName); - } - final XmlAttribute attribute = myParam.getNameAttribute(); - assert attribute != null; - //noinspection ConstantConditions - return attribute.getValueElement(); - } + public MySelfReference(XmlAttribute attribute, XsltParameter param) { + super(attribute, param); + myParam = param; + myTag = param.getTag(); + } - public boolean isReferenceTo(PsiElement element) { - // self-reference is only a trick to enable rename/find usages etc. but it shouldn't actually - // refer to itself because this would list the element to be renamed/searched for twice - assert !super.isReferenceTo(element); - if (element == myParam) return false; - if (!(element instanceof XsltParameter)) return false; - - final XsltParameter param = ((XsltParameter)element); - final String name = param.getName(); - if (name == null || !name.equals(myParam.getName())) return false; - - final XsltTemplate template = XsltCodeInsightUtil.getTemplate(myTag, false); - final XsltTemplate myTemplate = XsltCodeInsightUtil.getTemplate(param.getTag(), false); - if (template == myTemplate) return true; - if (template == null || myTemplate == null) return false; - - if (!Comparing.equal(template.getMode(), myTemplate.getMode())) { - return false; - } - - final XmlFile xmlFile = (XmlFile)element.getContainingFile(); - final XmlFile myFile = (XmlFile)myParam.getContainingFile(); - if (myFile == xmlFile) return true; - - return XsltIncludeIndex.isReachableFrom(myFile, xmlFile); - } + public PsiElement handleElementRename(String newElementName) throws IncorrectOperationException { + if (!newElementName.equals(myParam.getName())) { + myParam.setName(newElementName); } + final XmlAttribute attribute = myParam.getNameAttribute(); + assert attribute != null; + //noinspection ConstantConditions + return attribute.getValueElement(); + } + + public boolean isReferenceTo(PsiElement element) { + // self-reference is only a trick to enable rename/find usages etc. but it shouldn't actually + // refer to itself because this would list the element to be renamed/searched for twice + assert !super.isReferenceTo(element); + + if (element == myParam) return false; + if (!(element instanceof XsltParameter)) return false; + + final XsltParameter param = ((XsltParameter)element); + final String name = param.getName(); + if (name == null || !name.equals(myParam.getName())) return false; + + final XsltTemplate template = XsltCodeInsightUtil.getTemplate(myTag, false); + final XsltTemplate myTemplate = XsltCodeInsightUtil.getTemplate(param.getTag(), false); + if (template == myTemplate) return true; + if (template == null || myTemplate == null) return false; + + if (!Comparing.equal(template.getMode(), myTemplate.getMode())) { + return false; + } + + final XmlFile xmlFile = (XmlFile)element.getContainingFile(); + final XmlFile myFile = (XmlFile)myParam.getContainingFile(); + if (myFile == xmlFile) return true; + + return XsltIncludeIndex.isReachableFrom(myFile, xmlFile); + } + } + } + + private static boolean isInsideUnnamedTemplate(XmlTag tag) { + final XmlTag t = XsltCodeInsightUtil.getTemplateTag(tag, false, false); + return t != null && t.getAttribute("name", null) == null; + } + + static class MyParamMatcher extends NamedTemplateMatcher { + private final XsltCallTemplate myCall; + private final String myParamName; + private String[] myExcludedNames = ArrayUtil.EMPTY_STRING_ARRAY; + + MyParamMatcher(String paramName, XsltCallTemplate call) { + super(XsltCodeInsightUtil.getDocument(call), call.getTemplateName()); + myCall = call; + myParamName = paramName; } - private static boolean isInsideUnnamedTemplate(XmlTag tag) { - final XmlTag t = XsltCodeInsightUtil.getTemplateTag(tag, false, false); - return t != null && t.getAttribute("name", null) == null; + private MyParamMatcher(String paramName, XsltCallTemplate call, String[] excludedNames) { + super(getDocument(call), call.getTemplateName()); + myCall = call; + myParamName = paramName; + myExcludedNames = excludedNames; } - static class MyParamMatcher extends NamedTemplateMatcher { - private final XsltCallTemplate myCall; - private final String myParamName; - private String[] myExcludedNames = ArrayUtil.EMPTY_STRING_ARRAY; - - MyParamMatcher(String paramName, XsltCallTemplate call) { - super(XsltCodeInsightUtil.getDocument(call), call.getTemplateName()); - myCall = call; - myParamName = paramName; - } - - private MyParamMatcher(String paramName, XsltCallTemplate call, String[] excludedNames) { - super(getDocument(call), call.getTemplateName()); - myCall = call; - myParamName = paramName; - myExcludedNames = excludedNames; - } - - private static XmlDocument getDocument(XsltCallTemplate call) { - final XsltTemplate template = call.getTemplate(); - return XsltCodeInsightUtil.getDocument(template != null ? template : call); - } - - @Override - protected ResolveUtil.Matcher changeDocument(XmlDocument document) { - return new MyParamMatcher(myParamName, myCall, myExcludedNames); - } - - @Override - protected Result matchImpl(XmlTag element) { - if (matches(element)) { - return Result.create(new ParamMatcher(element, myExcludedNames, myParamName)); - } - return null; - } - - @Override - public ResolveUtil.Matcher variantMatcher() { - final PsiElement[] suppliedArgs = ResolveUtil.collect(new ArgumentMatcher(myCall)); - final String[] excludedNames = new String[suppliedArgs.length]; - for (int i = 0; i < suppliedArgs.length; i++) { - excludedNames[i] = ((XmlTag)suppliedArgs[i]).getAttributeValue("name"); - } - return new MyParamMatcher(null, myCall, excludedNames); - } + private static XmlDocument getDocument(XsltCallTemplate call) { + final XsltTemplate template = call.getTemplate(); + return XsltCodeInsightUtil.getDocument(template != null ? template : call); } - static class MyParamMatcher2 extends MatchTemplateMatcher { - private final String myParamName; - private final XsltApplyTemplates myCall; - private String[] myExcludedNames = ArrayUtil.EMPTY_STRING_ARRAY; - - MyParamMatcher2(String paramName, XsltApplyTemplates call) { - super(XsltCodeInsightUtil.getDocument(call), call.getMode()); - myParamName = paramName; - myCall = call; - } - - private MyParamMatcher2(String paramName, XsltApplyTemplates call, String[] excludedNames) { - this(paramName, call); - myExcludedNames = excludedNames; - } - - @Override - protected Result matchImpl(XmlTag element) { - if (matches(element)) { - return Result.create(new ParamMatcher(element, myExcludedNames, myParamName)); - } - return null; - } - - @Override - protected ResolveUtil.Matcher changeDocument(XmlDocument document) { - return new MyParamMatcher2(myParamName, myCall); - } - - @Override - public ResolveUtil.Matcher variantMatcher() { - final PsiElement[] suppliedArgs = ResolveUtil.collect(new ArgumentMatcher(myCall)); - final String[] excludedNames = new String[suppliedArgs.length]; - for (int i = 0; i < suppliedArgs.length; i++) { - excludedNames[i] = ((XmlTag)suppliedArgs[i]).getAttributeValue("name"); - } - return new MyParamMatcher2(null, myCall, excludedNames); - } + @Override + protected ResolveUtil.Matcher changeDocument(XmlDocument document) { + return new MyParamMatcher(myParamName, myCall, myExcludedNames); } + + @Override + protected Result matchImpl(XmlTag element) { + if (matches(element)) { + return Result.create(new ParamMatcher(element, myExcludedNames, myParamName)); + } + return null; + } + + @Override + public ResolveUtil.Matcher variantMatcher() { + final PsiElement[] suppliedArgs = ResolveUtil.collect(new ArgumentMatcher(myCall)); + final String[] excludedNames = new String[suppliedArgs.length]; + for (int i = 0; i < suppliedArgs.length; i++) { + excludedNames[i] = ((XmlTag)suppliedArgs[i]).getAttributeValue("name"); + } + return new MyParamMatcher(null, myCall, excludedNames); + } + } + + static class MyParamMatcher2 extends MatchTemplateMatcher { + private final String myParamName; + private final XsltApplyTemplates myCall; + private String[] myExcludedNames = ArrayUtil.EMPTY_STRING_ARRAY; + + MyParamMatcher2(String paramName, XsltApplyTemplates call) { + super(XsltCodeInsightUtil.getDocument(call), call.getMode()); + myParamName = paramName; + myCall = call; + } + + private MyParamMatcher2(String paramName, XsltApplyTemplates call, String[] excludedNames) { + this(paramName, call); + myExcludedNames = excludedNames; + } + + @Override + protected Result matchImpl(XmlTag element) { + if (matches(element)) { + return Result.create(new ParamMatcher(element, myExcludedNames, myParamName)); + } + return null; + } + + @Override + protected ResolveUtil.Matcher changeDocument(XmlDocument document) { + return new MyParamMatcher2(myParamName, myCall); + } + + @Override + public ResolveUtil.Matcher variantMatcher() { + final PsiElement[] suppliedArgs = ResolveUtil.collect(new ArgumentMatcher(myCall)); + final String[] excludedNames = new String[suppliedArgs.length]; + for (int i = 0; i < suppliedArgs.length; i++) { + excludedNames[i] = ((XmlTag)suppliedArgs[i]).getAttributeValue("name"); + } + return new MyParamMatcher2(null, myCall, excludedNames); + } + } }