[JS Test] Introduce tests for loading metadata produced by JS compiler
This commit is contained in:
committed by
Space Team
parent
2290a096d1
commit
7eca772ec2
+196
-36
@@ -7,9 +7,13 @@ package org.jetbrains.kotlin.test
|
||||
|
||||
import com.intellij.openapi.vfs.StandardFileSystems
|
||||
import com.intellij.openapi.vfs.VirtualFileManager
|
||||
import org.jetbrains.kotlin.backend.common.CommonKLibResolver
|
||||
import org.jetbrains.kotlin.cli.common.SessionWithSources
|
||||
import org.jetbrains.kotlin.cli.common.prepareJsSessions
|
||||
import org.jetbrains.kotlin.cli.common.prepareJvmSessions
|
||||
import org.jetbrains.kotlin.cli.jvm.compiler.VfsBasedProjectEnvironment
|
||||
import org.jetbrains.kotlin.config.ApiVersion
|
||||
import org.jetbrains.kotlin.config.CompilerConfiguration
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl
|
||||
import org.jetbrains.kotlin.fir.BinaryModuleData
|
||||
import org.jetbrains.kotlin.fir.DependencyListForCliModule
|
||||
@@ -19,31 +23,119 @@ import org.jetbrains.kotlin.fir.declarations.utils.nameOrSpecialName
|
||||
import org.jetbrains.kotlin.fir.renderer.FirRenderer
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.firProvider
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider
|
||||
import org.jetbrains.kotlin.js.resolve.JsPlatformAnalyzerServices
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.platform.TargetPlatform
|
||||
import org.jetbrains.kotlin.platform.isJs
|
||||
import org.jetbrains.kotlin.platform.js.JsPlatforms
|
||||
import org.jetbrains.kotlin.platform.jvm.JvmPlatforms
|
||||
import org.jetbrains.kotlin.platform.jvm.isJvm
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.PlatformDependentAnalyzerServices
|
||||
import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatformAnalyzerServices
|
||||
import org.jetbrains.kotlin.test.backend.handlers.JvmBinaryArtifactHandler
|
||||
import org.jetbrains.kotlin.test.directives.FirDiagnosticsDirectives
|
||||
import org.jetbrains.kotlin.test.directives.FirDiagnosticsDirectives.PLATFORM_DEPENDANT_METADATA
|
||||
import org.jetbrains.kotlin.test.directives.LanguageSettingsDirectives.LANGUAGE_VERSION
|
||||
import org.jetbrains.kotlin.test.directives.model.DirectivesContainer
|
||||
import org.jetbrains.kotlin.test.directives.model.RegisteredDirectives
|
||||
import org.jetbrains.kotlin.test.directives.model.singleOrZeroValue
|
||||
import org.jetbrains.kotlin.test.frontend.classic.ClassicFrontendOutputArtifact
|
||||
import org.jetbrains.kotlin.test.frontend.fir.FirFrontendFacade
|
||||
import org.jetbrains.kotlin.test.frontend.fir.FirOutputArtifact
|
||||
import org.jetbrains.kotlin.test.frontend.fir.getAllJsDependenciesPaths
|
||||
import org.jetbrains.kotlin.test.model.*
|
||||
import org.jetbrains.kotlin.test.services.*
|
||||
import org.jetbrains.kotlin.test.util.trimTrailingWhitespacesAndRemoveRedundantEmptyLinesAtTheEnd
|
||||
import org.jetbrains.kotlin.test.utils.MultiModuleInfoDumper
|
||||
import org.jetbrains.kotlin.test.utils.withExtension
|
||||
import org.jetbrains.kotlin.util.DummyLogger
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.shouldNotBeCalled
|
||||
import java.io.File
|
||||
|
||||
class LoadedMetadataDumpHandler(testServices: TestServices) : JvmBinaryArtifactHandler(testServices) {
|
||||
class JvmLoadedMetadataDumpHandler(testServices: TestServices) : AbstractLoadedMetadataDumpHandler<BinaryArtifacts.Jvm>(
|
||||
testServices,
|
||||
ArtifactKinds.Jvm
|
||||
) {
|
||||
override val targetPlatform: TargetPlatform
|
||||
get() = JvmPlatforms.defaultJvmPlatform
|
||||
override val platformAnalyzerServices: PlatformDependentAnalyzerServices
|
||||
get() = JvmPlatformAnalyzerServices
|
||||
override val dependencyKind: DependencyKind
|
||||
get() = DependencyKind.Binary
|
||||
|
||||
override fun prepareSessions(
|
||||
module: TestModule,
|
||||
configuration: CompilerConfiguration,
|
||||
environment: VfsBasedProjectEnvironment,
|
||||
moduleName: Name,
|
||||
libraryList: DependencyListForCliModule,
|
||||
): List<SessionWithSources<KtFile>> {
|
||||
return prepareJvmSessions(
|
||||
files = emptyList(),
|
||||
configuration, environment, moduleName,
|
||||
extensionRegistrars = emptyList(),
|
||||
environment.getSearchScopeForProjectLibraries(),
|
||||
libraryList,
|
||||
isCommonSource = { false },
|
||||
fileBelongsToModule = { _, _ -> false },
|
||||
createProviderAndScopeForIncrementalCompilation = { null }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
class KlibLoadedMetadataDumpHandler(testServices: TestServices) : AbstractLoadedMetadataDumpHandler<BinaryArtifacts.KLib>(
|
||||
testServices,
|
||||
ArtifactKinds.KLib
|
||||
) {
|
||||
override val targetPlatform: TargetPlatform
|
||||
get() = JsPlatforms.defaultJsPlatform
|
||||
override val platformAnalyzerServices: PlatformDependentAnalyzerServices
|
||||
get() = JsPlatformAnalyzerServices
|
||||
override val dependencyKind: DependencyKind
|
||||
get() = DependencyKind.KLib
|
||||
|
||||
override fun prepareSessions(
|
||||
module: TestModule,
|
||||
configuration: CompilerConfiguration,
|
||||
environment: VfsBasedProjectEnvironment,
|
||||
moduleName: Name,
|
||||
libraryList: DependencyListForCliModule,
|
||||
): List<SessionWithSources<KtFile>> {
|
||||
val libraries = getAllJsDependenciesPaths(module, testServices)
|
||||
val resolvedLibraries = CommonKLibResolver.resolve(libraries, DummyLogger).getFullResolvedList()
|
||||
return prepareJsSessions(
|
||||
files = emptyList(),
|
||||
configuration,
|
||||
moduleName,
|
||||
resolvedLibraries.map { it.library },
|
||||
libraryList,
|
||||
extensionRegistrars = emptyList(),
|
||||
isCommonSource = { false },
|
||||
fileBelongsToModule = { _, _ -> false },
|
||||
lookupTracker = null,
|
||||
icData = null
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
abstract class AbstractLoadedMetadataDumpHandler<A : ResultingArtifact.Binary<A>>(
|
||||
testServices: TestServices,
|
||||
override val artifactKind: BinaryKind<A>
|
||||
) : BinaryArtifactHandler<A>(
|
||||
testServices,
|
||||
artifactKind,
|
||||
failureDisablesNextSteps = false,
|
||||
doNotRunIfThereWerePreviousFailures = false
|
||||
) {
|
||||
private val dumper: MultiModuleInfoDumper = MultiModuleInfoDumper()
|
||||
|
||||
override fun processModule(module: TestModule, info: BinaryArtifacts.Jvm) {
|
||||
override val directiveContainers: List<DirectivesContainer>
|
||||
get() = listOf(FirDiagnosticsDirectives)
|
||||
|
||||
override fun processModule(module: TestModule, info: A) {
|
||||
if (testServices.loadedMetadataSuppressionDirective in module.directives) return
|
||||
val languageVersion = module.directives.singleOrZeroValue(LANGUAGE_VERSION)
|
||||
val languageVersionSettings = if (languageVersion != null) {
|
||||
@@ -51,10 +143,11 @@ class LoadedMetadataDumpHandler(testServices: TestServices) : JvmBinaryArtifactH
|
||||
} else {
|
||||
LanguageVersionSettingsImpl.DEFAULT
|
||||
}
|
||||
|
||||
val emptyModule = TestModule(
|
||||
name = "empty", JvmPlatforms.defaultJvmPlatform, TargetBackend.JVM_IR, FrontendKinds.FIR,
|
||||
BackendKinds.IrBackend, ArtifactKinds.Jvm, files = emptyList(),
|
||||
allDependencies = listOf(DependencyDescription(module.name, DependencyKind.Binary, DependencyRelation.RegularDependency)),
|
||||
name = "empty", module.targetPlatform, module.targetBackend, FrontendKinds.FIR,
|
||||
BackendKinds.IrBackend, module.binaryKind, files = emptyList(),
|
||||
allDependencies = listOf(DependencyDescription(module.name, dependencyKind, DependencyRelation.RegularDependency)),
|
||||
RegisteredDirectives.Empty, languageVersionSettings
|
||||
)
|
||||
val configuration = testServices.compilerConfigurationProvider.getCompilerConfiguration(emptyModule)
|
||||
@@ -63,20 +156,22 @@ class LoadedMetadataDumpHandler(testServices: TestServices) : JvmBinaryArtifactH
|
||||
VirtualFileManager.getInstance().getFileSystem(StandardFileSystems.FILE_PROTOCOL),
|
||||
testServices.compilerConfigurationProvider.getPackagePartProviderFactory(emptyModule)
|
||||
)
|
||||
val moduleName = Name.identifier(emptyModule.name)
|
||||
val binaryModuleData = BinaryModuleData.initialize(
|
||||
Name.identifier(emptyModule.name),
|
||||
JvmPlatforms.defaultJvmPlatform,
|
||||
JvmPlatformAnalyzerServices
|
||||
moduleName,
|
||||
targetPlatform,
|
||||
platformAnalyzerServices
|
||||
)
|
||||
val session = prepareJvmSessions(
|
||||
files = emptyList<KtFile>(),
|
||||
configuration, environment, Name.identifier(emptyModule.name),
|
||||
extensionRegistrars = emptyList(),
|
||||
environment.getSearchScopeForProjectLibraries(),
|
||||
DependencyListForCliModule.build(binaryModuleData),
|
||||
isCommonSource = { false },
|
||||
fileBelongsToModule = { _, _ -> false },
|
||||
createProviderAndScopeForIncrementalCompilation = { null }
|
||||
val libraryList = FirFrontendFacade.initializeLibraryList(
|
||||
emptyModule, binaryModuleData, targetPlatform, configuration, testServices
|
||||
)
|
||||
|
||||
val session = prepareSessions(
|
||||
emptyModule,
|
||||
configuration,
|
||||
environment,
|
||||
moduleName,
|
||||
libraryList
|
||||
).single().session
|
||||
|
||||
val packageFqName = FqName("test")
|
||||
@@ -84,42 +179,104 @@ class LoadedMetadataDumpHandler(testServices: TestServices) : JvmBinaryArtifactH
|
||||
.append(collectPackageContent(session, packageFqName, extractNames(module, packageFqName)))
|
||||
}
|
||||
|
||||
@Suppress("warnings")
|
||||
protected abstract val targetPlatform: TargetPlatform
|
||||
protected abstract val platformAnalyzerServices: PlatformDependentAnalyzerServices
|
||||
protected abstract val dependencyKind: DependencyKind
|
||||
|
||||
protected abstract fun prepareSessions(
|
||||
module: TestModule,
|
||||
configuration: CompilerConfiguration,
|
||||
environment: VfsBasedProjectEnvironment,
|
||||
moduleName: Name,
|
||||
libraryList: DependencyListForCliModule,
|
||||
): List<SessionWithSources<KtFile>>
|
||||
|
||||
override fun processAfterAllModules(someAssertionWasFailed: Boolean) {
|
||||
if (dumper.isEmpty()) return
|
||||
val testDataFile = testServices.moduleStructure.originalTestDataFiles.first()
|
||||
|
||||
val frontendKind = testServices.defaultsProvider.defaultFrontend
|
||||
|
||||
val commonExtension = ".fir.txt"
|
||||
val (specificExtension, otherSpecificExtension) = when (testServices.defaultsProvider.defaultFrontend) {
|
||||
val (specificExtension, otherSpecificExtension) = when (frontendKind) {
|
||||
FrontendKinds.ClassicFrontend -> ".fir.k1.txt" to ".fir.k2.txt"
|
||||
FrontendKinds.FIR -> ".fir.k2.txt" to ".fir.k1.txt"
|
||||
else -> shouldNotBeCalled()
|
||||
}
|
||||
val commonFirDump = testDataFile.withExtension(commonExtension)
|
||||
val specificFirDump = testDataFile.withExtension(specificExtension)
|
||||
|
||||
val expectedFile = when {
|
||||
commonFirDump.exists() -> commonFirDump
|
||||
else -> specificFirDump
|
||||
}
|
||||
val targetPlatform = testServices.defaultsProvider.defaultPlatform
|
||||
if (PLATFORM_DEPENDANT_METADATA in testServices.moduleStructure.allDirectives) {
|
||||
val platformExtension = specificExtension.replace(".txt", "${targetPlatform.suffix}.txt")
|
||||
val otherPlatformExtension = specificExtension.replace(".txt", "${targetPlatform.oppositeSuffix}.txt")
|
||||
|
||||
val actualText = dumper.generateResultingDump()
|
||||
assertions.assertEqualsToFile(expectedFile, actualText, message = { "Content is not equal" })
|
||||
val expectedFile = testDataFile.withExtension(platformExtension)
|
||||
val actualText = dumper.generateResultingDump()
|
||||
assertions.assertEqualsToFile(expectedFile, actualText, message = { "Content is not equal" })
|
||||
|
||||
if (commonFirDump.exists() && specificFirDump.exists()) {
|
||||
assertions.fail {
|
||||
"""
|
||||
val checks = listOf(commonExtension, specificExtension, otherSpecificExtension).map { extension ->
|
||||
{
|
||||
val baseFile = testDataFile.withExtension(extension)
|
||||
assertions.assertFalse(baseFile.exists()) {
|
||||
"Base file $baseFile exists in presence of $PLATFORM_DEPENDANT_METADATA directive. Please remove file or directive"
|
||||
}
|
||||
}
|
||||
}
|
||||
assertions.assertAll(checks)
|
||||
val secondFile = testDataFile.withExtension(otherPlatformExtension)
|
||||
val common = testDataFile.withExtension(specificExtension)
|
||||
checkDumpsIdentity(
|
||||
testDataFile, expectedFile, secondFile, common,
|
||||
postProcessTestData = { it.replace("// $PLATFORM_DEPENDANT_METADATA\n", "") }
|
||||
)
|
||||
} else {
|
||||
val commonFirDump = testDataFile.withExtension(commonExtension)
|
||||
val specificFirDump = testDataFile.withExtension(specificExtension)
|
||||
|
||||
val expectedFile = when {
|
||||
commonFirDump.exists() -> commonFirDump
|
||||
else -> specificFirDump
|
||||
}
|
||||
|
||||
val actualText = dumper.generateResultingDump()
|
||||
assertions.assertEqualsToFile(expectedFile, actualText, message = { "Content is not equal" })
|
||||
|
||||
|
||||
if (commonFirDump.exists() && specificFirDump.exists()) {
|
||||
assertions.fail {
|
||||
"""
|
||||
Common dump ${commonFirDump.name} and specific ${specificFirDump.name} exist at the same time
|
||||
Please remove ${specificFirDump.name}
|
||||
""".trimIndent()
|
||||
}
|
||||
}
|
||||
if (!commonFirDump.exists()) {
|
||||
val otherFirDump = testDataFile.withExtension(otherSpecificExtension)
|
||||
checkDumpsIdentity(testDataFile, specificFirDump, otherFirDump, commonFirDump)
|
||||
}
|
||||
}
|
||||
if (!commonFirDump.exists()) {
|
||||
val otherFirDump = testDataFile.withExtension(otherSpecificExtension)
|
||||
checkK1AndK2DumpsIdentity(specificFirDump, otherFirDump, commonFirDump)
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkK1AndK2DumpsIdentity(file1: File, file2: File, commonFile: File) {
|
||||
private val TargetPlatform.suffix: String
|
||||
get() = when {
|
||||
isJvm() -> ".jvm"
|
||||
isJs() -> ".klib"
|
||||
else -> error("Unsupported platform: $this")
|
||||
}
|
||||
|
||||
private val TargetPlatform.oppositeSuffix: String
|
||||
get() = when {
|
||||
isJvm() -> ".klib"
|
||||
isJs() -> ".jvm"
|
||||
else -> error("Unsupported platform: $this")
|
||||
}
|
||||
|
||||
private fun checkDumpsIdentity(
|
||||
testDataFile: File,
|
||||
file1: File,
|
||||
file2: File,
|
||||
commonFile: File,
|
||||
postProcessTestData: ((String) -> String)? = null
|
||||
) {
|
||||
if (!file1.exists() || !file2.exists()) return
|
||||
val dump1 = file1.readText().trimTrailingWhitespacesAndRemoveRedundantEmptyLinesAtTheEnd()
|
||||
val dump2 = file2.readText().trimTrailingWhitespacesAndRemoveRedundantEmptyLinesAtTheEnd()
|
||||
@@ -127,6 +284,9 @@ class LoadedMetadataDumpHandler(testServices: TestServices) : JvmBinaryArtifactH
|
||||
commonFile.writeText(dump1)
|
||||
file1.delete()
|
||||
file2.delete()
|
||||
if (postProcessTestData != null) {
|
||||
testDataFile.writeText(postProcessTestData(testDataFile.readText()))
|
||||
}
|
||||
assertions.fail {
|
||||
"""
|
||||
Files ${file1.name} and ${file2.name} are identical
|
||||
|
||||
+1
-1
@@ -37,7 +37,7 @@ abstract class AbstractFirLoadCompiledJvmKotlinTestBase<F : ResultingArtifact.Fr
|
||||
)
|
||||
|
||||
configureJvmArtifactsHandlersStep {
|
||||
useHandlers(::LoadedMetadataDumpHandler)
|
||||
useHandlers(::JvmLoadedMetadataDumpHandler)
|
||||
}
|
||||
|
||||
forTestsMatching("compiler/testData/loadJava/compiledKotlinWithStdlib/*") {
|
||||
|
||||
+7
@@ -81,6 +81,13 @@ object FirDiagnosticsDirectives : SimpleDirectivesContainer() {
|
||||
Directive must contain description of ignoring in argument
|
||||
""".trimIndent()
|
||||
)
|
||||
|
||||
val PLATFORM_DEPENDANT_METADATA by directive(
|
||||
description = """
|
||||
Generate separate dumps for JVM and JS load compiled kotlin tests
|
||||
See AbstractLoadedMetadataDumpHandler
|
||||
"""
|
||||
)
|
||||
}
|
||||
|
||||
fun TestConfigurationBuilder.configureFirParser(parser: FirParser) {
|
||||
|
||||
+36
-33
@@ -136,7 +136,7 @@ open class FirFrontendFacade(
|
||||
val compilerConfigurationProvider = testServices.compilerConfigurationProvider
|
||||
val configuration = compilerConfigurationProvider.getCompilerConfiguration(mainModule)
|
||||
|
||||
val libraryList = initializeLibraryList(mainModule, binaryModuleData, targetPlatform, configuration)
|
||||
val libraryList = initializeLibraryList(mainModule, binaryModuleData, targetPlatform, configuration, testServices)
|
||||
|
||||
val moduleInfoProvider = testServices.firModuleInfoProvider
|
||||
val moduleDataMap = mutableMapOf<TestModule, FirModuleData>()
|
||||
@@ -163,38 +163,6 @@ open class FirFrontendFacade(
|
||||
return moduleDataMap to libraryList.moduleDataProvider
|
||||
}
|
||||
|
||||
private fun initializeLibraryList(
|
||||
mainModule: TestModule,
|
||||
binaryModuleData: BinaryModuleData,
|
||||
targetPlatform: TargetPlatform,
|
||||
configuration: CompilerConfiguration,
|
||||
): DependencyListForCliModule {
|
||||
return DependencyListForCliModule.build(binaryModuleData) {
|
||||
when {
|
||||
targetPlatform.isCommon() || targetPlatform.isJvm() -> {
|
||||
dependencies(configuration.jvmModularRoots.map { it.toPath() })
|
||||
dependencies(configuration.jvmClasspathRoots.map { it.toPath() })
|
||||
friendDependencies(configuration[JVMConfigurationKeys.FRIEND_PATHS] ?: emptyList())
|
||||
}
|
||||
targetPlatform.isJs() -> {
|
||||
val runtimeKlibsPaths = JsEnvironmentConfigurator.getRuntimePathsForModule(mainModule, testServices)
|
||||
val (transitiveLibraries, friendLibraries) = getTransitivesAndFriends(mainModule, testServices)
|
||||
dependencies(runtimeKlibsPaths.map { Paths.get(it).toAbsolutePath() })
|
||||
dependencies(transitiveLibraries.map { it.toPath().toAbsolutePath() })
|
||||
friendDependencies(friendLibraries.map { it.toPath().toAbsolutePath() })
|
||||
}
|
||||
targetPlatform.isNative() -> {
|
||||
val runtimeKlibsPaths = NativeEnvironmentConfigurator.getRuntimePathsForModule(mainModule, testServices)
|
||||
val (transitiveLibraries, friendLibraries) = getTransitivesAndFriends(mainModule, testServices)
|
||||
dependencies(runtimeKlibsPaths.map { Paths.get(it).toAbsolutePath() })
|
||||
dependencies(transitiveLibraries.map { it.toPath().toAbsolutePath() })
|
||||
friendDependencies(friendLibraries.map { it.toPath().toAbsolutePath() })
|
||||
}
|
||||
else -> error("Unsupported")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun createLibrarySession(
|
||||
module: TestModule,
|
||||
project: Project,
|
||||
@@ -414,4 +382,39 @@ open class FirFrontendFacade(
|
||||
else -> error("Unsupported")
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun initializeLibraryList(
|
||||
mainModule: TestModule,
|
||||
binaryModuleData: BinaryModuleData,
|
||||
targetPlatform: TargetPlatform,
|
||||
configuration: CompilerConfiguration,
|
||||
testServices: TestServices
|
||||
): DependencyListForCliModule {
|
||||
return DependencyListForCliModule.build(binaryModuleData) {
|
||||
when {
|
||||
targetPlatform.isCommon() || targetPlatform.isJvm() -> {
|
||||
dependencies(configuration.jvmModularRoots.map { it.toPath() })
|
||||
dependencies(configuration.jvmClasspathRoots.map { it.toPath() })
|
||||
friendDependencies(configuration[JVMConfigurationKeys.FRIEND_PATHS] ?: emptyList())
|
||||
}
|
||||
targetPlatform.isJs() -> {
|
||||
val runtimeKlibsPaths = JsEnvironmentConfigurator.getRuntimePathsForModule(mainModule, testServices)
|
||||
val (transitiveLibraries, friendLibraries) = getTransitivesAndFriends(mainModule, testServices)
|
||||
dependencies(runtimeKlibsPaths.map { Paths.get(it).toAbsolutePath() })
|
||||
dependencies(transitiveLibraries.map { it.toPath().toAbsolutePath() })
|
||||
friendDependencies(friendLibraries.map { it.toPath().toAbsolutePath() })
|
||||
}
|
||||
targetPlatform.isNative() -> {
|
||||
val runtimeKlibsPaths = NativeEnvironmentConfigurator.getRuntimePathsForModule(mainModule, testServices)
|
||||
val (transitiveLibraries, friendLibraries) = getTransitivesAndFriends(mainModule, testServices)
|
||||
dependencies(runtimeKlibsPaths.map { Paths.get(it).toAbsolutePath() })
|
||||
dependencies(transitiveLibraries.map { it.toPath().toAbsolutePath() })
|
||||
friendDependencies(friendLibraries.map { it.toPath().toAbsolutePath() })
|
||||
}
|
||||
else -> error("Unsupported")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,6 +24,9 @@ object FrontendKinds {
|
||||
}
|
||||
}
|
||||
|
||||
val FrontendKind<*>.isFir: Boolean
|
||||
get() = this == FrontendKinds.FIR
|
||||
|
||||
object BackendKinds {
|
||||
object ClassicBackend : BackendKind<ClassicBackendInput>("ClassicBackend")
|
||||
object IrBackend : BackendKind<IrBackendInput>("IrBackend")
|
||||
|
||||
+33
@@ -72,6 +72,21 @@ abstract class KotlinStandardLibrariesPathProvider : TestService {
|
||||
*/
|
||||
abstract fun getAnnotationsJar(): File
|
||||
|
||||
/**
|
||||
* kotlin-stdlib-js.jar
|
||||
*/
|
||||
abstract fun fullJsStdlib(): File
|
||||
|
||||
/**
|
||||
* Jar with minimal version of kotlin stdlib JS (may be same as fullJsStdlib)
|
||||
*/
|
||||
abstract fun defaultJsStdlib(): File
|
||||
|
||||
/**
|
||||
* kotlin-test-js.jar
|
||||
*/
|
||||
abstract fun kotlinTestJsKLib(): File
|
||||
|
||||
fun getRuntimeJarClassLoader(): ClassLoader = synchronized(this) {
|
||||
var loader = runtimeJarClassLoader.get()
|
||||
if (loader == null) {
|
||||
@@ -108,13 +123,28 @@ object StandardLibrariesPathProviderForKotlinProject : KotlinStandardLibrariesPa
|
||||
override fun scriptRuntimeJarForTests(): File = ForTestCompileRuntime.scriptRuntimeJarForTests()
|
||||
override fun jvmAnnotationsForTests(): File = ForTestCompileRuntime.jvmAnnotationsForTests()
|
||||
override fun getAnnotationsJar(): File = KtTestUtil.getAnnotationsJar()
|
||||
|
||||
override fun fullJsStdlib(): File = extractFromPropertyFirst("kotlin.js.full.stdlib.path") { "kotlin-stdlib-js.jar".dist() }
|
||||
override fun defaultJsStdlib(): File = extractFromPropertyFirst("kotlin.js.reduced.stdlib.path") { "kotlin-stdlib-js.jar".dist() }
|
||||
override fun kotlinTestJsKLib(): File = extractFromPropertyFirst("kotlin.js.kotlin.test.path") { "kotlin-test-js.jar".dist() }
|
||||
|
||||
private inline fun extractFromPropertyFirst(prop: String, onMissingProperty: () -> String): File {
|
||||
val path = System.getProperty(prop, null) ?: onMissingProperty()
|
||||
return File(path)
|
||||
}
|
||||
|
||||
private fun String.dist(): String {
|
||||
return "dist/kotlinc/lib/$this"
|
||||
}
|
||||
}
|
||||
|
||||
object EnvironmentBasedStandardLibrariesPathProvider : KotlinStandardLibrariesPathProvider() {
|
||||
const val KOTLIN_STDLIB_PROP = "org.jetbrains.kotlin.test.kotlin-stdlib"
|
||||
const val KOTLIN_STDLIB_JS_PROP = "org.jetbrains.kotlin.test.kotlin-stdlib-js"
|
||||
const val KOTLIN_STDLIB_JDK8_PROP = "org.jetbrains.kotlin.test.kotlin-stdlib-jdk8"
|
||||
const val KOTLIN_REFLECT_PROP = "org.jetbrains.kotlin.test.kotlin-reflect"
|
||||
const val KOTLIN_TEST_PROP = "org.jetbrains.kotlin.test.kotlin-test"
|
||||
const val KOTLIN_TEST_JS_PROP = "org.jetbrains.kotlin.test.kotlin-test-js"
|
||||
const val KOTLIN_SCRIPT_RUNTIME_PROP = "org.jetbrains.kotlin.test.kotlin-script-runtime"
|
||||
const val KOTLIN_ANNOTATIONS_JVM_PROP = "org.jetbrains.kotlin.test.kotlin-annotations-jvm"
|
||||
|
||||
@@ -133,6 +163,9 @@ object EnvironmentBasedStandardLibrariesPathProvider : KotlinStandardLibrariesPa
|
||||
override fun scriptRuntimeJarForTests(): File = getFile(KOTLIN_SCRIPT_RUNTIME_PROP)
|
||||
override fun jvmAnnotationsForTests(): File = getFile(KOTLIN_ANNOTATIONS_JVM_PROP)
|
||||
override fun getAnnotationsJar(): File = getFile(KOTLIN_ANNOTATIONS_JVM_PROP)
|
||||
override fun fullJsStdlib(): File = getFile(KOTLIN_STDLIB_JS_PROP)
|
||||
override fun defaultJsStdlib(): File = getFile(KOTLIN_STDLIB_JS_PROP)
|
||||
override fun kotlinTestJsKLib(): File = getFile(KOTLIN_TEST_JS_PROP)
|
||||
}
|
||||
|
||||
val TestServices.standardLibrariesPathProvider: KotlinStandardLibrariesPathProvider by TestServices.testServiceAccessor()
|
||||
|
||||
+7
-2
@@ -154,8 +154,13 @@ class JsEnvironmentConfigurator(testServices: TestServices) : EnvironmentConfigu
|
||||
val needsFullIrRuntime = JsEnvironmentConfigurationDirectives.KJS_WITH_FULL_RUNTIME in module.directives ||
|
||||
ConfigurationDirectives.WITH_STDLIB in module.directives
|
||||
|
||||
val names = if (needsFullIrRuntime) listOf("full.stdlib", "kotlin.test") else listOf("reduced.stdlib")
|
||||
names.mapNotNullTo(result) { System.getProperty("kotlin.js.$it.path")?.let { File(it).absolutePath } }
|
||||
val pathProvider = testServices.standardLibrariesPathProvider
|
||||
if (needsFullIrRuntime) {
|
||||
result += pathProvider.fullJsStdlib().absolutePath
|
||||
result += pathProvider.kotlinTestJsKLib().absolutePath
|
||||
} else {
|
||||
result += pathProvider.defaultJsStdlib().absolutePath
|
||||
}
|
||||
val runtimeClasspaths = testServices.runtimeClasspathProviders.flatMap { it.runtimeClassPaths(module) }
|
||||
runtimeClasspaths.mapTo(result) { it.absolutePath }
|
||||
return result
|
||||
|
||||
@@ -37,6 +37,7 @@ dependencies {
|
||||
testApi(projectTests(":compiler:test-infrastructure-utils"))
|
||||
testApi(projectTests(":compiler:tests-compiler-utils"))
|
||||
testApi(projectTests(":compiler:tests-common-new"))
|
||||
testImplementation(projectTests(":compiler:fir:analysis-tests"))
|
||||
|
||||
testCompileOnly(project(":compiler:frontend"))
|
||||
testCompileOnly(project(":compiler:cli"))
|
||||
|
||||
@@ -230,6 +230,11 @@ fun main(args: Array<String>) {
|
||||
// testClass<AbstractFirJsSteppingTest> {
|
||||
// model("debug/stepping")
|
||||
// }
|
||||
|
||||
testClass<AbstractFirLoadK2CompiledJsKotlinTest> {
|
||||
model("loadJava/compiledKotlin", extension = "kt")
|
||||
model("loadJava/compiledKotlinWithStdlib", extension = "kt")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright 2010-2023 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.js.test.fir
|
||||
|
||||
import org.jetbrains.kotlin.js.test.converters.FirJsKlibBackendFacade
|
||||
import org.jetbrains.kotlin.js.test.ir.commonConfigurationForJsCodegenTest
|
||||
import org.jetbrains.kotlin.test.*
|
||||
import org.jetbrains.kotlin.test.backend.ir.IrBackendInput
|
||||
import org.jetbrains.kotlin.test.builders.TestConfigurationBuilder
|
||||
import org.jetbrains.kotlin.test.builders.configureKlibArtifactsHandlersStep
|
||||
import org.jetbrains.kotlin.test.directives.FirDiagnosticsDirectives.FIR_PARSER
|
||||
import org.jetbrains.kotlin.test.frontend.fir.Fir2IrResultsConverter
|
||||
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.runners.AbstractKotlinCompilerWithTargetBackendTest
|
||||
|
||||
abstract class AbstractFirLoadCompiledJsKotlinTestBase<F : ResultingArtifact.FrontendOutput<F>> :
|
||||
AbstractKotlinCompilerWithTargetBackendTest(TargetBackend.JS_IR)
|
||||
{
|
||||
protected abstract val frontendKind: FrontendKind<F>
|
||||
protected abstract val frontendFacade: Constructor<FrontendFacade<F>>
|
||||
protected abstract val frontendToBackendConverter: Constructor<Frontend2BackendConverter<F, IrBackendInput>>
|
||||
|
||||
override fun TestConfigurationBuilder.configuration() {
|
||||
commonConfigurationForJsCodegenTest(
|
||||
frontendKind,
|
||||
frontendFacade,
|
||||
frontendToBackendConverter,
|
||||
::FirJsKlibBackendFacade,
|
||||
)
|
||||
|
||||
configureKlibArtifactsHandlersStep {
|
||||
useHandlers(::KlibLoadedMetadataDumpHandler)
|
||||
}
|
||||
|
||||
useAfterAnalysisCheckers(::FirMetadataLoadingTestSuppressor)
|
||||
}
|
||||
}
|
||||
|
||||
open class AbstractFirLoadK2CompiledJsKotlinTest : AbstractFirLoadCompiledJsKotlinTestBase<FirOutputArtifact>() {
|
||||
override val frontendKind: FrontendKind<FirOutputArtifact>
|
||||
get() = FrontendKinds.FIR
|
||||
override val frontendFacade: Constructor<FrontendFacade<FirOutputArtifact>>
|
||||
get() = ::FirFrontendFacade
|
||||
override val frontendToBackendConverter: Constructor<Frontend2BackendConverter<FirOutputArtifact, IrBackendInput>>
|
||||
get() = ::Fir2IrResultsConverter
|
||||
|
||||
override fun configure(builder: TestConfigurationBuilder) {
|
||||
super.configure(builder)
|
||||
builder.defaultDirectives {
|
||||
FIR_PARSER with FirParser.LightTree
|
||||
}
|
||||
}
|
||||
}
|
||||
+61
-38
@@ -56,15 +56,10 @@ abstract class AbstractJsBlackBoxCodegenTestBase<R : ResultingArtifact.FrontendO
|
||||
}
|
||||
|
||||
protected fun TestConfigurationBuilder.commonConfigurationForJsBlackBoxCodegenTest() {
|
||||
globalDefaults {
|
||||
frontend = targetFrontend
|
||||
targetPlatform = JsPlatforms.defaultJsPlatform
|
||||
dependencyKind = DependencyKind.Binary
|
||||
}
|
||||
commonConfigurationForJsCodegenTest(targetFrontend, frontendFacade, frontendToBackendConverter, backendFacade)
|
||||
|
||||
val pathToRootOutputDir = System.getProperty("kotlin.js.test.root.out.dir") ?: error("'kotlin.js.test.root.out.dir' is not set")
|
||||
defaultDirectives {
|
||||
+DiagnosticsDirectives.REPORT_ONLY_EXPLICITLY_DEFINED_DEBUG_INFO
|
||||
JsEnvironmentConfigurationDirectives.PATH_TO_ROOT_OUTPUT_DIR with pathToRootOutputDir
|
||||
JsEnvironmentConfigurationDirectives.PATH_TO_TEST_DIR with pathToTestDir
|
||||
JsEnvironmentConfigurationDirectives.TEST_GROUP_OUTPUT_DIR_PREFIX with testGroupOutputDirPrefix
|
||||
@@ -74,6 +69,11 @@ abstract class AbstractJsBlackBoxCodegenTestBase<R : ResultingArtifact.FrontendO
|
||||
if (getBoolean("kotlin.js.ir.skipRegularMode")) +JsEnvironmentConfigurationDirectives.SKIP_REGULAR_MODE
|
||||
}
|
||||
|
||||
useAdditionalSourceProviders(
|
||||
::JsAdditionalSourceProvider,
|
||||
::CoroutineHelpersSourceFilesProvider,
|
||||
)
|
||||
|
||||
forTestsNotMatching("compiler/testData/codegen/box/diagnostics/functions/tailRecursion/*") {
|
||||
defaultDirectives {
|
||||
DIAGNOSTICS with "-warnings"
|
||||
@@ -84,47 +84,20 @@ abstract class AbstractJsBlackBoxCodegenTestBase<R : ResultingArtifact.FrontendO
|
||||
enableMetaInfoHandler()
|
||||
}
|
||||
|
||||
useConfigurators(
|
||||
::CommonEnvironmentConfigurator,
|
||||
::JsEnvironmentConfigurator,
|
||||
)
|
||||
|
||||
useAdditionalSourceProviders(
|
||||
::JsAdditionalSourceProvider,
|
||||
::CoroutineHelpersSourceFilesProvider,
|
||||
)
|
||||
|
||||
useAdditionalService(::JsLibraryProvider)
|
||||
|
||||
useAfterAnalysisCheckers(
|
||||
::JsFailingTestSuppressor,
|
||||
::BlackBoxCodegenSuppressor,
|
||||
::JsArtifactsDumpHandler
|
||||
)
|
||||
|
||||
facadeStep(frontendFacade)
|
||||
classicFrontendHandlersStep {
|
||||
commonClassicFrontendHandlersForCodegenTest()
|
||||
useHandlers(::ClassicDiagnosticsHandler)
|
||||
}
|
||||
|
||||
firHandlersStep {
|
||||
useHandlers(::FirDiagnosticsHandler)
|
||||
}
|
||||
|
||||
facadeStep(frontendToBackendConverter)
|
||||
irHandlersStep {
|
||||
configureIrHandlersStep {
|
||||
useHandlers(::IrMangledNameAndSignatureDumpHandler)
|
||||
}
|
||||
|
||||
facadeStep(backendFacade)
|
||||
klibArtifactsHandlersStep()
|
||||
afterBackendFacade?.let { facadeStep(it) }
|
||||
facadeStep(recompileFacade)
|
||||
jsArtifactsHandlersStep {
|
||||
useHandlers(::JsSourceMapPathRewriter)
|
||||
}
|
||||
|
||||
useAfterAnalysisCheckers(
|
||||
::JsArtifactsDumpHandler
|
||||
)
|
||||
|
||||
forTestsMatching("compiler/testData/codegen/box/involvesIrInterpreter/*") {
|
||||
enableMetaInfoHandler()
|
||||
configureKlibArtifactsHandlersStep {
|
||||
@@ -136,3 +109,53 @@ abstract class AbstractJsBlackBoxCodegenTestBase<R : ResultingArtifact.FrontendO
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("reformat")
|
||||
fun <
|
||||
R : ResultingArtifact.FrontendOutput<R>,
|
||||
I : ResultingArtifact.BackendInput<I>,
|
||||
A : ResultingArtifact.Binary<A>
|
||||
> TestConfigurationBuilder.commonConfigurationForJsCodegenTest(
|
||||
targetFrontend: FrontendKind<R>,
|
||||
frontendFacade: Constructor<FrontendFacade<R>>,
|
||||
frontendToBackendConverter: Constructor<Frontend2BackendConverter<R, I>>,
|
||||
backendFacade: Constructor<BackendFacade<I, A>>,
|
||||
) {
|
||||
globalDefaults {
|
||||
frontend = targetFrontend
|
||||
targetPlatform = JsPlatforms.defaultJsPlatform
|
||||
dependencyKind = DependencyKind.Binary
|
||||
}
|
||||
|
||||
defaultDirectives {
|
||||
+DiagnosticsDirectives.REPORT_ONLY_EXPLICITLY_DEFINED_DEBUG_INFO
|
||||
}
|
||||
|
||||
useConfigurators(
|
||||
::CommonEnvironmentConfigurator,
|
||||
::JsEnvironmentConfigurator,
|
||||
)
|
||||
|
||||
useAdditionalService(::JsLibraryProvider)
|
||||
|
||||
useAfterAnalysisCheckers(
|
||||
::JsFailingTestSuppressor,
|
||||
::BlackBoxCodegenSuppressor,
|
||||
)
|
||||
|
||||
facadeStep(frontendFacade)
|
||||
classicFrontendHandlersStep {
|
||||
commonClassicFrontendHandlersForCodegenTest()
|
||||
useHandlers(::ClassicDiagnosticsHandler)
|
||||
}
|
||||
|
||||
firHandlersStep {
|
||||
useHandlers(::FirDiagnosticsHandler)
|
||||
}
|
||||
|
||||
facadeStep(frontendToBackendConverter)
|
||||
irHandlersStep()
|
||||
|
||||
facadeStep(backendFacade)
|
||||
klibArtifactsHandlersStep()
|
||||
}
|
||||
|
||||
@@ -20,11 +20,8 @@ import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.test.TargetBackend
|
||||
import org.jetbrains.kotlin.test.directives.JsEnvironmentConfigurationDirectives
|
||||
import org.jetbrains.kotlin.test.model.TestModule
|
||||
import org.jetbrains.kotlin.test.services.TestService
|
||||
import org.jetbrains.kotlin.test.services.TestServices
|
||||
import org.jetbrains.kotlin.test.services.compilerConfigurationProvider
|
||||
import org.jetbrains.kotlin.test.services.*
|
||||
import org.jetbrains.kotlin.test.services.configuration.JsEnvironmentConfigurator
|
||||
import org.jetbrains.kotlin.test.services.jsLibraryProvider
|
||||
import java.io.ByteArrayOutputStream
|
||||
import java.io.File
|
||||
|
||||
@@ -46,14 +43,14 @@ private class TestArtifactCache(val moduleName: String, val binaryAsts: MutableM
|
||||
}
|
||||
|
||||
class JsIrIncrementalDataProvider(private val testServices: TestServices) : TestService {
|
||||
private val fullRuntimeKlib: String = System.getProperty("kotlin.js.full.stdlib.path")
|
||||
private val defaultRuntimeKlib = System.getProperty("kotlin.js.reduced.stdlib.path")
|
||||
private val kotlinTestKLib = System.getProperty("kotlin.js.kotlin.test.path")
|
||||
private val fullRuntimeKlib = testServices.standardLibrariesPathProvider.fullJsStdlib()
|
||||
private val defaultRuntimeKlib = testServices.standardLibrariesPathProvider.defaultJsStdlib()
|
||||
private val kotlinTestKLib = testServices.standardLibrariesPathProvider.kotlinTestJsKLib()
|
||||
|
||||
private val predefinedKlibHasIcCache = mutableMapOf<String, TestArtifactCache?>(
|
||||
File(fullRuntimeKlib).absolutePath to null,
|
||||
File(kotlinTestKLib).absolutePath to null,
|
||||
File(defaultRuntimeKlib).absolutePath to null
|
||||
fullRuntimeKlib.absolutePath to null,
|
||||
kotlinTestKLib.absolutePath to null,
|
||||
defaultRuntimeKlib.absolutePath to null
|
||||
)
|
||||
|
||||
private val icCache: MutableMap<String, TestArtifactCache> = mutableMapOf()
|
||||
|
||||
Generated
+3542
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user