diff --git a/java/java-tests/testData/codeInsight/completion/normalSorting/PreselectClosestExactPrefixItem.java b/java/java-tests/testData/codeInsight/completion/normalSorting/PreselectClosestExactPrefixItem.java new file mode 100644 index 000000000000..97a71ca1cc16 --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/normalSorting/PreselectClosestExactPrefixItem.java @@ -0,0 +1,6 @@ +import pack2.SameNamed; + +public class Usage { + private SameNamed f; + +} diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionOrderingTest.groovy b/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionOrderingTest.groovy index 33e05c6eff41..def3bfe930ac 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionOrderingTest.groovy +++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionOrderingTest.groovy @@ -787,4 +787,13 @@ class ContainerUtil extends ContainerUtilRt { checkPreferredItems 0, 'catch', 'finally' } + void testPreselectClosestExactPrefixItem() { + UISettings.instance.SORT_LOOKUP_ELEMENTS_LEXICOGRAPHICALLY = true + myFixture.addClass 'package pack1; public class SameNamed {}' + myFixture.addClass 'package pack2; public class SameNamed {}' + checkPreferredItems 1, 'SameNamed', 'SameNamed' + assert LookupElementPresentation.renderElement(myFixture.lookupElements[0]).tailText.contains('pack1') + assert LookupElementPresentation.renderElement(myFixture.lookupElements[1]).tailText.contains('pack2') + } + } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionLookupArranger.java b/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionLookupArranger.java index 7abcd019f078..4f48a81abf10 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionLookupArranger.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionLookupArranger.java @@ -39,6 +39,7 @@ import com.intellij.patterns.StandardPatterns; import com.intellij.psi.statistics.StatisticsInfo; import com.intellij.util.Alarm; import com.intellij.util.ProcessingContext; +import com.intellij.util.SmartList; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.MultiMap; import com.intellij.util.containers.hash.EqualityPolicy; @@ -391,31 +392,40 @@ public class CompletionLookupArranger extends LookupArranger { } } + LookupElement exactMatch = getBestExactMatch(lookup, items); + return Math.max(0, ContainerUtil.indexOfIdentity(items, exactMatch != null ? exactMatch : mostRelevant)); + } + + private List getExactMatches(LookupImpl lookup, List items) { String selectedText = lookup.getTopLevelEditor().getSelectionModel().getSelectedText(); - int exactMatchIndex = -1; + List exactMatches = new SmartList<>(); for (int i = 0; i < items.size(); i++) { LookupElement item = items.get(i); boolean isSuddenLiveTemplate = isSuddenLiveTemplate(item); if (isPrefixItem(item, true) && !isSuddenLiveTemplate || item.getLookupString().equals(selectedText)) { if (item instanceof LiveTemplateLookupElement) { // prefer most recent live template lookup item - exactMatchIndex = i; - break; - } - if (exactMatchIndex == -1) { - // prefer most recent item - exactMatchIndex = i; + return Collections.singletonList(item); } + exactMatches.add(item); } else if (i == 0 && isSuddenLiveTemplate && items.size() > 1 && !CompletionServiceImpl.isStartMatch(items.get(1), this)) { - return 0; + return Collections.singletonList(item); } } - if (exactMatchIndex >= 0) { - return exactMatchIndex; + return exactMatches; + } + + @Nullable + private LookupElement getBestExactMatch(LookupImpl lookup, List items) { + List exactMatches = getExactMatches(lookup, items); + if (exactMatches.isEmpty()) return null; + + if (exactMatches.size() == 1) { + return exactMatches.get(0); } - return Math.max(0, ContainerUtil.indexOfIdentity(items, mostRelevant)); + return sortByRelevance(groupItemsBySorter(exactMatches)).iterator().next(); } @Nullable