Commonizing klib metadata between native and js
This commit is contained in:
committed by
alexander-gorshenev
parent
f38123e78c
commit
c227c13799
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* 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.library.metadata;
|
||||
|
||||
import "core/metadata/src/metadata.proto";
|
||||
|
||||
option java_outer_classname = "KlibMetadataProtoBuf";
|
||||
option optimize_for = LITE_RUNTIME;
|
||||
|
||||
message Header {
|
||||
required string module_name = 1;
|
||||
/*
|
||||
0x1 = preRelease
|
||||
*/
|
||||
optional int32 flags = 2;
|
||||
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;
|
||||
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 {
|
||||
// If absent, id is the index of the file in the Files.file list
|
||||
optional int32 id = 1;
|
||||
required string name = 2;
|
||||
repeated org.jetbrains.kotlin.metadata.Annotation annotation = 3;
|
||||
}
|
||||
|
||||
message Files {
|
||||
repeated File file = 1;
|
||||
}
|
||||
|
||||
message DescriptorUniqId {
|
||||
required int64 index = 1;
|
||||
}
|
||||
|
||||
extend org.jetbrains.kotlin.metadata.Package {
|
||||
optional int32 package_fq_name = 171;
|
||||
}
|
||||
|
||||
extend org.jetbrains.kotlin.metadata.Class {
|
||||
repeated org.jetbrains.kotlin.metadata.Annotation class_annotation = 170;
|
||||
optional int32 class_file = 175;
|
||||
optional DescriptorUniqId class_uniq_id = 171;
|
||||
}
|
||||
|
||||
extend org.jetbrains.kotlin.metadata.Constructor {
|
||||
repeated org.jetbrains.kotlin.metadata.Annotation constructor_annotation = 170;
|
||||
optional DescriptorUniqId constructor_uniq_id = 172;
|
||||
}
|
||||
|
||||
extend org.jetbrains.kotlin.metadata.Function {
|
||||
repeated org.jetbrains.kotlin.metadata.Annotation function_annotation = 170;
|
||||
optional int32 function_file = 172;
|
||||
optional DescriptorUniqId function_uniq_id = 173;
|
||||
}
|
||||
|
||||
extend org.jetbrains.kotlin.metadata.Property {
|
||||
repeated org.jetbrains.kotlin.metadata.Annotation property_annotation = 170;
|
||||
repeated org.jetbrains.kotlin.metadata.Annotation property_getter_annotation = 177;
|
||||
repeated org.jetbrains.kotlin.metadata.Annotation property_setter_annotation = 178;
|
||||
optional org.jetbrains.kotlin.metadata.Annotation.Argument.Value compile_time_value = 173;
|
||||
optional int32 property_file = 176;
|
||||
optional DescriptorUniqId property_uniq_id = 179;
|
||||
}
|
||||
|
||||
extend org.jetbrains.kotlin.metadata.EnumEntry {
|
||||
repeated org.jetbrains.kotlin.metadata.Annotation enum_entry_annotation = 170;
|
||||
optional int32 enum_entry_ordinal = 171;
|
||||
optional DescriptorUniqId enum_entry_uniq_id = 172;
|
||||
}
|
||||
|
||||
extend org.jetbrains.kotlin.metadata.Type {
|
||||
repeated org.jetbrains.kotlin.metadata.Annotation type_annotation = 170;
|
||||
}
|
||||
|
||||
extend org.jetbrains.kotlin.metadata.TypeParameter {
|
||||
repeated org.jetbrains.kotlin.metadata.Annotation type_parameter_annotation = 170;
|
||||
optional DescriptorUniqId type_param_uniq_id = 171;
|
||||
}
|
||||
|
||||
extend org.jetbrains.kotlin.metadata.PackageFragment {
|
||||
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 {
|
||||
// TODO repeated org.jetbrains.kotlin.metadata.Annotation type_alias_annotation = 130;
|
||||
optional DescriptorUniqId type_alias_uniq_id = 131;
|
||||
}
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* 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.backend.common.serialization.metadata.KlibMetadataVersion
|
||||
import org.jetbrains.kotlin.descriptors.SourceElement
|
||||
import org.jetbrains.kotlin.library.metadata.KlibMetadataProtoBuf
|
||||
import org.jetbrains.kotlin.metadata.deserialization.NameResolver
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.serialization.deserialization.ClassData
|
||||
import org.jetbrains.kotlin.serialization.deserialization.ClassDataFinder
|
||||
import org.jetbrains.kotlin.serialization.deserialization.getClassId
|
||||
|
||||
class KlibMetadataClassDataFinder(
|
||||
private val fragment: org.jetbrains.kotlin.metadata.ProtoBuf.PackageFragment,
|
||||
private val nameResolver: NameResolver
|
||||
) : ClassDataFinder {
|
||||
val nameList = fragment.getExtension(KlibMetadataProtoBuf.className).orEmpty()
|
||||
|
||||
override fun findClassData(classId: ClassId): ClassData? {
|
||||
|
||||
val index = nameList.indexOfFirst { nameResolver.getClassId(it) == classId }
|
||||
if (index == -1) {
|
||||
return null
|
||||
}
|
||||
|
||||
val foundClass = fragment.getClass_(index) ?: error("Could not find data for serialized class $classId")
|
||||
|
||||
/* TODO: binary version supposed to be read from protobuf. */
|
||||
return ClassData(nameResolver, foundClass, KlibMetadataVersion.INSTANCE, SourceElement.NO_SOURCE)
|
||||
}
|
||||
}
|
||||
+30
@@ -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
|
||||
|
||||
+24
@@ -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>
|
||||
}
|
||||
+62
@@ -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)
|
||||
}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* 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.backend.common.serialization.metadata
|
||||
|
||||
import org.jetbrains.kotlin.metadata.deserialization.BinaryVersion
|
||||
|
||||
class KlibMetadataVersion(vararg numbers: Int) : BinaryVersion(*numbers) {
|
||||
|
||||
override fun isCompatible(): Boolean = this.major == 1 && this.minor == 0
|
||||
|
||||
companion object {
|
||||
@JvmField
|
||||
val INSTANCE = KlibMetadataVersion(1, 0, 0)
|
||||
|
||||
@JvmField
|
||||
val INVALID_VERSION = KlibMetadataVersion()
|
||||
}
|
||||
}
|
||||
+59
@@ -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
|
||||
}
|
||||
+92
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* 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.backend.common.serialization.metadata.KlibMetadataVersion
|
||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||
import org.jetbrains.kotlin.library.KotlinLibrary
|
||||
import org.jetbrains.kotlin.metadata.ProtoBuf
|
||||
import org.jetbrains.kotlin.metadata.deserialization.NameResolverImpl
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.serialization.deserialization.DeserializationComponents
|
||||
import org.jetbrains.kotlin.serialization.deserialization.DeserializedPackageFragment
|
||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedPackageMemberScope
|
||||
import org.jetbrains.kotlin.serialization.deserialization.getClassId
|
||||
import org.jetbrains.kotlin.serialization.deserialization.getName
|
||||
import org.jetbrains.kotlin.storage.StorageManager
|
||||
|
||||
class KlibMetadataPackageFragment(
|
||||
fqName: FqName,
|
||||
private val library: KotlinLibrary,
|
||||
private val packageAccessHandler: PackageAccessHandler?,
|
||||
storageManager: StorageManager,
|
||||
module: ModuleDescriptor,
|
||||
private val partName: String
|
||||
) : DeserializedPackageFragment(fqName, storageManager, module) {
|
||||
|
||||
lateinit var components: DeserializationComponents
|
||||
|
||||
override fun initialize(components: DeserializationComponents) {
|
||||
this.components = components
|
||||
}
|
||||
|
||||
// The proto field is lazy so that we can load only needed
|
||||
// packages from the library.
|
||||
private val protoForNames: ProtoBuf.PackageFragment by lazy {
|
||||
(packageAccessHandler ?: SimplePackageAccessHandler).loadPackageFragment(library, fqName.asString(), partName)
|
||||
}
|
||||
|
||||
// TODO: Do we really need both 'protoForNames' and 'proto' today?
|
||||
val proto: ProtoBuf.PackageFragment
|
||||
get() = protoForNames
|
||||
|
||||
private val nameResolver by lazy {
|
||||
NameResolverImpl(protoForNames.strings, protoForNames.qualifiedNames)
|
||||
}
|
||||
|
||||
override val classDataFinder by lazy {
|
||||
KlibMetadataClassDataFinder(proto, nameResolver)
|
||||
}
|
||||
|
||||
private val _memberScope by lazy {
|
||||
/* TODO: we fake proto binary versioning for now. */
|
||||
DeserializedPackageMemberScope(
|
||||
this,
|
||||
proto.getPackage(),
|
||||
nameResolver,
|
||||
KlibMetadataVersion.INSTANCE,
|
||||
/* containerSource = */ null,
|
||||
components
|
||||
) {
|
||||
loadClassNames()
|
||||
}
|
||||
}
|
||||
|
||||
override fun getMemberScope(): DeserializedPackageMemberScope = _memberScope
|
||||
|
||||
private val classifierNames: Set<Name> by lazy {
|
||||
val result = mutableSetOf<Name>()
|
||||
result.addAll(loadClassNames())
|
||||
protoForNames.getPackage().typeAliasList.mapTo(result) { nameResolver.getName(it.name) }
|
||||
result
|
||||
}
|
||||
|
||||
fun hasTopLevelClassifier(name: Name): Boolean = name in classifierNames
|
||||
|
||||
private fun loadClassNames(): Collection<Name> {
|
||||
|
||||
val classNameList = protoForNames.getExtension(KlibMetadataProtoBuf.className).orEmpty()
|
||||
|
||||
val names = classNameList.mapNotNull {
|
||||
val classId = nameResolver.getClassId(it)
|
||||
val shortName = classId.shortClassName
|
||||
if (!classId.isNestedClass) shortName else null
|
||||
}
|
||||
|
||||
return names
|
||||
}
|
||||
}
|
||||
+3581
File diff suppressed because it is too large
Load Diff
+25
@@ -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
|
||||
)
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* 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.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ClassifierDescriptorWithTypeParameters
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.classId
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.getAllSuperClassifiers
|
||||
import org.jetbrains.kotlin.serialization.StringTableImpl
|
||||
|
||||
class KlibMetadataStringTable : StringTableImpl() {
|
||||
override fun getLocalClassIdReplacement(descriptor: ClassifierDescriptorWithTypeParameters): ClassId? {
|
||||
return if (descriptor.containingDeclaration is CallableMemberDescriptor) {
|
||||
val superClassifiers = descriptor.getAllSuperClassifiers()
|
||||
.mapNotNull { it as ClassifierDescriptorWithTypeParameters }
|
||||
.filter { it != descriptor }
|
||||
.toList()
|
||||
if (superClassifiers.size == 1) {
|
||||
superClassifiers[0].classId
|
||||
} else {
|
||||
val superClass = superClassifiers.find { !DescriptorUtils.isInterface(it) }
|
||||
superClass?.classId ?: ClassId.topLevel(KotlinBuiltIns.FQ_NAMES.any.toSafe())
|
||||
}
|
||||
} else {
|
||||
super.getLocalClassIdReplacement(descriptor)
|
||||
}
|
||||
}
|
||||
}
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* 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.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.storage.StorageManager
|
||||
|
||||
interface KlibModuleDescriptorFactory {
|
||||
|
||||
/**
|
||||
* Base method for creation of any Kotlin/Native [ModuleDescriptor].
|
||||
*/
|
||||
fun createDescriptor(
|
||||
name: Name,
|
||||
storageManager: StorageManager,
|
||||
builtIns: KotlinBuiltIns,
|
||||
origin: KlibModuleOrigin,
|
||||
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(
|
||||
name: Name,
|
||||
storageManager: StorageManager,
|
||||
origin: KlibModuleOrigin,
|
||||
customCapabilities: Map<ModuleDescriptor.Capability<*>, Any?> = emptyMap()
|
||||
): ModuleDescriptorImpl
|
||||
}
|
||||
+36
@@ -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
|
||||
+50
@@ -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
|
||||
)
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* 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.ProtoBuf
|
||||
import org.jetbrains.kotlin.serialization.deserialization.FlexibleTypeDeserializer
|
||||
import org.jetbrains.kotlin.types.SimpleType
|
||||
|
||||
object NullFlexibleTypeDeserializer : FlexibleTypeDeserializer {
|
||||
|
||||
override fun create(
|
||||
proto: ProtoBuf.Type,
|
||||
flexibleId: String,
|
||||
lowerBound: SimpleType,
|
||||
upperBound: SimpleType
|
||||
) = error("Illegal use of flexible type deserializer.")
|
||||
}
|
||||
+54
@@ -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()
|
||||
}
|
||||
}
|
||||
+190
@@ -0,0 +1,190 @@
|
||||
package org.jetbrains.kotlin.backend.common.serialization.metadata.impl
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.serialization.metadata.KlibMetadataDeserializedPackageFragmentsFactory
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.impl.ClassDescriptorImpl
|
||||
import org.jetbrains.kotlin.descriptors.impl.PackageFragmentDescriptorImpl
|
||||
import org.jetbrains.kotlin.incremental.components.LookupLocation
|
||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||
import org.jetbrains.kotlin.library.*
|
||||
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.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.impl.ForwardDeclarationsFqNames
|
||||
import org.jetbrains.kotlin.storage.LockBasedStorageManager
|
||||
import org.jetbrains.kotlin.storage.StorageManager
|
||||
import org.jetbrains.kotlin.storage.getValue
|
||||
import org.jetbrains.kotlin.utils.Printer
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult
|
||||
|
||||
// FIXME(ddol): decouple and move interop-specific logic back to Kotlin/Native.
|
||||
open class KlibMetadataDeserializedPackageFragmentsFactoryImpl: KlibMetadataDeserializedPackageFragmentsFactory {
|
||||
|
||||
override fun createDeserializedPackageFragments(
|
||||
library: KotlinLibrary,
|
||||
packageFragmentNames: List<String>,
|
||||
moduleDescriptor: ModuleDescriptor,
|
||||
packageAccessedHandler: PackageAccessHandler?,
|
||||
storageManager: StorageManager
|
||||
) = packageFragmentNames.flatMap {
|
||||
val fqName = FqName(it)
|
||||
val parts = library.packageMetadataParts(fqName.asString())
|
||||
parts.map { partName ->
|
||||
KlibMetadataPackageFragment(fqName, library, packageAccessedHandler, storageManager, moduleDescriptor, partName)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
override fun createSyntheticPackageFragments(
|
||||
library: KotlinLibrary,
|
||||
deserializedPackageFragments: List<KlibMetadataPackageFragment>,
|
||||
moduleDescriptor: ModuleDescriptor
|
||||
): List<PackageFragmentDescriptor> {
|
||||
|
||||
if (!library.isInterop) return emptyList()
|
||||
|
||||
val mainPackageFqName = library.packageFqName?. let{ FqName(it) }
|
||||
?: error("Inconsistent manifest: interop library ${library.libraryName} should have `package` specified")
|
||||
val exportForwardDeclarations = library.exportForwardDeclarations.map{ FqName(it) }
|
||||
|
||||
val aliasedPackageFragments = deserializedPackageFragments.filter { it.fqName == mainPackageFqName }
|
||||
|
||||
val result = mutableListOf<PackageFragmentDescriptor>()
|
||||
listOf(
|
||||
ForwardDeclarationsFqNames.cNamesStructs,
|
||||
ForwardDeclarationsFqNames.objCNamesClasses,
|
||||
ForwardDeclarationsFqNames.objCNamesProtocols
|
||||
).mapTo(result) { fqName ->
|
||||
ClassifierAliasingPackageFragmentDescriptor(aliasedPackageFragments, moduleDescriptor, fqName)
|
||||
}
|
||||
|
||||
result.add(ExportedForwardDeclarationsPackageFragmentDescriptor(moduleDescriptor, mainPackageFqName, exportForwardDeclarations))
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* The package fragment to export forward declarations from interop package namespace, i.e.
|
||||
* redirect "$pkg.$name" to e.g. "cnames.structs.$name".
|
||||
*/
|
||||
class ExportedForwardDeclarationsPackageFragmentDescriptor(
|
||||
module: ModuleDescriptor,
|
||||
fqName: FqName,
|
||||
declarations: List<FqName>
|
||||
) : PackageFragmentDescriptorImpl(module, fqName) {
|
||||
|
||||
private val memberScope = object : MemberScopeImpl() {
|
||||
|
||||
private val nameToFqName = declarations.map { it.shortName() to it }.toMap()
|
||||
|
||||
override fun getContributedClassifier(name: Name, location: LookupLocation): ClassifierDescriptor? {
|
||||
val declFqName = nameToFqName[name] ?: return null
|
||||
|
||||
val packageView = module.getPackage(declFqName.parent())
|
||||
return packageView.memberScope.getContributedClassifier(name, location) // ?: FIXME(ddol): delegate to forward declarations synthetic module!
|
||||
}
|
||||
|
||||
override fun printScopeStructure(p: Printer) {
|
||||
p.println(this::class.java.simpleName, " {")
|
||||
p.pushIndent()
|
||||
|
||||
p.println("declarations = $declarations")
|
||||
|
||||
p.popIndent()
|
||||
p.println("}")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
override fun getMemberScope() = memberScope
|
||||
}
|
||||
|
||||
/**
|
||||
* The package fragment that redirects all requests for classifier lookup to its targets.
|
||||
*/
|
||||
class ClassifierAliasingPackageFragmentDescriptor(
|
||||
targets: List<KlibMetadataPackageFragment>,
|
||||
module: ModuleDescriptor,
|
||||
fqName: FqName
|
||||
) : PackageFragmentDescriptorImpl(module, fqName) {
|
||||
|
||||
private val memberScope = object : MemberScopeImpl() {
|
||||
|
||||
override fun getContributedClassifier(name: Name, location: LookupLocation) =
|
||||
targets.firstNotNullResult {
|
||||
if (it.hasTopLevelClassifier(name)) {
|
||||
it.getMemberScope().getContributedClassifier(name, location)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
override fun printScopeStructure(p: Printer) {
|
||||
p.println(this::class.java.simpleName, " {")
|
||||
p.pushIndent()
|
||||
|
||||
p.println("targets = $targets")
|
||||
|
||||
p.popIndent()
|
||||
p.println("}")
|
||||
}
|
||||
}
|
||||
|
||||
override fun getMemberScope(): MemberScope = memberScope
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Package fragment which creates descriptors for forward declarations on demand.
|
||||
*/
|
||||
private 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
|
||||
}
|
||||
|
||||
+155
@@ -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
|
||||
}
|
||||
}
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* 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.impl
|
||||
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
|
||||
import org.jetbrains.kotlin.descriptors.konan.*
|
||||
import org.jetbrains.kotlin.descriptors.konan.isInteropLibrary
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.ImplicitIntegerCoercion
|
||||
import org.jetbrains.kotlin.storage.StorageManager
|
||||
|
||||
internal class KlibModuleDescriptorFactoryImpl(val createBuiltIns: (StorageManager) -> KotlinBuiltIns) : KlibModuleDescriptorFactory {
|
||||
|
||||
override fun createDescriptor(
|
||||
name: Name,
|
||||
storageManager: StorageManager,
|
||||
builtIns: KotlinBuiltIns,
|
||||
origin: KlibModuleOrigin,
|
||||
customCapabilities: Map<ModuleDescriptor.Capability<*>, Any?>
|
||||
) = ModuleDescriptorImpl(
|
||||
name,
|
||||
storageManager,
|
||||
builtIns,
|
||||
capabilities = customCapabilities + mapOf(
|
||||
KlibModuleOrigin.CAPABILITY to origin,
|
||||
ImplicitIntegerCoercion.MODULE_CAPABILITY to origin.isInteropLibrary()
|
||||
)
|
||||
)
|
||||
|
||||
override fun createDescriptorAndNewBuiltIns(
|
||||
name: Name,
|
||||
storageManager: StorageManager,
|
||||
origin: KlibModuleOrigin,
|
||||
customCapabilities: Map<ModuleDescriptor.Capability<*>, Any?>
|
||||
): ModuleDescriptorImpl {
|
||||
|
||||
val builtIns = createBuiltIns(storageManager)
|
||||
|
||||
val moduleDescriptor = createDescriptor(name, storageManager, builtIns, origin, customCapabilities)
|
||||
builtIns.builtInsModule = moduleDescriptor
|
||||
|
||||
return moduleDescriptor
|
||||
}
|
||||
}
|
||||
+183
@@ -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"))
|
||||
}
|
||||
+56
@@ -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
|
||||
}
|
||||
+23
@@ -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
|
||||
}
|
||||
+156
@@ -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"
|
||||
}
|
||||
+38
@@ -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() }}"
|
||||
}
|
||||
Reference in New Issue
Block a user