mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
PsiClassImplUtil: don't calculate substitutors when searching for members by name, e.g. static classes (IDEA-228814)
GitOrigin-RevId: 63f32377d8a4475ece1f97a1ab383f04da842801
This commit is contained in:
committed by
intellij-monorepo-bot
parent
faac23b4a5
commit
ab46d8b8ce
@@ -15,12 +15,9 @@ import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.java.stubs.PsiClassReferenceListStub;
|
||||
import com.intellij.psi.impl.source.ClassInnerStuffCache;
|
||||
import com.intellij.psi.impl.source.PsiImmediateClassType;
|
||||
import com.intellij.psi.infos.MethodCandidateInfo;
|
||||
import com.intellij.psi.scope.ElementClassFilter;
|
||||
import com.intellij.psi.scope.ElementClassHint;
|
||||
import com.intellij.psi.scope.NameHint;
|
||||
import com.intellij.psi.scope.PsiScopeProcessor;
|
||||
import com.intellij.psi.scope.processor.FilterScopeProcessor;
|
||||
import com.intellij.psi.scope.processor.MethodResolverProcessor;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.search.LocalSearchScope;
|
||||
@@ -34,6 +31,7 @@ import com.intellij.ui.icons.RowIcon;
|
||||
import com.intellij.util.*;
|
||||
import com.intellij.util.containers.ConcurrentFactoryMap;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.containers.JBTreeTraverser;
|
||||
import gnu.trove.THashMap;
|
||||
import gnu.trove.THashSet;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
@@ -354,35 +352,20 @@ public class PsiClassImplUtil {
|
||||
final List<PsiMember> allMembers = new ArrayList<>();
|
||||
map.put(ALL, allMembers);
|
||||
|
||||
ElementClassFilter filter = key == MemberType.CLASS ? ElementClassFilter.CLASS :
|
||||
key == MemberType.METHOD ? ElementClassFilter.METHOD :
|
||||
ElementClassFilter.FIELD;
|
||||
final ElementClassHint classHint = kind -> key == MemberType.CLASS && kind == ElementClassHint.DeclarationKind.CLASS ||
|
||||
key == MemberType.FIELD && (kind == ElementClassHint.DeclarationKind.FIELD || kind == ElementClassHint.DeclarationKind.ENUM_CONST) ||
|
||||
key == MemberType.METHOD && kind == ElementClassHint.DeclarationKind.METHOD;
|
||||
FilterScopeProcessor<MethodCandidateInfo> processor = new FilterScopeProcessor<MethodCandidateInfo>(filter) {
|
||||
@Override
|
||||
protected void add(@NotNull PsiElement element, @NotNull PsiSubstitutor substitutor) {
|
||||
if (key == MemberType.CLASS && element instanceof PsiClass ||
|
||||
key == MemberType.METHOD && element instanceof PsiMethod ||
|
||||
key == MemberType.FIELD && element instanceof PsiField) {
|
||||
PsiUtilCore.ensureValid(element);
|
||||
allMembers.add((PsiMember)element);
|
||||
String currentName = ((PsiMember)element).getName();
|
||||
List<PsiMember> listByName = map.computeIfAbsent(currentName, __ -> new SmartList<>());
|
||||
listByName.add((PsiMember)element);
|
||||
}
|
||||
JBTreeTraverser<PsiClass> allSupers = JBTreeTraverser
|
||||
.from((PsiClass c) -> ContainerUtil.mapNotNull(c.getSupers(), s -> PsiSuperMethodUtil.correctClassByScope(s, scope)))
|
||||
.unique()
|
||||
.withRoot(psiClass);
|
||||
for (PsiClass eachSuper : allSupers) {
|
||||
PsiMember[] members = key == MemberType.CLASS ? eachSuper.getInnerClasses() :
|
||||
key == MemberType.METHOD ? eachSuper.getMethods() :
|
||||
eachSuper.getFields();
|
||||
for (PsiMember element : members) {
|
||||
PsiUtilCore.ensureValid(element);
|
||||
allMembers.add(element);
|
||||
map.computeIfAbsent(element.getName(), __ -> new SmartList<>()).add(element);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <K> K getHint(@NotNull Key<K> hintKey) {
|
||||
//noinspection unchecked
|
||||
return ElementClassHint.KEY == hintKey ? (K)classHint : super.getHint(hintKey);
|
||||
}
|
||||
};
|
||||
|
||||
processDeclarationsInClassNotCached(psiClass, processor, ResolveState.initial(), null, null, psiClass, false,
|
||||
PsiUtil.getLanguageLevel(psiClass), scope);
|
||||
}
|
||||
Map<String, PsiMember[]> result = new THashMap<>();
|
||||
for (Map.Entry<String, List<PsiMember>> entry : map.entrySet()) {
|
||||
result.put(entry.getKey(), entry.getValue().toArray(PsiMember.EMPTY_ARRAY));
|
||||
@@ -397,7 +380,7 @@ public class PsiClassImplUtil {
|
||||
@Override
|
||||
public CachedValueProvider.Result<Map<GlobalSearchScope, MembersMap>> compute(@NotNull final PsiClass myClass) {
|
||||
Map<GlobalSearchScope, MembersMap> map = ConcurrentFactoryMap.createMap(scope -> new MembersMap(myClass, scope));
|
||||
return CachedValueProvider.Result.create(map, PsiModificationTracker.OUT_OF_CODE_BLOCK_MODIFICATION_COUNT);
|
||||
return CachedValueProvider.Result.create(map, PsiModificationTracker.MODIFICATION_COUNT);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -454,7 +437,7 @@ public class PsiClassImplUtil {
|
||||
return processCachedMembersByName(aClass, processor, state, visited, last, place, isRaw, substitutor,
|
||||
getValues(aClass).getValue(aClass).get(resolveScope), name, languageLevel, resolveScope);
|
||||
}
|
||||
return processDeclarationsInClassNotCached(aClass, processor, state, visited, last, place, isRaw, languageLevel, resolveScope);
|
||||
return processClassMembersWithAllNames(aClass, processor, state, visited, last, place, isRaw, languageLevel, resolveScope);
|
||||
}
|
||||
|
||||
private static boolean processCachedMembersByName(@NotNull final PsiClass aClass,
|
||||
@@ -474,13 +457,16 @@ public class PsiClassImplUtil {
|
||||
final PsiElementFactory factory = JavaPsiFacade.getElementFactory(aClass.getProject());
|
||||
@Override
|
||||
public PsiSubstitutor fun(PsiMember member) {
|
||||
PsiClass containingClass = ObjectUtils.assertNotNull(member.getContainingClass());
|
||||
PsiSubstitutor superSubstitutor = hierarchy.getSuperMembersSubstitutor(containingClass, languageLevel);
|
||||
PsiSubstitutor finalSubstitutor = obtainFinalSubstitutor(containingClass,
|
||||
superSubstitutor == null ? PsiSubstitutor.EMPTY : superSubstitutor,
|
||||
aClass, substitutor, factory, languageLevel);
|
||||
PsiSubstitutor finalSubstitutor = member.hasModifierProperty(PsiModifier.STATIC) ? substitutor : obtainSubstitutor(member);
|
||||
return member instanceof PsiMethod ? checkRaw(isRaw, factory, (PsiMethod)member, finalSubstitutor) : finalSubstitutor;
|
||||
}
|
||||
|
||||
private PsiSubstitutor obtainSubstitutor(PsiMember member) {
|
||||
PsiClass containingClass = ObjectUtils.assertNotNull(member.getContainingClass());
|
||||
PsiSubstitutor superSubstitutor = ObjectUtils.notNull(hierarchy.getSuperMembersSubstitutor(containingClass, languageLevel),
|
||||
PsiSubstitutor.EMPTY);
|
||||
return obtainFinalSubstitutor(containingClass, superSubstitutor, aClass, substitutor, factory, languageLevel);
|
||||
}
|
||||
};
|
||||
|
||||
final ElementClassHint classHint = processor.getHint(ElementClassHint.KEY);
|
||||
@@ -632,33 +618,24 @@ public class PsiClassImplUtil {
|
||||
return ((PsiClassType)type).resolveGenerics().getSubstitutor();
|
||||
}
|
||||
|
||||
private static boolean processDeclarationsInClassNotCached(@NotNull PsiClass aClass,
|
||||
@NotNull final PsiScopeProcessor processor,
|
||||
@NotNull final ResolveState state,
|
||||
@Nullable Set<PsiClass> visited,
|
||||
final PsiElement last,
|
||||
@NotNull final PsiElement place,
|
||||
final boolean isRaw,
|
||||
@NotNull final LanguageLevel languageLevel,
|
||||
@NotNull final GlobalSearchScope resolveScope) {
|
||||
private static boolean processClassMembersWithAllNames(@NotNull PsiClass aClass,
|
||||
@NotNull final PsiScopeProcessor processor,
|
||||
@NotNull final ResolveState state,
|
||||
@Nullable Set<PsiClass> visited,
|
||||
final PsiElement last,
|
||||
@NotNull final PsiElement place,
|
||||
final boolean isRaw,
|
||||
@NotNull final LanguageLevel languageLevel,
|
||||
@NotNull final GlobalSearchScope resolveScope) {
|
||||
ProgressManager.checkCanceled();
|
||||
if (visited == null) visited = new THashSet<>();
|
||||
if (!visited.add(aClass)) return true;
|
||||
processor.handleEvent(PsiScopeProcessor.Event.SET_DECLARATION_HOLDER, aClass);
|
||||
final ElementClassHint classHint = processor.getHint(ElementClassHint.KEY);
|
||||
final NameHint nameHint = processor.getHint(NameHint.KEY);
|
||||
|
||||
|
||||
if (classHint == null || classHint.shouldProcess(ElementClassHint.DeclarationKind.FIELD)) {
|
||||
if (nameHint != null) {
|
||||
final PsiField fieldByName = aClass.findFieldByName(nameHint.getName(state), false);
|
||||
if (fieldByName != null && !processor.execute(fieldByName, state)) return false;
|
||||
}
|
||||
else {
|
||||
final PsiField[] fields = aClass.getFields();
|
||||
for (final PsiField field : fields) {
|
||||
if (!processor.execute(field, state)) return false;
|
||||
}
|
||||
for (PsiField field : aClass.getFields()) {
|
||||
if (!processor.execute(field, state)) return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -666,8 +643,7 @@ public class PsiClassImplUtil {
|
||||
|
||||
if (classHint == null || classHint.shouldProcess(ElementClassHint.DeclarationKind.METHOD)) {
|
||||
PsiSubstitutor baseSubstitutor = state.get(PsiSubstitutor.KEY);
|
||||
final PsiMethod[] methods = nameHint != null ? aClass.findMethodsByName(nameHint.getName(state), false) : aClass.getMethods();
|
||||
for (final PsiMethod method : methods) {
|
||||
for (PsiMethod method : aClass.getMethods()) {
|
||||
PsiSubstitutor finalSubstitutor = checkRaw(isRaw, factory, method, baseSubstitutor);
|
||||
ResolveState methodState = finalSubstitutor == baseSubstitutor ? state : state.put(PsiSubstitutor.KEY, finalSubstitutor);
|
||||
if (!processor.execute(method, methodState)) return false;
|
||||
@@ -682,18 +658,8 @@ public class PsiClassImplUtil {
|
||||
}
|
||||
|
||||
if (!(last instanceof PsiReferenceList) && !(last instanceof PsiModifierList)) {
|
||||
// Inners
|
||||
if (nameHint != null) {
|
||||
final PsiClass inner = aClass.findInnerClassByName(nameHint.getName(state), false);
|
||||
if (inner != null) {
|
||||
if (!processor.execute(inner, state)) return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
final PsiClass[] inners = aClass.getInnerClasses();
|
||||
for (final PsiClass inner : inners) {
|
||||
if (!processor.execute(inner, state)) return false;
|
||||
}
|
||||
for (PsiClass inner : aClass.getInnerClasses()) {
|
||||
if (!processor.execute(inner, state)) return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1056,7 +1022,7 @@ public class PsiClassImplUtil {
|
||||
@NotNull PsiManager manager) {
|
||||
if (list == null) return false;
|
||||
if (list instanceof StubBasedPsiElement) {
|
||||
StubElement stub = ((StubBasedPsiElement)list).getStub();
|
||||
StubElement<?> stub = ((StubBasedPsiElement<?>)list).getStub();
|
||||
if (stub instanceof PsiClassReferenceListStub && baseName != null) {
|
||||
// classStub.getReferencedNames() is cheaper than getReferencedTypes()
|
||||
PsiClassReferenceListStub classStub = (PsiClassReferenceListStub)stub;
|
||||
|
||||
@@ -389,7 +389,6 @@ public class RecursionManager {
|
||||
"com.intellij.psi.impl.source.resolve.graphInference.PsiPolyExpressionUtil.isPolyExpression(",
|
||||
// inner class imports
|
||||
"com.intellij.psi.impl.source.PsiJavaFileBaseImpl.processDeclarations(",
|
||||
"com.intellij.psi.impl.PsiClassImplUtil.getScopeCorrectedSuperTypes(",
|
||||
|
||||
// IDEA-212671
|
||||
"com.intellij.xml.impl.schema.XmlNSDescriptorImpl.getRedefinedElementDescriptor(",
|
||||
|
||||
Reference in New Issue
Block a user