[FIR] Implement Native test infrastructure, add FirNativeSessionFactory

This commit is contained in:
Ivan Kochurkin
2022-06-23 18:24:58 +03:00
parent 2f56b29b3f
commit 502349c594
27 changed files with 1661 additions and 40 deletions
@@ -21,7 +21,7 @@ import java.util.regex.Pattern;
public class DiagnosticsNativeTestGenerated extends AbstractDiagnosticsNativeTest {
@Test
public void testAllFilesPresentInNativeTests() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/nativeTests"), Pattern.compile("^(.+)\\.kt$"), null, true);
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/nativeTests"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true);
}
@Test
@@ -99,8 +99,8 @@ class FirFrontendFacade(
val isCommonOrJvm = module.targetPlatform.isJvm() || module.targetPlatform.isCommon()
val dependencyList: DependencyListForCliModule = buildDependencyList(module, moduleName, moduleInfoProvider, analyzerServices) {
if (isCommonOrJvm) {
val dependencyList = buildDependencyList(module, moduleName, moduleInfoProvider, analyzerServices) {
if (isCommonOrJvm || module.targetPlatform.isNative()) {
configureJvmDependencies(configuration)
} else {
configureJsDependencies(module, testServices)
@@ -109,35 +109,47 @@ class FirFrontendFacade(
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)
when {
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,
)
FirSessionFactory.createLibrarySession(
moduleName,
moduleInfoProvider.firSessionProvider,
dependencyList,
projectEnvironment,
projectFileSearchScope,
packagePartProvider,
languageVersionSettings,
)
}
module.targetPlatform.isJs() -> {
projectEnvironment = null
FirJsSessionFactory.createLibrarySession(
moduleName,
moduleInfoProvider.firSessionProvider,
dependencyList,
module,
testServices,
configuration,
languageVersionSettings,
)
}
module.targetPlatform.isNative() -> {
projectEnvironment = null
FirNativeSessionFactory.createLibrarySession(
moduleName,
moduleInfoProvider.firSessionProvider,
dependencyList,
languageVersionSettings,
)
}
else -> error("Unsupported")
}
val mainModuleData = FirModuleDataImpl(
@@ -175,6 +187,15 @@ class FirFrontendFacade(
sessionConfigurator,
)
}
module.targetPlatform.isNative() -> {
FirNativeSessionFactory.createModuleBasedSession(
mainModuleData,
moduleInfoProvider.firSessionProvider,
extensionRegistrars,
languageVersionSettings,
init = sessionConfigurator
)
}
else -> error("Unsupported")
}
@@ -0,0 +1,84 @@
/*
* 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.config.LanguageVersionSettings
import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.fir.analysis.FirOverridesBackwardCompatibilityHelper
import org.jetbrains.kotlin.fir.checkers.registerNativeCheckers
import org.jetbrains.kotlin.fir.extensions.FirExtensionRegistrar
import org.jetbrains.kotlin.fir.java.FirProjectSessionProvider
import org.jetbrains.kotlin.fir.resolve.calls.ConeCallConflictResolverFactory
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.FirAbstractSessionFactory
import org.jetbrains.kotlin.fir.session.FirSessionConfigurator
import org.jetbrains.kotlin.name.Name
object FirNativeSessionFactory : FirAbstractSessionFactory() {
fun createLibrarySession(
mainModuleName: Name,
sessionProvider: FirProjectSessionProvider,
dependencyListForCliModule: DependencyListForCliModule,
languageVersionSettings: LanguageVersionSettings
): FirSession {
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),
)
})
}
fun createModuleBasedSession(
moduleData: FirModuleData,
sessionProvider: FirProjectSessionProvider,
extensionRegistrars: List<FirExtensionRegistrar>,
languageVersionSettings: LanguageVersionSettings,
init: FirSessionConfigurator.() -> Unit
): FirSession {
return createModuleBasedSession(
moduleData,
sessionProvider,
extensionRegistrars,
languageVersionSettings,
null,
null,
init,
registerExtraComponents = { it.registerExtraComponentsForModuleBased() },
registerExtraCheckers = { it.registerNativeCheckers() },
createKotlinScopeProvider = { FirKotlinScopeProvider { _, declaredMemberScope, _, _ -> declaredMemberScope } },
createProviders = { _, _, symbolProvider, generatedSymbolsProvider, dependenciesSymbolProvider ->
listOfNotNull(
symbolProvider,
generatedSymbolsProvider,
dependenciesSymbolProvider,
)
}
)
}
@OptIn(SessionConfiguration::class)
fun FirSession.registerExtraComponentsForModuleBased() {
register(FirVisibilityChecker::class, FirVisibilityChecker.Default)
register(ConeCallConflictResolverFactory::class, NativeCallConflictResolverFactory)
register(FirPlatformClassMapper::class, FirPlatformClassMapper.Default)
register(FirSyntheticNamesProvider::class, FirNativeSyntheticNamesProvider)
register(FirOverridesBackwardCompatibilityHelper::class, FirOverridesBackwardCompatibilityHelper.Default())
}
}
@@ -0,0 +1,16 @@
/*
* 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.resolve.calls.FirSyntheticNamesProvider
import org.jetbrains.kotlin.load.java.setMethodName
import org.jetbrains.kotlin.name.Name
object FirNativeSyntheticNamesProvider : 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,30 @@
/*
* 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.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.resolve.calls.results.TypeSpecificityComparator
object NativeCallConflictResolverFactory : ConeCallConflictResolverFactory() {
override fun create(
typeSpecificityComparator: TypeSpecificityComparator,
components: InferenceComponents,
transformerComponents: BodyResolveComponents
): ConeCompositeConflictResolver {
val specificityComparator = TypeSpecificityComparator.NONE
return ConeCompositeConflictResolver(
ConeOverloadConflictResolver(specificityComparator, components, transformerComponents),
ConeEquivalentCallConflictResolver(specificityComparator, components, transformerComponents),
ConeIntegerOperatorConflictResolver(specificityComparator, components, transformerComponents)
)
}
}
@@ -6,24 +6,34 @@
package org.jetbrains.kotlin.test.runners
import org.jetbrains.kotlin.platform.konan.NativePlatforms
import org.jetbrains.kotlin.test.Constructor
import org.jetbrains.kotlin.test.builders.TestConfigurationBuilder
import org.jetbrains.kotlin.test.builders.classicFrontendHandlersStep
import org.jetbrains.kotlin.test.builders.classicFrontendStep
import org.jetbrains.kotlin.test.builders.firHandlersStep
import org.jetbrains.kotlin.test.directives.FirDiagnosticsDirectives
import org.jetbrains.kotlin.test.directives.JvmEnvironmentConfigurationDirectives
import org.jetbrains.kotlin.test.directives.LanguageSettingsDirectives
import org.jetbrains.kotlin.test.frontend.classic.ClassicFrontendFacade
import org.jetbrains.kotlin.test.frontend.classic.ClassicFrontendOutputArtifact
import org.jetbrains.kotlin.test.frontend.classic.handlers.ClassicDiagnosticsHandler
import org.jetbrains.kotlin.test.frontend.classic.handlers.DeclarationsDumpHandler
import org.jetbrains.kotlin.test.frontend.classic.handlers.OldNewInferenceMetaInfoProcessor
import org.jetbrains.kotlin.test.model.DependencyKind
import org.jetbrains.kotlin.test.model.FrontendKinds
import org.jetbrains.kotlin.test.frontend.fir.FirFrontendFacade
import org.jetbrains.kotlin.test.frontend.fir.FirOutputArtifact
import org.jetbrains.kotlin.test.model.*
import org.jetbrains.kotlin.test.services.configuration.CommonEnvironmentConfigurator
import org.jetbrains.kotlin.test.services.sourceProviders.AdditionalDiagnosticsSourceFilesProvider
import org.jetbrains.kotlin.test.services.sourceProviders.CoroutineHelpersSourceFilesProvider
import org.jetbrains.kotlin.test.frontend.fir.handlers.*
abstract class AbstractDiagnosticsNativeTestBase<R : ResultingArtifact.FrontendOutput<R>> : AbstractKotlinCompilerTest() {
abstract val targetFrontend: FrontendKind<R>
abstract val frontend: Constructor<FrontendFacade<R>>
abstract fun handlersSetup(builder: TestConfigurationBuilder)
abstract class AbstractDiagnosticsNativeTest : AbstractKotlinCompilerTest() {
override fun TestConfigurationBuilder.configuration() {
globalDefaults {
frontend = FrontendKinds.ClassicFrontend
frontend = targetFrontend
targetPlatform = NativePlatforms.unspecifiedNativePlatform
dependencyKind = DependencyKind.Source
}
@@ -42,8 +52,27 @@ abstract class AbstractDiagnosticsNativeTest : AbstractKotlinCompilerTest() {
::CoroutineHelpersSourceFilesProvider,
)
classicFrontendStep()
classicFrontendHandlersStep {
facadeStep(frontend)
handlersSetup(this)
forTestsMatching("testData/diagnostics/nativeTests/*") {
defaultDirectives {
+LanguageSettingsDirectives.ALLOW_KOTLIN_PACKAGE
}
}
}
}
abstract class AbstractDiagnosticsNativeTest : AbstractDiagnosticsNativeTestBase<ClassicFrontendOutputArtifact>() {
override val targetFrontend: FrontendKind<ClassicFrontendOutputArtifact>
get() = FrontendKinds.ClassicFrontend
override val frontend: Constructor<FrontendFacade<ClassicFrontendOutputArtifact>>
get() = ::ClassicFrontendFacade
override fun handlersSetup(builder: TestConfigurationBuilder) {
builder.classicFrontendHandlersStep {
useHandlers(
::DeclarationsDumpHandler,
::ClassicDiagnosticsHandler,
@@ -51,3 +80,44 @@ abstract class AbstractDiagnosticsNativeTest : AbstractKotlinCompilerTest() {
}
}
}
abstract class AbstractFirNativeDiagnosticsTest : AbstractDiagnosticsNativeTestBase<FirOutputArtifact>() {
override val targetFrontend: FrontendKind<FirOutputArtifact>
get() = FrontendKinds.FIR
override val frontend: Constructor<FrontendFacade<FirOutputArtifact>>
get() = ::FirFrontendFacade
override fun handlersSetup(builder: TestConfigurationBuilder) {
builder.firHandlersStep {
useHandlers(
::FirDiagnosticsHandler,
::FirDumpHandler,
::FirCfgDumpHandler,
::FirCfgConsistencyHandler,
::FirNoImplicitTypesHandler,
::FirScopeDumpHandler,
)
}
}
override fun configure(builder: TestConfigurationBuilder) {
super.configure(builder)
builder.forTestsMatching("compiler/testData/diagnostics/*") {
configurationForClassicAndFirTestsAlongside()
}
}
}
abstract class AbstractFirNativeDiagnosticsWithLightTreeTest : AbstractFirNativeDiagnosticsTest() {
override fun configure(builder: TestConfigurationBuilder) {
super.configure(builder)
with(builder) {
defaultDirectives {
+FirDiagnosticsDirectives.USE_LIGHT_TREE
}
}
}
}