IDEA-88058 Completion popup: toggling alpha vs. usage sorting blocks UI

This commit is contained in:
peter
2012-06-29 22:01:20 +02:00
parent a35a523a88
commit f5daffd107
5 changed files with 67 additions and 60 deletions
@@ -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) {
@@ -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<TextRange> fragments = matcher.matchingFragments(ls);
if (fragments != null) {
Iterator<TextRange> 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;
}
}
@@ -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<String, MinusculeMatcher> 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<String, MinusculeMatcher> 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<TextRange> fragments = matcher.matchingFragments(ls);
if (fragments != null) {
Iterator<TextRange> 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);
}
};
}
@@ -36,11 +36,6 @@ public abstract class LookupArranger {
public abstract Pair<List<LookupElement>, 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<LookupElement> result, boolean exactly, Collection<LookupElement> items) {
@@ -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<LookupElement> 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