From f5daffd10761c72b4bdc3a09a876b05f8e38aa94 Mon Sep 17 00:00:00 2001 From: peter Date: Fri, 29 Jun 2012 22:00:03 +0200 Subject: [PATCH] IDEA-88058 Completion popup: toggling alpha vs. usage sorting blocks UI --- .../completion/CompletionSortingTestCase.java | 2 +- .../completion/PrefixMatchingWeigher.java | 47 --------------- .../impl/CompletionServiceImpl.java | 60 ++++++++++++++++++- .../codeInsight/lookup/LookupArranger.java | 5 -- .../codeInsight/lookup/impl/LookupImpl.java | 13 ++-- 5 files changed, 67 insertions(+), 60 deletions(-) diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/CompletionSortingTestCase.java b/java/java-tests/testSrc/com/intellij/codeInsight/completion/CompletionSortingTestCase.java index f2ddcd3f4cc6..79820459b6cf 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/CompletionSortingTestCase.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/CompletionSortingTestCase.java @@ -71,7 +71,7 @@ public abstract class CompletionSortingTestCase extends LightFixtureCompletionTe protected static void refreshSorting(final LookupImpl lookup) { lookup.setSelectionTouched(false); - lookup.resort(); + lookup.resort(true); } protected static void imitateItemSelection(final LookupImpl lookup, final int index) { diff --git a/platform/lang-impl/src/com/intellij/codeInsight/completion/PrefixMatchingWeigher.java b/platform/lang-impl/src/com/intellij/codeInsight/completion/PrefixMatchingWeigher.java index 8c9b887c278a..1dff28843f05 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/completion/PrefixMatchingWeigher.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/completion/PrefixMatchingWeigher.java @@ -15,17 +15,9 @@ */ package com.intellij.codeInsight.completion; -import com.intellij.codeInsight.CodeInsightSettings; -import com.intellij.codeInsight.completion.impl.CamelHumpMatcher; import com.intellij.codeInsight.lookup.LookupElement; -import com.intellij.openapi.util.TextRange; -import com.intellij.openapi.util.text.StringUtil; -import com.intellij.psi.codeStyle.MinusculeMatcher; -import com.intellij.psi.codeStyle.NameUtil; import org.jetbrains.annotations.NotNull; -import java.util.Iterator; - /** * @author peter */ @@ -35,43 +27,4 @@ public class PrefixMatchingWeigher extends CompletionWeigher { public Comparable weigh(@NotNull LookupElement element, @NotNull CompletionLocation location) { throw new UnsupportedOperationException("Not implemented"); } - - public static int getPrefixMatchingDegree(LookupElement item, CompletionLocation location) { - final MinusculeMatcher matcher = getMinusculeMatcher(location.getCompletionParameters().getLookup().itemPattern(item)); - - int max = Integer.MIN_VALUE; - for (String lookupString : item.getAllLookupStrings()) { - max = Math.max(max, matcher.matchingDegree(lookupString)); - } - return max; - } - - private static MinusculeMatcher getMinusculeMatcher(String prefix) { - final int setting = CodeInsightSettings.getInstance().COMPLETION_CASE_SENSITIVE; - final NameUtil.MatchingCaseSensitivity sensitivity = - setting == CodeInsightSettings.NONE ? NameUtil.MatchingCaseSensitivity.NONE : - setting == CodeInsightSettings.FIRST_LETTER ? NameUtil.MatchingCaseSensitivity.FIRST_LETTER : NameUtil.MatchingCaseSensitivity.ALL; - return new MinusculeMatcher(CamelHumpMatcher.applyMiddleMatching(prefix), sensitivity); - } - - public static boolean isMiddleMatch(LookupElement element, CompletionLocation location) { - String prefix = location.getCompletionParameters().getLookup().itemPattern(element); - if (StringUtil.isNotEmpty(prefix)) { - MinusculeMatcher matcher = getMinusculeMatcher(prefix); - for (String ls : element.getAllLookupStrings()) { - Iterable fragments = matcher.matchingFragments(ls); - if (fragments != null) { - Iterator iterator = fragments.iterator(); - if (!ls.isEmpty() && prefix.charAt(0) == ls.charAt(0)) { - return false; - } - if (iterator.hasNext() && iterator.next().contains(0)) { - return false; - } - } - } - } - return true; - } - } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/completion/impl/CompletionServiceImpl.java b/platform/lang-impl/src/com/intellij/codeInsight/completion/impl/CompletionServiceImpl.java index 2d8c4eb47a3f..ba7543e680da 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/completion/impl/CompletionServiceImpl.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/completion/impl/CompletionServiceImpl.java @@ -15,6 +15,7 @@ */ package com.intellij.codeInsight.completion.impl; +import com.intellij.codeInsight.CodeInsightSettings; import com.intellij.codeInsight.completion.*; import com.intellij.codeInsight.lookup.*; import com.intellij.openapi.application.ApplicationManager; @@ -25,11 +26,16 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.project.ProjectManager; import com.intellij.openapi.project.ProjectManagerAdapter; import com.intellij.openapi.util.Disposer; +import com.intellij.openapi.util.Pair; +import com.intellij.openapi.util.TextRange; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.patterns.ElementPattern; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import com.intellij.psi.Weigher; import com.intellij.psi.WeighingService; +import com.intellij.psi.codeStyle.MinusculeMatcher; +import com.intellij.psi.codeStyle.NameUtil; import com.intellij.psi.impl.DebugUtil; import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil; import com.intellij.util.Consumer; @@ -37,6 +43,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.ArrayList; +import java.util.Iterator; /** * @author peter @@ -45,6 +52,7 @@ public class CompletionServiceImpl extends CompletionService{ private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.completion.impl.CompletionServiceImpl"); private static volatile CompletionPhase ourPhase = CompletionPhase.NoCompletion; private static String ourPhaseTrace; + private static CodeInsightSettings ourSettings = CodeInsightSettings.getInstance(); public CompletionServiceImpl() { ProjectManager.getInstance().addProjectManagerListener(new ProjectManagerAdapter() { @@ -103,6 +111,54 @@ public class CompletionServiceImpl extends CompletionService{ return null; } + private static int getPrefixMatchingDegree(LookupElement item, CompletionLocation location) { + final MinusculeMatcher matcher = getMinusculeMatcher(location.getCompletionParameters().getLookup().itemPattern(item)); + + int max = Integer.MIN_VALUE; + for (String lookupString : item.getAllLookupStrings()) { + max = Math.max(max, matcher.matchingDegree(lookupString)); + } + return max; + } + + private static volatile Pair lastMatcher; + + private static MinusculeMatcher getMinusculeMatcher(String prefix) { + final int setting = ourSettings.COMPLETION_CASE_SENSITIVE; + final NameUtil.MatchingCaseSensitivity sensitivity = + setting == CodeInsightSettings.NONE ? NameUtil.MatchingCaseSensitivity.NONE : + setting == CodeInsightSettings.FIRST_LETTER ? NameUtil.MatchingCaseSensitivity.FIRST_LETTER : NameUtil.MatchingCaseSensitivity.ALL; + + Pair pair = lastMatcher; + if (pair != null && pair.first.equals(prefix)) { + return pair.second; + } + + MinusculeMatcher matcher = new MinusculeMatcher(CamelHumpMatcher.applyMiddleMatching(prefix), sensitivity); + lastMatcher = Pair.create(prefix, matcher); + return matcher; + } + + private static boolean isMiddleMatch(LookupElement element, CompletionLocation location) { + String prefix = location.getCompletionParameters().getLookup().itemPattern(element); + if (StringUtil.isNotEmpty(prefix)) { + MinusculeMatcher matcher = getMinusculeMatcher(prefix); + for (String ls : element.getAllLookupStrings()) { + Iterable fragments = matcher.matchingFragments(ls); + if (fragments != null) { + Iterator iterator = fragments.iterator(); + if (!ls.isEmpty() && prefix.charAt(0) == ls.charAt(0)) { + return false; + } + if (iterator.hasNext() && iterator.next().contains(0)) { + return false; + } + } + } + } + return true; + } + private static class CompletionResultSetImpl extends CompletionResultSet { private final String myTextBeforePosition; private final CompletionParameters myParameters; @@ -244,7 +300,7 @@ public class CompletionServiceImpl extends CompletionService{ @NotNull @Override public Comparable getWeight(LookupElement element) { - return PrefixMatchingWeigher.isMiddleMatch(element, location); + return isMiddleMatch(element, location); } }; } @@ -260,7 +316,7 @@ public class CompletionServiceImpl extends CompletionService{ @NotNull @Override public Comparable getWeight(LookupElement element) { - return -PrefixMatchingWeigher.getPrefixMatchingDegree(element, location); + return -getPrefixMatchingDegree(element, location); } }; } 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 cdfc8ec5570c..b82a82849ba3 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/lookup/LookupArranger.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/lookup/LookupArranger.java @@ -36,11 +36,6 @@ public abstract class LookupArranger { public abstract Pair, Integer> arrangeItems(@NotNull Lookup lookup, boolean onExplicitAction); - public final void clearItems() { - prefixChanged(); - myItems.clear(); - } - public abstract LookupArranger createEmptyCopy(); protected static void addPrefixItems(Lookup lookup, LinkedHashSet result, boolean exactly, Collection items) { diff --git a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupImpl.java b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupImpl.java index eda7893855a9..70bd5d7e91cd 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupImpl.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupImpl.java @@ -260,7 +260,7 @@ public class LookupImpl extends LightweightHint implements LookupEx, Disposable mySortingLabel.setIcon(lexi ? lexiSortIcon : relevanceSortIcon); mySortingLabel.setToolTipText(lexi ? "Click to sort variants by relevance" : "Click to sort variants alphabetically"); - resort(); + resort(false); } public void setArranger(LookupArranger arranger) { @@ -314,7 +314,7 @@ public class LookupImpl extends LightweightHint implements LookupEx, Disposable mySelectionTouched = selectionTouched; } - public void resort() { + public void resort(boolean addAgain) { final List items = getItems(); synchronized (myList) { @@ -322,8 +322,10 @@ public class LookupImpl extends LightweightHint implements LookupEx, Disposable ((DefaultListModel)myList.getModel()).clear(); } - for (final LookupElement item : items) { - addItem(item, itemMatcher(item)); + if (addAgain) { + for (final LookupElement item : items) { + addItem(item, itemMatcher(item)); + } } refreshUi(true, true); } @@ -529,7 +531,8 @@ public class LookupImpl extends LightweightHint implements LookupEx, Disposable @NotNull @Override public String itemPattern(@NotNull LookupElement element) { - return itemMatcher(element).getPrefix() + myAdditionalPrefix; + String prefix = itemMatcher(element).getPrefix(); + return myAdditionalPrefix.isEmpty() ? prefix : prefix + myAdditionalPrefix; } @Override