diff --git a/xml/impl/src/com/intellij/codeInsight/completion/XmlLocationCompletionContributor.java b/xml/impl/src/com/intellij/codeInsight/completion/XmlLocationCompletionContributor.java index cc7b8ceb2679..c1ee129a445b 100644 --- a/xml/impl/src/com/intellij/codeInsight/completion/XmlLocationCompletionContributor.java +++ b/xml/impl/src/com/intellij/codeInsight/completion/XmlLocationCompletionContributor.java @@ -34,12 +34,14 @@ import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.MultiMap; import com.intellij.xml.XmlNamespaceHelper; import com.intellij.xml.XmlSchemaProvider; +import com.intellij.xml.index.XmlNamespaceIndex; import org.jetbrains.annotations.NotNull; import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.Set; +import java.util.stream.Collectors; /** * @author Dmitry Avdeev @@ -81,11 +83,6 @@ public class XmlLocationCompletionContributor extends CompletionContributor { private static Object[] completeNamespace(PsiElement myElement) { final XmlFile file = (XmlFile)myElement.getContainingFile(); PsiElement parent = myElement.getParent(); - final Set preferred = new HashSet<>(); - if (parent instanceof XmlAttribute && "xmlns".equals(((XmlAttribute)parent).getName())) { - XmlNamespaceHelper helper = XmlNamespaceHelper.getHelper(file); - preferred.addAll(helper.guessUnboundNamespaces(parent.getParent(), file)); - } Set list = new HashSet<>(); for (XmlSchemaProvider provider : Extensions.getExtensions(XmlSchemaProvider.EP_NAME)) { if (provider.isAvailable(file)) { @@ -95,7 +92,13 @@ public class XmlLocationCompletionContributor extends CompletionContributor { if (!list.isEmpty()) { return ArrayUtil.toObjectArray(list); } - Object[] resourceUrls = ExternalResourceManagerEx.getInstanceEx().getUrlsByNamespace(myElement.getProject()).keySet().toArray(); + Set set = new HashSet<>(ExternalResourceManagerEx.getInstanceEx().getUrlsByNamespace(myElement.getProject()).keySet()); + Set fromIndex = + XmlNamespaceIndex.getAllResources(null, myElement.getProject(), null).stream() + .filter(resource -> "xsd".equals(resource.getFile().getExtension())).map(resource -> resource.getValue().getNamespace()) + .collect(Collectors.toSet()); + ContainerUtil.addAllNotNull(set, fromIndex); + Object[] resourceUrls = set.toArray(); final XmlDocument document = file.getDocument(); assert document != null; XmlTag rootTag = document.getRootTag(); @@ -107,6 +110,11 @@ public class XmlLocationCompletionContributor extends CompletionContributor { }); resourceUrls = ArrayUtil.mergeArrays(resourceUrls, ArrayUtil.toStringArray(additionalNs)); + final Set preferred = new HashSet<>(); + if (parent instanceof XmlAttribute && "xmlns".equals(((XmlAttribute)parent).getName())) { + XmlNamespaceHelper helper = XmlNamespaceHelper.getHelper(file); + preferred.addAll(helper.guessUnboundNamespaces(parent.getParent(), file)); + } return ContainerUtil.map2Array(resourceUrls, o -> { LookupElementBuilder builder = LookupElementBuilder.create(o); return preferred.contains(o) ? PrioritizedLookupElement.withPriority(builder, 100) : builder; diff --git a/xml/tests/src/com/intellij/codeInsight/completion/XmlCompletionTest.java b/xml/tests/src/com/intellij/codeInsight/completion/XmlCompletionTest.java index 999b84bae65b..7b1f86700f18 100644 --- a/xml/tests/src/com/intellij/codeInsight/completion/XmlCompletionTest.java +++ b/xml/tests/src/com/intellij/codeInsight/completion/XmlCompletionTest.java @@ -34,6 +34,7 @@ import com.intellij.psi.statistics.impl.StatisticsManagerImpl; import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase; import com.intellij.xml.util.XmlUtil; +import java.util.Arrays; import java.util.List; /** @@ -755,6 +756,12 @@ public class XmlCompletionTest extends LightCodeInsightFixtureTestCase { assertTrue(myFixture.getLookupElementStrings().size() > 3); // all standard schemas actually } + public void testCustomNamespaceCompletion() { + myFixture.configureByFiles("main.xsd", "sub.xsd"); + LookupElement[] elements = myFixture.completeBasic(); + assertTrue(Arrays.stream(elements).anyMatch(element -> "http://www.test.com/sub".equals(element.getLookupString()))); + } + public void testRootTagCompletion() { boolean old = CodeInsightSettings.getInstance().AUTOCOMPLETE_ON_CODE_COMPLETION; CodeInsightSettings.getInstance().AUTOCOMPLETE_ON_CODE_COMPLETION = false; diff --git a/xml/tests/testData/completion/main.xsd b/xml/tests/testData/completion/main.xsd new file mode 100644 index 000000000000..1fb6b6a2ca6d --- /dev/null +++ b/xml/tests/testData/completion/main.xsd @@ -0,0 +1,8 @@ + + + + + \ No newline at end of file diff --git a/xml/tests/testData/completion/sub.xsd b/xml/tests/testData/completion/sub.xsd new file mode 100644 index 000000000000..c63e560e5e5f --- /dev/null +++ b/xml/tests/testData/completion/sub.xsd @@ -0,0 +1,7 @@ + + + + \ No newline at end of file