[Tests] Support KLIB metadata for stdlib in test compile utility
Create dependency provider able to resolve code from .knm metadata files to simplify migration from the legacy kotlin-stdlib-common artifact. KTIJ-28668 KTI-1457
This commit is contained in:
committed by
Space Team
parent
bfb1ef14f5
commit
ae664d37ae
+2
-1
@@ -146,6 +146,7 @@ class CommonResolverForModuleFactory(
|
|||||||
targetEnvironment: TargetEnvironment,
|
targetEnvironment: TargetEnvironment,
|
||||||
capabilities: Map<ModuleCapability<*>, Any?> = emptyMap(),
|
capabilities: Map<ModuleCapability<*>, Any?> = emptyMap(),
|
||||||
dependenciesContainer: CommonDependenciesContainer? = null,
|
dependenciesContainer: CommonDependenciesContainer? = null,
|
||||||
|
explicitProjectContext: ProjectContext? = null,
|
||||||
metadataPartProviderFactory: (ModuleContent<ModuleInfo>) -> MetadataPartProvider
|
metadataPartProviderFactory: (ModuleContent<ModuleInfo>) -> MetadataPartProvider
|
||||||
): AnalysisResult {
|
): AnalysisResult {
|
||||||
val moduleInfo = SourceModuleInfo(
|
val moduleInfo = SourceModuleInfo(
|
||||||
@@ -173,7 +174,7 @@ class CommonResolverForModuleFactory(
|
|||||||
dependenciesContainer
|
dependenciesContainer
|
||||||
)
|
)
|
||||||
|
|
||||||
val projectContext = ProjectContext(project, "metadata serializer")
|
val projectContext = explicitProjectContext ?: ProjectContext(project, "metadata serializer")
|
||||||
|
|
||||||
val resolver = ResolverForSingleModuleProject<ModuleInfo>(
|
val resolver = ResolverForSingleModuleProject<ModuleInfo>(
|
||||||
"sources for metadata serializer",
|
"sources for metadata serializer",
|
||||||
|
|||||||
@@ -6,6 +6,9 @@
|
|||||||
package org.jetbrains.kotlin.test
|
package org.jetbrains.kotlin.test
|
||||||
|
|
||||||
import com.intellij.openapi.util.Disposer
|
import com.intellij.openapi.util.Disposer
|
||||||
|
import org.jetbrains.kotlin.analyzer.ModuleInfo
|
||||||
|
import org.jetbrains.kotlin.analyzer.common.CommonDependenciesContainer
|
||||||
|
import org.jetbrains.kotlin.analyzer.common.CommonPlatformAnalyzerServices
|
||||||
import org.jetbrains.kotlin.analyzer.common.CommonResolverForModuleFactory
|
import org.jetbrains.kotlin.analyzer.common.CommonResolverForModuleFactory
|
||||||
import org.jetbrains.kotlin.backend.common.serialization.metadata.KlibMetadataMonolithicSerializer
|
import org.jetbrains.kotlin.backend.common.serialization.metadata.KlibMetadataMonolithicSerializer
|
||||||
import org.jetbrains.kotlin.builtins.DefaultBuiltIns
|
import org.jetbrains.kotlin.builtins.DefaultBuiltIns
|
||||||
@@ -21,24 +24,29 @@ import org.jetbrains.kotlin.codegen.forTestCompile.ForTestCompileRuntime
|
|||||||
import org.jetbrains.kotlin.config.CommonConfigurationKeys
|
import org.jetbrains.kotlin.config.CommonConfigurationKeys
|
||||||
import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl
|
import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl
|
||||||
import org.jetbrains.kotlin.config.languageVersionSettings
|
import org.jetbrains.kotlin.config.languageVersionSettings
|
||||||
|
import org.jetbrains.kotlin.context.ProjectContext
|
||||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.PackageFragmentProvider
|
||||||
|
import org.jetbrains.kotlin.descriptors.impl.CompositePackageFragmentProvider
|
||||||
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
|
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
|
||||||
import org.jetbrains.kotlin.library.KLIB_FILE_EXTENSION
|
import org.jetbrains.kotlin.incremental.components.LookupTracker
|
||||||
import org.jetbrains.kotlin.library.KotlinLibraryVersioning
|
import org.jetbrains.kotlin.ir.backend.js.moduleName
|
||||||
import org.jetbrains.kotlin.library.ToolingSingleFileKlibResolveStrategy
|
import org.jetbrains.kotlin.library.*
|
||||||
import org.jetbrains.kotlin.library.impl.BuiltInsPlatform
|
import org.jetbrains.kotlin.library.impl.BuiltInsPlatform
|
||||||
import org.jetbrains.kotlin.library.impl.KotlinLibraryLayoutForWriter
|
import org.jetbrains.kotlin.library.impl.KotlinLibraryLayoutForWriter
|
||||||
import org.jetbrains.kotlin.library.impl.KotlinLibraryWriterImpl
|
import org.jetbrains.kotlin.library.impl.KotlinLibraryWriterImpl
|
||||||
import org.jetbrains.kotlin.library.metadata.KlibMetadataFactories
|
import org.jetbrains.kotlin.library.metadata.*
|
||||||
import org.jetbrains.kotlin.library.metadata.KlibMetadataVersion
|
|
||||||
import org.jetbrains.kotlin.library.metadata.NullFlexibleTypeDeserializer
|
|
||||||
import org.jetbrains.kotlin.library.resolveSingleFileKlib
|
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.platform.CommonPlatforms
|
import org.jetbrains.kotlin.platform.CommonPlatforms
|
||||||
|
import org.jetbrains.kotlin.platform.TargetPlatform
|
||||||
|
import org.jetbrains.kotlin.resolve.CompilerDeserializationConfiguration
|
||||||
import org.jetbrains.kotlin.resolve.CompilerEnvironment
|
import org.jetbrains.kotlin.resolve.CompilerEnvironment
|
||||||
|
import org.jetbrains.kotlin.resolve.PlatformDependentAnalyzerServices
|
||||||
import org.jetbrains.kotlin.storage.LockBasedStorageManager
|
import org.jetbrains.kotlin.storage.LockBasedStorageManager
|
||||||
import org.jetbrains.kotlin.util.DummyLogger
|
import org.jetbrains.kotlin.util.DummyLogger
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
import java.io.IOException
|
||||||
|
import java.nio.file.Path
|
||||||
import org.jetbrains.kotlin.konan.file.File as KFile
|
import org.jetbrains.kotlin.konan.file.File as KFile
|
||||||
|
|
||||||
object KlibTestUtil {
|
object KlibTestUtil {
|
||||||
@@ -53,6 +61,7 @@ object KlibTestUtil {
|
|||||||
configuration.put(CommonConfigurationKeys.MODULE_NAME, libraryName)
|
configuration.put(CommonConfigurationKeys.MODULE_NAME, libraryName)
|
||||||
configuration.addKotlinSourceRoots(sourceFiles.map { it.absolutePath })
|
configuration.addKotlinSourceRoots(sourceFiles.map { it.absolutePath })
|
||||||
val stdlibFile = ForTestCompileRuntime.stdlibCommonForTests()
|
val stdlibFile = ForTestCompileRuntime.stdlibCommonForTests()
|
||||||
|
// support for the legacy version of kotlin-stdlib-common (JAR with .kotlin_metadata)
|
||||||
configuration.addJvmClasspathRoot(stdlibFile)
|
configuration.addJvmClasspathRoot(stdlibFile)
|
||||||
|
|
||||||
val rootDisposable = Disposer.newDisposable("Disposable for ${KlibTestUtil::class.simpleName}.compileCommonSourcesToKlib")
|
val rootDisposable = Disposer.newDisposable("Disposable for ${KlibTestUtil::class.simpleName}.compileCommonSourcesToKlib")
|
||||||
@@ -63,6 +72,8 @@ object KlibTestUtil {
|
|||||||
extensionConfigs = EnvironmentConfigFiles.METADATA_CONFIG_FILES
|
extensionConfigs = EnvironmentConfigFiles.METADATA_CONFIG_FILES
|
||||||
)
|
)
|
||||||
|
|
||||||
|
val projectContext = ProjectContext(environment.project, "Compile common sources to KLIB metadata")
|
||||||
|
|
||||||
val analyzer = AnalyzerWithCompilerReport(
|
val analyzer = AnalyzerWithCompilerReport(
|
||||||
configuration.getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY),
|
configuration.getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY),
|
||||||
configuration.languageVersionSettings,
|
configuration.languageVersionSettings,
|
||||||
@@ -77,6 +88,9 @@ object KlibTestUtil {
|
|||||||
environment.configuration.languageVersionSettings,
|
environment.configuration.languageVersionSettings,
|
||||||
CommonPlatforms.defaultCommonPlatform,
|
CommonPlatforms.defaultCommonPlatform,
|
||||||
CompilerEnvironment,
|
CompilerEnvironment,
|
||||||
|
explicitProjectContext = projectContext,
|
||||||
|
// support for the KLIB version of kotlin-stdlib-common (KLIB with .knm metadata)
|
||||||
|
dependenciesContainer = createDependencyContainerForStdlibIfKlib(stdlibFile.toPath(), environment, projectContext),
|
||||||
) { content ->
|
) { content ->
|
||||||
environment.createPackagePartProvider(content.moduleContentScope)
|
environment.createPackagePartProvider(content.moduleContentScope)
|
||||||
}
|
}
|
||||||
@@ -153,3 +167,96 @@ object KlibTestUtil {
|
|||||||
return module
|
return module
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a dependency container that includes common stdlib, if the passed file path points to a metadata KLIB in the supported format.
|
||||||
|
* Note that [resolveSingleFileKlib] is sensitive to the library layout and to the file extension.
|
||||||
|
* In the case of a custom klib layout or file extension other than .klib, the library won't be resolved even if it contains .knm files.
|
||||||
|
* For the current kotlin-stdlib-common.jar it will always return null, the purpose of the function is to simplify future migration.
|
||||||
|
* It's been checked that the dependency container for a library with the supported layout is functional.
|
||||||
|
* See KTI-1457.
|
||||||
|
*/
|
||||||
|
private fun createDependencyContainerForStdlibIfKlib(
|
||||||
|
stdlibFilePath: Path,
|
||||||
|
environment: KotlinCoreEnvironment,
|
||||||
|
projectContext: ProjectContext,
|
||||||
|
): CommonDependenciesContainerImpl? {
|
||||||
|
val stdlibKlib = resolveSingleFileKlib(KFile(stdlibFilePath), strategy = ToolingSingleFileKlibResolveStrategy).also {
|
||||||
|
try {
|
||||||
|
it.moduleName // trigger an exception in case of unsupported file/layout
|
||||||
|
} catch (e: IOException) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val stdlibModuleDescriptor = createAndInitializeKlibBasedStdlibCommonDescriptor(stdlibKlib, environment, projectContext)
|
||||||
|
return CommonDependenciesContainerImpl(listOf(stdlibModuleDescriptor))
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createAndInitializeKlibBasedStdlibCommonDescriptor(
|
||||||
|
stdlibKlib: KotlinLibrary,
|
||||||
|
environment: KotlinCoreEnvironment,
|
||||||
|
projectContext: ProjectContext,
|
||||||
|
): ModuleDescriptor {
|
||||||
|
val stdlibCommonDescriptor = ModuleDescriptorImpl(
|
||||||
|
Name.special("<stdlib-common>"),
|
||||||
|
projectContext.storageManager, DefaultBuiltIns.Instance, CommonPlatforms.defaultCommonPlatform
|
||||||
|
).also {
|
||||||
|
it.setDependencies(it)
|
||||||
|
}
|
||||||
|
|
||||||
|
val metadataModuleDescriptorFactory: KlibMetadataModuleDescriptorFactory = KlibMetadataFactories(
|
||||||
|
{ DefaultBuiltIns.Instance },
|
||||||
|
NullFlexibleTypeDeserializer,
|
||||||
|
).DefaultDeserializedDescriptorFactory
|
||||||
|
|
||||||
|
val klibPackageFragmentProvider = metadataModuleDescriptorFactory.createPackageFragmentProvider(
|
||||||
|
library = stdlibKlib,
|
||||||
|
packageAccessHandler = null,
|
||||||
|
packageFragmentNames = parseModuleHeader(stdlibKlib.moduleHeaderData).packageFragmentNameList,
|
||||||
|
storageManager = projectContext.storageManager,
|
||||||
|
moduleDescriptor = stdlibCommonDescriptor,
|
||||||
|
configuration = CompilerDeserializationConfiguration(environment.configuration.languageVersionSettings),
|
||||||
|
compositePackageFragmentAddend = null,
|
||||||
|
lookupTracker = LookupTracker.DO_NOTHING,
|
||||||
|
)
|
||||||
|
|
||||||
|
stdlibCommonDescriptor.initialize(
|
||||||
|
CompositePackageFragmentProvider(
|
||||||
|
listOf(
|
||||||
|
klibPackageFragmentProvider,
|
||||||
|
DefaultBuiltIns.Instance.builtInsModule.packageFragmentProvider,
|
||||||
|
),
|
||||||
|
"Test provider for .knm metadata and built-in declarations of kotlin-stdlib-common"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
return stdlibCommonDescriptor
|
||||||
|
}
|
||||||
|
|
||||||
|
private class CommonDependenciesContainerImpl(dependencies: Collection<ModuleDescriptor>) : CommonDependenciesContainer {
|
||||||
|
private class ModuleInfoImpl(val module: ModuleDescriptor) : ModuleInfo {
|
||||||
|
override val name: Name get() = module.name
|
||||||
|
|
||||||
|
override fun dependencies(): List<ModuleInfo> = listOf(this)
|
||||||
|
override fun dependencyOnBuiltIns(): ModuleInfo.DependencyOnBuiltIns = ModuleInfo.DependencyOnBuiltIns.LAST
|
||||||
|
|
||||||
|
override val platform: TargetPlatform get() = CommonPlatforms.defaultCommonPlatform
|
||||||
|
override val analyzerServices: PlatformDependentAnalyzerServices get() = CommonPlatformAnalyzerServices
|
||||||
|
}
|
||||||
|
|
||||||
|
private val moduleDescriptorByModuleInfo: Map<ModuleInfo, ModuleDescriptor> = dependencies.associateBy(::ModuleInfoImpl)
|
||||||
|
|
||||||
|
override val moduleInfos: List<ModuleInfo> get() = moduleDescriptorByModuleInfo.keys.toList()
|
||||||
|
|
||||||
|
override fun moduleDescriptorForModuleInfo(moduleInfo: ModuleInfo): ModuleDescriptor {
|
||||||
|
return moduleDescriptorByModuleInfo[moduleInfo]
|
||||||
|
?: error("Unknown module info $moduleInfo")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun registerDependencyForAllModules(moduleInfo: ModuleInfo, descriptorForModule: ModuleDescriptorImpl) = Unit
|
||||||
|
override fun packageFragmentProviderForModuleInfo(moduleInfo: ModuleInfo): PackageFragmentProvider? = null
|
||||||
|
|
||||||
|
override val friendModuleInfos: List<ModuleInfo> get() = emptyList()
|
||||||
|
override val refinesModuleInfos: List<ModuleInfo> get() = emptyList()
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user