From 5733197e655e3b3f62f34db45635eedfbc3ce142 Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Fri, 20 May 2011 15:04:12 +0400 Subject: [PATCH] IDEA-69031: XmlUnusedNamespaceDeclaration - Does not take element content into account: QName in attribute values support --- .../XmlUnboundNsPrefixInspection.java | 14 ++++++ .../schema/XmlAttributeDescriptorImpl.java | 7 ++- .../xml/impl/schema/XmlNSDescriptorImpl.java | 4 +- .../xml/util/XmlPrefixReferenceProvider.java | 50 +++++++++++++++++++ .../xml/util/XmlReferenceContributor.java | 9 ++-- 5 files changed, 78 insertions(+), 6 deletions(-) create mode 100644 xml/impl/src/com/intellij/xml/util/XmlPrefixReferenceProvider.java diff --git a/xml/impl/src/com/intellij/codeInsight/daemon/impl/analysis/XmlUnboundNsPrefixInspection.java b/xml/impl/src/com/intellij/codeInsight/daemon/impl/analysis/XmlUnboundNsPrefixInspection.java index 0af2637080d3..0c8ef2b2fd48 100644 --- a/xml/impl/src/com/intellij/codeInsight/daemon/impl/analysis/XmlUnboundNsPrefixInspection.java +++ b/xml/impl/src/com/intellij/codeInsight/daemon/impl/analysis/XmlUnboundNsPrefixInspection.java @@ -24,6 +24,7 @@ import com.intellij.codeInspection.XmlSuppressableInspectionTool; import com.intellij.lang.injection.InjectedLanguageManager; import com.intellij.openapi.util.TextRange; import com.intellij.psi.*; +import com.intellij.psi.impl.source.xml.SchemaPrefixReference; import com.intellij.psi.templateLanguages.OuterLanguageElement; import com.intellij.psi.xml.*; import com.intellij.xml.XmlBundle; @@ -96,6 +97,19 @@ public class XmlUnboundNsPrefixInspection extends XmlSuppressableInspectionTool checkUnboundNamespacePrefix(attribute, tag, XmlUtil.findPrefixByQualifiedName(name), null, holder, isOnTheFly); } + + @Override + public void visitXmlAttributeValue(XmlAttributeValue value) { + PsiReference[] references = value.getReferences(); + for (PsiReference reference : references) { + if (reference instanceof SchemaPrefixReference) { + if (!XML.equals(((SchemaPrefixReference)reference).getNamespacePrefix()) && reference.resolve() == null) { + holder.registerProblem(reference, XmlErrorMessages.message("unbound.namespace", + ((SchemaPrefixReference)reference).getNamespacePrefix()), ProblemHighlightType.LIKE_UNKNOWN_SYMBOL); + } + } + } + } }; } diff --git a/xml/impl/src/com/intellij/xml/impl/schema/XmlAttributeDescriptorImpl.java b/xml/impl/src/com/intellij/xml/impl/schema/XmlAttributeDescriptorImpl.java index 3ceeb69fadfc..24591d37c2be 100644 --- a/xml/impl/src/com/intellij/xml/impl/schema/XmlAttributeDescriptorImpl.java +++ b/xml/impl/src/com/intellij/xml/impl/schema/XmlAttributeDescriptorImpl.java @@ -76,7 +76,7 @@ public class XmlAttributeDescriptorImpl extends BasicXmlAttributeDescriptor impl } private boolean hasSimpleSchemaType(@NonNls String type) { - final String attributeValue = myTag.getAttributeValue("type"); + final String attributeValue = getType(); if (attributeValue != null) { if (attributeValue.endsWith(type)) { @@ -93,6 +93,11 @@ public class XmlAttributeDescriptorImpl extends BasicXmlAttributeDescriptor impl return false; } + @Nullable + public String getType() { + return myTag.getAttributeValue("type"); + } + public boolean hasIdType() { return hasSimpleSchemaType("ID"); } diff --git a/xml/impl/src/com/intellij/xml/impl/schema/XmlNSDescriptorImpl.java b/xml/impl/src/com/intellij/xml/impl/schema/XmlNSDescriptorImpl.java index a4ff68979449..22d9318c721d 100644 --- a/xml/impl/src/com/intellij/xml/impl/schema/XmlNSDescriptorImpl.java +++ b/xml/impl/src/com/intellij/xml/impl/schema/XmlNSDescriptorImpl.java @@ -379,13 +379,13 @@ public class XmlNSDescriptorImpl implements XmlNSDescriptor,Validator 0){ return checkSchemaNamespace(namespace); diff --git a/xml/impl/src/com/intellij/xml/util/XmlPrefixReferenceProvider.java b/xml/impl/src/com/intellij/xml/util/XmlPrefixReferenceProvider.java new file mode 100644 index 000000000000..f1b829475a3b --- /dev/null +++ b/xml/impl/src/com/intellij/xml/util/XmlPrefixReferenceProvider.java @@ -0,0 +1,50 @@ +package com.intellij.xml.util; + +import com.intellij.openapi.util.TextRange; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiReference; +import com.intellij.psi.PsiReferenceProvider; +import com.intellij.psi.impl.source.xml.SchemaPrefixReference; +import com.intellij.psi.xml.XmlAttribute; +import com.intellij.psi.xml.XmlAttributeValue; +import com.intellij.psi.xml.XmlTag; +import com.intellij.util.ProcessingContext; +import com.intellij.xml.XmlAttributeDescriptor; +import com.intellij.xml.impl.schema.XmlAttributeDescriptorImpl; +import com.intellij.xml.impl.schema.XmlNSDescriptorImpl; +import org.jetbrains.annotations.NotNull; + +/** + * @author Dmitry Avdeev + */ +public class XmlPrefixReferenceProvider extends PsiReferenceProvider { + + @NotNull + @Override + public PsiReference[] getReferencesByElement(@NotNull PsiElement element, @NotNull ProcessingContext context) { + XmlAttributeValue attributeValue = (XmlAttributeValue)element; + PsiElement parent = attributeValue.getParent(); + if (parent instanceof XmlAttribute && !XmlNSDescriptorImpl.checkSchemaNamespace(((XmlAttribute)parent).getParent())) { + XmlAttributeDescriptor descriptor = ((XmlAttribute)parent).getDescriptor(); + if (descriptor instanceof XmlAttributeDescriptorImpl) { + String type = ((XmlAttributeDescriptorImpl)descriptor).getType(); + if (type != null && type.endsWith(":QName")) { + String prefix = XmlUtil.findPrefixByQualifiedName(type); + String ns = ((XmlTag)descriptor.getDeclaration()).getNamespaceByPrefix(prefix); + if (XmlNSDescriptorImpl.checkSchemaNamespace(ns)) { + String value = attributeValue.getValue(); + if (value != null) { + int i = value.indexOf(':'); + if (i > 0) { + return new PsiReference[] { + new SchemaPrefixReference(attributeValue, TextRange.from(1, i), value.substring(0, i), null) + }; + } + } + } + } + } + } + return PsiReference.EMPTY_ARRAY; + } +} diff --git a/xml/impl/src/com/intellij/xml/util/XmlReferenceContributor.java b/xml/impl/src/com/intellij/xml/util/XmlReferenceContributor.java index d1e490191d26..872d17462e20 100644 --- a/xml/impl/src/com/intellij/xml/util/XmlReferenceContributor.java +++ b/xml/impl/src/com/intellij/xml/util/XmlReferenceContributor.java @@ -2,10 +2,8 @@ package com.intellij.xml.util; import com.intellij.codeInsight.daemon.impl.analysis.encoding.XmlEncodingReferenceProvider; import com.intellij.patterns.PlatformPatterns; -import static com.intellij.patterns.StandardPatterns.string; -import static com.intellij.patterns.XmlPatterns.*; +import com.intellij.patterns.XmlPatterns; import com.intellij.psi.PsiReferenceContributor; -import com.intellij.psi.PsiReferenceProvider; import com.intellij.psi.PsiReferenceRegistrar; import com.intellij.psi.filters.*; import com.intellij.psi.filters.position.NamespaceFilter; @@ -16,6 +14,9 @@ import com.intellij.psi.impl.source.resolve.reference.impl.providers.SchemaRefer import com.intellij.psi.impl.source.resolve.reference.impl.providers.URIReferenceProvider; import com.intellij.psi.xml.*; +import static com.intellij.patterns.StandardPatterns.string; +import static com.intellij.patterns.XmlPatterns.*; + /** * @author peter */ @@ -79,5 +80,7 @@ public class XmlReferenceContributor extends PsiReferenceContributor { XmlUtil.registerXmlAttributeValueReferenceProvider(registrar, new String[] {"encoding"}, new ScopeFilter(new ParentElementFilter(new ClassFilter(XmlProcessingInstruction.class))), true, new XmlEncodingReferenceProvider()); + + registrar.registerReferenceProvider(XmlPatterns.xmlAttributeValue(), new XmlPrefixReferenceProvider()); } }