diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionSorting.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionSorting.java index 097d9363ba1c..d7aeb67f0b71 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionSorting.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionSorting.java @@ -33,7 +33,6 @@ import com.intellij.psi.javadoc.PsiDocComment; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiUtil; import com.intellij.psi.util.TypeConversionUtil; -import com.intellij.util.Function; import com.intellij.util.SmartList; import com.intellij.util.containers.ContainerUtil; import gnu.trove.THashSet; @@ -72,22 +71,22 @@ public class JavaCompletionSorting { sorter = sorter.weighAfter("priority", new PreferDefaultTypeWeigher(expectedTypes, parameters)); } - List afterPrefix = ContainerUtil.newArrayList(); - afterPrefix.add(new PreferByKindWeigher(type, position, expectedTypes)); + List afterStats = ContainerUtil.newArrayList(); + afterStats.add(new PreferByKindWeigher(type, position, expectedTypes)); if (!smart) { - ContainerUtil.addIfNotNull(afterPrefix, preferStatics(position, expectedTypes)); + ContainerUtil.addIfNotNull(afterStats, preferStatics(position, expectedTypes)); if (!afterNew) { - afterPrefix.add(new PreferExpected(false, expectedTypes, position)); + afterStats.add(new PreferExpected(false, expectedTypes, position)); } } - ContainerUtil.addIfNotNull(afterPrefix, recursion(parameters, expectedTypes)); - afterPrefix.add(new PreferSimilarlyEnding(expectedTypes)); + ContainerUtil.addIfNotNull(afterStats, recursion(parameters, expectedTypes)); + afterStats.add(new PreferSimilarlyEnding(expectedTypes)); if (ContainerUtil.or(expectedTypes, info -> !info.getType().equals(PsiType.VOID))) { - afterPrefix.add(new PreferNonGeneric()); + afterStats.add(new PreferNonGeneric()); } - Collections.addAll(afterPrefix, new PreferAccessible(position), new PreferSimple()); + Collections.addAll(afterStats, new PreferAccessible(position), new PreferSimple()); - sorter = sorter.weighAfter("prefix", afterPrefix.toArray(new LookupElementWeigher[afterPrefix.size()])); + sorter = sorter.weighAfter("stats", afterStats.toArray(new LookupElementWeigher[afterStats.size()])); sorter = sorter.weighAfter("proximity", afterProximity.toArray(new LookupElementWeigher[afterProximity.size()])); return result.withRelevanceSorter(sorter); } diff --git a/java/java-tests/testData/codeInsight/completion/normalSorting/AbandonSameStatsForDifferentQualifiers.java b/java/java-tests/testData/codeInsight/completion/normalSorting/AbandonSameStatsForDifferentQualifiers.java deleted file mode 100644 index 7c1e547204e3..000000000000 --- a/java/java-tests/testData/codeInsight/completion/normalSorting/AbandonSameStatsForDifferentQualifiers.java +++ /dev/null @@ -1,11 +0,0 @@ -class Foo1 { boolean method1() {} } -class Foo2 { boolean method2() {} } -class Foo3 { boolean method3() {} } - -public class MyFirstTestClassFoo { - - void foo(Foo1 f1, Foo2 f2, Foo3 f3) { - f1. - } - -} diff --git a/java/java-tests/testData/codeInsight/completion/normalSorting/ExpectedTypeIsMoreImportantThanCase.java b/java/java-tests/testData/codeInsight/completion/normalSorting/ExpectedTypeIsMoreImportantThanCase.java deleted file mode 100644 index 95e9cc36bf6e..000000000000 --- a/java/java-tests/testData/codeInsight/completion/normalSorting/ExpectedTypeIsMoreImportantThanCase.java +++ /dev/null @@ -1,9 +0,0 @@ -class Foo { - boolean ENABLED; - void enable() {} - - { - if (!en) - } - -} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/completion/normalSorting/StatisticsByPrefix.java b/java/java-tests/testData/codeInsight/completion/normalSorting/StatisticsByPrefix.java deleted file mode 100644 index 3e96c0452b07..000000000000 --- a/java/java-tests/testData/codeInsight/completion/normalSorting/StatisticsByPrefix.java +++ /dev/null @@ -1,6 +0,0 @@ -class FooBar { - int _foo1, _foo2, _boo1, _boo2, _goo1, _goo2; - { - - } -} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionOrderingTest.groovy b/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionOrderingTest.groovy index def3bfe930ac..469e1cf5882d 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionOrderingTest.groovy +++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionOrderingTest.groovy @@ -27,7 +27,6 @@ import com.intellij.openapi.fileEditor.FileDocumentManager import com.intellij.psi.PsiClass import com.intellij.psi.PsiField import com.intellij.psi.PsiMethod -import com.intellij.psi.statistics.StatisticsManager import com.intellij.ui.JBColor class NormalCompletionOrderingTest extends CompletionSortingTestCase { @@ -199,27 +198,6 @@ class NormalCompletionOrderingTest extends CompletionSortingTestCase { assertPreferredItems(0, "getComponents", "getComponent") } - void testAbandonSameStatsForDifferentQualifiers() throws Throwable { - invokeCompletion(getTestName(false) + ".java") - assertPreferredItems 0, "method1", "equals" - myFixture.type('eq\n2);\nf2.') - - myFixture.completeBasic() - assertPreferredItems 0, "equals", "method2" - myFixture.type('me\n);\n') - - for (i in 0..StatisticsManager.OBLIVION_THRESHOLD) { - myFixture.type('f2.') - myFixture.completeBasic() - assertPreferredItems 0, "method2", "equals" - myFixture.type('me\n);\n') - } - - myFixture.type('f3.') - myFixture.completeBasic() - assertPreferredItems 0, "method3", "equals" - } - void testDispreferFinalize() throws Throwable { checkPreferredItems(0, "final", "finalize") } @@ -393,13 +371,6 @@ class NormalCompletionOrderingTest extends CompletionSortingTestCase { checkPreferredItems(1, "Foo", "foo1", "foo2") } - void testExpectedTypeIsMoreImportantThanCase() { - CodeInsightSettings.getInstance().COMPLETION_CASE_SENSITIVE = CodeInsightSettings.NONE - checkPreferredItems 0, "enable", "ENABLED" - incUseCount(lookup, 1) - assertPreferredItems 0, "ENABLED", "enable" - } - void testPreferKeywordsToVoidMethodsInExpectedTypeContext() { checkPreferredItems 0, 'noo', 'new', 'null', 'noo2', 'notify', 'notifyAll' } @@ -516,41 +487,6 @@ interface TxANotAnno {} assert lookup.currentItem.lookupString == 'JComponent' } - void testStatisticsByPrefix() { - Closure repeatCompletion = { String letter -> - String var1 = "_${letter}oo1" - String var2 = "_${letter}oo2" - - myFixture.type("_$letter") - myFixture.completeBasic() - assertPreferredItems(0, var1, var2) - myFixture.type('2\n;\n') - - for (i in 0.. classify(@NotNull Iterable source, @NotNull final ProcessingContext context) { checkPrefixChanged(context); - final Collection> byWeight = buildMapByWeight(source, context).descendingMap().values(); + final Collection> byWeight = buildMapByWeight(source).descendingMap().values(); List initialList = getInitialNoStatElements(source, context); @@ -117,10 +115,10 @@ public class StatisticsWeigher extends CompletionWeigher { return initialList; } - private TreeMap> buildMapByWeight(Iterable source, ProcessingContext context) { + private TreeMap> buildMapByWeight(Iterable source) { TreeMap> map = new TreeMap<>(); for (LookupElement element : source) { - final int weight = getWeight(element, context.get(CompletionLookupArranger.WEIGHING_CONTEXT)).getScalar(); + final int weight = getWeight(element).getScalar(); List list = map.get(weight); if (list == null) { map.put(weight, list = new SmartList<>()); @@ -130,31 +128,28 @@ public class StatisticsWeigher extends CompletionWeigher { return map; } - private StatisticsComparable getWeight(LookupElement t, WeighingContext context) { + private StatisticsComparable getWeight(LookupElement t) { StatisticsComparable w = myWeights.get(t); if (w == null) { StatisticsInfo info = getBaseStatisticsInfo(t, myLocation); - myWeights.put(t, w = new StatisticsComparable(weigh(t, info, context), info)); + myWeights.put(t, w = new StatisticsComparable(weigh(info), info)); } return w; } - private static int weigh(@NotNull LookupElement item, final StatisticsInfo baseInfo, WeighingContext context) { + private static int weigh(final StatisticsInfo baseInfo) { if (baseInfo == StatisticsInfo.EMPTY) { return 0; } - String prefix = context.itemPattern(item); - StatisticsInfo composed = composeStatsWithPrefix(baseInfo, prefix, false); - int minRecency = composed.getLastUseRecency(); - int useCount = composed.getUseCount(); - return minRecency == Integer.MAX_VALUE ? useCount : 100 - minRecency; + int minRecency = baseInfo.getLastUseRecency(); + return minRecency == Integer.MAX_VALUE ? 0 : StatisticsManager.RECENCY_OBLIVION_THRESHOLD - minRecency; } @NotNull @Override public List> getSortingWeights(@NotNull Iterable items, @NotNull final ProcessingContext context) { checkPrefixChanged(context); - return ContainerUtil.map(items, lookupElement -> new Pair(lookupElement, getWeight(lookupElement, context.get(CompletionLookupArranger.WEIGHING_CONTEXT)))); + return ContainerUtil.map(items, lookupElement -> new Pair(lookupElement, getWeight(lookupElement))); } @Override @@ -190,41 +185,4 @@ public class StatisticsWeigher extends CompletionWeigher { return info == null ? StatisticsInfo.EMPTY : info; } - /** - * For different prefixes we want to prefer different completion items, - * so we decorate their basic stat-infos depending on prefix. - * For example, consider that an item "fooBar" was chosen with a prefix "foo" - * Then we'll register "fooBar" for each of the sub-prefixes: "", "f", "fo" and "foo" - * and suggest "foobar" whenever we a user types any of those prefixes - * - * If a user has typed "fooB" for which there's no stat-info registered, we want to check - * all of its sub-prefixes: "", "f", "fo", "foo" and see if any of them is associated with a stat-info - * But if the item were "fobia" and the user has typed "fob", we don't want to claim - * that "fooBar" (which matches) is statistically better than "fobia" with prefix "fob" even though both begin with "fo" - * So we only check non-partial sub-prefixes, then ones that had been really typed by the user before completing - * - * @param forWriting controls whether this stat-info will be used for incrementing usage count or for its retrieval (for sorting) - */ - public static StatisticsInfo composeStatsWithPrefix(StatisticsInfo info, final String fullPrefix, boolean forWriting) { - ArrayList infos = new ArrayList<>((fullPrefix.length() + 3) * info.getConjuncts().size()); - for (StatisticsInfo conjunct : info.getConjuncts()) { - if (forWriting) { - // some completion contributors may need pure statistical information to speed up searching for frequently chosen items - infos.add(conjunct); - } - for (int i = 0; i <= fullPrefix.length(); i++) { - // if we're incrementing usage count, register all sub-prefixes with "partial" mark - // if we're sorting and any sub-prefix was used as non-partial to choose this completion item, prefer it - infos.add(composeWithPrefix(conjunct, fullPrefix.substring(0, i), forWriting)); - } - // if we're incrementing usage count, the full prefix is registered as non-partial - // if we're sorting and the current prefix was used as partial sub-prefix to choose this completion item, prefer it - infos.add(composeWithPrefix(conjunct, fullPrefix, !forWriting)); - } - return StatisticsInfo.createComposite(infos); - } - - private static StatisticsInfo composeWithPrefix(StatisticsInfo info, String fullPrefix, boolean partial) { - return new StatisticsInfo(info.getContext() + "###prefix=" + fullPrefix + "###part#" + partial, info.getValue()); - } } diff --git a/platform/platform-resources/src/META-INF/LangExtensions.xml b/platform/platform-resources/src/META-INF/LangExtensions.xml index ce85e1d88d9e..a5817dbe8fd7 100644 --- a/platform/platform-resources/src/META-INF/LangExtensions.xml +++ b/platform/platform-resources/src/META-INF/LangExtensions.xml @@ -543,12 +543,12 @@ order="after inResolveScope"/> - - + + + id="groovyWithWeigher" order="after prefix, after stats"/>