[Analysis API FIR] fix invalid usages of CachedValue
it should not cache map as values are stored on soft references
This commit is contained in:
+75
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.analysis.utils.caches
|
||||
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.psi.util.CachedValue
|
||||
import com.intellij.psi.util.CachedValueProvider
|
||||
import com.intellij.psi.util.CachedValuesManager
|
||||
import com.intellij.util.containers.ContainerUtil
|
||||
import org.jetbrains.annotations.TestOnly
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
|
||||
public abstract class SoftCachedMap<K : Any, V : Any> {
|
||||
public abstract fun getOrPut(key: K, create: () -> V): V
|
||||
|
||||
@TestOnly
|
||||
public abstract fun clear()
|
||||
|
||||
public companion object {
|
||||
public fun <K : Any, V : Any> create(
|
||||
project: Project,
|
||||
kind: Kind,
|
||||
trackers: List<Any>
|
||||
): SoftCachedMap<K, V> = when {
|
||||
trackers.isEmpty() -> SoftCachedMapWithoutTrackers(kind)
|
||||
else -> SoftCachedMapWithTrackers(project, kind, trackers.toTypedArray())
|
||||
}
|
||||
}
|
||||
|
||||
public enum class Kind {
|
||||
SOFT_KEYS_SOFT_VALUES,
|
||||
STRONG_KEYS_SOFT_VALUES
|
||||
}
|
||||
}
|
||||
|
||||
private class SoftCachedMapWithTrackers<K : Any, V : Any>(
|
||||
private val project: Project,
|
||||
kind: Kind,
|
||||
private val trackers: Array<Any>
|
||||
) : SoftCachedMap<K, V>() {
|
||||
private val cache = when (kind) {
|
||||
Kind.SOFT_KEYS_SOFT_VALUES -> ContainerUtil.createConcurrentSoftMap<K, CachedValue<V>>()
|
||||
Kind.STRONG_KEYS_SOFT_VALUES -> ConcurrentHashMap<K, CachedValue<V>>()
|
||||
}
|
||||
|
||||
override fun clear() {
|
||||
cache.clear()
|
||||
}
|
||||
|
||||
override fun getOrPut(key: K, create: () -> V): V {
|
||||
return cache.getOrPut(key) {
|
||||
CachedValuesManager.getManager(project).createCachedValue {
|
||||
CachedValueProvider.Result(create(), *trackers)
|
||||
}
|
||||
}.value
|
||||
}
|
||||
}
|
||||
|
||||
private class SoftCachedMapWithoutTrackers<K : Any, V : Any>(kind: Kind) : SoftCachedMap<K, V>() {
|
||||
private val cache = when (kind) {
|
||||
Kind.SOFT_KEYS_SOFT_VALUES -> ContainerUtil.createConcurrentSoftKeySoftValueMap<K, V>()
|
||||
Kind.STRONG_KEYS_SOFT_VALUES -> ContainerUtil.createSoftValueMap<K, V>()
|
||||
}
|
||||
|
||||
override fun clear() {
|
||||
cache.clear()
|
||||
}
|
||||
|
||||
override fun getOrPut(key: K, create: () -> V): V {
|
||||
return cache.getOrPut(key, create)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user