[low level api] rework components structure, add ScopeSession caches

This commit is contained in:
Ilya Kirillov
2022-04-16 00:05:54 +02:00
parent 079400796a
commit 9a18598606
51 changed files with 542 additions and 435 deletions
@@ -18,6 +18,7 @@ import org.jetbrains.kotlin.analysis.low.level.api.fir.api.LLFirModuleResolveSta
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.LowLevelFirApiFacadeForResolveOnAir import org.jetbrains.kotlin.analysis.low.level.api.fir.api.LowLevelFirApiFacadeForResolveOnAir
import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.moduleData import org.jetbrains.kotlin.fir.moduleData
import org.jetbrains.kotlin.fir.resolve.ScopeSession
import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider
import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider
import org.jetbrains.kotlin.platform.TargetPlatform import org.jetbrains.kotlin.platform.TargetPlatform
@@ -116,6 +117,8 @@ private constructor(
val firSymbolProvider: FirSymbolProvider get() = rootModuleSession.symbolProvider val firSymbolProvider: FirSymbolProvider get() = rootModuleSession.symbolProvider
val targetPlatform: TargetPlatform get() = rootModuleSession.moduleData.platform val targetPlatform: TargetPlatform get() = rootModuleSession.moduleData.platform
fun getScopeSessionFor(session: FirSession): ScopeSession = firResolveState.getScopeSessionFor(session)
companion object { companion object {
@InvalidWayOfUsingAnalysisSession @InvalidWayOfUsingAnalysisSession
internal fun createAnalysisSessionByResolveState( internal fun createAnalysisSessionByResolveState(
@@ -929,7 +929,11 @@ internal class KtFirCallResolver(
} }
private fun FirClassSymbol<*>.getEqualsSymbol(equalsSymbolInAny: FirNamedFunctionSymbol): FirNamedFunctionSymbol { private fun FirClassSymbol<*>.getEqualsSymbol(equalsSymbolInAny: FirNamedFunctionSymbol): FirNamedFunctionSymbol {
val scope = unsubstitutedScope(analysisSession.rootModuleSession, ScopeSession(), false) val scope = unsubstitutedScope(
analysisSession.rootModuleSession,
analysisSession.getScopeSessionFor(analysisSession.rootModuleSession),
false
)
var equalsSymbol: FirNamedFunctionSymbol? = null var equalsSymbol: FirNamedFunctionSymbol? = null
scope.processFunctionsByName(EQUALS) { equalsSymbolFromScope -> scope.processFunctionsByName(EQUALS) { equalsSymbolFromScope ->
if (equalsSymbol != null) return@processFunctionsByName if (equalsSymbol != null) return@processFunctionsByName
@@ -66,7 +66,7 @@ internal class KtFirReferenceShortener(
override val token: ValidityToken, override val token: ValidityToken,
override val firResolveState: LLFirModuleResolveState, override val firResolveState: LLFirModuleResolveState,
) : KtReferenceShortener(), KtFirAnalysisSessionComponent { ) : KtReferenceShortener(), KtFirAnalysisSessionComponent {
private val context = FirShorteningContext(firResolveState) private val context = FirShorteningContext(analysisSession)
override fun collectShortenings( override fun collectShortenings(
file: KtFile, file: KtFile,
@@ -163,7 +163,8 @@ private data class AvailableSymbol<out T>(
val importKind: ImportKind, val importKind: ImportKind,
) )
private class FirShorteningContext(val firResolveState: LLFirModuleResolveState) { private class FirShorteningContext(val analysisSession: KtFirAnalysisSession) {
private val firResolveState = analysisSession.firResolveState
private val firSession: FirSession private val firSession: FirSession
get() = firResolveState.rootModuleSession get() = firResolveState.rootModuleSession
@@ -229,7 +230,11 @@ private class FirShorteningContext(val firResolveState: LLFirModuleResolveState)
val resolvedNewImports = newImports.mapNotNull { createFakeResolvedImport(it) } val resolvedNewImports = newImports.mapNotNull { createFakeResolvedImport(it) }
if (resolvedNewImports.isEmpty()) return null if (resolvedNewImports.isEmpty()) return null
return FirExplicitSimpleImportingScope(resolvedNewImports, firSession, ScopeSession()) return FirExplicitSimpleImportingScope(
resolvedNewImports,
firSession,
analysisSession.getScopeSessionFor(firSession),
)
} }
private fun createFakeResolvedImport(fqNameToImport: FqName): FirResolvedImport? { private fun createFakeResolvedImport(fqNameToImport: FqName): FirResolvedImport? {
@@ -28,16 +28,18 @@ internal class KtFirSamResolver(
override fun getSamConstructor(ktClassLikeSymbol: KtClassLikeSymbol): KtSamConstructorSymbol? { override fun getSamConstructor(ktClassLikeSymbol: KtClassLikeSymbol): KtSamConstructorSymbol? {
val classId = ktClassLikeSymbol.classIdIfNonLocal ?: return null val classId = ktClassLikeSymbol.classIdIfNonLocal ?: return null
val owner = analysisSession.getClassLikeSymbol(classId) as? FirRegularClass ?: return null val owner = analysisSession.getClassLikeSymbol(classId) as? FirRegularClass ?: return null
val resolver = LocalSamResolver(analysisSession.rootModuleSession) val resolver = LocalSamResolver(analysisSession, analysisSession.rootModuleSession)
return resolver.getSamConstructor(owner)?.let { return resolver.getSamConstructor(owner)?.let {
analysisSession.firSymbolBuilder.functionLikeBuilder.buildSamConstructorSymbol(it.symbol) analysisSession.firSymbolBuilder.functionLikeBuilder.buildSamConstructorSymbol(it.symbol)
} }
} }
private class LocalSamResolver( private class LocalSamResolver(
analysisSession: KtFirAnalysisSession,
private val firSession: FirSession, private val firSession: FirSession,
) { ) {
private val scopeSession = ScopeSession() private val scopeSession = analysisSession.getScopeSessionFor(firSession)
// TODO: This transformer is not intended for actual transformations and // TODO: This transformer is not intended for actual transformations and
// created here only to simplify access to SAM resolver in body resolve components // created here only to simplify access to SAM resolver in body resolve components
@@ -36,7 +36,6 @@ import org.jetbrains.kotlin.fir.declarations.FirClass
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
import org.jetbrains.kotlin.fir.declarations.utils.delegateFields import org.jetbrains.kotlin.fir.declarations.utils.delegateFields
import org.jetbrains.kotlin.fir.expressions.FirAnonymousObjectExpression import org.jetbrains.kotlin.fir.expressions.FirAnonymousObjectExpression
import org.jetbrains.kotlin.fir.resolve.ScopeSession
import org.jetbrains.kotlin.fir.resolve.calls.FirSyntheticPropertiesScope import org.jetbrains.kotlin.fir.resolve.calls.FirSyntheticPropertiesScope
import org.jetbrains.kotlin.fir.resolve.scope import org.jetbrains.kotlin.fir.resolve.scope
import org.jetbrains.kotlin.fir.scopes.* import org.jetbrains.kotlin.fir.scopes.*
@@ -53,6 +52,10 @@ internal class KtFirScopeProvider(
firResolveState: LLFirModuleResolveState, firResolveState: LLFirModuleResolveState,
override val token: ValidityToken, override val token: ValidityToken,
) : KtScopeProvider(), ValidityTokenOwner { ) : KtScopeProvider(), ValidityTokenOwner {
// KtFirScopeProvider is thread local, so it's okay to use the same session here
private val scopeSession = analysisSession.getScopeSessionFor(analysisSession.rootModuleSession)
override val analysisSession: KtFirAnalysisSession by weakRef(analysisSession) override val analysisSession: KtFirAnalysisSession by weakRef(analysisSession)
private val builder by weakRef(builder) private val builder by weakRef(builder)
private val firResolveState by weakRef(firResolveState) private val firResolveState by weakRef(firResolveState)
@@ -89,7 +92,7 @@ internal class KtFirScopeProvider(
val firSession = analysisSession.rootModuleSession val firSession = analysisSession.rootModuleSession
fir.unsubstitutedScope( fir.unsubstitutedScope(
firSession, firSession,
ScopeSession(), scopeSession,
withForcedTypeCalculator = false withForcedTypeCalculator = false
) )
} ?: return@getOrPut getEmptyScope() } ?: return@getOrPut getEmptyScope()
@@ -100,7 +103,12 @@ internal class KtFirScopeProvider(
override fun getStaticMemberScope(symbol: KtSymbolWithMembers): KtScope { override fun getStaticMemberScope(symbol: KtSymbolWithMembers): KtScope {
val firScope = symbol.withFirForScope { fir -> val firScope = symbol.withFirForScope { fir ->
fir.scopeProvider.getStaticScope(fir, analysisSession.rootModuleSession, ScopeSession()) val firSession = analysisSession.rootModuleSession
fir.scopeProvider.getStaticScope(
fir,
firSession,
scopeSession,
)
} ?: return getEmptyScope() } ?: return getEmptyScope()
return KtFirDelegatingScope(firScope, builder, token) return KtFirDelegatingScope(firScope, builder, token)
} }
@@ -122,9 +130,10 @@ internal class KtFirScopeProvider(
val firScope = classSymbol.withFirForScope { fir -> val firScope = classSymbol.withFirForScope { fir ->
val delegateFields = fir.delegateFields val delegateFields = fir.delegateFields
if (delegateFields.isNotEmpty()) { if (delegateFields.isNotEmpty()) {
val firSession = analysisSession.rootModuleSession
FirDelegatedMemberScope( FirDelegatedMemberScope(
analysisSession.rootModuleSession, firSession,
ScopeSession(), scopeSession,
fir, fir,
declaredScope, declaredScope,
delegateFields delegateFields
@@ -170,7 +179,7 @@ internal class KtFirScopeProvider(
val firSession = firResolveState.rootModuleSession val firSession = firResolveState.rootModuleSession
val firTypeScope = type.coneType.scope( val firTypeScope = type.coneType.scope(
firSession, firSession,
ScopeSession(), scopeSession,
FakeOverrideTypeCalculator.Forced FakeOverrideTypeCalculator.Forced
) ?: return null ) ?: return null
return getCompositeScope( return getCompositeScope(
@@ -117,9 +117,10 @@ internal class KtFirSymbolDeclarationOverridesProvider(
val firContainer = containingDeclaration.firSymbol.fir val firContainer = containingDeclaration.firSymbol.fir
val firCallableDeclaration = callableSymbol.firSymbol.fir val firCallableDeclaration = callableSymbol.firSymbol.fir
val firSession = firContainer.moduleData.session
val firTypeScope = firContainer.unsubstitutedScope( val firTypeScope = firContainer.unsubstitutedScope(
firContainer.moduleData.session, firSession,
ScopeSession(), analysisSession.getScopeSessionFor(firSession),
withForcedTypeCalculator = false withForcedTypeCalculator = false
) )
firTypeScope.processCallableByName(firCallableDeclaration) firTypeScope.processCallableByName(firCallableDeclaration)
@@ -25,7 +25,11 @@ internal class KtFirTypeInfoProvider(
override fun isFunctionalInterfaceType(type: KtType): Boolean { override fun isFunctionalInterfaceType(type: KtType): Boolean {
val coneType = (type as KtFirType).coneType val coneType = (type as KtFirType).coneType
val samResolver = FirSamResolverImpl(analysisSession.rootModuleSession, ScopeSession()) val firSession = analysisSession.rootModuleSession
val samResolver = FirSamResolverImpl(
firSession,
analysisSession.getScopeSessionFor(firSession),
)
return samResolver.getFunctionTypeForPossibleSamType(coneType) != null return samResolver.getFunctionTypeForPossibleSamType(coneType) != null
} }
@@ -54,7 +54,10 @@ internal class KtFirOverrideInfoProvider(
val parentClassFir = parentClassSymbol.firSymbol.fir as? FirClass ?: return null val parentClassFir = parentClassSymbol.firSymbol.fir as? FirClass ?: return null
return memberFir.symbol.getImplementationStatus( return memberFir.symbol.getImplementationStatus(
SessionHolderImpl(rootModuleSession, ScopeSession()), SessionHolderImpl(
rootModuleSession,
analysisSession.getScopeSessionFor(analysisSession.rootModuleSession),
),
parentClassFir.symbol parentClassFir.symbol
) )
} }
@@ -24,9 +24,10 @@ internal abstract class KtFirMemberSymbolPointer<S : KtSymbol>(
require(analysisSession is KtFirAnalysisSession) require(analysisSession is KtFirAnalysisSession)
val owner = analysisSession.getClassLikeSymbol(ownerClassId) as? FirRegularClass val owner = analysisSession.getClassLikeSymbol(ownerClassId) as? FirRegularClass
?: return null ?: return null
val firSession = analysisSession.rootModuleSession
val scope = owner.unsubstitutedScope( val scope = owner.unsubstitutedScope(
analysisSession.firResolveState.rootModuleSession, firSession,
ScopeSession(), analysisSession.getScopeSessionFor(firSession),
withForcedTypeCalculator = false withForcedTypeCalculator = false
) )
return analysisSession.chooseCandidateAndCreateSymbol(scope, owner.moduleData.session) return analysisSession.chooseCandidateAndCreateSymbol(scope, owner.moduleData.session)
@@ -6,6 +6,8 @@
package org.jetbrains.kotlin.analysis.low.level.api.fir package org.jetbrains.kotlin.analysis.low.level.api.fir
import com.intellij.openapi.project.Project import com.intellij.openapi.project.Project
import com.intellij.openapi.roots.ProjectRootModificationTracker
import com.intellij.psi.util.PsiModificationTracker
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.DiagnosticCheckerFilter import org.jetbrains.kotlin.analysis.low.level.api.fir.api.DiagnosticCheckerFilter
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.LLFirModuleResolveState import org.jetbrains.kotlin.analysis.low.level.api.fir.api.LLFirModuleResolveState
import org.jetbrains.kotlin.analysis.low.level.api.fir.element.builder.FirElementBuilder import org.jetbrains.kotlin.analysis.low.level.api.fir.element.builder.FirElementBuilder
@@ -14,19 +16,23 @@ import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.ModuleFileCa
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.structure.KtToFirMapping import org.jetbrains.kotlin.analysis.low.level.api.fir.file.structure.KtToFirMapping
import org.jetbrains.kotlin.analysis.low.level.api.fir.state.LLFirResolvableModuleResolveState import org.jetbrains.kotlin.analysis.low.level.api.fir.state.LLFirResolvableModuleResolveState
import org.jetbrains.kotlin.analysis.low.level.api.fir.state.TowerProviderForElementForState import org.jetbrains.kotlin.analysis.low.level.api.fir.state.TowerProviderForElementForState
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.LLFirScopeSessionProvider
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.containingKtFileIfAny import org.jetbrains.kotlin.analysis.low.level.api.fir.util.containingKtFileIfAny
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.originalKtFile import org.jetbrains.kotlin.analysis.low.level.api.fir.util.originalKtFile
import org.jetbrains.kotlin.analysis.project.structure.KtModule import org.jetbrains.kotlin.analysis.project.structure.KtModule
import org.jetbrains.kotlin.analysis.utils.caches.*
import org.jetbrains.kotlin.diagnostics.KtPsiDiagnostic import org.jetbrains.kotlin.diagnostics.KtPsiDiagnostic
import org.jetbrains.kotlin.fir.FirElement import org.jetbrains.kotlin.fir.FirElement
import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.FirSession
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.declarations.FirResolvePhase import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
import org.jetbrains.kotlin.fir.resolve.ScopeSession
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
import org.jetbrains.kotlin.psi.KtDeclaration import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.psi.KtElement import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.psi.KtFile
import java.util.concurrent.ConcurrentHashMap
internal class FirModuleResolveStateDepended( internal class FirModuleResolveStateDepended(
val originalState: LLFirResolvableModuleResolveState, val originalState: LLFirResolvableModuleResolveState,
@@ -37,6 +43,20 @@ internal class FirModuleResolveStateDepended(
override val module: KtModule get() = originalState.module override val module: KtModule get() = originalState.module
override val rootModuleSession get() = originalState.rootModuleSession override val rootModuleSession get() = originalState.rootModuleSession
private val scopeSessionProviderCache by softCachedValue(
project,
PsiModificationTracker.MODIFICATION_COUNT,
ProjectRootModificationTracker.getInstance(project),
) {
ConcurrentHashMap<FirSession, LLFirScopeSessionProvider>()
}
override fun getScopeSessionFor(firSession: FirSession): ScopeSession {
return scopeSessionProviderCache
.getOrPut(firSession) { LLFirScopeSessionProvider.create(project, invalidationTrackers = emptyList()) }
.getScopeSession()
}
override fun getSessionFor(module: KtModule): FirSession = override fun getSessionFor(module: KtModule): FirSession =
originalState.getSessionFor(module) originalState.getSessionFor(module)
@@ -0,0 +1,20 @@
/*
* 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.low.level.api.fir
import com.intellij.openapi.project.Project
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.LockProvider
import org.jetbrains.kotlin.analysis.project.structure.KtModule
import org.jetbrains.kotlin.fir.declarations.FirFile
@Suppress("unused")
internal class LLFirGlobalResolveComponents(
val useSiteKtModule: KtModule,
val project: Project,
) {
val phaseRunner: LLFirPhaseRunner = LLFirPhaseRunner()
val lockProvider: LockProvider<FirFile> = LockProvider()
}
@@ -0,0 +1,45 @@
/*
* 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.low.level.api.fir
import com.intellij.openapi.roots.ProjectRootModificationTracker
import com.intellij.psi.util.PsiModificationTracker
import org.jetbrains.kotlin.analysis.low.level.api.fir.diagnostics.DiagnosticsCollector
import org.jetbrains.kotlin.analysis.low.level.api.fir.element.builder.FirElementBuilder
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.FirFileBuilder
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.ModuleFileCache
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.ModuleFileCacheImpl
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.structure.FileStructureCache
import org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve.FirLazyDeclarationResolver
import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.LLFirResolvableModuleSession
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.LLFirScopeSessionProvider
import org.jetbrains.kotlin.analysis.project.structure.KtModule
import org.jetbrains.kotlin.fir.scopes.FirScopeProvider
@Suppress("CanBeParameter")
internal class LLFirModuleResolveComponents(
val module: KtModule,
val globalResolveComponents: LLFirGlobalResolveComponents,
val scopeProvider: FirScopeProvider,
) {
val cache: ModuleFileCache = ModuleFileCacheImpl(this)
val firFileBuilder: FirFileBuilder = FirFileBuilder(this)
val lazyFirDeclarationsResolver = FirLazyDeclarationResolver(this)
val scopeSessionProvider: LLFirScopeSessionProvider = LLFirScopeSessionProvider.create(
globalResolveComponents.project,
invalidationTrackers = listOf(
PsiModificationTracker.MODIFICATION_COUNT,
ProjectRootModificationTracker.getInstance(globalResolveComponents.project),
)
)
val fileStructureCache: FileStructureCache = FileStructureCache(this)
val elementsBuilder = FirElementBuilder(this)
val diagnosticsCollector = DiagnosticsCollector(fileStructureCache)
lateinit var session: LLFirResolvableModuleSession
}
@@ -7,34 +7,27 @@ package org.jetbrains.kotlin.analysis.low.level.api.fir
import org.jetbrains.kotlin.fir.ThreadSafeMutableState import org.jetbrains.kotlin.fir.ThreadSafeMutableState
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
import org.jetbrains.kotlin.fir.resolve.ScopeSession
import org.jetbrains.kotlin.fir.symbols.FirPhaseManager import org.jetbrains.kotlin.fir.symbols.FirPhaseManager
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.ModuleFileCache import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.LLFirResolvableModuleSession
import org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve.FirLazyDeclarationResolver
import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.LLFirSessionInvalidator import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.LLFirSessionInvalidator
@ThreadSafeMutableState @ThreadSafeMutableState
internal class LLFirPhaseManager( internal class LLFirPhaseManager(private val sessionInvalidator: LLFirSessionInvalidator) : FirPhaseManager() {
private val lazyDeclarationResolver: FirLazyDeclarationResolver, override fun ensureResolved(symbol: FirBasedSymbol<*>, requiredPhase: FirResolvePhase) {
private val cache: ModuleFileCache,
private val sessionInvalidator: LLFirSessionInvalidator,
) : FirPhaseManager() {
override fun ensureResolved(
symbol: FirBasedSymbol<*>,
requiredPhase: FirResolvePhase
) {
val fir = symbol.fir val fir = symbol.fir
val session = fir.moduleData.session
if (session !is LLFirResolvableModuleSession) return
val moduleComponents = session.moduleComponents
try { try {
lazyDeclarationResolver.lazyResolveDeclaration( moduleComponents.lazyFirDeclarationsResolver.lazyResolveDeclaration(
firDeclarationToResolve = fir, firDeclarationToResolve = fir,
moduleFileCache = cache, scopeSession = moduleComponents.scopeSessionProvider.getScopeSession(),
scopeSession = ScopeSession(),
toPhase = requiredPhase, toPhase = requiredPhase,
checkPCE = true, checkPCE = true,
) )
} catch (e: Throwable) { } catch (e: Throwable) {
sessionInvalidator.invalidate(fir.moduleData.session) sessionInvalidator.invalidate(session)
throw e throw e
} }
} }
@@ -11,10 +11,9 @@ import com.intellij.openapi.roots.ProjectRootModificationTracker
import org.jetbrains.annotations.TestOnly import org.jetbrains.annotations.TestOnly
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.LLFirModuleResolveState import org.jetbrains.kotlin.analysis.low.level.api.fir.api.LLFirModuleResolveState
import org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve.FirLazyDeclarationResolver import org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve.FirLazyDeclarationResolver
import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.LLFirSession import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.*
import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.LLFirSessionProviderStorage
import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.LLFirSourcesSession
import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.LLFirLibraryOrLibrarySourceResolvableModuleSession import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.LLFirLibraryOrLibrarySourceResolvableModuleSession
import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.LLFirSessionProviderStorage
import org.jetbrains.kotlin.analysis.low.level.api.fir.state.LLFirSourceModuleResolveState import org.jetbrains.kotlin.analysis.low.level.api.fir.state.LLFirSourceModuleResolveState
import org.jetbrains.kotlin.analysis.low.level.api.fir.state.LLFirLibraryOrLibrarySourceResolvableModuleResolveState import org.jetbrains.kotlin.analysis.low.level.api.fir.state.LLFirLibraryOrLibrarySourceResolvableModuleResolveState
import org.jetbrains.kotlin.analysis.low.level.api.fir.state.LLFirResolvableModuleResolveState import org.jetbrains.kotlin.analysis.low.level.api.fir.state.LLFirResolvableModuleResolveState
@@ -49,25 +48,22 @@ internal class LLFirResolveStateService(project: Project) {
configureSession: (LLFirSession.() -> Unit)? = null, configureSession: (LLFirSession.() -> Unit)? = null,
): LLFirResolvableModuleResolveState { ): LLFirResolvableModuleResolveState {
val sessionProvider = sessionProviderStorage.getSessionProvider(module, configureSession) val sessionProvider = sessionProviderStorage.getSessionProvider(module, configureSession)
val useSiteSession = sessionProvider.rootModuleSession
return when (module) { return when (module) {
is KtSourceModule -> { is KtSourceModule -> {
val firFileBuilder = (sessionProvider.rootModuleSession as LLFirSourcesSession).firFileBuilder
LLFirSourceModuleResolveState( LLFirSourceModuleResolveState(
useSiteSession.moduleComponents.globalResolveComponents,
sessionProviderStorage.project, sessionProviderStorage.project,
module, module,
sessionProvider, sessionProvider,
firFileBuilder,
FirLazyDeclarationResolver(firFileBuilder),
) )
} }
is KtLibraryModule, is KtLibrarySourceModule -> { is KtLibraryModule, is KtLibrarySourceModule -> {
val firFileBuilder = (sessionProvider.rootModuleSession as LLFirLibraryOrLibrarySourceResolvableModuleSession).firFileBuilder
LLFirLibraryOrLibrarySourceResolvableModuleResolveState( LLFirLibraryOrLibrarySourceResolvableModuleResolveState(
useSiteSession.moduleComponents.globalResolveComponents,
sessionProviderStorage.project, sessionProviderStorage.project,
module, module,
sessionProvider, sessionProvider,
firFileBuilder,
FirLazyDeclarationResolver(firFileBuilder),
) )
} }
else -> { else -> {
@@ -6,8 +6,10 @@
package org.jetbrains.kotlin.analysis.low.level.api.fir.api package org.jetbrains.kotlin.analysis.low.level.api.fir.api
import com.intellij.openapi.project.Project import com.intellij.openapi.project.Project
import org.jetbrains.kotlin.analysis.low.level.api.fir.LLFirGlobalResolveComponents
import org.jetbrains.kotlin.analysis.low.level.api.fir.element.builder.FirTowerContextProvider import org.jetbrains.kotlin.analysis.low.level.api.fir.element.builder.FirTowerContextProvider
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.ModuleFileCache import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.ModuleFileCache
import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.LLFirResolvableModuleSession
import org.jetbrains.kotlin.analysis.project.structure.KtLibraryModule import org.jetbrains.kotlin.analysis.project.structure.KtLibraryModule
import org.jetbrains.kotlin.analysis.project.structure.KtModule import org.jetbrains.kotlin.analysis.project.structure.KtModule
import org.jetbrains.kotlin.analysis.project.structure.KtSourceModule import org.jetbrains.kotlin.analysis.project.structure.KtSourceModule
@@ -18,6 +20,7 @@ import org.jetbrains.kotlin.fir.FirSession
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.declarations.FirResolvePhase import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
import org.jetbrains.kotlin.fir.resolve.ScopeSession
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
import org.jetbrains.kotlin.psi.KtDeclaration import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.psi.KtElement import org.jetbrains.kotlin.psi.KtElement
@@ -33,6 +36,9 @@ abstract class LLFirModuleResolveState {
internal abstract fun getSessionFor(module: KtModule): FirSession internal abstract fun getSessionFor(module: KtModule): FirSession
abstract fun getScopeSessionFor(firSession: FirSession): ScopeSession
/** /**
* Build fully resolved FIR node for requested element. * Build fully resolved FIR node for requested element.
* This operation could be performance affective because it create FIleStructureElement and resolve non-local declaration into BODY phase, use * This operation could be performance affective because it create FIleStructureElement and resolve non-local declaration into BODY phase, use
@@ -18,6 +18,7 @@ import org.jetbrains.kotlin.analysis.low.level.api.fir.file.structure.FirElement
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.structure.KtToFirMapping import org.jetbrains.kotlin.analysis.low.level.api.fir.file.structure.KtToFirMapping
import org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve.* import org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve.*
import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.LLFirResolvableModuleSession import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.LLFirResolvableModuleSession
import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.llFirResolvableSession
import org.jetbrains.kotlin.analysis.low.level.api.fir.state.LLFirResolvableModuleResolveState import org.jetbrains.kotlin.analysis.low.level.api.fir.state.LLFirResolvableModuleResolveState
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.getElementTextInContext import org.jetbrains.kotlin.analysis.low.level.api.fir.util.getElementTextInContext
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.originalDeclaration import org.jetbrains.kotlin.analysis.low.level.api.fir.util.originalDeclaration
@@ -121,20 +122,18 @@ object LowLevelFirApiFacadeForResolveOnAir {
): FirTowerDataContext { ): FirTowerDataContext {
require(file.isPhysical) require(file.isPhysical)
val session = state.getSessionFor(file.getKtModule(state.project)) as LLFirResolvableModuleSession val session = state.getSessionFor(file.getKtModule(state.project)) as LLFirResolvableModuleSession
val moduleComponents = session.moduleComponents
val firFile = session.firFileBuilder.buildRawFirFileWithCaching( val firFile = moduleComponents.firFileBuilder.buildRawFirFileWithCaching(file)
ktFile = file,
cache = session.cache,
)
state.firLazyDeclarationResolver.lazyResolveFileDeclaration( val scopeSession = state.getScopeSessionFor(session)
moduleComponents.lazyFirDeclarationsResolver.lazyResolveFileDeclaration(
firFile = firFile, firFile = firFile,
moduleFileCache = session.cache, scopeSession = scopeSession,
scopeSession = ScopeSession(),
toPhase = FirResolvePhase.IMPORTS toPhase = FirResolvePhase.IMPORTS
) )
val importingScopes = createImportingScopes(firFile, firFile.moduleData.session, ScopeSession(), useCaching = false) val importingScopes = createImportingScopes(firFile, firFile.moduleData.session, scopeSession, useCaching = false)
val fileScopeElements = importingScopes.map { it.asTowerDataElement(isLocal = false) } val fileScopeElements = importingScopes.map { it.asTowerDataElement(isLocal = false) }
return FirTowerDataContext().addNonLocalTowerDataElements(fileScopeElements) return FirTowerDataContext().addNonLocalTowerDataElements(fileScopeElements)
} }
@@ -178,7 +177,6 @@ object LowLevelFirApiFacadeForResolveOnAir {
private fun tryResolveAsFileAnnotation( private fun tryResolveAsFileAnnotation(
annotationEntry: KtAnnotationEntry, annotationEntry: KtAnnotationEntry,
state: LLFirResolvableModuleResolveState,
replacement: RawFirReplacement, replacement: RawFirReplacement,
firFile: FirFile, firFile: FirFile,
collector: FirTowerDataContextCollector? = null, collector: FirTowerDataContextCollector? = null,
@@ -189,10 +187,12 @@ object LowLevelFirApiFacadeForResolveOnAir {
fileAnnotation = annotationEntry, fileAnnotation = annotationEntry,
replacement = replacement replacement = replacement
) )
state.firLazyDeclarationResolver.resolveFileAnnotations( val llFirResolvableSession = firFile.llFirResolvableSession ?: error("FirFile session expected to be a resolvable session")
val declarationResolver = llFirResolvableSession.moduleComponents.lazyFirDeclarationsResolver
declarationResolver.resolveFileAnnotations(
firFile = firFile, firFile = firFile,
annotations = listOf(annotationCall), annotations = listOf(annotationCall),
moduleFileCache = state.cache,
scopeSession = ScopeSession(), scopeSession = ScopeSession(),
checkPCE = true, checkPCE = true,
collector = collector collector = collector
@@ -207,7 +207,6 @@ object LowLevelFirApiFacadeForResolveOnAir {
onAirCreatedDeclaration: Boolean, onAirCreatedDeclaration: Boolean,
collector: FirTowerDataContextCollector? = null, collector: FirTowerDataContextCollector? = null,
): FirElement { ): FirElement {
val nonLocalDeclaration = findEnclosingNonLocalDeclaration(replacement.from) val nonLocalDeclaration = findEnclosingNonLocalDeclaration(replacement.from)
val originalFirFile = state.getOrBuildFirFile(replacement.from.containingKtFile) val originalFirFile = state.getOrBuildFirFile(replacement.from.containingKtFile)
@@ -217,7 +216,6 @@ object LowLevelFirApiFacadeForResolveOnAir {
if (annotationCall != null) { if (annotationCall != null) {
return tryResolveAsFileAnnotation( return tryResolveAsFileAnnotation(
annotationEntry = annotationCall, annotationEntry = annotationCall,
state = state,
replacement = replacement, replacement = replacement,
firFile = originalFirFile, firFile = originalFirFile,
collector = collector, collector = collector,
@@ -241,7 +239,7 @@ object LowLevelFirApiFacadeForResolveOnAir {
val isInBodyReplacement = isInBodyReplacement(nonLocalDeclaration, replacement) val isInBodyReplacement = isInBodyReplacement(nonLocalDeclaration, replacement)
return state.cache.firFileLockProvider.runCustomResolveUnderLock(originalFirFile, true) { return state.globalComponents.lockProvider.runCustomResolveUnderLock(originalFirFile, true) {
val copiedFirDeclaration = if (isInBodyReplacement) { val copiedFirDeclaration = if (isInBodyReplacement) {
when (originalDeclaration) { when (originalDeclaration) {
is FirSimpleFunction -> is FirSimpleFunction ->
@@ -261,13 +259,15 @@ object LowLevelFirApiFacadeForResolveOnAir {
firFile = originalFirFile firFile = originalFirFile
) )
ResolveTreeBuilder.resolveEnsure(onAirDesignation.declaration, FirResolvePhase.BODY_RESOLVE) { ResolveTreeBuilder.resolveEnsure(onAirDesignation.declaration, FirResolvePhase.BODY_RESOLVE) {
state.firLazyDeclarationResolver.runLazyDesignatedOnAirResolveToBodyWithoutLock( val resolvableSession = onAirDesignation.declaration.llFirResolvableSession
designation = onAirDesignation, ?: error("Expected resolvable session")
moduleFileCache = state.cache, resolvableSession.moduleComponents.lazyFirDeclarationsResolver
checkPCE = true, .runLazyDesignatedOnAirResolveToBodyWithoutLock(
onAirCreatedDeclaration = onAirCreatedDeclaration, designation = onAirDesignation,
towerDataContextCollector = collector, checkPCE = true,
) onAirCreatedDeclaration = onAirCreatedDeclaration,
towerDataContextCollector = collector,
)
} }
copiedFirDeclaration copiedFirDeclaration
} }
@@ -12,19 +12,16 @@ import org.jetbrains.kotlin.diagnostics.KtPsiDiagnostic
import org.jetbrains.kotlin.psi.KtElement import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.psi.KtFile
internal class DiagnosticsCollector( internal class DiagnosticsCollector(private val fileStructureCache: FileStructureCache) {
private val fileStructureCache: FileStructureCache,
private val cache: ModuleFileCache,
) {
fun getDiagnosticsFor(element: KtElement, filter: DiagnosticCheckerFilter): List<KtPsiDiagnostic> { fun getDiagnosticsFor(element: KtElement, filter: DiagnosticCheckerFilter): List<KtPsiDiagnostic> {
val fileStructure = fileStructureCache.getFileStructure(element.containingKtFile, cache) val fileStructure = fileStructureCache.getFileStructure(element.containingKtFile)
val structureElement = fileStructure.getStructureElementFor(element) val structureElement = fileStructure.getStructureElementFor(element)
val diagnostics = structureElement.diagnostics val diagnostics = structureElement.diagnostics
return diagnostics.diagnosticsFor(filter, element) return diagnostics.diagnosticsFor(filter, element)
} }
fun collectDiagnosticsForFile(ktFile: KtFile, filter: DiagnosticCheckerFilter): Collection<KtPsiDiagnostic> { fun collectDiagnosticsForFile(ktFile: KtFile, filter: DiagnosticCheckerFilter): Collection<KtPsiDiagnostic> {
val fileStructure = fileStructureCache.getFileStructure(ktFile, cache) val fileStructure = fileStructureCache.getFileStructure(ktFile)
return fileStructure.getAllDiagnosticsForFile(filter) return fileStructure.getAllDiagnosticsForFile(filter)
} }
} }
@@ -6,9 +6,9 @@
package org.jetbrains.kotlin.analysis.low.level.api.fir.diagnostics package org.jetbrains.kotlin.analysis.low.level.api.fir.diagnostics
import org.jetbrains.kotlin.KtFakeSourceElementKind import org.jetbrains.kotlin.KtFakeSourceElementKind
import org.jetbrains.kotlin.analysis.low.level.api.fir.LLFirModuleResolveComponents
import org.jetbrains.kotlin.analysis.low.level.api.fir.diagnostics.fir.PersistenceContextCollector import org.jetbrains.kotlin.analysis.low.level.api.fir.diagnostics.fir.PersistenceContextCollector
import org.jetbrains.kotlin.analysis.low.level.api.fir.diagnostics.fir.PersistentCheckerContextFactory import org.jetbrains.kotlin.analysis.low.level.api.fir.diagnostics.fir.PersistentCheckerContextFactory
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.LockProvider
import org.jetbrains.kotlin.fir.FirElement import org.jetbrains.kotlin.fir.FirElement
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.collectors.components.AbstractDiagnosticCollectorComponent import org.jetbrains.kotlin.fir.analysis.collectors.components.AbstractDiagnosticCollectorComponent
@@ -19,7 +19,7 @@ internal abstract class FileStructureElementDiagnosticRetriever {
abstract fun retrieve( abstract fun retrieve(
firFile: FirFile, firFile: FirFile,
collector: FileStructureElementDiagnosticsCollector, collector: FileStructureElementDiagnosticsCollector,
lockProvider: LockProvider<FirFile> moduleComponents: LLFirModuleResolveComponents,
): FileStructureElementDiagnosticList ): FileStructureElementDiagnosticList
} }
@@ -29,10 +29,10 @@ internal class SingleNonLocalDeclarationDiagnosticRetriever(
override fun retrieve( override fun retrieve(
firFile: FirFile, firFile: FirFile,
collector: FileStructureElementDiagnosticsCollector, collector: FileStructureElementDiagnosticsCollector,
lockProvider: LockProvider<FirFile> moduleComponents: LLFirModuleResolveComponents,
): FileStructureElementDiagnosticList { ): FileStructureElementDiagnosticList {
val sessionHolder = SessionHolderImpl.createWithEmptyScopeSession(firFile.moduleData.session) val sessionHolder = SessionHolderImpl(moduleComponents.session, moduleComponents.scopeSessionProvider.getScopeSession())
val context = lockProvider.withWriteLock(firFile) { val context = moduleComponents.globalResolveComponents.lockProvider.withWriteLock(firFile) {
PersistenceContextCollector.collectContext(sessionHolder, firFile, structureElementDeclaration) PersistenceContextCollector.collectContext(sessionHolder, firFile, structureElementDeclaration)
} }
return collector.collectForStructureElement(structureElementDeclaration) { components -> return collector.collectForStructureElement(structureElementDeclaration) { components ->
@@ -95,17 +95,19 @@ internal object FileDiagnosticRetriever : FileStructureElementDiagnosticRetrieve
override fun retrieve( override fun retrieve(
firFile: FirFile, firFile: FirFile,
collector: FileStructureElementDiagnosticsCollector, collector: FileStructureElementDiagnosticsCollector,
lockProvider: LockProvider<FirFile> moduleComponents: LLFirModuleResolveComponents,
): FileStructureElementDiagnosticList = ): FileStructureElementDiagnosticList =
collector.collectForStructureElement(firFile) { components -> collector.collectForStructureElement(firFile) { components ->
Visitor(firFile, components) Visitor(components, moduleComponents)
} }
private class Visitor( private class Visitor(
firFile: FirFile, components: List<AbstractDiagnosticCollectorComponent>,
components: List<AbstractDiagnosticCollectorComponent> moduleComponents: LLFirModuleResolveComponents,
) : LLFirDiagnosticVisitor( ) : LLFirDiagnosticVisitor(
PersistentCheckerContextFactory.createEmptyPersistenceCheckerContext(SessionHolderImpl.createWithEmptyScopeSession(firFile.moduleData.session)), PersistentCheckerContextFactory.createEmptyPersistenceCheckerContext(
SessionHolderImpl(moduleComponents.session, moduleComponents.scopeSessionProvider.getScopeSession())
),
components, components,
) { ) {
override fun visitFile(file: FirFile, data: Nothing?) { override fun visitFile(file: FirFile, data: Nothing?) {
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.analysis.low.level.api.fir.diagnostics
import com.intellij.psi.PsiElement import com.intellij.psi.PsiElement
import com.intellij.util.SmartList import com.intellij.util.SmartList
import org.jetbrains.kotlin.analysis.low.level.api.fir.LLFirModuleResolveComponents
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.DiagnosticCheckerFilter import org.jetbrains.kotlin.analysis.low.level.api.fir.api.DiagnosticCheckerFilter
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.LockProvider import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.LockProvider
import org.jetbrains.kotlin.diagnostics.KtPsiDiagnostic import org.jetbrains.kotlin.diagnostics.KtPsiDiagnostic
@@ -14,15 +15,15 @@ import org.jetbrains.kotlin.fir.declarations.FirFile
internal class FileStructureElementDiagnostics( internal class FileStructureElementDiagnostics(
private val firFile: FirFile, private val firFile: FirFile,
private val lockProvider: LockProvider<FirFile>, private val retriever: FileStructureElementDiagnosticRetriever,
private val retriever: FileStructureElementDiagnosticRetriever private val moduleComponents: LLFirModuleResolveComponents,
) { ) {
private val diagnosticByCommonCheckers: FileStructureElementDiagnosticList by lazy { private val diagnosticByCommonCheckers: FileStructureElementDiagnosticList by lazy {
retriever.retrieve(firFile, FileStructureElementDiagnosticsCollector.USUAL_COLLECTOR, lockProvider) retriever.retrieve(firFile, FileStructureElementDiagnosticsCollector.USUAL_COLLECTOR, moduleComponents)
} }
private val diagnosticByExtendedCheckers: FileStructureElementDiagnosticList by lazy { private val diagnosticByExtendedCheckers: FileStructureElementDiagnosticList by lazy {
retriever.retrieve(firFile, FileStructureElementDiagnosticsCollector.EXTENDED_COLLECTOR, lockProvider) retriever.retrieve(firFile, FileStructureElementDiagnosticsCollector.EXTENDED_COLLECTOR, moduleComponents)
} }
fun diagnosticsFor(filter: DiagnosticCheckerFilter, element: PsiElement): List<KtPsiDiagnostic> = fun diagnosticsFor(filter: DiagnosticCheckerFilter, element: PsiElement): List<KtPsiDiagnostic> =
@@ -16,7 +16,7 @@ internal object PersistentCheckerContextFactory {
fun createEmptyPersistenceCheckerContext(sessionHolder: SessionHolder): PersistentCheckerContext { fun createEmptyPersistenceCheckerContext(sessionHolder: SessionHolder): PersistentCheckerContext {
val returnTypeCalculator = createReturnTypeCalculatorForIDE( val returnTypeCalculator = createReturnTypeCalculatorForIDE(
sessionHolder.session, sessionHolder.session,
ScopeSession(), sessionHolder.scopeSession,
ImplicitBodyResolveComputationSession(), ImplicitBodyResolveComputationSession(),
::LLFirDesignatedImpliciteTypesBodyResolveTransformerForReturnTypeCalculator ::LLFirDesignatedImpliciteTypesBodyResolveTransformerForReturnTypeCalculator
) )
@@ -8,16 +8,12 @@ package org.jetbrains.kotlin.analysis.low.level.api.fir.element.builder
import com.intellij.psi.PsiElement import com.intellij.psi.PsiElement
import org.jetbrains.annotations.TestOnly import org.jetbrains.annotations.TestOnly
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.fir.FirElement import org.jetbrains.kotlin.fir.FirElement
import org.jetbrains.kotlin.fir.declarations.FirFile import org.jetbrains.kotlin.fir.declarations.FirFile
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
import org.jetbrains.kotlin.fir.resolve.ScopeSession
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.LLFirModuleResolveState import org.jetbrains.kotlin.analysis.low.level.api.fir.api.LLFirModuleResolveState
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.FirFileBuilder
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.ModuleFileCache
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.structure.FileStructureCache
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.structure.FileStructureElement import org.jetbrains.kotlin.analysis.low.level.api.fir.file.structure.FileStructureElement
import org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve.FirLazyDeclarationResolver
import org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve.declarationCanBeLazilyResolved import org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve.declarationCanBeLazilyResolved
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.getElementTextInContext import org.jetbrains.kotlin.analysis.low.level.api.fir.util.getElementTextInContext
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.isNonAnonymousClassOrObject import org.jetbrains.kotlin.analysis.low.level.api.fir.util.isNonAnonymousClassOrObject
@@ -26,12 +22,11 @@ import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject
import org.jetbrains.kotlin.psi.psiUtil.isAncestor import org.jetbrains.kotlin.psi.psiUtil.isAncestor
import org.jetbrains.kotlin.psi2ir.deparenthesize import org.jetbrains.kotlin.psi2ir.deparenthesize
/**
* Maps [KtElement] to [FirElement]
* Stateless, caches everything into [ModuleFileCache] & [FileStructureCache] passed into the function
*/
@ThreadSafe @ThreadSafe
internal class FirElementBuilder { internal class FirElementBuilder(
private val moduleComponents: LLFirModuleResolveComponents,
) {
companion object { companion object {
fun getPsiAsFirElementSource(element: KtElement): KtElement? { fun getPsiAsFirElementSource(element: KtElement): KtElement? {
val deparenthesized = if (element is KtPropertyDelegate) element.deparenthesize() else element val deparenthesized = if (element is KtPropertyDelegate) element.deparenthesize() else element
@@ -65,28 +60,18 @@ internal class FirElementBuilder {
fun getOrBuildFirFor( fun getOrBuildFirFor(
element: KtElement, element: KtElement,
firFileBuilder: FirFileBuilder,
moduleFileCache: ModuleFileCache,
fileStructureCache: FileStructureCache,
firLazyDeclarationResolver: FirLazyDeclarationResolver,
state: LLFirModuleResolveState, state: LLFirModuleResolveState,
): FirElement? = when (element) { ): FirElement? = when (element) {
is KtFile -> getOrBuildFirForKtFile(element, firFileBuilder, moduleFileCache, firLazyDeclarationResolver) is KtFile -> getOrBuildFirForKtFile(element)
else -> getOrBuildFirForNonKtFileElement(element, fileStructureCache, moduleFileCache, state) else -> getOrBuildFirForNonKtFileElement(element, state)
} }
private fun getOrBuildFirForKtFile( private fun getOrBuildFirForKtFile(ktFile: KtFile): FirFile {
ktFile: KtFile, val firFile = moduleComponents.firFileBuilder.buildRawFirFileWithCaching(ktFile)
firFileBuilder: FirFileBuilder, moduleComponents.lazyFirDeclarationsResolver.lazyResolveFileDeclaration(
moduleFileCache: ModuleFileCache,
firLazyDeclarationResolver: FirLazyDeclarationResolver
): FirFile {
val firFile = firFileBuilder.buildRawFirFileWithCaching(ktFile, moduleFileCache)
firLazyDeclarationResolver.lazyResolveFileDeclaration(
firFile = firFile, firFile = firFile,
moduleFileCache = moduleFileCache,
toPhase = FirResolvePhase.BODY_RESOLVE, toPhase = FirResolvePhase.BODY_RESOLVE,
scopeSession = ScopeSession(), scopeSession = moduleComponents.scopeSessionProvider.getScopeSession(),
checkPCE = true checkPCE = true
) )
return firFile return firFile
@@ -94,8 +79,6 @@ internal class FirElementBuilder {
private fun getOrBuildFirForNonKtFileElement( private fun getOrBuildFirForNonKtFileElement(
element: KtElement, element: KtElement,
fileStructureCache: FileStructureCache,
moduleFileCache: ModuleFileCache,
state: LLFirModuleResolveState, state: LLFirModuleResolveState,
): FirElement? { ): FirElement? {
require(element !is KtFile) require(element !is KtFile)
@@ -105,7 +88,7 @@ internal class FirElementBuilder {
} }
val firFile = element.containingKtFile val firFile = element.containingKtFile
val fileStructure = fileStructureCache.getFileStructure(firFile, moduleFileCache) val fileStructure = moduleComponents.fileStructureCache.getFileStructure(firFile)
val mappings = fileStructure.getStructureElementFor(element).mappings val mappings = fileStructure.getStructureElementFor(element).mappings
val psi = getPsiAsFirElementSource(element) ?: return null val psi = getPsiAsFirElementSource(element) ?: return null
@@ -114,12 +97,8 @@ internal class FirElementBuilder {
} }
@TestOnly @TestOnly
fun getStructureElementFor( fun getStructureElementFor(element: KtElement): FileStructureElement {
element: KtElement, val fileStructure = moduleComponents.fileStructureCache.getFileStructure(element.containingKtFile)
moduleFileCache: ModuleFileCache,
fileStructureCache: FileStructureCache,
): FileStructureElement {
val fileStructure = fileStructureCache.getFileStructure(element.containingKtFile, moduleFileCache)
return fileStructure.getStructureElementFor(element) return fileStructure.getStructureElementFor(element)
} }
} }
@@ -6,6 +6,7 @@
package org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder package org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder
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.fir.builder.RawFirBuilder import org.jetbrains.kotlin.fir.builder.RawFirBuilder
import org.jetbrains.kotlin.fir.builder.BodyBuildingMode import org.jetbrains.kotlin.fir.builder.BodyBuildingMode
import org.jetbrains.kotlin.fir.builder.PsiHandlingMode import org.jetbrains.kotlin.fir.builder.PsiHandlingMode
@@ -16,24 +17,15 @@ import org.jetbrains.kotlin.psi.KtFile
/** /**
* Responsible for building [FirFile] by [KtFile] * Responsible for building [FirFile] by [KtFile]
* Stateless, all caches are stored in [ModuleFileCache] passed into corresponding functions
*/ */
@ThreadSafe @ThreadSafe
internal class FirFileBuilder( internal class FirFileBuilder(
private val scopeProvider: FirScopeProvider, val moduleComponents: LLFirModuleResolveComponents,
val firPhaseRunner: LLFirPhaseRunner
) { ) {
/** fun buildRawFirFileWithCaching(ktFile: KtFile): FirFile = moduleComponents.cache.fileCached(ktFile) {
* Builds a [FirFile] by given [ktFile] and records it's parenting info if it not present in [cache]
* [FirFile] building a happens at most once per each [KtFile]
*/
fun buildRawFirFileWithCaching(
ktFile: KtFile,
cache: ModuleFileCache,
): FirFile = cache.fileCached(ktFile) {
RawFirBuilder( RawFirBuilder(
cache.session, moduleComponents.session,
scopeProvider, moduleComponents.scopeProvider,
psiMode = PsiHandlingMode.IDE, psiMode = PsiHandlingMode.IDE,
bodyBuildingMode = BodyBuildingMode.LAZY_BODIES bodyBuildingMode = BodyBuildingMode.LAZY_BODIES
).buildFirFile(ktFile) ).buildFirFile(ktFile)
@@ -5,19 +5,16 @@
package org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder package org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder
import org.jetbrains.kotlin.analysis.low.level.api.fir.LLFirPhaseRunner import org.jetbrains.kotlin.analysis.low.level.api.fir.LLFirModuleResolveComponents
import org.jetbrains.kotlin.analysis.low.level.api.fir.element.builder.FirTowerDataContextAllElementsCollector import org.jetbrains.kotlin.analysis.low.level.api.fir.element.builder.FirTowerDataContextAllElementsCollector
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.structure.FirElementsRecorder import org.jetbrains.kotlin.analysis.low.level.api.fir.file.structure.FirElementsRecorder
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.structure.KtToFirMapping import org.jetbrains.kotlin.analysis.low.level.api.fir.file.structure.KtToFirMapping
import org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve.FirLazyDeclarationResolver
import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.LLFirLibraryOrLibrarySourceResolvableModuleSession import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.LLFirLibraryOrLibrarySourceResolvableModuleSession
import org.jetbrains.kotlin.fir.declarations.FirClassLikeDeclaration 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.declarations.FirResolvePhase import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
import org.jetbrains.kotlin.fir.psi import org.jetbrains.kotlin.fir.psi
import org.jetbrains.kotlin.fir.resolve.ScopeSession
import org.jetbrains.kotlin.fir.scopes.FirScopeProvider
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
import org.jetbrains.kotlin.name.CallableId import org.jetbrains.kotlin.name.CallableId
import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.ClassId
@@ -25,13 +22,7 @@ import org.jetbrains.kotlin.psi.KtFile
import java.util.* import java.util.*
import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.ConcurrentHashMap
internal class LLFirLibraryResolveModuleFileCache( internal class LLFirLibraryResolveModuleFileCache: ModuleFileCache() {
val kotlinScopeProvider: FirScopeProvider,
override val session: LLFirLibraryOrLibrarySourceResolvableModuleSession
) : ModuleFileCache() {
private val firFileBuilder = FirFileBuilder(kotlinScopeProvider, LLFirPhaseRunner())
private val firLazyDeclarationResolver = FirLazyDeclarationResolver(firFileBuilder)
private val kfFileToFirCache = ConcurrentHashMap<KtFile, ResolvedFile>() private val kfFileToFirCache = ConcurrentHashMap<KtFile, ResolvedFile>()
@@ -58,16 +49,16 @@ internal class LLFirLibraryResolveModuleFileCache(
createKtFile: (KtFile) -> FirFile createKtFile: (KtFile) -> FirFile
): ResolvedFile = kfFileToFirCache.computeIfAbsent(ktFile) { ): ResolvedFile = kfFileToFirCache.computeIfAbsent(ktFile) {
val collector = FirTowerDataContextAllElementsCollector() val collector = FirTowerDataContextAllElementsCollector()
val scopeSession = ScopeSession()
val scopeSession = moduleComponents.scopeSessionProvider.getScopeSession()
val firFile = createKtFile(ktFile) val firFile = createKtFile(ktFile)
firLazyDeclarationResolver.lazyResolveFileDeclaration( moduleComponents.lazyFirDeclarationsResolver.lazyResolveFileDeclaration(
firFile, firFile,
this,
FirResolvePhase.BODY_RESOLVE, FirResolvePhase.BODY_RESOLVE,
scopeSession, scopeSession,
collector = collector, collector,
checkPCE = true checkPCE = true
) )
@@ -7,7 +7,7 @@ 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.fir.FirSession import org.jetbrains.kotlin.analysis.low.level.api.fir.LLFirModuleResolveComponents
import org.jetbrains.kotlin.fir.declarations.FirClassLikeDeclaration 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
@@ -24,7 +24,7 @@ import java.util.concurrent.ConcurrentHashMap
*/ */
@ThreadSafe @ThreadSafe
internal abstract class ModuleFileCache { internal abstract class ModuleFileCache {
abstract val session: FirSession abstract val moduleComponents: LLFirModuleResolveComponents
/** /**
* Maps [ClassId] to corresponding classifiers * Maps [ClassId] to corresponding classifiers
@@ -47,11 +47,9 @@ internal abstract class ModuleFileCache {
abstract fun getContainerFirFile(declaration: FirDeclaration): FirFile? abstract fun getContainerFirFile(declaration: FirDeclaration): FirFile?
abstract fun getCachedFirFile(ktFile: KtFile): FirFile? abstract fun getCachedFirFile(ktFile: KtFile): FirFile?
abstract val firFileLockProvider: LockProvider<FirFile>
} }
internal class ModuleFileCacheImpl(override val session: FirSession) : 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 classifierByClassId: ConcurrentHashMap<ClassId, Optional<FirClassLikeDeclaration>> = ConcurrentHashMap()
@@ -66,6 +64,4 @@ internal class ModuleFileCacheImpl(override val session: FirSession) : ModuleFil
val ktFile = declaration.psi?.containingFile as? KtFile ?: return null val ktFile = declaration.psi?.containingFile as? KtFile ?: return null
return getCachedFirFile(ktFile) return getCachedFirFile(ktFile)
} }
override val firFileLockProvider: LockProvider<FirFile> = LockProvider()
} }
@@ -5,11 +5,11 @@
package org.jetbrains.kotlin.analysis.low.level.api.fir.file.structure package org.jetbrains.kotlin.analysis.low.level.api.fir.file.structure
import org.jetbrains.kotlin.analysis.low.level.api.fir.LLFirModuleResolveComponents
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.declarations.FirProperty import org.jetbrains.kotlin.fir.declarations.FirProperty
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.LockProvider
import org.jetbrains.kotlin.psi.KtDeclaration import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.psi.KtNamedFunction import org.jetbrains.kotlin.psi.KtNamedFunction
import org.jetbrains.kotlin.psi.KtProperty import org.jetbrains.kotlin.psi.KtProperty
@@ -22,14 +22,14 @@ internal object FileElementFactory {
firDeclaration: FirDeclaration, firDeclaration: FirDeclaration,
ktDeclaration: KtDeclaration, ktDeclaration: KtDeclaration,
firFile: FirFile, firFile: FirFile,
firFileLockProvider: LockProvider<FirFile>, moduleComponents: LLFirModuleResolveComponents,
): FileStructureElement = when { ): FileStructureElement = when {
ktDeclaration is KtNamedFunction && ktDeclaration.isReanalyzableContainer() -> ReanalyzableFunctionStructureElement( ktDeclaration is KtNamedFunction && ktDeclaration.isReanalyzableContainer() -> ReanalyzableFunctionStructureElement(
firFile, firFile,
ktDeclaration, ktDeclaration,
(firDeclaration as FirSimpleFunction).symbol, (firDeclaration as FirSimpleFunction).symbol,
ktDeclaration.modificationStamp, ktDeclaration.modificationStamp,
firFileLockProvider, moduleComponents,
) )
ktDeclaration is KtProperty && ktDeclaration.isReanalyzableContainer() -> ReanalyzablePropertyStructureElement( ktDeclaration is KtProperty && ktDeclaration.isReanalyzableContainer() -> ReanalyzablePropertyStructureElement(
@@ -37,14 +37,14 @@ internal object FileElementFactory {
ktDeclaration, ktDeclaration,
(firDeclaration as FirProperty).symbol, (firDeclaration as FirProperty).symbol,
ktDeclaration.modificationStamp, ktDeclaration.modificationStamp,
firFileLockProvider, moduleComponents,
) )
else -> NonReanalyzableDeclarationStructureElement( else -> NonReanalyzableDeclarationStructureElement(
firFile, firFile,
firDeclaration, firDeclaration,
ktDeclaration, ktDeclaration,
firFileLockProvider, moduleComponents,
) )
} }
} }
@@ -6,18 +6,14 @@
package org.jetbrains.kotlin.analysis.low.level.api.fir.file.structure package org.jetbrains.kotlin.analysis.low.level.api.fir.file.structure
import com.intellij.psi.PsiElement import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.analysis.low.level.api.fir.LLFirModuleResolveComponents
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.DiagnosticCheckerFilter import org.jetbrains.kotlin.analysis.low.level.api.fir.api.DiagnosticCheckerFilter
import org.jetbrains.kotlin.analysis.low.level.api.fir.element.builder.getNonLocalContainingOrThisDeclaration import org.jetbrains.kotlin.analysis.low.level.api.fir.element.builder.getNonLocalContainingOrThisDeclaration
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.FirFileBuilder
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.ModuleFileCache
import org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve.FirLazyDeclarationResolver
import org.jetbrains.kotlin.analysis.low.level.api.fir.providers.LLFirProvider
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.findSourceNonLocalFirDeclaration import org.jetbrains.kotlin.analysis.low.level.api.fir.util.findSourceNonLocalFirDeclaration
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.getElementTextInContext import org.jetbrains.kotlin.analysis.low.level.api.fir.util.getElementTextInContext
import org.jetbrains.kotlin.diagnostics.KtPsiDiagnostic import org.jetbrains.kotlin.diagnostics.KtPsiDiagnostic
import org.jetbrains.kotlin.fir.declarations.FirFile import org.jetbrains.kotlin.fir.declarations.FirFile
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
import org.jetbrains.kotlin.fir.resolve.ScopeSession
import org.jetbrains.kotlin.fir.resolve.providers.firProvider import org.jetbrains.kotlin.fir.resolve.providers.firProvider
import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.*
import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.ConcurrentHashMap
@@ -25,19 +21,15 @@ import java.util.concurrent.ConcurrentHashMap
internal class FileStructure private constructor( internal class FileStructure private constructor(
private val ktFile: KtFile, private val ktFile: KtFile,
private val firFile: FirFile, private val firFile: FirFile,
private val firLazyDeclarationResolver: FirLazyDeclarationResolver, private val moduleComponents: LLFirModuleResolveComponents,
private val firFileBuilder: FirFileBuilder,
private val moduleFileCache: ModuleFileCache,
) { ) {
companion object { companion object {
fun build( fun build(
ktFile: KtFile, ktFile: KtFile,
firLazyDeclarationResolver: FirLazyDeclarationResolver, moduleComponents: LLFirModuleResolveComponents,
firFileBuilder: FirFileBuilder,
moduleFileCache: ModuleFileCache,
): FileStructure { ): FileStructure {
val firFile = firFileBuilder.buildRawFirFileWithCaching(ktFile, moduleFileCache) val firFile = moduleComponents.firFileBuilder.buildRawFirFileWithCaching(ktFile)
return FileStructure(ktFile, firFile, firLazyDeclarationResolver, firFileBuilder, moduleFileCache) return FileStructure(ktFile, firFile, moduleComponents)
} }
} }
@@ -56,11 +48,7 @@ internal class FileStructure private constructor(
when { when {
structureElement == null -> createStructureElement(declaration) structureElement == null -> createStructureElement(declaration)
structureElement is ReanalyzableStructureElement<KtDeclaration, *> && !structureElement.isUpToDate() -> { structureElement is ReanalyzableStructureElement<KtDeclaration, *> && !structureElement.isUpToDate() -> {
structureElement.reanalyze( structureElement.reanalyze(newKtDeclaration = declaration as KtDeclaration,)
newKtDeclaration = declaration as KtDeclaration,
cache = moduleFileCache,
firLazyDeclarationResolver = firLazyDeclarationResolver,
)
} }
else -> structureElement else -> structureElement
} }
@@ -111,15 +99,13 @@ internal class FileStructure private constructor(
private fun createDeclarationStructure(declaration: KtDeclaration): FileStructureElement { private fun createDeclarationStructure(declaration: KtDeclaration): FileStructureElement {
val firDeclaration = declaration.findSourceNonLocalFirDeclaration( val firDeclaration = declaration.findSourceNonLocalFirDeclaration(
firFileBuilder, moduleComponents.firFileBuilder,
firProvider.symbolProvider, firProvider,
moduleFileCache,
firFile firFile
) )
firLazyDeclarationResolver.lazyResolveDeclaration( moduleComponents.lazyFirDeclarationsResolver.lazyResolveDeclaration(
firDeclarationToResolve = firDeclaration, firDeclarationToResolve = firDeclaration,
moduleFileCache = moduleFileCache, scopeSession = moduleComponents.scopeSessionProvider.getScopeSession(),
scopeSession = ScopeSession(),
toPhase = FirResolvePhase.BODY_RESOLVE, toPhase = FirResolvePhase.BODY_RESOLVE,
checkPCE = true, checkPCE = true,
) )
@@ -127,25 +113,20 @@ internal class FileStructure private constructor(
firDeclaration = firDeclaration, firDeclaration = firDeclaration,
ktDeclaration = declaration, ktDeclaration = declaration,
firFile = firFile, firFile = firFile,
firFileLockProvider = moduleFileCache.firFileLockProvider moduleComponents = moduleComponents
) )
} }
private fun createStructureElement(container: KtAnnotated): FileStructureElement = when (container) { private fun createStructureElement(container: KtAnnotated): FileStructureElement = when (container) {
is KtFile -> { is KtFile -> {
val firFile = firFileBuilder.buildRawFirFileWithCaching(ktFile, moduleFileCache) val firFile = moduleComponents.firFileBuilder.buildRawFirFileWithCaching(ktFile)
firLazyDeclarationResolver.resolveFileAnnotations( moduleComponents.lazyFirDeclarationsResolver.resolveFileAnnotations(
firFile = firFile, firFile = firFile,
annotations = firFile.annotations, annotations = firFile.annotations,
moduleFileCache = moduleFileCache, scopeSession = moduleComponents.scopeSessionProvider.getScopeSession(),
scopeSession = ScopeSession(),
checkPCE = true checkPCE = true
) )
RootStructureElement( RootStructureElement(firFile, container, moduleComponents)
firFile,
container,
moduleFileCache.firFileLockProvider,
)
} }
is KtDeclaration -> createDeclarationStructure(container) is KtDeclaration -> createDeclarationStructure(container)
else -> error("Invalid container $container") else -> error("Invalid container $container")
@@ -5,22 +5,17 @@
package org.jetbrains.kotlin.analysis.low.level.api.fir.file.structure package org.jetbrains.kotlin.analysis.low.level.api.fir.file.structure
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.FirFileBuilder import org.jetbrains.kotlin.analysis.low.level.api.fir.LLFirModuleResolveComponents
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.ModuleFileCache
import org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve.FirLazyDeclarationResolver
import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.psi.KtFile
import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.ConcurrentHashMap
/** /**
* Belongs to a [org.jetbrains.kotlin.analysis.low.level.api.fir.api.LLFirModuleResolveState] * Belongs to a [org.jetbrains.kotlin.analysis.low.level.api.fir.api.LLFirModuleResolveState]
*/ */
internal class FileStructureCache( internal class FileStructureCache(private val moduleResolveComponents: LLFirModuleResolveComponents) {
private val fileBuilder: FirFileBuilder,
private val firLazyDeclarationResolver: FirLazyDeclarationResolver,
) {
private val cache = ConcurrentHashMap<KtFile, FileStructure>() private val cache = ConcurrentHashMap<KtFile, FileStructure>()
fun getFileStructure(ktFile: KtFile, moduleFileCache: ModuleFileCache): FileStructure = cache.computeIfAbsent(ktFile) { fun getFileStructure(ktFile: KtFile): FileStructure = cache.computeIfAbsent(ktFile) {
FileStructure.build(ktFile, firLazyDeclarationResolver, fileBuilder, moduleFileCache) FileStructure.build(ktFile, moduleResolveComponents)
} }
} }
@@ -6,21 +6,18 @@
package org.jetbrains.kotlin.analysis.low.level.api.fir.file.structure package org.jetbrains.kotlin.analysis.low.level.api.fir.file.structure
import com.intellij.psi.PsiElement import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.analysis.low.level.api.fir.LLFirModuleResolveComponents
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.LLFirModuleResolveState import org.jetbrains.kotlin.analysis.low.level.api.fir.api.LLFirModuleResolveState
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.LowLevelFirApiFacadeForResolveOnAir import org.jetbrains.kotlin.analysis.low.level.api.fir.api.LowLevelFirApiFacadeForResolveOnAir
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.collectDesignation import org.jetbrains.kotlin.analysis.low.level.api.fir.api.collectDesignation
import org.jetbrains.kotlin.analysis.low.level.api.fir.diagnostics.FileDiagnosticRetriever import org.jetbrains.kotlin.analysis.low.level.api.fir.diagnostics.FileDiagnosticRetriever
import org.jetbrains.kotlin.analysis.low.level.api.fir.diagnostics.FileStructureElementDiagnostics import org.jetbrains.kotlin.analysis.low.level.api.fir.diagnostics.FileStructureElementDiagnostics
import org.jetbrains.kotlin.analysis.low.level.api.fir.diagnostics.SingleNonLocalDeclarationDiagnosticRetriever import org.jetbrains.kotlin.analysis.low.level.api.fir.diagnostics.SingleNonLocalDeclarationDiagnosticRetriever
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.LockProvider
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.ModuleFileCache
import org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve.FirLazyDeclarationResolver
import org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve.RawFirNonLocalDeclarationBuilder import org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve.RawFirNonLocalDeclarationBuilder
import org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve.declarationCanBeLazilyResolved import org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve.declarationCanBeLazilyResolved
import org.jetbrains.kotlin.fir.FirElement import org.jetbrains.kotlin.fir.FirElement
import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.psi import org.jetbrains.kotlin.fir.psi
import org.jetbrains.kotlin.fir.resolve.ScopeSession
import org.jetbrains.kotlin.fir.scopes.kotlinScopeProvider import org.jetbrains.kotlin.fir.scopes.kotlinScopeProvider
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol
@@ -28,7 +25,7 @@ import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.*
import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.ConcurrentHashMap
internal sealed class FileStructureElement(val firFile: FirFile, protected val lockProvider: LockProvider<FirFile>) { internal sealed class FileStructureElement(val firFile: FirFile, protected val moduleComponents: LLFirModuleResolveComponents) {
abstract val psi: KtAnnotated abstract val psi: KtAnnotated
abstract val mappings: KtToFirMapping abstract val mappings: KtToFirMapping
abstract val diagnostics: FileStructureElementDiagnostics abstract val diagnostics: FileStructureElementDiagnostics
@@ -71,8 +68,8 @@ internal class KtToFirMapping(firElement: FirElement, recorder: FirElementsRecor
internal sealed class ReanalyzableStructureElement<KT : KtDeclaration, S : FirBasedSymbol<*>>( internal sealed class ReanalyzableStructureElement<KT : KtDeclaration, S : FirBasedSymbol<*>>(
firFile: FirFile, firFile: FirFile,
val firSymbol: S, val firSymbol: S,
lockProvider: LockProvider<FirFile>, moduleComponents: LLFirModuleResolveComponents,
) : FileStructureElement(firFile, lockProvider) { ) : FileStructureElement(firFile, moduleComponents) {
abstract override val psi: KtDeclaration abstract override val psi: KtDeclaration
abstract val timestamp: Long abstract val timestamp: Long
@@ -82,16 +79,14 @@ internal sealed class ReanalyzableStructureElement<KT : KtDeclaration, S : FirBa
*/ */
abstract fun reanalyze( abstract fun reanalyze(
newKtDeclaration: KT, newKtDeclaration: KT,
cache: ModuleFileCache,
firLazyDeclarationResolver: FirLazyDeclarationResolver,
): ReanalyzableStructureElement<KT, S> ): ReanalyzableStructureElement<KT, S>
fun isUpToDate(): Boolean = psi.getModificationStamp() == timestamp fun isUpToDate(): Boolean = psi.getModificationStamp() == timestamp
override val diagnostics = FileStructureElementDiagnostics( override val diagnostics = FileStructureElementDiagnostics(
firFile, firFile,
lockProvider, SingleNonLocalDeclarationDiagnosticRetriever(firSymbol.fir),
SingleNonLocalDeclarationDiagnosticRetriever(firSymbol.fir) moduleComponents,
) )
companion object { companion object {
@@ -104,15 +99,11 @@ internal class ReanalyzableFunctionStructureElement(
override val psi: KtNamedFunction, override val psi: KtNamedFunction,
firSymbol: FirFunctionSymbol<*>, firSymbol: FirFunctionSymbol<*>,
override val timestamp: Long, override val timestamp: Long,
lockProvider: LockProvider<FirFile>, moduleComponents: LLFirModuleResolveComponents,
) : ReanalyzableStructureElement<KtNamedFunction, FirFunctionSymbol<*>>(firFile, firSymbol, lockProvider) { ) : ReanalyzableStructureElement<KtNamedFunction, FirFunctionSymbol<*>>(firFile, firSymbol, moduleComponents) {
override val mappings = KtToFirMapping(firSymbol.fir, recorder) override val mappings = KtToFirMapping(firSymbol.fir, recorder)
override fun reanalyze( override fun reanalyze(newKtDeclaration: KtNamedFunction): ReanalyzableFunctionStructureElement {
newKtDeclaration: KtNamedFunction,
cache: ModuleFileCache,
firLazyDeclarationResolver: FirLazyDeclarationResolver,
): ReanalyzableFunctionStructureElement {
val originalFunction = firSymbol.fir as FirSimpleFunction val originalFunction = firSymbol.fir as FirSimpleFunction
val designation = originalFunction.collectDesignation() val designation = originalFunction.collectDesignation()
@@ -123,7 +114,7 @@ internal class ReanalyzableFunctionStructureElement(
rootNonLocalDeclaration = newKtDeclaration, rootNonLocalDeclaration = newKtDeclaration,
) as FirSimpleFunction ) as FirSimpleFunction
return cache.firFileLockProvider.withWriteLock(firFile) { return moduleComponents.globalResolveComponents.lockProvider.withWriteLock(firFile) {
val upgradedPhase = minOf(originalFunction.resolvePhase, FirResolvePhase.DECLARATIONS) val upgradedPhase = minOf(originalFunction.resolvePhase, FirResolvePhase.DECLARATIONS)
with(originalFunction) { with(originalFunction) {
replaceBody(temporaryFunction.body) replaceBody(temporaryFunction.body)
@@ -134,10 +125,9 @@ internal class ReanalyzableFunctionStructureElement(
it.replaceResolvePhase(minOf(it.resolvePhase, upgradedPhase)) it.replaceResolvePhase(minOf(it.resolvePhase, upgradedPhase))
} }
firLazyDeclarationResolver.lazyResolveDeclaration( moduleComponents.lazyFirDeclarationsResolver.lazyResolveDeclaration(
firDeclarationToResolve = originalFunction, firDeclarationToResolve = originalFunction,
moduleFileCache = cache, scopeSession = moduleComponents.scopeSessionProvider.getScopeSession(),
scopeSession = ScopeSession(),
toPhase = FirResolvePhase.BODY_RESOLVE, toPhase = FirResolvePhase.BODY_RESOLVE,
checkPCE = true, checkPCE = true,
) )
@@ -147,7 +137,7 @@ internal class ReanalyzableFunctionStructureElement(
newKtDeclaration, newKtDeclaration,
originalFunction.symbol, originalFunction.symbol,
newKtDeclaration.modificationStamp, newKtDeclaration.modificationStamp,
lockProvider, moduleComponents,
) )
} }
} }
@@ -158,15 +148,11 @@ internal class ReanalyzablePropertyStructureElement(
override val psi: KtProperty, override val psi: KtProperty,
firSymbol: FirPropertySymbol, firSymbol: FirPropertySymbol,
override val timestamp: Long, override val timestamp: Long,
lockProvider: LockProvider<FirFile>, moduleComponents: LLFirModuleResolveComponents,
) : ReanalyzableStructureElement<KtProperty, FirPropertySymbol>(firFile, firSymbol, lockProvider) { ) : ReanalyzableStructureElement<KtProperty, FirPropertySymbol>(firFile, firSymbol, moduleComponents) {
override val mappings = KtToFirMapping(firSymbol.fir, recorder) override val mappings = KtToFirMapping(firSymbol.fir, recorder)
override fun reanalyze( override fun reanalyze(newKtDeclaration: KtProperty): ReanalyzablePropertyStructureElement {
newKtDeclaration: KtProperty,
cache: ModuleFileCache,
firLazyDeclarationResolver: FirLazyDeclarationResolver,
): ReanalyzablePropertyStructureElement {
val originalProperty = firSymbol.fir val originalProperty = firSymbol.fir
val designation = originalProperty.collectDesignation() val designation = originalProperty.collectDesignation()
@@ -177,7 +163,7 @@ internal class ReanalyzablePropertyStructureElement(
rootNonLocalDeclaration = newKtDeclaration, rootNonLocalDeclaration = newKtDeclaration,
) as FirProperty ) as FirProperty
return cache.firFileLockProvider.withWriteLock(firFile) { return moduleComponents.globalResolveComponents.lockProvider.withWriteLock(firFile) {
val getterPhase = originalProperty.getter?.resolvePhase ?: originalProperty.resolvePhase val getterPhase = originalProperty.getter?.resolvePhase ?: originalProperty.resolvePhase
val setterPhase = originalProperty.setter?.resolvePhase ?: originalProperty.resolvePhase val setterPhase = originalProperty.setter?.resolvePhase ?: originalProperty.resolvePhase
@@ -193,10 +179,9 @@ internal class ReanalyzablePropertyStructureElement(
replaceBodyResolveState(FirPropertyBodyResolveState.NOTHING_RESOLVED) replaceBodyResolveState(FirPropertyBodyResolveState.NOTHING_RESOLVED)
} }
firLazyDeclarationResolver.lazyResolveDeclaration( moduleComponents.lazyFirDeclarationsResolver.lazyResolveDeclaration(
firDeclarationToResolve = originalProperty, firDeclarationToResolve = originalProperty,
moduleFileCache = cache, scopeSession = moduleComponents.scopeSessionProvider.getScopeSession(),
scopeSession = ScopeSession(),
toPhase = FirResolvePhase.BODY_RESOLVE, toPhase = FirResolvePhase.BODY_RESOLVE,
checkPCE = true, checkPCE = true,
) )
@@ -207,7 +192,7 @@ internal class ReanalyzablePropertyStructureElement(
newKtDeclaration, newKtDeclaration,
originalProperty.symbol, originalProperty.symbol,
newKtDeclaration.modificationStamp, newKtDeclaration.modificationStamp,
lockProvider, moduleComponents,
) )
} }
} }
@@ -217,11 +202,15 @@ internal class NonReanalyzableDeclarationStructureElement(
firFile: FirFile, firFile: FirFile,
val fir: FirDeclaration, val fir: FirDeclaration,
override val psi: KtDeclaration, override val psi: KtDeclaration,
lockProvider: LockProvider<FirFile>, moduleComponents: LLFirModuleResolveComponents,
) : FileStructureElement(firFile, lockProvider) { ) : FileStructureElement(firFile, moduleComponents) {
override val mappings = KtToFirMapping(fir, recorder) override val mappings = KtToFirMapping(fir, recorder)
override val diagnostics = FileStructureElementDiagnostics(firFile, lockProvider, SingleNonLocalDeclarationDiagnosticRetriever(fir)) override val diagnostics = FileStructureElementDiagnostics(
firFile,
SingleNonLocalDeclarationDiagnosticRetriever(fir),
moduleComponents,
)
companion object { companion object {
@@ -247,11 +236,12 @@ internal class NonReanalyzableDeclarationStructureElement(
internal class RootStructureElement( internal class RootStructureElement(
firFile: FirFile, firFile: FirFile,
override val psi: KtFile, override val psi: KtFile,
lockProvider: LockProvider<FirFile>, moduleComponents: LLFirModuleResolveComponents,
) : FileStructureElement(firFile, lockProvider) { ) : FileStructureElement(firFile, moduleComponents) {
override val mappings = KtToFirMapping(firFile, recorder) override val mappings = KtToFirMapping(firFile, recorder)
override val diagnostics = FileStructureElementDiagnostics(firFile, lockProvider, FileDiagnosticRetriever) override val diagnostics =
FileStructureElementDiagnostics(firFile, FileDiagnosticRetriever, moduleComponents)
companion object { companion object {
private val recorder = object : FirElementsRecorder() { private val recorder = object : FirElementsRecorder() {
@@ -5,12 +5,13 @@
package org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve package org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve
import org.jetbrains.kotlin.analysis.low.level.api.fir.LLFirModuleResolveComponents
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.FirDeclarationDesignationWithFile import org.jetbrains.kotlin.analysis.low.level.api.fir.api.FirDeclarationDesignationWithFile
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.collectDesignationWithFile import org.jetbrains.kotlin.analysis.low.level.api.fir.api.collectDesignationWithFile
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.tryCollectDesignationWithFile import org.jetbrains.kotlin.analysis.low.level.api.fir.api.tryCollectDesignationWithFile
import org.jetbrains.kotlin.analysis.low.level.api.fir.element.builder.getNonLocalContainingOrThisDeclaration import org.jetbrains.kotlin.analysis.low.level.api.fir.element.builder.getNonLocalContainingOrThisDeclaration
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.FirFileBuilder import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.FirFileBuilder
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.ModuleFileCache import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.LockProvider
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.runCustomResolveUnderLock import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.runCustomResolveUnderLock
import org.jetbrains.kotlin.analysis.low.level.api.fir.transformers.LLFirFileAnnotationsResolveTransformer import org.jetbrains.kotlin.analysis.low.level.api.fir.transformers.LLFirFileAnnotationsResolveTransformer
import org.jetbrains.kotlin.analysis.low.level.api.fir.transformers.LLFirFirProviderInterceptor import org.jetbrains.kotlin.analysis.low.level.api.fir.transformers.LLFirFirProviderInterceptor
@@ -30,7 +31,7 @@ import org.jetbrains.kotlin.psi.KtClassBody
import org.jetbrains.kotlin.psi.KtDeclaration import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.psi.KtEnumEntry import org.jetbrains.kotlin.psi.KtEnumEntry
internal class FirLazyDeclarationResolver(private val firFileBuilder: FirFileBuilder) { internal class FirLazyDeclarationResolver(val moduleComponents: LLFirModuleResolveComponents) {
/** /**
* Fully resolve file annotations (synchronized) * Fully resolve file annotations (synchronized)
* @see resolveFileAnnotationsWithoutLock not synchronized * @see resolveFileAnnotationsWithoutLock not synchronized
@@ -38,13 +39,12 @@ internal class FirLazyDeclarationResolver(private val firFileBuilder: FirFileBui
fun resolveFileAnnotations( fun resolveFileAnnotations(
firFile: FirFile, firFile: FirFile,
annotations: List<FirAnnotation>, annotations: List<FirAnnotation>,
moduleFileCache: ModuleFileCache,
scopeSession: ScopeSession, scopeSession: ScopeSession,
checkPCE: Boolean, checkPCE: Boolean,
collector: FirTowerDataContextCollector? = null, collector: FirTowerDataContextCollector? = null,
) { ) {
if (firFile.resolvePhase >= FirResolvePhase.IMPORTS && annotations.all { it.resolved }) return if (firFile.resolvePhase >= FirResolvePhase.IMPORTS && annotations.all { it.resolved }) return
moduleFileCache.firFileLockProvider.runCustomResolveUnderLock(firFile, checkPCE) { moduleComponents.globalResolveComponents.lockProvider.runCustomResolveUnderLock(firFile, checkPCE) {
resolveFileAnnotationsWithoutLock( resolveFileAnnotationsWithoutLock(
firFile = firFile, firFile = firFile,
annotations = annotations, annotations = annotations,
@@ -75,7 +75,7 @@ internal class FirLazyDeclarationResolver(private val firFileBuilder: FirFileBui
session = firFile.moduleData.session, session = firFile.moduleData.session,
scopeSession = scopeSession, scopeSession = scopeSession,
firTowerDataContextCollector = collector, firTowerDataContextCollector = collector,
).transformDeclaration(firFileBuilder.firPhaseRunner) ).transformDeclaration(moduleComponents.globalResolveComponents.phaseRunner)
} }
} }
@@ -110,21 +110,19 @@ internal class FirLazyDeclarationResolver(private val firFileBuilder: FirFileBui
fun lazyResolveFileDeclaration( fun lazyResolveFileDeclaration(
firFile: FirFile, firFile: FirFile,
moduleFileCache: ModuleFileCache,
toPhase: FirResolvePhase, toPhase: FirResolvePhase,
scopeSession: ScopeSession, scopeSession: ScopeSession,
collector: FirTowerDataContextCollector? = null, collector: FirTowerDataContextCollector? = null,
checkPCE: Boolean = false, checkPCE: Boolean = false,
) { ) {
if (toPhase == FirResolvePhase.RAW_FIR) return if (toPhase == FirResolvePhase.RAW_FIR) return
resolveFileToImports(firFile, moduleFileCache, checkPCE) resolveFileToImports(firFile, checkPCE)
if (toPhase == FirResolvePhase.IMPORTS) return if (toPhase == FirResolvePhase.IMPORTS) return
if (firFile.resolvePhase >= toPhase) return if (firFile.resolvePhase >= toPhase) return
moduleFileCache.firFileLockProvider.runCustomResolveUnderLock(firFile, checkPCE) { moduleComponents.globalResolveComponents.lockProvider.runCustomResolveUnderLock(firFile, checkPCE) {
ResolveTreeBuilder.resolveEnsure(firFile, toPhase) { ResolveTreeBuilder.resolveEnsure(firFile, toPhase) {
lazyResolveFileDeclarationWithoutLock( lazyResolveFileDeclarationWithoutLock(
firFile = firFile, firFile = firFile,
moduleFileCache = moduleFileCache,
toPhase = toPhase, toPhase = toPhase,
collector = collector, collector = collector,
scopeSession = scopeSession, scopeSession = scopeSession,
@@ -134,9 +132,9 @@ internal class FirLazyDeclarationResolver(private val firFileBuilder: FirFileBui
} }
} }
private fun resolveFileToImports(firFile: FirFile, moduleFileCache: ModuleFileCache, checkPCE: Boolean) { private fun resolveFileToImports(firFile: FirFile, checkPCE: Boolean) {
if (firFile.resolvePhase >= FirResolvePhase.IMPORTS) return if (firFile.resolvePhase >= FirResolvePhase.IMPORTS) return
moduleFileCache.firFileLockProvider.runCustomResolveUnderLock(firFile, checkPCE) { moduleComponents.globalResolveComponents.lockProvider.runCustomResolveUnderLock(firFile, checkPCE) {
resolveFileToImportsWithoutLock(firFile, checkPCE) resolveFileToImportsWithoutLock(firFile, checkPCE)
} }
} }
@@ -150,7 +148,6 @@ internal class FirLazyDeclarationResolver(private val firFileBuilder: FirFileBui
private fun lazyResolveFileDeclarationWithoutLock( private fun lazyResolveFileDeclarationWithoutLock(
firFile: FirFile, firFile: FirFile,
moduleFileCache: ModuleFileCache,
toPhase: FirResolvePhase, toPhase: FirResolvePhase,
scopeSession: ScopeSession, scopeSession: ScopeSession,
checkPCE: Boolean = false, checkPCE: Boolean = false,
@@ -183,7 +180,6 @@ internal class FirLazyDeclarationResolver(private val firFileBuilder: FirFileBui
phase = currentPhase, phase = currentPhase,
designation = it, designation = it,
scopeSession = scopeSession, scopeSession = scopeSession,
moduleFileCache = moduleFileCache,
lazyDeclarationResolver = this, lazyDeclarationResolver = this,
towerDataContextCollector = collector, towerDataContextCollector = collector,
firProviderInterceptor = null, firProviderInterceptor = null,
@@ -193,9 +189,9 @@ internal class FirLazyDeclarationResolver(private val firFileBuilder: FirFileBui
} }
if (transformersToApply.isEmpty()) continue if (transformersToApply.isEmpty()) continue
firFileBuilder.firPhaseRunner.runPhaseWithCustomResolve(currentPhase) { moduleComponents.globalResolveComponents.phaseRunner.runPhaseWithCustomResolve(currentPhase) {
for (currentTransformer in transformersToApply) { for (currentTransformer in transformersToApply) {
currentTransformer.transformDeclaration(firFileBuilder.firPhaseRunner) currentTransformer.transformDeclaration(moduleComponents.globalResolveComponents.phaseRunner)
} }
} }
firFile.replaceResolvePhase(currentPhase) firFile.replaceResolvePhase(currentPhase)
@@ -204,7 +200,6 @@ internal class FirLazyDeclarationResolver(private val firFileBuilder: FirFileBui
private fun fastTrackForImportsPhase( private fun fastTrackForImportsPhase(
firDeclarationToResolve: FirDeclaration, firDeclarationToResolve: FirDeclaration,
moduleFileCache: ModuleFileCache,
checkPCE: Boolean, checkPCE: Boolean,
): Boolean { ): Boolean {
val provider = firDeclarationToResolve.moduleData.session.firProvider val provider = firDeclarationToResolve.moduleData.session.firProvider
@@ -214,7 +209,7 @@ internal class FirLazyDeclarationResolver(private val firFileBuilder: FirFileBui
is FirClassLikeDeclaration -> provider.getFirClassifierContainerFile(firDeclarationToResolve.symbol) is FirClassLikeDeclaration -> provider.getFirClassifierContainerFile(firDeclarationToResolve.symbol)
else -> null else -> null
} ?: return false } ?: return false
resolveFileToImports(firFile, moduleFileCache, checkPCE) resolveFileToImports(firFile, checkPCE)
return true return true
} }
@@ -226,14 +221,13 @@ internal class FirLazyDeclarationResolver(private val firFileBuilder: FirFileBui
*/ */
fun lazyResolveDeclaration( fun lazyResolveDeclaration(
firDeclarationToResolve: FirDeclaration, firDeclarationToResolve: FirDeclaration,
moduleFileCache: ModuleFileCache,
scopeSession: ScopeSession, scopeSession: ScopeSession,
toPhase: FirResolvePhase, toPhase: FirResolvePhase,
checkPCE: Boolean, checkPCE: Boolean,
) { ) {
if (toPhase == FirResolvePhase.RAW_FIR) return if (toPhase == FirResolvePhase.RAW_FIR) return
if (toPhase == FirResolvePhase.IMPORTS) { if (toPhase == FirResolvePhase.IMPORTS) {
if (fastTrackForImportsPhase(firDeclarationToResolve, moduleFileCache, checkPCE)) { if (fastTrackForImportsPhase(firDeclarationToResolve, checkPCE)) {
return return
} }
} }
@@ -241,7 +235,6 @@ internal class FirLazyDeclarationResolver(private val firFileBuilder: FirFileBui
is FirSyntheticPropertyAccessor -> { is FirSyntheticPropertyAccessor -> {
lazyResolveDeclaration( lazyResolveDeclaration(
firDeclarationToResolve.delegate, firDeclarationToResolve.delegate,
moduleFileCache,
scopeSession, scopeSession,
toPhase, toPhase,
checkPCE, checkPCE,
@@ -252,7 +245,6 @@ internal class FirLazyDeclarationResolver(private val firFileBuilder: FirFileBui
is FirBackingField -> { is FirBackingField -> {
lazyResolveDeclaration( lazyResolveDeclaration(
firDeclarationToResolve.propertySymbol.fir, firDeclarationToResolve.propertySymbol.fir,
moduleFileCache,
scopeSession, scopeSession,
toPhase, toPhase,
checkPCE, checkPCE,
@@ -262,7 +254,6 @@ internal class FirLazyDeclarationResolver(private val firFileBuilder: FirFileBui
is FirFile -> { is FirFile -> {
lazyResolveFileDeclaration( lazyResolveFileDeclaration(
firFile = firDeclarationToResolve, firFile = firDeclarationToResolve,
moduleFileCache = moduleFileCache,
toPhase = toPhase, toPhase = toPhase,
scopeSession = scopeSession, scopeSession = scopeSession,
checkPCE = checkPCE, checkPCE = checkPCE,
@@ -297,16 +288,14 @@ internal class FirLazyDeclarationResolver(private val firFileBuilder: FirFileBui
val enumEntry = possiblyLocalDeclaration.getContainingEnumEntryAsMemberOfEnumEntry() ?: return val enumEntry = possiblyLocalDeclaration.getContainingEnumEntryAsMemberOfEnumEntry() ?: return
declarationToResolve = enumEntry.findSourceNonLocalFirDeclaration( declarationToResolve = enumEntry.findSourceNonLocalFirDeclaration(
firFileBuilder, moduleComponents.firFileBuilder,
firDeclarationToResolve.moduleData.session.firProvider.symbolProvider, firDeclarationToResolve.moduleData.session.firProvider,
moduleFileCache
) )
neededPhase = FirResolvePhase.BODY_RESOLVE neededPhase = FirResolvePhase.BODY_RESOLVE
} else { } else {
declarationToResolve = nonLocalDeclaration.findSourceNonLocalFirDeclaration( declarationToResolve = nonLocalDeclaration.findSourceNonLocalFirDeclaration(
firFileBuilder, moduleComponents.firFileBuilder,
firDeclarationToResolve.moduleData.session.firProvider.symbolProvider, firDeclarationToResolve.moduleData.session.firProvider,
moduleFileCache
) )
neededPhase = toPhase neededPhase = toPhase
} }
@@ -320,15 +309,14 @@ internal class FirLazyDeclarationResolver(private val firFileBuilder: FirFileBui
if (designation.declaration.resolvePhase >= neededPhase) return if (designation.declaration.resolvePhase >= neededPhase) return
if (neededPhase == FirResolvePhase.IMPORTS) { if (neededPhase == FirResolvePhase.IMPORTS) {
resolveFileToImports(designation.firFile, moduleFileCache, checkPCE) resolveFileToImports(designation.firFile, checkPCE)
return return
} }
moduleFileCache.firFileLockProvider.runCustomResolveUnderLock(designation.firFile, checkPCE) { moduleComponents.globalResolveComponents.lockProvider.runCustomResolveUnderLock(designation.firFile, checkPCE) {
ResolveTreeBuilder.resolveEnsure(designation.declaration, neededPhase) { ResolveTreeBuilder.resolveEnsure(designation.declaration, neededPhase) {
runLazyDesignatedResolveWithoutLock( runLazyDesignatedResolveWithoutLock(
designation = designation, designation = designation,
moduleFileCache = moduleFileCache,
scopeSession = scopeSession, scopeSession = scopeSession,
toPhase = neededPhase, toPhase = neededPhase,
checkPCE = checkPCE, checkPCE = checkPCE,
@@ -341,7 +329,6 @@ internal class FirLazyDeclarationResolver(private val firFileBuilder: FirFileBui
private fun runLazyDesignatedResolveWithoutLock( private fun runLazyDesignatedResolveWithoutLock(
designation: FirDeclarationDesignationWithFile, designation: FirDeclarationDesignationWithFile,
moduleFileCache: ModuleFileCache,
scopeSession: ScopeSession, scopeSession: ScopeSession,
toPhase: FirResolvePhase, toPhase: FirResolvePhase,
checkPCE: Boolean, checkPCE: Boolean,
@@ -363,18 +350,16 @@ internal class FirLazyDeclarationResolver(private val firFileBuilder: FirFileBui
phase = currentPhase, phase = currentPhase,
designation = designation, designation = designation,
scopeSession = scopeSession, scopeSession = scopeSession,
moduleFileCache = moduleFileCache,
lazyDeclarationResolver = this, lazyDeclarationResolver = this,
towerDataContextCollector = null, towerDataContextCollector = null,
firProviderInterceptor = null, firProviderInterceptor = null,
checkPCE = checkPCE, checkPCE = checkPCE,
).transformDeclaration(firFileBuilder.firPhaseRunner) ).transformDeclaration(moduleComponents.globalResolveComponents.phaseRunner)
} }
} }
internal fun runLazyDesignatedOnAirResolveToBodyWithoutLock( internal fun runLazyDesignatedOnAirResolveToBodyWithoutLock(
designation: FirDeclarationDesignationWithFile, designation: FirDeclarationDesignationWithFile,
moduleFileCache: ModuleFileCache,
checkPCE: Boolean, checkPCE: Boolean,
onAirCreatedDeclaration: Boolean, onAirCreatedDeclaration: Boolean,
towerDataContextCollector: FirTowerDataContextCollector?, towerDataContextCollector: FirTowerDataContextCollector?,
@@ -400,12 +385,11 @@ internal class FirLazyDeclarationResolver(private val firFileBuilder: FirFileBui
phase = currentPhase, phase = currentPhase,
designation = designation, designation = designation,
scopeSession = scopeSession, scopeSession = scopeSession,
moduleFileCache = moduleFileCache,
lazyDeclarationResolver = this, lazyDeclarationResolver = this,
towerDataContextCollector = towerDataContextCollector, towerDataContextCollector = towerDataContextCollector,
firProviderInterceptor = firProviderInterceptor, firProviderInterceptor = firProviderInterceptor,
checkPCE = checkPCE, checkPCE = checkPCE,
).transformDeclaration(firFileBuilder.firPhaseRunner) ).transformDeclaration(moduleComponents.globalResolveComponents.phaseRunner)
} }
} }
} }
@@ -5,10 +5,8 @@
package org.jetbrains.kotlin.analysis.low.level.api.fir.providers package org.jetbrains.kotlin.analysis.low.level.api.fir.providers
import com.intellij.openapi.project.Project import org.jetbrains.kotlin.analysis.low.level.api.fir.LLFirModuleResolveComponents
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.FirFileBuilder
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.ModuleFileCache import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.ModuleFileCache
import org.jetbrains.kotlin.analysis.project.structure.KtModule
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.FirSession
@@ -21,7 +19,6 @@ import org.jetbrains.kotlin.fir.originalForSubstitutionOverride
import org.jetbrains.kotlin.fir.resolve.providers.FirProvider import org.jetbrains.kotlin.fir.resolve.providers.FirProvider
import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider
import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProviderInternals import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProviderInternals
import org.jetbrains.kotlin.fir.scopes.FirKotlinScopeProvider
import org.jetbrains.kotlin.fir.symbols.impl.* import org.jetbrains.kotlin.fir.symbols.impl.*
import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
@@ -29,20 +26,16 @@ import org.jetbrains.kotlin.name.Name
@ThreadSafeMutableState @ThreadSafeMutableState
internal class LLFirProvider( internal class LLFirProvider(
@Suppress("UNUSED_PARAMETER") project: Project,
val session: FirSession, val session: FirSession,
@Suppress("UNUSED_PARAMETER") module: KtModule, private val moduleComponents: LLFirModuleResolveComponents,
val kotlinScopeProvider: FirKotlinScopeProvider,
firFileBuilder: FirFileBuilder,
val cache: ModuleFileCache,
private val declarationProvider: KotlinDeclarationProvider, private val declarationProvider: KotlinDeclarationProvider,
packageProvider: KotlinPackageProvider, packageProvider: KotlinPackageProvider,
) : FirProvider() { ) : FirProvider() {
override val symbolProvider: FirSymbolProvider = SymbolProvider() override val symbolProvider: FirSymbolProvider = SymbolProvider()
private val providerHelper = LLFirProviderHelper( private val providerHelper = LLFirProviderHelper(
cache, moduleComponents.cache,
firFileBuilder, moduleComponents.firFileBuilder,
declarationProvider, declarationProvider,
packageProvider, packageProvider,
) )
@@ -59,7 +52,7 @@ internal class LLFirProvider(
override fun getFirClassifierContainerFileIfAny(fqName: ClassId): FirFile? { override fun getFirClassifierContainerFileIfAny(fqName: ClassId): FirFile? {
val fir = getFirClassifierByFqName(fqName) ?: return null // Necessary to ensure cacheProvider contains this classifier val fir = getFirClassifierByFqName(fqName) ?: return null // Necessary to ensure cacheProvider contains this classifier
return cache.getContainerFirFile(fir) return moduleComponents.cache.getContainerFirFile(fir)
} }
override fun getFirClassifierContainerFile(symbol: FirClassLikeSymbol<*>): FirFile { override fun getFirClassifierContainerFile(symbol: FirClassLikeSymbol<*>): FirFile {
@@ -68,7 +61,7 @@ internal class LLFirProvider(
} }
override fun getFirClassifierContainerFileIfAny(symbol: FirClassLikeSymbol<*>): FirFile? = override fun getFirClassifierContainerFileIfAny(symbol: FirClassLikeSymbol<*>): FirFile? =
cache.getContainerFirFile(symbol.fir) moduleComponents.cache.getContainerFirFile(symbol.fir)
override fun getFirCallableContainerFile(symbol: FirCallableSymbol<*>): FirFile? { override fun getFirCallableContainerFile(symbol: FirCallableSymbol<*>): FirFile? {
@@ -81,7 +74,7 @@ internal class LLFirProvider(
return getFirCallableContainerFile(fir.getter.delegate.symbol) return getFirCallableContainerFile(fir.getter.delegate.symbol)
} }
} }
return cache.getContainerFirFile(symbol.fir) return moduleComponents.cache.getContainerFirFile(symbol.fir)
} }
override fun getFirFilesByPackage(fqName: FqName): List<FirFile> = error("Should not be called in FIR IDE") override fun getFirFilesByPackage(fqName: FqName): List<FirFile> = error("Should not be called in FIR IDE")
@@ -39,7 +39,7 @@ internal class LLFirProviderHelper(
null -> declarationProvider.getTypeAliasesByClassId(classId).firstOrNull() null -> declarationProvider.getTypeAliasesByClassId(classId).firstOrNull()
else -> if (klass.getClassId() == null) null else klass else -> if (klass.getClassId() == null) null else klass
} ?: return@computeIfAbsent Optional.empty() } ?: return@computeIfAbsent Optional.empty()
val firFile = firFileBuilder.buildRawFirFileWithCaching(ktClass.containingKtFile, cache) val firFile = firFileBuilder.buildRawFirFileWithCaching(ktClass.containingKtFile)
val classifier = FirElementFinder.findElementIn<FirClassLikeDeclaration>(firFile) { classifier -> val classifier = FirElementFinder.findElementIn<FirClassLikeDeclaration>(firFile) { classifier ->
classifier.symbol.classId == classId classifier.symbol.classId == classId
} }
@@ -61,7 +61,7 @@ internal class LLFirProviderHelper(
@OptIn(ExperimentalStdlibApi::class) @OptIn(ExperimentalStdlibApi::class)
buildList { buildList {
files.forEach { ktFile -> files.forEach { ktFile ->
val firFile = firFileBuilder.buildRawFirFileWithCaching(ktFile, cache) val firFile = firFileBuilder.buildRawFirFileWithCaching(ktFile)
firFile.collectCallableDeclarationsTo(this, name) firFile.collectCallableDeclarationsTo(this, name)
} }
} }
@@ -24,8 +24,6 @@ class SingleCandidateResolver(
private val firSession: FirSession, private val firSession: FirSession,
private val firFile: FirFile, private val firFile: FirFile,
) { ) {
private val scopeSession = ScopeSession()
private val bodyResolveComponents = createStubBodyResolveComponents(firSession) private val bodyResolveComponents = createStubBodyResolveComponents(firSession)
private val firCallCompleter = FirCallCompleter( private val firCallCompleter = FirCallCompleter(
bodyResolveComponents.transformer, bodyResolveComponents.transformer,
@@ -11,6 +11,6 @@ import org.jetbrains.kotlin.fir.PrivateSessionConstructor
@OptIn(PrivateSessionConstructor::class) @OptIn(PrivateSessionConstructor::class)
class LLFirBuiltinsAndCloneableSession @PrivateSessionConstructor constructor( class LLFirBuiltinsAndCloneableSession @PrivateSessionConstructor constructor(
override val project: Project, project: Project,
builtinTypes: BuiltinTypes, builtinTypes: BuiltinTypes,
) : LLFirSession(builtinTypes, Kind.Library) ) : LLFirLibraryLikeSession(project, builtinTypes)
@@ -14,6 +14,6 @@ import org.jetbrains.kotlin.fir.PrivateSessionConstructor
*/ */
@OptIn(PrivateSessionConstructor::class) @OptIn(PrivateSessionConstructor::class)
internal class LLFirLibrariesSession @PrivateSessionConstructor constructor( internal class LLFirLibrariesSession @PrivateSessionConstructor constructor(
override val project: Project, project: Project,
builtinTypes: BuiltinTypes, builtinTypes: BuiltinTypes,
) : LLFirSession(builtinTypes, Kind.Library) ) : LLFirLibraryLikeSession(project, builtinTypes)
@@ -0,0 +1,23 @@
/*
* 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.low.level.api.fir.sessions
import com.intellij.openapi.project.Project
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.LLFirScopeSessionProvider
import org.jetbrains.kotlin.fir.BuiltinTypes
import org.jetbrains.kotlin.fir.resolve.ScopeSession
abstract class LLFirLibraryLikeSession(
final override val project: Project,
builtinTypes: BuiltinTypes,
) : LLFirSession(builtinTypes, Kind.Library) {
private val scopeSessionProvider = LLFirScopeSessionProvider.create(project, invalidationTrackers = emptyList())
override fun getScopeSession(): ScopeSession {
return scopeSessionProvider.getScopeSession()
}
}
@@ -6,7 +6,8 @@
package org.jetbrains.kotlin.analysis.low.level.api.fir.sessions package org.jetbrains.kotlin.analysis.low.level.api.fir.sessions
import com.intellij.openapi.project.Project import com.intellij.openapi.project.Project
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.FirFileBuilder import org.jetbrains.kotlin.analysis.low.level.api.fir.LLFirGlobalResolveComponents
import org.jetbrains.kotlin.analysis.low.level.api.fir.LLFirModuleResolveComponents
import org.jetbrains.kotlin.analysis.project.structure.KtLibraryModule import org.jetbrains.kotlin.analysis.project.structure.KtLibraryModule
import org.jetbrains.kotlin.analysis.project.structure.KtLibrarySourceModule import org.jetbrains.kotlin.analysis.project.structure.KtLibrarySourceModule
import org.jetbrains.kotlin.analysis.project.structure.KtModule import org.jetbrains.kotlin.analysis.project.structure.KtModule
@@ -15,7 +16,7 @@ import org.jetbrains.kotlin.fir.BuiltinTypes
internal class LLFirLibraryOrLibrarySourceResolvableModuleSession( internal class LLFirLibraryOrLibrarySourceResolvableModuleSession(
override val module: KtModule, override val module: KtModule,
override val project: Project, override val project: Project,
override val firFileBuilder: FirFileBuilder, override val moduleComponents: LLFirModuleResolveComponents,
builtinTypes: BuiltinTypes, builtinTypes: BuiltinTypes,
) : LLFirResolvableModuleSession(builtinTypes) { ) : LLFirResolvableModuleSession(builtinTypes) {
init { init {
@@ -5,15 +5,27 @@
package org.jetbrains.kotlin.analysis.low.level.api.fir.sessions package org.jetbrains.kotlin.analysis.low.level.api.fir.sessions
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.FirFileBuilder import org.jetbrains.kotlin.analysis.low.level.api.fir.LLFirModuleResolveComponents
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.ModuleFileCache import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.ModuleFileCache
import org.jetbrains.kotlin.analysis.low.level.api.fir.providers.LLFirProvider import org.jetbrains.kotlin.analysis.low.level.api.fir.providers.LLFirProvider
import org.jetbrains.kotlin.fir.BuiltinTypes import org.jetbrains.kotlin.fir.BuiltinTypes
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
import org.jetbrains.kotlin.fir.resolve.ScopeSession
import org.jetbrains.kotlin.fir.resolve.providers.firProvider import org.jetbrains.kotlin.fir.resolve.providers.firProvider
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
internal abstract class LLFirResolvableModuleSession( abstract class LLFirResolvableModuleSession(
builtinTypes: BuiltinTypes, builtinTypes: BuiltinTypes,
) : LLFirModuleSession(builtinTypes, Kind.Source) { ) : LLFirModuleSession(builtinTypes, Kind.Source) {
internal val cache: ModuleFileCache get() = (firProvider as LLFirProvider).cache internal abstract val moduleComponents: LLFirModuleResolveComponents
abstract val firFileBuilder: FirFileBuilder
} final override fun getScopeSession(): ScopeSession {
return moduleComponents.scopeSessionProvider.getScopeSession()
}
}
internal val FirDeclaration.llFirResolvableSession: LLFirResolvableModuleSession?
get() = llFirSession as? LLFirResolvableModuleSession
internal val FirBasedSymbol<*>.llFirResolvableSession: LLFirResolvableModuleSession?
get() = fir.llFirResolvableSession
@@ -6,17 +6,30 @@
package org.jetbrains.kotlin.analysis.low.level.api.fir.sessions package org.jetbrains.kotlin.analysis.low.level.api.fir.sessions
import com.intellij.openapi.project.Project import com.intellij.openapi.project.Project
import org.jetbrains.kotlin.analysis.low.level.api.fir.project.structure.firModuleData
import org.jetbrains.kotlin.analysis.project.structure.KtModule import org.jetbrains.kotlin.analysis.project.structure.KtModule
import org.jetbrains.kotlin.fir.BuiltinTypes import org.jetbrains.kotlin.fir.BuiltinTypes
import org.jetbrains.kotlin.fir.FirElement
import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.PrivateSessionConstructor import org.jetbrains.kotlin.fir.PrivateSessionConstructor
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
import org.jetbrains.kotlin.fir.resolve.ScopeSession
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
@OptIn(PrivateSessionConstructor::class) @OptIn(PrivateSessionConstructor::class)
abstract class LLFirSession(override val builtinTypes: BuiltinTypes, kind: Kind) : FirSession(sessionProvider = null, kind) { abstract class LLFirSession(override val builtinTypes: BuiltinTypes, kind: Kind) : FirSession(sessionProvider = null, kind) {
abstract val project: Project abstract val project: Project
abstract fun getScopeSession(): ScopeSession
} }
@OptIn(PrivateSessionConstructor::class) @OptIn(PrivateSessionConstructor::class)
abstract class LLFirModuleSession(builtinTypes: BuiltinTypes, kind: Kind) : LLFirSession(builtinTypes, kind) { abstract class LLFirModuleSession(builtinTypes: BuiltinTypes, kind: Kind) : LLFirSession(builtinTypes, kind) {
abstract val module: KtModule abstract val module: KtModule
} }
val FirDeclaration.llFirSession: LLFirSession
get() = moduleData.session as LLFirSession
val FirBasedSymbol<*>.llFirSession: LLFirSession
get() = moduleData.session as LLFirSession
@@ -8,15 +8,14 @@ package org.jetbrains.kotlin.analysis.low.level.api.fir.sessions
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 com.intellij.psi.search.ProjectScope import com.intellij.psi.search.ProjectScope
import org.jetbrains.kotlin.analysis.low.level.api.fir.LLFirPhaseRunner
import org.jetbrains.kotlin.analysis.low.level.api.fir.LLFirPhaseManager import org.jetbrains.kotlin.analysis.low.level.api.fir.LLFirPhaseManager
import org.jetbrains.kotlin.analysis.low.level.api.fir.IdeSessionComponents import org.jetbrains.kotlin.analysis.low.level.api.fir.IdeSessionComponents
import org.jetbrains.kotlin.analysis.low.level.api.fir.LLFirGlobalResolveComponents
import org.jetbrains.kotlin.analysis.low.level.api.fir.LLFirModuleResolveComponents
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.services.createPackagePartProviderForLibrary import org.jetbrains.kotlin.analysis.low.level.api.fir.api.services.createPackagePartProviderForLibrary
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.services.createSealedInheritorsProvider import org.jetbrains.kotlin.analysis.low.level.api.fir.api.services.createSealedInheritorsProvider
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.FirFileBuilder
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.ModuleFileCacheImpl import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.ModuleFileCacheImpl
import org.jetbrains.kotlin.analysis.low.level.api.fir.fir.caches.FirThreadSafeCachesFactory import org.jetbrains.kotlin.analysis.low.level.api.fir.fir.caches.FirThreadSafeCachesFactory
import org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve.FirLazyDeclarationResolver
import org.jetbrains.kotlin.analysis.low.level.api.fir.project.structure.LLFirKtModuleBasedModuleData import org.jetbrains.kotlin.analysis.low.level.api.fir.project.structure.LLFirKtModuleBasedModuleData
import org.jetbrains.kotlin.analysis.low.level.api.fir.project.structure.LLFirBuiltinsModuleData import org.jetbrains.kotlin.analysis.low.level.api.fir.project.structure.LLFirBuiltinsModuleData
import org.jetbrains.kotlin.analysis.low.level.api.fir.providers.* import org.jetbrains.kotlin.analysis.low.level.api.fir.providers.*
@@ -74,7 +73,7 @@ internal object LLFirSessionFactory {
project: Project, project: Project,
module: KtSourceModule, module: KtSourceModule,
builtinsAndCloneableSession: LLFirBuiltinsAndCloneableSession, builtinsAndCloneableSession: LLFirBuiltinsAndCloneableSession,
firPhaseRunner: LLFirPhaseRunner, globalResolveComponents: LLFirGlobalResolveComponents,
sessionInvalidator: LLFirSessionInvalidator, sessionInvalidator: LLFirSessionInvalidator,
builtinTypes: BuiltinTypes, builtinTypes: BuiltinTypes,
sessionsCache: MutableMap<KtModule, LLFirResolvableModuleSession>, sessionsCache: MutableMap<KtModule, LLFirResolvableModuleSession>,
@@ -85,20 +84,20 @@ internal object LLFirSessionFactory {
sessionsCache[module]?.let { return it as LLFirSourcesSession } sessionsCache[module]?.let { return it as LLFirSourcesSession }
val languageVersionSettings = module.languageVersionSettings val languageVersionSettings = module.languageVersionSettings
val scopeProvider = FirKotlinScopeProvider(::wrapScopeWithJvmMapped) val scopeProvider = FirKotlinScopeProvider(::wrapScopeWithJvmMapped)
val firBuilder = FirFileBuilder(scopeProvider, firPhaseRunner)
val components = LLFirModuleResolveComponents(module, globalResolveComponents, scopeProvider)
val contentScope = module.contentScope val contentScope = module.contentScope
val dependentModules = module.directRegularDependenciesOfType<KtSourceModule>() val dependentModules = module.directRegularDependenciesOfType<KtSourceModule>()
val session = LLFirSourcesSession(module, project, firBuilder, builtinTypes) val session = LLFirSourcesSession(module, project, components, builtinTypes)
sessionsCache[module] = session sessionsCache[module] = session
components.session = session
return session.apply session@{ return session.apply session@{
val moduleData = LLFirKtModuleBasedModuleData(module).apply { bindSession(this@session) } val moduleData = LLFirKtModuleBasedModuleData(module).apply { bindSession(this@session) }
registerModuleData(moduleData) registerModuleData(moduleData)
register(FirKotlinScopeProvider::class, scopeProvider) register(FirKotlinScopeProvider::class, scopeProvider)
val cache = ModuleFileCacheImpl(this)
val firPhaseManager = LLFirPhaseManager(FirLazyDeclarationResolver(firFileBuilder), cache, sessionInvalidator)
registerIdeComponents(project) registerIdeComponents(project)
registerCommonComponents(languageVersionSettings) registerCommonComponents(languageVersionSettings)
registerCommonJavaComponents(JavaModuleResolver.getInstance(project)) registerCommonJavaComponents(JavaModuleResolver.getInstance(project))
@@ -106,12 +105,8 @@ internal object LLFirSessionFactory {
registerJavaSpecificResolveComponents() registerJavaSpecificResolveComponents()
val provider = LLFirProvider( val provider = LLFirProvider(
project,
this, this,
module, components,
scopeProvider,
firFileBuilder,
cache,
project.createDeclarationProvider(contentScope), project.createDeclarationProvider(contentScope),
project.createPackageProvider(contentScope), project.createPackageProvider(contentScope),
) )
@@ -119,7 +114,7 @@ internal object LLFirSessionFactory {
register(FirProvider::class, provider) register(FirProvider::class, provider)
register(LLFirProvider::class, provider) register(LLFirProvider::class, provider)
register(FirPhaseManager::class, firPhaseManager) register(FirPhaseManager::class, LLFirPhaseManager(sessionInvalidator))
@OptIn(ExperimentalStdlibApi::class) @OptIn(ExperimentalStdlibApi::class)
val dependentProviders = buildList { val dependentProviders = buildList {
@@ -140,7 +135,7 @@ internal object LLFirSessionFactory {
project, project,
it, it,
builtinsAndCloneableSession, builtinsAndCloneableSession,
firPhaseRunner, globalResolveComponents,
sessionInvalidator, sessionInvalidator,
builtinTypes, builtinTypes,
sessionsCache, sessionsCache,
@@ -330,7 +325,7 @@ internal object LLFirSessionFactory {
project: Project, project: Project,
module: KtModule, module: KtModule,
builtinsAndCloneableSession: LLFirBuiltinsAndCloneableSession, builtinsAndCloneableSession: LLFirBuiltinsAndCloneableSession,
firPhaseRunner: LLFirPhaseRunner, globalComponents: LLFirGlobalResolveComponents,
sessionInvalidator: LLFirSessionInvalidator, sessionInvalidator: LLFirSessionInvalidator,
builtinTypes: BuiltinTypes, builtinTypes: BuiltinTypes,
sessionsCache: MutableMap<KtModule, LLFirResolvableModuleSession>, sessionsCache: MutableMap<KtModule, LLFirResolvableModuleSession>,
@@ -348,19 +343,18 @@ internal object LLFirSessionFactory {
} }
val scopeProvider = FirKotlinScopeProvider() val scopeProvider = FirKotlinScopeProvider()
val firFileBuilder = FirFileBuilder(scopeProvider, firPhaseRunner) val components = LLFirModuleResolveComponents(module, globalComponents, scopeProvider)
val contentScope = module.contentScope val contentScope = module.contentScope
val session = LLFirLibraryOrLibrarySourceResolvableModuleSession(module, project, firFileBuilder, builtinTypes) val session = LLFirLibraryOrLibrarySourceResolvableModuleSession(module, project, components, builtinTypes)
sessionsCache[module] = session sessionsCache[module] = session
components.session = session
return session.apply session@{ return session.apply session@{
val moduleData = LLFirKtModuleBasedModuleData(module).apply { bindSession(this@session) } val moduleData = LLFirKtModuleBasedModuleData(module).apply { bindSession(this@session) }
registerModuleData(moduleData) registerModuleData(moduleData)
register(FirKotlinScopeProvider::class, scopeProvider) register(FirKotlinScopeProvider::class, scopeProvider)
val cache = ModuleFileCacheImpl(this)
val firPhaseManager = LLFirPhaseManager(FirLazyDeclarationResolver(firFileBuilder), cache, sessionInvalidator)
registerIdeComponents(project) registerIdeComponents(project)
registerCommonComponents(languageVersionSettings) registerCommonComponents(languageVersionSettings)
registerCommonJavaComponents(JavaModuleResolver.getInstance(project)) registerCommonJavaComponents(JavaModuleResolver.getInstance(project))
@@ -368,12 +362,8 @@ internal object LLFirSessionFactory {
registerJavaSpecificResolveComponents() registerJavaSpecificResolveComponents()
val provider = LLFirProvider( val provider = LLFirProvider(
project,
this, this,
module, components,
scopeProvider,
firFileBuilder,
cache,
project.createDeclarationProvider(contentScope), project.createDeclarationProvider(contentScope),
project.createPackageProvider(contentScope), project.createPackageProvider(contentScope),
) )
@@ -381,7 +371,7 @@ internal object LLFirSessionFactory {
register(FirProvider::class, provider) register(FirProvider::class, provider)
register(LLFirProvider::class, provider) register(LLFirProvider::class, provider)
register(FirPhaseManager::class, firPhaseManager) register(FirPhaseManager::class, LLFirPhaseManager(sessionInvalidator))
val dependentProviders = buildList { val dependentProviders = buildList {
val librariesSearchScope = ProjectScope.getLibrariesScope(project) val librariesSearchScope = ProjectScope.getLibrariesScope(project)
.intersectWith(GlobalSearchScope.notScope(libraryModule.contentScope)) // <all libraries scope> - <current library scope> .intersectWith(GlobalSearchScope.notScope(libraryModule.contentScope)) // <all libraries scope> - <current library scope>
@@ -8,7 +8,9 @@ package org.jetbrains.kotlin.analysis.low.level.api.fir.sessions
import com.intellij.openapi.project.Project import com.intellij.openapi.project.Project
import org.jetbrains.kotlin.analysis.api.impl.barebone.annotations.Immutable import org.jetbrains.kotlin.analysis.api.impl.barebone.annotations.Immutable
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.ModuleFileCache import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.ModuleFileCache
import org.jetbrains.kotlin.analysis.low.level.api.fir.project.structure.LLFirBuiltinsModuleData
import org.jetbrains.kotlin.analysis.low.level.api.fir.project.structure.LLFirKtModuleBasedModuleData import org.jetbrains.kotlin.analysis.low.level.api.fir.project.structure.LLFirKtModuleBasedModuleData
import org.jetbrains.kotlin.analysis.low.level.api.fir.project.structure.LLFirModuleData
import org.jetbrains.kotlin.analysis.project.structure.KtModule import org.jetbrains.kotlin.analysis.project.structure.KtModule
import org.jetbrains.kotlin.analysis.project.structure.NoCacheForModuleException import org.jetbrains.kotlin.analysis.project.structure.NoCacheForModuleException
import org.jetbrains.kotlin.analysis.utils.errors.requireIsInstance import org.jetbrains.kotlin.analysis.utils.errors.requireIsInstance
@@ -23,17 +25,16 @@ class LLFirSessionProvider internal constructor(
private val moduleToSession: Map<KtModule, LLFirResolvableModuleSession> private val moduleToSession: Map<KtModule, LLFirResolvableModuleSession>
) : FirSessionProvider() { ) : FirSessionProvider() {
override fun getSession(moduleData: FirModuleData): FirSession? { override fun getSession(moduleData: FirModuleData): LLFirSession {
requireIsInstance<LLFirKtModuleBasedModuleData>(moduleData) requireIsInstance<LLFirModuleData>(moduleData)
return moduleToSession[moduleData.ktModule] return when (moduleData) {
is LLFirBuiltinsModuleData -> moduleData.session as LLFirBuiltinsAndCloneableSession
is LLFirKtModuleBasedModuleData -> getSession(moduleData.ktModule)
}
} }
fun getSession(module: KtModule): FirSession? = fun getSession(module: KtModule): LLFirResolvableModuleSession =
moduleToSession[module] moduleToSession.getValue(module)
internal fun getModuleCache(module: KtModule): ModuleFileCache =
moduleToSession[module]?.cache
?: throw NoCacheForModuleException(module, moduleToSession.keys)
val allSessions: Collection<LLFirModuleSession> val allSessions: Collection<LLFirModuleSession>
get() = moduleToSession.values get() = moduleToSession.values
@@ -10,6 +10,7 @@ import com.intellij.openapi.util.ModificationTracker
import kotlinx.collections.immutable.PersistentMap import kotlinx.collections.immutable.PersistentMap
import kotlinx.collections.immutable.persistentMapOf import kotlinx.collections.immutable.persistentMapOf
import kotlinx.collections.immutable.toPersistentMap import kotlinx.collections.immutable.toPersistentMap
import org.jetbrains.kotlin.analysis.low.level.api.fir.LLFirGlobalResolveComponents
import org.jetbrains.kotlin.analysis.low.level.api.fir.LLFirPhaseRunner import org.jetbrains.kotlin.analysis.low.level.api.fir.LLFirPhaseRunner
import org.jetbrains.kotlin.analysis.low.level.api.fir.project.structure.firKtModuleBasedModuleData import org.jetbrains.kotlin.analysis.low.level.api.fir.project.structure.firKtModuleBasedModuleData
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.addValueFor import org.jetbrains.kotlin.analysis.low.level.api.fir.util.addValueFor
@@ -20,7 +21,7 @@ import org.jetbrains.kotlin.analysis.providers.createModuleWithoutDependenciesOu
import org.jetbrains.kotlin.analysis.utils.caches.getValue import org.jetbrains.kotlin.analysis.utils.caches.getValue
import org.jetbrains.kotlin.analysis.utils.caches.softCachedValue import org.jetbrains.kotlin.analysis.utils.caches.softCachedValue
import org.jetbrains.kotlin.fir.BuiltinTypes import org.jetbrains.kotlin.fir.BuiltinTypes
import org.jetbrains.kotlin.fir.moduleData import org.jetbrains.kotlin.fir.FirSessionProvider
import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.ConcurrentHashMap
class LLFirSessionProviderStorage(val project: Project) { class LLFirSessionProviderStorage(val project: Project) {
@@ -32,7 +33,7 @@ class LLFirSessionProviderStorage(val project: Project) {
rootModule: KtModule, rootModule: KtModule,
configureSession: (LLFirSession.() -> Unit)? = null configureSession: (LLFirSession.() -> Unit)? = null
): LLFirSessionProvider { ): LLFirSessionProvider {
val firPhaseRunner = LLFirPhaseRunner() val globalComponents = LLFirGlobalResolveComponents(rootModule, project)
val builtinTypes = BuiltinTypes() val builtinTypes = BuiltinTypes()
@@ -47,7 +48,7 @@ class LLFirSessionProviderStorage(val project: Project) {
project, project,
rootModule, rootModule,
builtinsAndCloneableSession, builtinsAndCloneableSession,
firPhaseRunner, globalComponents,
cache.sessionInvalidator, cache.sessionInvalidator,
builtinTypes, builtinTypes,
sessions, sessions,
@@ -61,7 +62,7 @@ class LLFirSessionProviderStorage(val project: Project) {
project, project,
rootModule, rootModule,
builtinsAndCloneableSession, builtinsAndCloneableSession,
firPhaseRunner, globalComponents,
cache.sessionInvalidator, cache.sessionInvalidator,
builtinTypes, builtinTypes,
sessions, sessions,
@@ -6,6 +6,7 @@
package org.jetbrains.kotlin.analysis.low.level.api.fir.sessions package org.jetbrains.kotlin.analysis.low.level.api.fir.sessions
import com.intellij.openapi.project.Project import com.intellij.openapi.project.Project
import org.jetbrains.kotlin.analysis.low.level.api.fir.LLFirModuleResolveComponents
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.FirFileBuilder import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.FirFileBuilder
import org.jetbrains.kotlin.analysis.project.structure.KtSourceModule import org.jetbrains.kotlin.analysis.project.structure.KtSourceModule
import org.jetbrains.kotlin.fir.BuiltinTypes import org.jetbrains.kotlin.fir.BuiltinTypes
@@ -14,6 +15,6 @@ import org.jetbrains.kotlin.fir.PrivateSessionConstructor
internal class LLFirSourcesSession @PrivateSessionConstructor constructor( internal class LLFirSourcesSession @PrivateSessionConstructor constructor(
override val module: KtSourceModule, override val module: KtSourceModule,
override val project: Project, override val project: Project,
override val firFileBuilder: FirFileBuilder, override val moduleComponents: LLFirModuleResolveComponents,
builtinTypes: BuiltinTypes, builtinTypes: BuiltinTypes,
) : LLFirResolvableModuleSession(builtinTypes) ) : LLFirResolvableModuleSession(builtinTypes)
@@ -6,6 +6,7 @@
package org.jetbrains.kotlin.analysis.low.level.api.fir.state package org.jetbrains.kotlin.analysis.low.level.api.fir.state
import com.intellij.openapi.project.Project import com.intellij.openapi.project.Project
import org.jetbrains.kotlin.analysis.low.level.api.fir.LLFirGlobalResolveComponents
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.DiagnosticCheckerFilter import org.jetbrains.kotlin.analysis.low.level.api.fir.api.DiagnosticCheckerFilter
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.FirFileBuilder import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.FirFileBuilder
import org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve.FirLazyDeclarationResolver import org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve.FirLazyDeclarationResolver
@@ -18,12 +19,11 @@ import org.jetbrains.kotlin.psi.KtFile
internal class LLFirLibraryOrLibrarySourceResolvableModuleResolveState( internal class LLFirLibraryOrLibrarySourceResolvableModuleResolveState(
override val globalComponents: LLFirGlobalResolveComponents,
override val project: Project, override val project: Project,
override val module: KtModule, override val module: KtModule,
sessionProvider: LLFirSessionProvider, sessionProvider: LLFirSessionProvider,
firFileBuilder: FirFileBuilder, ) : LLFirResolvableModuleResolveState(sessionProvider) {
firLazyDeclarationResolver: FirLazyDeclarationResolver,
) : LLFirResolvableModuleResolveState(sessionProvider, firFileBuilder, firLazyDeclarationResolver) {
override fun getDiagnostics(element: KtElement, filter: DiagnosticCheckerFilter): List<KtPsiDiagnostic> = override fun getDiagnostics(element: KtElement, filter: DiagnosticCheckerFilter): List<KtPsiDiagnostic> =
emptyList() emptyList()
@@ -5,23 +5,22 @@
package org.jetbrains.kotlin.analysis.low.level.api.fir.state package org.jetbrains.kotlin.analysis.low.level.api.fir.state
import org.jetbrains.kotlin.analysis.low.level.api.fir.LLFirGlobalResolveComponents
import org.jetbrains.kotlin.analysis.low.level.api.fir.LLFirModuleResolveComponents
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.LLFirModuleResolveState import org.jetbrains.kotlin.analysis.low.level.api.fir.api.LLFirModuleResolveState
import org.jetbrains.kotlin.analysis.low.level.api.fir.element.builder.FirElementBuilder
import org.jetbrains.kotlin.analysis.low.level.api.fir.element.builder.FirTowerContextProvider import org.jetbrains.kotlin.analysis.low.level.api.fir.element.builder.FirTowerContextProvider
import org.jetbrains.kotlin.analysis.low.level.api.fir.element.builder.getNonLocalContainingOrThisDeclaration import org.jetbrains.kotlin.analysis.low.level.api.fir.element.builder.getNonLocalContainingOrThisDeclaration
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.FirFileBuilder import org.jetbrains.kotlin.analysis.low.level.api.fir.project.structure.firModuleData
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.ModuleFileCache import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.LLFirResolvableModuleSession
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.structure.FileStructureCache import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.LLFirSession
import org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve.FirLazyDeclarationResolver
import org.jetbrains.kotlin.analysis.low.level.api.fir.providers.LLFirProvider
import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.LLFirSessionProvider import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.LLFirSessionProvider
import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.LLFirSourcesSession
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.FirDeclarationForCompiledElementSearcher import org.jetbrains.kotlin.analysis.low.level.api.fir.util.FirDeclarationForCompiledElementSearcher
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.findSourceNonLocalFirDeclaration import org.jetbrains.kotlin.analysis.low.level.api.fir.util.findSourceNonLocalFirDeclaration
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.getElementTextInContext import org.jetbrains.kotlin.analysis.low.level.api.fir.util.getElementTextInContext
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.originalDeclaration import org.jetbrains.kotlin.analysis.low.level.api.fir.util.originalDeclaration
import org.jetbrains.kotlin.analysis.project.structure.KtModule import org.jetbrains.kotlin.analysis.project.structure.KtModule
import org.jetbrains.kotlin.analysis.project.structure.getKtModule import org.jetbrains.kotlin.analysis.project.structure.getKtModule
import org.jetbrains.kotlin.analysis.utils.errors.requireIsInstance
import org.jetbrains.kotlin.fir.FirElement import org.jetbrains.kotlin.fir.FirElement
import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.FirDeclaration import org.jetbrains.kotlin.fir.declarations.FirDeclaration
@@ -36,36 +35,38 @@ import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.*
internal abstract class LLFirResolvableModuleResolveState( internal abstract class LLFirResolvableModuleResolveState(
protected val sessionProvider: LLFirSessionProvider, private val sessionProvider: LLFirSessionProvider,
val firFileBuilder: FirFileBuilder,
val firLazyDeclarationResolver: FirLazyDeclarationResolver,
) : LLFirModuleResolveState() { ) : LLFirModuleResolveState() {
final override val rootModuleSession = sessionProvider.rootModuleSession abstract val globalComponents: LLFirGlobalResolveComponents
val cache = (rootModuleSession.firProvider as LLFirProvider).cache
val fileStructureCache = FileStructureCache(firFileBuilder, firLazyDeclarationResolver) final override val rootModuleSession = sessionProvider.rootModuleSession
val elementBuilder = FirElementBuilder()
override fun getSessionFor(module: KtModule): FirSession = override fun getSessionFor(module: KtModule): FirSession =
sessionProvider.getSession(module)!! sessionProvider.getSession(module)
override fun getOrBuildFirFor(element: KtElement): FirElement? = override fun getScopeSessionFor(firSession: FirSession): ScopeSession {
elementBuilder.getOrBuildFirFor( requireIsInstance<LLFirSession>(firSession)
element = element, return firSession.getScopeSession()
firFileBuilder = firFileBuilder, }
moduleFileCache = cache,
fileStructureCache = fileStructureCache,
firLazyDeclarationResolver = firLazyDeclarationResolver,
state = this
)
override fun getOrBuildFirFor(element: KtElement): FirElement? {
val moduleComponents = getModuleComponentsForElement(element)
return moduleComponents.elementsBuilder.getOrBuildFirFor(element, this)
}
override fun getOrBuildFirFile(ktFile: KtFile): FirFile = override fun getOrBuildFirFile(ktFile: KtFile): FirFile {
firFileBuilder.buildRawFirFileWithCaching(ktFile, cache) val moduleComponents = getModuleComponentsForElement(ktFile)
return moduleComponents.firFileBuilder.buildRawFirFileWithCaching(ktFile)
}
override fun tryGetCachedFirFile(declaration: FirDeclaration, cache: ModuleFileCache): FirFile? = override fun tryGetCachedFirFile(declaration: FirDeclaration, cache: ModuleFileCache): FirFile? =
cache.getContainerFirFile(declaration) cache.getContainerFirFile(declaration)
protected fun getModuleComponentsForElement(element: KtElement): LLFirModuleResolveComponents {
val ktModule = element.getKtModule()
return sessionProvider.getSession(ktModule).moduleComponents
}
override fun resolveToFirSymbol( override fun resolveToFirSymbol(
ktDeclaration: KtDeclaration, ktDeclaration: KtDeclaration,
phase: FirResolvePhase phase: FirResolvePhase
@@ -102,10 +103,10 @@ internal abstract class LLFirResolvableModuleResolveState(
?: error("Declaration should have non-local container${ktDeclaration.getElementTextInContext()}") ?: error("Declaration should have non-local container${ktDeclaration.getElementTextInContext()}")
if (ktDeclaration == nonLocalNamedDeclaration) { if (ktDeclaration == nonLocalNamedDeclaration) {
val session = sessionProvider.getSession(module)
return nonLocalNamedDeclaration.findSourceNonLocalFirDeclaration( return nonLocalNamedDeclaration.findSourceNonLocalFirDeclaration(
firFileBuilder = firFileBuilder, firFileBuilder = session.moduleComponents.firFileBuilder,
firSymbolProvider = rootModuleSession.firProvider.symbolProvider, provider = session.firProvider,
moduleFileCache = sessionProvider.getModuleCache(module)
).symbol ).symbol
} }
@@ -126,14 +127,12 @@ internal abstract class LLFirResolvableModuleResolveState(
override fun resolveFirToPhase(declaration: FirDeclaration, toPhase: FirResolvePhase) { override fun resolveFirToPhase(declaration: FirDeclaration, toPhase: FirResolvePhase) {
if (toPhase == FirResolvePhase.RAW_FIR) return if (toPhase == FirResolvePhase.RAW_FIR) return
val fileCache = when (val session = declaration.moduleData.session) { val llFirResolvableModuleSession = declaration.firModuleData.session as? LLFirResolvableModuleSession ?: return
is LLFirSourcesSession -> session.cache
else -> return val moduleComponents = llFirResolvableModuleSession.moduleComponents
} moduleComponents.lazyFirDeclarationsResolver.lazyResolveDeclaration(
firLazyDeclarationResolver.lazyResolveDeclaration(
firDeclarationToResolve = declaration, firDeclarationToResolve = declaration,
moduleFileCache = fileCache, scopeSession = moduleComponents.scopeSessionProvider.getScopeSession(),
scopeSession = ScopeSession(),
toPhase = toPhase, toPhase = toPhase,
checkPCE = true, checkPCE = true,
) )
@@ -6,6 +6,7 @@
package org.jetbrains.kotlin.analysis.low.level.api.fir.state package org.jetbrains.kotlin.analysis.low.level.api.fir.state
import com.intellij.openapi.project.Project import com.intellij.openapi.project.Project
import org.jetbrains.kotlin.analysis.low.level.api.fir.LLFirGlobalResolveComponents
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.DiagnosticCheckerFilter import org.jetbrains.kotlin.analysis.low.level.api.fir.api.DiagnosticCheckerFilter
import org.jetbrains.kotlin.analysis.low.level.api.fir.diagnostics.DiagnosticsCollector import org.jetbrains.kotlin.analysis.low.level.api.fir.diagnostics.DiagnosticsCollector
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.FirFileBuilder import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.FirFileBuilder
@@ -20,19 +21,20 @@ import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.psi.KtFile
internal class LLFirSourceModuleResolveState( internal class LLFirSourceModuleResolveState(
override val globalComponents: LLFirGlobalResolveComponents,
override val project: Project, override val project: Project,
override val module: KtModule, override val module: KtModule,
sessionProvider: LLFirSessionProvider, sessionProvider: LLFirSessionProvider,
firFileBuilder: FirFileBuilder, ) : LLFirResolvableModuleResolveState(sessionProvider) {
firLazyDeclarationResolver: FirLazyDeclarationResolver, override fun getDiagnostics(element: KtElement, filter: DiagnosticCheckerFilter): List<KtPsiDiagnostic> {
) : LLFirResolvableModuleResolveState(sessionProvider, firFileBuilder, firLazyDeclarationResolver) { val moduleComponents = getModuleComponentsForElement(element)
private val diagnosticsCollector = DiagnosticsCollector(fileStructureCache, cache) return moduleComponents.diagnosticsCollector.getDiagnosticsFor(element, filter)
}
override fun getDiagnostics(element: KtElement, filter: DiagnosticCheckerFilter): List<KtPsiDiagnostic> = override fun collectDiagnosticsForFile(ktFile: KtFile, filter: DiagnosticCheckerFilter): Collection<KtPsiDiagnostic> {
diagnosticsCollector.getDiagnosticsFor(element, filter) val moduleComponents = getModuleComponentsForElement(ktFile)
return moduleComponents.diagnosticsCollector.collectDiagnosticsForFile(ktFile, filter)
override fun collectDiagnosticsForFile(ktFile: KtFile, filter: DiagnosticCheckerFilter): Collection<KtPsiDiagnostic> = }
diagnosticsCollector.collectDiagnosticsForFile(ktFile, filter)
override fun getModuleKind(module: KtModule): ModuleKind { override fun getModuleKind(module: KtModule): ModuleKind {
return when (module) { return when (module) {
@@ -17,10 +17,12 @@ import org.jetbrains.kotlin.analysis.low.level.api.fir.LLFirPhaseRunner
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.FirDeclarationDesignation import org.jetbrains.kotlin.analysis.low.level.api.fir.api.FirDeclarationDesignation
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.FirDeclarationDesignationWithFile import org.jetbrains.kotlin.analysis.low.level.api.fir.api.FirDeclarationDesignationWithFile
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.collectDesignation import org.jetbrains.kotlin.analysis.low.level.api.fir.api.collectDesignation
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.LockProvider
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.ModuleFileCache import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.ModuleFileCache
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.runCustomResolveUnderLock import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.runCustomResolveUnderLock
import org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve.FirLazyDeclarationResolver import org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve.FirLazyDeclarationResolver
import org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve.ResolveTreeBuilder import org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve.ResolveTreeBuilder
import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.llFirResolvableSession
import org.jetbrains.kotlin.analysis.low.level.api.fir.transformers.LLFirLazyTransformer.Companion.updatePhaseDeep import org.jetbrains.kotlin.analysis.low.level.api.fir.transformers.LLFirLazyTransformer.Companion.updatePhaseDeep
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.checkCanceled import org.jetbrains.kotlin.analysis.low.level.api.fir.util.checkCanceled
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.ensurePhase import org.jetbrains.kotlin.analysis.low.level.api.fir.util.ensurePhase
@@ -32,8 +34,8 @@ internal class LLFirDesignatedSupertypeResolverTransformer(
private val designation: FirDeclarationDesignationWithFile, private val designation: FirDeclarationDesignationWithFile,
private val session: FirSession, private val session: FirSession,
private val scopeSession: ScopeSession, private val scopeSession: ScopeSession,
private val moduleFileCache: ModuleFileCache,
private val firLazyDeclarationResolver: FirLazyDeclarationResolver, private val firLazyDeclarationResolver: FirLazyDeclarationResolver,
private val lockProvider: LockProvider<FirFile>,
private val firProviderInterceptor: FirProviderInterceptor?, private val firProviderInterceptor: FirProviderInterceptor?,
private val checkPCE: Boolean, private val checkPCE: Boolean,
) : LLFirLazyTransformer { ) : LLFirLazyTransformer {
@@ -80,10 +82,9 @@ internal class LLFirDesignatedSupertypeResolverTransformer(
for (nowVisit in toVisit) { for (nowVisit in toVisit) {
if (checkPCE) checkCanceled() if (checkPCE) checkCanceled()
val resolver = DesignatedFirSupertypeResolverVisitor(nowVisit) val resolver = DesignatedFirSupertypeResolverVisitor(nowVisit)
moduleFileCache.firFileLockProvider.runCustomResolveUnderLock(nowVisit.firFile, checkPCE) { lockProvider.runCustomResolveUnderLock(nowVisit.firFile, checkPCE) {
firLazyDeclarationResolver.lazyResolveFileDeclaration( firLazyDeclarationResolver.lazyResolveFileDeclaration(
firFile = nowVisit.firFile, firFile = nowVisit.firFile,
moduleFileCache = moduleFileCache,
toPhase = FirResolvePhase.IMPORTS, toPhase = FirResolvePhase.IMPORTS,
scopeSession = scopeSession, scopeSession = scopeSession,
checkPCE = true, checkPCE = true,
@@ -102,7 +103,8 @@ internal class LLFirDesignatedSupertypeResolverTransformer(
if (classLikeDeclaration !is FirClassLikeDeclaration) continue if (classLikeDeclaration !is FirClassLikeDeclaration) continue
if (classLikeDeclaration is FirJavaClass) continue if (classLikeDeclaration is FirJavaClass) continue
if (visited.containsKey(classLikeDeclaration)) continue if (visited.containsKey(classLikeDeclaration)) continue
val containingFile = moduleFileCache.getContainerFirFile(classLikeDeclaration) ?: continue val cache = classLikeDeclaration.llFirResolvableSession?.moduleComponents?.cache ?: continue
val containingFile = cache.getContainerFirFile(classLikeDeclaration) ?: continue
toVisit.add(classLikeDeclaration.collectDesignation(containingFile)) toVisit.add(classLikeDeclaration.collectDesignation(containingFile))
} }
} }
@@ -123,7 +125,7 @@ internal class LLFirDesignatedSupertypeResolverTransformer(
val filesToDesignations = visited.groupBy { it.firFile } val filesToDesignations = visited.groupBy { it.firFile }
for (designationsPerFile in filesToDesignations) { for (designationsPerFile in filesToDesignations) {
if (checkPCE) checkCanceled() if (checkPCE) checkCanceled()
moduleFileCache.firFileLockProvider.runCustomResolveUnderLock(designationsPerFile.key, checkPCE) { lockProvider.runCustomResolveUnderLock(designationsPerFile.key, checkPCE) {
applyToFileSymbols(designationsPerFile.value) applyToFileSymbols(designationsPerFile.value)
} }
} }
@@ -18,7 +18,6 @@ internal object LazyTransformerFactory {
phase: FirResolvePhase, phase: FirResolvePhase,
designation: FirDeclarationDesignationWithFile, designation: FirDeclarationDesignationWithFile,
scopeSession: ScopeSession, scopeSession: ScopeSession,
moduleFileCache: ModuleFileCache,
lazyDeclarationResolver: FirLazyDeclarationResolver, lazyDeclarationResolver: FirLazyDeclarationResolver,
towerDataContextCollector: FirTowerDataContextCollector?, towerDataContextCollector: FirTowerDataContextCollector?,
firProviderInterceptor: FirProviderInterceptor?, firProviderInterceptor: FirProviderInterceptor?,
@@ -33,8 +32,8 @@ internal object LazyTransformerFactory {
designation = designation, designation = designation,
session = designation.firFile.moduleData.session, session = designation.firFile.moduleData.session,
scopeSession = scopeSession, scopeSession = scopeSession,
moduleFileCache = moduleFileCache,
firLazyDeclarationResolver = lazyDeclarationResolver, firLazyDeclarationResolver = lazyDeclarationResolver,
lockProvider = lazyDeclarationResolver.moduleComponents.globalResolveComponents.lockProvider,
firProviderInterceptor = firProviderInterceptor, firProviderInterceptor = firProviderInterceptor,
checkPCE = checkPCE, checkPCE = checkPCE,
) )
@@ -0,0 +1,51 @@
/*
* 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.low.level.api.fir.util
import com.intellij.openapi.project.Project
import com.intellij.openapi.roots.ProjectRootModificationTracker
import com.intellij.psi.util.PsiModificationTracker
import org.jetbrains.kotlin.analysis.utils.caches.getValue
import org.jetbrains.kotlin.analysis.utils.caches.softCachedValue
import org.jetbrains.kotlin.fir.resolve.ScopeSession
import java.util.concurrent.ConcurrentHashMap
abstract class LLFirScopeSessionProvider {
abstract fun getScopeSession(): ScopeSession
companion object {
fun create(project: Project, invalidationTrackers: List<Any>): LLFirScopeSessionProvider = when {
invalidationTrackers.isEmpty() -> LLFirNonInvalidatableScopeSessionProvider()
else -> LLFirInvalidatableScopeSessionProvider(project, invalidationTrackers)
}
}
}
private class LLFirInvalidatableScopeSessionProvider(project: Project, invalidationTrackers: List<Any>) : LLFirScopeSessionProvider() {
// ScopeSession is thread-local, so we use Thread id as a key
// We cannot use thread locals here as it may lead to memory leaks
private val cache by softCachedValue(
project,
*invalidationTrackers.toTypedArray(),
) {
ConcurrentHashMap<Long, ScopeSession>()
}
override fun getScopeSession(): ScopeSession {
return cache.getOrPut(Thread.currentThread().id) { ScopeSession() }
}
}
private class LLFirNonInvalidatableScopeSessionProvider : LLFirScopeSessionProvider() {
// ScopeSession is thread-local, so we use Thread id as a key
// We cannot use thread locals here as it may lead to memory leaks
private val cache = ConcurrentHashMap<Long, ScopeSession>()
override fun getScopeSession(): ScopeSession {
return cache.getOrPut(Thread.currentThread().id) { ScopeSession() }
}
}
@@ -8,13 +8,13 @@ package org.jetbrains.kotlin.analysis.low.level.api.fir.util
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.throwUnexpectedFirElementError import org.jetbrains.kotlin.analysis.low.level.api.fir.api.throwUnexpectedFirElementError
import org.jetbrains.kotlin.analysis.low.level.api.fir.element.builder.getNonLocalContainingOrThisDeclaration import org.jetbrains.kotlin.analysis.low.level.api.fir.element.builder.getNonLocalContainingOrThisDeclaration
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.FirFileBuilder import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.FirFileBuilder
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.ModuleFileCache
import org.jetbrains.kotlin.fir.declarations.FirClassLikeDeclaration 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.declarations.FirRegularClass import org.jetbrains.kotlin.fir.declarations.FirRegularClass
import org.jetbrains.kotlin.fir.psi import org.jetbrains.kotlin.fir.psi
import org.jetbrains.kotlin.fir.realPsi import org.jetbrains.kotlin.fir.realPsi
import org.jetbrains.kotlin.fir.resolve.providers.FirProvider
import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider
import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject
@@ -24,24 +24,22 @@ import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject
*/ */
internal fun KtDeclaration.findSourceNonLocalFirDeclaration( internal fun KtDeclaration.findSourceNonLocalFirDeclaration(
firFileBuilder: FirFileBuilder, firFileBuilder: FirFileBuilder,
firSymbolProvider: FirSymbolProvider, provider: FirProvider,
moduleFileCache: ModuleFileCache,
containerFirFile: FirFile? = null containerFirFile: FirFile? = null
): FirDeclaration { ): FirDeclaration {
//TODO test what way faster //TODO test what way faster
findSourceNonLocalFirDeclarationByProvider(firFileBuilder, firSymbolProvider, moduleFileCache, containerFirFile)?.let { return it } findSourceNonLocalFirDeclarationByProvider(firFileBuilder, provider, containerFirFile)?.let { return it }
findSourceOfNonLocalFirDeclarationByTraversingWholeTree(firFileBuilder, moduleFileCache, containerFirFile)?.let { return it } findSourceOfNonLocalFirDeclarationByTraversingWholeTree(firFileBuilder, containerFirFile)?.let { return it }
error("No fir element was found for\n${getElementTextInContext()}") error("No fir element was found for\n${getElementTextInContext()}")
} }
internal fun KtDeclaration.findFirDeclarationForAnyFirSourceDeclaration( internal fun KtDeclaration.findFirDeclarationForAnyFirSourceDeclaration(
firFileBuilder: FirFileBuilder, firFileBuilder: FirFileBuilder,
firSymbolProvider: FirSymbolProvider, provider: FirProvider,
moduleFileCache: ModuleFileCache
): FirDeclaration { ): FirDeclaration {
val nonLocalDeclaration = getNonLocalContainingOrThisDeclaration() val nonLocalDeclaration = getNonLocalContainingOrThisDeclaration()
?.findSourceNonLocalFirDeclaration(firFileBuilder, firSymbolProvider, moduleFileCache) ?.findSourceNonLocalFirDeclaration(firFileBuilder, provider)
?: firFileBuilder.buildRawFirFileWithCaching(containingKtFile, moduleFileCache) ?: firFileBuilder.buildRawFirFileWithCaching(containingKtFile)
val originalDeclaration = originalDeclaration val originalDeclaration = originalDeclaration
val fir = FirElementFinder.findElementIn<FirDeclaration>(nonLocalDeclaration) { firDeclaration -> val fir = FirElementFinder.findElementIn<FirDeclaration>(nonLocalDeclaration) { firDeclaration ->
firDeclaration.psi == this || firDeclaration.psi == originalDeclaration firDeclaration.psi == this || firDeclaration.psi == originalDeclaration
@@ -52,20 +50,18 @@ internal fun KtDeclaration.findFirDeclarationForAnyFirSourceDeclaration(
internal inline fun <reified F : FirDeclaration> KtDeclaration.findFirDeclarationForAnyFirSourceDeclarationOfType( internal inline fun <reified F : FirDeclaration> KtDeclaration.findFirDeclarationForAnyFirSourceDeclarationOfType(
firFileBuilder: FirFileBuilder, firFileBuilder: FirFileBuilder,
firSymbolProvider: FirSymbolProvider, provider: FirProvider,
moduleFileCache: ModuleFileCache
): FirDeclaration { ): FirDeclaration {
val fir = findFirDeclarationForAnyFirSourceDeclaration(firFileBuilder, firSymbolProvider, moduleFileCache) val fir = findFirDeclarationForAnyFirSourceDeclaration(firFileBuilder, provider)
if (fir !is F) throwUnexpectedFirElementError(fir, this, F::class) if (fir !is F) throwUnexpectedFirElementError(fir, this, F::class)
return fir return fir
} }
private fun KtDeclaration.findSourceOfNonLocalFirDeclarationByTraversingWholeTree( private fun KtDeclaration.findSourceOfNonLocalFirDeclarationByTraversingWholeTree(
firFileBuilder: FirFileBuilder, firFileBuilder: FirFileBuilder,
moduleFileCache: ModuleFileCache,
containerFirFile: FirFile?, containerFirFile: FirFile?,
): FirDeclaration? { ): FirDeclaration? {
val firFile = containerFirFile ?: firFileBuilder.buildRawFirFileWithCaching(containingKtFile, moduleFileCache) val firFile = containerFirFile ?: firFileBuilder.buildRawFirFileWithCaching(containingKtFile)
val originalDeclaration = originalDeclaration val originalDeclaration = originalDeclaration
return FirElementFinder.findElementIn(firFile, goInside = { it is FirRegularClass }) { firDeclaration -> return FirElementFinder.findElementIn(firFile, goInside = { it is FirRegularClass }) { firDeclaration ->
firDeclaration.psi == this || firDeclaration.psi == originalDeclaration firDeclaration.psi == this || firDeclaration.psi == originalDeclaration
@@ -74,20 +70,19 @@ private fun KtDeclaration.findSourceOfNonLocalFirDeclarationByTraversingWholeTre
private fun KtDeclaration.findSourceNonLocalFirDeclarationByProvider( private fun KtDeclaration.findSourceNonLocalFirDeclarationByProvider(
firFileBuilder: FirFileBuilder, firFileBuilder: FirFileBuilder,
firSymbolProvider: FirSymbolProvider, provider: FirProvider,
moduleFileCache: ModuleFileCache,
containerFirFile: FirFile? containerFirFile: FirFile?
): FirDeclaration? { ): FirDeclaration? {
val candidate = when { val candidate = when {
this is KtClassOrObject -> findFir(firSymbolProvider) this is KtClassOrObject -> findFir(provider)
this is KtNamedDeclaration && (this is KtProperty || this is KtNamedFunction) -> { this is KtNamedDeclaration && (this is KtProperty || this is KtNamedFunction) -> {
val containerClass = containingClassOrObject val containerClass = containingClassOrObject
val declarations = if (containerClass != null) { val declarations = if (containerClass != null) {
val containerClassFir = containerClass.findFir(firSymbolProvider) as? FirRegularClass val containerClassFir = containerClass.findFir(provider) as? FirRegularClass
containerClassFir?.declarations containerClassFir?.declarations
} else { } else {
val ktFile = containingKtFile val ktFile = containingKtFile
val firFile = containerFirFile ?: firFileBuilder.buildRawFirFileWithCaching(ktFile, moduleFileCache) val firFile = containerFirFile ?: firFileBuilder.buildRawFirFileWithCaching(ktFile)
firFile.declarations firFile.declarations
} }
val original = originalDeclaration val original = originalDeclaration
@@ -101,10 +96,10 @@ private fun KtDeclaration.findSourceNonLocalFirDeclarationByProvider(
this is KtConstructor<*> -> { this is KtConstructor<*> -> {
val containingClass = containingClassOrObject val containingClass = containingClassOrObject
?: error("Container class should be not null for KtConstructor") ?: error("Container class should be not null for KtConstructor")
val containerClassFir = containingClass.findFir(firSymbolProvider) as? FirRegularClass ?: return null val containerClassFir = containingClass.findFir(provider) as? FirRegularClass ?: return null
containerClassFir.declarations.firstOrNull { it.psi === this } containerClassFir.declarations.firstOrNull { it.psi === this }
} }
this is KtTypeAlias -> findFir(firSymbolProvider) this is KtTypeAlias -> findFir(provider)
else -> error("Invalid container ${this::class}\n${getElementTextInContext()}") else -> error("Invalid container ${this::class}\n${getElementTextInContext()}")
} }
return candidate?.takeIf { it.realPsi == this } return candidate?.takeIf { it.realPsi == this }
@@ -117,10 +112,10 @@ private val ORIGINAL_KT_FILE_KEY = com.intellij.openapi.util.Key<KtFile>("ORIGIN
var KtFile.originalKtFile by UserDataProperty(ORIGINAL_KT_FILE_KEY) var KtFile.originalKtFile by UserDataProperty(ORIGINAL_KT_FILE_KEY)
private fun KtClassLikeDeclaration.findFir(firSymbolProvider: FirSymbolProvider): FirClassLikeDeclaration? { private fun KtClassLikeDeclaration.findFir(provider: FirProvider): FirClassLikeDeclaration? {
val classId = getClassId() ?: return null val classId = getClassId() ?: return null
return executeWithoutPCE { return executeWithoutPCE {
firSymbolProvider.getClassLikeSymbolByClassId(classId)?.fir as? FirRegularClass provider.getFirClassifierByFqName(classId) as? FirRegularClass
} }
} }
@@ -15,6 +15,7 @@ import org.jetbrains.kotlin.analysis.low.level.api.fir.state.LLFirSourceModuleRe
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.DiagnosticCheckerFilter import org.jetbrains.kotlin.analysis.low.level.api.fir.api.DiagnosticCheckerFilter
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.getDiagnostics import org.jetbrains.kotlin.analysis.low.level.api.fir.api.getDiagnostics
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.getOrBuildFirFile import org.jetbrains.kotlin.analysis.low.level.api.fir.api.getOrBuildFirFile
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.getResolveState
import org.jetbrains.kotlin.analysis.low.level.api.fir.diagnostics.BeforeElementDiagnosticCollectionHandler import org.jetbrains.kotlin.analysis.low.level.api.fir.diagnostics.BeforeElementDiagnosticCollectionHandler
import org.jetbrains.kotlin.analysis.low.level.api.fir.diagnostics.fir.PersistenceContextCollector import org.jetbrains.kotlin.analysis.low.level.api.fir.diagnostics.fir.PersistenceContextCollector
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.structure.FileStructureElement import org.jetbrains.kotlin.analysis.low.level.api.fir.file.structure.FileStructureElement
@@ -23,7 +24,9 @@ import org.jetbrains.kotlin.analysis.low.level.api.fir.file.structure.Reanalyzab
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.structure.RootStructureElement import org.jetbrains.kotlin.analysis.low.level.api.fir.file.structure.RootStructureElement
import org.jetbrains.kotlin.analysis.low.level.api.fir.name import org.jetbrains.kotlin.analysis.low.level.api.fir.name
import org.jetbrains.kotlin.analysis.low.level.api.fir.resolveWithClearCaches import org.jetbrains.kotlin.analysis.low.level.api.fir.resolveWithClearCaches
import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.LLFirResolvableModuleSession
import org.jetbrains.kotlin.analysis.low.level.api.fir.test.base.AbstractLowLevelApiSingleFileTest import org.jetbrains.kotlin.analysis.low.level.api.fir.test.base.AbstractLowLevelApiSingleFileTest
import org.jetbrains.kotlin.analysis.project.structure.getKtModule
import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.test.services.AssertionsService import org.jetbrains.kotlin.test.services.AssertionsService
import org.jetbrains.kotlin.test.services.TestModuleStructure import org.jetbrains.kotlin.test.services.TestModuleStructure
@@ -43,7 +46,10 @@ abstract class AbstractFirContextCollectionTest : AbstractLowLevelApiSingleFileT
) { resolveState -> ) { resolveState ->
check(resolveState is LLFirSourceModuleResolveState) check(resolveState is LLFirSourceModuleResolveState)
val fileStructure = resolveState.fileStructureCache.getFileStructure(ktFile, resolveState.cache) val session = resolveState.getSessionFor(ktFile.getKtModule()) as LLFirResolvableModuleSession
val fileStructureCache = session.moduleComponents.fileStructureCache
val fileStructure = fileStructureCache.getFileStructure(ktFile)
val allStructureElements = fileStructure.getAllStructureElements() val allStructureElements = fileStructure.getAllStructureElements()
handler.elementsToCheckContext = allStructureElements.map { it.getFirDeclaration() } handler.elementsToCheckContext = allStructureElements.map { it.getFirDeclaration() }
@@ -11,7 +11,9 @@ import com.intellij.psi.PsiElementVisitor
import com.intellij.psi.impl.source.tree.LeafPsiElement import com.intellij.psi.impl.source.tree.LeafPsiElement
import org.jetbrains.kotlin.analysis.low.level.api.fir.state.LLFirSourceModuleResolveState import org.jetbrains.kotlin.analysis.low.level.api.fir.state.LLFirSourceModuleResolveState
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.getResolveState import org.jetbrains.kotlin.analysis.low.level.api.fir.api.getResolveState
import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.LLFirResolvableModuleSession
import org.jetbrains.kotlin.analysis.low.level.api.fir.test.base.AbstractLowLevelApiSingleFileTest import org.jetbrains.kotlin.analysis.low.level.api.fir.test.base.AbstractLowLevelApiSingleFileTest
import org.jetbrains.kotlin.analysis.project.structure.getKtModule
import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.forEachDescendantOfType import org.jetbrains.kotlin.psi.psiUtil.forEachDescendantOfType
import org.jetbrains.kotlin.test.KotlinTestUtils import org.jetbrains.kotlin.test.KotlinTestUtils
@@ -86,10 +88,8 @@ abstract class AbstractFileStructureTest : AbstractLowLevelApiSingleFileTest() {
private fun KtFile.getFileStructure(): FileStructure { private fun KtFile.getFileStructure(): FileStructure {
val moduleResolveState = getResolveState() as LLFirSourceModuleResolveState val moduleResolveState = getResolveState() as LLFirSourceModuleResolveState
return moduleResolveState.fileStructureCache.getFileStructure( val session = moduleResolveState.getSessionFor(getKtModule()) as LLFirResolvableModuleSession
ktFile = this, return session.moduleComponents.fileStructureCache.getFileStructure(this)
moduleFileCache = moduleResolveState.cache
)
} }
@OptIn(ExperimentalStdlibApi::class) @OptIn(ExperimentalStdlibApi::class)