Minor: refactor PerModulePackageCacheService
This commit is contained in:
+34
-37
@@ -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<PerModulePackageCacheService>().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<KtPackageDirective>(false) != null)
|
||||
PerModulePackageCacheService.notifyPackageChange(file)
|
||||
project.service<PerModulePackageCacheService>().notifyPackageChange(file)
|
||||
}
|
||||
else -> {
|
||||
}
|
||||
@@ -79,46 +79,43 @@ class KotlinPackageStatementPsiTreeChangePreprocessor : PsiTreeChangePreprocesso
|
||||
}
|
||||
}
|
||||
|
||||
class PerModulePackageCacheService {
|
||||
class PerModulePackageCacheService(private val project: Project) {
|
||||
|
||||
val cache = ContainerUtil.createConcurrentWeakMap<ModuleInfo, Ref<ConcurrentMap<FqName, Boolean>>>()
|
||||
private val cache = ContainerUtil.createConcurrentWeakMap<ModuleInfo, Ref<ConcurrentMap<FqName, Boolean>>>()
|
||||
|
||||
companion object {
|
||||
internal fun notifyPackageChange(file: VirtualFile) {
|
||||
(getModuleInfoByVirtualFile(project, file) as? ModuleSourceInfo)?.let { onChangeInModuleSource(it) }
|
||||
}
|
||||
|
||||
val PER_MODULE_PACKAGE_CACHE = Key.create<ConcurrentMap<ModuleInfo, Ref<ConcurrentMap<FqName, Boolean>>>>("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<ModuleInfo, Ref<ConcurrentMap<FqName, Boolean>>>()
|
||||
.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<ModuleInfo, Ref<ConcurrentMap<FqName, Boolean>>>()
|
||||
.apply { module.putUserData(PerModulePackageCacheService.PER_MODULE_PACKAGE_CACHE, this) }
|
||||
}
|
||||
val cached = moduleOwnCache.getOrPut(moduleInfo) { cache.getOrPut(moduleInfo) { Ref() } }
|
||||
.apply { if (isNull) set(ContainerUtil.createConcurrentSoftMap<FqName, Boolean>()) }
|
||||
.get()
|
||||
val cached = moduleOwnCache.getOrPut(moduleInfo) { cache.getOrPut(moduleInfo) { Ref() } }
|
||||
.apply { if (isNull) set(ContainerUtil.createConcurrentSoftMap<FqName, Boolean>()) }
|
||||
.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<ConcurrentMap<ModuleInfo, Ref<ConcurrentMap<FqName, Boolean>>>>("per_module_package_cache")
|
||||
}
|
||||
}
|
||||
+2
-1
@@ -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<PerModulePackageCacheService>().packageExists(name, moduleInfo)
|
||||
else
|
||||
PackageIndexUtil.packageExists(name, indexedFilesScope, project)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user