FIR IDE: separate fir session for current module from dependent modules session

This commit is contained in:
Ilya Kirillov
2020-09-04 12:22:32 +03:00
parent ab897752de
commit 07be30c5db
14 changed files with 185 additions and 87 deletions
@@ -297,14 +297,14 @@ private fun Module.hasTestRoots() =
private fun Module.hasRootsOfType(sourceRootType: JpsModuleSourceRootType<*>): Boolean = private fun Module.hasRootsOfType(sourceRootType: JpsModuleSourceRootType<*>): Boolean =
rootManager.contentEntries.any { it.getSourceFolders(sourceRootType).isNotEmpty() } rootManager.contentEntries.any { it.getSourceFolders(sourceRootType).isNotEmpty() }
private abstract class ModuleSourceScope(val module: Module) : GlobalSearchScope(module.project) { abstract class ModuleSourceScope(val module: Module) : GlobalSearchScope(module.project) {
override fun compare(file1: VirtualFile, file2: VirtualFile) = 0 override fun compare(file1: VirtualFile, file2: VirtualFile) = 0
override fun isSearchInModuleContent(aModule: Module) = aModule == module override fun isSearchInModuleContent(aModule: Module) = aModule == module
override fun isSearchInLibraries() = false override fun isSearchInLibraries() = false
} }
@Suppress("EqualsOrHashCode") // DelegatingGlobalSearchScope requires to provide calcHashCode() @Suppress("EqualsOrHashCode") // DelegatingGlobalSearchScope requires to provide calcHashCode()
private class ModuleProductionSourceScope(module: Module) : ModuleSourceScope(module) { class ModuleProductionSourceScope(module: Module) : ModuleSourceScope(module) {
val moduleFileIndex = ModuleRootManager.getInstance(module).fileIndex val moduleFileIndex = ModuleRootManager.getInstance(module).fileIndex
override fun equals(other: Any?): Boolean { override fun equals(other: Any?): Boolean {
@@ -31,6 +31,7 @@ internal class FirIdeResolveStateService(private val project: Project) {
ConcurrentHashMap<IdeaModuleInfo, FirIdeLibrariesSession>() ConcurrentHashMap<IdeaModuleInfo, FirIdeLibrariesSession>()
} }
private fun createResolveStateFor(moduleInfo: IdeaModuleInfo): FirModuleResolveStateImpl { private fun createResolveStateFor(moduleInfo: IdeaModuleInfo): FirModuleResolveStateImpl {
require(moduleInfo is ModuleSourceInfo) require(moduleInfo is ModuleSourceInfo)
val firPhaseRunner = FirPhaseRunner() val firPhaseRunner = FirPhaseRunner()
@@ -39,27 +40,32 @@ internal class FirIdeResolveStateService(private val project: Project) {
val librariesSession = librarySessionCache.computeIfAbsent(moduleInfo) { val librariesSession = librarySessionCache.computeIfAbsent(moduleInfo) {
FirIdeSessionFactory.createLibrarySession(moduleInfo, sessionProvider, project) FirIdeSessionFactory.createLibrarySession(moduleInfo, sessionProvider, project)
} }
val sourcesSession = FirIdeSessionFactory.createSourcesSession(
val dependentModulesSession = FirIdeSessionFactory.createDependentModulesSourcesSession(
project, project,
moduleInfo, moduleInfo,
firPhaseRunner, firPhaseRunner,
sessionProvider, sessionProvider,
librariesSession, librariesSession,
) )
val currentModuleSession = FirIdeSessionFactory.createCurrentModuleSourcesSession(
project,
moduleInfo,
firPhaseRunner,
dependentModulesSession,
sessionProvider,
)
sessionProvider.apply { sessionProvider.init(currentModuleSession, dependentModulesSession, librariesSession)
setSourcesSession(sourcesSession)
setLibrariesSession(librariesSession)
}
return FirModuleResolveStateImpl( return FirModuleResolveStateImpl(
moduleInfo, moduleInfo,
sourcesSession, currentModuleSession,
dependentModulesSession,
librariesSession, librariesSession,
sessionProvider, sessionProvider,
sourcesSession.firFileBuilder, currentModuleSession.firFileBuilder,
FirLazyDeclarationResolver(sourcesSession.firFileBuilder), FirLazyDeclarationResolver(currentModuleSession.firFileBuilder),
sourcesSession.cache
) )
} }
@@ -21,14 +21,20 @@ import org.jetbrains.kotlin.idea.fir.low.level.api.file.builder.FirFileBuilder
import org.jetbrains.kotlin.idea.fir.low.level.api.file.builder.ModuleFileCache import org.jetbrains.kotlin.idea.fir.low.level.api.file.builder.ModuleFileCache
import org.jetbrains.kotlin.idea.fir.low.level.api.lazy.resolve.FirLazyDeclarationResolver import org.jetbrains.kotlin.idea.fir.low.level.api.lazy.resolve.FirLazyDeclarationResolver
import org.jetbrains.kotlin.idea.fir.low.level.api.providers.FirIdeProvider import org.jetbrains.kotlin.idea.fir.low.level.api.providers.FirIdeProvider
import org.jetbrains.kotlin.idea.fir.low.level.api.sessions.*
import org.jetbrains.kotlin.idea.fir.low.level.api.sessions.FirIdeCurrentModuleSourcesSession
import org.jetbrains.kotlin.idea.fir.low.level.api.sessions.FirIdeDependentModulesSourcesSession
import org.jetbrains.kotlin.idea.fir.low.level.api.sessions.FirIdeLibrariesSession
import org.jetbrains.kotlin.idea.fir.low.level.api.sessions.FirIdeSessionProvider import org.jetbrains.kotlin.idea.fir.low.level.api.sessions.FirIdeSessionProvider
import org.jetbrains.kotlin.idea.fir.low.level.api.sessions.FirIdeSourcesSession
import org.jetbrains.kotlin.psi.KtElement import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.psi.KtFile
abstract class FirModuleResolveState { abstract class FirModuleResolveState {
abstract val moduleInfo: IdeaModuleInfo abstract val moduleInfo: IdeaModuleInfo
abstract val firIdeSourcesSession: FirSession abstract val currentModuleSourcesSession: FirSession
abstract val firIdeLibrariesSession: FirSession abstract val dependentModulesSourcesSession: FirSession
abstract val librariesSession: FirSession
abstract fun getSessionFor(moduleInfo: IdeaModuleInfo): FirSession abstract fun getSessionFor(moduleInfo: IdeaModuleInfo): FirSession
@@ -56,24 +62,25 @@ abstract class FirModuleResolveState {
} }
internal open class FirModuleResolveStateImpl( internal class FirModuleResolveStateImpl(
override val moduleInfo: IdeaModuleInfo, override val moduleInfo: IdeaModuleInfo,
override val firIdeSourcesSession: FirSession, override val currentModuleSourcesSession: FirIdeCurrentModuleSourcesSession,
override val firIdeLibrariesSession: FirSession, override val dependentModulesSourcesSession: FirIdeDependentModulesSourcesSession,
override val librariesSession: FirIdeLibrariesSession,
private val sessionProvider: FirIdeSessionProvider, private val sessionProvider: FirIdeSessionProvider,
val firFileBuilder: FirFileBuilder, val firFileBuilder: FirFileBuilder,
val firLazyDeclarationResolver: FirLazyDeclarationResolver, val firLazyDeclarationResolver: FirLazyDeclarationResolver,
val fileCache: ModuleFileCache,
) : FirModuleResolveState() { ) : FirModuleResolveState() {
val psiToFirCache = PsiToFirCache(fileCache) val psiToFirCache = PsiToFirCache(currentModuleSourcesSession.cache)
val elementBuilder = FirElementBuilder(firFileBuilder, firLazyDeclarationResolver) val elementBuilder = FirElementBuilder(firFileBuilder, firLazyDeclarationResolver)
private val diagnosticsCollector = DiagnosticsCollector(firFileBuilder, fileCache) private val diagnosticsCollector =
DiagnosticsCollector(firFileBuilder, elementBuilder, psiToFirCache, currentModuleSourcesSession.cache)
override fun getSessionFor(moduleInfo: IdeaModuleInfo): FirSession = override fun getSessionFor(moduleInfo: IdeaModuleInfo): FirSession =
sessionProvider.getSession(moduleInfo) sessionProvider.getSession(moduleInfo)
override fun getOrBuildFirFor(element: KtElement, toPhase: FirResolvePhase): FirElement = override fun getOrBuildFirFor(element: KtElement, toPhase: FirResolvePhase): FirElement =
elementBuilder.getOrBuildFirFor(element, fileCache, psiToFirCache, toPhase) elementBuilder.getOrBuildFirFor(element, currentModuleSourcesSession.cache, psiToFirCache, toPhase)
override fun getDiagnostics(element: KtElement): List<Diagnostic> = override fun getDiagnostics(element: KtElement): List<Diagnostic> =
diagnosticsCollector.getDiagnosticsFor(element) diagnosticsCollector.getDiagnosticsFor(element)
@@ -83,6 +90,10 @@ internal open class FirModuleResolveStateImpl(
} }
override fun <D : FirDeclaration> resolvedFirToPhase(declaration: D, toPhase: FirResolvePhase): D { override fun <D : FirDeclaration> resolvedFirToPhase(declaration: D, toPhase: FirResolvePhase): D {
val fileCache = when (val session = declaration.session) {
is FirIdeSourcesSession -> session.cache
else -> return declaration
}
firLazyDeclarationResolver.lazyResolveDeclaration(declaration, fileCache, toPhase, checkPCE = true) firLazyDeclarationResolver.lazyResolveDeclaration(declaration, fileCache, toPhase, checkPCE = true)
return declaration return declaration
} }
@@ -99,7 +110,7 @@ internal open class FirModuleResolveStateImpl(
) { ) {
firLazyDeclarationResolver.runLazyResolveWithoutLock( firLazyDeclarationResolver.runLazyResolveWithoutLock(
firFunction, firFunction,
fileCache, currentModuleSourcesSession.cache,
containerFirFile, containerFirFile,
firIdeProvider, firIdeProvider,
toPhase, toPhase,
@@ -15,6 +15,9 @@ import org.jetbrains.kotlin.idea.caches.project.IdeaModuleInfo
import org.jetbrains.kotlin.idea.fir.low.level.api.element.builder.FirTowerDataContextCollector import org.jetbrains.kotlin.idea.fir.low.level.api.element.builder.FirTowerDataContextCollector
import org.jetbrains.kotlin.idea.fir.low.level.api.element.builder.PsiToFirCache import org.jetbrains.kotlin.idea.fir.low.level.api.element.builder.PsiToFirCache
import org.jetbrains.kotlin.idea.fir.low.level.api.providers.FirIdeProvider import org.jetbrains.kotlin.idea.fir.low.level.api.providers.FirIdeProvider
import org.jetbrains.kotlin.idea.fir.low.level.api.sessions.FirIdeCurrentModuleSourcesSession
import org.jetbrains.kotlin.idea.fir.low.level.api.sessions.FirIdeDependentModulesSourcesSession
import org.jetbrains.kotlin.idea.fir.low.level.api.sessions.FirIdeLibrariesSession
import org.jetbrains.kotlin.psi.KtElement import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.psi.KtFile
@@ -22,10 +25,11 @@ internal class FirModuleResolveStateForCompletion(
private val originalState: FirModuleResolveStateImpl private val originalState: FirModuleResolveStateImpl
) : FirModuleResolveState() { ) : FirModuleResolveState() {
override val moduleInfo: IdeaModuleInfo get() = originalState.moduleInfo override val moduleInfo: IdeaModuleInfo get() = originalState.moduleInfo
override val firIdeSourcesSession: FirSession get() = originalState.firIdeSourcesSession override val currentModuleSourcesSession: FirIdeCurrentModuleSourcesSession get() = originalState.currentModuleSourcesSession
override val firIdeLibrariesSession: FirSession get() = originalState.firIdeSourcesSession override val dependentModulesSourcesSession: FirIdeDependentModulesSourcesSession get() = originalState.dependentModulesSourcesSession
override val librariesSession: FirIdeLibrariesSession get() = originalState.librariesSession
private val psiToFirCache = PsiToFirCache(originalState.fileCache) private val psiToFirCache = PsiToFirCache(originalState.currentModuleSourcesSession.cache)
override fun getSessionFor(moduleInfo: IdeaModuleInfo): FirSession = override fun getSessionFor(moduleInfo: IdeaModuleInfo): FirSession =
originalState.getSessionFor(moduleInfo) originalState.getSessionFor(moduleInfo)
@@ -34,7 +38,7 @@ internal class FirModuleResolveStateForCompletion(
getCachedMappingForCompletion(element)?.let { return it } getCachedMappingForCompletion(element)?.let { return it }
return originalState.elementBuilder.getOrBuildFirFor( return originalState.elementBuilder.getOrBuildFirFor(
element, element,
originalState.fileCache, originalState.currentModuleSourcesSession.cache,
psiToFirCache, psiToFirCache,
toPhase toPhase
) )
@@ -122,7 +122,7 @@ object LowLevelFirApiFacade {
symbol = builtFunction.symbol as FirNamedFunctionSymbol symbol = builtFunction.symbol as FirNamedFunctionSymbol
resolvePhase = minOf(originalFunction.resolvePhase, FirResolvePhase.DECLARATIONS) resolvePhase = minOf(originalFunction.resolvePhase, FirResolvePhase.DECLARATIONS)
source = builtFunction.source source = builtFunction.source
session = state.firIdeSourcesSession session = state.currentModuleSourcesSession
} }
} }
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.idea.fir.low.level.api.sessions
import com.intellij.openapi.module.impl.scopes.ModuleWithDependentsScope import com.intellij.openapi.module.impl.scopes.ModuleWithDependentsScope
import com.intellij.openapi.project.Project import com.intellij.openapi.project.Project
import com.intellij.psi.search.GlobalSearchScope
import org.jetbrains.kotlin.fir.PrivateSessionConstructor import org.jetbrains.kotlin.fir.PrivateSessionConstructor
import org.jetbrains.kotlin.fir.SessionConfiguration import org.jetbrains.kotlin.fir.SessionConfiguration
import org.jetbrains.kotlin.fir.checkers.registerCommonCheckers import org.jetbrains.kotlin.fir.checkers.registerCommonCheckers
@@ -23,14 +24,15 @@ import org.jetbrains.kotlin.fir.resolve.transformers.FirPhaseManager
import org.jetbrains.kotlin.fir.scopes.KotlinScopeProvider import org.jetbrains.kotlin.fir.scopes.KotlinScopeProvider
import org.jetbrains.kotlin.fir.session.FirSessionFactory import org.jetbrains.kotlin.fir.session.FirSessionFactory
import org.jetbrains.kotlin.fir.session.registerCommonComponents import org.jetbrains.kotlin.fir.session.registerCommonComponents
import org.jetbrains.kotlin.fir.session.registerJavaSpecificResolveComponents import org.jetbrains.kotlin.fir.session.registerJavaSpecificComponents
import org.jetbrains.kotlin.fir.session.registerResolveComponents import org.jetbrains.kotlin.fir.session.registerResolveComponents
import org.jetbrains.kotlin.idea.caches.project.ModuleSourceInfo import org.jetbrains.kotlin.idea.caches.project.*
import org.jetbrains.kotlin.idea.caches.resolve.IDEPackagePartProvider import org.jetbrains.kotlin.idea.caches.resolve.IDEPackagePartProvider
import org.jetbrains.kotlin.idea.fir.low.level.api.FirPhaseRunner import org.jetbrains.kotlin.idea.fir.low.level.api.FirPhaseRunner
import org.jetbrains.kotlin.idea.fir.low.level.api.IdeFirPhaseManager import org.jetbrains.kotlin.idea.fir.low.level.api.IdeFirPhaseManager
import org.jetbrains.kotlin.idea.fir.low.level.api.IdeSessionComponents import org.jetbrains.kotlin.idea.fir.low.level.api.IdeSessionComponents
import org.jetbrains.kotlin.idea.fir.low.level.api.file.builder.FirFileBuilder import org.jetbrains.kotlin.idea.fir.low.level.api.file.builder.FirFileBuilder
import org.jetbrains.kotlin.idea.fir.low.level.api.file.builder.ModuleFileCache
import org.jetbrains.kotlin.idea.fir.low.level.api.file.builder.ModuleFileCacheImpl import org.jetbrains.kotlin.idea.fir.low.level.api.file.builder.ModuleFileCacheImpl
import org.jetbrains.kotlin.idea.fir.low.level.api.lazy.resolve.FirLazyDeclarationResolver import org.jetbrains.kotlin.idea.fir.low.level.api.lazy.resolve.FirLazyDeclarationResolver
import org.jetbrains.kotlin.idea.fir.low.level.api.providers.FirIdeProvider import org.jetbrains.kotlin.idea.fir.low.level.api.providers.FirIdeProvider
@@ -40,66 +42,118 @@ import org.jetbrains.kotlin.load.kotlin.VirtualFileFinderFactory
@OptIn(PrivateSessionConstructor::class, SessionConfiguration::class) @OptIn(PrivateSessionConstructor::class, SessionConfiguration::class)
internal object FirIdeSessionFactory { internal object FirIdeSessionFactory {
fun createSourcesSession( fun createCurrentModuleSourcesSession(
project: Project,
moduleInfo: ModuleSourceInfo,
firPhaseRunner: FirPhaseRunner,
dependentModulesSourcesSession: FirIdeDependentModulesSourcesSession,
sessionProvider: FirIdeSessionProvider,
): FirIdeCurrentModuleSourcesSession {
val scopeProvider = KotlinScopeProvider(::wrapScopeWithJvmMapped)
val firBuilder = FirFileBuilder(scopeProvider, firPhaseRunner)
val searchScope = ModuleProductionSourceScope(moduleInfo.module)
return FirIdeCurrentModuleSourcesSession(moduleInfo, sessionProvider, searchScope, firBuilder).apply {
val cache = ModuleFileCacheImpl(this)
registerCommonSourceSessionComponents(
project,
moduleInfo,
scopeProvider,
searchScope,
cache,
additionalSymbolProviders = listOf(
dependentModulesSourcesSession.firSymbolProvider,
)
)
FirSessionFactory.FirSessionConfigurator(this).apply {
registerCommonCheckers()
}.configure()
}
}
fun createDependentModulesSourcesSession(
project: Project, project: Project,
moduleInfo: ModuleSourceInfo, moduleInfo: ModuleSourceInfo,
firPhaseRunner: FirPhaseRunner, firPhaseRunner: FirPhaseRunner,
sessionProvider: FirIdeSessionProvider, sessionProvider: FirIdeSessionProvider,
librariesSession: FirIdeLibrariesSession, librariesSession: FirIdeLibrariesSession,
init: FirSessionFactory.FirSessionConfigurator.() -> Unit = {} ): FirIdeDependentModulesSourcesSession {
): FirIdeSourcesSession {
val scopeProvider = KotlinScopeProvider(::wrapScopeWithJvmMapped) val scopeProvider = KotlinScopeProvider(::wrapScopeWithJvmMapped)
val firBuilder = FirFileBuilder(scopeProvider, firPhaseRunner) val firBuilder = FirFileBuilder(scopeProvider, firPhaseRunner)
val dependentModules = moduleInfo.collectTransitiveDependenciesWithSelf().filterIsInstance<ModuleSourceInfo>() val dependentModules = moduleInfo.collectTransitiveDependenciesWithSelf()
val searchScope = ModuleWithDependentsScope(project, dependentModules.map { it.module }) .filterIsInstance<ModuleSourceInfo>()
return FirIdeSourcesSession(moduleInfo, sessionProvider, searchScope, firBuilder).apply { .filterNot { it === moduleInfo }
val searchScope = ModuleWithDependentsScope(project, dependentModules.mapTo(mutableListOf()) { it.module })
return FirIdeDependentModulesSourcesSession(moduleInfo, sessionProvider, searchScope, firBuilder).apply {
val cache = ModuleFileCacheImpl(this) val cache = ModuleFileCacheImpl(this)
val firPhaseManager = IdeFirPhaseManager(FirLazyDeclarationResolver(firFileBuilder), cache) registerCommonSourceSessionComponents(
registerCommonComponents()
registerResolveComponents()
val provider = FirIdeProvider(
project, project,
this,
moduleInfo, moduleInfo,
scopeProvider, scopeProvider,
firFileBuilder, searchScope,
cache, cache,
searchScope additionalSymbolProviders = listOf(librariesSession.firSymbolProvider)
) )
FirSessionFactory.FirSessionConfigurator(this).configure()
register(FirProvider::class, provider)
register(FirIdeProvider::class, provider)
register(FirPhaseManager::class, firPhaseManager)
register(
FirSymbolProvider::class,
FirCompositeSymbolProvider(
this,
@OptIn(ExperimentalStdlibApi::class)
buildList {
add(provider.symbolProvider)
add(JavaSymbolProvider(this@apply, sessionProvider.project, searchScope))
add(librariesSession.firSymbolProvider)
}
) as FirSymbolProvider
)
registerJavaSpecificResolveComponents()
FirSessionFactory.FirSessionConfigurator(this).apply {
registerCommonCheckers()
init()
}.configure()
} }
} }
private fun FirIdeSourcesSession.registerCommonSourceSessionComponents(
project: Project,
moduleInfo: ModuleSourceInfo,
scopeProvider: KotlinScopeProvider,
searchScope: GlobalSearchScope,
cache: ModuleFileCache,
additionalSymbolProviders: List<FirSymbolProvider> = emptyList()
) {
val firPhaseManager = IdeFirPhaseManager(FirLazyDeclarationResolver(firFileBuilder), cache)
registerCommonComponents()
registerResolveComponents()
val provider = FirIdeProvider(
project,
this,
moduleInfo,
scopeProvider,
firFileBuilder,
cache,
searchScope
)
register(FirProvider::class, provider)
register(FirIdeProvider::class, provider)
register(FirPhaseManager::class, firPhaseManager)
register(
FirSymbolProvider::class,
FirCompositeSymbolProvider(
this,
@OptIn(ExperimentalStdlibApi::class)
buildList {
add(provider.symbolProvider)
add(JavaSymbolProvider(this@registerCommonSourceSessionComponents, project, searchScope))
addAll(additionalSymbolProviders)
}
) as FirSymbolProvider
)
registerJavaSpecificComponents()
}
private fun IdeaModuleInfo.librarySearchScope(): GlobalSearchScope? = when (this) {
is LibraryInfo -> contentScope()
is SdkInfo -> contentScope()
else -> null
}
fun createLibrarySession( fun createLibrarySession(
moduleInfo: ModuleSourceInfo, moduleInfo: ModuleSourceInfo,
sessionProvider: FirIdeSessionProvider, sessionProvider: FirIdeSessionProvider,
project: Project, project: Project,
): FirIdeLibrariesSession { ): FirIdeLibrariesSession {
val searchScope = moduleInfo.module.moduleWithLibrariesScope val dependencies = moduleInfo.collectTransitiveDependenciesWithSelf()
.mapNotNullTo(mutableListOf()) { it.librarySearchScope() }
val searchScope = if (dependencies.isEmpty()) GlobalSearchScope.EMPTY_SCOPE else GlobalSearchScope.union(dependencies)
val javaClassFinder = JavaClassFinderImpl().apply { val javaClassFinder = JavaClassFinderImpl().apply {
setProjectInstance(project) setProjectInstance(project)
setScope(searchScope) setScope(searchScope)
@@ -109,7 +163,7 @@ internal object FirIdeSessionFactory {
val kotlinClassFinder = VirtualFileFinderFactory.getInstance(project).create(searchScope) val kotlinClassFinder = VirtualFileFinderFactory.getInstance(project).create(searchScope)
return FirIdeLibrariesSession(moduleInfo, sessionProvider, searchScope).apply { return FirIdeLibrariesSession(moduleInfo, sessionProvider, searchScope).apply {
registerCommonComponents() registerCommonComponents()
registerJavaSpecificResolveComponents() registerJavaSpecificComponents()
val javaSymbolProvider = JavaSymbolProvider(this, sessionProvider.project, searchScope) val javaSymbolProvider = JavaSymbolProvider(this, sessionProvider.project, searchScope)
@@ -137,4 +191,4 @@ internal object FirIdeSessionFactory {
) )
} }
} }
} }
@@ -18,26 +18,31 @@ import org.jetbrains.kotlin.idea.fir.low.level.api.annotations.ThreadSafe
internal class FirIdeSessionProvider( internal class FirIdeSessionProvider(
override val project: Project, override val project: Project,
) : FirSessionProvider { ) : FirSessionProvider {
private lateinit var sourcesSession: FirIdeSourcesSession private lateinit var currentModuleSourcesSession: FirIdeSourcesSession
private lateinit var dependentModulesModuleSourcesSession: FirIdeSourcesSession
private lateinit var librariesSession: FirIdeLibrariesSession private lateinit var librariesSession: FirIdeLibrariesSession
fun setSourcesSession(sourcesSession: FirIdeSourcesSession) { fun init(
check(!this::sourcesSession.isInitialized) currentModuleSourcesSession: FirIdeSourcesSession,
this.sourcesSession = sourcesSession dependentModulesModuleSourcesSession: FirIdeSourcesSession,
} librariesSession: FirIdeLibrariesSession,
) {
fun setLibrariesSession(librariesSession: FirIdeLibrariesSession) { this.currentModuleSourcesSession = currentModuleSourcesSession
check(!this::librariesSession.isInitialized) this.dependentModulesModuleSourcesSession = dependentModulesModuleSourcesSession
this.librariesSession = librariesSession this.librariesSession = librariesSession
} }
override fun getSession(moduleInfo: ModuleInfo): FirSession = when { override fun getSession(moduleInfo: ModuleInfo): FirSession = when {
moduleInfo is IdeaModuleInfo && moduleInfo.isLibraryClasses() -> { moduleInfo is IdeaModuleInfo && moduleInfo.isLibraryClasses() -> {
librariesSession /* TODO check if library is in libraries session scope */ librariesSession /* TODO check if library is in libraries session scope */
} }
moduleInfo == currentModuleSourcesSession.moduleInfo -> {
currentModuleSourcesSession
}
moduleInfo is ModuleSourceInfo -> { moduleInfo is ModuleSourceInfo -> {
sourcesSession /* TODO check if source is in sources session scope */ currentModuleSourcesSession /* TODO check if source is in sources session scope */
} }
else -> error("Invalid module info $moduleInfo") else -> error("Invalid module info $moduleInfo")
} }
@@ -15,7 +15,7 @@ import org.jetbrains.kotlin.idea.fir.low.level.api.providers.firIdeProvider
* [org.jetbrains.kotlin.fir.FirSession] responsible for all Kotlin & Java source modules analysing module transitively depends on * [org.jetbrains.kotlin.fir.FirSession] responsible for all Kotlin & Java source modules analysing module transitively depends on
*/ */
@OptIn(PrivateSessionConstructor::class) @OptIn(PrivateSessionConstructor::class)
internal class FirIdeSourcesSession @PrivateSessionConstructor constructor( internal abstract class FirIdeSourcesSession @PrivateSessionConstructor constructor(
moduleInfo: ModuleInfo, moduleInfo: ModuleInfo,
sessionProvider: FirIdeSessionProvider, sessionProvider: FirIdeSessionProvider,
override val scope: GlobalSearchScope, override val scope: GlobalSearchScope,
@@ -23,3 +23,21 @@ internal class FirIdeSourcesSession @PrivateSessionConstructor constructor(
) : FirIdeSession(moduleInfo, sessionProvider) { ) : FirIdeSession(moduleInfo, sessionProvider) {
val cache get() = firIdeProvider.cache val cache get() = firIdeProvider.cache
} }
@OptIn(PrivateSessionConstructor::class)
internal class FirIdeCurrentModuleSourcesSession @PrivateSessionConstructor constructor(
moduleInfo: ModuleInfo,
sessionProvider: FirIdeSessionProvider,
scope: GlobalSearchScope,
firFileBuilder: FirFileBuilder,
) : FirIdeSourcesSession(moduleInfo, sessionProvider, scope, firFileBuilder) {
}
@OptIn(PrivateSessionConstructor::class)
internal class FirIdeDependentModulesSourcesSession @PrivateSessionConstructor constructor(
moduleInfo: ModuleInfo,
sessionProvider: FirIdeSessionProvider,
scope: GlobalSearchScope,
firFileBuilder: FirFileBuilder,
) : FirIdeSourcesSession(moduleInfo, sessionProvider, scope, firFileBuilder)
@@ -102,7 +102,7 @@ abstract class AbstractFirLazyResolveTest : KotlinLightCodeInsightFixtureTestCas
val files = FileTypeIndex.getFiles(KotlinFileType.INSTANCE, contentScope) val files = FileTypeIndex.getFiles(KotlinFileType.INSTANCE, contentScope)
for (file in files) { for (file in files) {
val psiFile = psiManager.findFile(file) as KtFile val psiFile = psiManager.findFile(file) as KtFile
val session = resolveState.firIdeSourcesSession val session = resolveState.currentModuleSourcesSession
val firProvider = session.firIdeProvider val firProvider = session.firIdeProvider
val firFile = firProvider.cache.getCachedFirFile(psiFile) ?: continue val firFile = firProvider.cache.getCachedFirFile(psiFile) ?: continue
KotlinTestUtils.assertEqualsToFile(File(expectedTxtPath(file)), firFile.render()) KotlinTestUtils.assertEqualsToFile(File(expectedTxtPath(file)), firFile.render())
@@ -40,7 +40,7 @@ private constructor(
override val callResolver: KtCallResolver = KtFirCallResolver(this, token) override val callResolver: KtCallResolver = KtFirCallResolver(this, token)
override val scopeProvider by threadLocal { KtFirScopeProvider(this, firSymbolBuilder, project, firResolveState, token) } override val scopeProvider by threadLocal { KtFirScopeProvider(this, firSymbolBuilder, project, firResolveState, token) }
override val symbolProvider: KtSymbolProvider = override val symbolProvider: KtSymbolProvider =
KtFirSymbolProvider(this, firResolveState.firIdeLibrariesSession.firSymbolProvider, firResolveState, firSymbolBuilder, token) KtFirSymbolProvider(this, firResolveState.currentModuleSourcesSession.firSymbolProvider, firResolveState, firSymbolBuilder, token)
override val completionCandidateChecker: KtCompletionCandidateChecker by threadLocal { KtFirCompletionCandidateChecker(this, token) } override val completionCandidateChecker: KtCompletionCandidateChecker by threadLocal { KtFirCompletionCandidateChecker(this, token) }
override val symbolDeclarationOverridesProvider: KtSymbolDeclarationOverridesProvider override val symbolDeclarationOverridesProvider: KtSymbolDeclarationOverridesProvider
by threadLocal { KtFirSymbolDeclarationOverridesProvider(this, token) } by threadLocal { KtFirSymbolDeclarationOverridesProvider(this, token) }
@@ -47,11 +47,11 @@ internal class KtSymbolByFirBuilder private constructor(
ConeTypeCheckerContext( ConeTypeCheckerContext(
isErrorTypeEqualsToAnything = true, isErrorTypeEqualsToAnything = true,
isStubTypeEqualsToAnything = true, isStubTypeEqualsToAnything = true,
resolveState.firIdeLibrariesSession resolveState.currentModuleSourcesSession
) )
} }
private val firProvider get() = resolveState.firIdeSourcesSession.firSymbolProvider private val firProvider get() = resolveState.currentModuleSourcesSession.firSymbolProvider
constructor( constructor(
resolveState: FirModuleResolveState, resolveState: FirModuleResolveState,
@@ -50,7 +50,7 @@ internal class KtFirCallResolver(
} }
private fun resolveCall(firCall: FirFunctionCall, callExpression: KtExpression): CallInfo? { private fun resolveCall(firCall: FirFunctionCall, callExpression: KtExpression): CallInfo? {
val session = firResolveState.firIdeSourcesSession val session = firResolveState.currentModuleSourcesSession
val resolvedFunctionSymbol = firCall.calleeReference.toTargetSymbol(session, firSymbolBuilder) val resolvedFunctionSymbol = firCall.calleeReference.toTargetSymbol(session, firSymbolBuilder)
val resolvedCalleeSymbol = (firCall.calleeReference as? FirResolvedNamedReference)?.resolvedSymbol val resolvedCalleeSymbol = (firCall.calleeReference as? FirResolvedNamedReference)?.resolvedSymbol
return when { return when {
@@ -79,7 +79,7 @@ internal class KtFirScopeProvider(
val firPackageScope = val firPackageScope =
FirPackageMemberScope( FirPackageMemberScope(
packageSymbol.fqName, packageSymbol.fqName,
firResolveState.firIdeSourcesSession/*TODO use correct session here*/ firResolveState.currentModuleSourcesSession/*TODO use correct session here*/
).also(firScopeStorage::register) ).also(firScopeStorage::register)
KtFirPackageScope(firPackageScope, project, builder, token) KtFirPackageScope(firPackageScope, project, builder, token)
} }
@@ -92,7 +92,7 @@ internal class KtFirScopeProvider(
override fun getTypeScope(type: KtType): KtScope? { override fun getTypeScope(type: KtType): KtScope? {
check(type is KtFirType) { "KtFirScopeProvider can only work with KtFirType, but ${type::class} was provided" } check(type is KtFirType) { "KtFirScopeProvider can only work with KtFirType, but ${type::class} was provided" }
val firTypeScope = type.coneType.scope(firResolveState.firIdeSourcesSession, ScopeSession()) ?: return null val firTypeScope = type.coneType.scope(firResolveState.currentModuleSourcesSession, ScopeSession()) ?: return null
return convertToKtScope(firTypeScope) return convertToKtScope(firTypeScope)
} }
@@ -136,7 +136,7 @@ internal object FirReferenceResolveHelper {
val expression = ref.expression val expression = ref.expression
val symbolBuilder = analysisSession.firSymbolBuilder val symbolBuilder = analysisSession.firSymbolBuilder
val fir = expression.getOrBuildFir(analysisSession.firResolveState) val fir = expression.getOrBuildFir(analysisSession.firResolveState)
val session = analysisSession.firResolveState.firIdeSourcesSession val session = analysisSession.firResolveState.currentModuleSourcesSession
when (fir) { when (fir) {
is FirResolvable -> { is FirResolvable -> {
val calleeReference = val calleeReference =