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 110f637b5522..68aba5f3c3ab 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionLookupArranger.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionLookupArranger.java @@ -35,8 +35,6 @@ import com.intellij.psi.WeighingService; import com.intellij.psi.statistics.StatisticsInfo; import com.intellij.psi.statistics.StatisticsManager; import com.intellij.util.Alarm; -import com.intellij.util.SmartList; -import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.FactoryMap; import com.intellij.util.containers.MultiMap; import gnu.trove.THashMap; @@ -50,8 +48,10 @@ public class CompletionLookupArranger extends LookupArranger { @Nullable private static StatisticsUpdate ourPendingUpdate; private static final Alarm ourStatsAlarm = new Alarm(ApplicationManager.getApplication()); private static final Key PRESENTATION_INVARIANT = Key.create("PRESENTATION_INVARIANT"); + private static final int MAX_PREFERRED_COUNT = 5; private final List myFrozenItems = new ArrayList(); - + private static final String SELECTED = "selected"; + static final String IGNORED = "ignored"; static { Disposer.register(ApplicationManager.getApplication(), new Disposable() { @Override @@ -61,8 +61,6 @@ public class CompletionLookupArranger extends LookupArranger { }); } - private static final String SELECTED = "selected"; - static final String IGNORED = "ignored"; private final CompletionLocation myLocation; @SuppressWarnings("unchecked") private final Map mySortingWeights = new THashMap(TObjectHashingStrategy.IDENTITY); private final CompletionParameters myParameters; @@ -152,24 +150,24 @@ public class CompletionLookupArranger extends LookupArranger { MultiMap inputBySorter = groupInputBySorter(items); - final List> groups = new ArrayList>(); + final List byRelevance = new ArrayList(); for (CompletionSorterImpl sorter : myClassifiers.keySet()) { - ContainerUtil.addAll(groups, myClassifiers.get(sorter).classify((List)inputBySorter.get(sorter))); + for (List elements : myClassifiers.get(sorter).classify((List)inputBySorter.get(sorter))) { + byRelevance.addAll(elements); + } } LinkedHashSet model = new LinkedHashSet(); - for (List group : groups) { - addPrefixItems(lookup, model, true, group); - } - for (List group : groups) { - addPrefixItems(lookup, model, false, group); - } + addPrefixItems(lookup, model, true, byRelevance); + addPrefixItems(lookup, model, false, byRelevance); myFrozenItems.retainAll(items); model.addAll(myFrozenItems); if (!isAlphaSorted()) { - addMostRelevantItems(model, groups); + for (int i = 0; i < byRelevance.size() && model.size() < MAX_PREFERRED_COUNT; i++) { + model.add(byRelevance.get(i)); + } LookupElement lastSelection = lookup.getCurrentItem(); if (items.contains(lastSelection)) { model.add(lastSelection); @@ -177,6 +175,7 @@ public class CompletionLookupArranger extends LookupArranger { } myFrozenItems.clear(); + if (((LookupImpl)lookup).isShown()) { myFrozenItems.addAll(model); } @@ -190,59 +189,51 @@ public class CompletionLookupArranger extends LookupArranger { }); model.addAll(items); } else { - for (List group : groups) { - model.addAll(group); - } + model.addAll(byRelevance); } ArrayList listModel = new ArrayList(model); - return new Pair, Integer>(listModel, getItemToSelect(lookup, groups, listModel)); + return new Pair, Integer>(listModel, getItemToSelect(lookup, byRelevance, listModel)); } + @Override public LookupArranger createEmptyCopy() { return new CompletionLookupArranger(myParameters, myProcess); } - private int getItemToSelect(Lookup lookup, Iterable> groups, List items) { + private int getItemToSelect(Lookup lookup, List byRelevance, List items) { if (items.isEmpty() || !lookup.isFocused()) { return 0; } - if (!lookup.isSelectionTouched()) { - LookupElement first = items.get(0); - if (isExactPrefixItem(lookup, first, true) && !isLiveTemplate(first)) { - return 0; + if (lookup.isSelectionTouched()) { + LookupElement lastSelection = lookup.getCurrentItem(); + int old = items.indexOf(lastSelection); + if (old >= 0) { + return old; } - } - LookupElement lastSelection = lookup.getCurrentItem(); - int old = items.indexOf(lastSelection); - if (old >= 0) { - return old; - } - - for (int i = 0; i < items.size(); i++) { - String invariant = PRESENTATION_INVARIANT.get(items.get(i)); - if (invariant != null && invariant.equals(PRESENTATION_INVARIANT.get(lastSelection))) { - return i; + for (int i = 0; i < items.size(); i++) { + String invariant = PRESENTATION_INVARIANT.get(items.get(i)); + if (invariant != null && invariant.equals(PRESENTATION_INVARIANT.get(lastSelection))) { + return i; + } } } for (int i = 0; i < items.size(); i++) { LookupElement item = items.get(i); - if (isExactPrefixItem(lookup, item, true) && !isLiveTemplate(item)) { + if (isPrefixItem(lookup, item, true) && !isLiveTemplate(item)) { return i; } } final CompletionPreselectSkipper[] skippers = CompletionPreselectSkipper.EP_NAME.getExtensions(); - for (List group : groups) { - for (LookupElement element : group) { - if (!shouldSkip(skippers, element)) { - return items.indexOf(element); - } + for (LookupElement element : byRelevance) { + if (!shouldSkip(skippers, element)) { + return items.indexOf(element); } } @@ -253,24 +244,6 @@ public class CompletionLookupArranger extends LookupArranger { return element instanceof LiveTemplateLookupElement && ((LiveTemplateLookupElement)element).sudden; } - private static final int MAX_PREFERRED_COUNT = 5; - private static void addMostRelevantItems(final Set model, final Iterable> sortedItems) { - if (model.size() > MAX_PREFERRED_COUNT) return; - - for (final List elements : sortedItems) { - final List suitable = new SmartList(); - for (final LookupElement item : elements) { - if (!model.contains(item)) { - suitable.add(item); - } - } - - if (model.size() + suitable.size() > MAX_PREFERRED_COUNT) break; - model.addAll(suitable); - } - } - - public static StatisticsUpdate collectStatisticChanges(CompletionProgressIndicator indicator, LookupElement item) { LookupImpl lookupImpl = indicator.getLookup(); applyLastCompletionStatisticsUpdate(); diff --git a/platform/lang-impl/src/com/intellij/codeInsight/lookup/LookupArranger.java b/platform/lang-impl/src/com/intellij/codeInsight/lookup/LookupArranger.java index aa558fdb49c4..5aee53c4232e 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/lookup/LookupArranger.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/lookup/LookupArranger.java @@ -43,28 +43,25 @@ public abstract class LookupArranger { public abstract LookupArranger createEmptyCopy(); - protected static void addPrefixItems(Lookup lookup, LinkedHashSet result, boolean caseSensitive, Collection items) { + protected static void addPrefixItems(Lookup lookup, LinkedHashSet result, boolean exactly, Collection items) { for (LookupElement element : items) { - if (isExactPrefixItem(lookup, element, caseSensitive)) { + if (isPrefixItem(lookup, element, exactly)) { result.add(element); } } } - protected static boolean isExactPrefixItem(Lookup lookup, LookupElement item, final boolean caseSensitive) { + protected static boolean isPrefixItem(Lookup lookup, LookupElement item, final boolean exactly) { final String pattern = lookup.itemPattern(item); - final Set strings = item.getAllLookupStrings(); - if (strings.contains(pattern)) { - return caseSensitive; //to not add the same elements twice to the model, as sensitive and then as insensitive + if (pattern.equals(item.getLookupString())) { + return true; } - if (caseSensitive) { - return false; - } - - for (String s : strings) { - if (s.equalsIgnoreCase(pattern)) { - return true; + if (!exactly) { + for (String s : item.getAllLookupStrings()) { + if (s.equalsIgnoreCase(pattern)) { + return true; + } } } return false;