mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
don't build hierarchy for all class methods just to check that one of them has a super (IDEA-85127)
This commit is contained in:
+32
-34
@@ -19,18 +19,20 @@ import com.intellij.ide.util.DefaultPsiElementCellRenderer;
|
||||
import com.intellij.navigation.ChooseByNameContributor;
|
||||
import com.intellij.navigation.NavigationItem;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.progress.ProgressManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.PsiSuperMethodImplUtil;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.search.PsiShortNamesCache;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.containers.HashSet;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
public class DefaultSymbolNavigationContributor implements ChooseByNameContributor {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.ide.util.gotoByName.DefaultSymbolNavigationContributor");
|
||||
@@ -52,45 +54,41 @@ public class DefaultSymbolNavigationContributor implements ChooseByNameContribut
|
||||
GlobalSearchScope scope = includeNonProjectItems ? GlobalSearchScope.allScope(project) : GlobalSearchScope.projectScope(project);
|
||||
PsiShortNamesCache cache = PsiShortNamesCache.getInstance(project);
|
||||
|
||||
PsiMethod[] methods = cache.getMethodsByName(name, scope);
|
||||
methods = filterInheritedMethods(methods);
|
||||
PsiField[] fields = cache.getFieldsByName(name, scope);
|
||||
PsiClass[] classes = cache.getClassesByName(name, scope);
|
||||
|
||||
List<PsiMember> result = new ArrayList<PsiMember>();
|
||||
ContainerUtil.addAll(result, methods);
|
||||
ContainerUtil.addAll(result, fields);
|
||||
ContainerUtil.addAll(result, classes);
|
||||
filterOutNonOpenable(result);
|
||||
for (PsiMethod method : cache.getMethodsByName(name, scope)) {
|
||||
if (!method.isConstructor() && isOpenable(method) && !hasSuperMethod(method)) {
|
||||
result.add(method);
|
||||
}
|
||||
}
|
||||
for (PsiField field : cache.getFieldsByName(name, scope)) {
|
||||
if (isOpenable(field)) {
|
||||
result.add(field);
|
||||
}
|
||||
}
|
||||
for (PsiClass aClass : cache.getClassesByName(name, scope)) {
|
||||
if (isOpenable(aClass)) {
|
||||
result.add(aClass);
|
||||
}
|
||||
}
|
||||
PsiMember[] array = result.toArray(new PsiMember[result.size()]);
|
||||
Arrays.sort(array, MyComparator.INSTANCE);
|
||||
return array;
|
||||
}
|
||||
|
||||
private static void filterOutNonOpenable(List<PsiMember> members) {
|
||||
ListIterator<PsiMember> it = members.listIterator();
|
||||
while (it.hasNext()) {
|
||||
PsiMember member = it.next();
|
||||
if (isNonOpenable(member)) {
|
||||
it.remove();
|
||||
private static boolean isOpenable(PsiMember member) {
|
||||
return member.getContainingFile().getVirtualFile() != null;
|
||||
}
|
||||
|
||||
private static boolean hasSuperMethod(PsiMethod method) {
|
||||
PsiClass containingClass = method.getContainingClass();
|
||||
if (containingClass == null) return false;
|
||||
|
||||
for (PsiMethod candidate : containingClass.findMethodsByName(method.getName(), true)) {
|
||||
if (candidate.getContainingClass() != containingClass && PsiSuperMethodImplUtil.isSuperMethodSmart(method, candidate)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isNonOpenable(PsiMember member) {
|
||||
return member.getContainingFile().getVirtualFile() == null;
|
||||
}
|
||||
|
||||
private static PsiMethod[] filterInheritedMethods(PsiMethod[] methods) {
|
||||
ArrayList<PsiMethod> list = new ArrayList<PsiMethod>(methods.length);
|
||||
for (PsiMethod method : methods) {
|
||||
ProgressManager.checkCanceled();
|
||||
if (method.isConstructor()) continue;
|
||||
PsiMethod[] supers = method.findSuperMethods();
|
||||
if (supers.length > 0) continue;
|
||||
list.add(method);
|
||||
}
|
||||
return list.toArray(new PsiMethod[list.size()]);
|
||||
return false;
|
||||
}
|
||||
|
||||
private static class MyComparator implements Comparator<PsiModifierListOwner>{
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
package com.intellij.navigation
|
||||
|
||||
import com.intellij.ide.util.gotoByName.ChooseByNameBase
|
||||
import com.intellij.ide.util.gotoByName.ChooseByNameModel
|
||||
import com.intellij.ide.util.gotoByName.ChooseByNamePopup
|
||||
import com.intellij.ide.util.gotoByName.GotoClassModel2
|
||||
import com.intellij.ide.util.gotoByName.GotoSymbolModel2
|
||||
import com.intellij.openapi.Disposable
|
||||
import com.intellij.openapi.application.ModalityState
|
||||
import com.intellij.openapi.util.Disposer
|
||||
@@ -43,6 +43,28 @@ class ChooseByNameTest extends LightCodeInsightFixtureTestCase {
|
||||
assert getPopupElements(new GotoClassModel2(project), "@") == []
|
||||
}
|
||||
|
||||
public void "test filter overridden methods from goto symbol"() {
|
||||
def intf = myFixture.addClass("""
|
||||
class Intf {
|
||||
void xxx1() {}
|
||||
void xxx2() {}
|
||||
}""")
|
||||
def impl = myFixture.addClass("""
|
||||
class Impl extends Intf {
|
||||
void xxx1() {}
|
||||
void xxx3() {}
|
||||
}
|
||||
""")
|
||||
|
||||
def elements = getPopupElements(new GotoSymbolModel2(project), "xxx")
|
||||
|
||||
assert intf.findMethodsByName('xxx1', false)[0] in elements
|
||||
assert intf.findMethodsByName('xxx2', false)[0] in elements
|
||||
|
||||
assert impl.findMethodsByName('xxx3', false)[0] in elements
|
||||
assert !(impl.findMethodsByName('xxx1', false)[0] in elements)
|
||||
}
|
||||
|
||||
private List<Object> getPopupElements(ChooseByNameModel model, String text) {
|
||||
return getPopupElements(createPopup(model), text)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user