Extract common AbstractMetadataSerializer

With inheritors: MetadataSerializer, K2MetadataKlibSerializer, FirMetadataSerializer
This commit is contained in:
Ivan Kochurkin
2023-01-17 23:20:56 +01:00
committed by Space Team
parent 8a8823e81a
commit 1dde34b610
9 changed files with 155 additions and 140 deletions
@@ -5,7 +5,6 @@
package org.jetbrains.kotlin.serialization.builtins package org.jetbrains.kotlin.serialization.builtins
import com.intellij.openapi.project.Project
import com.intellij.openapi.util.Disposer import com.intellij.openapi.util.Disposer
import org.jetbrains.kotlin.builtins.StandardNames import org.jetbrains.kotlin.builtins.StandardNames
import org.jetbrains.kotlin.builtins.jvm.JvmBuiltInClassDescriptorFactory import org.jetbrains.kotlin.builtins.jvm.JvmBuiltInClassDescriptorFactory
@@ -15,19 +14,18 @@ import org.jetbrains.kotlin.cli.common.config.addKotlinSourceRoots
import org.jetbrains.kotlin.cli.common.messages.* import org.jetbrains.kotlin.cli.common.messages.*
import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
import org.jetbrains.kotlin.cli.jvm.config.configureJdkClasspathRoots
import org.jetbrains.kotlin.cli.jvm.config.addJvmClasspathRoots import org.jetbrains.kotlin.cli.jvm.config.addJvmClasspathRoots
import org.jetbrains.kotlin.cli.jvm.config.configureJdkClasspathRoots
import org.jetbrains.kotlin.cli.metadata.CommonAnalysisResult
import org.jetbrains.kotlin.cli.metadata.MetadataSerializer import org.jetbrains.kotlin.cli.metadata.MetadataSerializer
import org.jetbrains.kotlin.config.CommonConfigurationKeys import org.jetbrains.kotlin.config.CommonConfigurationKeys
import org.jetbrains.kotlin.config.CompilerConfiguration import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.config.languageVersionSettings
import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.descriptors.impl.EmptyPackageFragmentDescriptor import org.jetbrains.kotlin.descriptors.impl.EmptyPackageFragmentDescriptor
import org.jetbrains.kotlin.metadata.builtins.BuiltInsBinaryVersion import org.jetbrains.kotlin.metadata.builtins.BuiltInsBinaryVersion
import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
import org.jetbrains.kotlin.serialization.KotlinSerializerExtensionBase import org.jetbrains.kotlin.serialization.KotlinSerializerExtensionBase
@@ -35,76 +33,78 @@ import org.jetbrains.kotlin.serialization.deserialization.builtins.BuiltInSerial
import org.jetbrains.kotlin.storage.LockBasedStorageManager import org.jetbrains.kotlin.storage.LockBasedStorageManager
import java.io.File import java.io.File
class BuiltInsSerializer(dependOnOldBuiltIns: Boolean) : MetadataSerializer(BuiltInsBinaryVersion.INSTANCE, dependOnOldBuiltIns) { class BuiltInsSerializer(
fun serialize( configuration: CompilerConfiguration,
environment: KotlinCoreEnvironment,
dependOnOldBuiltIns: Boolean
) : MetadataSerializer(configuration, environment, dependOnOldBuiltIns, BuiltInsBinaryVersion.INSTANCE) {
companion object {
fun analyzeAndSerialize(
destDir: File, destDir: File,
srcDirs: List<File>, srcDirs: List<File>,
extraClassPath: List<File>, extraClassPath: List<File>,
dependOnOldBuiltIns: Boolean,
onComplete: (totalSize: Int, totalFiles: Int) -> Unit onComplete: (totalSize: Int, totalFiles: Int) -> Unit
) { ) {
val rootDisposable = Disposer.newDisposable() val rootDisposable = Disposer.newDisposable()
val messageCollector = createMessageCollector() val messageCollector = createMessageCollector()
val performanceManager = object : CommonCompilerPerformanceManager(presentableName = "test") {} val performanceManager = object : CommonCompilerPerformanceManager(presentableName = "test") {}
try { try {
val configuration = CompilerConfiguration().apply { val configuration = CompilerConfiguration().apply {
put(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY, messageCollector) put(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY, messageCollector)
addKotlinSourceRoots(srcDirs.map { it.path }) addKotlinSourceRoots(srcDirs.map { it.path })
addJvmClasspathRoots(extraClassPath) addJvmClasspathRoots(extraClassPath)
configureJdkClasspathRoots() configureJdkClasspathRoots()
put(CLIConfigurationKeys.METADATA_DESTINATION_DIRECTORY, destDir) put(CLIConfigurationKeys.METADATA_DESTINATION_DIRECTORY, destDir)
put(CommonConfigurationKeys.MODULE_NAME, "module for built-ins serialization") put(CommonConfigurationKeys.MODULE_NAME, "module for built-ins serialization")
put(CLIConfigurationKeys.PERF_MANAGER, performanceManager) put(CLIConfigurationKeys.PERF_MANAGER, performanceManager)
}
val environment = KotlinCoreEnvironment.createForProduction(rootDisposable, configuration, EnvironmentConfigFiles.JVM_CONFIG_FILES)
val serializer = BuiltInsSerializer(configuration, environment, dependOnOldBuiltIns)
serializer.analyzeAndSerialize()
onComplete(serializer.totalSize, serializer.totalFiles)
} finally {
messageCollector.flush()
Disposer.dispose(rootDisposable)
} }
val environment = KotlinCoreEnvironment.createForProduction(rootDisposable, configuration, EnvironmentConfigFiles.JVM_CONFIG_FILES)
serialize(environment)
onComplete(totalSize, totalFiles)
} }
finally {
messageCollector.flush()
Disposer.dispose(rootDisposable)
}
}
private fun createMessageCollector() = object : GroupingMessageCollector( private fun createMessageCollector() = object : GroupingMessageCollector(
PrintingMessageCollector(System.err, MessageRenderer.PLAIN_RELATIVE_PATHS, false), PrintingMessageCollector(System.err, MessageRenderer.PLAIN_RELATIVE_PATHS, false),
false false
) { ) {
override fun report(severity: CompilerMessageSeverity, message: String, location: CompilerMessageSourceLocation?) { override fun report(severity: CompilerMessageSeverity, message: String, location: CompilerMessageSourceLocation?) {
// Only report diagnostics without a particular location because there's plenty of errors in built-in sources // Only report diagnostics without a particular location because there's plenty of errors in built-in sources
// (functions without bodies, incorrect combination of modifiers, etc.) // (functions without bodies, incorrect combination of modifiers, etc.)
if (location == null) { if (location == null) {
super.report(severity, message, location) super.report(severity, message, location)
}
} }
} }
} }
override fun performSerialization( override fun serialize(analysisResult: CommonAnalysisResult, destDir: File) {
files: Collection<KtFile>, val files = environment.getSourceFiles()
bindingContext: BindingContext, val module = analysisResult.moduleDescriptor
module: ModuleDescriptor,
destDir: File,
project: Project?,
languageVersionSettings: LanguageVersionSettings,
) {
destDir.deleteRecursively() destDir.deleteRecursively()
if (!destDir.mkdirs()) { if (!destDir.mkdirs()) {
throw AssertionError("Could not make directories: " + destDir) throw AssertionError("Could not make directories: " + destDir)
} }
files.map { it.packageFqName }.toSet().forEach { files.map { it.packageFqName }.toSet().forEach { fqName ->
fqName ->
val packageView = module.getPackage(fqName) val packageView = module.getPackage(fqName)
PackageSerializer( PackageSerializer(
packageView.memberScope.getContributedDescriptors(DescriptorKindFilter.CLASSIFIERS) + createCloneable(module), packageView.memberScope.getContributedDescriptors(DescriptorKindFilter.CLASSIFIERS) + createCloneable(module),
packageView.fragments.flatMap { fragment -> DescriptorUtils.getAllDescriptors(fragment.getMemberScope()) }, packageView.fragments.flatMap { fragment -> DescriptorUtils.getAllDescriptors(fragment.getMemberScope()) },
packageView.fqName, packageView.fqName,
File(destDir, BuiltInSerializerProtocol.getBuiltInsFilePath(packageView.fqName)), File(destDir, BuiltInSerializerProtocol.getBuiltInsFilePath(packageView.fqName)),
languageVersionSettings, environment.configuration.languageVersionSettings,
).run() ).run()
} }
} }
@@ -118,6 +118,6 @@ class BuiltInsSerializer(dependOnOldBuiltIns: Boolean) : MetadataSerializer(Buil
EmptyPackageFragmentDescriptor(module, StandardNames.BUILT_INS_PACKAGE_FQ_NAME) EmptyPackageFragmentDescriptor(module, StandardNames.BUILT_INS_PACKAGE_FQ_NAME)
} }
return factory.createClass(ClassId.topLevel(StandardNames.FqNames.cloneable.toSafe())) return factory.createClass(ClassId.topLevel(StandardNames.FqNames.cloneable.toSafe()))
?: error("Could not create kotlin.Cloneable in $module") ?: error("Could not create kotlin.Cloneable in $module")
} }
} }
@@ -41,7 +41,7 @@ found top-level declarations to <destination dir> (*.kotlin_builtins files)"""
val missing = srcDirs.filterNot(File::exists) val missing = srcDirs.filterNot(File::exists)
assert(missing.isEmpty()) { "These source directories are missing: $missing" } assert(missing.isEmpty()) { "These source directories are missing: $missing" }
BuiltInsSerializer(dependOnOldBuiltIns = false).serialize(destDir, srcDirs, listOf()) { totalSize, totalFiles -> BuiltInsSerializer.analyzeAndSerialize(destDir, srcDirs, listOf(), dependOnOldBuiltIns = false) { totalSize, totalFiles ->
if (System.getProperty("kotlin.builtins.serializer.log") == "true") { if (System.getProperty("kotlin.builtins.serializer.log") == "true") {
println("Total bytes written: $totalSize to $totalFiles files") println("Total bytes written: $totalSize to $totalFiles files")
} }
@@ -0,0 +1,45 @@
/*
* 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.cli.metadata
import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
import org.jetbrains.kotlin.config.CommonConfigurationKeys
import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.metadata.builtins.BuiltInsBinaryVersion
import java.io.File
abstract class AbstractMetadataSerializer<T>(
val configuration: CompilerConfiguration,
val environment: KotlinCoreEnvironment,
definedMetadataVersion: BuiltInsBinaryVersion? = null
) {
protected val metadataVersion =
definedMetadataVersion ?: configuration.get(CommonConfigurationKeys.METADATA_VERSION) as? BuiltInsBinaryVersion
?: BuiltInsBinaryVersion.INSTANCE
fun analyzeAndSerialize() {
val destDir = environment.destDir
if (destDir == null) {
val configuration = environment.configuration
val messageCollector = configuration.getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY)
messageCollector.report(CompilerMessageSeverity.ERROR, "Specify destination via -d")
return
}
val analysisResult = analyze() ?: return
val performanceManager = environment.configuration.getNotNull(CLIConfigurationKeys.PERF_MANAGER)
performanceManager.notifyGenerationStarted()
serialize(analysisResult, destDir)
performanceManager.notifyGenerationFinished()
}
protected abstract fun analyze(): T?
protected abstract fun serialize(analysisResult: T, destDir: File)
}
@@ -10,7 +10,6 @@ import org.jetbrains.kotlin.analyzer.common.CommonDependenciesContainer
import org.jetbrains.kotlin.analyzer.common.CommonResolverForModuleFactory import org.jetbrains.kotlin.analyzer.common.CommonResolverForModuleFactory
import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys
import org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport import org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
import org.jetbrains.kotlin.config.CommonConfigurationKeys import org.jetbrains.kotlin.config.CommonConfigurationKeys
import org.jetbrains.kotlin.config.languageVersionSettings import org.jetbrains.kotlin.config.languageVersionSettings
@@ -31,13 +30,6 @@ internal fun runCommonAnalysisForSerialization(
dependOnBuiltins: Boolean, dependOnBuiltins: Boolean,
dependencyContainerFactory: () -> CommonDependenciesContainer? dependencyContainerFactory: () -> CommonDependenciesContainer?
): CommonAnalysisResult? { ): CommonAnalysisResult? {
if (environment.destDir == null) {
val configuration = environment.configuration
val messageCollector = configuration.getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY)
messageCollector.report(CompilerMessageSeverity.ERROR, "Specify destination via -d")
return null
}
val performanceManager = environment.configuration.getNotNull(CLIConfigurationKeys.PERF_MANAGER) val performanceManager = environment.configuration.getNotNull(CLIConfigurationKeys.PERF_MANAGER)
var analysisResultWithHasErrors: AnalysisResultWithHasErrors var analysisResultWithHasErrors: AnalysisResultWithHasErrors
@@ -5,13 +5,11 @@
package org.jetbrains.kotlin.cli.metadata package org.jetbrains.kotlin.cli.metadata
import com.intellij.openapi.Disposable
import com.intellij.openapi.vfs.StandardFileSystems import com.intellij.openapi.vfs.StandardFileSystems
import com.intellij.openapi.vfs.VirtualFileManager import com.intellij.openapi.vfs.VirtualFileManager
import org.jetbrains.kotlin.KtSourceFile import org.jetbrains.kotlin.KtSourceFile
import org.jetbrains.kotlin.analyzer.common.CommonPlatformAnalyzerServices import org.jetbrains.kotlin.analyzer.common.CommonPlatformAnalyzerServices
import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys
import org.jetbrains.kotlin.cli.common.CommonCompilerPerformanceManager
import org.jetbrains.kotlin.cli.common.fir.FirDiagnosticsCompilerResultsReporter import org.jetbrains.kotlin.cli.common.fir.FirDiagnosticsCompilerResultsReporter
import org.jetbrains.kotlin.cli.jvm.compiler.* import org.jetbrains.kotlin.cli.jvm.compiler.*
import org.jetbrains.kotlin.cli.jvm.compiler.pipeline.collectSources import org.jetbrains.kotlin.cli.jvm.compiler.pipeline.collectSources
@@ -28,6 +26,8 @@ import org.jetbrains.kotlin.fir.pipeline.ModuleCompilerAnalyzedOutput
import org.jetbrains.kotlin.fir.pipeline.buildFirFromKtFiles import org.jetbrains.kotlin.fir.pipeline.buildFirFromKtFiles
import org.jetbrains.kotlin.fir.pipeline.buildFirViaLightTree import org.jetbrains.kotlin.fir.pipeline.buildFirViaLightTree
import org.jetbrains.kotlin.fir.pipeline.resolveAndCheckFir import org.jetbrains.kotlin.fir.pipeline.resolveAndCheckFir
import org.jetbrains.kotlin.fir.serialization.FirElementAwareSerializableStringTable
import org.jetbrains.kotlin.fir.serialization.FirKLibSerializerExtension
import org.jetbrains.kotlin.fir.serialization.serializeSingleFirFile import org.jetbrains.kotlin.fir.serialization.serializeSingleFirFile
import org.jetbrains.kotlin.fir.session.FirCommonSessionFactory import org.jetbrains.kotlin.fir.session.FirCommonSessionFactory
import org.jetbrains.kotlin.fir.session.IncrementalCompilationContext import org.jetbrains.kotlin.fir.session.IncrementalCompilationContext
@@ -40,31 +40,20 @@ import org.jetbrains.kotlin.library.impl.buildKotlinLibrary
import org.jetbrains.kotlin.library.metadata.KlibMetadataHeaderFlags import org.jetbrains.kotlin.library.metadata.KlibMetadataHeaderFlags
import org.jetbrains.kotlin.library.metadata.KlibMetadataProtoBuf import org.jetbrains.kotlin.library.metadata.KlibMetadataProtoBuf
import org.jetbrains.kotlin.library.metadata.KlibMetadataVersion import org.jetbrains.kotlin.library.metadata.KlibMetadataVersion
import org.jetbrains.kotlin.metadata.builtins.BuiltInsBinaryVersion
import org.jetbrains.kotlin.modules.TargetId import org.jetbrains.kotlin.modules.TargetId
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.psi.KtFile import org.jetbrains.kotlin.psi.KtFile
import java.io.File import java.io.File
internal class FirMetadataSerializer(private val metadataVersion: BuiltInsBinaryVersion) { internal class FirMetadataSerializer(
fun serialize(environment: KotlinCoreEnvironment, rootDisposable: Disposable) { configuration: CompilerConfiguration,
environment: KotlinCoreEnvironment
) : AbstractMetadataSerializer<ModuleCompilerAnalyzedOutput>(configuration, environment) {
override fun analyze(): ModuleCompilerAnalyzedOutput? {
val performanceManager = environment.configuration.getNotNull(CLIConfigurationKeys.PERF_MANAGER) val performanceManager = environment.configuration.getNotNull(CLIConfigurationKeys.PERF_MANAGER)
performanceManager.notifyAnalysisStarted() performanceManager.notifyAnalysisStarted()
val compilerResult = runFirCompiler(environment, performanceManager, rootDisposable) ?: return
performanceManager.notifyAnalysisFinished()
performanceManager.notifyGenerationStarted()
performSerialization(compilerResult, environment.configuration, checkNotNull(environment.destDir))
performanceManager.notifyGenerationFinished()
}
private fun runFirCompiler(
environment: KotlinCoreEnvironment,
performanceManager: CommonCompilerPerformanceManager,
rootDisposable: Disposable
): ModuleCompilerAnalyzedOutput? {
val configuration = environment.configuration val configuration = environment.configuration
val messageCollector = configuration.getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY) val messageCollector = configuration.getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY)
val moduleName = Name.special("<${configuration.getNotNull(CommonConfigurationKeys.MODULE_NAME)}>") val moduleName = Name.special("<${configuration.getNotNull(CommonConfigurationKeys.MODULE_NAME)}>")
@@ -164,19 +153,30 @@ internal class FirMetadataSerializer(private val metadataVersion: BuiltInsBinary
null null
} else { } else {
result result
}.also {
performanceManager.notifyAnalysisFinished()
} }
} }
private fun performSerialization(firOutput: ModuleCompilerAnalyzedOutput, configuration: CompilerConfiguration, destDir: File) { override fun serialize(analysisResult: ModuleCompilerAnalyzedOutput, destDir: File) {
val fragments = mutableMapOf<String, MutableList<ByteArray>>() val fragments = mutableMapOf<String, MutableList<ByteArray>>()
for (firFile in firOutput.fir) { val (session, scopeSession, fir) = analysisResult
val packageFragment = serializeSingleFirFile(firFile, firOutput.session, firOutput.scopeSession, metadataVersion)
val languageVersionSettings = environment.configuration.languageVersionSettings
for (firFile in fir) {
val packageFragment = serializeSingleFirFile(
firFile,
session,
scopeSession,
FirKLibSerializerExtension(session, metadataVersion, FirElementAwareSerializableStringTable()),
languageVersionSettings
)
fragments.getOrPut(firFile.packageFqName.asString()) { mutableListOf() }.add(packageFragment.toByteArray()) fragments.getOrPut(firFile.packageFqName.asString()) { mutableListOf() }.add(packageFragment.toByteArray())
} }
val header = KlibMetadataProtoBuf.Header.newBuilder() val header = KlibMetadataProtoBuf.Header.newBuilder()
header.moduleName = firOutput.session.moduleData.name.asString() header.moduleName = session.moduleData.name.asString()
if (configuration.languageVersionSettings.isPreRelease()) { if (configuration.languageVersionSettings.isPreRelease()) {
header.flags = KlibMetadataHeaderFlags.PRE_RELEASE header.flags = KlibMetadataHeaderFlags.PRE_RELEASE
@@ -112,17 +112,13 @@ class K2MetadataCompiler : CLICompiler<K2MetadataCompilerArguments>() {
checkKotlinPackageUsage(environment.configuration, environment.getSourceFiles()) checkKotlinPackageUsage(environment.configuration, environment.getSourceFiles())
try { try {
val metadataVersion = val useFir = configuration.getBoolean(CommonConfigurationKeys.USE_FIR)
configuration.get(CommonConfigurationKeys.METADATA_VERSION) as? BuiltInsBinaryVersion ?: BuiltInsBinaryVersion.INSTANCE val metadataSerializer = when {
if (configuration.getBoolean(CommonConfigurationKeys.USE_FIR)) { useFir -> FirMetadataSerializer(configuration, environment)
FirMetadataSerializer(metadataVersion).serialize(environment, rootDisposable) arguments.expectActualLinker -> K2MetadataKlibSerializer(configuration, environment)
} else { else -> MetadataSerializer(configuration, environment, dependOnOldBuiltIns = true)
if (arguments.expectActualLinker) {
K2MetadataKlibSerializer(metadataVersion).serialize(environment)
} else {
MetadataSerializer(metadataVersion, true).serialize(environment)
}
} }
metadataSerializer.analyzeAndSerialize()
} catch (e: CompilationException) { } catch (e: CompilationException) {
collector.report(EXCEPTION, OutputMessageUtil.renderException(e), MessageUtil.psiElementToMessageLocation(e.element)) collector.report(EXCEPTION, OutputMessageUtil.renderException(e), MessageUtil.psiElementToMessageLocation(e.element))
return ExitCode.INTERNAL_ERROR return ExitCode.INTERNAL_ERROR
@@ -5,7 +5,6 @@
package org.jetbrains.kotlin.cli.metadata package org.jetbrains.kotlin.cli.metadata
import com.intellij.openapi.project.Project
import org.jetbrains.kotlin.analyzer.ModuleInfo import org.jetbrains.kotlin.analyzer.ModuleInfo
import org.jetbrains.kotlin.analyzer.common.CommonDependenciesContainer import org.jetbrains.kotlin.analyzer.common.CommonDependenciesContainer
import org.jetbrains.kotlin.analyzer.common.CommonPlatformAnalyzerServices import org.jetbrains.kotlin.analyzer.common.CommonPlatformAnalyzerServices
@@ -29,7 +28,6 @@ import org.jetbrains.kotlin.library.impl.BuiltInsPlatform
import org.jetbrains.kotlin.library.impl.buildKotlinLibrary import org.jetbrains.kotlin.library.impl.buildKotlinLibrary
import org.jetbrains.kotlin.library.metadata.* import org.jetbrains.kotlin.library.metadata.*
import org.jetbrains.kotlin.library.metadata.impl.KlibMetadataModuleDescriptorFactoryImpl import org.jetbrains.kotlin.library.metadata.impl.KlibMetadataModuleDescriptorFactoryImpl
import org.jetbrains.kotlin.metadata.builtins.BuiltInsBinaryVersion
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.platform.TargetPlatform
@@ -40,30 +38,23 @@ import org.jetbrains.kotlin.storage.StorageManager
import org.jetbrains.kotlin.utils.keysToMap import org.jetbrains.kotlin.utils.keysToMap
import java.io.File import java.io.File
internal class K2MetadataKlibSerializer(private val metadataVersion: BuiltInsBinaryVersion) { internal class K2MetadataKlibSerializer(
fun serialize(environment: KotlinCoreEnvironment) { configuration: CompilerConfiguration,
val configuration = environment.configuration environment: KotlinCoreEnvironment
val performanceManager = configuration.getNotNull(CLIConfigurationKeys.PERF_MANAGER) ) : AbstractMetadataSerializer<CommonAnalysisResult>(configuration, environment) {
override fun analyze(): CommonAnalysisResult? {
val analysisResult = runCommonAnalysisForSerialization(environment, true, dependencyContainerFactory = { return runCommonAnalysisForSerialization(environment, true, dependencyContainerFactory = {
KlibMetadataDependencyContainer( KlibMetadataDependencyContainer(
configuration, configuration,
LockBasedStorageManager("K2MetadataKlibSerializer") LockBasedStorageManager("K2MetadataKlibSerializer")
) )
}) ?: return })
performanceManager.notifyGenerationStarted()
val destDir = checkNotNull(environment.destDir)
performSerialization(configuration, analysisResult.moduleDescriptor, destDir, environment.project)
performanceManager.notifyGenerationFinished()
} }
private fun performSerialization( override fun serialize(analysisResult: CommonAnalysisResult, destDir: File) {
configuration: CompilerConfiguration, val project = environment.project
module: ModuleDescriptor, val module = analysisResult.moduleDescriptor
destDir: File,
project: Project
) {
val serializedMetadata: SerializedMetadata = KlibMetadataMonolithicSerializer( val serializedMetadata: SerializedMetadata = KlibMetadataMonolithicSerializer(
configuration.languageVersionSettings, configuration.languageVersionSettings,
metadataVersion, metadataVersion,
@@ -6,15 +6,14 @@
package org.jetbrains.kotlin.cli.metadata package org.jetbrains.kotlin.cli.metadata
import com.intellij.openapi.project.Project import com.intellij.openapi.project.Project
import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
import org.jetbrains.kotlin.codegen.JvmCodegenUtil import org.jetbrains.kotlin.codegen.JvmCodegenUtil
import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.config.languageVersionSettings import org.jetbrains.kotlin.config.languageVersionSettings
import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.load.kotlin.PackagePartClassUtils import org.jetbrains.kotlin.load.kotlin.PackagePartClassUtils
import org.jetbrains.kotlin.metadata.ProtoBuf import org.jetbrains.kotlin.metadata.ProtoBuf
import org.jetbrains.kotlin.metadata.builtins.BuiltInsBinaryVersion import org.jetbrains.kotlin.metadata.builtins.BuiltInsBinaryVersion
@@ -35,33 +34,24 @@ import java.io.DataOutputStream
import java.io.File import java.io.File
open class MetadataSerializer( open class MetadataSerializer(
private val metadataVersion: BuiltInsBinaryVersion, configuration: CompilerConfiguration,
private val dependOnOldBuiltIns: Boolean environment: KotlinCoreEnvironment,
) { private val dependOnOldBuiltIns: Boolean,
definedMetadataVersion: BuiltInsBinaryVersion? = null
) : AbstractMetadataSerializer<CommonAnalysisResult>(configuration, environment, definedMetadataVersion) {
protected var totalSize = 0 protected var totalSize = 0
protected var totalFiles = 0 protected var totalFiles = 0
fun serialize(environment: KotlinCoreEnvironment) { override fun analyze(): CommonAnalysisResult? {
val performanceManager = environment.configuration.getNotNull(CLIConfigurationKeys.PERF_MANAGER) return runCommonAnalysisForSerialization(environment, dependOnOldBuiltIns, dependencyContainerFactory = { null })
val analysisResult = runCommonAnalysisForSerialization(environment, dependOnOldBuiltIns, dependencyContainerFactory = { null })
?: return
val (moduleDescriptor, bindingContext) = analysisResult
performanceManager.notifyGenerationStarted()
val destDir = checkNotNull(environment.destDir)
performSerialization(
environment.getSourceFiles(), bindingContext, moduleDescriptor, destDir, environment.project,
environment.configuration.languageVersionSettings
)
performanceManager.notifyGenerationFinished()
} }
protected open fun performSerialization( override fun serialize(analysisResult: CommonAnalysisResult, destDir: File) {
files: Collection<KtFile>, bindingContext: BindingContext, module: ModuleDescriptor, destDir: File, project: Project?, val languageVersionSettings = environment.configuration.languageVersionSettings
languageVersionSettings: LanguageVersionSettings, val files = environment.getSourceFiles()
) { val project = environment.project
val (module, bindingContext) = analysisResult
val packageTable = hashMapOf<FqName, PackageParts>() val packageTable = hashMapOf<FqName, PackageParts>()
for (file in files) { for (file in files) {
@@ -33,11 +33,12 @@ import java.io.FileInputStream
class BuiltInsSerializerTest : TestCaseWithTmpdir() { class BuiltInsSerializerTest : TestCaseWithTmpdir() {
private fun doTest(fileName: String) { private fun doTest(fileName: String) {
val source = "compiler/testData/serialization/builtinsSerializer/$fileName" val source = "compiler/testData/serialization/builtinsSerializer/$fileName"
BuiltInsSerializer(dependOnOldBuiltIns = true).serialize( BuiltInsSerializer.analyzeAndSerialize(
tmpdir, tmpdir,
srcDirs = listOf(File(source)), srcDirs = listOf(File(source)),
extraClassPath = listOf(ForTestCompileRuntime.runtimeJarForTests()), extraClassPath = listOf(ForTestCompileRuntime.runtimeJarForTests()),
onComplete = { _, _ -> } dependOnOldBuiltIns = true,
onComplete = { _, _ -> }
) )
val module = KotlinTestUtils.createEmptyModule("<module>", DefaultBuiltIns.Instance) val module = KotlinTestUtils.createEmptyModule("<module>", DefaultBuiltIns.Instance)