Minor: refactor PerModulePackageCacheService
This commit is contained in:
+34
-37
@@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.idea.caches
|
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.project.Project
|
||||||
import com.intellij.openapi.util.Key
|
import com.intellij.openapi.util.Key
|
||||||
import com.intellij.openapi.util.Ref
|
import com.intellij.openapi.util.Ref
|
||||||
@@ -57,13 +57,13 @@ class KotlinPackageContentModificationListener(
|
|||||||
.filterNotNull()
|
.filterNotNull()
|
||||||
.filter { it in scope }
|
.filter { it in scope }
|
||||||
.forEach { file ->
|
.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) {
|
override fun treeChanged(event: PsiTreeChangeEventImpl) {
|
||||||
val file = event.file as? KtFile ?: return
|
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 -> {
|
PsiTreeChangeEventImpl.PsiEventType.CHILD_ADDED, PsiTreeChangeEventImpl.PsiEventType.CHILD_MOVED, PsiTreeChangeEventImpl.PsiEventType.CHILD_REPLACED, PsiTreeChangeEventImpl.PsiEventType.CHILD_REMOVED -> {
|
||||||
val child = event.child ?: return
|
val child = event.child ?: return
|
||||||
if (child.getParentOfType<KtPackageDirective>(false) != null)
|
if (child.getParentOfType<KtPackageDirective>(false) != null)
|
||||||
PerModulePackageCacheService.notifyPackageChange(file)
|
project.service<PerModulePackageCacheService>().notifyPackageChange(file)
|
||||||
}
|
}
|
||||||
else -> {
|
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 {
|
internal fun onChangeInModuleSource(moduleSourceInfo: ModuleSourceInfo) {
|
||||||
(file.getNullableModuleInfo() as? ModuleSourceInfo)?.let { onChangeInModuleSource(it, file.project) }
|
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) }
|
||||||
}
|
}
|
||||||
|
val cached = moduleOwnCache.getOrPut(moduleInfo) { cache.getOrPut(moduleInfo) { Ref() } }
|
||||||
internal fun onChangeInModuleSource(moduleSourceInfo: ModuleSourceInfo, project: Project) = with(getInstance(project)) {
|
.apply { if (isNull) set(ContainerUtil.createConcurrentSoftMap<FqName, Boolean>()) }
|
||||||
cache[moduleSourceInfo]?.set(null)
|
.get()
|
||||||
}
|
|
||||||
|
|
||||||
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()
|
|
||||||
|
|
||||||
|
|
||||||
return cached.getOrPut(packageFqName) {
|
return cached.getOrPut(packageFqName) {
|
||||||
PackageIndexUtil.packageExists(packageFqName, moduleInfo.contentScope(), project)
|
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
|
package org.jetbrains.kotlin.idea.stubindex.resolve
|
||||||
|
|
||||||
|
import com.intellij.openapi.components.service
|
||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
import com.intellij.psi.search.GlobalSearchScope
|
import com.intellij.psi.search.GlobalSearchScope
|
||||||
import org.jetbrains.kotlin.analyzer.ModuleInfo
|
import org.jetbrains.kotlin.analyzer.ModuleInfo
|
||||||
@@ -55,7 +56,7 @@ class PluginDeclarationProviderFactory(
|
|||||||
|
|
||||||
private fun packageExists(name: FqName): Boolean {
|
private fun packageExists(name: FqName): Boolean {
|
||||||
return if (moduleInfo is ModuleSourceInfo)
|
return if (moduleInfo is ModuleSourceInfo)
|
||||||
PerModulePackageCacheService.packageExists(name, moduleInfo, project)
|
project.service<PerModulePackageCacheService>().packageExists(name, moduleInfo)
|
||||||
else
|
else
|
||||||
PackageIndexUtil.packageExists(name, indexedFilesScope, project)
|
PackageIndexUtil.packageExists(name, indexedFilesScope, project)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user