diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/PerModulePackageCacheService.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/PerModulePackageCacheService.kt index 6b6fea02e63..c1e645434fa 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/PerModulePackageCacheService.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/PerModulePackageCacheService.kt @@ -16,7 +16,7 @@ package org.jetbrains.kotlin.idea.caches -import com.intellij.openapi.components.ServiceManager +import com.intellij.openapi.components.service import com.intellij.openapi.project.Project import com.intellij.openapi.util.Key import com.intellij.openapi.util.Ref @@ -57,13 +57,13 @@ class KotlinPackageContentModificationListener( .filterNotNull() .filter { it in scope } .forEach { file -> - PerModulePackageCacheService.notifyPackageChange(file, project) + project.service().notifyPackageChange(file) } }) } } -class KotlinPackageStatementPsiTreeChangePreprocessor : PsiTreeChangePreprocessor { +class KotlinPackageStatementPsiTreeChangePreprocessor(private val project: Project) : PsiTreeChangePreprocessor { override fun treeChanged(event: PsiTreeChangeEventImpl) { val file = event.file as? KtFile ?: return @@ -71,7 +71,7 @@ class KotlinPackageStatementPsiTreeChangePreprocessor : PsiTreeChangePreprocesso PsiTreeChangeEventImpl.PsiEventType.CHILD_ADDED, PsiTreeChangeEventImpl.PsiEventType.CHILD_MOVED, PsiTreeChangeEventImpl.PsiEventType.CHILD_REPLACED, PsiTreeChangeEventImpl.PsiEventType.CHILD_REMOVED -> { val child = event.child ?: return if (child.getParentOfType(false) != null) - PerModulePackageCacheService.notifyPackageChange(file) + project.service().notifyPackageChange(file) } else -> { } @@ -79,46 +79,43 @@ class KotlinPackageStatementPsiTreeChangePreprocessor : PsiTreeChangePreprocesso } } -class PerModulePackageCacheService { +class PerModulePackageCacheService(private val project: Project) { - val cache = ContainerUtil.createConcurrentWeakMap>>() + private val cache = ContainerUtil.createConcurrentWeakMap>>() - companion object { + internal fun notifyPackageChange(file: VirtualFile) { + (getModuleInfoByVirtualFile(project, file) as? ModuleSourceInfo)?.let { onChangeInModuleSource(it) } + } - val PER_MODULE_PACKAGE_CACHE = Key.create>>>("per_module_package_cache") + internal fun notifyPackageChange(file: KtFile) { + (file.getNullableModuleInfo() as? ModuleSourceInfo)?.let { onChangeInModuleSource(it) } + } - internal fun notifyPackageChange(file: KtFile): Unit { - (file.getNullableModuleInfo() as? ModuleSourceInfo)?.let { onChangeInModuleSource(it, file.project) } + internal fun onChangeInModuleSource(moduleSourceInfo: ModuleSourceInfo) { + cache[moduleSourceInfo]?.set(null) + } + + fun packageExists(packageFqName: FqName, moduleInfo: ModuleSourceInfo): Boolean { + val module = moduleInfo.module + + // Module own cache is a view on global cache. Since global cache based on WeakReferences when module + // gets disposed this soft map will be disposed too, leading to drop soft refs on ModuleInfo's, and then to + // disposing global cache entry + val moduleOwnCache = module.getUserData(PerModulePackageCacheService.PER_MODULE_PACKAGE_CACHE) ?: run { + ContainerUtil.createConcurrentSoftMap>>() + .apply { module.putUserData(PerModulePackageCacheService.PER_MODULE_PACKAGE_CACHE, this) } } - - internal fun onChangeInModuleSource(moduleSourceInfo: ModuleSourceInfo, project: Project) = with(getInstance(project)) { - cache[moduleSourceInfo]?.set(null) - } - - internal fun notifyPackageChange(file: VirtualFile, project: Project): Unit { - (getModuleInfoByVirtualFile(project, file) as? ModuleSourceInfo)?.let { onChangeInModuleSource(it, project) } - } - - fun getInstance(project: Project): PerModulePackageCacheService = ServiceManager.getService(project, PerModulePackageCacheService::class.java) - - fun packageExists(packageFqName: FqName, moduleInfo: ModuleSourceInfo, project: Project): Boolean = with(getInstance(project)) { - val module = moduleInfo.module - - // Module own cache is a view on global cache. Since global cache based on WeakReferences when module - // gets disposed this soft map will be disposed too, leading to drop soft refs on ModuleInfo's, and then to - // disposing global cache entry - val moduleOwnCache = module.getUserData(PerModulePackageCacheService.PER_MODULE_PACKAGE_CACHE) ?: run { - ContainerUtil.createConcurrentSoftMap>>() - .apply { module.putUserData(PerModulePackageCacheService.PER_MODULE_PACKAGE_CACHE, this) } - } - val cached = moduleOwnCache.getOrPut(moduleInfo) { cache.getOrPut(moduleInfo) { Ref() } } - .apply { if (isNull) set(ContainerUtil.createConcurrentSoftMap()) } - .get() + val cached = moduleOwnCache.getOrPut(moduleInfo) { cache.getOrPut(moduleInfo) { Ref() } } + .apply { if (isNull) set(ContainerUtil.createConcurrentSoftMap()) } + .get() - return cached.getOrPut(packageFqName) { - PackageIndexUtil.packageExists(packageFqName, moduleInfo.contentScope(), project) - } + return cached.getOrPut(packageFqName) { + PackageIndexUtil.packageExists(packageFqName, moduleInfo.contentScope(), project) } } + + companion object { + private val PER_MODULE_PACKAGE_CACHE = Key.create>>>("per_module_package_cache") + } } \ No newline at end of file diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/stubindex/resolve/PluginDeclarationProviderFactory.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/stubindex/resolve/PluginDeclarationProviderFactory.kt index e64c5e68eb9..dfbef347f40 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/stubindex/resolve/PluginDeclarationProviderFactory.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/stubindex/resolve/PluginDeclarationProviderFactory.kt @@ -16,6 +16,7 @@ package org.jetbrains.kotlin.idea.stubindex.resolve +import com.intellij.openapi.components.service import com.intellij.openapi.project.Project import com.intellij.psi.search.GlobalSearchScope import org.jetbrains.kotlin.analyzer.ModuleInfo @@ -55,7 +56,7 @@ class PluginDeclarationProviderFactory( private fun packageExists(name: FqName): Boolean { return if (moduleInfo is ModuleSourceInfo) - PerModulePackageCacheService.packageExists(name, moduleInfo, project) + project.service().packageExists(name, moduleInfo) else PackageIndexUtil.packageExists(name, indexedFilesScope, project) }