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 32c1716645b4..44701a3ab0de 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionSorting.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionSorting.java @@ -17,10 +17,13 @@ package com.intellij.codeInsight.completion; import com.intellij.codeInsight.ExpectedTypeInfo; import com.intellij.codeInsight.ExpectedTypeInfoImpl; -import com.intellij.codeInsight.lookup.LookupElement; -import com.intellij.codeInsight.lookup.LookupElementWeigher; -import com.intellij.codeInsight.lookup.PsiTypeLookupItem; +import com.intellij.codeInsight.completion.impl.CompletionSorterImpl; +import com.intellij.codeInsight.completion.impl.LiftShorterItemsClassifier; +import com.intellij.codeInsight.lookup.*; +import com.intellij.openapi.roots.ProjectFileIndex; +import com.intellij.openapi.roots.ProjectRootManager; import com.intellij.openapi.util.Pair; +import com.intellij.openapi.vfs.VirtualFile; import com.intellij.patterns.PsiJavaPatterns; import com.intellij.psi.*; import com.intellij.psi.codeStyle.JavaCodeStyleManager; @@ -31,6 +34,7 @@ import com.intellij.psi.util.PropertyUtil; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiUtil; import com.intellij.psi.util.TypeConversionUtil; +import com.intellij.util.ProcessingContext; import com.intellij.util.containers.ContainerUtil; import gnu.trove.THashSet; import org.jetbrains.annotations.NotNull; @@ -75,6 +79,32 @@ public class JavaCompletionSorting { CompletionSorter sorter = CompletionSorter.defaultSorter(parameters, result.getPrefixMatcher()); if (!smart && afterNew) { sorter = sorter.weighBefore("liftShorter", new PreferExpected(true, expectedTypes)); + } else { + final ProjectFileIndex fileIndex = ProjectRootManager.getInstance(position.getProject()).getFileIndex(); + sorter = ((CompletionSorterImpl)sorter).withClassifier("liftShorter", true, new ClassifierFactory("liftShorterClasses") { + @Override + public Classifier createClassifier(Classifier next) { + return new LiftShorterItemsClassifier(next, new LiftShorterItemsClassifier.LiftingCondition() { + @Override + public boolean shouldLift(LookupElement shorterElement, LookupElement longerElement, ProcessingContext context) { + if (super.shouldLift(shorterElement, longerElement, context)) { + return true; + } + Object object = shorterElement.getObject(); + if (object instanceof PsiClass) { + PsiFile file = ((PsiClass)object).getContainingFile(); + if (file != null) { + VirtualFile vFile = file.getOriginalFile().getVirtualFile(); + if (vFile != null && fileIndex.isInSource(vFile)) { + return true; + } + } + } + return false; + } + }); + } + }); } if (smart) { sorter = sorter.weighBefore("negativeStats", new PreferDefaultTypeWeigher(expectedTypes, parameters)); 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 4148143c9fce..a3c6273a587a 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionOrderingTest.groovy +++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionOrderingTest.groovy @@ -101,7 +101,7 @@ public class NormalCompletionOrderingTest extends CompletionSortingTestCase { public void testDispreferImpls() throws Throwable { myFixture.addClass("package foo; public class Xxx {}"); configureSecondCompletion(); - assertPreferredItems(1, "Xxx", "XxxEx", "XxxImpl", "Xxy"); + assertPreferredItems(0, "Xxx", "XxxEx", "XxxImpl", "Xxy"); } public void testPreferOwnInnerClasses() throws Throwable { @@ -128,7 +128,7 @@ public class NormalCompletionOrderingTest extends CompletionSortingTestCase { myFixture.addClass("package foo; public interface XaYa {}"); myFixture.addClass("package foo; public interface XyYa {}"); configureSecondCompletion(); - assertPreferredItems(1, "XaYa", "XaYaEx", "XaYaImpl", "XyYa", "XyYaXa"); + assertPreferredItems(0, "XaYa", "XaYaEx", "XaYaImpl", "XyYa", "XyYaXa"); } public void testPreferLessParameters() throws Throwable { @@ -219,7 +219,7 @@ public class NormalCompletionOrderingTest extends CompletionSortingTestCase { } public void testPreferClassStaticMembers() { - checkPreferredItems(1, "Zoo", "Zoo.A", "Zoo.B", "Zoo.C", "Zoo.D", "Zoo.E", "Zoo.F", "Zoo.G", "Zoo.H"); + checkPreferredItems(0, "Zoo", "Zoo.A", "Zoo.B", "Zoo.C", "Zoo.D", "Zoo.E", "Zoo.F", "Zoo.G", "Zoo.H"); } public void testPreferFinallyToFinal() { diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartTypeCompletionOrderingTest.groovy b/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartTypeCompletionOrderingTest.groovy index e8002a8be6c4..cddb71d9e6bc 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartTypeCompletionOrderingTest.groovy +++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartTypeCompletionOrderingTest.groovy @@ -21,7 +21,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", "getName"); } public void testJComponentAddNew() throws Throwable { 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 aa3a9510ae46..4854888bfc60 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 @@ -292,7 +292,7 @@ public class CompletionServiceImpl extends CompletionService{ return sorter.withClassifier("priority", true, new ClassifierFactory("liftShorter") { @Override public Classifier createClassifier(final Classifier next) { - return new LiftShorterItemsClassifier(next); + return new LiftShorterItemsClassifier(next, new LiftShorterItemsClassifier.LiftingCondition()); } }); } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/completion/impl/LiftShorterItemsClassifier.java b/platform/lang-impl/src/com/intellij/codeInsight/completion/impl/LiftShorterItemsClassifier.java index 4a05b7758acf..65391ce8e046 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/completion/impl/LiftShorterItemsClassifier.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/completion/impl/LiftShorterItemsClassifier.java @@ -30,14 +30,16 @@ import java.util.*; /** * @author peter */ -class LiftShorterItemsClassifier extends Classifier { +public class LiftShorterItemsClassifier extends Classifier { private final TreeSet mySortedStrings; private final MultiMap myElements; private final MultiMap myPrefixes; private final Classifier myNext; + private final LiftingCondition myCondition; - public LiftShorterItemsClassifier(Classifier next) { + public LiftShorterItemsClassifier(Classifier next, LiftingCondition condition) { myNext = next; + myCondition = condition; mySortedStrings = new TreeSet(); myElements = new MultiMap(); myPrefixes = new MultiMap(); @@ -76,9 +78,6 @@ class LiftShorterItemsClassifier extends Classifier { @Override public Iterable classify(Iterable source, ProcessingContext context) { - if (context.get(CompletionLookupArranger.PURE_RELEVANCE) == Boolean.TRUE) { - return myNext.classify(source, context); - } return liftShorterElements(source, new THashSet(TObjectHashingStrategy.IDENTITY), context); } @@ -99,7 +98,7 @@ class LiftShorterItemsClassifier extends Classifier { for (String prefix : prefixes) { List shorter = new SmartList(); for (LookupElement shorterElement : myElements.get(prefix)) { - if (srcSet.contains(shorterElement) && processed.add(shorterElement)) { + if (srcSet.contains(shorterElement) && myCondition.shouldLift(shorterElement, element, context) && processed.add(shorterElement)) { shorter.add(shorterElement); } } @@ -134,4 +133,10 @@ class LiftShorterItemsClassifier extends Classifier { } myNext.describeItems(map, context); } + + public static class LiftingCondition { + public boolean shouldLift(LookupElement shorterElement, LookupElement longerElement, ProcessingContext context) { + return context.get(CompletionLookupArranger.PURE_RELEVANCE) != Boolean.TRUE; + } + } }