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:
Peter Gromov
2019-12-17 21:33:47 +00:00
committed by intellij-monorepo-bot
parent faac23b4a5
commit ab46d8b8ce
2 changed files with 39 additions and 74 deletions
@@ -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(",