[LL API] use FirCacheFactory in LLFirProviderHelper
This commit is contained in:
-21
@@ -8,16 +8,11 @@ package org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder
|
|||||||
import com.intellij.concurrency.ConcurrentCollectionFactory
|
import com.intellij.concurrency.ConcurrentCollectionFactory
|
||||||
import org.jetbrains.kotlin.analysis.api.impl.barebone.annotations.ThreadSafe
|
import org.jetbrains.kotlin.analysis.api.impl.barebone.annotations.ThreadSafe
|
||||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.LLFirModuleResolveComponents
|
import org.jetbrains.kotlin.analysis.low.level.api.fir.LLFirModuleResolveComponents
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirClassLikeDeclaration
|
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
|
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirFile
|
import org.jetbrains.kotlin.fir.declarations.FirFile
|
||||||
import org.jetbrains.kotlin.fir.psi
|
import org.jetbrains.kotlin.fir.psi
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
|
|
||||||
import org.jetbrains.kotlin.name.CallableId
|
|
||||||
import org.jetbrains.kotlin.name.ClassId
|
|
||||||
import org.jetbrains.kotlin.psi.KtFile
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import java.util.concurrent.ConcurrentHashMap
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Caches mapping [KtFile] -> [FirFile] of module [KtModule]
|
* Caches mapping [KtFile] -> [FirFile] of module [KtModule]
|
||||||
@@ -26,18 +21,6 @@ import java.util.concurrent.ConcurrentHashMap
|
|||||||
internal abstract class ModuleFileCache {
|
internal abstract class ModuleFileCache {
|
||||||
abstract val moduleComponents: LLFirModuleResolveComponents
|
abstract val moduleComponents: LLFirModuleResolveComponents
|
||||||
|
|
||||||
/**
|
|
||||||
* Maps [ClassId] to corresponding classifiers
|
|
||||||
* If classifier with required [ClassId] is not found in given module then map contains [Optional.EMPTY]
|
|
||||||
*/
|
|
||||||
abstract val classifierByClassId: ConcurrentHashMap<ClassId, Optional<FirClassLikeDeclaration>>
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Maps [CallableId] to corresponding callable
|
|
||||||
* If callable with required [CallableId]] is not found in given module then map contains emptyList
|
|
||||||
*/
|
|
||||||
abstract val callableByCallableId: ConcurrentHashMap<CallableId, List<FirCallableSymbol<*>>>
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return [FirFile] by [file] if it was previously built or runs [createValue] otherwise
|
* @return [FirFile] by [file] if it was previously built or runs [createValue] otherwise
|
||||||
* The [createValue] is run under the lock so [createValue] is executed at most once for each [KtFile]
|
* The [createValue] is run under the lock so [createValue] is executed at most once for each [KtFile]
|
||||||
@@ -51,10 +34,6 @@ internal abstract class ModuleFileCache {
|
|||||||
|
|
||||||
internal class ModuleFileCacheImpl(override val moduleComponents: LLFirModuleResolveComponents) : ModuleFileCache() {
|
internal class ModuleFileCacheImpl(override val moduleComponents: LLFirModuleResolveComponents) : ModuleFileCache() {
|
||||||
private val ktFileToFirFile = ConcurrentCollectionFactory.createConcurrentIdentityMap<KtFile, FirFile>()
|
private val ktFileToFirFile = ConcurrentCollectionFactory.createConcurrentIdentityMap<KtFile, FirFile>()
|
||||||
|
|
||||||
override val classifierByClassId: ConcurrentHashMap<ClassId, Optional<FirClassLikeDeclaration>> = ConcurrentHashMap()
|
|
||||||
override val callableByCallableId: ConcurrentHashMap<CallableId, List<FirCallableSymbol<*>>> = ConcurrentHashMap()
|
|
||||||
|
|
||||||
override fun fileCached(file: KtFile, createValue: () -> FirFile): FirFile =
|
override fun fileCached(file: KtFile, createValue: () -> FirFile): FirFile =
|
||||||
ktFileToFirFile.computeIfAbsent(file) { createValue() }
|
ktFileToFirFile.computeIfAbsent(file) { createValue() }
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -34,7 +34,7 @@ internal class LLFirProvider(
|
|||||||
override val symbolProvider: FirSymbolProvider = SymbolProvider()
|
override val symbolProvider: FirSymbolProvider = SymbolProvider()
|
||||||
|
|
||||||
private val providerHelper = LLFirProviderHelper(
|
private val providerHelper = LLFirProviderHelper(
|
||||||
moduleComponents.cache,
|
session,
|
||||||
moduleComponents.firFileBuilder,
|
moduleComponents.firFileBuilder,
|
||||||
declarationProvider,
|
declarationProvider,
|
||||||
packageProvider,
|
packageProvider,
|
||||||
|
|||||||
+38
-39
@@ -6,71 +6,70 @@
|
|||||||
package org.jetbrains.kotlin.analysis.low.level.api.fir.providers
|
package org.jetbrains.kotlin.analysis.low.level.api.fir.providers
|
||||||
|
|
||||||
import com.google.common.collect.Sets
|
import com.google.common.collect.Sets
|
||||||
|
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.LLFirFileBuilder
|
||||||
|
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.FirElementFinder
|
||||||
import org.jetbrains.kotlin.analysis.providers.KotlinDeclarationProvider
|
import org.jetbrains.kotlin.analysis.providers.KotlinDeclarationProvider
|
||||||
import org.jetbrains.kotlin.analysis.providers.KotlinPackageProvider
|
import org.jetbrains.kotlin.analysis.providers.KotlinPackageProvider
|
||||||
|
import org.jetbrains.kotlin.fir.FirSession
|
||||||
|
import org.jetbrains.kotlin.fir.caches.createCache
|
||||||
|
import org.jetbrains.kotlin.fir.caches.firCachesFactory
|
||||||
|
import org.jetbrains.kotlin.fir.caches.getValue
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirCallableDeclaration
|
import org.jetbrains.kotlin.fir.declarations.FirCallableDeclaration
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirClassLikeDeclaration
|
import org.jetbrains.kotlin.fir.declarations.FirClassLikeDeclaration
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirFile
|
import org.jetbrains.kotlin.fir.declarations.FirFile
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
|
||||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.LLFirFileBuilder
|
|
||||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.ModuleFileCache
|
|
||||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.FirElementFinder
|
|
||||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.executeOrReturnDefaultValueOnPCE
|
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
|
||||||
import org.jetbrains.kotlin.name.CallableId
|
import org.jetbrains.kotlin.name.CallableId
|
||||||
import org.jetbrains.kotlin.name.ClassId
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.psi.KtFile
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
internal class LLFirProviderHelper(
|
internal class LLFirProviderHelper(
|
||||||
private val cache: ModuleFileCache,
|
firSession: FirSession,
|
||||||
private val firFileBuilder: LLFirFileBuilder,
|
private val firFileBuilder: LLFirFileBuilder,
|
||||||
private val declarationProvider: KotlinDeclarationProvider,
|
private val declarationProvider: KotlinDeclarationProvider,
|
||||||
private val packageProvider: KotlinPackageProvider,
|
private val packageProvider: KotlinPackageProvider,
|
||||||
) {
|
) {
|
||||||
fun getFirClassifierByFqName(classId: ClassId): FirClassLikeDeclaration? {
|
private val classifierByClassId = firSession.firCachesFactory.createCache<ClassId, FirClassLikeDeclaration?> { classId ->
|
||||||
if (classId.isLocal) return null
|
val ktClass = declarationProvider.getClassLikeDeclarationByClassId(classId)
|
||||||
return executeOrReturnDefaultValueOnPCE(null) {
|
?: return@createCache null
|
||||||
cache.classifierByClassId.computeIfAbsent(classId) {
|
if (ktClass.getClassId() == null) return@createCache null
|
||||||
val ktClass = declarationProvider.getClassLikeDeclarationByClassId(classId)
|
val firFile = firFileBuilder.buildRawFirFileWithCaching(ktClass.containingKtFile)
|
||||||
?: return@computeIfAbsent Optional.empty()
|
FirElementFinder.findElementIn<FirClassLikeDeclaration>(
|
||||||
if (ktClass.getClassId() == null) return@computeIfAbsent Optional.empty()
|
firFile,
|
||||||
val firFile = firFileBuilder.buildRawFirFileWithCaching(ktClass.containingKtFile)
|
canGoInside = { it is FirRegularClass },
|
||||||
val classifier = FirElementFinder.findElementIn<FirClassLikeDeclaration>(
|
predicate = { it.symbol.classId == classId },
|
||||||
firFile,
|
)
|
||||||
canGoInside = { it is FirRegularClass },
|
?: error("Classifier $classId was found in file ${ktClass.containingKtFile.virtualFilePath} but was not found in FirFile")
|
||||||
predicate = { it.symbol.classId == classId },
|
|
||||||
)
|
|
||||||
?: error("Classifier $classId was found in file ${ktClass.containingKtFile.virtualFilePath} but was not found in FirFile")
|
|
||||||
Optional.of(classifier)
|
|
||||||
}.getOrNull()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fun getTopLevelCallableSymbols(packageFqName: FqName, name: Name): List<FirCallableSymbol<*>> {
|
private val callablesByCallableId = firSession.firCachesFactory.createCache<CallableId, List<FirCallableSymbol<*>>> { callableId ->
|
||||||
val callableId = CallableId(packageFqName, name)
|
val files = Sets.newIdentityHashSet<KtFile>().apply {
|
||||||
return executeOrReturnDefaultValueOnPCE(emptyList()) {
|
declarationProvider.getTopLevelFunctions(callableId).mapTo(this) { it.containingKtFile }
|
||||||
cache.callableByCallableId.computeIfAbsent(callableId) {
|
declarationProvider.getTopLevelProperties(callableId).mapTo(this) { it.containingKtFile }
|
||||||
val files = Sets.newIdentityHashSet<KtFile>().apply {
|
}
|
||||||
declarationProvider.getTopLevelFunctions(callableId).mapTo(this) { it.containingKtFile }
|
buildList {
|
||||||
declarationProvider.getTopLevelProperties(callableId).mapTo(this) { it.containingKtFile }
|
files.forEach { ktFile ->
|
||||||
}
|
val firFile = firFileBuilder.buildRawFirFileWithCaching(ktFile)
|
||||||
@OptIn(ExperimentalStdlibApi::class)
|
firFile.collectCallableDeclarationsTo(this, callableId.callableName)
|
||||||
buildList {
|
|
||||||
files.forEach { ktFile ->
|
|
||||||
val firFile = firFileBuilder.buildRawFirFileWithCaching(ktFile)
|
|
||||||
firFile.collectCallableDeclarationsTo(this, name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getFirClassifierByFqName(classId: ClassId): FirClassLikeDeclaration? {
|
||||||
|
if (classId.isLocal) return null
|
||||||
|
return classifierByClassId.getValue(classId)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getTopLevelCallableSymbols(packageFqName: FqName, name: Name): List<FirCallableSymbol<*>> {
|
||||||
|
val callableId = CallableId(packageFqName, name)
|
||||||
|
return callablesByCallableId.getValue(callableId)
|
||||||
|
}
|
||||||
|
|
||||||
fun getTopLevelFunctionSymbols(packageFqName: FqName, name: Name): List<FirNamedFunctionSymbol> {
|
fun getTopLevelFunctionSymbols(packageFqName: FqName, name: Name): List<FirNamedFunctionSymbol> {
|
||||||
return getTopLevelCallableSymbols(packageFqName, name).filterIsInstance<FirNamedFunctionSymbol>()
|
return getTopLevelCallableSymbols(packageFqName, name).filterIsInstance<FirNamedFunctionSymbol>()
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user