From f2a398f755348a9c1712717f32001ffbc0f09173 Mon Sep 17 00:00:00 2001 From: Tor Norbye Date: Wed, 17 Sep 2014 17:20:29 -0700 Subject: IDEA-129977: Offer quickfixes for unbound attributes Change-Id: Id8e645746a5e68edb9178a560a6f43fbd04360a3 --- .../analysis/CreateNSDeclarationIntentionFix.java | 51 +++++++++++++++++----- .../daemon/impl/analysis/ImportNSAction.java | 14 +++--- .../src/com/intellij/xml/XmlNamespaceHelper.java | 9 ++++ .../analysis/XmlUnboundNsPrefixInspection.java | 5 +++ 4 files changed, 61 insertions(+), 18 deletions(-) diff --git a/xml/impl/src/com/intellij/codeInsight/daemon/impl/analysis/CreateNSDeclarationIntentionFix.java b/xml/impl/src/com/intellij/codeInsight/daemon/impl/analysis/CreateNSDeclarationIntentionFix.java index 88d639a09127..a06a24a43509 100644 --- a/xml/impl/src/com/intellij/codeInsight/daemon/impl/analysis/CreateNSDeclarationIntentionFix.java +++ b/xml/impl/src/com/intellij/codeInsight/daemon/impl/analysis/CreateNSDeclarationIntentionFix.java @@ -45,16 +45,14 @@ import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import com.intellij.psi.impl.cache.impl.id.IdTableBuilding; import com.intellij.psi.meta.PsiMetaData; -import com.intellij.psi.xml.XmlDocument; -import com.intellij.psi.xml.XmlFile; -import com.intellij.psi.xml.XmlTag; -import com.intellij.psi.xml.XmlToken; +import com.intellij.psi.xml.*; import com.intellij.ui.components.JBList; import com.intellij.util.ArrayUtil; import com.intellij.util.IncorrectOperationException; -import com.intellij.xml.XmlNamespaceHelper; import com.intellij.xml.XmlElementDescriptor; import com.intellij.xml.XmlExtension; +import com.intellij.xml.XmlNamespaceHelper; +import com.intellij.xml.XmlSchemaProvider; import com.intellij.xml.impl.schema.AnyXmlElementDescriptor; import com.intellij.xml.impl.schema.XmlNSDescriptorImpl; import com.intellij.xml.util.XmlUtil; @@ -63,7 +61,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; -import java.util.Arrays; +import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Set; @@ -144,15 +142,32 @@ public class CreateNSDeclarationIntentionFix implements HintAction, LocalQuickFi return element != null && element.isValid(); } + /** Looks up the unbound namespaces and sorts them */ + @NotNull + private List getNamespaces(PsiElement element, XmlFile xmlFile) { + if (element instanceof XmlAttribute) { + element = element.getParent(); + } + Set set = getXmlExtension().guessUnboundNamespaces(element, xmlFile); + + final String match = getUnboundNamespaceForPrefix(myNamespacePrefix, xmlFile, set); + if (match != null) { + return Collections.singletonList(match); + } + + List namespaces = new ArrayList(set); + Collections.sort(namespaces); + return namespaces; + } + @Override public void invoke(@NotNull final Project project, final Editor editor, final PsiFile file) throws IncorrectOperationException { if (!FileModificationService.getInstance().prepareFileForWrite(file)) return; final PsiElement element = myElement.retrieve(); if (element == null) return; - final Set set = getXmlExtension().guessUnboundNamespaces(element, getFile()); - final String[] namespaces = ArrayUtil.toStringArray(set); - Arrays.sort(namespaces); + XmlFile xmlFile = getFile(); + final String[] namespaces = ArrayUtil.toStringArray(getNamespaces(element, xmlFile)); runActionOverSeveralAttributeValuesAfterLettingUserSelectTheNeededOne( namespaces, @@ -195,6 +210,22 @@ public class CreateNSDeclarationIntentionFix implements HintAction, LocalQuickFi editor); } + /** Given a prefix in a file and a set of candidate namespaces, returns the namespace that matches the prefix (if any) + * as determined by the {@link com.intellij.xml.XmlSchemaProvider#getDefaultPrefix(String, com.intellij.psi.xml.XmlFile)} + * implementations */ + @Nullable + public static String getUnboundNamespaceForPrefix(String prefix, XmlFile xmlFile, Set namespaces) { + final List providers = XmlSchemaProvider.getAvailableProviders(xmlFile); + for (XmlSchemaProvider provider : providers) { + for (String namespace : namespaces) { + if (prefix.equals(provider.getDefaultPrefix(namespace, xmlFile))) { + return namespace; + } + } + } + return null; + } + private String getTitle() { return XmlErrorMessages.message("select.namespace.title", StringUtil.capitalize(getXmlExtension().getNamespaceAlias(getFile()))); } @@ -216,7 +247,7 @@ public class CreateNSDeclarationIntentionFix implements HintAction, LocalQuickFi } final PsiElement element = myElement.retrieve(); if (element == null) return false; - final Set namespaces = getXmlExtension().guessUnboundNamespaces(element, getFile()); + final List namespaces = getNamespaces(element, getFile()); if (!namespaces.isEmpty()) { final String message = ShowAutoImportPass.getMessage(namespaces.size() > 1, namespaces.iterator().next()); final String title = getTitle(); diff --git a/xml/impl/src/com/intellij/codeInsight/daemon/impl/analysis/ImportNSAction.java b/xml/impl/src/com/intellij/codeInsight/daemon/impl/analysis/ImportNSAction.java index d3afcd58640c..24917fdeaee5 100644 --- a/xml/impl/src/com/intellij/codeInsight/daemon/impl/analysis/ImportNSAction.java +++ b/xml/impl/src/com/intellij/codeInsight/daemon/impl/analysis/ImportNSAction.java @@ -25,27 +25,26 @@ import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiElement; import com.intellij.psi.xml.XmlFile; import com.intellij.ui.components.JBList; +import com.intellij.util.ArrayUtil; import com.intellij.util.IncorrectOperationException; import com.intellij.xml.XmlNamespaceHelper; import org.jetbrains.annotations.NotNull; import javax.swing.*; -import java.util.Arrays; import java.util.Collections; -import java.util.Set; +import java.util.List; /** * @author Dmitry Avdeev */ public class ImportNSAction implements QuestionAction { - private final Set myNamespaces; + private final List myNamespaces; private final XmlFile myFile; private final PsiElement myElement; private final Editor myEditor; private final String myTitle; - public ImportNSAction(final Set namespaces, XmlFile file, @NotNull PsiElement element, Editor editor, final String title) { - + public ImportNSAction(final List namespaces, XmlFile file, @NotNull PsiElement element, Editor editor, final String title) { myNamespaces = namespaces; myFile = file; myElement = element; @@ -55,9 +54,8 @@ public class ImportNSAction implements QuestionAction { @Override public boolean execute() { - final Object[] objects = myNamespaces.toArray(); - Arrays.sort(objects); - final JList list = new JBList(objects); + final String[] strings = ArrayUtil.toStringArray(myNamespaces); + final JList list = new JBList(strings); list.setCellRenderer(XmlNSRenderer.INSTANCE); list.setSelectedIndex(0); final int offset = myElement.getTextOffset(); diff --git a/xml/impl/src/com/intellij/xml/XmlNamespaceHelper.java b/xml/impl/src/com/intellij/xml/XmlNamespaceHelper.java index 797ae43a8ad3..058e989f3bb6 100644 --- a/xml/impl/src/com/intellij/xml/XmlNamespaceHelper.java +++ b/xml/impl/src/com/intellij/xml/XmlNamespaceHelper.java @@ -19,8 +19,10 @@ import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.extensions.ExtensionPointName; import com.intellij.openapi.extensions.Extensions; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; +import com.intellij.psi.xml.XmlAttribute; import com.intellij.psi.xml.XmlFile; import com.intellij.psi.xml.XmlTag; import com.intellij.util.IncorrectOperationException; @@ -55,6 +57,13 @@ public abstract class XmlNamespaceHelper { @Nullable public String getNamespacePrefix(PsiElement element) { + if (element instanceof XmlAttribute) { + XmlAttribute attribute = (XmlAttribute)element; + String prefix = attribute.getNamespacePrefix(); + if (!StringUtil.isEmpty(prefix)) { + return prefix; + } + } final PsiElement tag = element instanceof XmlTag ? element : element.getParent(); if (tag instanceof XmlTag) { return ((XmlTag)tag).getNamespacePrefix(); diff --git a/xml/xml-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/XmlUnboundNsPrefixInspection.java b/xml/xml-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/XmlUnboundNsPrefixInspection.java index a8bd40221ce9..fc05a4849506 100644 --- a/xml/xml-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/XmlUnboundNsPrefixInspection.java +++ b/xml/xml-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/XmlUnboundNsPrefixInspection.java @@ -152,6 +152,11 @@ public class XmlUnboundNsPrefixInspection extends XmlSuppressableInspectionTool LocalQuickFix fix = isOnTheFly ? XmlQuickFixFactory.getInstance().createNSDeclarationIntentionFix(context, namespacePrefix, token) : null; reportTagProblem(element, localizedMessage, range, highlightType, fix, holder); } + else if (element instanceof XmlAttribute) { + LocalQuickFix fix = isOnTheFly ? XmlQuickFixFactory.getInstance().createNSDeclarationIntentionFix(element, namespacePrefix, token) : null; + XmlAttribute attribute = (XmlAttribute)element; + holder.registerProblem(attribute.getNameElement(), localizedMessage, highlightType, range, fix); + } else { holder.registerProblem(element, localizedMessage, highlightType, range); } -- cgit v1.2.3