Minor: refactor PerModulePackageCacheService

This commit is contained in:
Pavel V. Talanov
2017-05-11 21:04:29 +03:00
parent f750d08350
commit 77e611b2e7
2 changed files with 36 additions and 38 deletions
@@ -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")
}
}
@@ -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)
}