[FIR] Add special inline class for caches which are used in symbol providers
This commit is contained in:
@@ -9,7 +9,6 @@ import com.intellij.openapi.progress.ProcessCanceledException
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.search.GlobalSearchScope
|
||||
import org.jetbrains.annotations.TestOnly
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||
@@ -21,8 +20,9 @@ import org.jetbrains.kotlin.fir.declarations.impl.FirResolvedDeclarationStatusIm
|
||||
import org.jetbrains.kotlin.fir.expressions.builder.*
|
||||
import org.jetbrains.kotlin.fir.java.declarations.*
|
||||
import org.jetbrains.kotlin.fir.resolve.constructType
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.AbstractFirSymbolProvider
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.AbstractFirSymbolProviderWithCache
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProviderInternals
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.SymbolProviderCache
|
||||
import org.jetbrains.kotlin.fir.resolve.scopes.wrapScopeWithJvmMapped
|
||||
import org.jetbrains.kotlin.fir.scopes.FirScope
|
||||
import org.jetbrains.kotlin.fir.scopes.impl.lazyNestedClassifierScope
|
||||
@@ -48,7 +48,7 @@ class JavaSymbolProvider(
|
||||
val session: FirSession,
|
||||
val project: Project,
|
||||
private val searchScope: GlobalSearchScope,
|
||||
) : AbstractFirSymbolProvider<FirRegularClassSymbol>() {
|
||||
) : AbstractFirSymbolProviderWithCache<FirRegularClassSymbol>() {
|
||||
companion object {
|
||||
private val VALUE_METHOD_NAME = Name.identifier("value")
|
||||
}
|
||||
@@ -56,7 +56,7 @@ class JavaSymbolProvider(
|
||||
private val scopeProvider = JavaScopeProvider(::wrapScopeWithJvmMapped, this)
|
||||
|
||||
private val facade: KotlinJavaPsiFacade get() = KotlinJavaPsiFacade.getInstance(project)
|
||||
private val parentClassTypeParameterStackCache: MutableMap<FirRegularClassSymbol, JavaTypeParameterStack> = mutableMapOf()
|
||||
private val parentClassTypeParameterStackCache: SymbolProviderCache<FirRegularClassSymbol, JavaTypeParameterStack> = SymbolProviderCache()
|
||||
|
||||
private fun findClass(
|
||||
classId: ClassId,
|
||||
|
||||
+12
-13
@@ -25,8 +25,9 @@ import org.jetbrains.kotlin.fir.references.builder.buildErrorNamedReference
|
||||
import org.jetbrains.kotlin.fir.references.builder.buildResolvedNamedReference
|
||||
import org.jetbrains.kotlin.fir.references.impl.FirReferencePlaceholderForResolvedAnnotations
|
||||
import org.jetbrains.kotlin.fir.resolve.firSymbolProvider
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.AbstractFirSymbolProvider
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.AbstractFirSymbolProviderWithCache
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProviderInternals
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.SymbolProviderCache
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.getClassDeclaredCallableSymbols
|
||||
import org.jetbrains.kotlin.fir.scopes.FirScope
|
||||
import org.jetbrains.kotlin.fir.scopes.KotlinScopeProvider
|
||||
@@ -37,7 +38,6 @@ import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef
|
||||
import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef
|
||||
import org.jetbrains.kotlin.fir.types.constructClassType
|
||||
import org.jetbrains.kotlin.load.java.JavaClassFinder
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaClass
|
||||
import org.jetbrains.kotlin.load.kotlin.*
|
||||
import org.jetbrains.kotlin.load.kotlin.KotlinJvmBinaryClass.AnnotationArrayArgumentVisitor
|
||||
import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader
|
||||
@@ -54,7 +54,6 @@ import org.jetbrains.kotlin.resolve.jvm.JvmClassName
|
||||
import org.jetbrains.kotlin.serialization.deserialization.IncompatibleVersionErrorData
|
||||
import org.jetbrains.kotlin.serialization.deserialization.getName
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult
|
||||
import org.jetbrains.kotlin.utils.getOrPutNullable
|
||||
|
||||
class KotlinDeserializedJvmSymbolsProvider(
|
||||
val session: FirSession,
|
||||
@@ -64,11 +63,11 @@ class KotlinDeserializedJvmSymbolsProvider(
|
||||
private val kotlinClassFinder: KotlinClassFinder,
|
||||
private val javaClassFinder: JavaClassFinder,
|
||||
private val kotlinScopeProvider: KotlinScopeProvider,
|
||||
) : AbstractFirSymbolProvider<FirClassLikeSymbol<*>>() {
|
||||
private val classesCache = HashMap<ClassId, FirRegularClassSymbol>()
|
||||
private val typeAliasCache = HashMap<ClassId, FirTypeAliasSymbol?>()
|
||||
private val packagePartsCache = HashMap<FqName, Collection<PackagePartsCacheData>>()
|
||||
) : AbstractFirSymbolProviderWithCache<FirRegularClassSymbol>() {
|
||||
private val typeAliasCache = SymbolProviderCache<ClassId, FirTypeAliasSymbol>()
|
||||
private val packagePartsCache = SymbolProviderCache<FqName, Collection<PackagePartsCacheData>>()
|
||||
|
||||
// TODO: implement thread safety for this property
|
||||
private val handledByJava = HashSet<ClassId>()
|
||||
|
||||
private class PackagePartsCacheData(
|
||||
@@ -154,7 +153,7 @@ class KotlinDeserializedJvmSymbolsProvider(
|
||||
classId: ClassId,
|
||||
): FirTypeAliasSymbol? {
|
||||
if (!classId.relativeClassName.isOneSegmentFQN()) return null
|
||||
return typeAliasCache.getOrPutNullable(classId) {
|
||||
return typeAliasCache.lookupCacheOrCalculate(classId) {
|
||||
getPackageParts(classId.packageFqName).firstNotNullResult { part ->
|
||||
val ids = part.typeAliasNameIndex[classId.shortClassName]
|
||||
if (ids == null || ids.isEmpty()) return@firstNotNullResult null
|
||||
@@ -307,7 +306,7 @@ class KotlinDeserializedJvmSymbolsProvider(
|
||||
parentContext: FirDeserializationContext? = null
|
||||
): FirRegularClassSymbol? {
|
||||
if (hasNoTopLevelClassOf(classId)) return null
|
||||
if (classesCache.containsKey(classId)) return classesCache[classId]
|
||||
if (classId in classCache) return classCache[classId]
|
||||
|
||||
if (classId in handledByJava) return null
|
||||
|
||||
@@ -346,7 +345,7 @@ class KotlinDeserializedJvmSymbolsProvider(
|
||||
this::findAndDeserializeClass
|
||||
)
|
||||
|
||||
classesCache[classId] = symbol
|
||||
classCache[classId] = symbol
|
||||
val annotations = mutableListOf<FirAnnotationCall>()
|
||||
kotlinJvmBinaryClass.loadClassAnnotations(
|
||||
object : KotlinJvmBinaryClass.AnnotationVisitor {
|
||||
@@ -364,7 +363,7 @@ class KotlinDeserializedJvmSymbolsProvider(
|
||||
(symbol.fir.annotations as MutableList<FirAnnotationCall>) += annotations
|
||||
}
|
||||
|
||||
return classesCache[classId]
|
||||
return classCache[classId]
|
||||
}
|
||||
|
||||
private fun loadFunctionsByName(part: PackagePartsCacheData, name: Name): List<FirCallableSymbol<*>> {
|
||||
@@ -399,13 +398,13 @@ class KotlinDeserializedJvmSymbolsProvider(
|
||||
}
|
||||
|
||||
private fun getPackageParts(packageFqName: FqName): Collection<PackagePartsCacheData> {
|
||||
return packagePartsCache.getOrPut(packageFqName) {
|
||||
return packagePartsCache.lookupCacheOrCalculate(packageFqName) {
|
||||
try {
|
||||
computePackagePartsInfos(packageFqName)
|
||||
} catch (e: ProcessCanceledException) {
|
||||
emptyList()
|
||||
}
|
||||
}
|
||||
}!!
|
||||
}
|
||||
|
||||
private fun findRegularClass(classId: ClassId): FirRegularClass? =
|
||||
|
||||
-41
@@ -1,41 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2020 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.fir.resolve.providers
|
||||
|
||||
import org.jetbrains.kotlin.fir.symbols.CallableId
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
|
||||
abstract class AbstractFirSymbolProvider<C : FirClassLikeSymbol<*>> : FirSymbolProvider() {
|
||||
protected val classCache = HashMap<ClassId, C?>()
|
||||
protected val topLevelCallableCache = HashMap<CallableId, List<FirCallableSymbol<*>>>()
|
||||
protected val packageCache = HashMap<FqName, FqName?>()
|
||||
|
||||
protected inline fun <K, V : Any?> MutableMap<K, V>.lookupCacheOrCalculate(key: K, crossinline l: (K) -> V): V? {
|
||||
return if (containsKey(key)) {
|
||||
this[key]
|
||||
} else {
|
||||
val calculated = l(key)
|
||||
this[key] = calculated
|
||||
calculated
|
||||
}
|
||||
}
|
||||
|
||||
protected inline fun <K, V : Any, T> MutableMap<K, V?>.lookupCacheOrCalculateWithPostCompute(
|
||||
key: K, crossinline l: (K) -> Pair<V?, T>, postCompute: (V, T) -> Unit
|
||||
): V? {
|
||||
return if (containsKey(key)) {
|
||||
this[key]
|
||||
} else {
|
||||
val calculated = l(key)
|
||||
this[key] = calculated.first
|
||||
calculated.first?.let { first -> postCompute(first, calculated.second) }
|
||||
calculated.first
|
||||
}
|
||||
}
|
||||
}
|
||||
+76
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright 2010-2020 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.fir.resolve.providers
|
||||
|
||||
import org.jetbrains.kotlin.fir.PrivateForInline
|
||||
import org.jetbrains.kotlin.fir.symbols.CallableId
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
|
||||
abstract class AbstractFirSymbolProviderWithCache<C : FirClassLikeSymbol<*>> : FirSymbolProvider() {
|
||||
protected val classCache = SymbolProviderCache<ClassId, C>()
|
||||
protected val topLevelCallableCache = SymbolProviderCache<CallableId, List<FirCallableSymbol<*>>>()
|
||||
protected val packageCache = SymbolProviderCache<FqName, FqName>()
|
||||
}
|
||||
|
||||
@Suppress("EXPERIMENTAL_FEATURE_WARNING")
|
||||
inline class SymbolProviderCache<K, V : Any> @PrivateForInline constructor(@PrivateForInline val cache: HashMap<K, Any>) {
|
||||
@OptIn(PrivateForInline::class)
|
||||
constructor() : this(HashMap())
|
||||
|
||||
@PrivateForInline
|
||||
object NullValue
|
||||
|
||||
@OptIn(PrivateForInline::class)
|
||||
inline fun lookupCacheOrCalculate(key: K, crossinline l: (K) -> V?): V? {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return when (val value = cache[key]) {
|
||||
null -> {
|
||||
val calculated = l(key)
|
||||
cache[key] = calculated ?: NullValue
|
||||
calculated
|
||||
}
|
||||
NullValue -> null
|
||||
else -> value as V
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(PrivateForInline::class)
|
||||
inline fun <T> lookupCacheOrCalculateWithPostCompute(
|
||||
key: K, crossinline l: (K) -> Pair<V?, T>, postCompute: (V, T) -> Unit
|
||||
): V? {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return when (val value = cache[key]) {
|
||||
null -> {
|
||||
val calculated = l(key)
|
||||
cache[key] = calculated.first ?: NullValue
|
||||
calculated.first?.let { postCompute(it, calculated.second) }
|
||||
calculated.first
|
||||
}
|
||||
NullValue -> null
|
||||
else -> value as V
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(PrivateForInline::class)
|
||||
operator fun contains(key: K): Boolean = key in cache
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
@OptIn(PrivateForInline::class)
|
||||
operator fun get(key: K): V? = cache[key].takeIf { it !== NullValue } as V?
|
||||
|
||||
@OptIn(PrivateForInline::class)
|
||||
operator fun set(key: K, value: V) {
|
||||
cache[key] = value
|
||||
}
|
||||
|
||||
@OptIn(PrivateForInline::class)
|
||||
fun remove(key: K) {
|
||||
cache.remove(key)
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -8,7 +8,7 @@ package org.jetbrains.kotlin.fir.resolve.providers.impl
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.dependenciesWithoutSelf
|
||||
import org.jetbrains.kotlin.fir.resolve.firSymbolProvider
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.AbstractFirSymbolProvider
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.AbstractFirSymbolProviderWithCache
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProviderInternals
|
||||
import org.jetbrains.kotlin.fir.scopes.FirScope
|
||||
import org.jetbrains.kotlin.fir.symbols.CallableId
|
||||
@@ -19,7 +19,7 @@ import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult
|
||||
|
||||
open class FirDependenciesSymbolProviderImpl(val session: FirSession) : AbstractFirSymbolProvider<FirClassLikeSymbol<*>>() {
|
||||
open class FirDependenciesSymbolProviderImpl(val session: FirSession) : AbstractFirSymbolProviderWithCache<FirClassLikeSymbol<*>>() {
|
||||
protected open val dependencyProviders by lazy {
|
||||
val moduleInfo = session.moduleInfo ?: return@lazy emptyList()
|
||||
moduleInfo.dependenciesWithoutSelf().mapNotNull {
|
||||
|
||||
Reference in New Issue
Block a user