[FIR] Commonize code for creating common, JVM and JS session

Extract FirAbstractSessionFactory
This commit is contained in:
Ivan Kochurkin
2022-06-21 18:38:15 +03:00
parent d6f235679b
commit 94527e24e8
4 changed files with 369 additions and 451 deletions
@@ -0,0 +1,139 @@
/*
* 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.fir.session
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.fir.checkers.registerCommonCheckers
import org.jetbrains.kotlin.fir.deserialization.ModuleDataProvider
import org.jetbrains.kotlin.fir.extensions.FirExtensionRegistrar
import org.jetbrains.kotlin.fir.extensions.FirSwitchableExtensionDeclarationsSymbolProvider
import org.jetbrains.kotlin.fir.java.FirCliSession
import org.jetbrains.kotlin.fir.java.FirProjectSessionProvider
import org.jetbrains.kotlin.fir.resolve.providers.FirDependenciesSymbolProvider
import org.jetbrains.kotlin.fir.resolve.providers.FirProvider
import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider
import org.jetbrains.kotlin.fir.resolve.providers.impl.FirCompositeSymbolProvider
import org.jetbrains.kotlin.fir.resolve.providers.impl.FirDependenciesSymbolProviderImpl
import org.jetbrains.kotlin.fir.resolve.providers.impl.FirLibrarySessionProvider
import org.jetbrains.kotlin.fir.resolve.providers.impl.FirProviderImpl
import org.jetbrains.kotlin.fir.scopes.FirKotlinScopeProvider
import org.jetbrains.kotlin.incremental.components.EnumWhenTracker
import org.jetbrains.kotlin.incremental.components.LookupTracker
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.platform.TargetPlatform
import org.jetbrains.kotlin.resolve.PlatformDependentAnalyzerServices
@OptIn(PrivateSessionConstructor::class, SessionConfiguration::class)
abstract class FirAbstractSessionFactory {
protected fun createLibrarySession(
mainModuleName: Name,
sessionProvider: FirProjectSessionProvider,
moduleDataProvider: ModuleDataProvider,
languageVersionSettings: LanguageVersionSettings,
registerExtraComponents: ((FirSession) -> Unit)?,
createKotlinScopeProvider: () -> FirKotlinScopeProvider,
createProviders: (FirSession, FirModuleData, FirKotlinScopeProvider) -> List<FirSymbolProvider>
): FirSession {
return FirCliSession(sessionProvider, FirSession.Kind.Library).apply session@{
moduleDataProvider.allModuleData.forEach {
sessionProvider.registerSession(it, this)
it.bindSession(this)
}
registerCliCompilerOnlyComponents()
registerCommonComponents(languageVersionSettings)
registerExtraComponents?.invoke(this)
val kotlinScopeProvider = createKotlinScopeProvider.invoke()
register(FirKotlinScopeProvider::class, kotlinScopeProvider)
val builtinsModuleData = createModuleDataForBuiltins(
mainModuleName,
moduleDataProvider.platform,
moduleDataProvider.analyzerServices
).also { it.bindSession(this@session) }
val providers = createProviders(this, builtinsModuleData, kotlinScopeProvider)
val symbolProvider = FirCompositeSymbolProvider(this, providers)
register(FirSymbolProvider::class, symbolProvider)
register(FirProvider::class, FirLibrarySessionProvider(symbolProvider))
}
}
private fun createModuleDataForBuiltins(
parentModuleName: Name,
platform: TargetPlatform,
analyzerServices: PlatformDependentAnalyzerServices
): FirModuleData {
return DependencyListForCliModule.createDependencyModuleData(
Name.special("<builtins of ${parentModuleName.identifier}"),
platform,
analyzerServices,
)
}
protected fun createModuleBasedSession(
moduleData: FirModuleData,
sessionProvider: FirProjectSessionProvider,
extensionRegistrars: List<FirExtensionRegistrar>,
languageVersionSettings: LanguageVersionSettings,
lookupTracker: LookupTracker?,
enumWhenTracker: EnumWhenTracker?,
init: FirSessionConfigurator.() -> Unit,
registerExtraComponents: ((FirSession) -> Unit)?,
registerExtraCheckers: ((FirSessionConfigurator) -> Unit)?,
createKotlinScopeProvider: () -> FirKotlinScopeProvider,
createProviders: (
FirSession, FirKotlinScopeProvider, FirSymbolProvider,
FirSwitchableExtensionDeclarationsSymbolProvider?,
FirDependenciesSymbolProviderImpl
) -> List<FirSymbolProvider>
): FirSession {
return FirCliSession(sessionProvider, FirSession.Kind.Source).apply session@{
moduleData.bindSession(this@session)
sessionProvider.registerSession(moduleData, this@session)
registerModuleData(moduleData)
registerCliCompilerOnlyComponents()
registerCommonComponents(languageVersionSettings)
registerResolveComponents(lookupTracker, enumWhenTracker)
registerExtraComponents?.invoke(this)
val kotlinScopeProvider = createKotlinScopeProvider.invoke()
register(FirKotlinScopeProvider::class, kotlinScopeProvider)
val firProvider = FirProviderImpl(this, kotlinScopeProvider)
register(FirProvider::class, firProvider)
FirSessionFactory.FirSessionConfigurator(this).apply {
registerCommonCheckers()
registerExtraCheckers?.invoke(this)
for (extensionRegistrar in extensionRegistrars) {
registerExtensions(extensionRegistrar.configure())
}
init()
}.configure()
val dependenciesSymbolProvider = FirDependenciesSymbolProviderImpl(this)
val generatedSymbolsProvider = FirSwitchableExtensionDeclarationsSymbolProvider.create(this)
val providers = createProviders(
this, kotlinScopeProvider, firProvider.symbolProvider, generatedSymbolsProvider, dependenciesSymbolProvider,
)
register(FirSymbolProvider::class, FirCompositeSymbolProvider(this, providers))
generatedSymbolsProvider?.let { register(FirSwitchableExtensionDeclarationsSymbolProvider::class, it) }
register(
FirDependenciesSymbolProvider::class,
dependenciesSymbolProvider
)
}
}
}
@@ -14,21 +14,21 @@ import org.jetbrains.kotlin.fir.analysis.checkers.expression.ExpressionCheckers
import org.jetbrains.kotlin.fir.analysis.checkers.type.TypeCheckers
import org.jetbrains.kotlin.fir.analysis.checkersComponent
import org.jetbrains.kotlin.fir.analysis.extensions.additionalCheckers
import org.jetbrains.kotlin.fir.checkers.registerCommonCheckers
import org.jetbrains.kotlin.fir.checkers.registerJvmCheckers
import org.jetbrains.kotlin.fir.declarations.FirDeclarationOrigin
import org.jetbrains.kotlin.fir.deserialization.ModuleDataProvider
import org.jetbrains.kotlin.fir.deserialization.SingleModuleDataProvider
import org.jetbrains.kotlin.fir.extensions.*
import org.jetbrains.kotlin.fir.java.FirCliSession
import org.jetbrains.kotlin.fir.extensions.BunchOfRegisteredExtensions
import org.jetbrains.kotlin.fir.extensions.FirExtensionRegistrar
import org.jetbrains.kotlin.fir.extensions.extensionService
import org.jetbrains.kotlin.fir.extensions.registerExtensions
import org.jetbrains.kotlin.fir.java.FirProjectSessionProvider
import org.jetbrains.kotlin.fir.java.JavaSymbolProvider
import org.jetbrains.kotlin.fir.java.deserialization.JvmClassFileBasedSymbolProvider
import org.jetbrains.kotlin.fir.java.deserialization.OptionalAnnotationClassesProvider
import org.jetbrains.kotlin.fir.resolve.providers.FirDependenciesSymbolProvider
import org.jetbrains.kotlin.fir.resolve.providers.FirProvider
import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider
import org.jetbrains.kotlin.fir.resolve.providers.impl.*
import org.jetbrains.kotlin.fir.resolve.providers.impl.FirBuiltinSymbolProvider
import org.jetbrains.kotlin.fir.resolve.providers.impl.FirCloneableSymbolProvider
import org.jetbrains.kotlin.fir.resolve.providers.impl.FirDependenciesSymbolProviderImpl
import org.jetbrains.kotlin.fir.resolve.scopes.wrapScopeWithJvmMapped
import org.jetbrains.kotlin.fir.scopes.FirKotlinScopeProvider
import org.jetbrains.kotlin.fir.session.environment.AbstractProjectEnvironment
@@ -43,7 +43,7 @@ import org.jetbrains.kotlin.resolve.PlatformDependentAnalyzerServices
import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatformAnalyzerServices
@OptIn(PrivateSessionConstructor::class, SessionConfiguration::class)
object FirSessionFactory {
object FirSessionFactory : FirAbstractSessionFactory() {
class FirSessionConfigurator(private val session: FirSession) {
private val registeredExtensions: MutableList<BunchOfRegisteredExtensions> = mutableListOf(BunchOfRegisteredExtensions.empty())
@@ -98,13 +98,14 @@ object FirSessionFactory {
): FirSession {
val dependencyList = DependencyListForCliModule.build(moduleName, platform, analyzerServices, dependenciesConfigurator)
val sessionProvider = externalSessionProvider ?: FirProjectSessionProvider()
val packagePartProvider = projectEnvironment.getPackagePartProvider(librariesScope)
createLibrarySession(
moduleName,
sessionProvider,
dependencyList.moduleDataProvider,
librariesScope,
dependencyList,
projectEnvironment,
projectEnvironment.getPackagePartProvider(librariesScope),
librariesScope,
packagePartProvider,
languageVersionSettings
)
@@ -116,22 +117,58 @@ object FirSessionFactory {
dependencyList.platform,
dependencyList.analyzerServices
)
return createJavaModuleBasedSession(
return createModuleBasedSession(
mainModuleData,
sessionProvider,
javaSourcesScope,
projectEnvironment,
incrementalCompilationContext,
extensionRegistrars,
languageVersionSettings = languageVersionSettings,
lookupTracker = lookupTracker,
enumWhenTracker = enumWhenTracker,
languageVersionSettings,
lookupTracker,
enumWhenTracker,
needRegisterJavaElementFinder,
init = sessionConfigurator
sessionConfigurator
)
}
fun createJavaModuleBasedSession(
fun createLibrarySession(
mainModuleName: Name,
sessionProvider: FirProjectSessionProvider,
dependencyList: DependencyListForCliModule,
projectEnvironment: AbstractProjectEnvironment,
scope: AbstractProjectFileSearchScope,
packagePartProvider: PackagePartProvider,
languageVersionSettings: LanguageVersionSettings,
): FirSession {
return createLibrarySession(
mainModuleName,
sessionProvider,
dependencyList.moduleDataProvider,
languageVersionSettings,
registerExtraComponents = { it.registerCommonJavaComponents(projectEnvironment.getJavaModuleResolver()) },
createKotlinScopeProvider = { FirKotlinScopeProvider(::wrapScopeWithJvmMapped) },
createProviders = { session, builtinsModuleData, kotlinScopeProvider ->
listOf(
JvmClassFileBasedSymbolProvider(
session,
dependencyList.moduleDataProvider,
kotlinScopeProvider,
packagePartProvider,
projectEnvironment.getKotlinClassFinder(scope),
projectEnvironment.getFirJavaFacade(session, dependencyList.moduleDataProvider.allModuleData.last(), scope)
),
FirBuiltinSymbolProvider(session, builtinsModuleData, kotlinScopeProvider),
FirCloneableSymbolProvider(session, builtinsModuleData, kotlinScopeProvider),
FirDependenciesSymbolProviderImpl(session),
OptionalAnnotationClassesProvider(session, dependencyList.moduleDataProvider, kotlinScopeProvider, packagePartProvider)
)
}
)
}
@OptIn(SessionConfiguration::class)
fun createModuleBasedSession(
moduleData: FirModuleData,
sessionProvider: FirProjectSessionProvider,
javaSourcesScope: AbstractProjectFileSearchScope,
@@ -144,148 +181,67 @@ object FirSessionFactory {
needRegisterJavaElementFinder: Boolean,
init: FirSessionConfigurator.() -> Unit = {}
): FirSession {
return FirCliSession(sessionProvider, FirSession.Kind.Source).apply session@{
moduleData.bindSession(this@session)
sessionProvider.registerSession(moduleData, this@session)
registerModuleData(moduleData)
registerCliCompilerOnlyComponents()
registerCommonComponents(languageVersionSettings)
registerCommonJavaComponents(projectEnvironment.getJavaModuleResolver())
registerResolveComponents(lookupTracker, enumWhenTracker)
registerJavaSpecificResolveComponents()
val kotlinScopeProvider = FirKotlinScopeProvider(::wrapScopeWithJvmMapped)
register(FirKotlinScopeProvider::class, kotlinScopeProvider)
val firProvider = FirProviderImpl(this, kotlinScopeProvider)
register(FirProvider::class, firProvider)
var symbolProviderForBinariesFromIncrementalCompilation: JvmClassFileBasedSymbolProvider? = null
var optionalAnnotationClassesProviderForBinariesFromIncrementalCompilation: OptionalAnnotationClassesProvider? = null
incrementalCompilationContext?.let {
if (it.precompiledBinariesPackagePartProvider != null && it.precompiledBinariesFileScope != null) {
val moduleDataProvider = SingleModuleDataProvider(moduleData)
symbolProviderForBinariesFromIncrementalCompilation =
JvmClassFileBasedSymbolProvider(
this@session,
moduleDataProvider,
kotlinScopeProvider,
it.precompiledBinariesPackagePartProvider,
projectEnvironment.getKotlinClassFinder(it.precompiledBinariesFileScope),
projectEnvironment.getFirJavaFacade(this, moduleData, it.precompiledBinariesFileScope),
defaultDeserializationOrigin = FirDeclarationOrigin.Precompiled
)
optionalAnnotationClassesProviderForBinariesFromIncrementalCompilation =
OptionalAnnotationClassesProvider(
this@session,
moduleDataProvider,
kotlinScopeProvider,
it.precompiledBinariesPackagePartProvider,
defaultDeserializationOrigin = FirDeclarationOrigin.Precompiled
)
return createModuleBasedSession(
moduleData,
sessionProvider,
extensionRegistrars,
languageVersionSettings,
lookupTracker,
enumWhenTracker,
init,
registerExtraComponents = {
it.registerCommonJavaComponents(projectEnvironment.getJavaModuleResolver())
it.registerJavaSpecificResolveComponents()
},
registerExtraCheckers = { it.registerJvmCheckers() },
createKotlinScopeProvider = { FirKotlinScopeProvider(::wrapScopeWithJvmMapped) },
createProviders = { session, kotlinScopeProvider, symbolProvider, generatedSymbolsProvider, dependenciesSymbolProvider ->
var symbolProviderForBinariesFromIncrementalCompilation: JvmClassFileBasedSymbolProvider? = null
var optionalAnnotationClassesProviderForBinariesFromIncrementalCompilation: OptionalAnnotationClassesProvider? = null
incrementalCompilationContext?.let {
if (it.precompiledBinariesPackagePartProvider != null && it.precompiledBinariesFileScope != null) {
val moduleDataProvider = SingleModuleDataProvider(moduleData)
symbolProviderForBinariesFromIncrementalCompilation =
JvmClassFileBasedSymbolProvider(
session,
moduleDataProvider,
kotlinScopeProvider,
it.precompiledBinariesPackagePartProvider,
projectEnvironment.getKotlinClassFinder(it.precompiledBinariesFileScope),
projectEnvironment.getFirJavaFacade(session, moduleData, it.precompiledBinariesFileScope),
defaultDeserializationOrigin = FirDeclarationOrigin.Precompiled
)
optionalAnnotationClassesProviderForBinariesFromIncrementalCompilation =
OptionalAnnotationClassesProvider(
session,
moduleDataProvider,
kotlinScopeProvider,
it.precompiledBinariesPackagePartProvider,
defaultDeserializationOrigin = FirDeclarationOrigin.Precompiled
)
}
}
}
FirSessionConfigurator(this).apply {
registerCommonCheckers()
registerJvmCheckers()
for (extensionRegistrar in extensionRegistrars) {
registerExtensions(extensionRegistrar.configure())
}
init()
}.configure()
val javaSymbolProvider = JavaSymbolProvider(session, projectEnvironment.getFirJavaFacade(session, moduleData, javaSourcesScope))
session.register(JavaSymbolProvider::class, javaSymbolProvider)
val dependenciesSymbolProvider = FirDependenciesSymbolProviderImpl(this)
val generatedSymbolsProvider = FirSwitchableExtensionDeclarationsSymbolProvider.create(this)
val javaSymbolProvider = JavaSymbolProvider(this, projectEnvironment.getFirJavaFacade(this, moduleData, javaSourcesScope))
register(
FirSymbolProvider::class,
FirCompositeSymbolProvider(
this,
listOfNotNull(
firProvider.symbolProvider,
*(incrementalCompilationContext?.previousFirSessionsSymbolProviders?.toTypedArray() ?: emptyArray()),
symbolProviderForBinariesFromIncrementalCompilation,
generatedSymbolsProvider,
javaSymbolProvider,
dependenciesSymbolProvider,
optionalAnnotationClassesProviderForBinariesFromIncrementalCompilation,
)
listOfNotNull(
symbolProvider,
*(incrementalCompilationContext?.previousFirSessionsSymbolProviders?.toTypedArray() ?: emptyArray()),
symbolProviderForBinariesFromIncrementalCompilation,
generatedSymbolsProvider,
javaSymbolProvider,
dependenciesSymbolProvider,
optionalAnnotationClassesProviderForBinariesFromIncrementalCompilation,
)
)
register(JavaSymbolProvider::class, javaSymbolProvider)
generatedSymbolsProvider?.let { register(FirSwitchableExtensionDeclarationsSymbolProvider::class, it) }
register(
FirDependenciesSymbolProvider::class,
dependenciesSymbolProvider
)
}
).also {
if (needRegisterJavaElementFinder) {
projectEnvironment.registerAsJavaElementFinder(this)
projectEnvironment.registerAsJavaElementFinder(it)
}
}
}
fun createLibrarySession(
mainModuleName: Name,
sessionProvider: FirProjectSessionProvider,
moduleDataProvider: ModuleDataProvider,
scope: AbstractProjectFileSearchScope,
projectEnvironment: AbstractProjectEnvironment,
packagePartProvider: PackagePartProvider,
languageVersionSettings: LanguageVersionSettings = LanguageVersionSettingsImpl.DEFAULT,
): FirSession {
return FirCliSession(sessionProvider, FirSession.Kind.Library).apply session@{
moduleDataProvider.allModuleData.forEach {
sessionProvider.registerSession(it, this)
it.bindSession(this)
}
registerCliCompilerOnlyComponents()
registerCommonComponents(languageVersionSettings)
registerCommonJavaComponents(projectEnvironment.getJavaModuleResolver())
val kotlinScopeProvider = FirKotlinScopeProvider(::wrapScopeWithJvmMapped)
register(FirKotlinScopeProvider::class, kotlinScopeProvider)
val classFileBasedSymbolProvider = JvmClassFileBasedSymbolProvider(
this,
moduleDataProvider,
kotlinScopeProvider,
packagePartProvider,
projectEnvironment.getKotlinClassFinder(scope),
projectEnvironment.getFirJavaFacade(this, moduleDataProvider.allModuleData.last(), scope)
)
val optionalAnnotationClassesProvider = OptionalAnnotationClassesProvider(
this,
moduleDataProvider,
kotlinScopeProvider,
packagePartProvider
)
val builtinsModuleData = createModuleDataForBuiltins(
mainModuleName,
moduleDataProvider.platform,
moduleDataProvider.analyzerServices
).also { it.bindSession(this@session) }
val symbolProvider = FirCompositeSymbolProvider(
this,
listOf(
classFileBasedSymbolProvider,
FirBuiltinSymbolProvider(this, builtinsModuleData, kotlinScopeProvider),
FirCloneableSymbolProvider(this, builtinsModuleData, kotlinScopeProvider),
FirDependenciesSymbolProviderImpl(this),
optionalAnnotationClassesProvider
)
)
register(FirSymbolProvider::class, symbolProvider)
register(FirProvider::class, FirLibrarySessionProvider(symbolProvider))
}
}
@TestOnly
fun createEmptySession(): FirSession {
return object : FirSession(null, Kind.Source) {}.apply {
@@ -301,16 +257,4 @@ object FirSessionFactory {
moduleData.bindSession(this)
}
}
fun createModuleDataForBuiltins(
parentModuleName: Name,
platform: TargetPlatform,
analyzerServices: PlatformDependentAnalyzerServices
): FirModuleData {
return DependencyListForCliModule.createDependencyModuleData(
Name.special("<builtins of ${parentModuleName.identifier}"),
platform,
analyzerServices,
)
}
}
@@ -5,11 +5,9 @@
package org.jetbrains.kotlin.test.frontend.fir
import com.intellij.openapi.project.Project
import com.intellij.openapi.vfs.StandardFileSystems
import com.intellij.openapi.vfs.VirtualFileManager
import com.intellij.psi.PsiElementFinder
import com.intellij.psi.search.GlobalSearchScope
import com.intellij.psi.search.ProjectScope
import org.jetbrains.kotlin.analyzer.common.CommonPlatformAnalyzerServices
import org.jetbrains.kotlin.asJava.finder.JavaElementFinder
@@ -21,13 +19,10 @@ import org.jetbrains.kotlin.cli.jvm.config.jvmClasspathRoots
import org.jetbrains.kotlin.cli.jvm.config.jvmModularRoots
import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.config.JVMConfigurationKeys
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl
import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.fir.FirAnalyzerFacade
import org.jetbrains.kotlin.fir.checkers.registerExtendedCommonCheckers
import org.jetbrains.kotlin.fir.extensions.FirExtensionRegistrar
import org.jetbrains.kotlin.fir.java.FirProjectSessionProvider
import org.jetbrains.kotlin.fir.session.FirSessionFactory
import org.jetbrains.kotlin.ir.backend.js.jsResolveLibraries
import org.jetbrains.kotlin.ir.backend.js.toResolverLogger
@@ -101,33 +96,82 @@ class FirFrontendFacade(
additionalSessionConfiguration?.invoke(this)
}
val isCommonOrJvm = module.targetPlatform.isJvm() || module.targetPlatform.isCommon()
val dependencyList: DependencyListForCliModule = buildDependencyList(module, moduleName, moduleInfoProvider, analyzerServices) {
if (isCommonOrJvm) {
configureJvmDependencies(configuration)
} else {
configureJsDependencies(module, testServices)
}
}
val projectEnvironment: VfsBasedProjectEnvironment?
if (isCommonOrJvm) {
val packagePartProviderFactory = compilerConfigurationProvider.getPackagePartProviderFactory(module)
projectEnvironment = VfsBasedProjectEnvironment(
project, VirtualFileManager.getInstance().getFileSystem(StandardFileSystems.FILE_PROTOCOL),
) { packagePartProviderFactory.invoke(it) }
val projectFileSearchScope = PsiBasedProjectFileSearchScope(ProjectScope.getLibrariesScope(project))
val packagePartProvider = projectEnvironment.getPackagePartProvider(projectFileSearchScope)
FirSessionFactory.createLibrarySession(
moduleName,
moduleInfoProvider.firSessionProvider,
dependencyList,
projectEnvironment,
projectFileSearchScope,
packagePartProvider,
languageVersionSettings,
)
} else {
projectEnvironment = null
FirJsSessionFactory.createLibrarySession(
moduleName,
moduleInfoProvider.firSessionProvider,
dependencyList,
module,
testServices,
configuration,
languageVersionSettings,
)
}
val mainModuleData = FirModuleDataImpl(
moduleName,
dependencyList.regularDependencies,
dependencyList.dependsOnDependencies,
dependencyList.friendsDependencies,
dependencyList.platform,
dependencyList.analyzerServices
)
val session = when {
module.targetPlatform.isJvm() || module.targetPlatform.isCommon() -> {
configureSessionsForJvmOrCommon(
module,
moduleName,
project,
ktFiles,
compilerConfigurationProvider,
moduleInfoProvider,
analyzerServices,
configuration,
sessionConfigurator,
isCommonOrJvm -> {
FirSessionFactory.createModuleBasedSession(
mainModuleData,
moduleInfoProvider.firSessionProvider,
PsiBasedProjectFileSearchScope(TopDownAnalyzerFacadeForJVM.newModuleSearchScope(project, ktFiles)),
projectEnvironment!!,
incrementalCompilationContext = null,
extensionRegistrars,
languageVersionSettings,
lookupTracker = null,
enumWhenTracker = null,
needRegisterJavaElementFinder = true,
sessionConfigurator,
)
}
module.targetPlatform.isJs() -> {
configureSessionsForJs(
module,
moduleName,
moduleInfoProvider,
analyzerServices,
configuration,
testServices,
sessionConfigurator,
FirJsSessionFactory.createModuleBasedSession(
mainModuleData,
moduleInfoProvider.firSessionProvider,
extensionRegistrars,
languageVersionSettings,
null,
sessionConfigurator,
)
}
else -> error("Unsupported")
@@ -213,166 +257,6 @@ private fun buildDependencyList(
sourceDependsOnDependencies(moduleInfoProvider.getDependentDependsOnSourceModules(module))
}
private fun configureSessionsForJvmOrCommon(
module: TestModule,
moduleName: Name,
project: Project,
ktFiles: Collection<KtFile>,
compilerConfigurationProvider: CompilerConfigurationProvider,
moduleInfoProvider: FirModuleInfoProvider,
analyzerServices: PlatformDependentAnalyzerServices,
configuration: CompilerConfiguration,
sessionConfigurator: FirSessionFactory.FirSessionConfigurator.() -> Unit,
extensionRegistrars: List<FirExtensionRegistrar>,
languageVersionSettings: LanguageVersionSettings = LanguageVersionSettingsImpl.DEFAULT,
): FirSession {
val librariesScope = ProjectScope.getLibrariesScope(project)
val sourcesScope = TopDownAnalyzerFacadeForJVM.newModuleSearchScope(project, ktFiles)
val dependencyList = buildDependencyList(module, moduleName, moduleInfoProvider, analyzerServices) {
configureJvmDependencies(configuration)
}
configureLibrarySessionForJvmOrCommon(
module,
moduleName,
moduleInfoProvider.firSessionProvider,
dependencyList,
librariesScope,
project,
compilerConfigurationProvider,
languageVersionSettings,
)
val mainModuleData = FirModuleDataImpl(
moduleName,
dependencyList.regularDependencies,
dependencyList.dependsOnDependencies,
dependencyList.friendsDependencies,
dependencyList.platform,
dependencyList.analyzerServices
)
return configureMainSessionForJvmOrCommon(
module,
project,
compilerConfigurationProvider,
sessionConfigurator,
extensionRegistrars,
sourcesScope,
mainModuleData,
moduleInfoProvider.firSessionProvider,
languageVersionSettings,
)
}
private fun configureLibrarySessionForJvmOrCommon(
module: TestModule,
moduleName: Name,
sessionProvider: FirProjectSessionProvider,
dependencyList: DependencyListForCliModule,
librariesScope: GlobalSearchScope,
project: Project,
compilerConfigurationProvider: CompilerConfigurationProvider,
languageVersionSettings: LanguageVersionSettings = LanguageVersionSettingsImpl.DEFAULT,
): FirSession {
val packagePartProviderFactory = compilerConfigurationProvider.getPackagePartProviderFactory(module)
val projectEnvironment = VfsBasedProjectEnvironment(
project, VirtualFileManager.getInstance().getFileSystem(StandardFileSystems.FILE_PROTOCOL),
) { packagePartProviderFactory.invoke(it) }
val projectFileSearchScope = PsiBasedProjectFileSearchScope(librariesScope)
return FirSessionFactory.createLibrarySession(
moduleName,
sessionProvider,
dependencyList.moduleDataProvider,
projectFileSearchScope,
projectEnvironment,
projectEnvironment.getPackagePartProvider(projectFileSearchScope),
languageVersionSettings,
)
}
private fun configureMainSessionForJvmOrCommon(
module: TestModule,
project: Project,
compilerConfigurationProvider: CompilerConfigurationProvider,
sessionConfigurator: FirSessionFactory.FirSessionConfigurator.() -> Unit,
extensionRegistrars: List<FirExtensionRegistrar>,
sourcesScope: GlobalSearchScope,
mainModuleData: FirModuleData,
sessionProvider: FirProjectSessionProvider,
languageVersionSettings: LanguageVersionSettings = LanguageVersionSettingsImpl.DEFAULT,
): FirSession {
val packagePartProviderFactory = compilerConfigurationProvider.getPackagePartProviderFactory(module)
val projectEnvironment = VfsBasedProjectEnvironment(
project, VirtualFileManager.getInstance().getFileSystem(StandardFileSystems.FILE_PROTOCOL),
) { packagePartProviderFactory.invoke(it) }
val projectFileSearchScope = PsiBasedProjectFileSearchScope(sourcesScope)
return FirSessionFactory.createJavaModuleBasedSession(
mainModuleData,
sessionProvider,
projectFileSearchScope,
projectEnvironment,
incrementalCompilationContext = null,
extensionRegistrars,
languageVersionSettings,
lookupTracker = null,
enumWhenTracker = null,
needRegisterJavaElementFinder = true,
sessionConfigurator,
)
}
private fun configureSessionsForJs(
module: TestModule,
moduleName: Name,
moduleInfoProvider: FirModuleInfoProvider,
analyzerServices: PlatformDependentAnalyzerServices,
configuration: CompilerConfiguration,
testServices: TestServices,
sessionConfigurator: FirSessionFactory.FirSessionConfigurator.() -> Unit,
extensionRegistrars: List<FirExtensionRegistrar>,
languageVersionSettings: LanguageVersionSettings = LanguageVersionSettingsImpl.DEFAULT,
): FirSession {
val dependencyList = buildDependencyList(module, moduleName, moduleInfoProvider, analyzerServices) {
configureJsDependencies(module, testServices)
}
FirJsSessionFactory.createJsLibrarySession(
moduleName,
module,
testServices,
configuration,
moduleInfoProvider.firSessionProvider,
dependencyList.moduleDataProvider,
languageVersionSettings,
)
val mainModuleData = FirModuleDataImpl(
moduleName,
dependencyList.regularDependencies,
dependencyList.dependsOnDependencies,
dependencyList.friendsDependencies,
dependencyList.platform,
dependencyList.analyzerServices
)
return FirJsSessionFactory.createJsModuleBasedSession(
mainModuleData,
moduleInfoProvider.firSessionProvider,
extensionRegistrars,
languageVersionSettings,
null,
sessionConfigurator,
)
}
fun TargetPlatform.getAnalyzerServices(): PlatformDependentAnalyzerServices {
return when {
isJvm() -> JvmPlatformAnalyzerServices
@@ -10,72 +10,79 @@ import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl
import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.fir.analysis.FirOverridesBackwardCompatibilityHelper
import org.jetbrains.kotlin.fir.checkers.registerCommonCheckers
import org.jetbrains.kotlin.fir.checkers.registerJsCheckers
import org.jetbrains.kotlin.fir.deserialization.ModuleDataProvider
import org.jetbrains.kotlin.fir.extensions.FirExtensionRegistrar
import org.jetbrains.kotlin.fir.extensions.FirSwitchableExtensionDeclarationsSymbolProvider
import org.jetbrains.kotlin.fir.java.FirCliSession
import org.jetbrains.kotlin.fir.java.FirProjectSessionProvider
import org.jetbrains.kotlin.fir.resolve.calls.ConeCallConflictResolverFactory
import org.jetbrains.kotlin.fir.resolve.calls.FirSyntheticNamesProvider
import org.jetbrains.kotlin.fir.resolve.providers.FirDependenciesSymbolProvider
import org.jetbrains.kotlin.fir.resolve.providers.FirProvider
import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider
import org.jetbrains.kotlin.fir.resolve.providers.impl.*
import org.jetbrains.kotlin.fir.resolve.scopes.wrapScopeWithJvmMapped
import org.jetbrains.kotlin.fir.resolve.providers.impl.FirBuiltinSymbolProvider
import org.jetbrains.kotlin.fir.resolve.providers.impl.FirCloneableSymbolProvider
import org.jetbrains.kotlin.fir.resolve.providers.impl.FirDependenciesSymbolProviderImpl
import org.jetbrains.kotlin.fir.scopes.FirKotlinScopeProvider
import org.jetbrains.kotlin.fir.scopes.FirPlatformClassMapper
import org.jetbrains.kotlin.fir.session.*
import org.jetbrains.kotlin.fir.session.FirAbstractSessionFactory
import org.jetbrains.kotlin.fir.session.FirSessionFactory
import org.jetbrains.kotlin.fir.session.KlibBasedSymbolProvider
import org.jetbrains.kotlin.incremental.components.LookupTracker
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.test.model.TestModule
import org.jetbrains.kotlin.test.services.TestServices
object FirJsSessionFactory {
@OptIn(PrivateSessionConstructor::class, SessionConfiguration::class)
fun createJsLibrarySession(
object FirJsSessionFactory : FirAbstractSessionFactory() {
fun createLibrarySession(
mainModuleName: Name,
sessionProvider: FirProjectSessionProvider,
dependencyListForCliModule: DependencyListForCliModule,
module: TestModule,
testServices: TestServices,
configuration: CompilerConfiguration,
sessionProvider: FirProjectSessionProvider,
moduleDataProvider: ModuleDataProvider,
languageVersionSettings: LanguageVersionSettings = LanguageVersionSettingsImpl.DEFAULT,
languageVersionSettings: LanguageVersionSettings,
): FirSession {
return FirCliSession(sessionProvider, FirSession.Kind.Library).apply session@{
moduleDataProvider.allModuleData.forEach {
sessionProvider.registerSession(it, this)
it.bindSession(this)
val moduleDataProvider = dependencyListForCliModule.moduleDataProvider
return createLibrarySession(
mainModuleName,
sessionProvider,
moduleDataProvider,
languageVersionSettings,
null,
createKotlinScopeProvider = { FirKotlinScopeProvider { _, declaredMemberScope, _, _ -> declaredMemberScope } },
createProviders = { session, builtinsModuleData, kotlinScopeProvider ->
listOf(
FirBuiltinSymbolProvider(session, builtinsModuleData, kotlinScopeProvider),
FirCloneableSymbolProvider(session, builtinsModuleData, kotlinScopeProvider),
FirDependenciesSymbolProviderImpl(session),
) + resolveJsLibraries(module, testServices, configuration).map {
KlibBasedSymbolProvider(session, moduleDataProvider, kotlinScopeProvider, it)
}
})
}
fun createModuleBasedSession(
moduleData: FirModuleData,
sessionProvider: FirProjectSessionProvider,
extensionRegistrars: List<FirExtensionRegistrar>,
languageVersionSettings: LanguageVersionSettings = LanguageVersionSettingsImpl.DEFAULT,
lookupTracker: LookupTracker?,
init: FirSessionConfigurator.() -> Unit
): FirSession {
return createModuleBasedSession(
moduleData,
sessionProvider,
extensionRegistrars,
languageVersionSettings,
lookupTracker,
null,
init,
registerExtraComponents = { it.registerJsSpecificResolveComponents() },
registerExtraCheckers = { it.registerJsCheckers() },
createKotlinScopeProvider = { FirKotlinScopeProvider { _, declaredMemberScope, _, _ -> declaredMemberScope } },
createProviders = { _, _, symbolProvider, generatedSymbolsProvider, dependenciesSymbolProvider ->
listOfNotNull(
symbolProvider,
generatedSymbolsProvider,
dependenciesSymbolProvider,
)
}
registerCliCompilerOnlyComponents()
registerCommonComponents(languageVersionSettings)
val kotlinScopeProvider = FirKotlinScopeProvider(::wrapScopeWithJvmMapped)
register(FirKotlinScopeProvider::class, kotlinScopeProvider)
val builtinsModuleData = FirSessionFactory.createModuleDataForBuiltins(
mainModuleName,
moduleDataProvider.platform,
moduleDataProvider.analyzerServices
).also { it.bindSession(this@session) }
val klibProviders = resolveJsLibraries(module, testServices, configuration).map {
KlibBasedSymbolProvider(this@session, moduleDataProvider, kotlinScopeProvider, it)
}
val otherProviders = listOf(
FirBuiltinSymbolProvider(this, builtinsModuleData, kotlinScopeProvider),
FirCloneableSymbolProvider(this, builtinsModuleData, kotlinScopeProvider),
FirDependenciesSymbolProviderImpl(this)
)
val symbolProvider = FirCompositeSymbolProvider(this, otherProviders + klibProviders)
register(FirSymbolProvider::class, symbolProvider)
register(FirProvider::class, FirLibrarySessionProvider(symbolProvider))
}
)
}
@OptIn(SessionConfiguration::class)
@@ -86,60 +93,4 @@ object FirJsSessionFactory {
register(FirSyntheticNamesProvider::class, FirJsSyntheticNamesProvider)
register(FirOverridesBackwardCompatibilityHelper::class, FirOverridesBackwardCompatibilityHelper.Default())
}
@OptIn(PrivateSessionConstructor::class, SessionConfiguration::class)
fun createJsModuleBasedSession(
moduleData: FirModuleData,
sessionProvider: FirProjectSessionProvider,
extensionRegistrars: List<FirExtensionRegistrar>,
languageVersionSettings: LanguageVersionSettings = LanguageVersionSettingsImpl.DEFAULT,
lookupTracker: LookupTracker? = null,
init: FirSessionFactory.FirSessionConfigurator.() -> Unit = {}
): FirSession {
return FirCliSession(sessionProvider, FirSession.Kind.Source).apply session@{
moduleData.bindSession(this@session)
sessionProvider.registerSession(moduleData, this@session)
registerModuleData(moduleData)
registerCliCompilerOnlyComponents()
registerCommonComponents(languageVersionSettings)
registerResolveComponents(lookupTracker)
registerJsSpecificResolveComponents()
val kotlinScopeProvider = FirKotlinScopeProvider { _, declaredMemberScope, _, _ -> declaredMemberScope }
register(FirKotlinScopeProvider::class, kotlinScopeProvider)
val firProvider = FirProviderImpl(this, kotlinScopeProvider)
register(FirProvider::class, firProvider)
FirSessionFactory.FirSessionConfigurator(this).apply {
registerCommonCheckers()
registerJsCheckers()
for (extensionRegistrar in extensionRegistrars) {
registerExtensions(extensionRegistrar.configure())
}
init()
}.configure()
val dependenciesSymbolProvider = FirDependenciesSymbolProviderImpl(this)
val generatedSymbolsProvider = FirSwitchableExtensionDeclarationsSymbolProvider.create(this)
register(
FirSymbolProvider::class,
FirCompositeSymbolProvider(
this,
listOfNotNull(
firProvider.symbolProvider,
generatedSymbolsProvider,
dependenciesSymbolProvider,
)
)
)
generatedSymbolsProvider?.let { register(FirSwitchableExtensionDeclarationsSymbolProvider::class, it) }
register(
FirDependenciesSymbolProvider::class,
dependenciesSymbolProvider
)
}
}
}