Improve package caching in KotlinJavaPsiFacade

^KT-33394 Fixed
This commit is contained in:
Vladimir Dolzhenko
2020-09-10 07:38:46 +00:00
parent 05d3e48564
commit 5036673187
22 changed files with 348 additions and 121 deletions
@@ -15,6 +15,8 @@ import com.intellij.openapi.roots.impl.libraries.LibraryEx
import com.intellij.openapi.roots.libraries.Library
import com.intellij.openapi.util.ModificationTracker
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.openapi.vfs.newvfs.NewVirtualFile
import com.intellij.openapi.vfs.newvfs.NewVirtualFileSystem
import com.intellij.psi.search.GlobalSearchScope
import com.intellij.util.PathUtil
import com.intellij.util.SmartList
@@ -58,6 +60,7 @@ import org.jetbrains.kotlin.platform.konan.NativePlatform
import org.jetbrains.kotlin.platform.konan.NativePlatforms
import org.jetbrains.kotlin.platform.konan.isNative
import org.jetbrains.kotlin.resolve.PlatformDependentAnalyzerServices
import org.jetbrains.kotlin.resolve.jvm.TopPackageNamesProvider
import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatformAnalyzerServices
import org.jetbrains.kotlin.types.typeUtil.closure
import org.jetbrains.kotlin.utils.addIfNotNull
@@ -459,9 +462,40 @@ object NotUnderContentRootModuleInfo : IdeaModuleInfo {
get() = platform.single().findAnalyzerServices()
}
internal open class PoweredLibraryScopeBase(project: Project, classes: Array<VirtualFile>, sources: Array<VirtualFile>) :
LibraryScopeBase(project, classes, sources), TopPackageNamesProvider {
private val entriesVirtualFileSystems: Set<NewVirtualFileSystem>? = run {
val fileSystems = mutableSetOf<NewVirtualFileSystem>()
for (file in classes + sources) {
val newVirtualFile = file as? NewVirtualFile ?: return@run null
fileSystems.add(newVirtualFile.fileSystem)
}
fileSystems
}
override val topPackageNames: Set<String> by lazy {
(classes + sources)
.flatMap { it.children.toList() }
.filter(VirtualFile::isDirectory)
.map(VirtualFile::getName)
.toSet() + "" // empty package is always present
}
override fun contains(file: VirtualFile): Boolean {
((file as? NewVirtualFile)?.fileSystem)?.let {
if (entriesVirtualFileSystems != null && !entriesVirtualFileSystems.contains(it)) {
return false
}
}
return super.contains(file)
}
}
@Suppress("EqualsOrHashCode") // DelegatingGlobalSearchScope requires to provide calcHashCode()
private class LibraryWithoutSourceScope(project: Project, private val library: Library) :
LibraryScopeBase(project, library.getFiles(OrderRootType.CLASSES), arrayOf<VirtualFile>()) {
PoweredLibraryScopeBase(project, library.getFiles(OrderRootType.CLASSES), arrayOf()) {
override fun getFileRoot(file: VirtualFile): VirtualFile? = myIndex.getClassRootForFile(file)
@@ -474,7 +508,7 @@ private class LibraryWithoutSourceScope(project: Project, private val library: L
@Suppress("EqualsOrHashCode") // DelegatingGlobalSearchScope requires to provide calcHashCode()
private class LibrarySourceScope(project: Project, private val library: Library) :
LibraryScopeBase(project, arrayOf<VirtualFile>(), library.getFiles(OrderRootType.SOURCES)) {
PoweredLibraryScopeBase(project, arrayOf(), library.getFiles(OrderRootType.SOURCES)) {
override fun getFileRoot(file: VirtualFile): VirtualFile? = myIndex.getSourceRootForFile(file)
@@ -488,7 +522,7 @@ private class LibrarySourceScope(project: Project, private val library: Library)
//TODO: (module refactoring) android sdk has modified scope
@Suppress("EqualsOrHashCode") // DelegatingGlobalSearchScope requires to provide calcHashCode()
private class SdkScope(project: Project, val sdk: Sdk) :
LibraryScopeBase(project, sdk.rootProvider.getFiles(OrderRootType.CLASSES), arrayOf<VirtualFile>()) {
PoweredLibraryScopeBase(project, sdk.rootProvider.getFiles(OrderRootType.CLASSES), arrayOf()) {
override fun equals(other: Any?) = other is SdkScope && sdk == other.sdk
@@ -29,8 +29,8 @@ abstract class DeserializerForDecompilerBase(val directoryPackageFqName: FqName)
protected val moduleDescriptor: ModuleDescriptorImpl = createDummyModule("module for building decompiled sources")
protected val packageFragmentProvider: PackageFragmentProvider = object : PackageFragmentProvider {
override fun getPackageFragments(fqName: FqName): List<PackageFragmentDescriptor> {
return listOf(createDummyPackageFragment(fqName))
override fun collectPackageFragments(fqName: FqName, packageFragments: MutableCollection<PackageFragmentDescriptor>) {
packageFragments.add(createDummyPackageFragment(fqName))
}
override fun getSubPackagesOf(fqName: FqName, nameFilter: (Name) -> Boolean): Collection<FqName> {
@@ -16,10 +16,13 @@
package org.jetbrains.kotlin.idea;
import com.intellij.ProjectTopics;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.extensions.PluginId;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ModuleRootEvent;
import com.intellij.openapi.roots.ModuleRootListener;
import com.intellij.openapi.startup.StartupActivity;
import com.intellij.openapi.updateSettings.impl.UpdateChecker;
import org.jetbrains.annotations.NotNull;
@@ -27,6 +30,7 @@ import org.jetbrains.kotlin.diagnostics.DiagnosticFactory;
import org.jetbrains.kotlin.diagnostics.Errors;
import org.jetbrains.kotlin.idea.reporter.KotlinReportSubmitter;
import org.jetbrains.kotlin.js.resolve.diagnostics.ErrorsJs;
import org.jetbrains.kotlin.resolve.jvm.KotlinJavaPsiFacade;
import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm;
import org.jetbrains.kotlin.resolve.konan.diagnostics.ErrorsNative;
@@ -44,6 +48,13 @@ public class PluginStartupActivity implements StartupActivity {
StartupCompatKt.runActivity(project);
PluginStartupService.Companion.getInstance(project).register(project);
project.getMessageBus().connect().subscribe(ProjectTopics.PROJECT_ROOTS, new ModuleRootListener() {
@Override
public void rootsChanged(@NotNull ModuleRootEvent event) {
KotlinJavaPsiFacade.getInstance(project).clearPackageCaches();
}
});
initializeDiagnostics();
try {