prefix matching should depend on the actual prefix in the editor, not on the one that the completion was invoked with (IDEA-69525)

This commit is contained in:
peter
2011-05-12 18:39:59 +02:00
parent 8301cbedae
commit 7d67470070
6 changed files with 97 additions and 31 deletions
@@ -774,5 +774,13 @@ public class UTest {
assert myFixture.lookupElementStrings == ['new', 'nextWord']
}
public void testUpdatePrefixMatchingOnTyping() {
myFixture.addClass("class CertificateEncodingException {}")
myFixture.addClass("class CertificateException {}")
myFixture.configureByText 'a.java', 'class Foo {<caret>}'
type 'CertificateExce'
assert myFixture.lookupElementStrings == ['CertificateException', 'CertificateEncodingException']
}
}
@@ -25,7 +25,12 @@ import org.jetbrains.annotations.NotNull;
*/
public class PrefixMatchingWeigher extends CompletionWeigher {
public Comparable weigh(@NotNull final LookupElement item, @NotNull final CompletionLocation location) {
@Override
public Comparable weigh(@NotNull LookupElement element, @NotNull CompletionLocation location) {
throw new UnsupportedOperationException("Not implemented");
}
public static int getPrefixMatchingDegree(LookupElement item, CompletionLocation location) {
final String prefix = location.getCompletionParameters().getLookup().itemPattern(item);
final int setting = CodeInsightSettings.getInstance().COMPLETION_CASE_SENSITIVE;
@@ -16,10 +16,7 @@
package com.intellij.codeInsight.completion.impl;
import com.intellij.codeInsight.completion.*;
import com.intellij.codeInsight.lookup.Classifier;
import com.intellij.codeInsight.lookup.ClassifierFactory;
import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.codeInsight.lookup.LookupElementWeigher;
import com.intellij.codeInsight.lookup.*;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.progress.ProgressIndicator;
@@ -262,13 +259,31 @@ public class CompletionServiceImpl extends CompletionService{
}
for (final Weigher weigher : WeighingService.getWeighers(CompletionService.RELEVANCE_KEY)) {
sorter = sorter.weigh(new LookupElementWeigher(weigher.toString()) {
@NotNull
@Override
public Comparable weigh(@NotNull LookupElement element) {
return new NegatingComparable(weigher.weigh(element, location));
}
});
final String id = weigher.toString();
if ("prefix".equals(id)) {
sorter = sorter.withClassifier(new ClassifierFactory<LookupElement>(id) {
@Override
public Classifier<LookupElement> createClassifier(Classifier<LookupElement> next) {
return new ComparingClassifier<LookupElement>(next, id) {
@NotNull
@Override
public Comparable getWeight(LookupElement element) {
return -PrefixMatchingWeigher.getPrefixMatchingDegree(element, location);
}
};
}
});
}
else {
sorter = sorter.weigh(new LookupElementWeigher(id) {
@NotNull
@Override
public Comparable weigh(@NotNull LookupElement element) {
return new NegatingComparable(weigher.weigh(element, location));
}
});
}
}
return sorter.withClassifier("priority", true, new ClassifierFactory<LookupElement>("liftShorter") {
@@ -39,13 +39,7 @@ public class CompletionSorterImpl extends CompletionSorter {
return new ClassifierFactory<LookupElement>(id) {
@Override
public Classifier<LookupElement> createClassifier(Classifier<LookupElement> next) {
return new ComparingClassifier<LookupElement>(next, id) {
@NotNull
@Override
public Comparable getWeight(LookupElement element) {
return weigher.weigh(element);
}
};
return new CachingComparingClassifier(next, weigher);
}
};
}
@@ -0,0 +1,52 @@
/*
* Copyright 2000-2011 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.codeInsight.lookup;
import com.intellij.util.containers.StripedLockConcurrentHashMap;
import gnu.trove.TObjectHashingStrategy;
import org.jetbrains.annotations.NotNull;
import java.util.Map;
/**
* @author peter
*/
public class CachingComparingClassifier extends ComparingClassifier<LookupElement> {
private final Map<LookupElement, Comparable> myWeights = new StripedLockConcurrentHashMap<LookupElement, Comparable>(TObjectHashingStrategy.IDENTITY);
private final LookupElementWeigher myWeigher;
public CachingComparingClassifier(Classifier<LookupElement> next, LookupElementWeigher weigher) {
super(next, weigher.toString());
myWeigher = weigher;
}
@NotNull
@Override
public final Comparable getWeight(LookupElement t) {
final Comparable weight = myWeights.get(t);
if (weight == null) {
throw new AssertionError(myName + "; " + myWeights.containsKey(t) + "; element=" + t);
}
return weight;
}
@Override
public void addElement(LookupElement t) {
myWeights.put(t, myWeigher.weigh(t));
super.addElement(t);
}
}
@@ -18,19 +18,16 @@ package com.intellij.codeInsight.lookup;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.util.SmartList;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.StripedLockConcurrentHashMap;
import gnu.trove.TObjectHashingStrategy;
import org.jetbrains.annotations.NotNull;
import java.util.*;
/**
* @author peter
*/
* @author peter
*/
public abstract class ComparingClassifier<T> extends Classifier<T> {
private final Map<T, Comparable> myWeights = new StripedLockConcurrentHashMap<T, Comparable>(TObjectHashingStrategy.IDENTITY);
private final Classifier<T> myNext;
private final String myName;
protected final String myName;
public ComparingClassifier(Classifier<T> next, String name) {
myNext = next;
@@ -40,19 +37,14 @@ public abstract class ComparingClassifier<T> extends Classifier<T> {
@NotNull
public abstract Comparable getWeight(T t);
@Override
public void addElement(T t) {
myWeights.put(t, getWeight(t));
myNext.addElement(t);
}
private TreeMap<Comparable, List<T>> groupByWeights(List<T> source) {
TreeMap<Comparable, List<T>> map = new TreeMap<Comparable, List<T>>();
for (T t : source) {
final Comparable weight = myWeights.get(t);
if (weight == null) {
throw new AssertionError(myName + "; " + myWeights.containsKey(t) + "; element=" + t);
}
final Comparable weight = getWeight(t);
List<T> list = map.get(weight);
if (list == null) {
map.put(weight, list = new SmartList<T>());