mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-13 21:55:01 +07:00
make entering class literals in method calls easier during smart completion (IDEA-162394)
sort class literals by class proximity process closest (imported) inheritors first
This commit is contained in:
@@ -26,6 +26,7 @@ import com.intellij.openapi.progress.ProgressManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.scope.PsiScopeProcessor;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.search.searches.ClassInheritorsSearch;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
@@ -326,10 +327,12 @@ public class CodeInsightUtil {
|
||||
|
||||
if (baseClass.hasModifierProperty(PsiModifier.FINAL)) return;
|
||||
|
||||
Set<PsiClass> imported = processImportedInheritors(context, baseClass, inheritorsProcessor);
|
||||
|
||||
if (matcher.getPrefix().length() > 2) {
|
||||
JBTreeTraverser<PsiClass> traverser = JBTreeTraverser.of(PsiClass::getInnerClasses);
|
||||
AllClassesGetter.processJavaClasses(matcher, context.getProject(), scope, psiClass -> {
|
||||
Iterable<PsiClass> inheritors = traverser.withRoot(psiClass).filter(c -> c.isInheritor(baseClass, true));
|
||||
Iterable<PsiClass> inheritors = traverser.withRoot(psiClass).filter(c -> c.isInheritor(baseClass, true) && !imported.contains(c));
|
||||
return ContainerUtil.process(inheritors, inheritorsProcessor);
|
||||
});
|
||||
}
|
||||
@@ -337,11 +340,28 @@ public class CodeInsightUtil {
|
||||
Query<PsiClass> baseQuery = ClassInheritorsSearch.search(baseClass, scope, true, true, false);
|
||||
Query<PsiClass> query = new FilteredQuery<>(baseQuery, psiClass ->
|
||||
!(psiClass instanceof PsiTypeParameter) &&
|
||||
ContainerUtil.exists(JavaCompletionUtil.getAllLookupStrings(psiClass), matcher::prefixMatches));
|
||||
ContainerUtil.exists(JavaCompletionUtil.getAllLookupStrings(psiClass), matcher::prefixMatches) &&
|
||||
!imported.contains(psiClass));
|
||||
query.forEach(inheritorsProcessor);
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static Set<PsiClass> processImportedInheritors(PsiElement context, PsiClass baseClass, Processor<PsiClass> inheritorsProcessor) {
|
||||
Set<PsiClass> visited = new HashSet<>();
|
||||
|
||||
context.getContainingFile().getOriginalFile().processDeclarations(new PsiScopeProcessor() {
|
||||
@Override
|
||||
public boolean execute(@NotNull PsiElement element, @NotNull ResolveState state) {
|
||||
if (element instanceof PsiClass && ((PsiClass)element).isInheritor(baseClass, true) && visited.add((PsiClass)element)) {
|
||||
return inheritorsProcessor.process((PsiClass)element);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}, ResolveState.initial(), null, context);
|
||||
return visited;
|
||||
}
|
||||
|
||||
private static void addContextTypeArguments(PsiElement context, PsiClassType baseType, Processor<PsiClass> inheritorsProcessor) {
|
||||
Set<String> usedNames = ContainerUtil.newHashSet();
|
||||
PsiElementFactory factory = JavaPsiFacade.getElementFactory(context.getProject());
|
||||
|
||||
@@ -32,13 +32,17 @@ import org.jetbrains.annotations.Nullable;
|
||||
/**
|
||||
* @author peter
|
||||
*/
|
||||
public class ClassLiteralLookupElement extends LookupElement implements TypedLookupItem {
|
||||
class ClassLiteralLookupElement extends LookupElement implements TypedLookupItem {
|
||||
@NonNls private static final String DOT_CLASS = ".class";
|
||||
@Nullable private final SmartPsiElementPointer<PsiClass> myClass;
|
||||
private final PsiExpression myExpr;
|
||||
private final String myPresentableText;
|
||||
private final String myCanonicalText;
|
||||
|
||||
public ClassLiteralLookupElement(PsiClassType type, PsiElement context) {
|
||||
ClassLiteralLookupElement(PsiClassType type, PsiElement context) {
|
||||
PsiClass psiClass = PsiUtil.resolveClassInType(type);
|
||||
myClass = psiClass == null ? null : SmartPointerManager.createPointer(psiClass);
|
||||
|
||||
myCanonicalText = type.getCanonicalText();
|
||||
myPresentableText = type.getPresentableText();
|
||||
myExpr = JavaPsiFacade.getInstance(context.getProject()).getElementFactory().createExpressionFromText(myCanonicalText + DOT_CLASS, context);
|
||||
@@ -63,7 +67,7 @@ public class ClassLiteralLookupElement extends LookupElement implements TypedLoo
|
||||
@Nullable
|
||||
@Override
|
||||
public PsiElement getPsiElement() {
|
||||
return PsiUtil.resolveClassInType(getType());
|
||||
return myClass == null ? null : myClass.getElement();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
class X {
|
||||
|
||||
<T> void foo(Class<T> c) {
|
||||
|
||||
}
|
||||
|
||||
{
|
||||
foo(Str<caret>)
|
||||
}
|
||||
|
||||
}
|
||||
+4
@@ -275,4 +275,8 @@ public void testConvertToObjectStream() {
|
||||
myFixture.assertPreferredCompletionItems(2, "SortedMap", "NavigableMap", "TreeMap", "ConcurrentNavigableMap", "ConcurrentSkipListMap");
|
||||
}
|
||||
|
||||
public void testConsiderClassProximityForClassLiterals() {
|
||||
configureByTestName();
|
||||
myFixture.assertPreferredCompletionItems(0, "String.class");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user