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
+1
View File
@@ -215,6 +215,7 @@ extra["compilerModules"] = arrayOf(
":compiler:ir.serialization.js", ":compiler:ir.serialization.js",
":kotlin-util-io", ":kotlin-util-io",
":kotlin-util-klib", ":kotlin-util-klib",
":kotlin-util-klib-metadata",
":compiler:backend-common", ":compiler:backend-common",
":compiler:backend", ":compiler:backend",
":compiler:plugin-api", ":compiler:plugin-api",
@@ -33,7 +33,11 @@ import org.jetbrains.kotlin.js.config.EcmaVersion
import org.jetbrains.kotlin.js.config.JSConfigurationKeys import org.jetbrains.kotlin.js.config.JSConfigurationKeys
import org.jetbrains.kotlin.js.config.JsConfig import org.jetbrains.kotlin.js.config.JsConfig
import org.jetbrains.kotlin.js.config.SourceMapSourceEmbedding import org.jetbrains.kotlin.js.config.SourceMapSourceEmbedding
import org.jetbrains.kotlin.library.resolver.impl.libraryResolver
import org.jetbrains.kotlin.library.KotlinLibrary import org.jetbrains.kotlin.library.KotlinLibrary
import org.jetbrains.kotlin.library.KotlinLibrarySearchPathResolver
import org.jetbrains.kotlin.library.UnresolvedLibrary
import org.jetbrains.kotlin.library.toUnresolvedLibraries
import org.jetbrains.kotlin.metadata.deserialization.BinaryVersion import org.jetbrains.kotlin.metadata.deserialization.BinaryVersion
import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.serialization.js.ModuleKind import org.jetbrains.kotlin.serialization.js.ModuleKind
@@ -138,20 +142,21 @@ class K2JsIrCompiler : CLICompiler<K2JSCompilerArguments>() {
// TODO: Handle non-empty main call arguments // TODO: Handle non-empty main call arguments
val mainCallArguments = if (K2JsArgumentConstants.NO_CALL == arguments.main) null else emptyList<String>() val mainCallArguments = if (K2JsArgumentConstants.NO_CALL == arguments.main) null else emptyList<String>()
val loadedLibrariesNames = mutableSetOf<String>() val unresolvedLibraries = libraries.toUnresolvedLibraries
val dependencies = mutableListOf<KotlinLibrary>() // Configure resolver to only understands absolute path libraries.
val friendDependencies = mutableListOf<KotlinLibrary>() val libraryResolver = KotlinLibrarySearchPathResolver<KotlinLibrary>(
repositories = emptyList(),
for (library in libraries) { directLibs = libraries,
val irLib = loadKlib(library) distributionKlib = null,
if (irLib.moduleName !in loadedLibrariesNames) { localKotlinDir = null,
dependencies.add(irLib) skipCurrentDir = true
loadedLibrariesNames.add(irLib.moduleName) // TODO: pass logger attached to message collector here.
if (library in friendLibraries) { ).libraryResolver()
friendDependencies.add(irLib) val resolvedLibraries = libraryResolver.resolveWithDependencies(unresolvedLibraries, true, true, true)
} val friendDependencies = resolvedLibraries.getFullList()
.filter {
it.moduleName in friendLibraries
} }
}
val produceKind = produceMap[arguments.irProduceOnly] val produceKind = produceMap[arguments.irProduceOnly]
if (produceKind == null) { if (produceKind == null) {
@@ -169,7 +174,7 @@ class K2JsIrCompiler : CLICompiler<K2JSCompilerArguments>() {
project = config.project, project = config.project,
files = sourcesFiles, files = sourcesFiles,
configuration = config.configuration, configuration = config.configuration,
allDependencies = dependencies, allDependencies = resolvedLibraries,
friendDependencies = friendDependencies, friendDependencies = friendDependencies,
outputKlibPath = outputKlibPath, outputKlibPath = outputKlibPath,
nopack = arguments.irLegacyGradlePluginCompatibility nopack = arguments.irLegacyGradlePluginCompatibility
@@ -184,7 +189,7 @@ class K2JsIrCompiler : CLICompiler<K2JSCompilerArguments>() {
sourcesFiles, sourcesFiles,
configuration, configuration,
phaseConfig, phaseConfig,
allDependencies = dependencies, allDependencies = resolvedLibraries,
friendDependencies = friendDependencies, friendDependencies = friendDependencies,
mainArguments = mainCallArguments mainArguments = mainCallArguments
) )
@@ -6,6 +6,7 @@
package org.jetbrains.kotlin.ir.backend.js package org.jetbrains.kotlin.ir.backend.js
import com.intellij.openapi.project.Project import com.intellij.openapi.project.Project
import org.jetbrains.kotlin.library.resolver.KotlinLibraryResolveResult
import org.jetbrains.kotlin.backend.common.phaser.PhaseConfig import org.jetbrains.kotlin.backend.common.phaser.PhaseConfig
import org.jetbrains.kotlin.backend.common.phaser.invokeToplevel import org.jetbrains.kotlin.backend.common.phaser.invokeToplevel
import org.jetbrains.kotlin.config.CompilerConfiguration import org.jetbrains.kotlin.config.CompilerConfiguration
@@ -28,7 +29,7 @@ fun compile(
files: List<KtFile>, files: List<KtFile>,
configuration: CompilerConfiguration, configuration: CompilerConfiguration,
phaseConfig: PhaseConfig, phaseConfig: PhaseConfig,
allDependencies: List<KotlinLibrary>, allDependencies: KotlinLibraryResolveResult,
friendDependencies: List<KotlinLibrary>, friendDependencies: List<KotlinLibrary>,
mainArguments: List<String>?, mainArguments: List<String>?,
exportedDeclarations: Set<FqName> = emptySet() exportedDeclarations: Set<FqName> = emptySet()
@@ -6,6 +6,7 @@
package org.jetbrains.kotlin.backend.wasm package org.jetbrains.kotlin.backend.wasm
import com.intellij.openapi.project.Project import com.intellij.openapi.project.Project
import org.jetbrains.kotlin.library.resolver.KotlinLibraryResolveResult
import org.jetbrains.kotlin.backend.common.phaser.PhaseConfig import org.jetbrains.kotlin.backend.common.phaser.PhaseConfig
import org.jetbrains.kotlin.backend.common.phaser.invokeToplevel import org.jetbrains.kotlin.backend.common.phaser.invokeToplevel
import org.jetbrains.kotlin.backend.wasm.codegen.IrModuleToWasm import org.jetbrains.kotlin.backend.wasm.codegen.IrModuleToWasm
@@ -24,7 +25,7 @@ fun compileWasm(
files: List<KtFile>, files: List<KtFile>,
configuration: CompilerConfiguration, configuration: CompilerConfiguration,
phaseConfig: PhaseConfig, phaseConfig: PhaseConfig,
allDependencies: List<KotlinLibrary>, allDependencies: KotlinLibraryResolveResult,
friendDependencies: List<KotlinLibrary>, friendDependencies: List<KotlinLibrary>,
exportedDeclarations: Set<FqName> = emptySet() exportedDeclarations: Set<FqName> = emptySet()
): WasmCompilerResult { ): WasmCompilerResult {
@@ -5,9 +5,19 @@ plugins {
dependencies { dependencies {
// TODO: decouple from backend.common // TODO: decouple from backend.common
compile(project(":compiler:frontend"))
compile(project(":compiler:ir.backend.common")) compile(project(":compiler:ir.backend.common"))
compile(project(":compiler:ir.tree")) compile(project(":compiler:ir.tree"))
compile(project(":compiler:serialization"))
compile(project(":kotlin-util-klib")) compile(project(":kotlin-util-klib"))
compile(project(":kotlin-util-klib-metadata"))
compile(project(":compiler:util"))
compile(project(":compiler:ir.psi2ir"))
compile(project(":compiler:ir.backend.common"))
compileOnly(intellijCoreDep()) { includeJars("intellij-core") }
} }
sourceSets { sourceSets {
@@ -14,8 +14,8 @@ import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedClassDescriptor
import org.jetbrains.kotlin.resolve.scopes.MemberScope import org.jetbrains.kotlin.resolve.scopes.MemberScope
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedClassDescriptor
// This is all information needed to find a descriptor in the // This is all information needed to find a descriptor in the
// tree of deserialized descriptors. Think of it as base + offset. // tree of deserialized descriptors. Think of it as base + offset.
@@ -5,9 +5,11 @@
package org.jetbrains.kotlin.backend.common.serialization package org.jetbrains.kotlin.backend.common.serialization
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
//import org.jetbrains.kotlin.ir.backend.js.lower.serialization.metadata.JsKlibMetadataProtoBuf import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.library.metadata.KlibMetadataProtoBuf
import org.jetbrains.kotlin.protobuf.GeneratedMessageLite import org.jetbrains.kotlin.protobuf.GeneratedMessageLite
import org.jetbrains.kotlin.serialization.deserialization.descriptors.*
import org.jetbrains.kotlin.backend.common.serialization.proto.UniqId as ProtoUniqId import org.jetbrains.kotlin.backend.common.serialization.proto.UniqId as ProtoUniqId
// This is an abstract uniqIdIndex any serialized IR declarations gets. // This is an abstract uniqIdIndex any serialized IR declarations gets.
@@ -35,4 +37,17 @@ interface DescriptorUniqIdAware {
fun DeclarationDescriptor.getUniqId(): Long? fun DeclarationDescriptor.getUniqId(): Long?
} }
//val UniqId.declarationFileName: String get() = "$index${if (isLocal) "L" else "G"}.kjd" object DeserializedDescriptorUniqIdAware : DescriptorUniqIdAware {
override fun DeclarationDescriptor.getUniqId(): Long? = when (this) {
is DeserializedClassDescriptor -> this.classProto.tryGetExtension(KlibMetadataProtoBuf.classUniqId)
is DeserializedSimpleFunctionDescriptor -> this.proto.tryGetExtension(KlibMetadataProtoBuf.functionUniqId)
is DeserializedPropertyDescriptor -> this.proto.tryGetExtension(KlibMetadataProtoBuf.propertyUniqId)
is DeserializedClassConstructorDescriptor -> this.proto.tryGetExtension(KlibMetadataProtoBuf.constructorUniqId)
is DeserializedTypeParameterDescriptor -> this.proto.tryGetExtension(KlibMetadataProtoBuf.typeParamUniqId)
is DeserializedTypeAliasDescriptor -> this.proto.tryGetExtension(KlibMetadataProtoBuf.typeAliasUniqId)
else -> null
}?.index
}
fun newDescriptorUniqId(index: Long): KlibMetadataProtoBuf.DescriptorUniqId =
KlibMetadataProtoBuf.DescriptorUniqId.newBuilder().setIndex(index).build()
@@ -3,7 +3,7 @@
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. * 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 package org.jetbrains.kotlin.backend.common.serialization.metadata
import org.jetbrains.kotlin.metadata.ProtoBuf import org.jetbrains.kotlin.metadata.ProtoBuf
import org.jetbrains.kotlin.serialization.deserialization.FlexibleTypeDeserializer import org.jetbrains.kotlin.serialization.deserialization.FlexibleTypeDeserializer
@@ -5,13 +5,14 @@
package org.jetbrains.kotlin.ir.backend.js.lower.serialization.metadata package org.jetbrains.kotlin.ir.backend.js.lower.serialization.metadata
import org.jetbrains.kotlin.library.metadata.KlibMetadataPackageFragment
import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.psi.KtFile
sealed class JsKlibFileMetadata sealed class KlibFileMetadata
data class KotlinPsiFileMetadata(val ktFile: KtFile) : JsKlibFileMetadata() data class KotlinPsiFileMetadata(val ktFile: KtFile) : KlibFileMetadata()
data class KotlinDeserializedFileMetadata( data class KotlinDeserializedFileMetadata(
val packageFragment: JsKlibMetadataPackageFragment, val packageFragment: KlibMetadataPackageFragment,
val fileId: Int val fileId: Int
) : JsKlibFileMetadata() ) : KlibFileMetadata()
@@ -0,0 +1,41 @@
/*
* 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.backend.common.serialization.metadata.extractFileId
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.DeclarationDescriptorWithSource
import org.jetbrains.kotlin.library.metadata.KlibMetadataPackageFragment
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.source.PsiSourceFile
class KlibMetadataFileRegistry {
private val fileIdsImpl = mutableMapOf<KlibFileMetadata, Int>()
fun lookup(file: KlibFileMetadata) = fileIdsImpl.getOrPut(file) { fileIdsImpl.size }
val fileIds: Map<KlibFileMetadata, Int>
get() = fileIdsImpl
fun getFileId(descriptor: DeclarationDescriptor): Int? {
if (!DescriptorUtils.isTopLevelDeclaration(descriptor) || descriptor !is DeclarationDescriptorWithSource) return null
val fileId = descriptor.extractFileId()
if (fileId != null) {
(descriptor.containingDeclaration as? KlibMetadataPackageFragment)?.let { packageFragment ->
return this.lookup(KotlinDeserializedFileMetadata(packageFragment, fileId))
}
}
val file = descriptor.source.containingFile as? PsiSourceFile ?: return null
val psiFile = file.psiFile
return (psiFile as? KtFile)?.let { this.lookup(KotlinPsiFileMetadata(it)) }
}
}
@@ -0,0 +1,85 @@
/*
* 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.backend.common.serialization.DescriptorTable
import org.jetbrains.kotlin.backend.common.serialization.isExpectMember
import org.jetbrains.kotlin.backend.common.serialization.isSerializableExpectClass
import org.jetbrains.kotlin.backend.common.serialization.metadata.KlibMetadataSerializer
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.descriptors.ClassifierDescriptor
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
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.descriptorUtil.fqNameSafe
import org.jetbrains.kotlin.resolve.descriptorUtil.module
import org.jetbrains.kotlin.serialization.DescriptorSerializer
// TODO: need a refactoring between IncrementalSerializer and MonolithicSerializer.
class KlibMetadataIncrementalSerializer(
languageVersionSettings: LanguageVersionSettings,
metadataVersion: BinaryVersion,
descriptorTable: DescriptorTable
) : KlibMetadataSerializer(languageVersionSettings, metadataVersion, descriptorTable) {
fun serializePackageFragment(
bindingContext: BindingContext,
module: ModuleDescriptor,
scope: Collection<DeclarationDescriptor>,
fqName: FqName
): ProtoBuf.PackageFragment {
val allDescriptors = scope.filter {
it.module == module
}
val classifierDescriptors = allDescriptors
.filterIsInstance<ClassifierDescriptor>()
.filter { !it.isExpectMember || it.isSerializableExpectClass }
.sortedBy { it.fqNameSafe.asString() }
val topLevelDescriptors = DescriptorSerializer.sort(
allDescriptors
.filterIsInstance<CallableDescriptor>()
.filter { !it.isExpectMember }
)
// TODO: For now, in the incremental serializer, we assume
// there is only a single package fragment per file.
// This is no always the case, actually.
// But marrying split package fragments with incremental compilation is an endeavour.
// See monolithic serializer for details.
return serializeDescriptors(fqName, classifierDescriptors, topLevelDescriptors, bindingContext).single()
}
fun serializedMetadata(
fragments: Map<String, List<ByteArray>>,
header: ByteArray
): SerializedMetadata {
val fragmentNames = mutableListOf<String>()
val fragmentParts = mutableListOf<List<ByteArray>>()
for ((fqName, fragment) in fragments.entries.sortedBy { it.key }) {
fragmentNames += fqName
fragmentParts += fragment
}
return SerializedMetadata(header, fragmentParts, fragmentNames)
}
// TODO: For now, in the incremental serializer, we assume
// there is only a single package fragment per file.
// This is no always the case, actually.
// But marrying split package fragments with incremental compilation is an endeavour.
// See monolithic serializer for details.
override val TOP_LEVEL_DECLARATION_COUNT_PER_FILE = null
override val TOP_LEVEL_CLASS_DECLARATION_COUNT_PER_FILE = null
}
@@ -0,0 +1,86 @@
package org.jetbrains.kotlin.backend.common.serialization.metadata
import org.jetbrains.kotlin.backend.common.serialization.DescriptorTable
import org.jetbrains.kotlin.backend.common.serialization.isExpectMember
import org.jetbrains.kotlin.backend.common.serialization.isSerializableExpectClass
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.library.SerializedMetadata
import org.jetbrains.kotlin.library.metadata.KlibMetadataProtoBuf
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.descriptorUtil.module
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
import org.jetbrains.kotlin.resolve.scopes.getDescriptorsFiltered
import org.jetbrains.kotlin.serialization.DescriptorSerializer
// TODO: need a refactoring between IncrementalSerializer and MonolithicSerializer.
class KlibMetadataMonolithicSerializer(
languageVersionSettings: LanguageVersionSettings,
metadataVersion: BinaryVersion,
descriptorTable: DescriptorTable,
val bindingContext: BindingContext
) : KlibMetadataSerializer(languageVersionSettings, metadataVersion, descriptorTable) {
protected fun serializePackageFragment(fqName: FqName,
module: ModuleDescriptor,
bindingContext: BindingContext
):
List<ProtoBuf.PackageFragment> {
// TODO: ModuleDescriptor should be able to return
// the package only with the contents of that module, without dependencies
val fragments = module.getPackage(fqName).fragments.filter { it.module == module }
if (fragments.isEmpty()) return emptyList()
val classifierDescriptors = DescriptorSerializer.sort(
fragments.flatMap {
it.getMemberScope().getDescriptorsFiltered(DescriptorKindFilter.CLASSIFIERS)
}.filter { !it.isExpectMember || it.isSerializableExpectClass }
)
val topLevelDescriptors = DescriptorSerializer.sort(
fragments.flatMap { fragment ->
fragment.getMemberScope().getDescriptorsFiltered(DescriptorKindFilter.CALLABLES)
}.filter { !it.isExpectMember }
)
return serializeDescriptors(fqName, classifierDescriptors, topLevelDescriptors, bindingContext)
}
fun serializeModule(moduleDescriptor: ModuleDescriptor): SerializedMetadata {
val fragments = mutableListOf<List<ByteArray>>()
val fragmentNames = mutableListOf<String>()
val emptyPackages = mutableListOf<String>()
for (packageFqName in getPackagesFqNames(moduleDescriptor)) {
val packageProtos =
serializePackageFragment(packageFqName, moduleDescriptor, bindingContext)
if (packageProtos.isEmpty()) continue
val packageFqNameStr = packageFqName.asString()
if (packageProtos.all { it.getExtension(KlibMetadataProtoBuf.isEmpty)}) {
emptyPackages.add(packageFqNameStr)
}
fragments.add(packageProtos.map { it.toByteArray() })
fragmentNames.add(packageFqNameStr)
}
val header = serializeHeader(moduleDescriptor, fragmentNames, emptyPackages)
val libraryAsByteArray = header.toByteArray()
return SerializedMetadata(libraryAsByteArray, fragments, fragmentNames)
}
// For platform libraries we get HUGE files.
// Indexing them in IDEA takes ages.
// So we split them into chunks.
override val TOP_LEVEL_DECLARATION_COUNT_PER_FILE = 128
override val TOP_LEVEL_CLASS_DECLARATION_COUNT_PER_FILE = 64
}
@@ -0,0 +1,314 @@
/*
* 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.backend.common.serialization.metadata
import org.jetbrains.kotlin.backend.common.serialization.DescriptorTable
import org.jetbrains.kotlin.backend.common.serialization.newDescriptorUniqId
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.ir.backend.js.lower.serialization.metadata.KlibMetadataFileRegistry
import org.jetbrains.kotlin.ir.backend.js.lower.serialization.metadata.KotlinPsiFileMetadata
import org.jetbrains.kotlin.library.metadata.KlibMetadataProtoBuf
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.descriptorUtil.filterOutSourceAnnotations
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
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
internal fun <T, R> Iterable<T>.maybeChunked(size: Int?, transform: (List<T>) -> R): List<R>
= size?.let { this.chunked(size, transform) } ?: listOf(transform(this.toList()))
abstract class KlibMetadataSerializer(
val languageVersionSettings: LanguageVersionSettings,
val metadataVersion: BinaryVersion,
val descriptorTable: DescriptorTable
) {
val fileRegistry = KlibMetadataFileRegistry()
lateinit var serializerContext: SerializerContext
data class SerializerContext(
val serializerExtension: KlibMetadataSerializerExtension,
val topSerializer: DescriptorSerializer,
var classSerializer: DescriptorSerializer = topSerializer
)
fun declarationTableHandler(declarationDescriptor: DeclarationDescriptor): KlibMetadataProtoBuf.DescriptorUniqId {
val index = descriptorTable.get(declarationDescriptor) ?: error("No descriptor ID found for $declarationDescriptor")
return index.let { newDescriptorUniqId(it) }
}
protected fun createNewContext(): SerializerContext {
val extension = KlibMetadataSerializerExtension(
languageVersionSettings,
metadataVersion,
::declarationTableHandler,
{descriptor -> fileRegistry.getFileId(descriptor) } ,
KlibMetadataStringTable()
)
return SerializerContext(
extension,
DescriptorSerializer.createTopLevel(extension)
)
}
protected inline fun <T> withNewContext(crossinline block: SerializerContext.() -> T): T {
serializerContext = createNewContext()
return with(serializerContext, block)
}
private fun SerializerContext.buildFragment(
packageProto: ProtoBuf.Package,
classesProto: List<Pair<ProtoBuf.Class, Int>>,
fqName: FqName,
isEmpty: Boolean,
bindingContext: BindingContext
): ProtoBuf.PackageFragment {
val (stringTableProto, nameTableProto) = serializerExtension.stringTable.buildProto()
// TODO: we place files table to each and every fragment.
// Need to refactor it out sonehow.
val files = serializeFiles(fileRegistry, bindingContext, AnnotationSerializer(serializerExtension.stringTable))
return ProtoBuf.PackageFragment.newBuilder()
.setPackage(packageProto)
.addAllClass_(classesProto.map { it.first })
.setStrings(stringTableProto)
.setQualifiedNames(nameTableProto)
.also { packageFragment ->
classesProto.forEach {
packageFragment.addExtension(KlibMetadataProtoBuf.className, it.second )
}
packageFragment.setExtension(KlibMetadataProtoBuf.packageFragmentFiles, files)
packageFragment.setExtension(KlibMetadataProtoBuf.isEmpty, isEmpty)
packageFragment.setExtension(KlibMetadataProtoBuf.fqName, fqName.asString())
}
.build()
}
private fun serializeClass(packageName: FqName,
classDescriptor: ClassDescriptor): List<Pair<ProtoBuf.Class, Int>> {
with(serializerContext) {
val previousSerializer = classSerializer
classSerializer = DescriptorSerializer.create(classDescriptor, serializerExtension, classSerializer)
val classProto = classSerializer.classProto(classDescriptor).build() ?: error("Class not serialized: $classDescriptor")
//builder.addClass(classProto)
val index = classSerializer.stringTable.getFqNameIndex(classDescriptor)
//builder.addExtension(KlibMetadataProtoBuf.className, index)
val classes = serializeClasses(packageName/*, builder*/,
classDescriptor.unsubstitutedInnerClassesScope
.getContributedDescriptors(DescriptorKindFilter.CLASSIFIERS))
classSerializer = previousSerializer
return classes + Pair(classProto, index)
}
}
protected fun serializeClasses(packageName: FqName,
//builder: ProtoBuf.PackageFragment.Builder,
descriptors: Collection<DeclarationDescriptor>): List<Pair<ProtoBuf.Class, Int>> {
return descriptors.filterIsInstance<ClassDescriptor>().flatMap {
serializeClass(packageName, /*builder, */it)
}
}
private fun emptyPackageProto(): ProtoBuf.Package = ProtoBuf.Package.newBuilder().build()
private fun SerializerContext.buildPackageProto(
fqName: FqName,
descriptors: List<DeclarationDescriptor>) = topSerializer.packagePartProto(fqName, descriptors).build()
?: error("Package fragments not serialized: for $descriptors")
protected fun serializeDescriptors(
fqName: FqName,
classifierDescriptors: List<DeclarationDescriptor>,
topLevelDescriptors: List<DeclarationDescriptor>,
bindingContext: BindingContext
): List<ProtoBuf.PackageFragment> {
if (TOP_LEVEL_CLASS_DECLARATION_COUNT_PER_FILE == null &&
TOP_LEVEL_DECLARATION_COUNT_PER_FILE == null) {
val typeAliases = classifierDescriptors.filterIsInstance<TypeAliasDescriptor>()
val nonCassDescriptors = topLevelDescriptors+typeAliases
return listOf(withNewContext {
val packageProto = if (nonCassDescriptors.isEmpty())
emptyPackageProto()
else
buildPackageProto(fqName, nonCassDescriptors)
buildFragment(
packageProto,
serializeClasses(fqName, classifierDescriptors),
fqName,
topLevelDescriptors.isEmpty() && classifierDescriptors.isEmpty(),
bindingContext
)
}
)
}
val result = mutableListOf<ProtoBuf.PackageFragment>()
result += classifierDescriptors.maybeChunked(TOP_LEVEL_CLASS_DECLARATION_COUNT_PER_FILE) { descriptors ->
withNewContext {
//val classesProto = buildClassesProto { classesBuilder ->
// serializeClasses(fqName, classesBuilder, descriptors)
//}
val classesProto = serializeClasses(fqName, descriptors)
val typeAliases = descriptors.filterIsInstance<TypeAliasDescriptor>()
val packageProto =
if (typeAliases.isNotEmpty()) buildPackageProto(fqName, typeAliases)
else emptyPackageProto()
buildFragment(
packageProto,
classesProto,
fqName,
descriptors.isEmpty(),
bindingContext
)
}
}
result += topLevelDescriptors.maybeChunked(TOP_LEVEL_DECLARATION_COUNT_PER_FILE) { descriptors ->
withNewContext {
buildFragment(
buildPackageProto(fqName, descriptors),
emptyList(),
fqName,
descriptors.isEmpty(),
bindingContext
)
}
}
if (result.isEmpty()) {
result += withNewContext {
buildFragment(
emptyPackageProto(),
emptyList(),
fqName,
true,
bindingContext
)
}
}
return result
}
private fun serializeFiles(
fileRegistry: KlibMetadataFileRegistry,
bindingContext: BindingContext,
serializer: AnnotationSerializer
): KlibMetadataProtoBuf.Files {
val filesProto = KlibMetadataProtoBuf.Files.newBuilder()
for ((file, id) in fileRegistry.fileIds.entries.sortedBy { it.value }) {
val fileProto = KlibMetadataProtoBuf.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
else -> TODO("support other file types")
}
for (annotation in annotations.filterOutSourceAnnotations()) {
fileProto.addAnnotation(serializer.serializeAnnotation(annotation))
}
val name = when (file) {
is KotlinPsiFileMetadata -> file.ktFile.getName()
else -> TODO("support other file types")
}
fileProto.name = name
filesProto.addFile(fileProto)
}
return filesProto.build()
}
protected fun getPackagesFqNames(module: ModuleDescriptor): Set<FqName> {
val result = mutableSetOf<FqName>()
fun getSubPackages(fqName: FqName) {
result.add(fqName)
module.getSubPackagesOf(fqName) { true }.forEach { getSubPackages(it) }
}
getSubPackages(FqName.ROOT)
return result
}
fun serializeHeader(
moduleDescriptor: ModuleDescriptor,
fragmentNames: List<String>,
emptyPackages: List<String> = emptyList()
): KlibMetadataProtoBuf.Header {
val header = KlibMetadataProtoBuf.Header.newBuilder()
header.moduleName = moduleDescriptor.name.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 = moduleDescriptor.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
}
fragmentNames.forEach {
header.addPackageFragmentName(it)
}
emptyPackages.forEach {
header.addEmptyPackage(it)
}
return header.build()
}
// For platform libraries we get HUGE files.
// Indexing them in IDEA takes ages.
// So we split them into chunks.
abstract protected val TOP_LEVEL_DECLARATION_COUNT_PER_FILE: Int?
abstract protected val TOP_LEVEL_CLASS_DECLARATION_COUNT_PER_FILE: Int?
}
fun DeclarationDescriptor.extractFileId(): Int? = when (this) {
is DeserializedClassDescriptor -> classProto.getExtension(KlibMetadataProtoBuf.classFile)
is DeserializedSimpleFunctionDescriptor -> proto.getExtension(KlibMetadataProtoBuf.functionFile)
is DeserializedPropertyDescriptor -> proto.getExtension(KlibMetadataProtoBuf.propertyFile)
else -> null
}
@@ -3,56 +3,57 @@
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. * 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 package org.jetbrains.kotlin.backend.common.serialization.metadata
import org.jetbrains.kotlin.config.LanguageFeature import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.library.metadata.KlibMetadataProtoBuf
import org.jetbrains.kotlin.library.metadata.KlibMetadataSerializerProtocol
import org.jetbrains.kotlin.metadata.ProtoBuf import org.jetbrains.kotlin.metadata.ProtoBuf
import org.jetbrains.kotlin.metadata.deserialization.BinaryVersion import org.jetbrains.kotlin.metadata.deserialization.BinaryVersion
import org.jetbrains.kotlin.metadata.serialization.MutableVersionRequirementTable 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.DescriptorSerializer
import org.jetbrains.kotlin.serialization.KotlinSerializerExtensionBase import org.jetbrains.kotlin.serialization.KotlinSerializerExtensionBase
import org.jetbrains.kotlin.serialization.StringTableImpl
import org.jetbrains.kotlin.types.FlexibleType import org.jetbrains.kotlin.types.FlexibleType
class JsKlibMetadataSerializerExtension( class KlibMetadataSerializerExtension(
private val fileRegistry: JsKlibMetadataFileRegistry,
private val languageVersionSettings: LanguageVersionSettings, private val languageVersionSettings: LanguageVersionSettings,
override val metadataVersion: BinaryVersion, override val metadataVersion: BinaryVersion,
val declarationTableHandler: ((DeclarationDescriptor) -> JsKlibMetadataProtoBuf.DescriptorUniqId?) val declarationTableHandler: (DeclarationDescriptor) -> KlibMetadataProtoBuf.DescriptorUniqId?,
) : KotlinSerializerExtensionBase(JsKlibMetadataSerializerProtocol) { val descriptorFileId: (DeclarationDescriptor) -> Int?,
override val stringTable = JsKlibMetadataStringTable() override val stringTable: StringTableImpl
) : KotlinSerializerExtensionBase(KlibMetadataSerializerProtocol) {
override fun shouldUseTypeTable(): Boolean = true
override fun serializeFlexibleType(flexibleType: FlexibleType, lowerProto: ProtoBuf.Type.Builder, upperProto: ProtoBuf.Type.Builder) { override fun serializeFlexibleType(flexibleType: FlexibleType, lowerProto: ProtoBuf.Type.Builder, upperProto: ProtoBuf.Type.Builder) {
lowerProto.flexibleTypeCapabilitiesId = stringTable.getStringIndex(DynamicTypeDeserializer.id) lowerProto.flexibleTypeCapabilitiesId = stringTable.getStringIndex(DynamicTypeDeserializer.id)
} }
private fun uniqId(descriptor: DeclarationDescriptor): JsKlibMetadataProtoBuf.DescriptorUniqId? { private fun uniqId(descriptor: DeclarationDescriptor): KlibMetadataProtoBuf.DescriptorUniqId? {
return declarationTableHandler(descriptor) return declarationTableHandler(descriptor)
} }
override fun serializeTypeParameter(typeParameter: TypeParameterDescriptor, proto: ProtoBuf.TypeParameter.Builder) { override fun serializeTypeParameter(typeParameter: TypeParameterDescriptor, proto: ProtoBuf.TypeParameter.Builder) {
uniqId(typeParameter)?.let { proto.setExtension(JsKlibMetadataProtoBuf.typeParamUniqId, it) } uniqId(typeParameter)?.let { proto.setExtension(KlibMetadataProtoBuf.typeParamUniqId, it) }
super.serializeTypeParameter(typeParameter, proto) super.serializeTypeParameter(typeParameter, proto)
} }
override fun serializeTypeAlias(typeAlias: TypeAliasDescriptor, proto: ProtoBuf.TypeAlias.Builder) { override fun serializeTypeAlias(typeAlias: TypeAliasDescriptor, proto: ProtoBuf.TypeAlias.Builder) {
uniqId(typeAlias)?.let { proto.setExtension(JsKlibMetadataProtoBuf.typeAliasUniqId, it) } uniqId(typeAlias)?.let { proto.setExtension(KlibMetadataProtoBuf.typeAliasUniqId, it) }
super.serializeTypeAlias(typeAlias, proto) super.serializeTypeAlias(typeAlias, proto)
} }
override fun serializeEnumEntry(descriptor: ClassDescriptor, proto: ProtoBuf.EnumEntry.Builder) { override fun serializeEnumEntry(descriptor: ClassDescriptor, proto: ProtoBuf.EnumEntry.Builder) {
uniqId(descriptor)?.let { proto.setExtension(JsKlibMetadataProtoBuf.enumEntryUniqId, it) } uniqId(descriptor)?.let { proto.setExtension(KlibMetadataProtoBuf.enumEntryUniqId, it) }
super.serializeEnumEntry(descriptor, proto) super.serializeEnumEntry(descriptor, proto)
} }
override fun serializeConstructor(descriptor: ConstructorDescriptor, proto: ProtoBuf.Constructor.Builder, override fun serializeConstructor(descriptor: ConstructorDescriptor, proto: ProtoBuf.Constructor.Builder,
childSerializer: DescriptorSerializer childSerializer: DescriptorSerializer
) { ) {
uniqId(descriptor)?.let { proto.setExtension(JsKlibMetadataProtoBuf.constructorUniqId, it) } uniqId(descriptor)?.let { proto.setExtension(KlibMetadataProtoBuf.constructorUniqId, it) }
super.serializeConstructor(descriptor, proto, childSerializer) super.serializeConstructor(descriptor, proto, childSerializer)
} }
@@ -62,12 +63,10 @@ class JsKlibMetadataSerializerExtension(
versionRequirementTable: MutableVersionRequirementTable, versionRequirementTable: MutableVersionRequirementTable,
childSerializer: DescriptorSerializer childSerializer: DescriptorSerializer
) { ) {
uniqId(descriptor)?.let { proto.setExtension(JsKlibMetadataProtoBuf.classUniqId, it) } uniqId(descriptor)?.let { proto.setExtension(KlibMetadataProtoBuf.classUniqId, it) }
val id = getFileId(descriptor) descriptorFileId(descriptor)?.let { proto.setExtension(KlibMetadataProtoBuf.classFile, it) }
if (id != null) {
proto.setExtension(JsKlibMetadataProtoBuf.classContainingFileId, id)
}
super.serializeClass(descriptor, proto, versionRequirementTable, childSerializer) super.serializeClass(descriptor, proto, versionRequirementTable, childSerializer)
childSerializer.typeTable.serialize()?.let { proto.mergeTypeTable(it) }
} }
override fun serializeProperty( override fun serializeProperty(
@@ -76,11 +75,8 @@ class JsKlibMetadataSerializerExtension(
versionRequirementTable: MutableVersionRequirementTable?, versionRequirementTable: MutableVersionRequirementTable?,
childSerializer: DescriptorSerializer childSerializer: DescriptorSerializer
) { ) {
uniqId(descriptor)?.let { proto.setExtension(JsKlibMetadataProtoBuf.propertyUniqId, it) } uniqId(descriptor)?.let { proto.setExtension(KlibMetadataProtoBuf.propertyUniqId, it) }
val id = getFileId(descriptor) descriptorFileId(descriptor)?.let { proto.setExtension(KlibMetadataProtoBuf.propertyFile, it) }
if (id != null) {
proto.setExtension(JsKlibMetadataProtoBuf.propertyContainingFileId, id)
}
super.serializeProperty(descriptor, proto, versionRequirementTable, childSerializer) super.serializeProperty(descriptor, proto, versionRequirementTable, childSerializer)
} }
@@ -90,29 +86,11 @@ class JsKlibMetadataSerializerExtension(
versionRequirementTable: MutableVersionRequirementTable?, versionRequirementTable: MutableVersionRequirementTable?,
childSerializer: DescriptorSerializer childSerializer: DescriptorSerializer
) { ) {
uniqId(descriptor)?.let { proto.setExtension(JsKlibMetadataProtoBuf.functionUniqId, it) } uniqId(descriptor)?.let { proto.setExtension(KlibMetadataProtoBuf.functionUniqId, it) }
val id = getFileId(descriptor) descriptorFileId(descriptor)?.let { proto.setExtension(KlibMetadataProtoBuf.functionFile, it) }
if (id != null) {
proto.setExtension(JsKlibMetadataProtoBuf.functionContainingFileId, id)
}
super.serializeFunction(descriptor, proto, versionRequirementTable, childSerializer) super.serializeFunction(descriptor, proto, versionRequirementTable, childSerializer)
} }
private fun getFileId(descriptor: DeclarationDescriptor): Int? { override fun releaseCoroutines() =
if (!DescriptorUtils.isTopLevelDeclaration(descriptor) || descriptor !is DeclarationDescriptorWithSource) return null languageVersionSettings.supportsFeature(LanguageFeature.ReleaseCoroutines)
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)
} }
-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 com.intellij.psi.PsiElement
import org.jetbrains.kotlin.backend.common.LoggingContext import org.jetbrains.kotlin.backend.common.LoggingContext
import org.jetbrains.kotlin.backend.common.serialization.DescriptorTable 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.KotlinBuiltIns
import org.jetbrains.kotlin.builtins.functions.functionInterfacePackageFragmentProvider
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.config.languageVersionSettings import org.jetbrains.kotlin.config.languageVersionSettings
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.descriptors.ModuleDescriptor
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.incremental.components.LookupTracker
import org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir.JsIrLinker 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.JsIrModuleSerializer
import org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir.JsMangler 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.JsKlibMetadataVersion
import org.jetbrains.kotlin.ir.backend.js.lower.serialization.metadata.* import org.jetbrains.kotlin.ir.backend.js.lower.serialization.metadata.KlibMetadataIncrementalSerializer
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
import org.jetbrains.kotlin.ir.util.ExpectDeclarationRemover 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.KonanVersionImpl
import org.jetbrains.kotlin.konan.MetaVersion import org.jetbrains.kotlin.konan.MetaVersion
import org.jetbrains.kotlin.konan.properties.propertyList import org.jetbrains.kotlin.konan.properties.propertyList
import org.jetbrains.kotlin.konan.util.KlibMetadataFactories
import org.jetbrains.kotlin.library.* import org.jetbrains.kotlin.library.*
import org.jetbrains.kotlin.library.impl.buildKoltinLibrary import org.jetbrains.kotlin.library.impl.buildKoltinLibrary
import org.jetbrains.kotlin.library.impl.createKotlinLibrary 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.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStatus import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStatus
import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.psi2ir.Psi2IrConfiguration 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.psi2ir.generators.GeneratorContext
import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.BindingContextUtils import org.jetbrains.kotlin.resolve.BindingContextUtils
import org.jetbrains.kotlin.resolve.CompilerDeserializationConfiguration
import org.jetbrains.kotlin.storage.LockBasedStorageManager import org.jetbrains.kotlin.storage.LockBasedStorageManager
import org.jetbrains.kotlin.storage.StorageManager
import org.jetbrains.kotlin.utils.DFS import org.jetbrains.kotlin.utils.DFS
import java.io.File import java.io.File
import org.jetbrains.kotlin.konan.file.File as KFile import org.jetbrains.kotlin.konan.file.File as KFile
@@ -69,8 +69,6 @@ val KotlinLibrary.isBuiltIns: Boolean
fun loadKlib(klibPath: String) = fun loadKlib(klibPath: String) =
createKotlinLibrary(KFile(KFile(klibPath).absolutePath)) createKotlinLibrary(KFile(KFile(klibPath).absolutePath))
internal val JS_KLIBRARY_CAPABILITY = ModuleDescriptor.Capability<KotlinLibrary>("JS KLIBRARY")
private val emptyLoggingContext = object : LoggingContext { private val emptyLoggingContext = object : LoggingContext {
override var inVerbosePhase = false override var inVerbosePhase = false
@@ -86,7 +84,7 @@ fun generateKLib(
project: Project, project: Project,
files: List<KtFile>, files: List<KtFile>,
configuration: CompilerConfiguration, configuration: CompilerConfiguration,
allDependencies: List<KotlinLibrary>, allDependencies: KotlinLibraryResolveResult,
friendDependencies: List<KotlinLibrary>, friendDependencies: List<KotlinLibrary>,
outputKlibPath: String, outputKlibPath: String,
nopack: Boolean nopack: Boolean
@@ -136,7 +134,7 @@ fun generateKLib(
psi2IrContext.bindingContext, psi2IrContext.bindingContext,
files, files,
outputKlibPath, outputKlibPath,
allDependencies, allDependencies.getFullList(),
moduleFragment, moduleFragment,
icData, icData,
nopack nopack
@@ -164,7 +162,7 @@ fun loadIr(
project: Project, project: Project,
files: List<KtFile>, files: List<KtFile>,
configuration: CompilerConfiguration, configuration: CompilerConfiguration,
allDependencies: List<KotlinLibrary>, allDependencies: KotlinLibraryResolveResult,
friendDependencies: List<KotlinLibrary> friendDependencies: List<KotlinLibrary>
): IrModuleInfo { ): IrModuleInfo {
val depsDescriptors = ModulesStructure(project, files, configuration, allDependencies, friendDependencies) val depsDescriptors = ModulesStructure(project, files, configuration, allDependencies, friendDependencies)
@@ -177,7 +175,7 @@ fun loadIr(
val deserializer = JsIrLinker(moduleDescriptor, JsMangler, emptyLoggingContext, irBuiltIns, symbolTable) 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))!! deserializer.deserializeIrModuleHeader(depsDescriptors.getModuleDescriptor(it))!!
} }
@@ -203,70 +201,29 @@ private fun GeneratorContext.generateModuleFragment(files: List<KtFile>, deseria
Psi2IrTranslator(languageVersionSettings, configuration).generateModuleFragment(this, files, deserializer) Psi2IrTranslator(languageVersionSettings, configuration).generateModuleFragment(this, files, deserializer)
private fun loadKlibMetadataParts( private fun createBuiltIns(storageManager: StorageManager) = object : KotlinBuiltIns(storageManager) {}
moduleId: KotlinLibrary val JsFactories = KlibMetadataFactories(::createBuiltIns, DynamicTypeDeserializer)
): 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 class ModulesStructure( private class ModulesStructure(
private val project: Project, private val project: Project,
private val files: List<KtFile>, private val files: List<KtFile>,
val compilerConfiguration: CompilerConfiguration, val compilerConfiguration: CompilerConfiguration,
private val allDependencies: List<KotlinLibrary>, val allDependencies: KotlinLibraryResolveResult,
private val friendDependencies: List<KotlinLibrary> private val friendDependencies: List<KotlinLibrary>
) { ) {
private val deserializedModuleParts: Map<KotlinLibrary, JsKlibMetadataParts> = val moduleDependencies: Map<KotlinLibrary, List<KotlinLibrary>> = {
allDependencies.associateWith { loadKlibMetadataParts(it) } val result = mutableMapOf<KotlinLibrary, List<KotlinLibrary>>()
fun findModuleByName(name: String): KotlinLibrary = allDependencies.forEach { klib, _ ->
allDependencies.find { it.moduleName == name } ?: error("Module is not found: $name") val dependencies = allDependencies.filterRoots {
it.library == klib
val moduleDependencies: Map<KotlinLibrary, List<KotlinLibrary>> = }.getFullList(TopologicalLibraryOrder)
deserializedModuleParts.mapValues { (_, parts) -> result.put(klib, dependencies.minus(klib))
parts.importedModules.map(::findModuleByName)
} }
result
}()
val builtInsDep = allDependencies.find { it.isBuiltIns } val builtInsDep = allDependencies.getFullList().find { it.isBuiltIns }
fun runAnalysis(): JsAnalysisResult { fun runAnalysis(): JsAnalysisResult {
val analysisResult = val analysisResult =
@@ -274,7 +231,7 @@ private class ModulesStructure(
files, files,
project, project,
compilerConfiguration, compilerConfiguration,
allDependencies.map { getModuleDescriptor(it) }, allDependencies.getFullList().map { getModuleDescriptor(it) },
friendModuleDescriptors = friendDependencies.map { getModuleDescriptor(it) }, friendModuleDescriptors = friendDependencies.map { getModuleDescriptor(it) },
thisIsBuiltInsModule = builtInModuleDescriptor == null, thisIsBuiltInsModule = builtInModuleDescriptor == null,
customBuiltInsModule = builtInModuleDescriptor customBuiltInsModule = builtInModuleDescriptor
@@ -286,31 +243,29 @@ private class ModulesStructure(
return analysisResult return analysisResult
} }
private val lookupTracker: LookupTracker = LookupTracker.DO_NOTHING
private val metadataVersion: JsKlibMetadataVersion = compilerConfiguration.metadataVersion
private val languageVersionSettings: LanguageVersionSettings = compilerConfiguration.languageVersionSettings private val languageVersionSettings: LanguageVersionSettings = compilerConfiguration.languageVersionSettings
private val storageManager: LockBasedStorageManager = LockBasedStorageManager("ModulesStructure") private val storageManager: LockBasedStorageManager = LockBasedStorageManager("ModulesStructure")
private var runtimeModule: ModuleDescriptorImpl? = null private var runtimeModule: ModuleDescriptorImpl? = null
// TODO: these are roughly equivalent to KlibResolvedModuleDescriptorsFactoryImpl. Refactor me.
val descriptors = mutableMapOf<KotlinLibrary, ModuleDescriptorImpl>() val descriptors = mutableMapOf<KotlinLibrary, ModuleDescriptorImpl>()
fun getModuleDescriptor(current: KotlinLibrary): ModuleDescriptorImpl = descriptors.getOrPut(current) { fun getModuleDescriptor(current: KotlinLibrary): ModuleDescriptorImpl = descriptors.getOrPut(current) {
val parts = loadKlibMetadataParts(current) val isBuiltIns = current.unresolvedDependencies.isEmpty()
val isBuiltIns = parts.importedModules.isEmpty()
loadKlibMetadata( val md = JsFactories.DefaultDeserializedDescriptorFactory.createDescriptorOptionalBuiltIns(
parts,
current, current,
isBuiltIns,
lookupTracker,
storageManager,
metadataVersion,
languageVersionSettings, languageVersionSettings,
runtimeModule, storageManager,
moduleDependencies.getValue(current).map { getModuleDescriptor(it) } runtimeModule?.builtIns,
).also { packageAccessHandler = null // TODO: This is a speed optimization used by Native. Don't bother for now.
if (isBuiltIns) runtimeModule = it )
} if (isBuiltIns) runtimeModule = md
val dependencies = moduleDependencies.getValue(current).map { getModuleDescriptor(it) }
md.setDependencies(listOf(md) + dependencies)
md
} }
val builtInModuleDescriptor = val builtInModuleDescriptor =
@@ -318,6 +273,7 @@ private class ModulesStructure(
getModuleDescriptor(builtInsDep) getModuleDescriptor(builtInsDep)
else else
null // null in case compiling builtInModule itself null // null in case compiling builtInModule itself
} }
private fun getDescriptorForElement( private fun getDescriptorForElement(
@@ -344,23 +300,20 @@ fun serializeModuleIntoKlib(
val moduleDescriptor = moduleFragment.descriptor 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 metadataVersion = configuration.metadataVersion
val languageVersionSettings = configuration.languageVersionSettings val languageVersionSettings = configuration.languageVersionSettings
val metadataSerializer = KlibMetadataIncrementalSerializer(
languageVersionSettings,
metadataVersion,
descriptorTable)
fun serializeScope(fqName: FqName, memberScope: Collection<DeclarationDescriptor>): ByteArray { fun serializeScope(fqName: FqName, memberScope: Collection<DeclarationDescriptor>): ByteArray {
return JsKlibMetadataSerializationUtil.serializeDescriptors( return metadataSerializer.serializePackageFragment(
bindingContext, bindingContext,
moduleDescriptor, moduleDescriptor,
memberScope, memberScope,
fqName, fqName
languageVersionSettings,
metadataVersion,
descriptorSelector
).toByteArray() ).toByteArray()
} }
@@ -393,25 +346,28 @@ fun serializeModuleIntoKlib(
processCompiledFileData(VfsUtilCore.virtualToIoFile(ktFile.virtualFile), compiledKotlinFile) processCompiledFileData(VfsUtilCore.virtualToIoFile(ktFile.virtualFile), compiledKotlinFile)
} }
incrementalResultsConsumer?.run {
processHeader(JsKlibMetadataSerializationUtil.serializeHeader(moduleDescriptor, null, languageVersionSettings).toByteArray())
}
val compiledKotlinFiles = cleanFiles + additionalFiles val compiledKotlinFiles = cleanFiles + additionalFiles
val header = metadataSerializer.serializeHeader(
moduleDescriptor,
compiledKotlinFiles.map { it.irData.fqName }.distinct()
).toByteArray()
incrementalResultsConsumer?.run {
processHeader(header)
}
val serializedMetadata = val serializedMetadata =
JsKlibMetadataSerializationUtil.serializedMetadata( metadataSerializer.serializedMetadata(
moduleDescriptor, compiledKotlinFiles.groupBy { it.irData.fqName }.map { (fqn, data) -> fqn to data.sortedBy { it.irData.path }.map { it.metadata } }.toMap(),
languageVersionSettings, header
dependencies.map { it.moduleName },
compiledKotlinFiles.groupBy { it.irData.fqName }.map { (fqn, data) -> fqn to data.sortedBy { it.irData.path }.map { it.metadata } }.toMap()
) )
val fullSerializedIr = SerializedIrModule(compiledKotlinFiles.map { it.irData }) val fullSerializedIr = SerializedIrModule(compiledKotlinFiles.map { it.irData })
val abiVersion = KotlinAbiVersion.CURRENT val abiVersion = KotlinAbiVersion.CURRENT
// DO NOT PUSH. Commonize me.
val compilerVersion = KonanVersionImpl(MetaVersion.DEV, 1, 3, 0, -1) val compilerVersion = KonanVersionImpl(MetaVersion.DEV, 1, 3, 0, -1)
val libraryVersion = "JSIR" val libraryVersion = null
val versions = KonanLibraryVersioning(abiVersion = abiVersion, libraryVersion = libraryVersion, compilerVersion = compilerVersion) val versions = KonanLibraryVersioning(abiVersion = abiVersion, libraryVersion = libraryVersion, compilerVersion = compilerVersion)
@@ -6,16 +6,15 @@
package org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir package org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir
import org.jetbrains.kotlin.backend.common.serialization.* import org.jetbrains.kotlin.backend.common.serialization.*
import org.jetbrains.kotlin.builtins.functions.FunctionClassDescriptor import org.jetbrains.kotlin.backend.common.serialization.DescriptorReferenceDeserializer
import org.jetbrains.kotlin.builtins.functions.FunctionInvokeDescriptor import org.jetbrains.kotlin.backend.common.serialization.DescriptorUniqIdAware
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.backend.common.serialization.DeserializedDescriptorUniqIdAware
import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
import org.jetbrains.kotlin.name.FqName
class JsDescriptorReferenceDeserializer( class JsDescriptorReferenceDeserializer(
currentModule: ModuleDescriptor, currentModule: ModuleDescriptor,
mangler: KotlinMangler, mangler: KotlinMangler,
builtIns: IrBuiltIns builtIns: IrBuiltIns
) : DescriptorReferenceDeserializer(currentModule, mangler, builtIns, mutableMapOf()), ) : 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.DeclarationDescriptorWithVisibility
import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.descriptors.Visibilities 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.descriptors.IrBuiltIns
import org.jetbrains.kotlin.ir.util.SymbolTable import org.jetbrains.kotlin.ir.util.SymbolTable
import org.jetbrains.kotlin.resolve.descriptorUtil.isPublishedApi import org.jetbrains.kotlin.resolve.descriptorUtil.isPublishedApi
@@ -23,7 +23,7 @@ class JsIrLinker(
builtIns: IrBuiltIns, builtIns: IrBuiltIns,
symbolTable: SymbolTable symbolTable: SymbolTable
) : KotlinIrLinker(logger, builtIns, symbolTable, emptyList(), null, PUBLIC_LOCAL_UNIQ_ID_EDGE), ) : KotlinIrLinker(logger, builtIns, symbolTable, emptyList(), null, PUBLIC_LOCAL_UNIQ_ID_EDGE),
DescriptorUniqIdAware by JsDescriptorUniqIdAware { DescriptorUniqIdAware by DeserializedDescriptorUniqIdAware {
override val descriptorReferenceDeserializer = override val descriptorReferenceDeserializer =
JsDescriptorReferenceDeserializer(currentModule, mangler, builtIns) JsDescriptorReferenceDeserializer(currentModule, mangler, builtIns)
@@ -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.ModuleDescriptor
import org.jetbrains.kotlin.descriptors.SourceFile import org.jetbrains.kotlin.descriptors.SourceFile
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor 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.ProtoBuf
import org.jetbrains.kotlin.metadata.deserialization.NameResolverImpl import org.jetbrains.kotlin.metadata.deserialization.NameResolverImpl
import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.ClassId
@@ -22,14 +23,14 @@ class JsKlibMetadataPackageFragment(
storageManager: StorageManager, storageManager: StorageManager,
module: ModuleDescriptor, module: ModuleDescriptor,
proto: ProtoBuf.PackageFragment, proto: ProtoBuf.PackageFragment,
header: JsKlibMetadataProtoBuf.Header, header: KlibMetadataProtoBuf.Header,
metadataVersion: JsKlibMetadataVersion, metadataVersion: JsKlibMetadataVersion,
configuration: DeserializationConfiguration configuration: DeserializationConfiguration
) : DeserializedPackageFragmentImpl( ) : DeserializedPackageFragmentImpl(
fqName, storageManager, module, proto, metadataVersion, JsContainerSource(fqName, header, configuration) fqName, storageManager, module, proto, metadataVersion, JsContainerSource(fqName, header, configuration)
) { ) {
val fileMap: Map<Int, FileHolder> = 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) (if (file.hasId()) file.id else index) to FileHolder(file.annotationList)
} }
@@ -48,7 +49,7 @@ class JsKlibMetadataPackageFragment(
class JsContainerSource( class JsContainerSource(
private val fqName: FqName, private val fqName: FqName,
header: JsKlibMetadataProtoBuf.Header, header: KlibMetadataProtoBuf.Header,
configuration: DeserializationConfiguration configuration: DeserializationConfiguration
) : DeserializedContainerSource { ) : DeserializedContainerSource {
val annotations: List<ClassId> = 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,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
)
@@ -14,6 +14,10 @@ import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
import org.jetbrains.kotlin.config.* import org.jetbrains.kotlin.config.*
import org.jetbrains.kotlin.js.config.JSConfigurationKeys import org.jetbrains.kotlin.js.config.JSConfigurationKeys
import org.jetbrains.kotlin.library.KotlinLibrary 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.psi.KtFile
import org.jetbrains.kotlin.resolve.multiplatform.isCommonSource import org.jetbrains.kotlin.resolve.multiplatform.isCommonSource
import org.jetbrains.kotlin.serialization.js.ModuleKind import org.jetbrains.kotlin.serialization.js.ModuleKind
@@ -59,7 +63,7 @@ fun buildKLib(
moduleName: String, moduleName: String,
sources: List<String>, sources: List<String>,
outputPath: String, outputPath: String,
dependencies: List<KotlinLibrary>, allDependencies: KotlinLibraryResolveResult,
commonSources: List<String> commonSources: List<String>
) { ) {
generateKLib( generateKLib(
@@ -72,7 +76,7 @@ fun buildKLib(
file file
}, },
configuration = buildConfiguration(environment, moduleName), configuration = buildConfiguration(environment, moduleName),
allDependencies = dependencies, allDependencies = allDependencies,
friendDependencies = emptyList(), friendDependencies = emptyList(),
outputKlibPath = outputPath, outputKlibPath = outputPath,
nopack = true nopack = true
@@ -113,12 +117,18 @@ fun main(args: Array<String>) {
error("Please set path to .klm file: `-o some/dir/module-name.klm`") 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 { buildKLib(File(outputPath).absolutePath, listOfKtFilesFrom(inputFiles), outputPath, resolvedLibraries, listOfKtFilesFrom(commonSources))
val file = File(it)
loadKlib(file.path)
}
buildKLib(name.dropLast(4), listOfKtFilesFrom(inputFiles), outputPath, dependencyKLibs, listOfKtFilesFrom(commonSources))
} }
@@ -5,13 +5,12 @@
package org.jetbrains.kotlin.konan.file package org.jetbrains.kotlin.konan.file
import org.jetbrains.kotlin.konan.util.removeSuffixIfPresent import org.jetbrains.kotlin.util.removeSuffixIfPresent
import java.io.BufferedReader import java.io.BufferedReader
import java.io.InputStream import java.io.InputStream
import java.io.InputStreamReader import java.io.InputStreamReader
import java.io.RandomAccessFile import java.io.RandomAccessFile
import java.lang.Exception import java.lang.Exception
import java.net.URI
import java.nio.MappedByteBuffer import java.nio.MappedByteBuffer
import java.nio.channels.FileChannel import java.nio.channels.FileChannel
import java.nio.file.* import java.nio.file.*
@@ -6,7 +6,7 @@
package org.jetbrains.kotlin.konan.properties package org.jetbrains.kotlin.konan.properties
import org.jetbrains.kotlin.konan.file.* import org.jetbrains.kotlin.konan.file.*
import org.jetbrains.kotlin.konan.util.parseSpaceSeparatedArgs import org.jetbrains.kotlin.util.parseSpaceSeparatedArgs
import java.io.ByteArrayOutputStream import java.io.ByteArrayOutputStream
typealias Properties = java.util.Properties typealias Properties = java.util.Properties
@@ -3,7 +3,7 @@
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. * 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.konan.util package org.jetbrains.kotlin.util
import kotlin.system.measureTimeMillis import kotlin.system.measureTimeMillis
import org.jetbrains.kotlin.konan.file.* import org.jetbrains.kotlin.konan.file.*
@@ -20,7 +20,8 @@ fun <T> printMillisec(message: String, body: () -> T): T {
fun profile(message: String, body: () -> Unit) = profileIf( fun profile(message: String, body: () -> Unit) = profileIf(
System.getProperty("konan.profile")?.equals("true") ?: false, System.getProperty("konan.profile")?.equals("true") ?: false,
message, body) message, body
)
fun profileIf(condition: Boolean, message: String, body: () -> Unit) = fun profileIf(condition: Boolean, message: String, body: () -> Unit) =
if (condition) printMillisec(message, body) else body() if (condition) printMillisec(message, body) else body()
@@ -0,0 +1,24 @@
package org.jetbrains.kotlin.util
import kotlin.system.exitProcess
interface Logger {
fun log(message: String)
fun error(message: String)
fun warning(message: String)
fun fatal(message: String): Nothing
}
interface WithLogger {
val logger: Logger
}
object DummyLogger : Logger {
override fun log(message: String) = println(message)
override fun error(message: String) = println("e: $message")
override fun warning(message: String) = println("w: $message")
override fun fatal(message: String): Nothing {
println("e: $message")
exitProcess(1)
}
}
@@ -0,0 +1,24 @@
plugins {
kotlin("jvm")
id("jps-compatible")
}
description = "Common klib metadata reader and writer"
dependencies {
compile(kotlinStdlib())
compile(project(":compiler:frontend"))
compile(project(":core:deserialization"))
compile(project(":compiler:serialization"))
compile(project(":kotlin-util-io"))
compile(project(":kotlin-util-klib"))
}
sourceSets {
"main" { projectDefault() }
"test" { none() }
}
publish()
standardPublicJars()
@@ -14,37 +14,38 @@
* limitations under the License. * limitations under the License.
*/ */
package org.jetbrains.kotlin.ir.backend.js.lower.serialization.metadata; package org.jetbrains.kotlin.library.metadata;
import "core/metadata/src/metadata.proto"; import "core/metadata/src/metadata.proto";
option java_outer_classname = "JsKlibMetadataProtoBuf"; option java_outer_classname = "KlibMetadataProtoBuf";
option optimize_for = LITE_RUNTIME; option optimize_for = LITE_RUNTIME;
message Header { message Header {
required string module_name = 1;
/* /*
preRelease 0x1 = preRelease
*/ */
optional int32 flags = 1; optional int32 flags = 2;
// (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.StringTable strings = 4;
optional org.jetbrains.kotlin.metadata.QualifiedNameTable qualified_names = 5; optional org.jetbrains.kotlin.metadata.QualifiedNameTable qualified_names = 5;
// Annotations on the whole module // Annotations on the whole module
repeated org.jetbrains.kotlin.metadata.Annotation annotation = 6; repeated org.jetbrains.kotlin.metadata.Annotation annotation = 6;
repeated string package_fragment_name = 7;
repeated string empty_package = 8;
// TODO: Unused.
// TODO: We need to have backend specific extension for versionings.
// (patch << 16) + (minor << 8) + major
// optional int32 js_code_binary_version = 3 [default = 1];
} }
message File { message File {
// If absent, id is the index of the file in the Files.file list // If absent, id is the index of the file in the Files.file list
optional int32 id = 1; optional int32 id = 1;
required string name = 2;
repeated org.jetbrains.kotlin.metadata.Annotation annotation = 2; repeated org.jetbrains.kotlin.metadata.Annotation annotation = 3;
} }
message Files { message Files {
@@ -55,73 +56,60 @@ message DescriptorUniqId {
required int64 index = 1; required int64 index = 1;
} }
extend org.jetbrains.kotlin.metadata.Package { extend org.jetbrains.kotlin.metadata.Package {
optional int32 package_fq_name = 131; optional int32 package_fq_name = 171;
} }
extend org.jetbrains.kotlin.metadata.Class { extend org.jetbrains.kotlin.metadata.Class {
repeated org.jetbrains.kotlin.metadata.Annotation class_annotation = 130; repeated org.jetbrains.kotlin.metadata.Annotation class_annotation = 170;
optional int32 class_containing_file_id = 135; optional int32 class_file = 175;
optional DescriptorUniqId class_uniq_id = 136; optional DescriptorUniqId class_uniq_id = 171;
} }
extend org.jetbrains.kotlin.metadata.Constructor { extend org.jetbrains.kotlin.metadata.Constructor {
repeated org.jetbrains.kotlin.metadata.Annotation constructor_annotation = 130; repeated org.jetbrains.kotlin.metadata.Annotation constructor_annotation = 170;
optional DescriptorUniqId constructor_uniq_id = 131; optional DescriptorUniqId constructor_uniq_id = 172;
} }
extend org.jetbrains.kotlin.metadata.Function { extend org.jetbrains.kotlin.metadata.Function {
repeated org.jetbrains.kotlin.metadata.Annotation function_annotation = 130; repeated org.jetbrains.kotlin.metadata.Annotation function_annotation = 170;
optional int32 function_containing_file_id = 135; optional int32 function_file = 172;
optional DescriptorUniqId function_uniq_id = 136; optional DescriptorUniqId function_uniq_id = 173;
} }
extend org.jetbrains.kotlin.metadata.Property { extend org.jetbrains.kotlin.metadata.Property {
repeated org.jetbrains.kotlin.metadata.Annotation property_annotation = 130; repeated org.jetbrains.kotlin.metadata.Annotation property_annotation = 170;
repeated org.jetbrains.kotlin.metadata.Annotation property_getter_annotation = 132; repeated org.jetbrains.kotlin.metadata.Annotation property_getter_annotation = 177;
repeated org.jetbrains.kotlin.metadata.Annotation property_setter_annotation = 133; repeated org.jetbrains.kotlin.metadata.Annotation property_setter_annotation = 178;
optional org.jetbrains.kotlin.metadata.Annotation.Argument.Value compile_time_value = 131; optional org.jetbrains.kotlin.metadata.Annotation.Argument.Value compile_time_value = 173;
optional int32 property_containing_file_id = 135; optional int32 property_file = 176;
optional DescriptorUniqId property_uniq_id = 136; optional DescriptorUniqId property_uniq_id = 179;
} }
extend org.jetbrains.kotlin.metadata.EnumEntry { extend org.jetbrains.kotlin.metadata.EnumEntry {
repeated org.jetbrains.kotlin.metadata.Annotation enum_entry_annotation = 130; repeated org.jetbrains.kotlin.metadata.Annotation enum_entry_annotation = 170;
optional DescriptorUniqId enum_entry_uniq_id = 131; optional int32 enum_entry_ordinal = 171;
} optional DescriptorUniqId enum_entry_uniq_id = 172;
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 { extend org.jetbrains.kotlin.metadata.Type {
repeated org.jetbrains.kotlin.metadata.Annotation type_annotation = 130; repeated org.jetbrains.kotlin.metadata.Annotation type_annotation = 170;
} }
extend org.jetbrains.kotlin.metadata.TypeParameter { extend org.jetbrains.kotlin.metadata.TypeParameter {
repeated org.jetbrains.kotlin.metadata.Annotation type_parameter_annotation = 130; repeated org.jetbrains.kotlin.metadata.Annotation type_parameter_annotation = 170;
optional DescriptorUniqId type_param_uniq_id = 131; optional DescriptorUniqId type_param_uniq_id = 171;
} }
extend org.jetbrains.kotlin.metadata.PackageFragment { extend org.jetbrains.kotlin.metadata.PackageFragment {
optional Files package_fragment_files = 130; optional Files package_fragment_files = 170;
optional bool is_empty = 172;
optional string fq_name = 173;
// id in StringTable
repeated int32 class_name = 174 [packed = true];
} }
extend org.jetbrains.kotlin.metadata.TypeAlias { extend org.jetbrains.kotlin.metadata.TypeAlias {
// TODO repeated org.jetbrains.kotlin.metadata.Annotation type_alias_annotation = 130; // TODO repeated org.jetbrains.kotlin.metadata.Annotation type_alias_annotation = 130;
optional DescriptorUniqId type_alias_uniq_id = 131; 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;
}
@@ -3,33 +3,33 @@
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. * 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.serialization.konan package org.jetbrains.kotlin.library.metadata
import org.jetbrains.kotlin.backend.common.serialization.metadata.KlibMetadataVersion
import org.jetbrains.kotlin.descriptors.SourceElement import org.jetbrains.kotlin.descriptors.SourceElement
import org.jetbrains.kotlin.library.metadata.KlibMetadataProtoBuf
import org.jetbrains.kotlin.metadata.deserialization.NameResolver import org.jetbrains.kotlin.metadata.deserialization.NameResolver
import org.jetbrains.kotlin.metadata.konan.KonanProtoBuf
import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.serialization.deserialization.ClassData import org.jetbrains.kotlin.serialization.deserialization.ClassData
import org.jetbrains.kotlin.serialization.deserialization.ClassDataFinder import org.jetbrains.kotlin.serialization.deserialization.ClassDataFinder
import org.jetbrains.kotlin.serialization.deserialization.getClassId import org.jetbrains.kotlin.serialization.deserialization.getClassId
class KonanClassDataFinder( class KlibMetadataClassDataFinder(
private val fragment: KonanProtoBuf.LinkDataPackageFragment, private val fragment: org.jetbrains.kotlin.metadata.ProtoBuf.PackageFragment,
private val nameResolver: NameResolver private val nameResolver: NameResolver
) : ClassDataFinder { ) : ClassDataFinder {
val nameList = fragment.getExtension(KlibMetadataProtoBuf.className).orEmpty()
override fun findClassData(classId: ClassId): ClassData? { override fun findClassData(classId: ClassId): ClassData? {
val proto = fragment.classes
val nameList = proto.classNameList
val index = nameList.indexOfFirst { nameResolver.getClassId(it) == classId } val index = nameList.indexOfFirst { nameResolver.getClassId(it) == classId }
if (index == -1) { if (index == -1) {
return null return null
} }
val foundClass = proto.getClasses(index) ?: error("Could not find data for serialized class $classId") val foundClass = fragment.getClass_(index) ?: error("Could not find data for serialized class $classId")
/* TODO: binary version supposed to be read from protobuf. */ /* TODO: binary version supposed to be read from protobuf. */
return ClassData(nameResolver, foundClass, KonanMetadataVersion.INSTANCE, SourceElement.NO_SOURCE) return ClassData(nameResolver, foundClass, KlibMetadataVersion.INSTANCE, SourceElement.NO_SOURCE)
} }
} }
@@ -0,0 +1,30 @@
/*
* Copyright 2010-2018 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.library.metadata
import org.jetbrains.kotlin.library.KotlinLibrary
import org.jetbrains.kotlin.metadata.ProtoBuf
fun parsePackageFragment(packageMetadata: ByteArray): ProtoBuf.PackageFragment =
ProtoBuf.PackageFragment.parseFrom(packageMetadata, KlibMetadataSerializerProtocol.extensionRegistry)
fun parseModuleHeader(libraryMetadata: ByteArray): KlibMetadataProtoBuf.Header =
KlibMetadataProtoBuf.Header.parseFrom(libraryMetadata, KlibMetadataSerializerProtocol.extensionRegistry)
interface PackageAccessHandler {
fun loadModuleHeader(
library: KotlinLibrary
): KlibMetadataProtoBuf.Header = parseModuleHeader(library.moduleHeaderData)
fun loadPackageFragment(
library: KotlinLibrary,
packageFqName: String,
partName: String
): ProtoBuf.PackageFragment = parsePackageFragment(library.packageMetadata(packageFqName, partName))
}
object SimplePackageAccessHandler : PackageAccessHandler
@@ -0,0 +1,24 @@
package org.jetbrains.kotlin.backend.common.serialization.metadata
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor
import org.jetbrains.kotlin.library.KotlinLibrary
import org.jetbrains.kotlin.library.metadata.KlibMetadataPackageFragment
import org.jetbrains.kotlin.library.metadata.PackageAccessHandler
import org.jetbrains.kotlin.storage.StorageManager
interface KlibMetadataDeserializedPackageFragmentsFactory {
fun createDeserializedPackageFragments(
library: KotlinLibrary,
packageFragmentNames: List<String>,
moduleDescriptor: ModuleDescriptor,
packageAccessedHandler: PackageAccessHandler?,
storageManager: StorageManager
): List<KlibMetadataPackageFragment>
fun createSyntheticPackageFragments(
library: KotlinLibrary,
deserializedPackageFragments: List<KlibMetadataPackageFragment>,
moduleDescriptor: ModuleDescriptor
): List<PackageFragmentDescriptor>
}
@@ -0,0 +1,62 @@
/*
* Copyright 2010-2018 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.konan.util
import org.jetbrains.kotlin.backend.common.serialization.metadata.KlibMetadataDeserializedPackageFragmentsFactory
import org.jetbrains.kotlin.backend.common.serialization.metadata.KlibMetadataModuleDescriptorFactory
import org.jetbrains.kotlin.backend.common.serialization.metadata.impl.KlibMetadataDeserializedPackageFragmentsFactoryImpl
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.konan.KlibModuleDescriptorFactory
import org.jetbrains.kotlin.descriptors.konan.impl.KlibModuleDescriptorFactoryImpl
import org.jetbrains.kotlin.serialization.deserialization.FlexibleTypeDeserializer
import org.jetbrains.kotlin.serialization.konan.KlibResolvedModuleDescriptorsFactory
import org.jetbrains.kotlin.serialization.konan.impl.KlibMetadataModuleDescriptorFactoryImpl
import org.jetbrains.kotlin.serialization.konan.impl.KlibResolvedModuleDescriptorsFactoryImpl
import org.jetbrains.kotlin.storage.StorageManager
/**
* The default Kotlin/Native factories.
*/
open class KlibMetadataFactories(
createBuiltIns:(StorageManager) -> KotlinBuiltIns,
val flexibleTypeDeserializer: FlexibleTypeDeserializer
) {
/**
* The default [KlibModuleDescriptorFactory] factory instance.
*/
val DefaultDescriptorFactory: KlibModuleDescriptorFactory = KlibModuleDescriptorFactoryImpl(createBuiltIns)
/**
* The default [KlibMetadataDeserializedPackageFragmentsFactory] factory instance.
*/
val DefaultPackageFragmentsFactory: KlibMetadataDeserializedPackageFragmentsFactory =
KlibMetadataDeserializedPackageFragmentsFactoryImpl()
/**
* The default [KlibMetadataModuleDescriptorFactory] factory instance.
*/
val DefaultDeserializedDescriptorFactory: KlibMetadataModuleDescriptorFactory =
createDefaultKonanDeserializedModuleDescriptorFactory(
DefaultDescriptorFactory, DefaultPackageFragmentsFactory
)
/**
* The default [KlibResolvedModuleDescriptorsFactory] factory instance.
*/
val DefaultResolvedDescriptorsFactory: KlibResolvedModuleDescriptorsFactory =
createDefaultKonanResolvedModuleDescriptorsFactory(DefaultDeserializedDescriptorFactory)
fun createDefaultKonanDeserializedModuleDescriptorFactory(
descriptorFactory: KlibModuleDescriptorFactory,
packageFragmentsFactory: KlibMetadataDeserializedPackageFragmentsFactory
): KlibMetadataModuleDescriptorFactory =
KlibMetadataModuleDescriptorFactoryImpl(descriptorFactory, packageFragmentsFactory, flexibleTypeDeserializer)
fun createDefaultKonanResolvedModuleDescriptorsFactory(
moduleDescriptorFactory: KlibMetadataModuleDescriptorFactory
): KlibResolvedModuleDescriptorsFactory = KlibResolvedModuleDescriptorsFactoryImpl(moduleDescriptorFactory)
}
@@ -3,19 +3,19 @@
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. * 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.serialization.konan package org.jetbrains.kotlin.backend.common.serialization.metadata
import org.jetbrains.kotlin.metadata.deserialization.BinaryVersion import org.jetbrains.kotlin.metadata.deserialization.BinaryVersion
class KonanMetadataVersion(vararg numbers: Int) : BinaryVersion(*numbers) { class KlibMetadataVersion(vararg numbers: Int) : BinaryVersion(*numbers) {
override fun isCompatible(): Boolean = this.major == 1 && this.minor == 0 override fun isCompatible(): Boolean = this.major == 1 && this.minor == 0
companion object { companion object {
@JvmField @JvmField
val INSTANCE = KonanMetadataVersion(1, 0, 0) val INSTANCE = KlibMetadataVersion(1, 0, 0)
@JvmField @JvmField
val INVALID_VERSION = KonanMetadataVersion() val INVALID_VERSION = KlibMetadataVersion()
} }
} }
@@ -0,0 +1,59 @@
package org.jetbrains.kotlin.backend.common.serialization.metadata
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.descriptors.PackageFragmentProvider
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
import org.jetbrains.kotlin.descriptors.konan.KlibModuleDescriptorFactory
import org.jetbrains.kotlin.library.KotlinLibrary
import org.jetbrains.kotlin.library.metadata.PackageAccessHandler
import org.jetbrains.kotlin.serialization.deserialization.DeserializationConfiguration
import org.jetbrains.kotlin.serialization.deserialization.FlexibleTypeDeserializer
import org.jetbrains.kotlin.storage.StorageManager
interface KlibMetadataModuleDescriptorFactory {
val descriptorFactory: KlibModuleDescriptorFactory
val packageFragmentsFactory: KlibMetadataDeserializedPackageFragmentsFactory
val flexibleTypeDeserializer: FlexibleTypeDeserializer
fun createDescriptor(
library: KotlinLibrary,
languageVersionSettings: LanguageVersionSettings,
storageManager: StorageManager,
builtIns: KotlinBuiltIns,
packageAccessHandler: PackageAccessHandler?
) = createDescriptorOptionalBuiltIns(
library,
languageVersionSettings,
storageManager,
builtIns,
packageAccessHandler
)
fun createDescriptorAndNewBuiltIns(
library: KotlinLibrary,
languageVersionSettings: LanguageVersionSettings,
storageManager: StorageManager,
packageAccessHandler: PackageAccessHandler?
) = createDescriptorOptionalBuiltIns(library, languageVersionSettings, storageManager, null, packageAccessHandler)
fun createDescriptorOptionalBuiltIns(
library: KotlinLibrary,
languageVersionSettings: LanguageVersionSettings,
storageManager: StorageManager,
builtIns: KotlinBuiltIns?,
packageAccessHandler: PackageAccessHandler?
): ModuleDescriptorImpl
fun createPackageFragmentProvider(
library: KotlinLibrary,
packageAccessHandler: PackageAccessHandler?,
packageFragmentNames: List<String>,
storageManager: StorageManager,
moduleDescriptor: ModuleDescriptor,
configuration: DeserializationConfiguration,
compositePackageFragmentAddend: PackageFragmentProvider?
): PackageFragmentProvider
}
@@ -3,13 +3,13 @@
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. * 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.serialization.konan package org.jetbrains.kotlin.library.metadata
import org.jetbrains.kotlin.backend.common.serialization.metadata.KlibMetadataVersion
import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.konan.library.KonanLibrary import org.jetbrains.kotlin.library.KotlinLibrary
import org.jetbrains.kotlin.konan.library.resolver.PackageAccessedHandler import org.jetbrains.kotlin.metadata.ProtoBuf
import org.jetbrains.kotlin.metadata.deserialization.NameResolverImpl import org.jetbrains.kotlin.metadata.deserialization.NameResolverImpl
import org.jetbrains.kotlin.metadata.konan.KonanProtoBuf
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.serialization.deserialization.DeserializationComponents import org.jetbrains.kotlin.serialization.deserialization.DeserializationComponents
@@ -19,13 +19,13 @@ import org.jetbrains.kotlin.serialization.deserialization.getClassId
import org.jetbrains.kotlin.serialization.deserialization.getName import org.jetbrains.kotlin.serialization.deserialization.getName
import org.jetbrains.kotlin.storage.StorageManager import org.jetbrains.kotlin.storage.StorageManager
class KonanPackageFragment( class KlibMetadataPackageFragment(
fqName: FqName, fqName: FqName,
private val library: KonanLibrary, private val library: KotlinLibrary,
private val packageAccessedHandler: PackageAccessedHandler?, private val packageAccessHandler: PackageAccessHandler?,
storageManager: StorageManager, storageManager: StorageManager,
module: ModuleDescriptor, module: ModuleDescriptor,
partName: String private val partName: String
) : DeserializedPackageFragment(fqName, storageManager, module) { ) : DeserializedPackageFragment(fqName, storageManager, module) {
lateinit var components: DeserializationComponents lateinit var components: DeserializationComponents
@@ -36,17 +36,20 @@ class KonanPackageFragment(
// The proto field is lazy so that we can load only needed // The proto field is lazy so that we can load only needed
// packages from the library. // packages from the library.
private val protoForNames: KonanProtoBuf.LinkDataPackageFragment by lazy { library.packageMetadata(fqName.asString(), partName) } private val protoForNames: ProtoBuf.PackageFragment by lazy {
(packageAccessHandler ?: SimplePackageAccessHandler).loadPackageFragment(library, fqName.asString(), partName)
}
val proto: KonanProtoBuf.LinkDataPackageFragment // TODO: Do we really need both 'protoForNames' and 'proto' today?
get() = protoForNames.also { packageAccessedHandler?.markPackageAccessed(fqName) } val proto: ProtoBuf.PackageFragment
get() = protoForNames
private val nameResolver by lazy { private val nameResolver by lazy {
NameResolverImpl(protoForNames.stringTable, protoForNames.nameTable) NameResolverImpl(protoForNames.strings, protoForNames.qualifiedNames)
} }
override val classDataFinder by lazy { override val classDataFinder by lazy {
KonanClassDataFinder(proto, nameResolver) KlibMetadataClassDataFinder(proto, nameResolver)
} }
private val _memberScope by lazy { private val _memberScope by lazy {
@@ -55,10 +58,12 @@ class KonanPackageFragment(
this, this,
proto.getPackage(), proto.getPackage(),
nameResolver, nameResolver,
KonanMetadataVersion.INSTANCE, KlibMetadataVersion.INSTANCE,
/* containerSource = */ null, /* containerSource = */ null,
components components
) { loadClassNames() } ) {
loadClassNames()
}
} }
override fun getMemberScope(): DeserializedPackageMemberScope = _memberScope override fun getMemberScope(): DeserializedPackageMemberScope = _memberScope
@@ -74,7 +79,7 @@ class KonanPackageFragment(
private fun loadClassNames(): Collection<Name> { private fun loadClassNames(): Collection<Name> {
val classNameList = protoForNames.classes.classNameList val classNameList = protoForNames.getExtension(KlibMetadataProtoBuf.className).orEmpty()
val names = classNameList.mapNotNull { val names = classNameList.mapNotNull {
val classId = nameResolver.getClassId(it) val classId = nameResolver.getClassId(it)
@@ -84,4 +89,4 @@ class KonanPackageFragment(
return names return names
} }
} }
@@ -0,0 +1,25 @@
/*
* 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.library.metadata
import org.jetbrains.kotlin.protobuf.ExtensionRegistryLite
import org.jetbrains.kotlin.serialization.SerializerExtensionProtocol
object KlibMetadataSerializerProtocol : SerializerExtensionProtocol(
ExtensionRegistryLite.newInstance().apply(KlibMetadataProtoBuf::registerAllExtensions),
KlibMetadataProtoBuf.packageFqName,
KlibMetadataProtoBuf.constructorAnnotation,
KlibMetadataProtoBuf.classAnnotation,
KlibMetadataProtoBuf.functionAnnotation,
KlibMetadataProtoBuf.propertyAnnotation,
KlibMetadataProtoBuf.propertyGetterAnnotation,
KlibMetadataProtoBuf.propertySetterAnnotation,
KlibMetadataProtoBuf.enumEntryAnnotation,
KlibMetadataProtoBuf.compileTimeValue,
KlibMetadataProtoBuf.parameterAnnotation,
KlibMetadataProtoBuf.typeAnnotation,
KlibMetadataProtoBuf.typeParameterAnnotation
)
@@ -3,7 +3,7 @@
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. * 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 package org.jetbrains.kotlin.backend.common.serialization.metadata
import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
@@ -14,7 +14,7 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.classId
import org.jetbrains.kotlin.resolve.descriptorUtil.getAllSuperClassifiers import org.jetbrains.kotlin.resolve.descriptorUtil.getAllSuperClassifiers
import org.jetbrains.kotlin.serialization.StringTableImpl import org.jetbrains.kotlin.serialization.StringTableImpl
class JsKlibMetadataStringTable : StringTableImpl() { class KlibMetadataStringTable : StringTableImpl() {
override fun getLocalClassIdReplacement(descriptor: ClassifierDescriptorWithTypeParameters): ClassId? { override fun getLocalClassIdReplacement(descriptor: ClassifierDescriptorWithTypeParameters): ClassId? {
return if (descriptor.containingDeclaration is CallableMemberDescriptor) { return if (descriptor.containingDeclaration is CallableMemberDescriptor) {
val superClassifiers = descriptor.getAllSuperClassifiers() val superClassifiers = descriptor.getAllSuperClassifiers()
@@ -11,7 +11,7 @@ import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.storage.StorageManager import org.jetbrains.kotlin.storage.StorageManager
interface KonanModuleDescriptorFactory { interface KlibModuleDescriptorFactory {
/** /**
* Base method for creation of any Kotlin/Native [ModuleDescriptor]. * Base method for creation of any Kotlin/Native [ModuleDescriptor].
@@ -20,7 +20,7 @@ interface KonanModuleDescriptorFactory {
name: Name, name: Name,
storageManager: StorageManager, storageManager: StorageManager,
builtIns: KotlinBuiltIns, builtIns: KotlinBuiltIns,
origin: KonanModuleOrigin, origin: KlibModuleOrigin,
customCapabilities: Map<ModuleDescriptor.Capability<*>, Any?> = emptyMap() customCapabilities: Map<ModuleDescriptor.Capability<*>, Any?> = emptyMap()
): ModuleDescriptorImpl ): ModuleDescriptorImpl
@@ -31,7 +31,7 @@ interface KonanModuleDescriptorFactory {
fun createDescriptorAndNewBuiltIns( fun createDescriptorAndNewBuiltIns(
name: Name, name: Name,
storageManager: StorageManager, storageManager: StorageManager,
origin: KonanModuleOrigin, origin: KlibModuleOrigin,
customCapabilities: Map<ModuleDescriptor.Capability<*>, Any?> = emptyMap() customCapabilities: Map<ModuleDescriptor.Capability<*>, Any?> = emptyMap()
): ModuleDescriptorImpl ): ModuleDescriptorImpl
} }
@@ -0,0 +1,36 @@
/*
* Copyright 2010-2018 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.descriptors.konan
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.library.KotlinLibrary
import org.jetbrains.kotlin.library.isInterop
sealed class KlibModuleOrigin {
companion object {
val CAPABILITY = ModuleDescriptor.Capability<KlibModuleOrigin>("KlibModuleOrigin")
}
}
sealed class CompiledKlibModuleOrigin: KlibModuleOrigin()
class DeserializedKlibModuleOrigin(val library: KotlinLibrary) : CompiledKlibModuleOrigin()
object CurrentKlibModuleOrigin: CompiledKlibModuleOrigin()
object SyntheticModulesOrigin : KlibModuleOrigin()
internal fun KlibModuleOrigin.isInteropLibrary(): Boolean = when (this) {
is DeserializedKlibModuleOrigin -> this.library.isInterop
CurrentKlibModuleOrigin, SyntheticModulesOrigin -> false
}
val ModuleDescriptor.klibModuleOrigin get() = this.getCapability(KlibModuleOrigin.CAPABILITY)!!
val ModuleDescriptor.kotlinLibrary get() =
(this.klibModuleOrigin as DeserializedKlibModuleOrigin)
.library
@@ -0,0 +1,50 @@
package org.jetbrains.kotlin.serialization.konan
import org.jetbrains.kotlin.library.resolver.KotlinLibraryResolveResult
import org.jetbrains.kotlin.backend.common.serialization.metadata.KlibMetadataModuleDescriptorFactory
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
import org.jetbrains.kotlin.library.KotlinLibrary
import org.jetbrains.kotlin.storage.StorageManager
interface KlibResolvedModuleDescriptorsFactory {
val moduleDescriptorFactory: KlibMetadataModuleDescriptorFactory
/**
* Given the [resolvedLibraries] creates the list of [ModuleDescriptorImpl]s with properly installed
* inter-dependencies. The result of this method is returned in a form of [KlibResolvedModuleDescriptors] instance.
*
* Please use this method with care: Unless this method accepts `null` for [builtIns], it is not recommended to
* invoke it this way. If you are compiling a source module, please supply the non-null [builtIns] from the
* source module, so that all modules created in your compilation session will share the same built-ins instance.
*
* Otherwise (if `null` was supplied), a new instance of [KotlinBuiltIns] will be created. The created built-ins
* instance will be shared by all modules created in this method. But this instance will have no connection
* with probably existing built-ins instance of your source module(s).
*/
fun createResolved(
resolvedLibraries: KotlinLibraryResolveResult,
storageManager: StorageManager,
builtIns: KotlinBuiltIns?,
languageVersionSettings: LanguageVersionSettings,
customAction: ((KotlinLibrary, ModuleDescriptorImpl) -> Unit)? = null
): KotlinResolvedModuleDescriptors
}
class KotlinResolvedModuleDescriptors(
/**
* The list of modules each representing an individual Kotlin/Native library. All modules
* in this list have properly installed dependencies, i.e. module has all necessary dependencies
* on other modules plus a dependency on the [forwardDeclarationsModule].
*/
val resolvedDescriptors: List<ModuleDescriptorImpl>,
/**
* This is a module which "contains" forward declarations.
* Note: this module should be unique per compilation and should always be the last dependency of any module.
*/
val forwardDeclarationsModule: ModuleDescriptorImpl
)
@@ -0,0 +1,54 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the LICENSE file.
*/
package org.jetbrains.kotlin.backend.common.serialization.metadata
import org.jetbrains.kotlin.descriptors.SourceFile
import org.jetbrains.kotlin.library.KotlinLibrary
private class DeserializedSourceFile(
val name_: String, val index: Int, val library: KotlinLibrary) : SourceFile {
override fun getName(): String? = name_
override fun equals(other: Any?): Boolean {
return other is DeserializedSourceFile && library == other.library && index == other.index
}
override fun hashCode(): Int {
return library.hashCode() xor index
}
}
class SourceFileMap {
private val sourceToIndex = mutableMapOf<SourceFile, Int>()
private val indexToSource = mutableMapOf<Int, SourceFile>()
fun assign(file: SourceFile): Int {
return sourceToIndex.getOrPut(file) {
sourceToIndex.size
}
}
fun provide(fileName: String, index: Int, library: KotlinLibrary) {
assert(indexToSource[index] == null)
indexToSource[index] =
DeserializedSourceFile(fileName, index, library)
}
fun sourceFile(index: Int): SourceFile =
indexToSource[index] ?: throw Error("Unknown file for $index")
fun filesAndClear() =
sourceToIndex.keys.sortedBy {
sourceToIndex[it]
}.also{
clear()
}
fun clear() {
sourceToIndex.clear()
indexToSource.clear()
}
}
@@ -1,32 +1,20 @@
/* package org.jetbrains.kotlin.backend.common.serialization.metadata.impl
* Copyright 2010-2018 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.serialization.konan.impl import org.jetbrains.kotlin.backend.common.serialization.metadata.KlibMetadataDeserializedPackageFragmentsFactory
import org.jetbrains.kotlin.builtins.functions.functionInterfacePackageFragmentProvider
import org.jetbrains.kotlin.contracts.ContractDeserializerImpl
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.impl.ClassDescriptorImpl import org.jetbrains.kotlin.descriptors.impl.ClassDescriptorImpl
import org.jetbrains.kotlin.descriptors.impl.CompositePackageFragmentProvider
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
import org.jetbrains.kotlin.descriptors.impl.PackageFragmentDescriptorImpl import org.jetbrains.kotlin.descriptors.impl.PackageFragmentDescriptorImpl
import org.jetbrains.kotlin.incremental.components.LookupLocation import org.jetbrains.kotlin.incremental.components.LookupLocation
import org.jetbrains.kotlin.incremental.components.LookupTracker
import org.jetbrains.kotlin.incremental.components.NoLookupLocation import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.konan.library.* import org.jetbrains.kotlin.library.*
import org.jetbrains.kotlin.konan.library.resolver.PackageAccessedHandler import org.jetbrains.kotlin.library.metadata.KlibMetadataPackageFragment
import org.jetbrains.kotlin.library.metadata.PackageAccessHandler
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
import org.jetbrains.kotlin.resolve.scopes.MemberScope import org.jetbrains.kotlin.resolve.scopes.MemberScope
import org.jetbrains.kotlin.resolve.scopes.MemberScopeImpl import org.jetbrains.kotlin.resolve.scopes.MemberScopeImpl
import org.jetbrains.kotlin.serialization.deserialization.* import org.jetbrains.kotlin.serialization.konan.impl.ForwardDeclarationsFqNames
import org.jetbrains.kotlin.serialization.konan.KonanDeserializedPackageFragmentsFactory
import org.jetbrains.kotlin.serialization.konan.KonanPackageFragment
import org.jetbrains.kotlin.serialization.konan.KonanSerializerProtocol
import org.jetbrains.kotlin.serialization.konan.NullFlexibleTypeDeserializer
import org.jetbrains.kotlin.storage.LockBasedStorageManager import org.jetbrains.kotlin.storage.LockBasedStorageManager
import org.jetbrains.kotlin.storage.StorageManager import org.jetbrains.kotlin.storage.StorageManager
import org.jetbrains.kotlin.storage.getValue import org.jetbrains.kotlin.storage.getValue
@@ -34,33 +22,34 @@ import org.jetbrains.kotlin.utils.Printer
import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult
// FIXME(ddol): decouple and move interop-specific logic back to Kotlin/Native. // FIXME(ddol): decouple and move interop-specific logic back to Kotlin/Native.
internal object KonanDeserializedPackageFragmentsFactoryImpl : KonanDeserializedPackageFragmentsFactory { open class KlibMetadataDeserializedPackageFragmentsFactoryImpl: KlibMetadataDeserializedPackageFragmentsFactory {
override fun createDeserializedPackageFragments( override fun createDeserializedPackageFragments(
library: KonanLibrary, library: KotlinLibrary,
packageFragmentNames: List<String>, packageFragmentNames: List<String>,
moduleDescriptor: ModuleDescriptor, moduleDescriptor: ModuleDescriptor,
packageAccessedHandler: PackageAccessedHandler?, packageAccessedHandler: PackageAccessHandler?,
storageManager: StorageManager storageManager: StorageManager
) = packageFragmentNames.flatMap { ) = packageFragmentNames.flatMap {
val fqName = FqName(it) val fqName = FqName(it)
val parts = library.packageMetadataParts(it) val parts = library.packageMetadataParts(fqName.asString())
parts.map { partName -> parts.map { partName ->
KonanPackageFragment(fqName, library, packageAccessedHandler, storageManager, moduleDescriptor, partName) KlibMetadataPackageFragment(fqName, library, packageAccessedHandler, storageManager, moduleDescriptor, partName)
} }
} }
override fun createSyntheticPackageFragments( override fun createSyntheticPackageFragments(
library: KonanLibrary, library: KotlinLibrary,
deserializedPackageFragments: List<KonanPackageFragment>, deserializedPackageFragments: List<KlibMetadataPackageFragment>,
moduleDescriptor: ModuleDescriptor moduleDescriptor: ModuleDescriptor
): List<PackageFragmentDescriptor> { ): List<PackageFragmentDescriptor> {
if (!library.isInterop) return emptyList() if (!library.isInterop) return emptyList()
val mainPackageFqName = library.packageFqName val mainPackageFqName = library.packageFqName?. let{ FqName(it) }
?: error("Inconsistent manifest: interop library ${library.libraryName} should have `package` specified") ?: error("Inconsistent manifest: interop library ${library.libraryName} should have `package` specified")
val exportForwardDeclarations = library.exportForwardDeclarations val exportForwardDeclarations = library.exportForwardDeclarations.map{ FqName(it) }
val aliasedPackageFragments = deserializedPackageFragments.filter { it.fqName == mainPackageFqName } val aliasedPackageFragments = deserializedPackageFragments.filter { it.fqName == mainPackageFqName }
@@ -78,87 +67,6 @@ internal object KonanDeserializedPackageFragmentsFactoryImpl : KonanDeserialized
return result return result
} }
override fun createPackageFragmentProvider(
library: KonanLibrary,
packageAccessedHandler: PackageAccessedHandler?,
packageFragmentNames: List<String>,
storageManager: StorageManager,
moduleDescriptor: ModuleDescriptor,
configuration: DeserializationConfiguration
): PackageFragmentProvider {
val deserializedPackageFragments = createDeserializedPackageFragments(
library, packageFragmentNames, moduleDescriptor, packageAccessedHandler, storageManager
)
val syntheticPackageFragments = createSyntheticPackageFragments(
library, deserializedPackageFragments, moduleDescriptor
)
val packageFragmentProvider = PackageFragmentProviderImpl(deserializedPackageFragments + syntheticPackageFragments)
val notFoundClasses = NotFoundClasses(storageManager, moduleDescriptor)
val annotationAndConstantLoader = AnnotationAndConstantLoaderImpl(
moduleDescriptor,
notFoundClasses,
KonanSerializerProtocol
)
val components = DeserializationComponents(
storageManager,
moduleDescriptor,
configuration,
DeserializedClassDataFinder(packageFragmentProvider),
annotationAndConstantLoader,
packageFragmentProvider,
LocalClassifierTypeSettings.Default,
ErrorReporter.DO_NOTHING,
LookupTracker.DO_NOTHING,
NullFlexibleTypeDeserializer,
emptyList(),
notFoundClasses,
ContractDeserializerImpl(configuration, storageManager),
extensionRegistryLite = KonanSerializerProtocol.extensionRegistry
)
for (packageFragment in deserializedPackageFragments) {
packageFragment.initialize(components)
}
return if (library.uniqueName == KONAN_STDLIB_NAME)
CompositePackageFragmentProvider(
listOf(
packageFragmentProvider,
functionInterfacePackageFragmentProvider(storageManager, moduleDescriptor)
)
)
else
packageFragmentProvider
}
override fun createForwardDeclarationHackPackagePartProvider(
storageManager: StorageManager,
module: ModuleDescriptorImpl
): PackageFragmentProviderImpl {
fun createPackage(fqName: FqName, supertypeName: String, classKind: ClassKind) =
ForwardDeclarationsPackageFragmentDescriptor(
storageManager,
module,
fqName,
Name.identifier(supertypeName),
classKind
)
val packageFragmentProvider = PackageFragmentProviderImpl(
listOf(
createPackage(ForwardDeclarationsFqNames.cNamesStructs, "COpaque", ClassKind.CLASS),
createPackage(ForwardDeclarationsFqNames.objCNamesClasses, "ObjCObjectBase", ClassKind.CLASS),
createPackage(ForwardDeclarationsFqNames.objCNamesProtocols, "ObjCObject", ClassKind.INTERFACE)
)
)
return packageFragmentProvider
}
} }
/** /**
@@ -201,7 +109,7 @@ class ExportedForwardDeclarationsPackageFragmentDescriptor(
* The package fragment that redirects all requests for classifier lookup to its targets. * The package fragment that redirects all requests for classifier lookup to its targets.
*/ */
class ClassifierAliasingPackageFragmentDescriptor( class ClassifierAliasingPackageFragmentDescriptor(
targets: List<KonanPackageFragment>, targets: List<KlibMetadataPackageFragment>,
module: ModuleDescriptor, module: ModuleDescriptor,
fqName: FqName fqName: FqName
) : PackageFragmentDescriptorImpl(module, fqName) { ) : PackageFragmentDescriptorImpl(module, fqName) {
@@ -278,4 +186,5 @@ private class ForwardDeclarationsPackageFragmentDescriptor(
} }
override fun getMemberScope(): MemberScope = memberScope override fun getMemberScope(): MemberScope = memberScope
} }
@@ -0,0 +1,155 @@
/*
* Copyright 2010-2018 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.serialization.konan.impl
import org.jetbrains.kotlin.backend.common.serialization.metadata.*
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.builtins.functions.functionInterfacePackageFragmentProvider
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.contracts.ContractDeserializerImpl
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.impl.CompositePackageFragmentProvider
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
import org.jetbrains.kotlin.descriptors.konan.DeserializedKlibModuleOrigin
import org.jetbrains.kotlin.descriptors.konan.KlibModuleDescriptorFactory
import org.jetbrains.kotlin.descriptors.konan.klibModuleOrigin
import org.jetbrains.kotlin.incremental.components.LookupTracker
import org.jetbrains.kotlin.library.KotlinLibrary
import org.jetbrains.kotlin.library.metadata.KlibMetadataSerializerProtocol
import org.jetbrains.kotlin.library.metadata.PackageAccessHandler
import org.jetbrains.kotlin.library.metadata.parseModuleHeader
import org.jetbrains.kotlin.library.unresolvedDependencies
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.CompilerDeserializationConfiguration
import org.jetbrains.kotlin.serialization.deserialization.*
import org.jetbrains.kotlin.storage.StorageManager
val ModuleDescriptorImpl.isStdlibModule
get() = (this.klibModuleOrigin as? DeserializedKlibModuleOrigin)
?.library?.unresolvedDependencies?.isEmpty() ?: false
class KlibMetadataModuleDescriptorFactoryImpl(
override val descriptorFactory: KlibModuleDescriptorFactory,
override val packageFragmentsFactory: KlibMetadataDeserializedPackageFragmentsFactory,
override val flexibleTypeDeserializer: FlexibleTypeDeserializer
): KlibMetadataModuleDescriptorFactory {
override fun createDescriptorOptionalBuiltIns(
library: KotlinLibrary,
languageVersionSettings: LanguageVersionSettings,
storageManager: StorageManager,
builtIns: KotlinBuiltIns?,
packageAccessHandler: PackageAccessHandler?
): ModuleDescriptorImpl {
val libraryProto = parseModuleHeader(library.moduleHeaderData)
val moduleName = Name.special(libraryProto.moduleName)
val moduleOrigin = DeserializedKlibModuleOrigin(library)
val moduleDescriptor = if (builtIns != null )
descriptorFactory.createDescriptor(moduleName, storageManager, builtIns, moduleOrigin)
else
descriptorFactory.createDescriptorAndNewBuiltIns(moduleName, storageManager, moduleOrigin)
val deserializationConfiguration = CompilerDeserializationConfiguration(languageVersionSettings)
val compositePackageFragmentAddend =
if (moduleDescriptor.isStdlibModule) {
functionInterfacePackageFragmentProvider(storageManager, moduleDescriptor)
} else null
val provider = createPackageFragmentProvider(
library,
packageAccessHandler,
libraryProto.packageFragmentNameList,
storageManager,
moduleDescriptor,
deserializationConfiguration,
compositePackageFragmentAddend
)
moduleDescriptor.initialize(provider)
return moduleDescriptor
}
override fun createPackageFragmentProvider(
library: KotlinLibrary,
packageAccessHandler: PackageAccessHandler?,
packageFragmentNames: List<String>,
storageManager: StorageManager,
moduleDescriptor: ModuleDescriptor,
configuration: DeserializationConfiguration,
compositePackageFragmentAddend: PackageFragmentProvider?
): PackageFragmentProvider {
val deserializedPackageFragments = packageFragmentsFactory.createDeserializedPackageFragments(
library, packageFragmentNames, moduleDescriptor, packageAccessHandler, storageManager)
// TODO: this is native specific. Move to a child class.
val syntheticPackageFragments = packageFragmentsFactory.createSyntheticPackageFragments(
library, deserializedPackageFragments, moduleDescriptor)
val provider = PackageFragmentProviderImpl(deserializedPackageFragments + syntheticPackageFragments)
val notFoundClasses = NotFoundClasses(storageManager, moduleDescriptor)
val annotationAndConstantLoader = AnnotationAndConstantLoaderImpl(
moduleDescriptor,
notFoundClasses,
KlibMetadataSerializerProtocol
)
val components = DeserializationComponents(
storageManager,
moduleDescriptor,
configuration,
DeserializedClassDataFinder(provider),
annotationAndConstantLoader,
provider,
LocalClassifierTypeSettings.Default,
ErrorReporter.DO_NOTHING,
LookupTracker.DO_NOTHING,
flexibleTypeDeserializer,
emptyList(),
notFoundClasses,
ContractDeserializerImpl(configuration, storageManager),
extensionRegistryLite = KlibMetadataSerializerProtocol.extensionRegistry)
for (packageFragment in deserializedPackageFragments) {
packageFragment.initialize(components)
}
return compositePackageFragmentAddend ?.let {
CompositePackageFragmentProvider(listOf(it, provider))
} ?: provider
}
fun createForwardDeclarationHackPackagePartProvider(
storageManager: StorageManager,
module: ModuleDescriptorImpl
): PackageFragmentProviderImpl {
fun createPackage(fqName: FqName, supertypeName: String, classKind: ClassKind) =
ForwardDeclarationsPackageFragmentDescriptor(
storageManager,
module,
fqName,
Name.identifier(supertypeName),
classKind
)
val packageFragmentProvider = PackageFragmentProviderImpl(
listOf(
createPackage(ForwardDeclarationsFqNames.cNamesStructs, "COpaque", ClassKind.CLASS),
createPackage(ForwardDeclarationsFqNames.objCNamesClasses, "ObjCObjectBase", ClassKind.CLASS),
createPackage(ForwardDeclarationsFqNames.objCNamesProtocols, "ObjCObject", ClassKind.INTERFACE)
)
)
return packageFragmentProvider
}
}
@@ -6,30 +6,28 @@
package org.jetbrains.kotlin.descriptors.konan.impl package org.jetbrains.kotlin.descriptors.konan.impl
import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.builtins.konan.KonanBuiltIns
import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
import org.jetbrains.kotlin.descriptors.konan.KonanModuleDescriptorFactory import org.jetbrains.kotlin.descriptors.konan.*
import org.jetbrains.kotlin.descriptors.konan.KonanModuleOrigin
import org.jetbrains.kotlin.descriptors.konan.isInteropLibrary import org.jetbrains.kotlin.descriptors.konan.isInteropLibrary
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.ImplicitIntegerCoercion import org.jetbrains.kotlin.resolve.ImplicitIntegerCoercion
import org.jetbrains.kotlin.storage.StorageManager import org.jetbrains.kotlin.storage.StorageManager
internal object KonanModuleDescriptorFactoryImpl : KonanModuleDescriptorFactory { internal class KlibModuleDescriptorFactoryImpl(val createBuiltIns: (StorageManager) -> KotlinBuiltIns) : KlibModuleDescriptorFactory {
override fun createDescriptor( override fun createDescriptor(
name: Name, name: Name,
storageManager: StorageManager, storageManager: StorageManager,
builtIns: KotlinBuiltIns, builtIns: KotlinBuiltIns,
origin: KonanModuleOrigin, origin: KlibModuleOrigin,
customCapabilities: Map<ModuleDescriptor.Capability<*>, Any?> customCapabilities: Map<ModuleDescriptor.Capability<*>, Any?>
) = ModuleDescriptorImpl( ) = ModuleDescriptorImpl(
name, name,
storageManager, storageManager,
builtIns, builtIns,
capabilities = customCapabilities + mapOf( capabilities = customCapabilities + mapOf(
KonanModuleOrigin.CAPABILITY to origin, KlibModuleOrigin.CAPABILITY to origin,
ImplicitIntegerCoercion.MODULE_CAPABILITY to origin.isInteropLibrary() ImplicitIntegerCoercion.MODULE_CAPABILITY to origin.isInteropLibrary()
) )
) )
@@ -37,11 +35,11 @@ internal object KonanModuleDescriptorFactoryImpl : KonanModuleDescriptorFactory
override fun createDescriptorAndNewBuiltIns( override fun createDescriptorAndNewBuiltIns(
name: Name, name: Name,
storageManager: StorageManager, storageManager: StorageManager,
origin: KonanModuleOrigin, origin: KlibModuleOrigin,
customCapabilities: Map<ModuleDescriptor.Capability<*>, Any?> customCapabilities: Map<ModuleDescriptor.Capability<*>, Any?>
): ModuleDescriptorImpl { ): ModuleDescriptorImpl {
val builtIns = KonanBuiltIns(storageManager) val builtIns = createBuiltIns(storageManager)
val moduleDescriptor = createDescriptor(name, storageManager, builtIns, origin, customCapabilities) val moduleDescriptor = createDescriptor(name, storageManager, builtIns, origin, customCapabilities)
builtIns.builtInsModule = moduleDescriptor builtIns.builtInsModule = moduleDescriptor
@@ -0,0 +1,183 @@
package org.jetbrains.kotlin.serialization.konan.impl
import org.jetbrains.kotlin.library.resolver.KotlinLibraryResolveResult
import org.jetbrains.kotlin.backend.common.serialization.metadata.KlibMetadataModuleDescriptorFactory
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.impl.ClassDescriptorImpl
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
import org.jetbrains.kotlin.descriptors.impl.PackageFragmentDescriptorImpl
import org.jetbrains.kotlin.descriptors.konan.KlibModuleOrigin
import org.jetbrains.kotlin.descriptors.konan.SyntheticModulesOrigin
import org.jetbrains.kotlin.incremental.components.LookupLocation
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.util.profile
import org.jetbrains.kotlin.library.KotlinLibrary
import org.jetbrains.kotlin.library.metadata.PackageAccessHandler
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
import org.jetbrains.kotlin.resolve.scopes.MemberScope
import org.jetbrains.kotlin.resolve.scopes.MemberScopeImpl
import org.jetbrains.kotlin.serialization.konan.KlibResolvedModuleDescriptorsFactory
import org.jetbrains.kotlin.serialization.konan.KotlinResolvedModuleDescriptors
import org.jetbrains.kotlin.storage.LockBasedStorageManager
import org.jetbrains.kotlin.storage.StorageManager
import org.jetbrains.kotlin.storage.getValue
import org.jetbrains.kotlin.utils.Printer
// TODO: eliminate Native specifics.
class KlibResolvedModuleDescriptorsFactoryImpl(
override val moduleDescriptorFactory: KlibMetadataModuleDescriptorFactory
): KlibResolvedModuleDescriptorsFactory {
override fun createResolved(
resolvedLibraries: KotlinLibraryResolveResult,
storageManager: StorageManager,
builtIns: KotlinBuiltIns?,
languageVersionSettings: LanguageVersionSettings,
customAction: ((KotlinLibrary, ModuleDescriptorImpl) -> Unit)?
): KotlinResolvedModuleDescriptors {
val moduleDescriptors = mutableListOf<ModuleDescriptorImpl>()
@Suppress("NAME_SHADOWING")
var builtIns = builtIns
// Build module descriptors.
resolvedLibraries.forEach { library, packageAccessHandler ->
profile("Loading ${library.libraryName}") {
// MutableModuleContext needs ModuleDescriptorImpl, rather than ModuleDescriptor.
val moduleDescriptor = createDescriptorOptionalBuiltsIns(
library, languageVersionSettings, storageManager, builtIns, packageAccessHandler
)
builtIns = moduleDescriptor.builtIns
moduleDescriptors.add(moduleDescriptor)
customAction?.invoke(library, moduleDescriptor)
}
}
val forwardDeclarationsModule = createForwardDeclarationsModule(builtIns, storageManager)
// Set inter-dependencies between module descriptors, add forwarding declarations module.
for (module in moduleDescriptors) {
// Yes, just to all of them.
module.setDependencies(moduleDescriptors + forwardDeclarationsModule)
}
return KotlinResolvedModuleDescriptors(moduleDescriptors, forwardDeclarationsModule)
}
private fun createForwardDeclarationsModule(
builtIns: KotlinBuiltIns?,
storageManager: StorageManager): ModuleDescriptorImpl {
val name = Name.special("<forward declarations>")
val module = createDescriptorOptionalBuiltsIns(name, storageManager, builtIns, SyntheticModulesOrigin)
fun createPackage(fqName: FqName, supertypeName: String, classKind: ClassKind) =
ForwardDeclarationsPackageFragmentDescriptor(
storageManager,
module,
fqName,
Name.identifier(supertypeName),
classKind)
val packageFragmentProvider = PackageFragmentProviderImpl(
listOf(
createPackage(ForwardDeclarationsFqNames.cNamesStructs, "COpaque", ClassKind.CLASS),
createPackage(ForwardDeclarationsFqNames.objCNamesClasses, "ObjCObjectBase", ClassKind.CLASS),
createPackage(ForwardDeclarationsFqNames.objCNamesProtocols, "ObjCObject", ClassKind.INTERFACE)
)
)
module.initialize(packageFragmentProvider)
module.setDependencies(module)
return module
}
private fun createDescriptorOptionalBuiltsIns(
name: Name,
storageManager: StorageManager,
builtIns: KotlinBuiltIns?,
moduleOrigin: KlibModuleOrigin
) = if (builtIns != null)
moduleDescriptorFactory.descriptorFactory.createDescriptor(name, storageManager, builtIns, moduleOrigin)
else
moduleDescriptorFactory.descriptorFactory.createDescriptorAndNewBuiltIns(name, storageManager, moduleOrigin)
private fun createDescriptorOptionalBuiltsIns(
library: KotlinLibrary,
languageVersionSettings: LanguageVersionSettings,
storageManager: StorageManager,
builtIns: KotlinBuiltIns?,
packageAccessHandler: PackageAccessHandler?
) = if (builtIns != null)
moduleDescriptorFactory.createDescriptor(library, languageVersionSettings, storageManager, builtIns, packageAccessHandler)
else
moduleDescriptorFactory.createDescriptorAndNewBuiltIns(library, languageVersionSettings, storageManager, packageAccessHandler)
}
/**
* Package fragment which creates descriptors for forward declarations on demand.
*/
class ForwardDeclarationsPackageFragmentDescriptor(
storageManager: StorageManager,
module: ModuleDescriptor,
fqName: FqName,
supertypeName: Name,
classKind: ClassKind
) : PackageFragmentDescriptorImpl(module, fqName) {
private val memberScope = object : MemberScopeImpl() {
private val declarations = storageManager.createMemoizedFunction(this::createDeclaration)
private val supertype by storageManager.createLazyValue {
val descriptor = builtIns.builtInsModule.getPackage(ForwardDeclarationsFqNames.packageName)
.memberScope
.getContributedClassifier(supertypeName, NoLookupLocation.FROM_BACKEND) as ClassDescriptor
descriptor.defaultType
}
private fun createDeclaration(name: Name): ClassDescriptor {
return ClassDescriptorImpl(
this@ForwardDeclarationsPackageFragmentDescriptor,
name,
Modality.FINAL,
classKind,
listOf(supertype),
SourceElement.NO_SOURCE,
false,
LockBasedStorageManager.NO_LOCKS
).apply {
this.initialize(MemberScope.Empty, emptySet(), null)
}
}
override fun getContributedClassifier(name: Name, location: LookupLocation) = declarations(name)
override fun printScopeStructure(p: Printer) {
p.println(this::class.java.simpleName, "{}")
}
}
override fun getMemberScope(): MemberScope = memberScope
}
// FIXME(ddol): decouple and move interop-specific logic back to Kotlin/Native.
internal object ForwardDeclarationsFqNames {
val packageName = FqName("kotlinx.cinterop")
val cNames = FqName("cnames")
val cNamesStructs = cNames.child(Name.identifier("structs"))
val objCNames = FqName("objcnames")
val objCNamesClasses = objCNames.child(Name.identifier("classes"))
val objCNamesProtocols = objCNames.child(Name.identifier("protocols"))
}
@@ -0,0 +1,56 @@
package org.jetbrains.kotlin.library.resolver
import org.jetbrains.kotlin.library.*
import org.jetbrains.kotlin.library.metadata.PackageAccessHandler
interface KotlinLibraryResolver<L: KotlinLibrary> {
val searchPathResolver: SearchPathResolver<L>
/**
* Given the list of Kotlin/Native library names, ABI version and other parameters
* resolves libraries and evaluates dependencies between them.
*/
fun resolveWithDependencies(
unresolvedLibraries: List<UnresolvedLibrary>,
noStdLib: Boolean = false,
noDefaultLibs: Boolean = false,
noEndorsedLibs: Boolean = false
): KotlinLibraryResolveResult
}
interface KotlinLibraryResolveResult {
fun filterRoots(predicate: (KotlinResolvedLibrary) -> Boolean): KotlinLibraryResolveResult
fun getFullList(order: LibraryOrder? = null): List<KotlinLibrary>
fun forEach(action: (KotlinLibrary, PackageAccessHandler) -> Unit)
}
typealias LibraryOrder = (Iterable<KotlinResolvedLibrary>) -> List<KotlinResolvedLibrary>
val TopologicalLibraryOrder: LibraryOrder = { input ->
val sorted = mutableListOf<KotlinResolvedLibrary>()
val visited = mutableSetOf<KotlinResolvedLibrary>()
val tempMarks = mutableSetOf<KotlinResolvedLibrary>()
fun visit(node: KotlinResolvedLibrary, result: MutableList<KotlinResolvedLibrary>) {
if (visited.contains(node)) return
if (tempMarks.contains(node)) error("Cyclic dependency in library graph for: ${node.library.libraryName}")
tempMarks.add(node)
node.resolvedDependencies.forEach {
visit(it, result)
}
visited.add(node)
result += node
}
input.forEach next@{
if (visited.contains(it)) return@next
visit(it, sorted)
}
sorted
}
@@ -0,0 +1,23 @@
package org.jetbrains.kotlin.library.resolver
import org.jetbrains.kotlin.library.KotlinLibrary
import org.jetbrains.kotlin.library.metadata.PackageAccessHandler
/**
* A [KotlinLibrary] wrapper that is used for resolving library's dependencies.
*/
interface KotlinResolvedLibrary: PackageAccessHandler {
// The library itself.
val library: KotlinLibrary
// Dependencies on other libraries.
val resolvedDependencies: List<KotlinResolvedLibrary>
// Any package fragment within this library has beed visited during frontend resolve phase.
// You need to utilize PackageAccessHandler to make it work for you.
val isNeededForLink: Boolean
// Is provided by the distribution?
val isDefault: Boolean
}
@@ -0,0 +1,156 @@
/*
* Copyright 2010-2019 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.library.resolver.impl
import org.jetbrains.kotlin.konan.file.File
import org.jetbrains.kotlin.library.*
import org.jetbrains.kotlin.library.metadata.PackageAccessHandler
import org.jetbrains.kotlin.library.resolver.KotlinLibraryResolveResult
import org.jetbrains.kotlin.library.resolver.KotlinLibraryResolver
import org.jetbrains.kotlin.library.resolver.KotlinResolvedLibrary
import org.jetbrains.kotlin.library.resolver.LibraryOrder
import org.jetbrains.kotlin.util.WithLogger
fun <L: KotlinLibrary> SearchPathResolver<L>.libraryResolver()
= KotlinLibraryResolverImpl<L>(this)
class KotlinLibraryResolverImpl<L: KotlinLibrary>(
override val searchPathResolver: SearchPathResolver<L>
): KotlinLibraryResolver<L>, WithLogger by searchPathResolver {
override fun resolveWithDependencies(
unresolvedLibraries: List<UnresolvedLibrary>,
noStdLib: Boolean,
noDefaultLibs: Boolean,
noEndorsedLibs: Boolean
) = findLibraries(unresolvedLibraries, noStdLib, noDefaultLibs, noEndorsedLibs)
.leaveDistinct()
.resolveDependencies()
/**
* Returns the list of libraries based on [libraryNames], [noStdLib], [noDefaultLibs] and [noEndorsedLibs] criteria.
*
* This method does not return any libraries that might be available via transitive dependencies
* from the original library set (root set).
*/
private fun findLibraries(
unresolvedLibraries: List<UnresolvedLibrary>,
noStdLib: Boolean,
noDefaultLibs: Boolean,
noEndorsedLibs: Boolean
): List<KotlinLibrary> {
val userProvidedLibraries = unresolvedLibraries.asSequence()
.map { searchPathResolver.resolve(it) }
.toList()
val defaultLibraries = searchPathResolver.defaultLinks(noStdLib, noDefaultLibs, noEndorsedLibs)
// Make sure the user provided ones appear first, so that
// they have precedence over defaults when duplicates are eliminated.
return userProvidedLibraries + defaultLibraries
}
/**
* Leaves only distinct libraries (by absolute path), warns on duplicated paths.
*/
private fun List<KotlinLibrary>.leaveDistinct() =
this.groupBy { it.libraryFile.absolutePath }.let { groupedByAbsolutePath ->
warnOnLibraryDuplicates(groupedByAbsolutePath.filter { it.value.size > 1 }.keys)
groupedByAbsolutePath.map { it.value.first() }
}
private fun warnOnLibraryDuplicates(duplicatedPaths: Iterable<String>) {
duplicatedPaths.forEach { logger.warning("library included more than once: $it") }
}
/**
* Given the list of root libraries does the following:
*
* 1. Evaluates other libraries that are available via transitive dependencies.
* 2. Wraps each [KotlinLibrary] into a [KotlinResolvedLibrary] with information about dependencies on other libraries.
* 3. Creates resulting [KotlinLibraryResolveResult] object.
*/
private fun List<KotlinLibrary>.resolveDependencies(): KotlinLibraryResolveResult {
val rootLibraries = this.map { KotlinResolvedLibraryImpl(it) }
// As far as the list of root libraries is known from the very beginning, the result can be
// constructed from the very beginning as well.
val result = KotlinLibraryResolverResultImpl(rootLibraries)
val cache = mutableMapOf<File, KotlinResolvedLibrary>()
cache.putAll(rootLibraries.map { it.library.libraryFile.absoluteFile to it })
var newDependencies = rootLibraries
do {
newDependencies = newDependencies.map { library: KotlinResolvedLibraryImpl ->
library.library.unresolvedDependencies.asSequence()
.map { KotlinResolvedLibraryImpl(searchPathResolver.resolve(it)) }
.map { resolved ->
val absoluteFile = resolved.library.libraryFile.absoluteFile
if (absoluteFile in cache) {
library.addDependency(cache[absoluteFile]!!)
null
} else {
cache.put(absoluteFile, resolved)
library.addDependency(resolved)
resolved
}
}.filterNotNull()
.toList()
}.flatten()
} while (newDependencies.isNotEmpty())
return result
}
}
class KotlinLibraryResolverResultImpl(
private val roots: List<KotlinResolvedLibrary>
): KotlinLibraryResolveResult {
private val all: List<KotlinResolvedLibrary> by lazy {
val result = mutableSetOf<KotlinResolvedLibrary>().also { it.addAll(roots) }
var newDependencies = result.toList()
do {
newDependencies = newDependencies
.map { it -> it.resolvedDependencies }.flatten()
.filter { it !in result }
result.addAll(newDependencies)
} while (newDependencies.isNotEmpty())
result.toList()
}
override fun filterRoots(predicate: (KotlinResolvedLibrary) -> Boolean) =
KotlinLibraryResolverResultImpl(roots.filter(predicate))
override fun getFullList(order: LibraryOrder?) = (order?.invoke(all) ?: all).asPlain()
override fun forEach(action: (KotlinLibrary, PackageAccessHandler) -> Unit) {
all.forEach { action(it.library, it) }
}
private fun List<KotlinResolvedLibrary>.asPlain() = map { it.library }
override fun toString() = "roots=$roots, all=$all"
}
@@ -0,0 +1,38 @@
package org.jetbrains.kotlin.library.resolver.impl
import org.jetbrains.kotlin.library.KotlinLibrary
import org.jetbrains.kotlin.library.metadata.parseModuleHeader
import org.jetbrains.kotlin.library.metadata.parsePackageFragment
import org.jetbrains.kotlin.library.resolver.KotlinResolvedLibrary
import org.jetbrains.kotlin.metadata.ProtoBuf
class KotlinResolvedLibraryImpl(override val library: KotlinLibrary): KotlinResolvedLibrary {
private val _resolvedDependencies = mutableListOf<KotlinResolvedLibrary>()
private val _emptyPackages by lazy { parseModuleHeader(library.moduleHeaderData).emptyPackageList }
override val resolvedDependencies: List<KotlinResolvedLibrary>
get() = _resolvedDependencies
internal fun addDependency(resolvedLibrary: KotlinResolvedLibrary) = _resolvedDependencies.add(resolvedLibrary)
override var isNeededForLink: Boolean = false
private set
override val isDefault: Boolean
get() = library.isDefault
override fun loadPackageFragment(
library: KotlinLibrary,
packageFqName: String,
partName: String
): ProtoBuf.PackageFragment {
if (!isNeededForLink // fast path
&& !_emptyPackages.contains(packageFqName)) {
isNeededForLink = true
}
return parsePackageFragment(library.packageMetadata(packageFqName, partName))
}
override fun toString() = "library=$library, dependsOn=${_resolvedDependencies.joinToString { it.library.toString() }}"
}
@@ -11,6 +11,9 @@ const val KLIB_PROPERTY_LIBRARY_VERSION = "library_version"
const val KLIB_PROPERTY_UNIQUE_NAME = "unique_name" const val KLIB_PROPERTY_UNIQUE_NAME = "unique_name"
const val KLIB_PROPERTY_DEPENDS = "depends" const val KLIB_PROPERTY_DEPENDS = "depends"
const val KLIB_PROPERTY_PACKAGE = "package" const val KLIB_PROPERTY_PACKAGE = "package"
const val KLIB_PROPERTY_INTEROP = "interop"
const val KLIB_PROPERTY_EXPORT_FORWARD_DECLARATIONS = "exportForwardDeclarations"
/** /**
* Abstractions for getting access to the information stored inside of Kotlin/Native library. * Abstractions for getting access to the information stored inside of Kotlin/Native library.
*/ */
@@ -51,3 +54,17 @@ val BaseKotlinLibrary.unresolvedDependencies: List<UnresolvedLibrary>
} }
interface KotlinLibrary : BaseKotlinLibrary, MetadataLibrary, IrLibrary interface KotlinLibrary : BaseKotlinLibrary, MetadataLibrary, IrLibrary
// TODO: should we move the below ones to Native?
val KotlinLibrary.isInterop
get() = manifestProperties.getProperty(KLIB_PROPERTY_INTEROP) == "true"
val KotlinLibrary.packageFqName: String?
get() = manifestProperties.getProperty(org.jetbrains.kotlin.library.KLIB_PROPERTY_PACKAGE)
val KotlinLibrary.exportForwardDeclarations
get() = manifestProperties.propertyList(KLIB_PROPERTY_EXPORT_FORWARD_DECLARATIONS, escapeInQuotes = true)
.asSequence()
.map { it.trim() }
.filter { it.isNotEmpty() }
.toList()
@@ -36,4 +36,4 @@ val List<String>.toUnresolvedLibraries
.let { if (it.isEmpty()) null else it } .let { if (it.isEmpty()) null else it }
val name = it.substringBeforeLast('@') val name = it.substringBeforeLast('@')
UnresolvedLibrary(name, version) UnresolvedLibrary(name, version)
} }
@@ -0,0 +1,160 @@
package org.jetbrains.kotlin.library
import org.jetbrains.kotlin.konan.KonanVersion
import org.jetbrains.kotlin.konan.file.File
import org.jetbrains.kotlin.library.impl.createKotlinLibrary
import org.jetbrains.kotlin.util.*
const val KOTLIN_STDLIB_NAME = "stdlib"
interface SearchPathResolver<out L: KotlinLibrary> : WithLogger {
val searchRoots: List<File>
fun resolutionSequence(givenPath: String): Sequence<File>
fun resolve(unresolved: UnresolvedLibrary, isDefaultLink: Boolean = false): L
fun resolve(givenPath: String): L
fun defaultLinks(noStdLib: Boolean, noDefaultLibs: Boolean, noEndorsedLibs: Boolean): List<L>
}
interface SearchPathResolverWithAttributes<out L: KotlinLibrary>: SearchPathResolver<L> {
val knownAbiVersions: List<KotlinAbiVersion>?
val knownCompilerVersions: List<KonanVersion>?
}
fun resolverByName(
repositories: List<String>,
directLibs: List<String> = emptyList(),
distributionKlib: String? = null,
localKotlinDir: String? = null,
skipCurrentDir: Boolean = false,
logger: Logger = DummyLogger
): SearchPathResolver<KotlinLibrary> = KotlinLibrarySearchPathResolver(repositories, directLibs, distributionKlib, localKotlinDir, skipCurrentDir, logger)
open class KotlinLibrarySearchPathResolver<out L: KotlinLibrary>(
repositories: List<String>,
directLibs: List<String>,
val distributionKlib: String?,
val localKotlinDir: String?,
val skipCurrentDir: Boolean,
override val logger: Logger = DummyLogger
) : SearchPathResolver<L> {
val localHead: File?
get() = localKotlinDir?.File()?.klib
val distHead: File?
get() = distributionKlib?.File()?.child("common")
open val distPlatformHead: File? = null
val currentDirHead: File?
get() = if (!skipCurrentDir) File.userDir else null
private val repoRoots: List<File> by lazy { repositories.map { File(it) } }
private val directLibraries: List<KotlinLibrary> by lazy {
directLibs.mapNotNull { found(File(it)) }.map { createKotlinLibrary(it) }
}
// This is the place where we specify the order of library search.
override val searchRoots: List<File> by lazy {
(listOf(currentDirHead) + repoRoots + listOf(localHead, distHead, distPlatformHead)).filterNotNull()
}
private fun found(candidate: File): File? {
fun check(file: File): Boolean =
file.exists && (file.isFile || File(file, "manifest").exists)
val noSuffix = File(candidate.path.removeSuffixIfPresent(KLIB_FILE_EXTENSION_WITH_DOT))
val withSuffix = File(candidate.path.suffixIfNot(KLIB_FILE_EXTENSION_WITH_DOT))
return when {
check(withSuffix) -> withSuffix
check(noSuffix) -> noSuffix
else -> null
}
}
override fun resolutionSequence(givenPath: String): Sequence<File> {
val given = File(givenPath)
val sequence = if (given.isAbsolute) {
sequenceOf(found(given))
} else {
// Search among user-provided libraries by unique name.
// It's a workaround for maven publication. When a library is published without Gradle metadata,
// it has a complex file name (e.g. foo-macos_x64-1.0.klib). But a dependency on this lib in manifests
// of other libs uses its unique name written in the manifest (i.e just 'foo'). So we cannot resolve this
// library by its filename. But we have this library's file (we've downloaded it using maven dependency
// resolution) so we can pass it to the compiler directly. This code takes this into account and looks for
// a library dependencies also in libs passed to the compiler as files (passed to the resolver as the
// 'directLibraries' property).
val directLibs = directLibraries.asSequence().filter {
it.uniqueName == givenPath
}.map {
it.libraryFile
}
// Search among libraries in repositoreis by library filename.
val repoLibs = searchRoots.asSequence().map {
found(File(it, givenPath))
}
directLibs + repoLibs
}
return sequence.filterNotNull()
}
override fun resolve(unresolved: UnresolvedLibrary, isDefaultLink: Boolean): L {
val givenPath = unresolved.path
return resolutionSequence(givenPath).firstOrNull() ?. let {
createKotlinLibrary(it, isDefaultLink) as L
} ?: run {
logger.fatal("Could not find \"$givenPath\" in ${searchRoots.map { it.absolutePath }}.")
}
}
override fun resolve(givenPath: String) = resolve(UnresolvedLibrary(givenPath, null), false)
private val File.klib
get() = File(this, "klib")
// The libraries from the default root are linked automatically.
val defaultRoots: List<File>
get() = listOfNotNull(distHead, distPlatformHead).filter { it.exists }
private fun getDefaultLibrariesFromDir(directory: File) =
if (directory.exists) {
directory.listFiles
.asSequence()
.filterNot { it.name.startsWith('.') }
.filterNot { it.name.removeSuffixIfPresent(KLIB_FILE_EXTENSION_WITH_DOT) == KOTLIN_STDLIB_NAME }
.map { UnresolvedLibrary(it.absolutePath, null) }
.map { resolve(it, isDefaultLink = true) }
} else emptySequence()
override fun defaultLinks(noStdLib: Boolean, noDefaultLibs: Boolean, noEndorsedLibs: Boolean): List<L> {
val result = mutableListOf<L>()
if (!noStdLib) {
result.add(resolve(UnresolvedLibrary(KOTLIN_STDLIB_NAME, null), true))
}
// Endorsed libraries in distHead.
if (!noEndorsedLibs) {
distHead?.let {
result.addAll(getDefaultLibrariesFromDir(it))
}
}
// Platform libraries resolve.
if (!noDefaultLibs) {
distPlatformHead?.let {
result.addAll(getDefaultLibrariesFromDir(it))
}
}
return result
}
}
fun KonanVersion.compatible(other: KonanVersion) =
this.major == other.major
&& this.minor == other.minor
&& this.maintenance == other.maintenance
@@ -22,7 +22,7 @@ import org.jetbrains.kotlin.konan.properties.Properties
import org.jetbrains.kotlin.konan.properties.loadProperties import org.jetbrains.kotlin.konan.properties.loadProperties
open class BaseKotlinLibraryImpl( open class BaseKotlinLibraryImpl(
private val access: BaseLibraryAccess<KotlinLibraryLayout>, val access: BaseLibraryAccess<KotlinLibraryLayout>,
override val isDefault: Boolean override val isDefault: Boolean
) : BaseKotlinLibrary { ) : BaseKotlinLibrary {
override val libraryFile get() = access.klib override val libraryFile get() = access.klib
@@ -40,7 +40,7 @@ open class BaseKotlinLibraryImpl(
} }
open class MetadataLibraryImpl( open class MetadataLibraryImpl(
private val access: MetadataLibraryAccess<MetadataKotlinLibraryLayout> val access: MetadataLibraryAccess<MetadataKotlinLibraryLayout>
) : MetadataLibrary { ) : MetadataLibrary {
override val moduleHeaderData: ByteArray by lazy { override val moduleHeaderData: ByteArray by lazy {
@@ -72,7 +72,7 @@ open class MetadataLibraryImpl(
} }
abstract class IrLibraryImpl( abstract class IrLibraryImpl(
protected val access: IrLibraryAccess<IrKotlinLibraryLayout> val access: IrLibraryAccess<IrKotlinLibraryLayout>
) : IrLibrary { ) : IrLibrary {
override val dataFlowGraph by lazy { override val dataFlowGraph by lazy {
access.inPlace { it: IrKotlinLibraryLayout -> access.inPlace { it: IrKotlinLibraryLayout ->
@@ -211,9 +211,9 @@ class IrPerFileLibraryImpl(_access: IrLibraryAccess<IrKotlinLibraryLayout>) : Ir
} }
open class KotlinLibraryImpl( open class KotlinLibraryImpl(
base: BaseKotlinLibraryImpl, val base: BaseKotlinLibraryImpl,
metadata: MetadataLibraryImpl, val metadata: MetadataLibraryImpl,
ir: IrLibraryImpl val ir: IrLibraryImpl
) : KotlinLibrary, ) : KotlinLibrary,
BaseKotlinLibrary by base, BaseKotlinLibrary by base,
MetadataLibrary by metadata, MetadataLibrary by metadata,
@@ -4,7 +4,7 @@ import org.jetbrains.kotlin.konan.file.File
import org.jetbrains.kotlin.konan.file.file import org.jetbrains.kotlin.konan.file.file
import org.jetbrains.kotlin.konan.file.withZipFileSystem import org.jetbrains.kotlin.konan.file.withZipFileSystem
import org.jetbrains.kotlin.library.* import org.jetbrains.kotlin.library.*
import org.jetbrains.kotlin.konan.util.removeSuffixIfPresent import org.jetbrains.kotlin.util.removeSuffixIfPresent
import java.nio.file.FileSystem import java.nio.file.FileSystem
open class KotlinLibraryLayoutImpl(val klib: File) : KotlinLibraryLayout { open class KotlinLibraryLayoutImpl(val klib: File) : KotlinLibraryLayout {
@@ -55,15 +55,10 @@ val PROTO_PATHS: List<ProtoPath> = listOf(
ProtoPath("core/metadata/src/builtins.proto"), ProtoPath("core/metadata/src/builtins.proto"),
ProtoPath("js/js.serializer/src/js.proto"), ProtoPath("js/js.serializer/src/js.proto"),
ProtoPath("js/js.serializer/src/js-ast.proto", false), ProtoPath("js/js.serializer/src/js-ast.proto", false),
ProtoPath("konan/library-reader/src/konan.proto"),
ProtoPath("core/metadata.jvm/src/jvm_metadata.proto"), ProtoPath("core/metadata.jvm/src/jvm_metadata.proto"),
ProtoPath("core/metadata.jvm/src/jvm_module.proto"), ProtoPath("core/metadata.jvm/src/jvm_module.proto"),
ProtoPath("build-common/src/java_descriptors.proto"), ProtoPath("build-common/src/java_descriptors.proto"),
ProtoPath("compiler/util-klib-metadata/src/KlibMetadataProtoBuf.proto", false),
// TODO drop this scheme, 'compiler/ir/serialization.js/src/js.proto' is the actual one
ProtoPath("compiler/ir/backend.js/src/js.proto", false),
ProtoPath("compiler/ir/serialization.js/src/js.proto", false),
ProtoPath("compiler/ir/serialization.common/src/KotlinIr.proto", false) ProtoPath("compiler/ir/serialization.common/src/KotlinIr.proto", false)
) )
@@ -35,7 +35,7 @@ import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.gradle.* import org.jetbrains.kotlin.gradle.*
import org.jetbrains.kotlin.idea.configuration.GradlePropertiesFileFacade.Companion.KOTLIN_NOT_IMPORTED_COMMON_SOURCE_SETS_SETTING import org.jetbrains.kotlin.idea.configuration.GradlePropertiesFileFacade.Companion.KOTLIN_NOT_IMPORTED_COMMON_SOURCE_SETS_SETTING
import org.jetbrains.kotlin.idea.platform.IdePlatformKindTooling import org.jetbrains.kotlin.idea.platform.IdePlatformKindTooling
import org.jetbrains.kotlin.konan.util.removeSuffixIfPresent import org.jetbrains.kotlin.util.removeSuffixIfPresent
import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult
import org.jetbrains.plugins.gradle.model.* import org.jetbrains.plugins.gradle.model.*
import org.jetbrains.plugins.gradle.model.data.BuildScriptClasspathData import org.jetbrains.plugins.gradle.model.data.BuildScriptClasspathData
@@ -14,28 +14,18 @@ import com.intellij.psi.SingleRootFileViewProvider
import com.intellij.psi.impl.PsiFileFactoryImpl import com.intellij.psi.impl.PsiFileFactoryImpl
import com.intellij.psi.stubs.PsiFileStub import com.intellij.psi.stubs.PsiFileStub
import com.intellij.testFramework.LightVirtualFile import com.intellij.testFramework.LightVirtualFile
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.descriptors.PackageFragmentProvider
import org.jetbrains.kotlin.ide.konan.decompiler.KotlinNativeLoadingMetadataCache import org.jetbrains.kotlin.ide.konan.decompiler.KotlinNativeLoadingMetadataCache
import org.jetbrains.kotlin.idea.KotlinFileType import org.jetbrains.kotlin.idea.KotlinFileType
import org.jetbrains.kotlin.idea.KotlinLanguage import org.jetbrains.kotlin.idea.KotlinLanguage
import org.jetbrains.kotlin.idea.caches.project.LibraryInfo
import org.jetbrains.kotlin.idea.decompiler.textBuilder.LoggingErrorReporter import org.jetbrains.kotlin.idea.decompiler.textBuilder.LoggingErrorReporter
import org.jetbrains.kotlin.konan.file.File import org.jetbrains.kotlin.library.KotlinLibrary
import org.jetbrains.kotlin.konan.util.KonanFactories.DefaultPackageFragmentsFactory import org.jetbrains.kotlin.library.impl.BaseKotlinLibraryImpl
import org.jetbrains.kotlin.konan.library.KonanLibrary import org.jetbrains.kotlin.library.impl.MetadataLibraryImpl
import org.jetbrains.kotlin.konan.library.KonanLibraryLayout import org.jetbrains.kotlin.library.metadata.KlibMetadataProtoBuf
import org.jetbrains.kotlin.konan.library.KonanLibrarySource.KonanLibraryDir import org.jetbrains.kotlin.library.metadata.PackageAccessHandler
import org.jetbrains.kotlin.konan.library.KonanLibrarySource.KonanLibraryFile import org.jetbrains.kotlin.metadata.ProtoBuf
import org.jetbrains.kotlin.konan.library.MetadataReader
import org.jetbrains.kotlin.konan.library.createKonanLibrary
import org.jetbrains.kotlin.metadata.konan.KonanProtoBuf
import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes
import org.jetbrains.kotlin.resolve.CompilerDeserializationConfiguration import org.jetbrains.kotlin.konan.file.File as KFile
import org.jetbrains.kotlin.storage.StorageManager
const val KOTLIN_NATIVE_CURRENT_ABI_VERSION = 1
fun createFileStub(project: Project, text: String): PsiFileStub<*> { fun createFileStub(project: Project, text: String): PsiFileStub<*> {
val virtualFile = LightVirtualFile("dummy.kt", KotlinFileType.INSTANCE, text) val virtualFile = LightVirtualFile("dummy.kt", KotlinFileType.INSTANCE, text)
@@ -49,62 +39,48 @@ fun createFileStub(project: Project, text: String): PsiFileStub<*> {
fun createLoggingErrorReporter(log: Logger) = LoggingErrorReporter(log) fun createLoggingErrorReporter(log: Logger) = LoggingErrorReporter(log)
fun KonanLibrary.createPackageFragmentProvider( internal object CachingIdeKonanLibraryMetadataLoader : PackageAccessHandler {
storageManager: StorageManager, override fun loadModuleHeader(
languageVersionSettings: LanguageVersionSettings, library: KotlinLibrary
moduleDescriptor: ModuleDescriptor ): KlibMetadataProtoBuf.Header {
): PackageFragmentProvider { val virtualFile = getVirtualFile(library, library.moduleHeaderFile)
return cache.getCachedModuleHeader(virtualFile)
val library = this
val libraryProto = library.moduleHeaderData
//TODO: Is it required somehow?
//val moduleName = Name.special(libraryProto.moduleName)
//val moduleOrigin = DeserializedKonanModuleOrigin(library)
val deserializationConfiguration = CompilerDeserializationConfiguration(languageVersionSettings)
return DefaultPackageFragmentsFactory.createPackageFragmentProvider(
library,
null,
libraryProto.packageFragmentNameList,
storageManager,
moduleDescriptor,
deserializationConfiguration
)
}
internal object CachingIdeMetadataReaderImpl : MetadataReader {
override fun loadSerializedModule(libraryLayout: KonanLibraryLayout): KonanProtoBuf.LinkDataLibrary =
cache.getCachedModuleHeader(libraryLayout.getVirtualFile(libraryLayout.moduleHeaderFile))
override fun loadSerializedPackageFragment(
libraryLayout: KonanLibraryLayout,
packageFqName: String,
partName: String
): KonanProtoBuf.LinkDataPackageFragment =
cache.getCachedPackageFragment(libraryLayout.getVirtualFile(libraryLayout.packageFragmentFile(packageFqName, partName)))
private fun KonanLibraryLayout.getVirtualFile(file: File): VirtualFile {
val source = this.source
return when (source) {
is KonanLibraryFile -> asJarFileSystemFile(source.klibFile, file)
is KonanLibraryDir -> asLocalFile(file)
}
} }
private fun asJarFileSystemFile(jarFile: File, localFile: File): VirtualFile { override fun loadPackageFragment(
library: KotlinLibrary,
packageFqName: String,
partName: String
): ProtoBuf.PackageFragment {
val virtualFile = getVirtualFile(library, library.packageFragmentFile(packageFqName, partName))
return cache.getCachedPackageFragment(virtualFile)
}
private fun getVirtualFile(library: KotlinLibrary, file: KFile): VirtualFile =
if (library.isZipped) asJarFileSystemFile(library.libraryFile, file) else asLocalFile(file)
private fun asJarFileSystemFile(jarFile: KFile, localFile: KFile): VirtualFile {
val fullPath = jarFile.absolutePath + "!" + localFile.absolutePath val fullPath = jarFile.absolutePath + "!" + localFile.absolutePath
return StandardFileSystems.jar().findFileByPath(fullPath) ?: error("File not found: $fullPath") return StandardFileSystems.jar().findFileByPath(fullPath) ?: error("File not found: $fullPath")
} }
private fun asLocalFile(localFile: File): VirtualFile { private fun asLocalFile(localFile: KFile): VirtualFile {
val fullPath = localFile.absolutePath val fullPath = localFile.absolutePath
return StandardFileSystems.local().findFileByPath(fullPath) ?: error("File not found: $fullPath") return StandardFileSystems.local().findFileByPath(fullPath) ?: error("File not found: $fullPath")
} }
private val cache private val cache
get() = KotlinNativeLoadingMetadataCache.getInstance() get() = KotlinNativeLoadingMetadataCache.getInstance()
private val KotlinLibrary.moduleHeaderFile get() =
(this as MetadataLibraryImpl).access.layout.moduleHeaderFile
private fun KotlinLibrary.packageFragmentFile(packageFqName: String, partName: String) =
(this as MetadataLibraryImpl).access.layout.packageFragmentFile(packageFqName, partName)
private val KotlinLibrary.isZipped get() =
(this as BaseKotlinLibraryImpl).access.layout.isZipped
} }
@@ -24,7 +24,8 @@ 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.PackageFragmentProvider
import org.jetbrains.kotlin.descriptors.impl.CompositePackageFragmentProvider import org.jetbrains.kotlin.descriptors.impl.CompositePackageFragmentProvider
import org.jetbrains.kotlin.descriptors.konan.DeserializedKonanModuleOrigin import org.jetbrains.kotlin.descriptors.konan.DeserializedKlibModuleOrigin
import org.jetbrains.kotlin.descriptors.konan.KlibModuleOrigin
import org.jetbrains.kotlin.ide.konan.analyzer.NativeResolverForModuleFactory import org.jetbrains.kotlin.ide.konan.analyzer.NativeResolverForModuleFactory
import org.jetbrains.kotlin.idea.caches.project.LibraryInfo import org.jetbrains.kotlin.idea.caches.project.LibraryInfo
import org.jetbrains.kotlin.idea.caches.project.lazyClosure import org.jetbrains.kotlin.idea.caches.project.lazyClosure
@@ -32,15 +33,47 @@ import org.jetbrains.kotlin.idea.caches.resolve.BuiltInsCacheKey
import org.jetbrains.kotlin.idea.compiler.IDELanguageSettingsProvider import org.jetbrains.kotlin.idea.compiler.IDELanguageSettingsProvider
import org.jetbrains.kotlin.konan.file.File import org.jetbrains.kotlin.konan.file.File
import org.jetbrains.kotlin.konan.library.* import org.jetbrains.kotlin.konan.library.*
import org.jetbrains.kotlin.konan.util.KonanFactories import org.jetbrains.kotlin.library.KotlinLibrary
import org.jetbrains.kotlin.library.impl.createKotlinLibrary
import org.jetbrains.kotlin.library.isInterop
import org.jetbrains.kotlin.library.metadata.parseModuleHeader
import org.jetbrains.kotlin.platform.TargetPlatform import org.jetbrains.kotlin.platform.TargetPlatform
import org.jetbrains.kotlin.platform.impl.NativeIdePlatformKind import org.jetbrains.kotlin.platform.impl.NativeIdePlatformKind
import org.jetbrains.kotlin.platform.konan.KonanPlatforms import org.jetbrains.kotlin.platform.konan.KonanPlatforms
import org.jetbrains.kotlin.resolve.CompilerDeserializationConfiguration import org.jetbrains.kotlin.resolve.CompilerDeserializationConfiguration
import org.jetbrains.kotlin.resolve.ImplicitIntegerCoercion import org.jetbrains.kotlin.resolve.ImplicitIntegerCoercion
import org.jetbrains.kotlin.resolve.TargetEnvironment import org.jetbrains.kotlin.resolve.TargetEnvironment
import org.jetbrains.kotlin.serialization.deserialization.DeserializationConfiguration
import org.jetbrains.kotlin.serialization.konan.impl.KlibMetadataModuleDescriptorFactoryImpl
import org.jetbrains.kotlin.storage.StorageManager import org.jetbrains.kotlin.storage.StorageManager
fun KotlinLibrary.createPackageFragmentProvider(
storageManager: StorageManager,
languageVersionSettings: LanguageVersionSettings,
moduleDescriptor: ModuleDescriptor
): PackageFragmentProvider {
val library = this
val libraryProto = parseModuleHeader(library.moduleHeaderData)
//TODO: Is it required somehow?
//val moduleName = Name.special(libraryProto.moduleName)
//val moduleOrigin = DeserializedKonanModuleOrigin(library)
val deserializationConfiguration = CompilerDeserializationConfiguration(languageVersionSettings)
return KonanFactories.DefaultDeserializedDescriptorFactory.createPackageFragmentProvider(
library,
null,
libraryProto.packageFragmentNameList,
storageManager,
moduleDescriptor,
deserializationConfiguration,
null
)
}
class NativePlatformKindResolution : IdePlatformKindResolution { class NativePlatformKindResolution : IdePlatformKindResolution {
override fun createLibraryInfo(project: Project, library: Library): List<LibraryInfo> { override fun createLibraryInfo(project: Project, library: Library): List<LibraryInfo> {
@@ -116,32 +149,34 @@ private fun createKotlinNativeBuiltIns(moduleInfo: ModuleInfo, projectContext: P
val builtInsModule = KonanFactories.DefaultDescriptorFactory.createDescriptorAndNewBuiltIns( val builtInsModule = KonanFactories.DefaultDescriptorFactory.createDescriptorAndNewBuiltIns(
KotlinBuiltIns.BUILTINS_MODULE_NAME, KotlinBuiltIns.BUILTINS_MODULE_NAME,
storageManager, storageManager,
DeserializedKonanModuleOrigin(konanLibrary), DeserializedKlibModuleOrigin(konanLibrary),
stdlibInfo.capabilities stdlibInfo.capabilities
) )
val languageSettings = IDELanguageSettingsProvider.getLanguageVersionSettings(stdlibInfo, project, isReleaseCoroutines = false) val languageSettings = IDELanguageSettingsProvider.getLanguageVersionSettings(stdlibInfo, project, isReleaseCoroutines = false)
val deserializationConfiguration = CompilerDeserializationConfiguration(languageSettings) val deserializationConfiguration = CompilerDeserializationConfiguration(languageSettings)
val libraryProto = konanLibrary.moduleHeaderData val libraryProto = parseModuleHeader(konanLibrary.moduleHeaderData)
val stdlibFragmentProvider = KonanFactories.DefaultPackageFragmentsFactory.createPackageFragmentProvider( val stdlibFragmentProvider = KonanFactories.DefaultDeserializedDescriptorFactory.createPackageFragmentProvider(
konanLibrary, konanLibrary,
null, CachingIdeKonanLibraryMetadataLoader,
libraryProto.packageFragmentNameList, libraryProto.packageFragmentNameList,
storageManager, storageManager,
builtInsModule, builtInsModule,
deserializationConfiguration deserializationConfiguration,
null
) )
builtInsModule.initialize( builtInsModule.initialize(
CompositePackageFragmentProvider( CompositePackageFragmentProvider(
listOf( listOf(
stdlibFragmentProvider, stdlibFragmentProvider,
KonanFactories.DefaultPackageFragmentsFactory.createForwardDeclarationHackPackagePartProvider( (KonanFactories.DefaultDeserializedDescriptorFactory as KlibMetadataModuleDescriptorFactoryImpl)
storageManager, .createForwardDeclarationHackPackagePartProvider(
builtInsModule storageManager,
) builtInsModule
)
) )
) )
) )
@@ -158,11 +193,7 @@ private fun ModuleInfo.findNativeStdlib(project: Project): NativeLibraryInfo? =
class NativeLibraryInfo(project: Project, library: Library, root: File) : LibraryInfo(project, library) { class NativeLibraryInfo(project: Project, library: Library, root: File) : LibraryInfo(project, library) {
private val nativeLibrary = createKonanLibrary( private val nativeLibrary = createKotlinLibrary(root)
root,
KOTLIN_NATIVE_CURRENT_ABI_VERSION,
metadataReader = CachingIdeMetadataReaderImpl
)
private val roots = listOf(root.absolutePath) private val roots = listOf(root.absolutePath)
@@ -173,8 +204,8 @@ class NativeLibraryInfo(project: Project, library: Library, root: File) : Librar
override val capabilities: Map<ModuleDescriptor.Capability<*>, Any?> override val capabilities: Map<ModuleDescriptor.Capability<*>, Any?>
get() = super.capabilities + get() = super.capabilities +
mapOf( mapOf(
ImplicitIntegerCoercion.MODULE_CAPABILITY to nativeLibrary.isInterop, KlibModuleOrigin.CAPABILITY to this,
NATIVE_LIBRARY_CAPABILITY to nativeLibrary ImplicitIntegerCoercion.MODULE_CAPABILITY to nativeLibrary.isInterop
) )
override val platform: TargetPlatform override val platform: TargetPlatform
@@ -183,6 +214,6 @@ class NativeLibraryInfo(project: Project, library: Library, root: File) : Librar
override fun toString() = "Native" + super.toString() override fun toString() = "Native" + super.toString()
companion object { companion object {
val NATIVE_LIBRARY_CAPABILITY = ModuleDescriptor.Capability<KonanLibrary>("KonanLibrary") val NATIVE_LIBRARY_CAPABILITY = ModuleDescriptor.Capability<KotlinLibrary>("KotlinLibrary")
} }
} }
@@ -11,9 +11,10 @@ import com.intellij.openapi.vfs.VirtualFile
import com.intellij.util.containers.ContainerUtil.createConcurrentWeakValueMap import com.intellij.util.containers.ContainerUtil.createConcurrentWeakValueMap
import org.jetbrains.kotlin.konan.library.KLIB_METADATA_FILE_EXTENSION import org.jetbrains.kotlin.konan.library.KLIB_METADATA_FILE_EXTENSION
import org.jetbrains.kotlin.konan.library.KLIB_MODULE_METADATA_FILE_NAME import org.jetbrains.kotlin.konan.library.KLIB_MODULE_METADATA_FILE_NAME
import org.jetbrains.kotlin.metadata.konan.KonanProtoBuf import org.jetbrains.kotlin.library.metadata.KlibMetadataProtoBuf
import org.jetbrains.kotlin.serialization.konan.parseModuleHeader import org.jetbrains.kotlin.library.metadata.parseModuleHeader
import org.jetbrains.kotlin.serialization.konan.parsePackageFragment import org.jetbrains.kotlin.library.metadata.parsePackageFragment
import org.jetbrains.kotlin.metadata.ProtoBuf
class KotlinNativeLoadingMetadataCache : BaseComponent { class KotlinNativeLoadingMetadataCache : BaseComponent {
@@ -32,15 +33,15 @@ class KotlinNativeLoadingMetadataCache : BaseComponent {
constructor(virtualFile: VirtualFile) : this(virtualFile.url, virtualFile.modificationStamp) constructor(virtualFile: VirtualFile) : this(virtualFile.url, virtualFile.modificationStamp)
} }
private val packageFragmentCache = createConcurrentWeakValueMap<CacheKey, KonanProtoBuf.LinkDataPackageFragment>() private val packageFragmentCache = createConcurrentWeakValueMap<CacheKey, ProtoBuf.PackageFragment>()
private val moduleHeaderCache = createConcurrentWeakValueMap<CacheKey, KonanProtoBuf.LinkDataLibrary>() private val moduleHeaderCache = createConcurrentWeakValueMap<CacheKey, KlibMetadataProtoBuf.Header>()
fun getCachedPackageFragment(virtualFile: VirtualFile): KonanProtoBuf.LinkDataPackageFragment = fun getCachedPackageFragment(virtualFile: VirtualFile): ProtoBuf.PackageFragment =
packageFragmentCache.computeIfAbsent(CacheKey(virtualFile.ensurePackageMetadataFile)) { packageFragmentCache.computeIfAbsent(CacheKey(virtualFile.ensurePackageMetadataFile)) {
virtualFile.createPackageFragmentCacheEntry virtualFile.createPackageFragmentCacheEntry
} }
fun getCachedModuleHeader(virtualFile: VirtualFile): KonanProtoBuf.LinkDataLibrary = fun getCachedModuleHeader(virtualFile: VirtualFile): KlibMetadataProtoBuf.Header =
moduleHeaderCache.computeIfAbsent(CacheKey(virtualFile.ensureModuleHeaderFile)) { moduleHeaderCache.computeIfAbsent(CacheKey(virtualFile.ensureModuleHeaderFile)) {
virtualFile.createModuleHeaderCacheEntry virtualFile.createModuleHeaderCacheEntry
} }
@@ -10,12 +10,12 @@ import com.intellij.openapi.fileTypes.FileTypeConsumer
import com.intellij.openapi.fileTypes.FileTypeFactory import com.intellij.openapi.fileTypes.FileTypeFactory
import com.intellij.openapi.vfs.VirtualFile import com.intellij.openapi.vfs.VirtualFile
import org.jetbrains.kotlin.konan.library.KLIB_METADATA_FILE_EXTENSION import org.jetbrains.kotlin.konan.library.KLIB_METADATA_FILE_EXTENSION
import org.jetbrains.kotlin.library.metadata.KlibMetadataSerializerProtocol
import org.jetbrains.kotlin.metadata.deserialization.BinaryVersion import org.jetbrains.kotlin.metadata.deserialization.BinaryVersion
import org.jetbrains.kotlin.serialization.konan.KonanSerializerProtocol
import org.jetbrains.kotlin.serialization.konan.NullFlexibleTypeDeserializer import org.jetbrains.kotlin.serialization.konan.NullFlexibleTypeDeserializer
class KotlinNativeMetadataDecompiler : KotlinNativeMetadataDecompilerBase<KotlinNativeMetadataVersion>( class KotlinNativeMetadataDecompiler : KotlinNativeMetadataDecompilerBase<KotlinNativeMetadataVersion>(
KotlinNativeMetaFileType, { KonanSerializerProtocol }, NullFlexibleTypeDeserializer, KotlinNativeMetaFileType, { KlibMetadataSerializerProtocol }, NullFlexibleTypeDeserializer,
{ KotlinNativeMetadataVersion.DEFAULT_INSTANCE }, { KotlinNativeMetadataVersion.DEFAULT_INSTANCE },
{ KotlinNativeMetadataVersion.INVALID_VERSION }, { KotlinNativeMetadataVersion.INVALID_VERSION },
KotlinNativeMetaFileType.STUB_VERSION KotlinNativeMetaFileType.STUB_VERSION
@@ -23,7 +23,7 @@ class KotlinNativeMetadataDecompiler : KotlinNativeMetadataDecompilerBase<Kotlin
override fun doReadFile(file: VirtualFile): FileWithMetadata? { override fun doReadFile(file: VirtualFile): FileWithMetadata? {
val proto = KotlinNativeLoadingMetadataCache.getInstance().getCachedPackageFragment(file) val proto = KotlinNativeLoadingMetadataCache.getInstance().getCachedPackageFragment(file)
return FileWithMetadata.Compatible(proto, KonanSerializerProtocol) //todo: check version compatibility return FileWithMetadata.Compatible(proto, KlibMetadataSerializerProtocol) //todo: check version compatibility
} }
} }
@@ -15,10 +15,10 @@ import org.jetbrains.kotlin.idea.decompiler.common.createIncompatibleAbiVersionD
import org.jetbrains.kotlin.idea.decompiler.textBuilder.DecompiledText import org.jetbrains.kotlin.idea.decompiler.textBuilder.DecompiledText
import org.jetbrains.kotlin.idea.decompiler.textBuilder.buildDecompiledText import org.jetbrains.kotlin.idea.decompiler.textBuilder.buildDecompiledText
import org.jetbrains.kotlin.idea.decompiler.textBuilder.defaultDecompilerRendererOptions import org.jetbrains.kotlin.idea.decompiler.textBuilder.defaultDecompilerRendererOptions
import org.jetbrains.kotlin.library.metadata.KlibMetadataProtoBuf
import org.jetbrains.kotlin.metadata.ProtoBuf import org.jetbrains.kotlin.metadata.ProtoBuf
import org.jetbrains.kotlin.metadata.deserialization.BinaryVersion import org.jetbrains.kotlin.metadata.deserialization.BinaryVersion
import org.jetbrains.kotlin.metadata.deserialization.NameResolverImpl import org.jetbrains.kotlin.metadata.deserialization.NameResolverImpl
import org.jetbrains.kotlin.metadata.konan.KonanProtoBuf
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.renderer.DescriptorRenderer import org.jetbrains.kotlin.renderer.DescriptorRenderer
import org.jetbrains.kotlin.serialization.SerializerExtensionProtocol import org.jetbrains.kotlin.serialization.SerializerExtensionProtocol
@@ -99,14 +99,14 @@ sealed class FileWithMetadata {
class Incompatible(val version: BinaryVersion) : FileWithMetadata() class Incompatible(val version: BinaryVersion) : FileWithMetadata()
open class Compatible( open class Compatible(
val proto: KonanProtoBuf.LinkDataPackageFragment, val proto: ProtoBuf.PackageFragment,
serializerProtocol: SerializerExtensionProtocol // TODO: Is it required? serializerProtocol: SerializerExtensionProtocol // TODO: Is it required?
) : FileWithMetadata() { ) : FileWithMetadata() {
val nameResolver = NameResolverImpl(proto.stringTable, proto.nameTable) val nameResolver = NameResolverImpl(proto.strings, proto.qualifiedNames)
val packageFqName = FqName(proto.fqName) val packageFqName = FqName(proto.getExtension(KlibMetadataProtoBuf.fqName))
open val classesToDecompile: List<ProtoBuf.Class> = open val classesToDecompile: List<ProtoBuf.Class> =
proto.classes.classesList.filter { proto -> proto.class_List.filter { proto ->
val classId = nameResolver.getClassId(proto.fqName) val classId = nameResolver.getClassId(proto.fqName)
!classId.isNestedClass && classId !in ClassDeserializer.BLACK_LIST !classId.isNestedClass && classId !in ClassDeserializer.BLACK_LIST
} }
@@ -15,8 +15,8 @@ import org.jetbrains.kotlin.ide.konan.createLoggingErrorReporter
import org.jetbrains.kotlin.idea.decompiler.textBuilder.DeserializerForDecompilerBase import org.jetbrains.kotlin.idea.decompiler.textBuilder.DeserializerForDecompilerBase
import org.jetbrains.kotlin.idea.decompiler.textBuilder.ResolveEverythingToKotlinAnyLocalClassifierResolver import org.jetbrains.kotlin.idea.decompiler.textBuilder.ResolveEverythingToKotlinAnyLocalClassifierResolver
import org.jetbrains.kotlin.incremental.components.LookupTracker import org.jetbrains.kotlin.incremental.components.LookupTracker
import org.jetbrains.kotlin.metadata.ProtoBuf
import org.jetbrains.kotlin.metadata.deserialization.NameResolver import org.jetbrains.kotlin.metadata.deserialization.NameResolver
import org.jetbrains.kotlin.metadata.konan.KonanProtoBuf
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.serialization.SerializerExtensionProtocol import org.jetbrains.kotlin.serialization.SerializerExtensionProtocol
import org.jetbrains.kotlin.serialization.deserialization.* import org.jetbrains.kotlin.serialization.deserialization.*
@@ -24,7 +24,7 @@ import org.jetbrains.kotlin.serialization.deserialization.descriptors.Deserializ
class KotlinNativeMetadataDeserializerForDecompiler( class KotlinNativeMetadataDeserializerForDecompiler(
packageFqName: FqName, packageFqName: FqName,
private val proto: KonanProtoBuf.LinkDataPackageFragment, private val proto: ProtoBuf.PackageFragment,
private val nameResolver: NameResolver, private val nameResolver: NameResolver,
serializerProtocol: SerializerExtensionProtocol, serializerProtocol: SerializerExtensionProtocol,
flexibleTypeDeserializer: FlexibleTypeDeserializer flexibleTypeDeserializer: FlexibleTypeDeserializer
@@ -6,20 +6,20 @@
package org.jetbrains.kotlin.ide.konan.decompiler package org.jetbrains.kotlin.ide.konan.decompiler
import org.jetbrains.kotlin.descriptors.SourceElement import org.jetbrains.kotlin.descriptors.SourceElement
import org.jetbrains.kotlin.metadata.ProtoBuf
import org.jetbrains.kotlin.metadata.deserialization.NameResolver import org.jetbrains.kotlin.metadata.deserialization.NameResolver
import org.jetbrains.kotlin.metadata.konan.KonanProtoBuf
import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.serialization.deserialization.ClassData import org.jetbrains.kotlin.serialization.deserialization.ClassData
import org.jetbrains.kotlin.serialization.deserialization.ClassDataFinder import org.jetbrains.kotlin.serialization.deserialization.ClassDataFinder
import org.jetbrains.kotlin.serialization.deserialization.getClassId import org.jetbrains.kotlin.serialization.deserialization.getClassId
class KotlinNativeProtoBasedClassDataFinder( class KotlinNativeProtoBasedClassDataFinder(
proto: KonanProtoBuf.LinkDataPackageFragment, proto: ProtoBuf.PackageFragment,
private val nameResolver: NameResolver, private val nameResolver: NameResolver,
private val classSource: (ClassId) -> SourceElement = { SourceElement.NO_SOURCE } private val classSource: (ClassId) -> SourceElement = { SourceElement.NO_SOURCE }
) : ClassDataFinder { ) : ClassDataFinder {
private val classIdToProto = private val classIdToProto =
proto.classes.classesList.associateBy { klass -> proto.class_List.associateBy { klass ->
nameResolver.getClassId(klass.fqName) nameResolver.getClassId(klass.fqName)
} }
@@ -9,6 +9,7 @@ import com.intellij.util.indexing.FileBasedIndex
import org.jetbrains.kotlin.ide.konan.decompiler.KotlinNativeLoadingMetadataCache import org.jetbrains.kotlin.ide.konan.decompiler.KotlinNativeLoadingMetadataCache
import org.jetbrains.kotlin.ide.konan.decompiler.KotlinNativeMetaFileType import org.jetbrains.kotlin.ide.konan.decompiler.KotlinNativeMetaFileType
import org.jetbrains.kotlin.idea.vfilefinder.KotlinFileIndexBase import org.jetbrains.kotlin.idea.vfilefinder.KotlinFileIndexBase
import org.jetbrains.kotlin.library.metadata.KlibMetadataProtoBuf
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
object KotlinNativeMetaFileIndex : KotlinFileIndexBase<KotlinNativeMetaFileIndex>(KotlinNativeMetaFileIndex::class.java) { object KotlinNativeMetaFileIndex : KotlinFileIndexBase<KotlinNativeMetaFileIndex>(KotlinNativeMetaFileIndex::class.java) {
@@ -27,6 +28,6 @@ object KotlinNativeMetaFileIndex : KotlinFileIndexBase<KotlinNativeMetaFileIndex
/*todo: check version?!*/ /*todo: check version?!*/
private val INDEXER = indexer { fileContent -> private val INDEXER = indexer { fileContent ->
val fragment = KotlinNativeLoadingMetadataCache.getInstance().getCachedPackageFragment(fileContent.file) val fragment = KotlinNativeLoadingMetadataCache.getInstance().getCachedPackageFragment(fileContent.file)
FqName(fragment.fqName) FqName(fragment.getExtension(KlibMetadataProtoBuf.fqName))
} }
} }
@@ -7,7 +7,6 @@ package org.jetbrains.kotlin.js.test
import org.jetbrains.kotlin.backend.common.phaser.PhaseConfig import org.jetbrains.kotlin.backend.common.phaser.PhaseConfig
import org.jetbrains.kotlin.backend.common.phaser.toPhaseMap import org.jetbrains.kotlin.backend.common.phaser.toPhaseMap
import org.jetbrains.kotlin.ir.backend.js.loadKlib
import org.jetbrains.kotlin.ir.backend.js.compile import org.jetbrains.kotlin.ir.backend.js.compile
import org.jetbrains.kotlin.ir.backend.js.generateKLib import org.jetbrains.kotlin.ir.backend.js.generateKLib
import org.jetbrains.kotlin.ir.backend.js.jsPhases import org.jetbrains.kotlin.ir.backend.js.jsPhases
@@ -15,15 +14,20 @@ import org.jetbrains.kotlin.js.config.JSConfigurationKeys
import org.jetbrains.kotlin.js.config.JsConfig import org.jetbrains.kotlin.js.config.JsConfig
import org.jetbrains.kotlin.js.facade.MainCallParameters import org.jetbrains.kotlin.js.facade.MainCallParameters
import org.jetbrains.kotlin.js.facade.TranslationUnit import org.jetbrains.kotlin.js.facade.TranslationUnit
import org.jetbrains.kotlin.library.KotlinLibrary
import org.jetbrains.kotlin.library.KotlinLibrarySearchPathResolver
import org.jetbrains.kotlin.library.UnresolvedLibrary
import org.jetbrains.kotlin.library.resolver.impl.libraryResolver
import org.jetbrains.kotlin.library.toUnresolvedLibraries
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.test.TargetBackend import org.jetbrains.kotlin.test.TargetBackend
import org.jetbrains.kotlin.utils.fileUtils.withReplacedExtensionOrNull import org.jetbrains.kotlin.utils.fileUtils.withReplacedExtensionOrNull
import java.io.File import java.io.File
import java.lang.Boolean.getBoolean import java.lang.Boolean.getBoolean
private val fullRuntimeKlib = loadKlib("compiler/ir/serialization.js/build/fullRuntime/klib") private val fullRuntimeKlib = "compiler/ir/serialization.js/build/fullRuntime/klib"
private val defaultRuntimeKlib = loadKlib("compiler/ir/serialization.js/build/reducedRuntime/klib") private val defaultRuntimeKlib = "compiler/ir/serialization.js/build/reducedRuntime/klib"
private val kotlinTestKLib = loadKlib("compiler/ir/serialization.js/build/kotlin.test/klib") private val kotlinTestKLib = "compiler/ir/serialization.js/build/kotlin.test/klib"
abstract class BasicIrBoxTest( abstract class BasicIrBoxTest(
pathToTestDir: String, pathToTestDir: String,
@@ -80,9 +84,27 @@ abstract class BasicIrBoxTest(
val transitiveLibraries = config.configuration[JSConfigurationKeys.TRANSITIVE_LIBRARIES]!!.map { File(it).name } val transitiveLibraries = config.configuration[JSConfigurationKeys.TRANSITIVE_LIBRARIES]!!.map { File(it).name }
val allDependencies = runtimeKlibs + transitiveLibraries.map { val allKlibPaths = (runtimeKlibs + transitiveLibraries.map {
loadKlib(compilationCache[it] ?: error("Can't find compiled module for dependency $it")) compilationCache[it] ?: error("Can't find compiled module for dependency $it")
} }).map { File(it).absolutePath }
val unresolvedLibraries = allKlibPaths.toUnresolvedLibraries
// Configure the resolver to only work with absolute paths for now.
val libraryResolver = KotlinLibrarySearchPathResolver<KotlinLibrary>(
repositories = emptyList(),
directLibs = allKlibPaths,
distributionKlib = null,
localKotlinDir = null,
skipCurrentDir = true
// TODO: pass logger attached to message collector here.
).libraryResolver()
val resolvedLibraries =
libraryResolver.resolveWithDependencies(
unresolvedLibraries = unresolvedLibraries,
noStdLib = true,
noDefaultLibs = true,
noEndorsedLibs = true
)
val actualOutputFile = outputFile.absolutePath.let { val actualOutputFile = outputFile.absolutePath.let {
if (!isMainModule) it.replace("_v5.js", "/") else it if (!isMainModule) it.replace("_v5.js", "/") else it
@@ -111,7 +133,7 @@ abstract class BasicIrBoxTest(
files = filesToCompile, files = filesToCompile,
configuration = config.configuration, configuration = config.configuration,
phaseConfig = phaseConfig, phaseConfig = phaseConfig,
allDependencies = allDependencies, allDependencies = resolvedLibraries,
friendDependencies = emptyList(), friendDependencies = emptyList(),
mainArguments = mainCallParameters.run { if (shouldBeGenerated()) arguments() else null }, mainArguments = mainCallParameters.run { if (shouldBeGenerated()) arguments() else null },
exportedDeclarations = setOf(FqName.fromSegments(listOfNotNull(testPackage, testFunction))) exportedDeclarations = setOf(FqName.fromSegments(listOfNotNull(testPackage, testFunction)))
@@ -130,7 +152,7 @@ abstract class BasicIrBoxTest(
project = config.project, project = config.project,
files = filesToCompile, files = filesToCompile,
configuration = config.configuration, configuration = config.configuration,
allDependencies = allDependencies, allDependencies = resolvedLibraries,
friendDependencies = emptyList(), friendDependencies = emptyList(),
outputKlibPath = actualOutputFile, outputKlibPath = actualOutputFile,
nopack = true nopack = true
@@ -21,6 +21,8 @@ import org.jetbrains.kotlin.ir.backend.js.loadKlib
import org.jetbrains.kotlin.js.config.JsConfig import org.jetbrains.kotlin.js.config.JsConfig
import org.jetbrains.kotlin.js.facade.TranslationUnit import org.jetbrains.kotlin.js.facade.TranslationUnit
import org.jetbrains.kotlin.js.test.engines.SpiderMonkeyEngine import org.jetbrains.kotlin.js.test.engines.SpiderMonkeyEngine
import org.jetbrains.kotlin.library.resolver.impl.KotlinLibraryResolverResultImpl
import org.jetbrains.kotlin.library.resolver.impl.KotlinResolvedLibraryImpl
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.psi.KtNamedFunction import org.jetbrains.kotlin.psi.KtNamedFunction
@@ -111,7 +113,8 @@ abstract class BasicWasmBoxTest(
files = filesToCompile, files = filesToCompile,
configuration = config.configuration, configuration = config.configuration,
phaseConfig = phaseConfig, phaseConfig = phaseConfig,
allDependencies = listOf(wasmRuntimeKlib), // TODO: Bypass the resolver fow wasm.
allDependencies = KotlinLibraryResolverResultImpl(listOf(KotlinResolvedLibraryImpl(wasmRuntimeKlib))),
friendDependencies = emptyList(), friendDependencies = emptyList(),
exportedDeclarations = setOf(FqName.fromSegments(listOfNotNull(testPackage, testFunction))) exportedDeclarations = setOf(FqName.fromSegments(listOfNotNull(testPackage, testFunction)))
) )
+3
View File
@@ -25,6 +25,9 @@ dependencies {
mavenCompileScope(project(":kotlin-compiler")) mavenCompileScope(project(":kotlin-compiler"))
compile(project(":kotlin-native:kotlin-native-utils")) compile(project(":kotlin-native:kotlin-native-utils"))
compile(project(":kotlin-util-io"))
compile(project(":kotlin-util-klib"))
compile(project(":kotlin-util-klib-metadata"))
testCompile(commonDep("junit:junit")) testCompile(commonDep("junit:junit"))
} }
-101
View File
@@ -1,101 +0,0 @@
/*
* Copyright 2010-2018 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.
*/
syntax = "proto2";
package org.jetbrains.kotlin.metadata.konan;
import "core/metadata/src/metadata.proto";
option java_outer_classname = "KonanProtoBuf";
option optimize_for = LITE_RUNTIME;
// Konan extensions to the "descriptors" protobuf.
extend Package {
optional int32 package_fq_name = 171;
}
extend Class {
repeated Annotation class_annotation = 170;
}
extend Constructor {
repeated Annotation constructor_annotation = 170;
optional InlineIrBody inline_constructor_ir_body = 171;
}
extend Function {
repeated Annotation function_annotation = 170;
optional InlineIrBody inline_ir_body = 171;
optional int32 function_file = 172;
}
extend Property {
repeated Annotation property_annotation = 170;
repeated Annotation property_getter_annotation = 177;
repeated Annotation property_setter_annotation = 178;
optional bool has_backing_field = 171;
optional bool used_as_variable = 172;
optional Annotation.Argument.Value compile_time_value = 173;
optional InlineIrBody inline_getter_ir_body = 174;
optional InlineIrBody inline_setter_ir_body = 175;
optional int32 property_file = 176;
}
extend EnumEntry {
repeated Annotation enum_entry_annotation = 170;
optional int32 enum_entry_ordinal = 171;
}
extend ValueParameter {
repeated Annotation parameter_annotation = 170;
}
extend Type {
repeated Annotation type_annotation = 170;
optional string type_text = 172; // TODO: remove me
}
extend TypeParameter {
repeated Annotation type_parameter_annotation = 170;
}
message InlineIrBody {
// We need to refer from descriptors to ir inline body.
// And in ir we need to refer local declaration descriptors
// That requires mutual import of KonanIr and KonanLinkData.
// I break the circle here by storing encoded IR.
// May be we need to merge KonanIr into KonanLinkData.
// That'd allow mutually recursive messages.
required string encoded_ir = 11;
}
// Konan Binary Linkdata structures.
message LinkDataPackageFragment {
// Make if an index?
required string fq_name = 1;
required Package package = 4;
required LinkDataClasses classes = 5;
required bool is_empty = 6;
// To construct name resolver
required QualifiedNameTable name_table = 2;
required StringTable string_table = 3;
}
message LinkDataClasses {
// Index in the QualifiedNameIndex table.
repeated int32 class_name = 1;
repeated Class classes = 2;
}
message LinkDataLibrary {
required string module_name = 1;
repeated string package_fragment_name = 2;
repeated string empty_package = 3;
repeated string file = 4;
}
@@ -1,32 +0,0 @@
/*
* Copyright 2010-2018 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.descriptors.konan
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.konan.library.KonanLibrary
import org.jetbrains.kotlin.konan.library.isInterop
sealed class KonanModuleOrigin {
companion object {
val CAPABILITY = ModuleDescriptor.Capability<KonanModuleOrigin>("KonanModuleOrigin")
}
}
sealed class CompiledKonanModuleOrigin: KonanModuleOrigin()
class DeserializedKonanModuleOrigin(val library: KonanLibrary) : CompiledKonanModuleOrigin()
object CurrentKonanModuleOrigin: CompiledKonanModuleOrigin()
object SyntheticModulesOrigin : KonanModuleOrigin()
internal fun KonanModuleOrigin.isInteropLibrary(): Boolean = when (this) {
is DeserializedKonanModuleOrigin -> this.library.isInterop
CurrentKonanModuleOrigin, SyntheticModulesOrigin -> false
}
val ModuleDescriptor.konanModuleOrigin get() = this.getCapability(KonanModuleOrigin.CAPABILITY)!!
@@ -0,0 +1,17 @@
/*
* 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.konan.library
import org.jetbrains.kotlin.builtins.konan.KonanBuiltIns
import org.jetbrains.kotlin.konan.util.KlibMetadataFactories
import org.jetbrains.kotlin.serialization.konan.NullFlexibleTypeDeserializer
import org.jetbrains.kotlin.storage.StorageManager
fun createKonanBuiltIns(storageManager: StorageManager) = KonanBuiltIns(storageManager)
/**
* The default Kotlin/Native factories.
*/
object KonanFactories : KlibMetadataFactories(::createKonanBuiltIns, NullFlexibleTypeDeserializer)
@@ -1,73 +0,0 @@
/*
* Copyright 2010-2018 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.konan.library
import org.jetbrains.kotlin.konan.file.File
import org.jetbrains.kotlin.konan.properties.Properties
import org.jetbrains.kotlin.konan.properties.propertyList
import org.jetbrains.kotlin.metadata.konan.KonanProtoBuf
import org.jetbrains.kotlin.name.FqName
const val KLIB_PROPERTY_ABI_VERSION = "abi_version"
const val KLIB_PROPERTY_UNIQUE_NAME = "unique_name"
const val KLIB_PROPERTY_COMPILER_VERSION = "compiler_version"
const val KLIB_PROPERTY_LINKED_OPTS = "linkerOpts"
const val KLIB_PROPERTY_DEPENDS = "depends"
const val KLIB_PROPERTY_INTEROP = "interop"
const val KLIB_PROPERTY_PACKAGE = "package"
const val KLIB_PROPERTY_EXPORT_FORWARD_DECLARATIONS = "exportForwardDeclarations"
const val KLIB_PROPERTY_INCLUDED_HEADERS = "includedHeaders"
/**
* An abstraction for getting access to the information stored inside of Kotlin/Native library.
*/
interface KonanLibrary {
val libraryName: String
val libraryFile: File
// Whether this library is default (provided by Kotlin/Native distribution)?
val isDefault: Boolean
// Properties:
val manifestProperties: Properties
val abiVersion: String
val linkerOpts: List<String>
// Paths:
val bitcodePaths: List<String>
val includedPaths: List<String>
val targetList: List<String>
val dataFlowGraph: ByteArray?
val moduleHeaderData: KonanProtoBuf.LinkDataLibrary
fun packageMetadataParts(fqName: String): Set<String>
fun packageMetadata(packageFqName: String, partName: String): KonanProtoBuf.LinkDataPackageFragment
}
val KonanLibrary.uniqueName
get() = manifestProperties.getProperty(KLIB_PROPERTY_UNIQUE_NAME)!!
val KonanLibrary.unresolvedDependencies: List<String>
get() = manifestProperties.propertyList(KLIB_PROPERTY_DEPENDS)
val KonanLibrary.isInterop
get() = manifestProperties.getProperty(KLIB_PROPERTY_INTEROP) == "true"
val KonanLibrary.packageFqName
get() = manifestProperties.getProperty(KLIB_PROPERTY_PACKAGE)?.let { FqName(it) }
val KonanLibrary.exportForwardDeclarations
get() = manifestProperties.getProperty(KLIB_PROPERTY_EXPORT_FORWARD_DECLARATIONS)
.split(' ').asSequence()
.map { it.trim() }
.filter { it.isNotEmpty() }
.map { FqName(it) }
.toList()
val KonanLibrary.includedHeaders
get() = manifestProperties.getProperty(KLIB_PROPERTY_INCLUDED_HEADERS).split(' ')
@@ -1,48 +0,0 @@
/*
* Copyright 2010-2018 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.konan.library
import org.jetbrains.kotlin.konan.file.File
import org.jetbrains.kotlin.konan.target.KonanTarget
/**
* This scheme describes the Kotlin/Native Library (KLIB) layout.
*/
interface KonanLibraryLayout {
val libraryName: String
val libDir: File
val source: KonanLibrarySource
// This is a default implementation. Can't make it an assignment.
val target: KonanTarget? get() = null
val manifestFile get() = File(libDir, KLIB_MANIFEST_FILE_NAME)
val resourcesDir get() = File(libDir, "resources")
val targetsDir get() = File(libDir, "targets")
val targetDir get() = File(targetsDir, target!!.visibleName)
val kotlinDir get() = File(targetDir, "kotlin")
val nativeDir get() = File(targetDir, "native")
val includedDir get() = File(targetDir, "included")
val linkdataDir get() = File(libDir, "linkdata")
val moduleHeaderFile get() = File(linkdataDir, KLIB_MODULE_METADATA_FILE_NAME)
val dataFlowGraphFile get() = File(linkdataDir, "module_data_flow_graph")
fun packageFragmentsDir(packageFqName: String) =
File(linkdataDir, if (packageFqName == "") "root_package" else "package_$packageFqName")
fun packageFragmentFile(packageFqName: String, partName: String) =
File(packageFragmentsDir(packageFqName), "$partName$KLIB_METADATA_FILE_EXTENSION_WITH_DOT")
}
sealed class KonanLibrarySource {
object KonanLibraryDir : KonanLibrarySource()
class KonanLibraryFile(val klibFile: File) : KonanLibrarySource()
}
@@ -1,45 +0,0 @@
/*
* Copyright 2010-2018 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.konan.library
import org.jetbrains.kotlin.konan.file.File
import org.jetbrains.kotlin.konan.file.file
import org.jetbrains.kotlin.konan.file.withMutableZipFileSystem
import org.jetbrains.kotlin.konan.library.impl.DefaultMetadataReaderImpl
import org.jetbrains.kotlin.konan.library.impl.KonanLibraryImpl
import org.jetbrains.kotlin.konan.library.impl.zippedKonanLibraryChecks
import org.jetbrains.kotlin.konan.library.resolver.KonanLibraryResolver
import org.jetbrains.kotlin.konan.library.resolver.impl.KonanLibraryResolverImpl
import org.jetbrains.kotlin.konan.target.KonanTarget
fun File.unpackZippedKonanLibraryTo(newDir: File) {
// First, run validity checks for the given KLIB file.
zippedKonanLibraryChecks(this)
if (newDir.exists) {
if (newDir.isDirectory)
newDir.deleteRecursively()
else
newDir.delete()
}
this.withMutableZipFileSystem {
it.file("/").recursiveCopyTo(newDir)
}
check(newDir.exists) { "Could not unpack $this as $newDir." }
}
fun createKonanLibrary(
libraryFile: File,
currentAbiVersion: Int,
target: KonanTarget? = null,
isDefault: Boolean = false,
metadataReader: MetadataReader = DefaultMetadataReaderImpl
): KonanLibrary = KonanLibraryImpl(libraryFile, currentAbiVersion, target, isDefault, metadataReader)
fun SearchPathResolverWithTarget.libraryResolver(abiVersion: Int): KonanLibraryResolver =
KonanLibraryResolverImpl(this, abiVersion)
@@ -1,17 +0,0 @@
/*
* Copyright 2010-2018 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.konan.library
import org.jetbrains.kotlin.metadata.konan.KonanProtoBuf
interface MetadataReader {
fun loadSerializedModule(libraryLayout: KonanLibraryLayout): KonanProtoBuf.LinkDataLibrary
fun loadSerializedPackageFragment(
libraryLayout: KonanLibraryLayout,
packageFqName: String,
partName: String
): KonanProtoBuf.LinkDataPackageFragment
}
@@ -1,19 +0,0 @@
/*
* Copyright 2010-2018 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.konan.library
import org.jetbrains.kotlin.konan.file.File
import org.jetbrains.kotlin.konan.target.KonanTarget
interface SearchPathResolver {
val searchRoots: List<File>
fun resolve(givenPath: String): File
fun defaultLinks(noStdLib: Boolean, noDefaultLibs: Boolean): List<File>
}
interface SearchPathResolverWithTarget : SearchPathResolver {
val target: KonanTarget
}
@@ -1,27 +0,0 @@
/*
* Copyright 2010-2018 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.konan.library.impl
import org.jetbrains.kotlin.konan.library.KonanLibraryLayout
import org.jetbrains.kotlin.konan.library.MetadataReader
import org.jetbrains.kotlin.metadata.konan.KonanProtoBuf
import org.jetbrains.kotlin.serialization.konan.parseModuleHeader
import org.jetbrains.kotlin.serialization.konan.parsePackageFragment
object DefaultMetadataReaderImpl : MetadataReader {
override fun loadSerializedModule(libraryLayout: KonanLibraryLayout): KonanProtoBuf.LinkDataLibrary =
parseModuleHeader(libraryLayout.moduleHeaderFile.readBytes())
override fun loadSerializedPackageFragment(
libraryLayout: KonanLibraryLayout,
packageFqName: String,
partName: String
): KonanProtoBuf.LinkDataPackageFragment =
parsePackageFragment(
libraryLayout.packageFragmentFile(packageFqName, partName).readBytes()
)
}
@@ -1,86 +0,0 @@
/*
* Copyright 2010-2018 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.konan.library.impl
import org.jetbrains.kotlin.konan.file.File
import org.jetbrains.kotlin.konan.library.*
import org.jetbrains.kotlin.konan.properties.Properties
import org.jetbrains.kotlin.konan.properties.loadProperties
import org.jetbrains.kotlin.konan.properties.propertyList
import org.jetbrains.kotlin.konan.target.KonanTarget
import org.jetbrains.kotlin.konan.util.defaultTargetSubstitutions
import org.jetbrains.kotlin.konan.util.substitute
import org.jetbrains.kotlin.metadata.konan.KonanProtoBuf
internal class KonanLibraryImpl(
override val libraryFile: File,
private val currentAbiVersion: Int,
internal val target: KonanTarget?,
override val isDefault: Boolean,
private val metadataReader: MetadataReader
) : KonanLibrary {
// For the zipped libraries inPlace gives files from zip file system
// whereas realFiles extracts them to /tmp.
// For unzipped libraries inPlace and realFiles are the same
// providing files in the library directory.
private val layout = createKonanLibraryLayout(libraryFile, target)
override val libraryName: String by lazy { layout.inPlace { it.libraryName } }
override val manifestProperties: Properties by lazy {
val properties = layout.inPlace { it.manifestFile.loadProperties() }
if (target != null) substitute(properties, defaultTargetSubstitutions(target))
properties
}
override val abiVersion: String
get() {
val manifestAbiVersion = manifestProperties.getProperty(KLIB_PROPERTY_ABI_VERSION)
check(currentAbiVersion.toString() == manifestAbiVersion) {
"ABI version mismatch. Compiler expects: $currentAbiVersion, the library is $manifestAbiVersion"
}
return manifestAbiVersion
}
override val linkerOpts: List<String>
get() = manifestProperties.propertyList(KLIB_PROPERTY_LINKED_OPTS, target!!.visibleName)
override val bitcodePaths: List<String>
get() = layout.realFiles { (it.kotlinDir.listFilesOrEmpty + it.nativeDir.listFilesOrEmpty).map { it.absolutePath } }
override val includedPaths: List<String>
get() = layout.realFiles { it.includedDir.listFilesOrEmpty.map { it.absolutePath } }
override val targetList by lazy { layout.inPlace { it.targetsDir.listFiles.map { it.name } } }
override val dataFlowGraph by lazy { layout.inPlace { it.dataFlowGraphFile.let { if (it.exists) it.readBytes() else null } } }
override val moduleHeaderData: KonanProtoBuf.LinkDataLibrary by lazy { layout.inPlace { metadataReader.loadSerializedModule(it) } }
override fun packageMetadata(packageFqName: String, partName: String) =
layout.inPlace { metadataReader.loadSerializedPackageFragment(it, packageFqName, partName) }
override fun packageMetadataParts(fqName: String): Set<String> =
layout.inPlace { inPlaceLayout ->
val fileList =
inPlaceLayout.packageFragmentsDir(fqName)
.listFiles
.mapNotNull {
it.name
.substringBeforeLast(KLIB_METADATA_FILE_EXTENSION_WITH_DOT, missingDelimiterValue = "")
.takeIf { it.isNotEmpty() }
}
fileList.toSortedSet().also {
require(it.size == fileList.size) { "Duplicated names: ${fileList.groupingBy { it }.eachCount().filter { (_, count) -> count > 1 }}" }
}
}
override fun toString() = "$libraryName[default=$isDefault]"
}
@@ -1,104 +0,0 @@
/*
* Copyright 2010-2018 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.konan.library.impl
import org.jetbrains.kotlin.konan.file.*
import org.jetbrains.kotlin.konan.library.KLIB_FILE_EXTENSION
import org.jetbrains.kotlin.konan.library.KLIB_FILE_EXTENSION_WITH_DOT
import org.jetbrains.kotlin.konan.library.KonanLibraryLayout
import org.jetbrains.kotlin.konan.library.KonanLibrarySource.KonanLibraryDir
import org.jetbrains.kotlin.konan.library.KonanLibrarySource.KonanLibraryFile
import org.jetbrains.kotlin.konan.target.KonanTarget
import java.nio.file.FileSystem
interface KonanLibraryLayoutImpl : KonanLibraryLayout {
fun <T> inPlace(action: (KonanLibraryLayout) -> T): T
fun <T> realFiles(action: (KonanLibraryLayout) -> T): T
}
private class ZippedKonanLibraryLayout(
klibFile: File,
override val target: KonanTarget?
) : KonanLibraryLayoutImpl {
init {
zippedKonanLibraryChecks(klibFile)
}
override val libraryName = klibFile.path.removeSuffix(KLIB_FILE_EXTENSION_WITH_DOT)
override val libDir: File = File("/")
override val source = KonanLibraryFile(klibFile)
override fun <T> realFiles(action: (KonanLibraryLayout) -> T) = action(FileExtractor(this))
override fun <T> inPlace(action: (KonanLibraryLayout) -> T) = source.klibFile.withZipFileSystem { zipFileSystem ->
action(DirectFromZip(this, zipFileSystem))
}
}
internal fun zippedKonanLibraryChecks(klibFile: File) {
check(klibFile.exists) { "Could not find $klibFile." }
check(klibFile.isFile) { "Expected $klibFile to be a regular file." }
val extension = klibFile.extension
check(extension.isEmpty() || extension == KLIB_FILE_EXTENSION) { "Unexpected file extension: $extension" }
}
private class UnzippedKonanLibraryLayout(
override val libDir: File,
override val target: KonanTarget?
) : KonanLibraryLayoutImpl {
override val libraryName = libDir.path
override val source = KonanLibraryDir
override fun <T> inPlace(action: (KonanLibraryLayout) -> T) = action(this)
override fun <T> realFiles(action: (KonanLibraryLayout) -> T) = inPlace(action)
}
private class DirectFromZip(
zippedLayout: ZippedKonanLibraryLayout,
zipFileSystem: FileSystem
) : KonanLibraryLayout {
override val libraryName = zippedLayout.libraryName
override val libDir = zipFileSystem.file(zippedLayout.libDir)
override val source = zippedLayout.source
}
/**
* This class automatically extracts pieces of the library on first access. Use it if you need
* to pass extracted files to an external tool. Otherwise, stick to [DirectFromZip].
*/
private class FileExtractor(
val zippedLayout: ZippedKonanLibraryLayout
) : KonanLibraryLayout by zippedLayout {
override val manifestFile: File by lazy { extract(super.manifestFile) }
override val resourcesDir: File by lazy { extractDir(super.resourcesDir) }
override val includedDir: File by lazy { extractDir(super.includedDir) }
override val kotlinDir: File by lazy { extractDir(super.kotlinDir) }
override val nativeDir: File by lazy { extractDir(super.nativeDir) }
override val linkdataDir: File by lazy { extractDir(super.linkdataDir) }
fun extract(file: File): File = zippedLayout.source.klibFile.withZipFileSystem { zipFileSystem ->
val temporary = createTempFile(file.name)
zipFileSystem.file(file).copyTo(temporary)
temporary.deleteOnExit()
temporary
}
fun extractDir(directory: File): File = zippedLayout.source.klibFile.withZipFileSystem { zipFileSystem ->
val temporary = createTempDir(directory.name)
zipFileSystem.file(directory).recursiveCopyTo(temporary)
temporary.deleteOnExitRecursively()
temporary
}
}
internal fun createKonanLibraryLayout(klib: File, target: KonanTarget? = null) =
if (klib.isFile) ZippedKonanLibraryLayout(klib, target) else UnzippedKonanLibraryLayout(klib, target)
@@ -6,6 +6,7 @@
package org.jetbrains.kotlin.konan.library.lite package org.jetbrains.kotlin.konan.library.lite
import org.jetbrains.kotlin.konan.library.* import org.jetbrains.kotlin.konan.library.*
import org.jetbrains.kotlin.library.*
import java.io.File import java.io.File
import java.io.IOException import java.io.IOException
import java.nio.file.Path import java.nio.file.Path
@@ -1,64 +0,0 @@
/*
* Copyright 2010-2018 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.konan.library.resolver
import org.jetbrains.kotlin.konan.library.KonanLibrary
import org.jetbrains.kotlin.konan.library.SearchPathResolverWithTarget
typealias DuplicatedLibraryLogger = (String) -> Unit
interface KonanLibraryResolver {
val searchPathResolver: SearchPathResolverWithTarget
val abiVersion: Int
/**
* Given the list of Kotlin/Native library names, ABI version and other parameters
* resolves libraries and evaluates dependencies between them.
*/
fun resolveWithDependencies(
libraryNames: List<String>,
noStdLib: Boolean = false,
noDefaultLibs: Boolean = false,
logger: DuplicatedLibraryLogger? = null
): KonanLibraryResolveResult
}
interface KonanLibraryResolveResult {
fun filterRoots(predicate: (KonanResolvedLibrary) -> Boolean): KonanLibraryResolveResult
fun getFullList(order: LibraryOrder? = null): List<KonanLibrary>
fun forEach(action: (KonanLibrary, PackageAccessedHandler) -> Unit)
}
typealias LibraryOrder = (Iterable<KonanResolvedLibrary>) -> List<KonanResolvedLibrary>
val TopologicalLibraryOrder: LibraryOrder = { input ->
val sorted = mutableListOf<KonanResolvedLibrary>()
val visited = mutableSetOf<KonanResolvedLibrary>()
val tempMarks = mutableSetOf<KonanResolvedLibrary>()
fun visit(node: KonanResolvedLibrary, result: MutableList<KonanResolvedLibrary>) {
if (visited.contains(node)) return
if (tempMarks.contains(node)) error("Cyclic dependency in library graph.")
tempMarks.add(node)
node.resolvedDependencies.forEach {
visit(it, result)
}
visited.add(node)
result += node
}
input.forEach next@{
if (visited.contains(it)) return@next
visit(it, sorted)
}
sorted
}
@@ -1,32 +0,0 @@
/*
* Copyright 2010-2018 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.konan.library.resolver
import org.jetbrains.kotlin.konan.library.KonanLibrary
import org.jetbrains.kotlin.name.FqName
interface PackageAccessedHandler {
fun markPackageAccessed(fqName: FqName)
}
/**
* A [KonanLibrary] wrapper that is used for resolving library's dependencies.
*/
interface KonanResolvedLibrary: PackageAccessedHandler {
// The library itself.
val library: KonanLibrary
// Dependencies on other libraries.
val resolvedDependencies: List<KonanResolvedLibrary>
// Whether it is needed to linker.
val isNeededForLink: Boolean
// Is provided by the distribution?
val isDefault: Boolean
}
@@ -1,142 +0,0 @@
/*
* Copyright 2010-2018 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.konan.library.resolver.impl
import org.jetbrains.kotlin.konan.file.File
import org.jetbrains.kotlin.konan.library.KonanLibrary
import org.jetbrains.kotlin.konan.library.SearchPathResolverWithTarget
import org.jetbrains.kotlin.konan.library.createKonanLibrary
import org.jetbrains.kotlin.konan.library.resolver.*
import org.jetbrains.kotlin.konan.library.unresolvedDependencies
internal class KonanLibraryResolverImpl(
override val searchPathResolver: SearchPathResolverWithTarget,
override val abiVersion: Int
) : KonanLibraryResolver {
override fun resolveWithDependencies(
libraryNames: List<String>,
noStdLib: Boolean,
noDefaultLibs: Boolean,
logger: DuplicatedLibraryLogger?
) = findLibraries(libraryNames, noStdLib, noDefaultLibs)
.leaveDistinct(logger)
.resolveDependencies()
/**
* Returns the list of libraries based on [libraryNames], [noStdLib] and [noDefaultLibs] criteria.
*
* This method does not return any libraries that might be available via transitive dependencies
* from the original library set (root set).
*/
private fun findLibraries(
libraryNames: List<String>,
noStdLib: Boolean,
noDefaultLibs: Boolean
): List<KonanLibrary> {
val userProvidedLibraries = libraryNames.asSequence()
.map { searchPathResolver.resolve(it) }
.map { createKonanLibrary(it, abiVersion, searchPathResolver.target) }
.toList()
val defaultLibraries = searchPathResolver.defaultLinks(noStdLib, noDefaultLibs).map {
createKonanLibrary(it, abiVersion, searchPathResolver.target, isDefault = true)
}
// Make sure the user provided ones appear first, so that
// they have precedence over defaults when duplicates are eliminated.
return userProvidedLibraries + defaultLibraries
}
/**
* Leaves only distinct libraries (by absolute path), warns on duplicated paths.
*/
private fun List<KonanLibrary>.leaveDistinct(logger: DuplicatedLibraryLogger?) =
this.groupBy { it.libraryFile.absolutePath }.let { groupedByAbsolutePath ->
warnOnLibraryDuplicates(groupedByAbsolutePath.filter { it.value.size > 1 }.keys, logger)
groupedByAbsolutePath.map { it.value.first() }
}
private fun warnOnLibraryDuplicates(duplicatedPaths: Iterable<String>, logger: DuplicatedLibraryLogger?) {
if (logger == null) return
duplicatedPaths.forEach { logger("library included more than once: $it") }
}
/**
* Given the list of root libraries does the following:
*
* 1. Evaluates other libraries that are available via transitive dependencies.
* 2. Wraps each [KonanLibrary] into a [KonanResolvedLibrary] with information about dependencies on other libraries.
* 3. Creates resulting [KonanLibraryResolveResult] object.
*/
private fun List<KonanLibrary>.resolveDependencies(): KonanLibraryResolveResult {
val rootLibraries = this.map { KonanResolvedLibraryImpl(it) }
// As far as the list of root libraries is known from the very beginning, the result can be
// constructed from the very beginning as well.
val result = KonanLibraryResolverResultImpl(rootLibraries)
val cache = mutableMapOf<File, KonanResolvedLibrary>()
cache.putAll(rootLibraries.map { it.library.libraryFile.absoluteFile to it })
var newDependencies = rootLibraries
do {
newDependencies = newDependencies.map { library: KonanResolvedLibraryImpl ->
library.library.unresolvedDependencies.asSequence()
.map { searchPathResolver.resolve(it).absoluteFile }
.mapNotNull {
if (it in cache) {
library.addDependency(cache[it]!!)
null
} else {
val newLibrary = KonanResolvedLibraryImpl(createKonanLibrary(it, abiVersion, searchPathResolver.target))
cache[it] = newLibrary
library.addDependency(newLibrary)
newLibrary
}
}
.toList()
}.flatten()
} while (newDependencies.isNotEmpty())
return result
}
}
internal class KonanLibraryResolverResultImpl(
private val roots: List<KonanResolvedLibrary>
) : KonanLibraryResolveResult {
private val all: List<KonanResolvedLibrary> by lazy {
val result = mutableSetOf<KonanResolvedLibrary>().also { it.addAll(roots) }
var newDependencies = result.toList()
do {
newDependencies = newDependencies
.map { it -> it.resolvedDependencies }.flatten()
.filter { it !in result }
result.addAll(newDependencies)
} while (newDependencies.isNotEmpty())
result.toList()
}
override fun filterRoots(predicate: (KonanResolvedLibrary) -> Boolean) =
KonanLibraryResolverResultImpl(roots.filter(predicate))
override fun getFullList(order: LibraryOrder?) = (order?.invoke(all) ?: all).asPlain()
override fun forEach(action: (KonanLibrary, PackageAccessedHandler) -> Unit) {
all.forEach { action(it.library, it) }
}
private fun List<KonanResolvedLibrary>.asPlain() = map { it.library }
override fun toString() = "roots=$roots, all=$all"
}
@@ -1,39 +0,0 @@
/*
* Copyright 2010-2018 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.konan.library.resolver.impl
import org.jetbrains.kotlin.konan.library.KonanLibrary
import org.jetbrains.kotlin.konan.library.resolver.KonanResolvedLibrary
import org.jetbrains.kotlin.name.FqName
internal class KonanResolvedLibraryImpl(
override val library: KonanLibrary
) : KonanResolvedLibrary {
private val _resolvedDependencies = mutableListOf<KonanResolvedLibrary>()
private val _emptyPackages by lazy { library.moduleHeaderData.emptyPackageList }
override val resolvedDependencies: List<KonanResolvedLibrary>
get() = _resolvedDependencies
internal fun addDependency(resolvedLibrary: KonanResolvedLibrary) = _resolvedDependencies.add(resolvedLibrary)
override var isNeededForLink: Boolean = false
private set
override val isDefault: Boolean
get() = library.isDefault
override fun markPackageAccessed(fqName: FqName) {
if (!isNeededForLink // fast path
&& !_emptyPackages.contains(fqName.asString())
) {
isNeededForLink = true
}
}
override fun toString() = "library=$library, dependsOn=${_resolvedDependencies.joinToString { it.library.toString() }}"
}
@@ -1,56 +0,0 @@
/*
* Copyright 2010-2018 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.konan.util
import org.jetbrains.kotlin.descriptors.konan.KonanModuleDescriptorFactory
import org.jetbrains.kotlin.descriptors.konan.impl.KonanModuleDescriptorFactoryImpl
import org.jetbrains.kotlin.serialization.konan.KonanDeserializedModuleDescriptorFactory
import org.jetbrains.kotlin.serialization.konan.KonanDeserializedPackageFragmentsFactory
import org.jetbrains.kotlin.serialization.konan.KonanResolvedModuleDescriptorsFactory
import org.jetbrains.kotlin.serialization.konan.impl.KonanDeserializedModuleDescriptorFactoryImpl
import org.jetbrains.kotlin.serialization.konan.impl.KonanDeserializedPackageFragmentsFactoryImpl
import org.jetbrains.kotlin.serialization.konan.impl.KonanResolvedModuleDescriptorsFactoryImpl
/**
* The default Kotlin/Native factories.
*/
object KonanFactories {
/**
* The default [KonanModuleDescriptorFactory] factory instance.
*/
val DefaultDescriptorFactory: KonanModuleDescriptorFactory = KonanModuleDescriptorFactoryImpl
/**
* The default [KonanDeserializedPackageFragmentsFactory] factory instance.
*/
val DefaultPackageFragmentsFactory: KonanDeserializedPackageFragmentsFactory =
KonanDeserializedPackageFragmentsFactoryImpl
/**
* The default [KonanDeserializedModuleDescriptorFactory] factory instance.
*/
val DefaultDeserializedDescriptorFactory: KonanDeserializedModuleDescriptorFactory =
createDefaultKonanDeserializedModuleDescriptorFactory(
DefaultDescriptorFactory, DefaultPackageFragmentsFactory
)
/**
* The default [KonanResolvedModuleDescriptorsFactory] factory instance.
*/
val DefaultResolvedDescriptorsFactory: KonanResolvedModuleDescriptorsFactory =
createDefaultKonanResolvedModuleDescriptorsFactory(DefaultDeserializedDescriptorFactory)
fun createDefaultKonanDeserializedModuleDescriptorFactory(
descriptorFactory: KonanModuleDescriptorFactory,
packageFragmentsFactory: KonanDeserializedPackageFragmentsFactory
): KonanDeserializedModuleDescriptorFactory =
KonanDeserializedModuleDescriptorFactoryImpl(descriptorFactory, packageFragmentsFactory)
fun createDefaultKonanResolvedModuleDescriptorsFactory(
moduleDescriptorFactory: KonanDeserializedModuleDescriptorFactory
): KonanResolvedModuleDescriptorsFactory = KonanResolvedModuleDescriptorsFactoryImpl(moduleDescriptorFactory)
}
File diff suppressed because it is too large Load Diff
@@ -1,14 +0,0 @@
/*
* Copyright 2010-2018 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.serialization.konan
import org.jetbrains.kotlin.metadata.konan.KonanProtoBuf
fun parsePackageFragment(packageMetadata: ByteArray): KonanProtoBuf.LinkDataPackageFragment =
KonanProtoBuf.LinkDataPackageFragment.parseFrom(packageMetadata, KonanSerializerProtocol.extensionRegistry)
fun parseModuleHeader(libraryMetadata: ByteArray): KonanProtoBuf.LinkDataLibrary =
KonanProtoBuf.LinkDataLibrary.parseFrom(libraryMetadata, KonanSerializerProtocol.extensionRegistry)
@@ -1,43 +0,0 @@
/*
* Copyright 2010-2018 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.serialization.konan
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
import org.jetbrains.kotlin.descriptors.konan.KonanModuleDescriptorFactory
import org.jetbrains.kotlin.konan.library.KonanLibrary
import org.jetbrains.kotlin.konan.library.resolver.PackageAccessedHandler
import org.jetbrains.kotlin.storage.LockBasedStorageManager
import org.jetbrains.kotlin.storage.StorageManager
interface KonanDeserializedModuleDescriptorFactory {
val descriptorFactory: KonanModuleDescriptorFactory
val packageFragmentsFactory: KonanDeserializedPackageFragmentsFactory
fun createDescriptor(
library: KonanLibrary,
languageVersionSettings: LanguageVersionSettings,
storageManager: StorageManager,
builtIns: KotlinBuiltIns,
packageAccessedHandler: PackageAccessedHandler? = null,
customCapabilities: Map<ModuleDescriptor.Capability<*>, Any?> = emptyMap()
): ModuleDescriptorImpl
/**
* Please use this method with care: As far as it creates an instance of [KotlinBuiltIns] it should be
* normally used for creation of the very first (e.g. "stdlib") module in the set of created modules.
*/
fun createDescriptorAndNewBuiltIns(
library: KonanLibrary,
languageVersionSettings: LanguageVersionSettings,
storageManager: StorageManager,
packageAccessedHandler: PackageAccessedHandler? = null,
customCapabilities: Map<ModuleDescriptor.Capability<*>, Any?> = emptyMap()
): ModuleDescriptorImpl
}
@@ -1,44 +0,0 @@
/*
* Copyright 2010-2018 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.serialization.konan
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
import org.jetbrains.kotlin.konan.library.KonanLibrary
import org.jetbrains.kotlin.konan.library.resolver.PackageAccessedHandler
import org.jetbrains.kotlin.serialization.deserialization.DeserializationConfiguration
import org.jetbrains.kotlin.storage.StorageManager
interface KonanDeserializedPackageFragmentsFactory {
fun createDeserializedPackageFragments(
library: KonanLibrary,
packageFragmentNames: List<String>,
moduleDescriptor: ModuleDescriptor,
packageAccessedHandler: PackageAccessedHandler?,
storageManager: StorageManager
): List<KonanPackageFragment>
fun createSyntheticPackageFragments(
library: KonanLibrary,
deserializedPackageFragments: List<KonanPackageFragment>,
moduleDescriptor: ModuleDescriptor
): List<PackageFragmentDescriptor>
fun createPackageFragmentProvider(
library: KonanLibrary,
packageAccessedHandler: PackageAccessedHandler?,
packageFragmentNames: List<String>,
storageManager: StorageManager,
moduleDescriptor: ModuleDescriptor,
configuration: DeserializationConfiguration
): PackageFragmentProvider
fun createForwardDeclarationHackPackagePartProvider(
storageManager: StorageManager,
module: ModuleDescriptorImpl
): PackageFragmentProviderImpl
}
@@ -1,56 +0,0 @@
/*
* Copyright 2010-2018 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.serialization.konan
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
import org.jetbrains.kotlin.konan.library.KonanLibrary
import org.jetbrains.kotlin.konan.library.resolver.KonanLibraryResolveResult
import org.jetbrains.kotlin.storage.StorageManager
interface KonanResolvedModuleDescriptorsFactory {
val moduleDescriptorFactory: KonanDeserializedModuleDescriptorFactory
/**
* Given the [resolvedLibraries] creates the list of [ModuleDescriptorImpl]s with properly installed
* inter-dependencies. The result of this method is returned in a form of [KonanResolvedModuleDescriptors] instance.
*
* Please use this method with care: Unless this method accepts `null` for [builtIns], it is not recommended to
* invoke it this way. If you are compiling a source module, please supply the non-null [builtIns] from the
* source module, so that all modules created in your compilation session will share the same built-ins instance.
*
* Otherwise (if `null` was supplied), a new instance of [KotlinBuiltIns] will be created. The created built-ins
* instance will be shared by all modules created in this method. But this instance will have no connection
* with probably existing built-ins instance of your source module(s).
*/
fun createResolved(
resolvedLibraries: KonanLibraryResolveResult,
storageManager: StorageManager,
builtIns: KotlinBuiltIns?,
languageVersionSettings: LanguageVersionSettings,
customAction: ((KonanLibrary, ModuleDescriptorImpl) -> Unit)? = null,
customCapabilitiesGenerator: ((KonanLibrary) -> Map<ModuleDescriptor.Capability<*>, Any?>)? = null
): KonanResolvedModuleDescriptors
}
class KonanResolvedModuleDescriptors(
/**
* The list of modules each representing an individual Kotlin/Native library. All modules
* in this list have properly installed dependencies, i.e. module has all necessary dependencies
* on other modules plus a dependency on the [forwardDeclarationsModule].
*/
val resolvedDescriptors: List<ModuleDescriptorImpl>,
/**
* This is a module which "contains" forward declarations.
* Note: this module should be unique per compilation and should always be the last dependency of any module.
*/
val forwardDeclarationsModule: ModuleDescriptorImpl
)
@@ -1,26 +0,0 @@
/*
* Copyright 2010-2018 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.serialization.konan
import org.jetbrains.kotlin.metadata.konan.KonanProtoBuf
import org.jetbrains.kotlin.protobuf.ExtensionRegistryLite
import org.jetbrains.kotlin.serialization.SerializerExtensionProtocol
object KonanSerializerProtocol : SerializerExtensionProtocol(
ExtensionRegistryLite.newInstance().apply(KonanProtoBuf::registerAllExtensions),
KonanProtoBuf.packageFqName,
KonanProtoBuf.constructorAnnotation,
KonanProtoBuf.classAnnotation,
KonanProtoBuf.functionAnnotation,
KonanProtoBuf.propertyAnnotation,
KonanProtoBuf.propertyGetterAnnotation,
KonanProtoBuf.propertySetterAnnotation,
KonanProtoBuf.enumEntryAnnotation,
KonanProtoBuf.compileTimeValue,
KonanProtoBuf.parameterAnnotation,
KonanProtoBuf.typeAnnotation,
KonanProtoBuf.typeParameterAnnotation
)
@@ -1,85 +0,0 @@
/*
* Copyright 2010-2018 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.serialization.konan.impl
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
import org.jetbrains.kotlin.descriptors.konan.DeserializedKonanModuleOrigin
import org.jetbrains.kotlin.descriptors.konan.KonanModuleDescriptorFactory
import org.jetbrains.kotlin.konan.library.KonanLibrary
import org.jetbrains.kotlin.konan.library.resolver.PackageAccessedHandler
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.CompilerDeserializationConfiguration
import org.jetbrains.kotlin.serialization.konan.KonanDeserializedModuleDescriptorFactory
import org.jetbrains.kotlin.serialization.konan.KonanDeserializedPackageFragmentsFactory
import org.jetbrains.kotlin.storage.StorageManager
internal class KonanDeserializedModuleDescriptorFactoryImpl(
override val descriptorFactory: KonanModuleDescriptorFactory,
override val packageFragmentsFactory: KonanDeserializedPackageFragmentsFactory
) : KonanDeserializedModuleDescriptorFactory {
override fun createDescriptor(
library: KonanLibrary,
languageVersionSettings: LanguageVersionSettings,
storageManager: StorageManager,
builtIns: KotlinBuiltIns,
packageAccessedHandler: PackageAccessedHandler?,
customCapabilities: Map<ModuleDescriptor.Capability<*>, Any?>
) = createDescriptorOptionalBuiltIns(
library,
languageVersionSettings,
storageManager,
builtIns,
packageAccessedHandler,
customCapabilities
)
override fun createDescriptorAndNewBuiltIns(
library: KonanLibrary,
languageVersionSettings: LanguageVersionSettings,
storageManager: StorageManager,
packageAccessedHandler: PackageAccessedHandler?,
customCapabilities: Map<ModuleDescriptor.Capability<*>, Any?>
) = createDescriptorOptionalBuiltIns(library, languageVersionSettings, storageManager, null, packageAccessedHandler, customCapabilities)
private fun createDescriptorOptionalBuiltIns(
library: KonanLibrary,
languageVersionSettings: LanguageVersionSettings,
storageManager: StorageManager,
builtIns: KotlinBuiltIns?,
packageAccessedHandler: PackageAccessedHandler?,
customCapabilities: Map<ModuleDescriptor.Capability<*>, Any?>
): ModuleDescriptorImpl {
val libraryProto = library.moduleHeaderData
val moduleName = Name.special(libraryProto.moduleName)
val moduleOrigin = DeserializedKonanModuleOrigin(library)
val moduleDescriptor = if (builtIns != null)
descriptorFactory.createDescriptor(moduleName, storageManager, builtIns, moduleOrigin, customCapabilities)
else
descriptorFactory.createDescriptorAndNewBuiltIns(moduleName, storageManager, moduleOrigin, customCapabilities)
val deserializationConfiguration = CompilerDeserializationConfiguration(languageVersionSettings)
val provider = packageFragmentsFactory.createPackageFragmentProvider(
library,
packageAccessedHandler,
libraryProto.packageFragmentNameList,
storageManager,
moduleDescriptor,
deserializationConfiguration
)
moduleDescriptor.initialize(provider)
return moduleDescriptor
}
}
@@ -1,144 +0,0 @@
/*
* Copyright 2010-2018 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.serialization.konan.impl
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.impl.ClassDescriptorImpl
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
import org.jetbrains.kotlin.descriptors.impl.PackageFragmentDescriptorImpl
import org.jetbrains.kotlin.descriptors.konan.KonanModuleOrigin
import org.jetbrains.kotlin.descriptors.konan.SyntheticModulesOrigin
import org.jetbrains.kotlin.incremental.components.LookupLocation
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.konan.library.KonanLibrary
import org.jetbrains.kotlin.konan.library.resolver.KonanLibraryResolveResult
import org.jetbrains.kotlin.konan.library.resolver.PackageAccessedHandler
import org.jetbrains.kotlin.konan.util.profile
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
import org.jetbrains.kotlin.resolve.scopes.MemberScope
import org.jetbrains.kotlin.resolve.scopes.MemberScopeImpl
import org.jetbrains.kotlin.serialization.konan.KonanDeserializedModuleDescriptorFactory
import org.jetbrains.kotlin.serialization.konan.KonanResolvedModuleDescriptors
import org.jetbrains.kotlin.serialization.konan.KonanResolvedModuleDescriptorsFactory
import org.jetbrains.kotlin.storage.LockBasedStorageManager
import org.jetbrains.kotlin.storage.StorageManager
import org.jetbrains.kotlin.storage.getValue
import org.jetbrains.kotlin.utils.Printer
class KonanResolvedModuleDescriptorsFactoryImpl(
override val moduleDescriptorFactory: KonanDeserializedModuleDescriptorFactory
) : KonanResolvedModuleDescriptorsFactory {
override fun createResolved(
resolvedLibraries: KonanLibraryResolveResult,
storageManager: StorageManager,
builtIns: KotlinBuiltIns?,
languageVersionSettings: LanguageVersionSettings,
customAction: ((KonanLibrary, ModuleDescriptorImpl) -> Unit)?,
customCapabilitiesGenerator: ((KonanLibrary) -> Map<ModuleDescriptor.Capability<*>, Any?>)?
): KonanResolvedModuleDescriptors {
val moduleDescriptors = mutableListOf<ModuleDescriptorImpl>()
@Suppress("NAME_SHADOWING")
var builtIns = builtIns
// Build module descriptors.
resolvedLibraries.forEach { library, packageAccessedHandler ->
profile("Loading ${library.libraryName}") {
val customCapabilities = customCapabilitiesGenerator?.invoke(library) ?: emptyMap()
// MutableModuleContext needs ModuleDescriptorImpl, rather than ModuleDescriptor.
val moduleDescriptor = createDescriptorOptionalBuiltsIns(
library, languageVersionSettings, storageManager, builtIns, packageAccessedHandler, customCapabilities
)
builtIns = moduleDescriptor.builtIns
moduleDescriptors.add(moduleDescriptor)
customAction?.invoke(library, moduleDescriptor)
}
}
val forwardDeclarationsModule = createForwardDeclarationsModule(builtIns, storageManager)
// Set inter-dependencies between module descriptors, add forwarding declarations module.
for (module in moduleDescriptors) {
// Yes, just to all of them.
module.setDependencies(moduleDescriptors + forwardDeclarationsModule)
}
return KonanResolvedModuleDescriptors(moduleDescriptors, forwardDeclarationsModule)
}
private fun createForwardDeclarationsModule(
builtIns: KotlinBuiltIns?,
storageManager: StorageManager
): ModuleDescriptorImpl {
val name = Name.special("<forward declarations>")
val module = createDescriptorOptionalBuiltsIns(name, storageManager, builtIns, SyntheticModulesOrigin)
val packageFragmentProvider =
moduleDescriptorFactory.packageFragmentsFactory.createForwardDeclarationHackPackagePartProvider(storageManager, module)
module.initialize(packageFragmentProvider)
module.setDependencies(module)
return module
}
private fun createDescriptorOptionalBuiltsIns(
name: Name,
storageManager: StorageManager,
builtIns: KotlinBuiltIns?,
moduleOrigin: KonanModuleOrigin
) = if (builtIns != null)
moduleDescriptorFactory.descriptorFactory.createDescriptor(name, storageManager, builtIns, moduleOrigin)
else
moduleDescriptorFactory.descriptorFactory.createDescriptorAndNewBuiltIns(name, storageManager, moduleOrigin)
private fun createDescriptorOptionalBuiltsIns(
library: KonanLibrary,
languageVersionSettings: LanguageVersionSettings,
storageManager: StorageManager,
builtIns: KotlinBuiltIns?,
packageAccessedHandler: PackageAccessedHandler?,
customCapabilities: Map<ModuleDescriptor.Capability<*>, Any?>
) = if (builtIns != null)
moduleDescriptorFactory.createDescriptor(
library,
languageVersionSettings,
storageManager,
builtIns,
packageAccessedHandler,
customCapabilities
)
else
moduleDescriptorFactory.createDescriptorAndNewBuiltIns(
library,
languageVersionSettings,
storageManager,
packageAccessedHandler,
customCapabilities
)
}
// FIXME(ddol): decouple and move interop-specific logic back to Kotlin/Native.
internal object ForwardDeclarationsFqNames {
val packageName = FqName("kotlinx.cinterop")
val cNames = FqName("cnames")
val cNamesStructs = cNames.child(Name.identifier("structs"))
val objCNames = FqName("objcnames")
val objCNamesClasses = objCNames.child(Name.identifier("classes"))
val objCNamesProtocols = objCNames.child(Name.identifier("protocols"))
}
+2
View File
@@ -25,6 +25,7 @@ include ":kotlin-build-common",
":compiler:util", ":compiler:util",
":kotlin-util-io", ":kotlin-util-io",
":kotlin-util-klib", ":kotlin-util-klib",
":kotlin-util-klib-metadata",
":daemon-common", ":daemon-common",
":daemon-common-new", ":daemon-common-new",
":kotlin-daemon", ":kotlin-daemon",
@@ -336,6 +337,7 @@ project(':compiler:ir.serialization.common').projectDir = "$rootDir/compiler/ir/
project(':compiler:ir.serialization.js').projectDir = "$rootDir/compiler/ir/serialization.js" as File project(':compiler:ir.serialization.js').projectDir = "$rootDir/compiler/ir/serialization.js" as File
project(':kotlin-util-io').projectDir = "$rootDir/compiler/util-io" as File project(':kotlin-util-io').projectDir = "$rootDir/compiler/util-io" as File
project(':kotlin-util-klib').projectDir = "$rootDir/compiler/util-klib" as File project(':kotlin-util-klib').projectDir = "$rootDir/compiler/util-klib" as File
project(':kotlin-util-klib-metadata').projectDir = "$rootDir/compiler/util-klib-metadata" as File
project(':kotlin-native:kotlin-native-utils').projectDir = "$rootDir/konan/utils" as File project(':kotlin-native:kotlin-native-utils').projectDir = "$rootDir/konan/utils" as File
project(':kotlin-native:kotlin-native-library-reader').projectDir = "$rootDir/konan/library-reader" as File project(':kotlin-native:kotlin-native-library-reader').projectDir = "$rootDir/konan/library-reader" as File
project(':kotlin-native:commonizer').projectDir = "$rootDir/konan/commonizer" as File project(':kotlin-native:commonizer').projectDir = "$rootDir/konan/commonizer" as File