mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-18 09:34:34 +07:00
items that are prefixes of other items should go first
Java expected type also should go first, and win current class should be preferred in completion (IDEA-64703)
This commit is contained in:
+3
-1
@@ -50,12 +50,14 @@ public class JavaClassNameCompletionContributor extends CompletionContributor {
|
||||
|
||||
public JavaClassNameCompletionContributor() {
|
||||
extend(CompletionType.CLASS_NAME, psiElement(), new CompletionProvider<CompletionParameters>() {
|
||||
public void addCompletions(@NotNull final CompletionParameters parameters, final ProcessingContext matchingContext, @NotNull final CompletionResultSet result) {
|
||||
public void addCompletions(@NotNull final CompletionParameters parameters, final ProcessingContext matchingContext, @NotNull final CompletionResultSet _result) {
|
||||
if (shouldShowSecondSmartCompletionHint(parameters) &&
|
||||
CompletionUtil.shouldShowFeature(parameters, CodeCompletionFeatures.SECOND_CLASS_NAME_COMPLETION)) {
|
||||
CompletionService.getCompletionService().setAdvertisementText(CompletionBundle.message("completion.class.name.hint.2", getActionShortcut(IdeActions.ACTION_CLASS_NAME_COMPLETION)));
|
||||
}
|
||||
|
||||
final CompletionResultSet result = JavaCompletionContributor.addJavaSorting(parameters, _result);
|
||||
|
||||
final PsiElement insertedElement = parameters.getPosition();
|
||||
|
||||
final ElementFilter filter =
|
||||
|
||||
+17
-1
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package com.intellij.codeInsight.completion;
|
||||
|
||||
import com.intellij.codeInsight.ExpectedTypeInfo;
|
||||
import com.intellij.codeInsight.TailType;
|
||||
import com.intellij.codeInsight.daemon.impl.quickfix.ImportClassFix;
|
||||
import com.intellij.codeInsight.hint.ShowParameterInfoHandler;
|
||||
@@ -165,7 +166,7 @@ public class JavaCompletionContributor extends CompletionContributor {
|
||||
return TrueFilter.INSTANCE;
|
||||
}
|
||||
|
||||
public void fillCompletionVariants(final CompletionParameters parameters, final CompletionResultSet result) {
|
||||
public void fillCompletionVariants(final CompletionParameters parameters, final CompletionResultSet _result) {
|
||||
if (parameters.getCompletionType() != CompletionType.BASIC) {
|
||||
return;
|
||||
}
|
||||
@@ -179,6 +180,9 @@ public class JavaCompletionContributor extends CompletionContributor {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
final CompletionResultSet result = addJavaSorting(parameters, _result);
|
||||
|
||||
if (ANNOTATION_ATTRIBUTE_NAME.accepts(position)) {
|
||||
completeAnnotationAttributeName(result, position, parameters);
|
||||
result.stopHere();
|
||||
@@ -202,6 +206,18 @@ public class JavaCompletionContributor extends CompletionContributor {
|
||||
result.stopHere();
|
||||
}
|
||||
|
||||
public static CompletionResultSet addJavaSorting(CompletionParameters parameters, CompletionResultSet result) {
|
||||
final boolean afterNew = JavaSmartCompletionContributor.AFTER_NEW.accepts(parameters.getPosition());
|
||||
final ExpectedTypeInfo[] expectedTypes = afterNew ? JavaSmartCompletionContributor.getExpectedTypes(parameters) : ExpectedTypeInfo.EMPTY_ARRAY;
|
||||
return result.withRelevanceSorter(CompletionSorter.defaultSorter(parameters).weighBefore("liftShorter", new LookupElementWeigher("expectedAfterNew") {
|
||||
@Override
|
||||
@Nullable
|
||||
public Comparable weigh(@NotNull LookupElement element) {
|
||||
return -((Enum)PreferExpectedTypeWeigher.weigh(element, expectedTypes)).ordinal();
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
public static void addAllClasses(CompletionParameters parameters,
|
||||
final CompletionResultSet result,
|
||||
PsiElement position,
|
||||
|
||||
+5
-1
@@ -43,8 +43,12 @@ public class PreferExpectedTypeWeigher extends CompletionWeigher {
|
||||
ExpectedTypeInfo[] expectedInfos = JavaCompletionUtil.EXPECTED_TYPES.getValue(location);
|
||||
if (expectedInfos == null) return MyResult.normal;
|
||||
|
||||
return weigh(item, expectedInfos);
|
||||
}
|
||||
|
||||
public static MyResult weigh(LookupElement item, ExpectedTypeInfo[] expectedInfos) {
|
||||
PsiType itemType = JavaCompletionUtil.getLookupElementType(item);
|
||||
if (itemType == null || !itemType.isValid()) return MyResult.normal;
|
||||
if (itemType == null) return MyResult.normal;
|
||||
|
||||
for (final ExpectedTypeInfo expectedInfo : expectedInfos) {
|
||||
final PsiType defaultType = expectedInfo.getDefaultType();
|
||||
|
||||
@@ -44,6 +44,12 @@ public class KnownElementWeigher extends ProximityWeigher {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if ("subSequence".equals(method.getName())) {
|
||||
final PsiClass containingClass = method.getContainingClass();
|
||||
if (containingClass != null && CommonClassNames.JAVA_LANG_STRING.equals(containingClass.getQualifiedName())) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
class A{
|
||||
{
|
||||
String str;
|
||||
str.toString();
|
||||
str.toCharArray();
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
class A{
|
||||
{
|
||||
final String path = BASE_PATH;
|
||||
path.toString()<caret>;
|
||||
path.toCharArray()<caret>;
|
||||
sdkfjsdkhjfh();
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -223,7 +223,7 @@ public class KeywordCompletionTest extends LightCompletionTestCase {
|
||||
|
||||
public void testTryInExpression() throws Throwable {
|
||||
configureByFile(BASE_PATH + "/" + getTestName(true) + ".java");
|
||||
assertStringItems("this", "toString");
|
||||
assertStringItems("toString", "this");
|
||||
}
|
||||
|
||||
public void testNull() throws Exception{
|
||||
|
||||
+4
-4
@@ -71,7 +71,7 @@ public class NormalCompletionOrderingTest extends CompletionSortingTestCase {
|
||||
final int old = CodeInsightSettings.getInstance().COMPLETION_CASE_SENSITIVE;
|
||||
try {
|
||||
CodeInsightSettings.getInstance().COMPLETION_CASE_SENSITIVE = CodeInsightSettings.FIRST_LETTER;
|
||||
checkPreferredItems(0, "classLoader", "classBeforeLoader", "clone", "class");
|
||||
checkPreferredItems(0, "classLoader", "class", "classBeforeLoader", "clone");
|
||||
}
|
||||
finally {
|
||||
CodeInsightSettings.getInstance().COMPLETION_CASE_SENSITIVE = old;
|
||||
@@ -111,7 +111,7 @@ public class NormalCompletionOrderingTest extends CompletionSortingTestCase {
|
||||
|
||||
public void testDispreferImpls() throws Throwable {
|
||||
myFixture.addClass("package foo; public class Xxx {}");
|
||||
checkPreferredItems(0, "Xxy", "Xxx", "XxxEx", "XxxImpl");
|
||||
checkPreferredItems(0, "Xxx", "XxxEx", "XxxImpl", "Xxy");
|
||||
}
|
||||
|
||||
public void testPreferOwnInnerClasses() throws Throwable {
|
||||
@@ -130,7 +130,7 @@ public class NormalCompletionOrderingTest extends CompletionSortingTestCase {
|
||||
public void testPreferLessHumps() throws Throwable {
|
||||
myFixture.addClass("package foo; public interface XaYa {}");
|
||||
myFixture.addClass("package foo; public interface XyYa {}");
|
||||
checkPreferredItems(0, "XaYa", "XyYa", "XaYaEx", "XaYaImpl", "XyYaXa");
|
||||
checkPreferredItems(0, "XaYa", "XaYaEx", "XaYaImpl", "XyYa", "XyYaXa");
|
||||
}
|
||||
|
||||
public void testPreferLessParameters() throws Throwable {
|
||||
@@ -178,7 +178,7 @@ public class NormalCompletionOrderingTest extends CompletionSortingTestCase {
|
||||
checkPreferredItems(0, "value");
|
||||
}
|
||||
|
||||
public void _testCurrentClassBest() {
|
||||
public void testCurrentClassBest() {
|
||||
checkPreferredItems(0, "XcodeProjectTemplate", "XcodeConfigurable");
|
||||
}
|
||||
|
||||
|
||||
+6
-15
@@ -7,13 +7,13 @@ import com.intellij.codeInsight.lookup.Lookup
|
||||
import com.intellij.codeInsight.lookup.LookupElement
|
||||
import com.intellij.codeInsight.lookup.LookupManager
|
||||
import com.intellij.openapi.command.WriteCommandAction
|
||||
import com.intellij.openapi.fileTypes.StdFileTypes
|
||||
import com.intellij.psi.CommonClassNames
|
||||
import com.intellij.psi.JavaPsiFacade
|
||||
import com.intellij.psi.PsiFile
|
||||
import com.intellij.psi.PsiMethod
|
||||
import com.intellij.psi.codeStyle.CodeStyleSettings
|
||||
import com.intellij.psi.codeStyle.CodeStyleSettingsManager
|
||||
import com.intellij.openapi.fileTypes.StdFileTypes
|
||||
|
||||
public class NormalCompletionTest extends LightFixtureCompletionTestCase {
|
||||
@Override
|
||||
@@ -101,26 +101,17 @@ public class NormalCompletionTest extends LightFixtureCompletionTestCase {
|
||||
}
|
||||
|
||||
public void testQualifiedNew1() throws Exception {
|
||||
configureByFile("QualifiedNew1.java");
|
||||
|
||||
assertEquals(2, myItems.length);
|
||||
assertEquals("Inner", myItems[0].getLookupString());
|
||||
assertEquals("IInner", myItems[1].getLookupString());
|
||||
configure()
|
||||
assertStringItems "IInner", "Inner"
|
||||
}
|
||||
|
||||
public void testQualifiedNew2() throws Exception {
|
||||
configureByFile("QualifiedNew2.java");
|
||||
|
||||
assertEquals(2, myItems.length);
|
||||
assertEquals("AnInner", myItems[0].getLookupString());
|
||||
assertEquals("Inner", myItems[1].getLookupString());
|
||||
configure()
|
||||
assertStringItems "AnInner", "Inner"
|
||||
}
|
||||
|
||||
public void testKeywordsInName() throws Exception {
|
||||
myFixture.configureByFile(getTestName(false) + ".java");
|
||||
myFixture.completeBasic()
|
||||
myFixture.type 'a\n'
|
||||
checkResult()
|
||||
doTest 'a\n'
|
||||
}
|
||||
|
||||
public void testSimpleVariable() throws Exception { doTest() }
|
||||
|
||||
+1
-1
@@ -16,7 +16,7 @@ public class SmartTypeCompletionOrderingTest extends CompletionSortingTestCase {
|
||||
}
|
||||
|
||||
public void testJComponentAdd() throws Throwable {
|
||||
checkPreferredItems(0, "name", "b", "fooBean239", "this", "getName");
|
||||
checkPreferredItems(0, "name", "b", "foo", "fooBean239", "this");
|
||||
}
|
||||
|
||||
public void testJComponentAddNew() throws Throwable {
|
||||
|
||||
+1
-1
@@ -35,7 +35,7 @@ public class PrefixMatchingWeigher extends CompletionWeigher {
|
||||
final String prefixHumps = StringUtil.capitalsOnly(prefix);
|
||||
final String itemHumps = StringUtil.capitalsOnly(lookupString);
|
||||
|
||||
if (itemHumps.startsWith(prefixHumps)) return 100 - itemHumps.length();
|
||||
if (itemHumps.startsWith(prefixHumps)) return 100;// - itemHumps.length();
|
||||
|
||||
if (lookupString.startsWith(prefix)) return 5;
|
||||
if (StringUtil.startsWithIgnoreCase(lookupString, prefix)) return 1;
|
||||
|
||||
+27
-3
@@ -16,6 +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;
|
||||
@@ -34,7 +35,7 @@ import com.intellij.util.Consumer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author peter
|
||||
@@ -231,7 +232,25 @@ public class CompletionServiceImpl extends CompletionService{
|
||||
public CompletionSorterImpl defaultSorter(CompletionParameters parameters) {
|
||||
final CompletionLocation location = new CompletionLocation(parameters);
|
||||
|
||||
CompletionSorterImpl sorter = emptySorter();
|
||||
CompletionSorterImpl sorter = emptySorter().weigh(new LookupElementWeigher("prefixHumps") {
|
||||
@Override
|
||||
public Boolean weigh(@NotNull LookupElement element) {
|
||||
final String prefix = element.getPrefixMatcher().getPrefix();
|
||||
if (!prefix.isEmpty()) {
|
||||
final String prefixHumps = StringUtil.capitalsOnly(prefix);
|
||||
if (prefixHumps.length() > 0) {
|
||||
for (String itemString : element.getAllLookupStrings()) {
|
||||
if (StringUtil.capitalsOnly(itemString).startsWith(prefixHumps)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
for (final Weigher weigher : WeighingService.getWeighers(CompletionService.RELEVANCE_KEY)) {
|
||||
sorter = sorter.weigh(new LookupElementWeigher(weigher.toString()) {
|
||||
@Override
|
||||
@@ -241,7 +260,12 @@ public class CompletionServiceImpl extends CompletionService{
|
||||
});
|
||||
}
|
||||
|
||||
return sorter;
|
||||
return sorter.withClassifier("priority", true, new ClassifierFactory<LookupElement>("liftShorter") {
|
||||
@Override
|
||||
public Classifier<LookupElement> createClassifier(final Classifier<LookupElement> next) {
|
||||
return new LiftShorterItemsClassifier(next);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public CompletionSorterImpl emptySorter() {
|
||||
|
||||
+3
-2
@@ -35,10 +35,11 @@ public class CompletionSorterImpl extends CompletionSorter {
|
||||
}
|
||||
|
||||
private static ClassifierFactory<LookupElement> weighingFactory(final LookupElementWeigher weigher) {
|
||||
return new ClassifierFactory<LookupElement>(weigher.getClass().getName()) {
|
||||
final String id = weigher.toString();
|
||||
return new ClassifierFactory<LookupElement>(id) {
|
||||
@Override
|
||||
public Classifier<LookupElement> createClassifier(Classifier<LookupElement> next) {
|
||||
return new ComparingClassifier<LookupElement>(next, weigher.toString()) {
|
||||
return new ComparingClassifier<LookupElement>(next, id) {
|
||||
@Override
|
||||
public Comparable getWeight(LookupElement element) {
|
||||
return weigher.weigh(element);
|
||||
|
||||
+125
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
* 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.completion.impl;
|
||||
|
||||
import com.intellij.codeInsight.lookup.Classifier;
|
||||
import com.intellij.codeInsight.lookup.LookupElement;
|
||||
import com.intellij.util.SmartList;
|
||||
import com.intellij.util.containers.MultiMap;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author peter
|
||||
*/
|
||||
class LiftShorterItemsClassifier extends Classifier<LookupElement> {
|
||||
private final TreeSet<String> mySortedStrings;
|
||||
private final MultiMap<String, LookupElement> myElements;
|
||||
private final MultiMap<String, String> myPrefixes;
|
||||
private final Classifier<LookupElement> myNext;
|
||||
|
||||
public LiftShorterItemsClassifier(Classifier<LookupElement> next) {
|
||||
myNext = next;
|
||||
mySortedStrings = new TreeSet<String>();
|
||||
myElements = new MultiMap<String, LookupElement>();
|
||||
myPrefixes = new MultiMap<String, String>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addElement(LookupElement element) {
|
||||
final Set<String> strings = element.getAllLookupStrings();
|
||||
for (String string : strings) {
|
||||
if (string.length() == 0) continue;
|
||||
|
||||
myElements.putValue(string, element);
|
||||
mySortedStrings.add(string);
|
||||
final NavigableSet<String> after = mySortedStrings.tailSet(string, false);
|
||||
for (String s : after) {
|
||||
if (!s.startsWith(string)) {
|
||||
break;
|
||||
}
|
||||
myPrefixes.putValue(s, string);
|
||||
}
|
||||
|
||||
final char first = string.charAt(0);
|
||||
final SortedSet<String> before = mySortedStrings.descendingSet().tailSet(string, false);
|
||||
for (String s : before) {
|
||||
if (s.charAt(0) != first) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (string.startsWith(s)) {
|
||||
myPrefixes.putValue(string, s);
|
||||
}
|
||||
}
|
||||
}
|
||||
myNext.addElement(element);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<List<LookupElement>> classify(List<LookupElement> source) {
|
||||
return liftShorterElements(source, new HashSet<LookupElement>());
|
||||
}
|
||||
|
||||
private Iterable<List<LookupElement>> liftShorterElements(List<LookupElement> source, Set<LookupElement> lifted) {
|
||||
final Set<LookupElement> srcSet = new HashSet<LookupElement>(source);
|
||||
final Iterable<List<LookupElement>> classified = myNext.classify(source);
|
||||
final Set<LookupElement> processed = new HashSet<LookupElement>();
|
||||
|
||||
final ArrayList<List<LookupElement>> result = new ArrayList<List<LookupElement>>();
|
||||
for (List<LookupElement> list : classified) {
|
||||
final ArrayList<LookupElement> group = new ArrayList<LookupElement>();
|
||||
for (LookupElement element : list) {
|
||||
if (processed.add(element)) {
|
||||
final List<String> prefixes = new SmartList<String>();
|
||||
for (String string : element.getAllLookupStrings()) {
|
||||
prefixes.addAll(myPrefixes.get(string));
|
||||
}
|
||||
Collections.sort(prefixes);
|
||||
for (String prefix : prefixes) {
|
||||
for (LookupElement shorterElement : myElements.get(prefix)) {
|
||||
if (srcSet.contains(shorterElement) && processed.add(shorterElement)) {
|
||||
lifted.add(shorterElement);
|
||||
group.add(shorterElement);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
group.add(element);
|
||||
}
|
||||
}
|
||||
result.add(group);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void describeItems(LinkedHashMap<LookupElement, StringBuilder> map) {
|
||||
final HashSet<LookupElement> lifted = new HashSet<LookupElement>();
|
||||
liftShorterElements(new ArrayList<LookupElement>(map.keySet()), lifted);
|
||||
if (!lifted.isEmpty()) {
|
||||
for (LookupElement element : map.keySet()) {
|
||||
final StringBuilder builder = map.get(element);
|
||||
if (builder.length() > 0) {
|
||||
builder.append(", ");
|
||||
}
|
||||
|
||||
builder.append("liftShorter=").append(lifted.contains(element));
|
||||
}
|
||||
}
|
||||
myNext.describeItems(map);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user