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