[FIR JS] Prepare the infrastructure for FIR JS tests

This commit is contained in:
Nikolay Lunyak
2021-12-24 12:16:57 +03:00
committed by teamcity
parent d2a8942353
commit 9a9beef25b
10 changed files with 644 additions and 40 deletions
@@ -0,0 +1,27 @@
/*
* 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.fir.FirSession
import org.jetbrains.kotlin.fir.deserialization.AbstractAnnotationDeserializer
import org.jetbrains.kotlin.fir.expressions.FirAnnotation
import org.jetbrains.kotlin.library.metadata.KlibMetadataProtoBuf
import org.jetbrains.kotlin.library.metadata.KlibMetadataSerializerProtocol
import org.jetbrains.kotlin.metadata.ProtoBuf
import org.jetbrains.kotlin.metadata.deserialization.NameResolver
import org.jetbrains.kotlin.serialization.SerializerExtensionProtocol
class KlibBasedAnnotationDeserializer(
session: FirSession
) : AbstractAnnotationDeserializer(session) {
override val protocol: SerializerExtensionProtocol
get() = KlibMetadataSerializerProtocol
override fun loadTypeAnnotations(typeProto: ProtoBuf.Type, nameResolver: NameResolver): List<FirAnnotation> {
val annotations = typeProto.getExtension(KlibMetadataProtoBuf.typeAnnotation).orEmpty()
return annotations.map { deserializeAnnotation(it, nameResolver) }
}
}
@@ -0,0 +1,134 @@
/*
* Copyright 2010-2021 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.descriptors.SourceFile
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.FirDeclarationOrigin
import org.jetbrains.kotlin.fir.deserialization.*
import org.jetbrains.kotlin.fir.languageVersionSettings
import org.jetbrains.kotlin.fir.scopes.FirKotlinScopeProvider
import org.jetbrains.kotlin.library.metadata.KlibMetadataClassDataFinder
import org.jetbrains.kotlin.library.resolver.KotlinResolvedLibrary
import org.jetbrains.kotlin.metadata.ProtoBuf
import org.jetbrains.kotlin.metadata.deserialization.NameResolverImpl
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.resolve.CompilerDeserializationConfiguration
import org.jetbrains.kotlin.serialization.deserialization.IncompatibleVersionErrorData
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerAbiStability
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource
import java.nio.file.Paths
class KlibBasedSymbolProvider(
session: FirSession,
moduleDataProvider: ModuleDataProvider,
kotlinScopeProvider: FirKotlinScopeProvider,
private val resolvedLibrary: KotlinResolvedLibrary,
defaultDeserializationOrigin: FirDeclarationOrigin = FirDeclarationOrigin.Library
) : AbstractFirDeserializedSymbolProvider(session, moduleDataProvider, kotlinScopeProvider, defaultDeserializationOrigin) {
private val moduleHeader by lazy {
resolvedLibrary.loadModuleHeader(resolvedLibrary.library)
}
private val fragmentNameList by lazy {
moduleHeader.packageFragmentNameList.toSet()
}
private val annotationDeserializer = KlibBasedAnnotationDeserializer(session)
private val constDeserializer = FirConstDeserializer(session)
private val deserializationConfiguration = CompilerDeserializationConfiguration(session.languageVersionSettings)
private val cachedFragments = mutableMapOf<Pair<String, String>, ProtoBuf.PackageFragment>()
private fun getPackageFragment(packageStringName: String, packageMetadataPart: String): ProtoBuf.PackageFragment {
return cachedFragments.getOrPut(packageStringName to packageMetadataPart) {
resolvedLibrary.loadPackageFragment(resolvedLibrary.library, packageStringName, packageMetadataPart)
}
}
override fun computePackagePartsInfos(packageFqName: FqName): List<PackagePartsCacheData> {
val packageStringName = packageFqName.asString()
if (packageStringName !in fragmentNameList) {
return emptyList()
}
return resolvedLibrary.library.packageMetadataParts(packageStringName).mapNotNull {
val fragment = getPackageFragment(packageStringName, it)
val libraryPath = Paths.get(resolvedLibrary.library.libraryName)
val moduleData = moduleDataProvider.getModuleData(libraryPath) ?: return@mapNotNull null
val packageProto = fragment.`package`
val nameResolver = NameResolverImpl(
fragment.strings,
fragment.qualifiedNames,
)
PackagePartsCacheData(
packageProto,
FirDeserializationContext.createForPackage(
packageFqName, packageProto, nameResolver, moduleData,
annotationDeserializer,
constDeserializer,
null,
),
)
}
}
override fun extractClassMetadata(classId: ClassId, parentContext: FirDeserializationContext?): ClassMetadataFindResult? {
val packageStringName = classId.packageFqName.asString()
if (packageStringName !in fragmentNameList) {
return null
}
resolvedLibrary.library.packageMetadataParts(packageStringName).forEach {
val libraryPath = Paths.get(resolvedLibrary.library.libraryName)
val fragment = getPackageFragment(packageStringName, it)
val nameResolver = NameResolverImpl(
fragment.strings,
fragment.qualifiedNames,
)
val finder = KlibMetadataClassDataFinder(fragment, nameResolver)
val classProto = finder.findClassData(classId)?.classProto ?: return@forEach
val source = object : DeserializedContainerSource {
override val incompatibility: IncompatibleVersionErrorData<*>? = null
override val isPreReleaseInvisible =
deserializationConfiguration.reportErrorsOnPreReleaseDependencies && (moduleHeader.flags and 1) != 0
override val abiStability = DeserializedContainerAbiStability.STABLE
override val presentableString = "Package '${classId.packageFqName}'"
override fun getContainingFile() = SourceFile.NO_SOURCE_FILE
}
return ClassMetadataFindResult.Metadata(
nameResolver,
classProto,
annotationDeserializer,
moduleDataProvider.getModuleData(libraryPath),
source,
classPostProcessor = {}
)
}
return null
}
override fun isNewPlaceForBodyGeneration(classProto: ProtoBuf.Class) = false
override fun getPackage(fqName: FqName): FqName? {
return if (fqName.toString() in fragmentNameList) {
fqName
} else {
null
}
}
}
@@ -35,6 +35,7 @@ import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.name.StandardClassIds
import org.jetbrains.kotlin.protobuf.MessageLite
import org.jetbrains.kotlin.serialization.SerializerExtensionProtocol
import org.jetbrains.kotlin.serialization.deserialization.builtins.BuiltInSerializerProtocol
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource
import org.jetbrains.kotlin.serialization.deserialization.getClassId
@@ -44,7 +45,8 @@ import org.jetbrains.kotlin.types.ConstantValueKind
abstract class AbstractAnnotationDeserializer(
private val session: FirSession
) {
protected val protocol = BuiltInSerializerProtocol
protected open val protocol: SerializerExtensionProtocol
get() = BuiltInSerializerProtocol
open fun inheritAnnotationInfo(parent: AbstractAnnotationDeserializer) {
}
@@ -5,9 +5,11 @@
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
@@ -17,13 +19,22 @@ import org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM
import org.jetbrains.kotlin.cli.jvm.compiler.VfsBasedProjectEnvironment
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.moduleData
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
import org.jetbrains.kotlin.ir.util.IrMessageLogger
import org.jetbrains.kotlin.js.config.JSConfigurationKeys
import org.jetbrains.kotlin.js.resolve.JsPlatformAnalyzerServices
import org.jetbrains.kotlin.library.resolver.KotlinResolvedLibrary
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.platform.TargetPlatform
import org.jetbrains.kotlin.platform.isCommon
@@ -36,10 +47,14 @@ import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatformAnalyzerServices
import org.jetbrains.kotlin.resolve.konan.platform.NativePlatformAnalyzerServices
import org.jetbrains.kotlin.test.directives.FirDiagnosticsDirectives
import org.jetbrains.kotlin.test.directives.model.DirectivesContainer
import org.jetbrains.kotlin.test.model.DependencyRelation
import org.jetbrains.kotlin.test.model.FrontendFacade
import org.jetbrains.kotlin.test.model.FrontendKinds
import org.jetbrains.kotlin.test.model.TestModule
import org.jetbrains.kotlin.test.services.*
import org.jetbrains.kotlin.test.services.configuration.JsEnvironmentConfigurator
import java.io.File
import java.nio.file.Paths
class FirFrontendFacade(
testServices: TestServices,
@@ -72,48 +87,51 @@ class FirFrontendFacade(
testServices.sourceFileProvider.getKtFilesForSourceFiles(module.files, project).values to emptyList()
}
val moduleName = Name.identifier(module.name)
val languageVersionSettings = module.languageVersionSettings
val packagePartProviderFactory = compilerConfigurationProvider.getPackagePartProviderFactory(module)
val analyzerServices = module.targetPlatform.getAnalyzerServices()
val configuration = compilerConfigurationProvider.getCompilerConfiguration(module)
val extensionRegistrars = FirExtensionRegistrar.getInstances(project)
val librariesScope = ProjectScope.getLibrariesScope(project)
val sourcesScope = TopDownAnalyzerFacadeForJVM.newModuleSearchScope(project, ktFiles)
val session = FirSessionFactory.createSessionWithDependencies(
Name.identifier(module.name),
module.targetPlatform,
module.targetPlatform.getAnalyzerServices(),
moduleInfoProvider.firSessionProvider,
VfsBasedProjectEnvironment(
project, VirtualFileManager.getInstance().getFileSystem(StandardFileSystems.FILE_PROTOCOL),
{ packagePartProviderFactory.invoke(it) }
),
languageVersionSettings,
PsiBasedProjectFileSearchScope(sourcesScope),
PsiBasedProjectFileSearchScope(librariesScope),
lookupTracker = null,
enumWhenTracker = null,
incrementalCompilationContext = null,
extensionRegistrars = FirExtensionRegistrar.getInstances(project),
needRegisterJavaElementFinder = true,
dependenciesConfigurator = {
dependencies(configuration.jvmModularRoots.map { it.toPath() })
dependencies(configuration.jvmClasspathRoots.map { it.toPath() })
friendDependencies(configuration[JVMConfigurationKeys.FRIEND_PATHS] ?: emptyList())
sourceDependencies(moduleInfoProvider.getRegularDependentSourceModules(module))
sourceFriendsDependencies(moduleInfoProvider.getDependentFriendSourceModules(module))
sourceDependsOnDependencies(moduleInfoProvider.getDependentDependsOnSourceModules(module))
}
) {
val sessionConfigurator: FirSessionFactory.FirSessionConfigurator.() -> Unit = {
if (FirDiagnosticsDirectives.WITH_EXTENDED_CHECKERS in module.directives) {
registerExtendedCommonCheckers()
}
additionalSessionConfiguration?.invoke(this)
}
val session = when {
module.targetPlatform.isJvm() || module.targetPlatform.isCommon() -> {
configureSessionsForJvmOrCommon(
module,
moduleName,
project,
ktFiles,
compilerConfigurationProvider,
moduleInfoProvider,
analyzerServices,
configuration,
sessionConfigurator,
extensionRegistrars,
languageVersionSettings,
)
}
module.targetPlatform.isJs() -> {
configureSessionsForJs(
module,
moduleName,
moduleInfoProvider,
analyzerServices,
configuration,
testServices,
sessionConfigurator,
extensionRegistrars,
languageVersionSettings,
)
}
else -> error("Unsupported")
}
moduleInfoProvider.registerModuleData(module, session.moduleData)
val enablePluginPhases = FirDiagnosticsDirectives.ENABLE_PLUGIN_PHASES in module.directives
@@ -136,6 +154,223 @@ class FirFrontendFacade(
}
}
private fun DependencyListForCliModule.Builder.configureJvmDependencies(
configuration: CompilerConfiguration,
) {
dependencies(configuration.jvmModularRoots.map { it.toPath() })
dependencies(configuration.jvmClasspathRoots.map { it.toPath() })
friendDependencies(configuration[JVMConfigurationKeys.FRIEND_PATHS] ?: emptyList())
}
private fun DependencyListForCliModule.Builder.configureJsDependencies(
module: TestModule,
testServices: TestServices,
) {
val (runtimeKlibsPaths, transitiveLibraries, friendLibraries) = getJsDependencies(module, testServices)
dependencies(runtimeKlibsPaths.map { Paths.get(it).toAbsolutePath() })
dependencies(transitiveLibraries.map { it.toPath().toAbsolutePath() })
friendDependencies(friendLibraries.map { it.toPath().toAbsolutePath() })
}
private fun getJsDependencies(module: TestModule, testServices: TestServices): Triple<List<String>, List<File>, List<File>> {
val runtimeKlibsPaths = JsEnvironmentConfigurator.getRuntimePathsForModule(module, testServices)
val transitiveLibraries = JsEnvironmentConfigurator.getKlibDependencies(module, testServices, DependencyRelation.RegularDependency)
val friendLibraries = JsEnvironmentConfigurator.getKlibDependencies(module, testServices, DependencyRelation.FriendDependency)
return Triple(runtimeKlibsPaths, transitiveLibraries, friendLibraries)
}
private fun getAllJsDependenciesPaths(module: TestModule, testServices: TestServices): List<String> {
val (runtimeKlibsPaths, transitiveLibraries, friendLibraries) = getJsDependencies(module, testServices)
return runtimeKlibsPaths + transitiveLibraries.map { it.path } + friendLibraries.map { it.path }
}
fun resolveJsLibraries(
module: TestModule,
testServices: TestServices,
configuration: CompilerConfiguration
): List<KotlinResolvedLibrary> {
val paths = getAllJsDependenciesPaths(module, testServices)
val repositories = configuration[JSConfigurationKeys.REPOSITORIES] ?: emptyList()
val logger = configuration[IrMessageLogger.IR_MESSAGE_LOGGER].toResolverLogger()
return jsResolveLibraries(paths, repositories, logger).getFullResolvedList()
}
private fun buildDependencyList(
module: TestModule,
moduleName: Name,
moduleInfoProvider: FirModuleInfoProvider,
analyzerServices: PlatformDependentAnalyzerServices,
configureDependencies: DependencyListForCliModule.Builder.() -> Unit,
) = DependencyListForCliModule.build(moduleName, module.targetPlatform, analyzerServices) {
configureDependencies()
sourceDependencies(moduleInfoProvider.getRegularDependentSourceModules(module))
sourceFriendsDependencies(moduleInfoProvider.getDependentFriendSourceModules(module))
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
@@ -0,0 +1,143 @@
/*
* Copyright 2010-2021 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.test.frontend.fir
import org.jetbrains.kotlin.config.CompilerConfiguration
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.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.scopes.FirKotlinScopeProvider
import org.jetbrains.kotlin.fir.scopes.FirPlatformClassMapper
import org.jetbrains.kotlin.fir.session.*
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(
mainModuleName: Name,
module: TestModule,
testServices: TestServices,
configuration: CompilerConfiguration,
sessionProvider: FirProjectSessionProvider,
moduleDataProvider: ModuleDataProvider,
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)
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)
fun FirSession.registerJsSpecificResolveComponents() {
register(FirVisibilityChecker::class, FirVisibilityChecker.Default)
register(ConeCallConflictResolverFactory::class, JsCallConflictResolverFactory)
register(FirPlatformClassMapper::class, FirPlatformClassMapper.Default)
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()
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
)
}
}
}
@@ -0,0 +1,18 @@
/*
* 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.test.frontend.fir
import org.jetbrains.kotlin.fir.NoMutableState
import org.jetbrains.kotlin.fir.resolve.calls.FirSyntheticNamesProvider
import org.jetbrains.kotlin.load.java.setMethodName
import org.jetbrains.kotlin.name.Name
@NoMutableState
object FirJsSyntheticNamesProvider : FirSyntheticNamesProvider() {
override fun possibleGetterNamesByPropertyName(name: Name): List<Name> = emptyList()
override fun setterNameByGetterName(name: Name): Name = setMethodName(getMethodName = name)
override fun possiblePropertyNamesByAccessorName(name: Name): List<Name> = emptyList()
}
@@ -0,0 +1,34 @@
/*
* 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.test.frontend.fir
import org.jetbrains.kotlin.fir.NoMutableState
import org.jetbrains.kotlin.fir.resolve.BodyResolveComponents
import org.jetbrains.kotlin.fir.resolve.calls.ConeCallConflictResolverFactory
import org.jetbrains.kotlin.fir.resolve.calls.ConeCompositeConflictResolver
import org.jetbrains.kotlin.fir.resolve.calls.ConeIntegerOperatorConflictResolver
import org.jetbrains.kotlin.fir.resolve.calls.ConeOverloadConflictResolver
import org.jetbrains.kotlin.fir.resolve.calls.jvm.ConeEquivalentCallConflictResolver
import org.jetbrains.kotlin.fir.resolve.inference.InferenceComponents
import org.jetbrains.kotlin.fir.types.typeContext
import org.jetbrains.kotlin.js.resolve.JsTypeSpecificityComparatorWithoutDelegate
import org.jetbrains.kotlin.resolve.calls.results.TypeSpecificityComparator
@NoMutableState
object JsCallConflictResolverFactory : ConeCallConflictResolverFactory() {
override fun create(
typeSpecificityComparator: TypeSpecificityComparator,
components: InferenceComponents,
transformerComponents: BodyResolveComponents
): ConeCompositeConflictResolver {
val specificityComparator = JsTypeSpecificityComparatorWithoutDelegate(components.session.typeContext)
return ConeCompositeConflictResolver(
ConeOverloadConflictResolver(specificityComparator, components, transformerComponents),
ConeEquivalentCallConflictResolver(specificityComparator, components, transformerComponents),
ConeIntegerOperatorConflictResolver(specificityComparator, components, transformerComponents)
)
}
}
@@ -153,13 +153,13 @@ class JsEnvironmentConfigurator(testServices: TestServices) : EnvironmentConfigu
ConfigurationDirectives.WITH_STDLIB in module.directives
val names = if (needsFullIrRuntime) listOf("full.stdlib", "kotlin.test") else listOf("reduced.stdlib")
names.mapTo(result) { System.getProperty("kotlin.js.$it.path") }
names.mapNotNullTo(result) { System.getProperty("kotlin.js.$it.path") }
val runtimeClasspaths = testServices.runtimeClasspathProviders.flatMap { it.runtimeClassPaths(module) }
runtimeClasspaths.mapTo(result) { it.absolutePath }
return result
}
fun getDependencies(module: TestModule, testServices: TestServices, kind: DependencyRelation): List<ModuleDescriptorImpl> {
fun getKlibDependencies(module: TestModule, testServices: TestServices, kind: DependencyRelation): List<File> {
val visited = mutableSetOf<TestModule>()
fun getRecursive(module: TestModule, kind: DependencyRelation) {
val dependencies = if (kind == DependencyRelation.FriendDependency) module.friendDependencies else module.regularDependencies
@@ -171,8 +171,11 @@ class JsEnvironmentConfigurator(testServices: TestServices) : EnvironmentConfigu
}
}
getRecursive(module, kind)
return visited
.map { testServices.dependencyProvider.getArtifact(it, ArtifactKinds.KLib).outputFile }
return visited.map { testServices.dependencyProvider.getArtifact(it, ArtifactKinds.KLib).outputFile }
}
fun getDependencies(module: TestModule, testServices: TestServices, kind: DependencyRelation): List<ModuleDescriptorImpl> {
return getKlibDependencies(module, testServices, kind)
.map { testServices.jsLibraryProvider.getDescriptorByPath(it.absolutePath) }
}
@@ -6,6 +6,9 @@
package org.jetbrains.kotlin.js.analyze
import com.intellij.openapi.project.Project
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.psi.search.DelegatingGlobalSearchScope
import com.intellij.psi.search.GlobalSearchScope
import org.jetbrains.kotlin.analyzer.AnalysisResult
import org.jetbrains.kotlin.builtins.DefaultBuiltIns
import org.jetbrains.kotlin.builtins.functions.functionInterfacePackageFragmentProvider
@@ -24,8 +24,13 @@ import org.jetbrains.kotlin.types.model.KotlinTypeMarker
import org.jetbrains.kotlin.types.model.TypeSystemInferenceExtensionContext
import org.jetbrains.kotlin.types.model.TypeSystemInferenceExtensionContextDelegate
class JsTypeSpecificityComparator(val context: TypeSystemInferenceExtensionContextDelegate) : TypeSpecificityComparator {
// Replacing the TypeSystemInferenceExtensionContextDelegate with
// TypeSystemInferenceExtensionContext here leads to clashed registrations
// (for example, when trying to run IrJsTextTestCaseGenerated).
class JsTypeSpecificityComparator(context: TypeSystemInferenceExtensionContextDelegate) :
TypeSpecificityComparator by JsTypeSpecificityComparatorWithoutDelegate(context)
class JsTypeSpecificityComparatorWithoutDelegate(val context: TypeSystemInferenceExtensionContext) : TypeSpecificityComparator {
private fun TypeSystemInferenceExtensionContext.checkOnlyDynamicFlexibleType(type: KotlinTypeMarker) {
if (type.asFlexibleType() != null) {
assert(type.isDynamic()) {