Commonizing klib metadata between native and js

This commit is contained in:
Alexander Gorshenev
2019-07-26 14:45:18 +03:00
committed by alexander-gorshenev
parent f38123e78c
commit c227c13799
98 changed files with 3265 additions and 7848 deletions
-127
View File
@@ -1,127 +0,0 @@
/*
* Copyright 2010-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.ir.backend.js.lower.serialization.metadata;
import "core/metadata/src/metadata.proto";
option java_outer_classname = "JsKlibMetadataProtoBuf";
option optimize_for = LITE_RUNTIME;
message Header {
/*
preRelease
*/
optional int32 flags = 1;
// (patch << 16) + (minor << 8) + major
optional int32 js_code_binary_version = 2 [default = 1];
optional string package_fq_name = 3;
optional org.jetbrains.kotlin.metadata.StringTable strings = 4;
optional org.jetbrains.kotlin.metadata.QualifiedNameTable qualified_names = 5;
// Annotations on the whole module
repeated org.jetbrains.kotlin.metadata.Annotation annotation = 6;
}
message File {
// If absent, id is the index of the file in the Files.file list
optional int32 id = 1;
repeated org.jetbrains.kotlin.metadata.Annotation annotation = 2;
}
message Files {
repeated File file = 1;
}
message DescriptorUniqId {
required int64 index = 1;
}
extend org.jetbrains.kotlin.metadata.Package {
optional int32 package_fq_name = 131;
}
extend org.jetbrains.kotlin.metadata.Class {
repeated org.jetbrains.kotlin.metadata.Annotation class_annotation = 130;
optional int32 class_containing_file_id = 135;
optional DescriptorUniqId class_uniq_id = 136;
}
extend org.jetbrains.kotlin.metadata.Constructor {
repeated org.jetbrains.kotlin.metadata.Annotation constructor_annotation = 130;
optional DescriptorUniqId constructor_uniq_id = 131;
}
extend org.jetbrains.kotlin.metadata.Function {
repeated org.jetbrains.kotlin.metadata.Annotation function_annotation = 130;
optional int32 function_containing_file_id = 135;
optional DescriptorUniqId function_uniq_id = 136;
}
extend org.jetbrains.kotlin.metadata.Property {
repeated org.jetbrains.kotlin.metadata.Annotation property_annotation = 130;
repeated org.jetbrains.kotlin.metadata.Annotation property_getter_annotation = 132;
repeated org.jetbrains.kotlin.metadata.Annotation property_setter_annotation = 133;
optional org.jetbrains.kotlin.metadata.Annotation.Argument.Value compile_time_value = 131;
optional int32 property_containing_file_id = 135;
optional DescriptorUniqId property_uniq_id = 136;
}
extend org.jetbrains.kotlin.metadata.EnumEntry {
repeated org.jetbrains.kotlin.metadata.Annotation enum_entry_annotation = 130;
optional DescriptorUniqId enum_entry_uniq_id = 131;
}
extend org.jetbrains.kotlin.metadata.ValueParameter {
repeated org.jetbrains.kotlin.metadata.Annotation parameter_annotation = 130;
optional DescriptorUniqId value_param_uniq_id = 131;
}
extend org.jetbrains.kotlin.metadata.Type {
repeated org.jetbrains.kotlin.metadata.Annotation type_annotation = 130;
}
extend org.jetbrains.kotlin.metadata.TypeParameter {
repeated org.jetbrains.kotlin.metadata.Annotation type_parameter_annotation = 130;
optional DescriptorUniqId type_param_uniq_id = 131;
}
extend org.jetbrains.kotlin.metadata.PackageFragment {
optional Files package_fragment_files = 130;
}
extend org.jetbrains.kotlin.metadata.TypeAlias {
// TODO repeated org.jetbrains.kotlin.metadata.Annotation type_alias_annotation = 130;
optional DescriptorUniqId type_alias_uniq_id = 131;
}
message Classes {
// id in StringTable
repeated int32 class_name = 1 [packed = true];
}
message Library {
repeated org.jetbrains.kotlin.metadata.PackageFragment package_fragment = 2;
repeated string imported_module = 3;
}
@@ -10,22 +10,20 @@ import com.intellij.openapi.vfs.VfsUtilCore
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.backend.common.LoggingContext
import org.jetbrains.kotlin.backend.common.serialization.DescriptorTable
import org.jetbrains.kotlin.backend.common.serialization.metadata.DynamicTypeDeserializer
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.builtins.functions.functionInterfacePackageFragmentProvider
import org.jetbrains.kotlin.config.CommonConfigurationKeys
import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.config.languageVersionSettings
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.descriptors.impl.CompositePackageFragmentProvider
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
import org.jetbrains.kotlin.incremental.components.LookupTracker
import org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir.JsIrLinker
import org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir.JsIrModuleSerializer
import org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir.JsMangler
import org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir.newJsDescriptorUniqId
import org.jetbrains.kotlin.ir.backend.js.lower.serialization.metadata.*
import org.jetbrains.kotlin.ir.backend.js.lower.serialization.metadata.JsKlibMetadataVersion
import org.jetbrains.kotlin.ir.backend.js.lower.serialization.metadata.KlibMetadataIncrementalSerializer
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
import org.jetbrains.kotlin.ir.util.ExpectDeclarationRemover
@@ -37,11 +35,13 @@ import org.jetbrains.kotlin.js.config.JSConfigurationKeys
import org.jetbrains.kotlin.konan.KonanVersionImpl
import org.jetbrains.kotlin.konan.MetaVersion
import org.jetbrains.kotlin.konan.properties.propertyList
import org.jetbrains.kotlin.konan.util.KlibMetadataFactories
import org.jetbrains.kotlin.library.*
import org.jetbrains.kotlin.library.impl.buildKoltinLibrary
import org.jetbrains.kotlin.library.impl.createKotlinLibrary
import org.jetbrains.kotlin.library.resolver.KotlinLibraryResolveResult
import org.jetbrains.kotlin.library.resolver.TopologicalLibraryOrder
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStatus
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.psi2ir.Psi2IrConfiguration
@@ -49,8 +49,8 @@ import org.jetbrains.kotlin.psi2ir.Psi2IrTranslator
import org.jetbrains.kotlin.psi2ir.generators.GeneratorContext
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.BindingContextUtils
import org.jetbrains.kotlin.resolve.CompilerDeserializationConfiguration
import org.jetbrains.kotlin.storage.LockBasedStorageManager
import org.jetbrains.kotlin.storage.StorageManager
import org.jetbrains.kotlin.utils.DFS
import java.io.File
import org.jetbrains.kotlin.konan.file.File as KFile
@@ -69,8 +69,6 @@ val KotlinLibrary.isBuiltIns: Boolean
fun loadKlib(klibPath: String) =
createKotlinLibrary(KFile(KFile(klibPath).absolutePath))
internal val JS_KLIBRARY_CAPABILITY = ModuleDescriptor.Capability<KotlinLibrary>("JS KLIBRARY")
private val emptyLoggingContext = object : LoggingContext {
override var inVerbosePhase = false
@@ -86,7 +84,7 @@ fun generateKLib(
project: Project,
files: List<KtFile>,
configuration: CompilerConfiguration,
allDependencies: List<KotlinLibrary>,
allDependencies: KotlinLibraryResolveResult,
friendDependencies: List<KotlinLibrary>,
outputKlibPath: String,
nopack: Boolean
@@ -136,7 +134,7 @@ fun generateKLib(
psi2IrContext.bindingContext,
files,
outputKlibPath,
allDependencies,
allDependencies.getFullList(),
moduleFragment,
icData,
nopack
@@ -164,7 +162,7 @@ fun loadIr(
project: Project,
files: List<KtFile>,
configuration: CompilerConfiguration,
allDependencies: List<KotlinLibrary>,
allDependencies: KotlinLibraryResolveResult,
friendDependencies: List<KotlinLibrary>
): IrModuleInfo {
val depsDescriptors = ModulesStructure(project, files, configuration, allDependencies, friendDependencies)
@@ -177,7 +175,7 @@ fun loadIr(
val deserializer = JsIrLinker(moduleDescriptor, JsMangler, emptyLoggingContext, irBuiltIns, symbolTable)
val deserializedModuleFragments = sortDependencies(allDependencies, depsDescriptors.descriptors).map {
val deserializedModuleFragments = sortDependencies(allDependencies.getFullList(), depsDescriptors.descriptors).map {
deserializer.deserializeIrModuleHeader(depsDescriptors.getModuleDescriptor(it))!!
}
@@ -203,70 +201,29 @@ private fun GeneratorContext.generateModuleFragment(files: List<KtFile>, deseria
Psi2IrTranslator(languageVersionSettings, configuration).generateModuleFragment(this, files, deserializer)
private fun loadKlibMetadataParts(
moduleId: KotlinLibrary
): JsKlibMetadataParts {
return JsKlibMetadataSerializationUtil.readModuleAsProto(moduleId.moduleHeaderData)
}
val ModuleDescriptor.kotlinLibrary get() = this.getCapability(JS_KLIBRARY_CAPABILITY)!!
private fun loadKlibMetadata(
parts: JsKlibMetadataParts,
moduleId: KotlinLibrary,
isBuiltIn: Boolean,
lookupTracker: LookupTracker,
storageManager: LockBasedStorageManager,
metadataVersion: JsKlibMetadataVersion,
languageVersionSettings: LanguageVersionSettings,
builtinsModule: ModuleDescriptorImpl?,
dependencies: List<ModuleDescriptorImpl>
): ModuleDescriptorImpl {
assert(isBuiltIn == (builtinsModule === null))
val builtIns = builtinsModule?.builtIns ?: object : KotlinBuiltIns(storageManager) {}
val md = ModuleDescriptorImpl(
Name.special("<${moduleId.moduleName}>"),
storageManager,
builtIns,
capabilities = mapOf(JS_KLIBRARY_CAPABILITY to moduleId)
)
if (isBuiltIn) builtIns.builtInsModule = md
val currentModuleFragmentProvider = createJsKlibMetadataPackageFragmentProvider(
storageManager, md, parts.header, parts.body, metadataVersion,
CompilerDeserializationConfiguration(languageVersionSettings),
lookupTracker
)
val packageFragmentProvider = if (isBuiltIn) {
val functionFragmentProvider = functionInterfacePackageFragmentProvider(storageManager, md)
CompositePackageFragmentProvider(listOf(functionFragmentProvider, currentModuleFragmentProvider))
} else currentModuleFragmentProvider
md.initialize(packageFragmentProvider)
md.setDependencies(listOf(md) + dependencies)
return md
}
private fun createBuiltIns(storageManager: StorageManager) = object : KotlinBuiltIns(storageManager) {}
val JsFactories = KlibMetadataFactories(::createBuiltIns, DynamicTypeDeserializer)
private class ModulesStructure(
private val project: Project,
private val files: List<KtFile>,
val compilerConfiguration: CompilerConfiguration,
private val allDependencies: List<KotlinLibrary>,
val allDependencies: KotlinLibraryResolveResult,
private val friendDependencies: List<KotlinLibrary>
) {
private val deserializedModuleParts: Map<KotlinLibrary, JsKlibMetadataParts> =
allDependencies.associateWith { loadKlibMetadataParts(it) }
val moduleDependencies: Map<KotlinLibrary, List<KotlinLibrary>> = {
val result = mutableMapOf<KotlinLibrary, List<KotlinLibrary>>()
fun findModuleByName(name: String): KotlinLibrary =
allDependencies.find { it.moduleName == name } ?: error("Module is not found: $name")
val moduleDependencies: Map<KotlinLibrary, List<KotlinLibrary>> =
deserializedModuleParts.mapValues { (_, parts) ->
parts.importedModules.map(::findModuleByName)
allDependencies.forEach { klib, _ ->
val dependencies = allDependencies.filterRoots {
it.library == klib
}.getFullList(TopologicalLibraryOrder)
result.put(klib, dependencies.minus(klib))
}
result
}()
val builtInsDep = allDependencies.find { it.isBuiltIns }
val builtInsDep = allDependencies.getFullList().find { it.isBuiltIns }
fun runAnalysis(): JsAnalysisResult {
val analysisResult =
@@ -274,7 +231,7 @@ private class ModulesStructure(
files,
project,
compilerConfiguration,
allDependencies.map { getModuleDescriptor(it) },
allDependencies.getFullList().map { getModuleDescriptor(it) },
friendModuleDescriptors = friendDependencies.map { getModuleDescriptor(it) },
thisIsBuiltInsModule = builtInModuleDescriptor == null,
customBuiltInsModule = builtInModuleDescriptor
@@ -286,31 +243,29 @@ private class ModulesStructure(
return analysisResult
}
private val lookupTracker: LookupTracker = LookupTracker.DO_NOTHING
private val metadataVersion: JsKlibMetadataVersion = compilerConfiguration.metadataVersion
private val languageVersionSettings: LanguageVersionSettings = compilerConfiguration.languageVersionSettings
private val storageManager: LockBasedStorageManager = LockBasedStorageManager("ModulesStructure")
private var runtimeModule: ModuleDescriptorImpl? = null
// TODO: these are roughly equivalent to KlibResolvedModuleDescriptorsFactoryImpl. Refactor me.
val descriptors = mutableMapOf<KotlinLibrary, ModuleDescriptorImpl>()
fun getModuleDescriptor(current: KotlinLibrary): ModuleDescriptorImpl = descriptors.getOrPut(current) {
val parts = loadKlibMetadataParts(current)
val isBuiltIns = parts.importedModules.isEmpty()
loadKlibMetadata(
parts,
val isBuiltIns = current.unresolvedDependencies.isEmpty()
val md = JsFactories.DefaultDeserializedDescriptorFactory.createDescriptorOptionalBuiltIns(
current,
isBuiltIns,
lookupTracker,
storageManager,
metadataVersion,
languageVersionSettings,
runtimeModule,
moduleDependencies.getValue(current).map { getModuleDescriptor(it) }
).also {
if (isBuiltIns) runtimeModule = it
}
storageManager,
runtimeModule?.builtIns,
packageAccessHandler = null // TODO: This is a speed optimization used by Native. Don't bother for now.
)
if (isBuiltIns) runtimeModule = md
val dependencies = moduleDependencies.getValue(current).map { getModuleDescriptor(it) }
md.setDependencies(listOf(md) + dependencies)
md
}
val builtInModuleDescriptor =
@@ -318,6 +273,7 @@ private class ModulesStructure(
getModuleDescriptor(builtInsDep)
else
null // null in case compiling builtInModule itself
}
private fun getDescriptorForElement(
@@ -344,23 +300,20 @@ fun serializeModuleIntoKlib(
val moduleDescriptor = moduleFragment.descriptor
val descriptorSelector = { declarationDescriptor: DeclarationDescriptor ->
val index = descriptorTable.get(declarationDescriptor) ?: error("No descriptor ID found for $declarationDescriptor")
newJsDescriptorUniqId(index)
}
val metadataVersion = configuration.metadataVersion
val languageVersionSettings = configuration.languageVersionSettings
val metadataSerializer = KlibMetadataIncrementalSerializer(
languageVersionSettings,
metadataVersion,
descriptorTable)
fun serializeScope(fqName: FqName, memberScope: Collection<DeclarationDescriptor>): ByteArray {
return JsKlibMetadataSerializationUtil.serializeDescriptors(
return metadataSerializer.serializePackageFragment(
bindingContext,
moduleDescriptor,
memberScope,
fqName,
languageVersionSettings,
metadataVersion,
descriptorSelector
fqName
).toByteArray()
}
@@ -393,25 +346,28 @@ fun serializeModuleIntoKlib(
processCompiledFileData(VfsUtilCore.virtualToIoFile(ktFile.virtualFile), compiledKotlinFile)
}
incrementalResultsConsumer?.run {
processHeader(JsKlibMetadataSerializationUtil.serializeHeader(moduleDescriptor, null, languageVersionSettings).toByteArray())
}
val compiledKotlinFiles = cleanFiles + additionalFiles
val header = metadataSerializer.serializeHeader(
moduleDescriptor,
compiledKotlinFiles.map { it.irData.fqName }.distinct()
).toByteArray()
incrementalResultsConsumer?.run {
processHeader(header)
}
val serializedMetadata =
JsKlibMetadataSerializationUtil.serializedMetadata(
moduleDescriptor,
languageVersionSettings,
dependencies.map { it.moduleName },
compiledKotlinFiles.groupBy { it.irData.fqName }.map { (fqn, data) -> fqn to data.sortedBy { it.irData.path }.map { it.metadata } }.toMap()
metadataSerializer.serializedMetadata(
compiledKotlinFiles.groupBy { it.irData.fqName }.map { (fqn, data) -> fqn to data.sortedBy { it.irData.path }.map { it.metadata } }.toMap(),
header
)
val fullSerializedIr = SerializedIrModule(compiledKotlinFiles.map { it.irData })
val abiVersion = KotlinAbiVersion.CURRENT
// DO NOT PUSH. Commonize me.
val compilerVersion = KonanVersionImpl(MetaVersion.DEV, 1, 3, 0, -1)
val libraryVersion = "JSIR"
val libraryVersion = null
val versions = KonanLibraryVersioning(abiVersion = abiVersion, libraryVersion = libraryVersion, compilerVersion = compilerVersion)
@@ -6,16 +6,15 @@
package org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir
import org.jetbrains.kotlin.backend.common.serialization.*
import org.jetbrains.kotlin.builtins.functions.FunctionClassDescriptor
import org.jetbrains.kotlin.builtins.functions.FunctionInvokeDescriptor
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.backend.common.serialization.DescriptorReferenceDeserializer
import org.jetbrains.kotlin.backend.common.serialization.DescriptorUniqIdAware
import org.jetbrains.kotlin.backend.common.serialization.DeserializedDescriptorUniqIdAware
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
import org.jetbrains.kotlin.name.FqName
class JsDescriptorReferenceDeserializer(
currentModule: ModuleDescriptor,
mangler: KotlinMangler,
builtIns: IrBuiltIns
) : DescriptorReferenceDeserializer(currentModule, mangler, builtIns, mutableMapOf()),
DescriptorUniqIdAware by JsDescriptorUniqIdAware
DescriptorUniqIdAware by DeserializedDescriptorUniqIdAware
@@ -1,27 +0,0 @@
/*
* Copyright 2010-2019 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.ir.backend.js.lower.serialization.ir
import org.jetbrains.kotlin.backend.common.serialization.DescriptorUniqIdAware
import org.jetbrains.kotlin.backend.common.serialization.tryGetExtension
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.ir.backend.js.lower.serialization.metadata.JsKlibMetadataProtoBuf
import org.jetbrains.kotlin.serialization.deserialization.descriptors.*
object JsDescriptorUniqIdAware: DescriptorUniqIdAware {
override fun DeclarationDescriptor.getUniqId(): Long? = when (this) {
is DeserializedClassDescriptor -> this.classProto.tryGetExtension(JsKlibMetadataProtoBuf.classUniqId)
is DeserializedSimpleFunctionDescriptor -> this.proto.tryGetExtension(JsKlibMetadataProtoBuf.functionUniqId)
is DeserializedPropertyDescriptor -> this.proto.tryGetExtension(JsKlibMetadataProtoBuf.propertyUniqId)
is DeserializedClassConstructorDescriptor -> this.proto.tryGetExtension(JsKlibMetadataProtoBuf.constructorUniqId)
is DeserializedTypeParameterDescriptor -> this.proto.tryGetExtension(JsKlibMetadataProtoBuf.typeParamUniqId)
is DeserializedTypeAliasDescriptor -> this.proto.tryGetExtension(JsKlibMetadataProtoBuf.typeAliasUniqId)
else -> null
}?.index
}
fun newJsDescriptorUniqId(index: Long): JsKlibMetadataProtoBuf.DescriptorUniqId =
JsKlibMetadataProtoBuf.DescriptorUniqId.newBuilder().setIndex(index).build()
@@ -11,7 +11,7 @@ import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.DeclarationDescriptorWithVisibility
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.ir.backend.js.kotlinLibrary
import org.jetbrains.kotlin.descriptors.konan.kotlinLibrary
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
import org.jetbrains.kotlin.ir.util.SymbolTable
import org.jetbrains.kotlin.resolve.descriptorUtil.isPublishedApi
@@ -23,7 +23,7 @@ class JsIrLinker(
builtIns: IrBuiltIns,
symbolTable: SymbolTable
) : KotlinIrLinker(logger, builtIns, symbolTable, emptyList(), null, PUBLIC_LOCAL_UNIQ_ID_EDGE),
DescriptorUniqIdAware by JsDescriptorUniqIdAware {
DescriptorUniqIdAware by DeserializedDescriptorUniqIdAware {
override val descriptorReferenceDeserializer =
JsDescriptorReferenceDeserializer(currentModule, mangler, builtIns)
@@ -1,31 +0,0 @@
/*
* Copyright 2010-2019 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.ir.backend.js.lower.serialization.metadata
import org.jetbrains.kotlin.metadata.ProtoBuf
import org.jetbrains.kotlin.serialization.deserialization.FlexibleTypeDeserializer
import org.jetbrains.kotlin.types.ErrorUtils
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.SimpleType
import org.jetbrains.kotlin.types.checker.StrictEqualityTypeChecker
import org.jetbrains.kotlin.types.createDynamicType
import org.jetbrains.kotlin.types.typeUtil.builtIns
object DynamicTypeDeserializer : FlexibleTypeDeserializer {
const val id = "kotlin.DynamicType"
override fun create(proto: ProtoBuf.Type, flexibleId: String, lowerBound: SimpleType, upperBound: SimpleType): KotlinType {
if (flexibleId != id) return ErrorUtils.createErrorType("Unexpected id: $flexibleId. ($lowerBound..$upperBound)")
return if (StrictEqualityTypeChecker.strictEqualTypes(lowerBound, lowerBound.builtIns.nothingType) &&
StrictEqualityTypeChecker.strictEqualTypes(upperBound, upperBound.builtIns.nullableAnyType)
) {
createDynamicType(lowerBound.builtIns)
} else {
ErrorUtils.createErrorType("Illegal type range for dynamic type: $lowerBound..$upperBound")
}
}
}
@@ -1,17 +0,0 @@
/*
* Copyright 2010-2019 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.ir.backend.js.lower.serialization.metadata
import org.jetbrains.kotlin.psi.KtFile
sealed class JsKlibFileMetadata
data class KotlinPsiFileMetadata(val ktFile: KtFile) : JsKlibFileMetadata()
data class KotlinDeserializedFileMetadata(
val packageFragment: JsKlibMetadataPackageFragment,
val fileId: Int
) : JsKlibFileMetadata()
@@ -1,16 +0,0 @@
/*
* Copyright 2010-2019 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.ir.backend.js.lower.serialization.metadata
class JsKlibMetadataFileRegistry {
private val fileIdsImpl = mutableMapOf<JsKlibFileMetadata, Int>()
fun lookup(file: JsKlibFileMetadata) = fileIdsImpl.getOrPut(file) { fileIdsImpl.size }
val fileIds: Map<JsKlibFileMetadata, Int>
get() = fileIdsImpl
}
@@ -1,86 +0,0 @@
/*
* Copyright 2010-2019 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.ir.backend.js.lower.serialization.metadata
import org.jetbrains.kotlin.contracts.ContractDeserializerImpl
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.deserialization.PlatformDependentDeclarationFilter
import org.jetbrains.kotlin.descriptors.impl.EmptyPackageFragmentDescriptor
import org.jetbrains.kotlin.incremental.components.LookupTracker
import org.jetbrains.kotlin.metadata.ProtoBuf
import org.jetbrains.kotlin.metadata.deserialization.NameResolverImpl
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.parentOrNull
import org.jetbrains.kotlin.serialization.deserialization.*
import org.jetbrains.kotlin.storage.StorageManager
fun createJsKlibMetadataPackageFragmentProvider(
storageManager: StorageManager,
module: ModuleDescriptor,
header: JsKlibMetadataProtoBuf.Header,
packageFragmentProtos: List<ProtoBuf.PackageFragment>,
metadataVersion: JsKlibMetadataVersion,
configuration: DeserializationConfiguration,
lookupTracker: LookupTracker
): PackageFragmentProvider {
val packageFragments: MutableList<PackageFragmentDescriptor> = packageFragmentProtos.mapNotNullTo(mutableListOf()) { proto ->
proto.fqName?.let { fqName ->
JsKlibMetadataPackageFragment(fqName, storageManager, module, proto, header, metadataVersion, configuration)
}
}
// Generate empty PackageFragmentDescriptor instances for packages that aren't mentioned in compilation units directly.
// For example, if there's `package foo.bar` directive, we'll get only PackageFragmentDescriptor for `foo.bar`, but
// none for `foo`. Various descriptor/scope code relies on presence of such package fragments, and currently we
// don't know if it's possible to fix this.
// TODO: think about fixing issues in descriptors/scopes
val packageFqNames = packageFragmentProtos.mapNotNullTo(mutableSetOf()) { it.fqName }
for (packageFqName in packageFqNames.mapNotNull { it.parentOrNull() }) {
var ancestorFqName = packageFqName
while (!ancestorFqName.isRoot && packageFqNames.add(ancestorFqName)) {
packageFragments += EmptyPackageFragmentDescriptor(module, ancestorFqName)
ancestorFqName = ancestorFqName.parent()
}
}
val provider = PackageFragmentProviderImpl(packageFragments)
val notFoundClasses = NotFoundClasses(storageManager, module)
val components = DeserializationComponents(
storageManager,
module,
configuration,
DeserializedClassDataFinder(provider),
AnnotationAndConstantLoaderImpl(module, notFoundClasses, JsKlibMetadataSerializerProtocol),
provider,
LocalClassifierTypeSettings.Default,
ErrorReporter.DO_NOTHING,
lookupTracker,
DynamicTypeDeserializer,
emptyList(),
notFoundClasses,
ContractDeserializerImpl(configuration, storageManager),
platformDependentDeclarationFilter = PlatformDependentDeclarationFilter.All,
extensionRegistryLite = JsKlibMetadataSerializerProtocol.extensionRegistry
)
for (packageFragment in packageFragments.filterIsInstance<JsKlibMetadataPackageFragment>()) {
packageFragment.initialize(components)
}
return provider
}
private val ProtoBuf.PackageFragment.fqName: FqName?
get() {
val nameResolver = NameResolverImpl(strings, qualifiedNames)
return when {
hasPackage() -> FqName(nameResolver.getPackageFqName(`package`.getExtension(JsKlibMetadataProtoBuf.packageFqName)))
class_Count > 0 -> nameResolver.getClassId(class_OrBuilderList.first().fqName).packageFqName
else -> null
}
}
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.ir.backend.js.lower.serialization.metadata
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.descriptors.SourceFile
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
import org.jetbrains.kotlin.library.metadata.KlibMetadataProtoBuf
import org.jetbrains.kotlin.metadata.ProtoBuf
import org.jetbrains.kotlin.metadata.deserialization.NameResolverImpl
import org.jetbrains.kotlin.name.ClassId
@@ -22,14 +23,14 @@ class JsKlibMetadataPackageFragment(
storageManager: StorageManager,
module: ModuleDescriptor,
proto: ProtoBuf.PackageFragment,
header: JsKlibMetadataProtoBuf.Header,
header: KlibMetadataProtoBuf.Header,
metadataVersion: JsKlibMetadataVersion,
configuration: DeserializationConfiguration
) : DeserializedPackageFragmentImpl(
fqName, storageManager, module, proto, metadataVersion, JsContainerSource(fqName, header, configuration)
) {
val fileMap: Map<Int, FileHolder> =
proto.getExtension(JsKlibMetadataProtoBuf.packageFragmentFiles).fileList.withIndex().associate { (index, file) ->
proto.getExtension(KlibMetadataProtoBuf.packageFragmentFiles).fileList.withIndex().associate { (index, file) ->
(if (file.hasId()) file.id else index) to FileHolder(file.annotationList)
}
@@ -48,7 +49,7 @@ class JsKlibMetadataPackageFragment(
class JsContainerSource(
private val fqName: FqName,
header: JsKlibMetadataProtoBuf.Header,
header: KlibMetadataProtoBuf.Header,
configuration: DeserializationConfiguration
) : DeserializedContainerSource {
val annotations: List<ClassId> =
@@ -1,220 +0,0 @@
/*
* Copyright 2010-2019 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.ir.backend.js.lower.serialization.metadata
import org.jetbrains.kotlin.config.AnalysisFlags
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.library.SerializedMetadata
import org.jetbrains.kotlin.metadata.ProtoBuf
import org.jetbrains.kotlin.metadata.deserialization.BinaryVersion
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.checkers.ExpectedActualDeclarationChecker
import org.jetbrains.kotlin.resolve.descriptorUtil.filterOutSourceAnnotations
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
import org.jetbrains.kotlin.resolve.descriptorUtil.module
import org.jetbrains.kotlin.serialization.AnnotationSerializer
import org.jetbrains.kotlin.serialization.DescriptorSerializer
import org.jetbrains.kotlin.serialization.StringTableImpl
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedClassDescriptor
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedPropertyDescriptor
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedSimpleFunctionDescriptor
import java.io.ByteArrayInputStream
import java.io.ByteArrayOutputStream
import java.io.OutputStream
object JsKlibMetadataSerializationUtil {
fun serializedMetadata(
module: ModuleDescriptor,
settings: LanguageVersionSettings,
importedModules: List<String>,
fragments: Map<String, List<ByteArray>>
): SerializedMetadata {
val fragmentNames = mutableListOf<String>()
val fragmentParts = mutableListOf<List<ByteArray>>()
for ((fqName, fragment) in fragments.entries.sortedBy { it.key }) {
fragmentNames += fqName
fragmentParts += fragment
}
val stream = ByteArrayOutputStream()
serializeHeader(module, null, settings).writeDelimitedTo(stream)
asLibrary().writeTo(stream)
stream.appendPackageFragments(fragments)
importedModules.forEach {
stream.writeProto(JsKlibMetadataProtoBuf.Library.IMPORTED_MODULE_FIELD_NUMBER, it.toByteArray())
}
val moduleLibrary = stream.toByteArray()
return SerializedMetadata(moduleLibrary, fragmentParts, fragmentNames)
}
private fun asLibrary(): JsKlibMetadataProtoBuf.Library {
return JsKlibMetadataProtoBuf.Library.newBuilder().build()
}
private fun OutputStream.writeProto(fieldNumber: Int, content: ByteArray) {
// Message header
write((fieldNumber shl 3) or 2)
// Size varint
var size = content.size
while (size > 0x7F) {
write(0x80 or (size and 0x7F))
size = size ushr 7
}
write(size)
// Fragment itself
write(content)
}
private fun OutputStream.appendPackageFragments(serializedFragments: Map<String, List<ByteArray>>) {
for ((_, fragments) in serializedFragments.entries.sortedBy { it.key }) {
for (fragment in fragments) {
writeProto(JsKlibMetadataProtoBuf.Library.PACKAGE_FRAGMENT_FIELD_NUMBER, fragment)
}
}
}
fun serializeHeader(
module: ModuleDescriptor, packageFqName: FqName?, languageVersionSettings: LanguageVersionSettings
): JsKlibMetadataProtoBuf.Header {
val header = JsKlibMetadataProtoBuf.Header.newBuilder()
if (packageFqName != null) {
header.packageFqName = packageFqName.asString()
}
if (languageVersionSettings.isPreRelease()) {
header.flags = 1
}
val experimentalAnnotationFqNames = languageVersionSettings.getFlag(AnalysisFlags.experimental)
if (experimentalAnnotationFqNames.isNotEmpty()) {
val stringTable = StringTableImpl()
for (fqName in experimentalAnnotationFqNames) {
val descriptor = module.resolveClassByFqName(FqName(fqName), NoLookupLocation.FOR_ALREADY_TRACKED) ?: continue
header.addAnnotation(ProtoBuf.Annotation.newBuilder().apply {
id = stringTable.getFqNameIndex(descriptor)
})
}
val (strings, qualifiedNames) = stringTable.buildProto()
header.strings = strings
header.qualifiedNames = qualifiedNames
}
// TODO: write JS code binary version
return header.build()
}
fun serializeDescriptors(
bindingContext: BindingContext,
module: ModuleDescriptor,
scope: Collection<DeclarationDescriptor>,
fqName: FqName,
languageVersionSettings: LanguageVersionSettings,
metadataVersion: BinaryVersion,
declarationTableHandler: ((DeclarationDescriptor) -> JsKlibMetadataProtoBuf.DescriptorUniqId?)
): ProtoBuf.PackageFragment {
val builder = ProtoBuf.PackageFragment.newBuilder()
val skip = fun(descriptor: DeclarationDescriptor): Boolean {
// TODO: ModuleDescriptor should be able to return the package only with the contents of that module, without dependencies
if (descriptor.module != module) return true
if (descriptor is MemberDescriptor && descriptor.isExpect) {
return !(descriptor is ClassDescriptor && ExpectedActualDeclarationChecker.shouldGenerateExpectClass(descriptor))
}
return false
}
val fileRegistry = JsKlibMetadataFileRegistry()
val extension = JsKlibMetadataSerializerExtension(fileRegistry, languageVersionSettings, metadataVersion, declarationTableHandler)
val classDescriptors = scope.filterIsInstance<ClassDescriptor>().sortedBy { it.fqNameSafe.asString() }
fun serializeClasses(descriptors: Collection<DeclarationDescriptor>, parentSerializer: DescriptorSerializer) {
for (descriptor in descriptors) {
if (descriptor !is ClassDescriptor || skip(descriptor)) continue
val serializer = DescriptorSerializer.create(descriptor, extension, parentSerializer)
serializeClasses(descriptor.unsubstitutedInnerClassesScope.getContributedDescriptors(), serializer)
val classProto = serializer.classProto(descriptor).build() ?: error("Class not serialized: $descriptor")
builder.addClass_(classProto)
}
}
val serializer = DescriptorSerializer.createTopLevel(extension)
serializeClasses(classDescriptors, serializer)
val stringTable = extension.stringTable
val members = scope.filterNot(skip)
builder.`package` = serializer.packagePartProto(fqName, members).build()
builder.setExtension(
JsKlibMetadataProtoBuf.packageFragmentFiles,
serializeFiles(fileRegistry, bindingContext, AnnotationSerializer(stringTable))
)
val (strings, qualifiedNames) = stringTable.buildProto()
builder.strings = strings
builder.qualifiedNames = qualifiedNames
return builder.build()
}
private fun serializeFiles(
fileRegistry: JsKlibMetadataFileRegistry,
bindingContext: BindingContext,
serializer: AnnotationSerializer
): JsKlibMetadataProtoBuf.Files {
val filesProto = JsKlibMetadataProtoBuf.Files.newBuilder()
for ((file, id) in fileRegistry.fileIds.entries.sortedBy { it.value }) {
val fileProto = JsKlibMetadataProtoBuf.File.newBuilder()
if (id != filesProto.fileCount) {
fileProto.id = id
}
val annotations = when (file) {
is KotlinPsiFileMetadata -> file.ktFile.annotationEntries.map { bindingContext[BindingContext.ANNOTATION, it]!! }
is KotlinDeserializedFileMetadata -> file.packageFragment.fileMap[file.fileId]!!.annotations
}
for (annotation in annotations.filterOutSourceAnnotations()) {
fileProto.addAnnotation(serializer.serializeAnnotation(annotation))
}
filesProto.addFile(fileProto)
}
return filesProto.build()
}
@JvmStatic
fun readModuleAsProto(metadata: ByteArray): JsKlibMetadataParts {
val inputStream = ByteArrayInputStream(metadata)
val header = JsKlibMetadataProtoBuf.Header.parseDelimitedFrom(inputStream, JsKlibMetadataSerializerProtocol.extensionRegistry)
val content = JsKlibMetadataProtoBuf.Library.parseFrom(inputStream, JsKlibMetadataSerializerProtocol.extensionRegistry)
return JsKlibMetadataParts(header, content.packageFragmentList, content.importedModuleList)
}
}
data class JsKlibMetadataParts(
val header: JsKlibMetadataProtoBuf.Header,
val body: List<ProtoBuf.PackageFragment>,
val importedModules: List<String>
)
internal fun DeclarationDescriptor.extractFileId(): Int? = when (this) {
is DeserializedClassDescriptor -> classProto.getExtension(JsKlibMetadataProtoBuf.classContainingFileId)
is DeserializedSimpleFunctionDescriptor -> proto.getExtension(JsKlibMetadataProtoBuf.functionContainingFileId)
is DeserializedPropertyDescriptor -> proto.getExtension(JsKlibMetadataProtoBuf.propertyContainingFileId)
else -> null
}
@@ -1,118 +0,0 @@
/*
* Copyright 2010-2019 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.ir.backend.js.lower.serialization.metadata
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.metadata.ProtoBuf
import org.jetbrains.kotlin.metadata.deserialization.BinaryVersion
import org.jetbrains.kotlin.metadata.serialization.MutableVersionRequirementTable
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.source.PsiSourceFile
import org.jetbrains.kotlin.serialization.DescriptorSerializer
import org.jetbrains.kotlin.serialization.KotlinSerializerExtensionBase
import org.jetbrains.kotlin.types.FlexibleType
class JsKlibMetadataSerializerExtension(
private val fileRegistry: JsKlibMetadataFileRegistry,
private val languageVersionSettings: LanguageVersionSettings,
override val metadataVersion: BinaryVersion,
val declarationTableHandler: ((DeclarationDescriptor) -> JsKlibMetadataProtoBuf.DescriptorUniqId?)
) : KotlinSerializerExtensionBase(JsKlibMetadataSerializerProtocol) {
override val stringTable = JsKlibMetadataStringTable()
override fun serializeFlexibleType(flexibleType: FlexibleType, lowerProto: ProtoBuf.Type.Builder, upperProto: ProtoBuf.Type.Builder) {
lowerProto.flexibleTypeCapabilitiesId = stringTable.getStringIndex(DynamicTypeDeserializer.id)
}
private fun uniqId(descriptor: DeclarationDescriptor): JsKlibMetadataProtoBuf.DescriptorUniqId? {
return declarationTableHandler(descriptor)
}
override fun serializeTypeParameter(typeParameter: TypeParameterDescriptor, proto: ProtoBuf.TypeParameter.Builder) {
uniqId(typeParameter)?.let { proto.setExtension(JsKlibMetadataProtoBuf.typeParamUniqId, it) }
super.serializeTypeParameter(typeParameter, proto)
}
override fun serializeTypeAlias(typeAlias: TypeAliasDescriptor, proto: ProtoBuf.TypeAlias.Builder) {
uniqId(typeAlias)?.let { proto.setExtension(JsKlibMetadataProtoBuf.typeAliasUniqId, it) }
super.serializeTypeAlias(typeAlias, proto)
}
override fun serializeEnumEntry(descriptor: ClassDescriptor, proto: ProtoBuf.EnumEntry.Builder) {
uniqId(descriptor)?.let { proto.setExtension(JsKlibMetadataProtoBuf.enumEntryUniqId, it) }
super.serializeEnumEntry(descriptor, proto)
}
override fun serializeConstructor(descriptor: ConstructorDescriptor, proto: ProtoBuf.Constructor.Builder,
childSerializer: DescriptorSerializer
) {
uniqId(descriptor)?.let { proto.setExtension(JsKlibMetadataProtoBuf.constructorUniqId, it) }
super.serializeConstructor(descriptor, proto, childSerializer)
}
override fun serializeClass(
descriptor: ClassDescriptor,
proto: ProtoBuf.Class.Builder,
versionRequirementTable: MutableVersionRequirementTable,
childSerializer: DescriptorSerializer
) {
uniqId(descriptor)?.let { proto.setExtension(JsKlibMetadataProtoBuf.classUniqId, it) }
val id = getFileId(descriptor)
if (id != null) {
proto.setExtension(JsKlibMetadataProtoBuf.classContainingFileId, id)
}
super.serializeClass(descriptor, proto, versionRequirementTable, childSerializer)
}
override fun serializeProperty(
descriptor: PropertyDescriptor,
proto: ProtoBuf.Property.Builder,
versionRequirementTable: MutableVersionRequirementTable?,
childSerializer: DescriptorSerializer
) {
uniqId(descriptor)?.let { proto.setExtension(JsKlibMetadataProtoBuf.propertyUniqId, it) }
val id = getFileId(descriptor)
if (id != null) {
proto.setExtension(JsKlibMetadataProtoBuf.propertyContainingFileId, id)
}
super.serializeProperty(descriptor, proto, versionRequirementTable, childSerializer)
}
override fun serializeFunction(
descriptor: FunctionDescriptor,
proto: ProtoBuf.Function.Builder,
versionRequirementTable: MutableVersionRequirementTable?,
childSerializer: DescriptorSerializer
) {
uniqId(descriptor)?.let { proto.setExtension(JsKlibMetadataProtoBuf.functionUniqId, it) }
val id = getFileId(descriptor)
if (id != null) {
proto.setExtension(JsKlibMetadataProtoBuf.functionContainingFileId, id)
}
super.serializeFunction(descriptor, proto, versionRequirementTable, childSerializer)
}
private fun getFileId(descriptor: DeclarationDescriptor): Int? {
if (!DescriptorUtils.isTopLevelDeclaration(descriptor) || descriptor !is DeclarationDescriptorWithSource) return null
val fileId = descriptor.extractFileId()
if (fileId != null) {
(descriptor.containingDeclaration as? JsKlibMetadataPackageFragment)?.let { packageFragment ->
return fileRegistry.lookup(KotlinDeserializedFileMetadata(packageFragment, fileId))
}
}
val file = descriptor.source.containingFile as? PsiSourceFile ?: return null
val psiFile = file.psiFile
return (psiFile as? KtFile)?.let { fileRegistry.lookup(KotlinPsiFileMetadata(it)) }
}
override fun releaseCoroutines() = languageVersionSettings.supportsFeature(LanguageFeature.ReleaseCoroutines)
}
@@ -1,25 +0,0 @@
/*
* Copyright 2010-2019 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.ir.backend.js.lower.serialization.metadata
import org.jetbrains.kotlin.protobuf.ExtensionRegistryLite
import org.jetbrains.kotlin.serialization.SerializerExtensionProtocol
object JsKlibMetadataSerializerProtocol : SerializerExtensionProtocol(
ExtensionRegistryLite.newInstance().apply(JsKlibMetadataProtoBuf::registerAllExtensions),
JsKlibMetadataProtoBuf.packageFqName,
JsKlibMetadataProtoBuf.constructorAnnotation,
JsKlibMetadataProtoBuf.classAnnotation,
JsKlibMetadataProtoBuf.functionAnnotation,
JsKlibMetadataProtoBuf.propertyAnnotation,
JsKlibMetadataProtoBuf.propertyGetterAnnotation,
JsKlibMetadataProtoBuf.propertySetterAnnotation,
JsKlibMetadataProtoBuf.enumEntryAnnotation,
JsKlibMetadataProtoBuf.compileTimeValue,
JsKlibMetadataProtoBuf.parameterAnnotation,
JsKlibMetadataProtoBuf.typeAnnotation,
JsKlibMetadataProtoBuf.typeParameterAnnotation
)
@@ -1,34 +0,0 @@
/*
* Copyright 2010-2019 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.ir.backend.js.lower.serialization.metadata
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
import org.jetbrains.kotlin.descriptors.ClassifierDescriptorWithTypeParameters
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.descriptorUtil.classId
import org.jetbrains.kotlin.resolve.descriptorUtil.getAllSuperClassifiers
import org.jetbrains.kotlin.serialization.StringTableImpl
class JsKlibMetadataStringTable : StringTableImpl() {
override fun getLocalClassIdReplacement(descriptor: ClassifierDescriptorWithTypeParameters): ClassId? {
return if (descriptor.containingDeclaration is CallableMemberDescriptor) {
val superClassifiers = descriptor.getAllSuperClassifiers()
.mapNotNull { it as ClassifierDescriptorWithTypeParameters }
.filter { it != descriptor }
.toList()
if (superClassifiers.size == 1) {
superClassifiers[0].classId
} else {
val superClass = superClassifiers.find { !DescriptorUtils.isInterface(it) }
superClass?.classId ?: ClassId.topLevel(KotlinBuiltIns.FQ_NAMES.any.toSafe())
}
} else {
super.getLocalClassIdReplacement(descriptor)
}
}
}
@@ -14,6 +14,10 @@ import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
import org.jetbrains.kotlin.config.*
import org.jetbrains.kotlin.js.config.JSConfigurationKeys
import org.jetbrains.kotlin.library.KotlinLibrary
import org.jetbrains.kotlin.library.KotlinLibrarySearchPathResolver
import org.jetbrains.kotlin.library.UnresolvedLibrary
import org.jetbrains.kotlin.library.resolver.KotlinLibraryResolveResult
import org.jetbrains.kotlin.library.resolver.impl.libraryResolver
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.resolve.multiplatform.isCommonSource
import org.jetbrains.kotlin.serialization.js.ModuleKind
@@ -59,7 +63,7 @@ fun buildKLib(
moduleName: String,
sources: List<String>,
outputPath: String,
dependencies: List<KotlinLibrary>,
allDependencies: KotlinLibraryResolveResult,
commonSources: List<String>
) {
generateKLib(
@@ -72,7 +76,7 @@ fun buildKLib(
file
},
configuration = buildConfiguration(environment, moduleName),
allDependencies = dependencies,
allDependencies = allDependencies,
friendDependencies = emptyList(),
outputKlibPath = outputPath,
nopack = true
@@ -113,12 +117,18 @@ fun main(args: Array<String>) {
error("Please set path to .klm file: `-o some/dir/module-name.klm`")
}
val name = outputPath.takeLastWhile { it != '/' }
val dependencyAbsolutePaths = dependencies.map{ File(it).absolutePath }
val unresolvedLibraries = dependencies.map { UnresolvedLibrary(it, null) }
// Configure the resolver to only understand absolute path libraries.
val libraryResolver = KotlinLibrarySearchPathResolver<KotlinLibrary>(
repositories = emptyList(),
directLibs = dependencyAbsolutePaths,
distributionKlib = null,
localKotlinDir = null,
skipCurrentDir = true
// TODO: pass logger attached to message collector here.
).libraryResolver()
val resolvedLibraries = libraryResolver.resolveWithDependencies(unresolvedLibraries, true, true, true)
val dependencyKLibs = dependencies.map {
val file = File(it)
loadKlib(file.path)
}
buildKLib(name.dropLast(4), listOfKtFilesFrom(inputFiles), outputPath, dependencyKLibs, listOfKtFilesFrom(commonSources))
buildKLib(File(outputPath).absolutePath, listOfKtFilesFrom(inputFiles), outputPath, resolvedLibraries, listOfKtFilesFrom(commonSources))
}