[java] migrate some usages of getOrderEntriesForFile to findContainingSdks/Libraries to improve performance (IJPL-930)

'getOrderEntriesForFile' builds 'OrderEntryGraph' for the whole project when called for the first time after a 'rootsChanged' event. This may lead to freezes, so it's much more efficient to use newly introduced 'findContainingSdks' and 'findContainingLibraries' methods from 'ProjectFileIndex' instead where it's possible.

Semantics of code which used 'ModuleFileIndex' (not 'ProjectFileIndex') before may change if some file is part of an SDK in one module and part of a source code of another module, but in practice such cases shouldn't happen.

GitOrigin-RevId: 57ee33df6fe10d4d90687d68245a7dba3e6b7b03
This commit is contained in:
Nikolay Chashnikov
2025-09-26 17:24:06 +00:00
committed by intellij-monorepo-bot
parent cd899d9e2d
commit d010a99375
6 changed files with 13 additions and 29 deletions
@@ -3,8 +3,8 @@ package com.intellij.java.codeserver.core
import com.intellij.openapi.module.Module
import com.intellij.openapi.module.ModuleUtilCore
import com.intellij.openapi.roots.JdkOrderEntry
import com.intellij.openapi.roots.ModuleRootManager
import com.intellij.openapi.roots.ProjectFileIndex
import com.intellij.openapi.roots.ProjectRootManager
import com.intellij.openapi.vfs.VfsUtilCore
import com.intellij.openapi.vfs.VirtualFile
@@ -65,7 +65,7 @@ data class JpmsModuleAccessInfo(val current: JpmsModuleInfo.CurrentModuleInfo, v
if (current.module == null) {
val origin = targetModule.containingFile?.virtualFile
if (origin == null || currentJpsModule == null ||
ModuleRootManager.getInstance(currentJpsModule).fileIndex.getOrderEntryForFile(origin) !is JdkOrderEntry
ProjectFileIndex.getInstance(currentJpsModule.project).findContainingSdks(origin).isEmpty()
) {
return null // a target is not on the mandatory module path
}
@@ -133,7 +133,7 @@ data class JpmsModuleAccessInfo(val current: JpmsModuleInfo.CurrentModuleInfo, v
if (origin == null && targetModule is LightJavaModule) origin = targetModule.rootVirtualFile
if (origin == null || currentJpsModule == null) return null
if (ModuleRootManager.getInstance(currentJpsModule).fileIndex.getOrderEntryForFile(origin) !is JdkOrderEntry) {
if (ProjectFileIndex.getInstance(currentJpsModule.project).findContainingSdks(origin).isEmpty()) {
val searchScope = GlobalSearchScope.moduleWithDependenciesAndLibrariesScope(currentJpsModule)
if (searchScope.contains(origin)) return null
return JpmsModuleAccessProblem.JPS_DEPENDENCY_PROBLEM
@@ -248,10 +248,10 @@ data class JpmsModuleAccessInfo(val current: JpmsModuleInfo.CurrentModuleInfo, v
if (target != null) {
val useVFile = place.virtualFile
if (useVFile != null) {
val index = ModuleRootManager.getInstance(module).fileIndex
val test = index.isInTestSourceContent(useVFile)
val test = ModuleRootManager.getInstance(module).fileIndex.isInTestSourceContent(useVFile)
val dirs = target.getDirectories(module.getModuleWithDependenciesAndLibrariesScope(test))
return dirs.any { index.getOrderEntryForFile(it.virtualFile) !is JdkOrderEntry }
val projectFileIndex = ProjectFileIndex.getInstance(module.project)
return dirs.any { projectFileIndex.findContainingSdks(it.virtualFile).isEmpty() }
}
}
}
@@ -64,7 +64,7 @@ final class ModuleChecker {
PsiJavaModule anotherJavaModule = JavaPsiModuleUtil.findDescriptorByElement(directory);
if (anotherJavaModule != null) {
VirtualFile moduleVFile = PsiUtilCore.getVirtualFile(anotherJavaModule);
if (moduleVFile != null && ContainerUtil.find(fileIndex.getOrderEntriesForFile(moduleVFile), JdkOrderEntry.class::isInstance) != null) {
if (moduleVFile != null && !fileIndex.findContainingSdks(moduleVFile).isEmpty()) {
VirtualFile rootForFile = fileIndex.getSourceRootForFile(file.getVirtualFile());
if (rootForFile != null && JavaCompilerConfigurationProxy.isPatchedModuleRoot(anotherJavaModule.getName(), module, rootForFile)) {
return;
@@ -242,10 +242,10 @@ public final class JavaFileManagerImpl implements JavaFileManager, Disposable {
if (isModular) {
List<PsiJavaModule> list = new ArrayList<>(modules);
ModuleFileIndex index = ModuleRootManager.getInstance(module).getFileIndex();
ProjectFileIndex index = ProjectFileIndex.getInstance(module.getProject());
for (ListIterator<PsiJavaModule> i = list.listIterator(); i.hasNext(); ) {
PsiJavaModule candidate = i.next();
if (index.getOrderEntryForFile(PsiImplUtil.getModuleVirtualFile(candidate)) instanceof JdkOrderEntry) {
if (!index.findContainingSdks(PsiImplUtil.getModuleVirtualFile(candidate)).isEmpty()) {
if (i.previousIndex() > 0) {
i.remove(); // not at the top -> is upgraded
}
@@ -11,8 +11,8 @@ import com.intellij.ide.util.PropertiesComponent
import com.intellij.java.JavaBundle
import com.intellij.openapi.Disposable
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.application.readAction
import com.intellij.openapi.application.edtWriteAction
import com.intellij.openapi.application.readAction
import com.intellij.openapi.components.Service
import com.intellij.openapi.components.serviceAsync
import com.intellij.openapi.editor.Editor
@@ -112,7 +112,7 @@ private class FileNotInSourceRootService(
val fileIndex = ProjectFileIndex.getInstance(project)
if (fileIndex.isInSource(virtualFile) || fileIndex.isExcluded(virtualFile) || fileIndex.isUnderIgnored(virtualFile)) return null
if (fileIndex.getOrderEntriesForFile(virtualFile).isNotEmpty()) return null
if (fileIndex.findContainingLibraries(virtualFile).isNotEmpty() || fileIndex.findContainingSdks(virtualFile).isNotEmpty()) return null
val psiFile = PsiDocumentManager.getInstance(project).getPsiFile(editor.document) as? PsiJavaFile ?: return null
if (DaemonCodeAnalyzerEx.getInstanceEx(project).hasFileLevelHighlights(GROUP, psiFile)) return null
@@ -2,8 +2,6 @@
package com.intellij.psi.util.proximity;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.JdkOrderEntry;
import com.intellij.openapi.roots.OrderEntry;
import com.intellij.openapi.roots.ProjectRootManager;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiElement;
@@ -12,8 +10,6 @@ import com.intellij.psi.util.PsiUtilCore;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import java.util.List;
@ApiStatus.Internal
public final class SdkOrLibraryWeigher extends ProximityWeigher {
@@ -25,12 +21,6 @@ public final class SdkOrLibraryWeigher extends ProximityWeigher {
private static boolean isJdkElement(PsiElement element, final @NotNull Project project) {
final VirtualFile file = PsiUtilCore.getVirtualFile(element);
if (file != null) {
List<OrderEntry> orderEntries = ProjectRootManager.getInstance(project).getFileIndex().getOrderEntriesForFile(file);
if (!orderEntries.isEmpty() && orderEntries.get(0) instanceof JdkOrderEntry) {
return true;
}
}
return false;
return file != null && !ProjectRootManager.getInstance(project).getFileIndex().findContainingSdks(file).isEmpty();
}
}
@@ -38,13 +38,7 @@ public class ModuleUtilCore {
public static boolean projectContainsFile(@NotNull Project project, @NotNull VirtualFile file, boolean isLibraryElement) {
ProjectFileIndex projectFileIndex = ProjectFileIndex.getInstance(project);
if (isLibraryElement) {
List<OrderEntry> orders = projectFileIndex.getOrderEntriesForFile(file);
for (OrderEntry orderEntry : orders) {
if (orderEntry instanceof JdkOrderEntry || orderEntry instanceof LibraryOrderEntry) {
return true;
}
}
return false;
return !projectFileIndex.findContainingSdks(file).isEmpty() || !projectFileIndex.findContainingLibraries(file).isEmpty();
}
else {
return projectFileIndex.isInContent(file);