mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
java: speedup resolving of statically-imported members by honoring name hint (IDEA-247726)
GitOrigin-RevId: 8cbdf1fca1afc4023fc95f1ed5e6da5fcc589000
This commit is contained in:
committed by
intellij-monorepo-bot
parent
781de9a390
commit
553cf412e7
@@ -123,6 +123,37 @@ public final class PsiClassImplUtil {
|
||||
return byMap.isEmpty() ? null : (PsiClass)byMap.get(0);
|
||||
}
|
||||
|
||||
public static boolean processAllMembersWithoutSubstitutors(@NotNull PsiClass psiClass, @NotNull PsiScopeProcessor processor, @NotNull ResolveState state) {
|
||||
ElementClassHint classHint = processor.getHint(ElementClassHint.KEY);
|
||||
|
||||
NameHint nameHint = processor.getHint(NameHint.KEY);
|
||||
String name = nameHint == null ? null : nameHint.getName(state);
|
||||
|
||||
if ((classHint == null || classHint.shouldProcess(ElementClassHint.DeclarationKind.METHOD)) &&
|
||||
!processMembers(state, processor, getMap(psiClass, MemberType.METHOD).get(name == null ? ALL : name))) {
|
||||
return false;
|
||||
}
|
||||
if ((classHint == null || classHint.shouldProcess(ElementClassHint.DeclarationKind.FIELD)) &&
|
||||
!processMembers(state, processor, getMap(psiClass, MemberType.FIELD).get(name == null ? ALL : name))) {
|
||||
return false;
|
||||
}
|
||||
if ((classHint == null || classHint.shouldProcess(ElementClassHint.DeclarationKind.CLASS)) &&
|
||||
!processMembers(state, processor, getMap(psiClass, MemberType.CLASS).get(name == null ? ALL : name))) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static boolean processMembers(ResolveState state, PsiScopeProcessor processor, PsiMember @Nullable[] members) {
|
||||
if (members == null) return true;
|
||||
for (PsiMember member : members) {
|
||||
if (!processor.execute(member, state)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static List<PsiMember> findByMap(@NotNull PsiClass aClass, String name, boolean checkBases, @NotNull MemberType type) {
|
||||
if (name == null) return Collections.emptyList();
|
||||
@@ -630,9 +661,7 @@ public final class PsiClassImplUtil {
|
||||
ElementClassHint classHint = processor.getHint(ElementClassHint.KEY);
|
||||
|
||||
if (classHint == null || classHint.shouldProcess(ElementClassHint.DeclarationKind.FIELD)) {
|
||||
for (PsiField field : aClass.getFields()) {
|
||||
if (!processor.execute(field, state)) return false;
|
||||
}
|
||||
if (!processMembers(state, processor, aClass.getFields())) return false;
|
||||
}
|
||||
|
||||
PsiElementFactory factory = JavaPsiFacade.getElementFactory(aClass.getProject());
|
||||
@@ -654,9 +683,7 @@ public final class PsiClassImplUtil {
|
||||
}
|
||||
|
||||
if (!(last instanceof PsiReferenceList) && !(last instanceof PsiModifierList)) {
|
||||
for (PsiClass inner : aClass.getInnerClasses()) {
|
||||
if (!processor.execute(inner, state)) return false;
|
||||
}
|
||||
if (!processMembers(state, processor, aClass.getInnerClasses())) return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@ import com.intellij.pom.java.LanguageLevel;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
|
||||
import com.intellij.psi.impl.JavaPsiImplementationHelper;
|
||||
import com.intellij.psi.impl.PsiClassImplUtil;
|
||||
import com.intellij.psi.impl.PsiFileEx;
|
||||
import com.intellij.psi.impl.PsiImplUtil;
|
||||
import com.intellij.psi.impl.java.stubs.JavaStubElementTypes;
|
||||
@@ -354,7 +355,8 @@ public abstract class PsiJavaFileBaseImpl extends PsiFileImpl implements PsiJava
|
||||
}
|
||||
|
||||
private boolean processOnDemandPackages(PsiScopeProcessor processor, @NotNull ResolveState state, PsiElement place) {
|
||||
boolean shouldProcessClasses = shouldProcess(processor, CLASS);
|
||||
ElementClassHint classHint = processor.getHint(ElementClassHint.KEY);
|
||||
boolean shouldProcessClasses = classHint == null || classHint.shouldProcess(CLASS);
|
||||
if (shouldProcessClasses) {
|
||||
if (!processCurrentPackage(processor, state, place)) return false;
|
||||
if (!processOnDemandTypeImports(processor, state, place)) return false;
|
||||
@@ -375,11 +377,6 @@ public abstract class PsiJavaFileBaseImpl extends PsiFileImpl implements PsiJava
|
||||
return getImportList() != null ? getImportList().getImportStatements() : PsiImportStatement.EMPTY_ARRAY;
|
||||
}
|
||||
|
||||
private static boolean shouldProcess(PsiScopeProcessor processor, ElementClassHint.DeclarationKind kind) {
|
||||
ElementClassHint classHint = processor.getHint(ElementClassHint.KEY);
|
||||
return classHint == null || classHint.shouldProcess(kind);
|
||||
}
|
||||
|
||||
private boolean processCurrentPackage(PsiScopeProcessor processor, ResolveState state, PsiElement place) {
|
||||
processor.handleEvent(JavaScopeProcessorEvent.SET_CURRENT_FILE_CONTEXT, null);
|
||||
PsiPackage aPackage = JavaPsiFacade.getInstance(myManager.getProject()).findPackage(getPackageName());
|
||||
@@ -405,18 +402,7 @@ public abstract class PsiJavaFileBaseImpl extends PsiFileImpl implements PsiJava
|
||||
final PsiClass targetElement = importStaticStatement.resolveTargetClass();
|
||||
if (targetElement != null) {
|
||||
processor.handleEvent(JavaScopeProcessorEvent.SET_CURRENT_FILE_CONTEXT, importStaticStatement);
|
||||
if (shouldProcess(processor, METHOD) && !processMembers(state, processor, targetElement.getAllMethods())) return false;
|
||||
if (shouldProcess(processor, FIELD) && !processMembers(state, processor, targetElement.getAllFields())) return false;
|
||||
if (shouldProcess(processor, CLASS) && !processMembers(state, processor, targetElement.getAllInnerClasses())) return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static boolean processMembers(ResolveState state, PsiScopeProcessor processor, PsiMember[] members) {
|
||||
for (PsiMember member : members) {
|
||||
if (!processor.execute(member, state)) {
|
||||
return false;
|
||||
if (!PsiClassImplUtil.processAllMembersWithoutSubstitutors(targetElement, processor, state)) return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
||||
+17
@@ -2197,4 +2197,21 @@ class Abc {
|
||||
assert !lookup
|
||||
}.assertTiming()
|
||||
}
|
||||
|
||||
void "test performance with many matching statically-imported declarations"() {
|
||||
def fieldCount = 7000
|
||||
|
||||
myFixture.addClass("interface Constants {" +
|
||||
(0..<fieldCount).collect { "String field$it = \"x\";\n" } +
|
||||
"}")
|
||||
myFixture.configureByText("a.java", "import static Constants.*; class C { { field<caret>x } }")
|
||||
PlatformTestUtil.startPerformanceTest(name, 10_000, {
|
||||
assert myFixture.completeBasic().length > 100
|
||||
}).setup {
|
||||
lookup?.hideLookup(true)
|
||||
myFixture.type("\bd")
|
||||
psiManager.dropPsiCaches()
|
||||
assert !lookup
|
||||
}.assertTiming()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ import com.intellij.psi.xml.XmlAttributeValue;
|
||||
import com.intellij.testFramework.JavaResolveTestCase;
|
||||
import com.intellij.testFramework.PlatformTestUtil;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import one.util.streamex.IntStreamEx;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
@@ -108,6 +109,34 @@ public class ResolvePerformanceTest extends JavaResolveTestCase {
|
||||
.attempts(1).assertTiming();
|
||||
}
|
||||
|
||||
public void testResolveOfManyStaticallyImportedFields() throws Exception {
|
||||
int fieldCount = 7000;
|
||||
|
||||
createFile(myModule, "Constants.java",
|
||||
"interface Constants { " +
|
||||
IntStreamEx.range(0, fieldCount).mapToObj(i -> "String field" + i + ";").joining("\n") +
|
||||
"}");
|
||||
|
||||
PsiFile file = createFile(myModule, "a.java",
|
||||
"import static Constants.*;\n" +
|
||||
"class Usage { \n" +
|
||||
"void foo(String s) {}\n" +
|
||||
"{" +
|
||||
IntStreamEx.range(0, fieldCount).mapToObj(i -> "foo(field" + i + ");").joining("\n") +
|
||||
"}}");
|
||||
|
||||
List<PsiJavaCodeReferenceElement> refs = SyntaxTraverser.psiTraverser(file).filter(PsiJavaCodeReferenceElement.class).toList();
|
||||
|
||||
PlatformTestUtil.startPerformanceTest(getTestName(false), 1_000, () -> {
|
||||
for (PsiJavaCodeReferenceElement ref : refs) {
|
||||
assertNotNull(ref.resolve());
|
||||
}
|
||||
})
|
||||
.setup(getPsiManager()::dropPsiCaches)
|
||||
.assertTiming();
|
||||
|
||||
}
|
||||
|
||||
private void ensureIndexUpToDate() {
|
||||
getJavaFacade().findClass(CommonClassNames.JAVA_UTIL_LIST, GlobalSearchScope.allScope(myProject));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user