[Commonizer] Drop support of descriptors, part 1

This commit is contained in:
Dmitriy Dolovov
2021-03-04 00:24:21 +03:00
parent eddeef1d51
commit e96dd3b301
20 changed files with 38 additions and 667 deletions
@@ -5,7 +5,6 @@
package org.jetbrains.kotlin.descriptors.commonizer
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.library.SerializedMetadata
import java.io.File
@@ -36,7 +35,4 @@ interface ModulesProvider {
* Loads metadata for the specified module.
*/
fun loadModuleMetadata(name: String): SerializedMetadata
@Deprecated("To be replaced by loadModuleMetadata()")
fun loadModules(dependencies: Collection<ModuleDescriptor>): Map<String, ModuleDescriptor>
}
@@ -5,18 +5,22 @@
package org.jetbrains.kotlin.descriptors.commonizer.cir
import org.jetbrains.kotlin.descriptors.*
import kotlinx.metadata.*
import kotlinx.metadata.klib.KlibModuleMetadata
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.DescriptorVisibility
import org.jetbrains.kotlin.descriptors.Modality
/**
* An intermediate representation of [DeclarationDescriptor]s for commonization purposes.
* An intermediate representation of declarations for commonization purposes.
*
* The most essential subclasses are:
* - [CirClass] - represents [ClassDescriptor]
* - [CirTypeAlias] - [TypeAliasDescriptor]
* - [CirFunction] - [SimpleFunctionDescriptor]
* - [CirProperty] - [PropertyDescriptor]
* - [CirPackage] - union of multiple [PackageFragmentDescriptor]s with the same FQ name contributed by commonized [ModuleDescriptor]s
* - [CirModule] - [ModuleDescriptor]
* - [CirClass] - represents [KmClass]
* - [CirTypeAlias] - [KmTypeAlias]
* - [CirFunction] - [KmFunction]
* - [CirProperty] - [KmProperty]
* - [CirPackage] - union of multiple [KmModuleFragment]s with the same FQ name contributed by commonized [KlibModuleMetadata]s
* - [CirModule] - [KlibModuleMetadata]
* - [CirRoot] - the root of the whole Commonizer IR tree
*/
interface CirDeclaration
@@ -5,7 +5,7 @@
package org.jetbrains.kotlin.descriptors.commonizer.cir
import org.jetbrains.kotlin.types.AbbreviatedType
import kotlinx.metadata.KmType
import org.jetbrains.kotlin.types.Variance
typealias CirTypeSignature = String
@@ -83,7 +83,7 @@ abstract class CirClassType : CirClassOrTypeAliasType(), CirHasVisibility {
}
/**
* All attributes are read from the abbreviation type: [AbbreviatedType.abbreviation].
* All attributes are read from the abbreviation type: [KmType.abbreviatedType].
*
* This is necessary to properly compare types for type aliases, where abbreviation type represents the type alias itself while
* expanded type represents right-hand side declaration that should be processed separately.
@@ -8,35 +8,13 @@ package org.jetbrains.kotlin.descriptors.commonizer.cir.factory
import kotlinx.metadata.Flag
import kotlinx.metadata.KmConstructor
import kotlinx.metadata.klib.annotations
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
import org.jetbrains.kotlin.descriptors.ClassConstructorDescriptor
import org.jetbrains.kotlin.descriptors.DescriptorVisibility
import org.jetbrains.kotlin.descriptors.commonizer.cir.*
import org.jetbrains.kotlin.descriptors.commonizer.cir.impl.CirClassConstructorImpl
import org.jetbrains.kotlin.descriptors.commonizer.metadata.decodeVisibility
import org.jetbrains.kotlin.descriptors.commonizer.utils.compactMap
import org.jetbrains.kotlin.descriptors.commonizer.utils.compactMapNotNull
object CirClassConstructorFactory {
fun create(source: ClassConstructorDescriptor, containingClass: CirContainingClass): CirClassConstructor {
check(source.kind == CallableMemberDescriptor.Kind.DECLARATION) {
"Unexpected ${CallableMemberDescriptor.Kind::class.java} for class constructor $source, ${source::class.java}: ${source.kind}"
}
return create(
annotations = source.annotations.compactMap(CirAnnotationFactory::create),
typeParameters = source.typeParameters.compactMapNotNull { typeParameter ->
// save only type parameters that are contributed by the constructor itself
typeParameter.takeIf { it.containingDeclaration == source }?.let(CirTypeParameterFactory::create)
},
visibility = source.visibility,
containingClass = containingClass,
valueParameters = source.valueParameters.compactMap(CirValueParameterFactory::create),
hasStableParameterNames = source.hasStableParameterNames(),
isPrimary = source.isPrimary
)
}
fun create(source: KmConstructor, containingClass: CirContainingClass, typeResolver: CirTypeResolver): CirClassConstructor {
return create(
annotations = CirAnnotationFactory.createAnnotations(source.flags, typeResolver, source::annotations),
@@ -6,19 +6,12 @@
package org.jetbrains.kotlin.descriptors.commonizer.cir.factory
import kotlinx.metadata.KmType
import org.jetbrains.kotlin.descriptors.ReceiverParameterDescriptor
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirAnnotation
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirExtensionReceiver
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirType
import org.jetbrains.kotlin.descriptors.commonizer.cir.impl.CirExtensionReceiverImpl
import org.jetbrains.kotlin.descriptors.commonizer.utils.compactMap
object CirExtensionReceiverFactory {
fun create(source: ReceiverParameterDescriptor): CirExtensionReceiver = create(
annotations = source.annotations.compactMap(CirAnnotationFactory::create),
type = CirTypeFactory.create(source.type)
)
fun create(receiverParameterType: KmType, typeResolver: CirTypeResolver): CirExtensionReceiver = create(
annotations = emptyList(), // TODO nowhere to read receiver annotations from, see KT-42490
type = CirTypeFactory.create(receiverParameterType, typeResolver)
@@ -8,7 +8,9 @@ package org.jetbrains.kotlin.descriptors.commonizer.cir.factory
import kotlinx.metadata.Flag
import kotlinx.metadata.KmFunction
import kotlinx.metadata.klib.annotations
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
import org.jetbrains.kotlin.descriptors.DescriptorVisibility
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.commonizer.cir.*
import org.jetbrains.kotlin.descriptors.commonizer.cir.impl.CirFunctionImpl
import org.jetbrains.kotlin.descriptors.commonizer.metadata.decodeCallableKind
@@ -17,21 +19,6 @@ import org.jetbrains.kotlin.descriptors.commonizer.metadata.decodeVisibility
import org.jetbrains.kotlin.descriptors.commonizer.utils.compactMap
object CirFunctionFactory {
fun create(source: SimpleFunctionDescriptor, containingClass: CirContainingClass?): CirFunction = create(
annotations = source.annotations.compactMap(CirAnnotationFactory::create),
name = CirName.create(source.name),
typeParameters = source.typeParameters.compactMap(CirTypeParameterFactory::create),
visibility = source.visibility,
modality = source.modality,
containingClass = containingClass,
valueParameters = source.valueParameters.compactMap(CirValueParameterFactory::create),
hasStableParameterNames = source.hasStableParameterNames(),
extensionReceiver = source.extensionReceiverParameter?.let(CirExtensionReceiverFactory::create),
returnType = CirTypeFactory.create(source.returnType!!),
kind = source.kind,
modifiers = CirFunctionModifiersFactory.create(source),
)
fun create(name: CirName, source: KmFunction, containingClass: CirContainingClass?, typeResolver: CirTypeResolver): CirFunction {
return create(
annotations = CirAnnotationFactory.createAnnotations(source.flags, typeResolver, source::annotations),
@@ -7,7 +7,6 @@ package org.jetbrains.kotlin.descriptors.commonizer.cir.factory
import kotlinx.metadata.Flag
import kotlinx.metadata.KmFunction
import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirFunctionModifiers
import org.jetbrains.kotlin.descriptors.commonizer.cir.impl.CirFunctionModifiersImpl
import org.jetbrains.kotlin.descriptors.commonizer.utils.Interner
@@ -15,15 +14,6 @@ import org.jetbrains.kotlin.descriptors.commonizer.utils.Interner
object CirFunctionModifiersFactory {
private val interner = Interner<CirFunctionModifiers>()
fun create(source: SimpleFunctionDescriptor): CirFunctionModifiers = create(
isOperator = source.isOperator,
isInfix = source.isInfix,
isInline = source.isInline,
isTailrec = source.isTailrec,
isSuspend = source.isSuspend,
isExternal = source.isExternal
)
fun create(source: KmFunction): CirFunctionModifiers = create(
isOperator = Flag.Function.IS_OPERATOR(source.flags),
isInfix = Flag.Function.IS_INFIX(source.flags),
@@ -12,7 +12,6 @@ import kotlinx.metadata.klib.compileTimeValue
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
import org.jetbrains.kotlin.descriptors.DescriptorVisibility
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
import org.jetbrains.kotlin.descriptors.commonizer.cir.*
import org.jetbrains.kotlin.descriptors.commonizer.cir.impl.CirPropertyImpl
import org.jetbrains.kotlin.descriptors.commonizer.metadata.decodeCallableKind
@@ -21,37 +20,6 @@ import org.jetbrains.kotlin.descriptors.commonizer.metadata.decodeVisibility
import org.jetbrains.kotlin.descriptors.commonizer.utils.compactMap
object CirPropertyFactory {
fun create(source: PropertyDescriptor, containingClass: CirContainingClass?): CirProperty {
val compileTimeInitializer = source.compileTimeInitializer?.let { constantValue ->
CirConstantValueFactory.createSafely(
constantValue = constantValue,
owner = source,
)
} ?: CirConstantValue.NullValue
return create(
annotations = source.annotations.compactMap(CirAnnotationFactory::create),
name = CirName.create(source.name),
typeParameters = source.typeParameters.compactMap(CirTypeParameterFactory::create),
visibility = source.visibility,
modality = source.modality,
containingClass = containingClass,
isExternal = source.isExternal,
extensionReceiver = source.extensionReceiverParameter?.let(CirExtensionReceiverFactory::create),
returnType = CirTypeFactory.create(source.returnType!!),
kind = source.kind,
isVar = source.isVar,
isLateInit = source.isLateInit,
isConst = source.isConst,
isDelegate = source.isDelegated,
getter = source.getter?.let(CirPropertyGetterFactory::create),
setter = source.setter?.let(CirPropertySetterFactory::create),
backingFieldAnnotations = source.backingField?.annotations?.compactMap(CirAnnotationFactory::create).orEmpty(),
delegateFieldAnnotations = source.delegateField?.annotations?.compactMap(CirAnnotationFactory::create).orEmpty(),
compileTimeInitializer = compileTimeInitializer
)
}
fun create(name: CirName, source: KmProperty, containingClass: CirContainingClass?, typeResolver: CirTypeResolver): CirProperty {
val compileTimeInitializer = if (Flag.Property.HAS_CONSTANT(source.flags)) {
CirConstantValueFactory.createSafely(
@@ -8,12 +8,10 @@ package org.jetbrains.kotlin.descriptors.commonizer.cir.factory
import kotlinx.metadata.Flag
import kotlinx.metadata.KmProperty
import kotlinx.metadata.klib.getterAnnotations
import org.jetbrains.kotlin.descriptors.PropertyGetterDescriptor
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirAnnotation
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirPropertyGetter
import org.jetbrains.kotlin.descriptors.commonizer.cir.impl.CirPropertyGetterImpl
import org.jetbrains.kotlin.descriptors.commonizer.utils.Interner
import org.jetbrains.kotlin.descriptors.commonizer.utils.compactMap
object CirPropertyGetterFactory {
private val interner = Interner<CirPropertyGetter>()
@@ -26,18 +24,6 @@ object CirPropertyGetterFactory {
isInline = false
)
fun create(source: PropertyGetterDescriptor): CirPropertyGetter {
return if (source.isDefault && source.annotations.isEmpty())
DEFAULT_NO_ANNOTATIONS
else
create(
annotations = source.annotations.compactMap(CirAnnotationFactory::create),
isDefault = source.isDefault,
isExternal = source.isExternal,
isInline = source.isInline
)
}
fun create(source: KmProperty, typeResolver: CirTypeResolver): CirPropertyGetter? {
if (!Flag.Property.HAS_GETTER(source.flags))
return null
@@ -9,7 +9,6 @@ import kotlinx.metadata.Flag
import kotlinx.metadata.KmProperty
import kotlinx.metadata.klib.annotations
import kotlinx.metadata.klib.setterAnnotations
import org.jetbrains.kotlin.descriptors.PropertySetterDescriptor
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
import org.jetbrains.kotlin.descriptors.DescriptorVisibility
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirAnnotation
@@ -17,20 +16,10 @@ import org.jetbrains.kotlin.descriptors.commonizer.cir.CirPropertySetter
import org.jetbrains.kotlin.descriptors.commonizer.cir.impl.CirPropertySetterImpl
import org.jetbrains.kotlin.descriptors.commonizer.metadata.decodeVisibility
import org.jetbrains.kotlin.descriptors.commonizer.utils.Interner
import org.jetbrains.kotlin.descriptors.commonizer.utils.compactMap
object CirPropertySetterFactory {
private val interner = Interner<CirPropertySetter>()
fun create(source: PropertySetterDescriptor): CirPropertySetter = create(
annotations = source.annotations.compactMap(CirAnnotationFactory::create),
parameterAnnotations = source.valueParameters[0].annotations.compactMap(CirAnnotationFactory::create),
visibility = source.visibility,
isDefault = source.isDefault,
isExternal = source.isExternal,
isInline = source.isInline
)
fun create(source: KmProperty, typeResolver: CirTypeResolver): CirPropertySetter? {
if (!Flag.Property.HAS_SETTER(source.flags))
return null
@@ -8,28 +8,16 @@ package org.jetbrains.kotlin.descriptors.commonizer.cir.factory
import kotlinx.metadata.Flag
import kotlinx.metadata.KmValueParameter
import kotlinx.metadata.klib.annotations
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirAnnotation
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirName
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirType
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirValueParameter
import org.jetbrains.kotlin.descriptors.commonizer.cir.impl.CirValueParameterImpl
import org.jetbrains.kotlin.descriptors.commonizer.utils.Interner
import org.jetbrains.kotlin.descriptors.commonizer.utils.compactMap
object CirValueParameterFactory {
private val interner = Interner<CirValueParameter>()
fun create(source: ValueParameterDescriptor): CirValueParameter = create(
annotations = source.annotations.compactMap(CirAnnotationFactory::create),
name = CirName.create(source.name),
returnType = CirTypeFactory.create(source.returnType!!),
varargElementType = source.varargElementType?.let(CirTypeFactory::create),
declaresDefaultValue = source.declaresDefaultValue(),
isCrossinline = source.isCrossinline,
isNoinline = source.isNoinline
)
fun create(source: KmValueParameter, typeResolver: CirTypeResolver): CirValueParameter = create(
annotations = CirAnnotationFactory.createAnnotations(source.flags, typeResolver, source::annotations),
name = CirName.create(source.name),
@@ -6,13 +6,11 @@
package org.jetbrains.kotlin.descriptors.commonizer.konan
import org.jetbrains.kotlin.descriptors.commonizer.*
import org.jetbrains.kotlin.descriptors.commonizer.LeafCommonizerTarget
import org.jetbrains.kotlin.descriptors.commonizer.konan.LibraryCommonizer.*
import org.jetbrains.kotlin.descriptors.commonizer.repository.Repository
import org.jetbrains.kotlin.descriptors.commonizer.stats.StatsCollector
import org.jetbrains.kotlin.descriptors.commonizer.utils.ProgressLogger
import org.jetbrains.kotlin.konan.library.*
import org.jetbrains.kotlin.storage.LockBasedStorageManager
internal class LibraryCommonizer internal constructor(
private val konanDistribution: KonanDistribution,
@@ -52,15 +50,14 @@ internal class LibraryCommonizer internal constructor(
val manifestProvider = TargetedNativeManifestDataProvider(allLibraries)
val parameters = CommonizerParameters(resultsConsumer, manifestProvider, statsCollector, progressLogger::log).apply {
val storageManager = LockBasedStorageManager("Commonized modules")
dependencyModulesProvider = NativeDistributionModulesProvider.forStandardLibrary(storageManager, allLibraries.stdlib)
dependencyModulesProvider = NativeDistributionModulesProvider.forStandardLibrary(allLibraries.stdlib)
allLibraries.librariesByTargets.forEach { (target, librariesToCommonize) ->
if (librariesToCommonize.libraries.isEmpty()) return@forEach
val modulesProvider = NativeDistributionModulesProvider.platformLibraries(storageManager, librariesToCommonize)
val modulesProvider = NativeDistributionModulesProvider.platformLibraries(librariesToCommonize)
val dependencyModuleProvider = NativeDistributionModulesProvider.platformLibraries(
storageManager, NativeLibrariesToCommonize(dependencies.getLibraries(target).toList()),
NativeLibrariesToCommonize(dependencies.getLibraries(target).toList()),
)
addTarget(
@@ -11,7 +11,6 @@ import org.jetbrains.kotlin.library.impl.BaseWriterImpl
import org.jetbrains.kotlin.library.impl.BuiltInsPlatform
import org.jetbrains.kotlin.library.impl.KotlinLibraryLayoutForWriter
import org.jetbrains.kotlin.library.impl.KotlinLibraryWriterImpl
import org.jetbrains.kotlin.util.Logger
import java.io.File
internal class ModuleSerializer(
@@ -5,24 +5,15 @@
package org.jetbrains.kotlin.descriptors.commonizer.konan
import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.descriptors.commonizer.ModulesProvider
import org.jetbrains.kotlin.descriptors.commonizer.ModulesProvider.CInteropModuleAttributes
import org.jetbrains.kotlin.descriptors.commonizer.ModulesProvider.ModuleInfo
import org.jetbrains.kotlin.descriptors.commonizer.utils.NativeFactories
import org.jetbrains.kotlin.descriptors.commonizer.utils.createKotlinNativeForwardDeclarationsModule
import org.jetbrains.kotlin.descriptors.commonizer.utils.strip
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
import org.jetbrains.kotlin.incremental.components.LookupTracker
import org.jetbrains.kotlin.konan.library.KONAN_STDLIB_NAME
import org.jetbrains.kotlin.library.SerializedMetadata
import org.jetbrains.kotlin.library.metadata.parseModuleHeader
import org.jetbrains.kotlin.storage.StorageManager
import org.jetbrains.kotlin.utils.addIfNotNull
import java.io.File
internal abstract class NativeDistributionModulesProvider(libraries: Collection<NativeLibrary>) : ModulesProvider {
internal class NativeDistributionModulesProvider(libraries: Collection<NativeLibrary>) : ModulesProvider {
internal class NativeModuleInfo(
name: String,
originalLocation: File,
@@ -30,8 +21,8 @@ internal abstract class NativeDistributionModulesProvider(libraries: Collection<
cInteropAttributes: CInteropModuleAttributes?
) : ModuleInfo(name, originalLocation, cInteropAttributes)
protected val libraryMap: Map<String, NativeLibrary>
protected val moduleInfoMap: Map<String, NativeModuleInfo>
private val libraryMap: Map<String, NativeLibrary>
private val moduleInfoMap: Map<String, NativeModuleInfo>
init {
val libraryMap = mutableMapOf<String, NativeLibrary>()
@@ -56,9 +47,9 @@ internal abstract class NativeDistributionModulesProvider(libraries: Collection<
this.moduleInfoMap = moduleInfoMap
}
final override fun loadModuleInfos(): Collection<ModuleInfo> = moduleInfoMap.values
override fun loadModuleInfos(): Collection<ModuleInfo> = moduleInfoMap.values
final override fun loadModuleMetadata(name: String): SerializedMetadata {
override fun loadModuleMetadata(name: String): SerializedMetadata {
val library = libraryMap[name]?.library ?: error("No such library: $name")
val moduleHeader = library.moduleHeaderData
@@ -76,77 +67,12 @@ internal abstract class NativeDistributionModulesProvider(libraries: Collection<
}
companion object {
fun forStandardLibrary(
storageManager: StorageManager,
stdlib: NativeLibrary
): ModulesProvider {
fun forStandardLibrary(stdlib: NativeLibrary): ModulesProvider {
check(stdlib.manifestData.uniqueName == KONAN_STDLIB_NAME)
return object : NativeDistributionModulesProvider(listOf(stdlib)) {
override fun loadModules(dependencies: Collection<ModuleDescriptor>): Map<String, ModuleDescriptor> {
check(dependencies.isEmpty())
val stdlibModule = NativeFactories.DefaultDeserializedDescriptorFactory.createDescriptorAndNewBuiltIns(
library = stdlib.library,
languageVersionSettings = LanguageVersionSettingsImpl.DEFAULT,
storageManager = storageManager,
packageAccessHandler = null
).apply {
setDependencies(listOf(this))
}
return mapOf(KONAN_STDLIB_NAME to stdlibModule)
}
}
return NativeDistributionModulesProvider(listOf(stdlib))
}
fun platformLibraries(
storageManager: StorageManager,
librariesToCommonize: NativeLibrariesToCommonize
): ModulesProvider = object : NativeDistributionModulesProvider(librariesToCommonize.libraries) {
override fun loadModules(dependencies: Collection<ModuleDescriptor>): Map<String, ModuleDescriptor> {
check(dependencies.isNotEmpty()) { "At least Kotlin/Native stdlib should be provided" }
val dependenciesMap = mutableMapOf<String, MutableList<ModuleDescriptorImpl>>()
dependencies.forEach { dependency ->
val name = dependency.name.strip()
dependenciesMap.getOrPut(name) { mutableListOf() } += dependency as ModuleDescriptorImpl
}
val builtIns = dependencies.first().builtIns
val platformModulesMap = libraryMap.mapValues { (_, library) ->
NativeFactories.DefaultDeserializedDescriptorFactory.createDescriptorOptionalBuiltIns(
library = library.library,
languageVersionSettings = LanguageVersionSettingsImpl.DEFAULT,
storageManager = storageManager,
builtIns = builtIns,
packageAccessHandler = null,
lookupTracker = LookupTracker.DO_NOTHING
)
}
val forwardDeclarations = createKotlinNativeForwardDeclarationsModule(
storageManager = storageManager,
builtIns = builtIns
)
platformModulesMap.forEach { (name, module) ->
val moduleDependencies = mutableListOf<ModuleDescriptorImpl>()
moduleDependencies += module
moduleInfoMap.getValue(name).dependencies.forEach {
moduleDependencies.addIfNotNull(platformModulesMap[it])
moduleDependencies += dependenciesMap[it].orEmpty()
}
moduleDependencies += forwardDeclarations
module.setDependencies(moduleDependencies)
}
return platformModulesMap
}
}
fun platformLibraries(librariesToCommonize: NativeLibrariesToCommonize): ModulesProvider =
NativeDistributionModulesProvider(librariesToCommonize.libraries)
}
}
@@ -1,265 +0,0 @@
/*
* Copyright 2010-2020 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.commonizer.mergedtree
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.commonizer.*
import org.jetbrains.kotlin.descriptors.commonizer.ModulesProvider.ModuleInfo
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirEntityId
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirName
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirPackageName
import org.jetbrains.kotlin.descriptors.commonizer.cir.factory.*
import org.jetbrains.kotlin.resolve.scopes.MemberScope
import org.jetbrains.kotlin.storage.StorageManager
/**
* N.B. Limitations on C/Obj-C interop.
*
* [Case 1]: An interop library with two fragments for two targets. The first fragment has a forward declaration of classifier A.
* The second one has a definition of class A. Both fragments have a top-level callable (ex: function)
* with the same signature that refers to type "A" as its return type.
*
* What will happen: Forward declarations will be ignored during building CIR merged tree. So the node for class A
* will contain CirClass "A" for the second target only. This node will not succeed in commonization, and no common class
* declaration will be produced. As a result the top-level callable will not be commonized, as it refers to the type "A"
* that is not formally commonized.
*
* This is not strictly correct: The classifier "A" exists in both targets though in different form. So if the user
* would write shared source code that uses "A" and the callable, then this code would successfully compile against both targets.
*
* The reason why commonization of such classifiers is not supported yet is that this is quite a rare case that requires
* a complex implementation with potential performance penalty.
*
* [Case 2]: A library with two fragments for two targets. The first fragment is interop. The second one is not.
* Similarly to case 1, the 1st fragment has a forward declaration of a classifier, and the 2nd has a real classifier.
*
* At the moment, this is an exotic case. It could happen if someone tries to commonize an MPP library for Native and non-Native
* targets (which is not supported yet), or a Native library where one fragment is produced via C-interop tool and the other one
* is compiled from Kotlin/Native source code (not sure this should be supported at all).
*/
class CirTreeMerger(
private val storageManager: StorageManager,
private val classifiers: CirKnownClassifiers,
private val parameters: CommonizerParameters
) {
class CirTreeMergeResult(
val root: CirRootNode,
val missingModuleInfos: Map<LeafCommonizerTarget, Collection<ModuleInfo>>
)
private val size = parameters.targetProviders.size
fun merge(): CirTreeMergeResult {
val result = processRoot()
System.gc()
return result
}
private fun processRoot(): CirTreeMergeResult {
val rootNode: CirRootNode = buildRootNode(storageManager, size)
// remember any exported forward declarations from common fragments of dependency modules
parameters.dependencyModulesProvider?.loadModuleInfos()?.forEach(::processCInteropModuleAttributes)
// load common dependencies
val dependencyModules = parameters.dependencyModulesProvider?.loadModules(emptyList())?.values.orEmpty()
val allModuleInfos: List<Map<String, ModuleInfo>> = parameters.targetProviders.map { targetProvider ->
targetProvider.modulesProvider.loadModuleInfos().associateBy { it.name }
}
val commonModuleNames = parameters.getCommonModuleNames()
parameters.targetProviders.forEachIndexed { targetIndex, targetProvider ->
val commonModuleInfos = allModuleInfos[targetIndex].filterKeys { it in commonModuleNames }
processTarget(rootNode, targetIndex, targetProvider, commonModuleInfos, dependencyModules)
parameters.progressLogger?.invoke("Loaded declarations for ${targetProvider.target.prettyName}")
System.gc()
}
val missingModuleInfos = allModuleInfos.mapIndexed { index, moduleInfos ->
val target = parameters.targetProviders[index].target
val missingInfos = moduleInfos.filterKeys { name -> name !in commonModuleNames }.values
target to missingInfos
}.toMap()
return CirTreeMergeResult(
root = rootNode,
missingModuleInfos = missingModuleInfos
)
}
private fun processTarget(
rootNode: CirRootNode,
targetIndex: Int,
targetProvider: TargetProvider,
commonModuleInfos: Map<String, ModuleInfo>,
dependencyModules: Collection<ModuleDescriptor>
) {
rootNode.targetDeclarations[targetIndex] = CirRootFactory.create(targetProvider.target)
val targetDependencyModules = targetProvider.dependencyModulesProvider?.loadModules(dependencyModules)?.values.orEmpty()
val allDependencyModules = targetDependencyModules + dependencyModules
val moduleDescriptors: Map<String, ModuleDescriptor> = targetProvider.modulesProvider.loadModules(allDependencyModules)
moduleDescriptors.forEach { (name, moduleDescriptor) ->
val moduleInfo = commonModuleInfos[name] ?: return@forEach
processModule(rootNode, targetIndex, moduleInfo, moduleDescriptor)
}
}
private fun processModule(
rootNode: CirRootNode,
targetIndex: Int,
moduleInfo: ModuleInfo,
moduleDescriptor: ModuleDescriptor
) {
processCInteropModuleAttributes(moduleInfo)
val moduleName: CirName = CirName.create(moduleDescriptor.name)
val moduleNode: CirModuleNode = rootNode.modules.getOrPut(moduleName) {
buildModuleNode(storageManager, size)
}
moduleNode.targetDeclarations[targetIndex] = CirModuleFactory.create(moduleName)
moduleDescriptor.collectNonEmptyPackageMemberScopes { packageName, packageMemberScope ->
processPackage(moduleNode, targetIndex, packageName, packageMemberScope)
}
}
private fun processPackage(
moduleNode: CirModuleNode,
targetIndex: Int,
packageName: CirPackageName,
packageMemberScope: MemberScope
) {
val packageNode: CirPackageNode = moduleNode.packages.getOrPut(packageName) {
buildPackageNode(storageManager, size)
}
packageNode.targetDeclarations[targetIndex] = CirPackageFactory.create(packageName)
packageMemberScope.collectMembers(
PropertyCollector { propertyDescriptor ->
processProperty(packageNode, targetIndex, propertyDescriptor)
},
FunctionCollector { functionDescriptor ->
processFunction(packageNode, targetIndex, functionDescriptor)
},
ClassCollector { classDescriptor ->
processClass(packageNode, targetIndex, classDescriptor) { className ->
CirEntityId.create(packageName, className)
}
},
TypeAliasCollector { typeAliasDescriptor ->
processTypeAlias(packageNode, targetIndex, typeAliasDescriptor)
}
)
}
private fun processProperty(
ownerNode: CirNodeWithMembers<*, *>,
targetIndex: Int,
propertyDescriptor: PropertyDescriptor
) {
val propertyNode: CirPropertyNode = ownerNode.properties.getOrPut(PropertyApproximationKey(propertyDescriptor)) {
buildPropertyNode(storageManager, size, classifiers, (ownerNode as? CirClassNode)?.commonDeclaration)
}
propertyNode.targetDeclarations[targetIndex] = CirPropertyFactory.create(
source = propertyDescriptor,
containingClass = (ownerNode as? CirClassNode)?.targetDeclarations?.get(targetIndex)
)
}
private fun processFunction(
ownerNode: CirNodeWithMembers<*, *>,
targetIndex: Int,
functionDescriptor: SimpleFunctionDescriptor
) {
val functionNode: CirFunctionNode = ownerNode.functions.getOrPut(FunctionApproximationKey(functionDescriptor)) {
buildFunctionNode(storageManager, size, classifiers, (ownerNode as? CirClassNode)?.commonDeclaration)
}
functionNode.targetDeclarations[targetIndex] = CirFunctionFactory.create(
source = functionDescriptor,
containingClass = (ownerNode as? CirClassNode)?.targetDeclarations?.get(targetIndex)
)
}
private fun processClass(
ownerNode: CirNodeWithMembers<*, *>,
targetIndex: Int,
classDescriptor: ClassDescriptor,
classIdFunction: (CirName) -> CirEntityId
) {
val className = CirName.create(classDescriptor.name)
val classId = classIdFunction(className)
val classNode: CirClassNode = ownerNode.classes.getOrPut(className) {
buildClassNode(storageManager, size, classifiers, (ownerNode as? CirClassNode)?.commonDeclaration, classId)
}
classNode.targetDeclarations[targetIndex] = CirClassFactory.create(classDescriptor)
if (classDescriptor.kind != ClassKind.ENUM_ENTRY) {
classDescriptor.constructors.forEach { constructorDescriptor ->
processClassConstructor(classNode, targetIndex, constructorDescriptor)
}
}
classDescriptor.unsubstitutedMemberScope.collectMembers(
PropertyCollector { propertyDescriptor ->
processProperty(classNode, targetIndex, propertyDescriptor)
},
FunctionCollector { functionDescriptor ->
processFunction(classNode, targetIndex, functionDescriptor)
},
ClassCollector { nestedClassDescriptor ->
processClass(classNode, targetIndex, nestedClassDescriptor) { nestedClassName ->
classId.createNestedEntityId(nestedClassName)
}
}
)
}
private fun processClassConstructor(
classNode: CirClassNode,
targetIndex: Int,
constructorDescriptor: ClassConstructorDescriptor
) {
val constructorNode: CirClassConstructorNode = classNode.constructors.getOrPut(ConstructorApproximationKey(constructorDescriptor)) {
buildClassConstructorNode(storageManager, size, classifiers, classNode.commonDeclaration)
}
constructorNode.targetDeclarations[targetIndex] = CirClassConstructorFactory.create(
source = constructorDescriptor,
containingClass = classNode.targetDeclarations[targetIndex]!!
)
}
private fun processTypeAlias(
packageNode: CirPackageNode,
targetIndex: Int,
typeAliasDescriptor: TypeAliasDescriptor
) {
val typeAliasName = CirName.create(typeAliasDescriptor.name)
val typeAliasClassId = CirEntityId.create(packageNode.packageName, typeAliasName)
val typeAliasNode: CirTypeAliasNode = packageNode.typeAliases.getOrPut(typeAliasName) {
buildTypeAliasNode(storageManager, size, classifiers, typeAliasClassId)
}
typeAliasNode.targetDeclarations[targetIndex] = CirTypeAliasFactory.create(typeAliasDescriptor)
}
private fun processCInteropModuleAttributes(moduleInfo: ModuleInfo) {
val cInteropAttributes = moduleInfo.cInteropAttributes ?: return
val exportForwardDeclarations = cInteropAttributes.exportForwardDeclarations.takeIf { it.isNotEmpty() } ?: return
exportForwardDeclarations.forEach { classFqName ->
// Class has synthetic package FQ name (cnames/objcnames). Need to transfer it to the main package.
val packageName = CirPackageName.create(classFqName.substringBeforeLast('.', missingDelimiterValue = ""))
val className = CirName.create(classFqName.substringAfterLast('.'))
classifiers.forwardDeclarations.addExportedForwardDeclaration(CirEntityId.create(packageName, className))
}
}
}
@@ -7,43 +7,32 @@ package org.jetbrains.kotlin.descriptors.commonizer.mergedtree
import kotlinx.metadata.*
import kotlinx.metadata.klib.annotations
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirName
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirTypeSignature
import org.jetbrains.kotlin.descriptors.commonizer.core.Commonizer
import org.jetbrains.kotlin.descriptors.commonizer.utils.*
import org.jetbrains.kotlin.descriptors.commonizer.utils.signature
import org.jetbrains.kotlin.descriptors.commonizer.utils.appendHashCode
import org.jetbrains.kotlin.descriptors.commonizer.utils.computeSignature
import org.jetbrains.kotlin.descriptors.commonizer.utils.hashCode
import org.jetbrains.kotlin.descriptors.commonizer.utils.isObjCInteropCallableAnnotation
/** Used for approximation of [PropertyDescriptor]s before running concrete [Commonizer]s */
/** Used for approximation of [KmProperty]s before running concrete [Commonizer]s */
data class PropertyApproximationKey(
val name: CirName,
val extensionReceiverParameterType: CirTypeSignature?
) {
constructor(property: PropertyDescriptor) : this(
CirName.create(property.name),
property.extensionReceiverParameter?.type?.signature
)
constructor(property: KmProperty, typeParameterResolver: TypeParameterResolver) : this(
CirName.create(property.name),
property.receiverParameterType?.computeSignature(typeParameterResolver)
)
}
/** Used for approximation of [SimpleFunctionDescriptor]s before running concrete [Commonizer]s */
/** Used for approximation of [KmFunction]s before running concrete [Commonizer]s */
data class FunctionApproximationKey(
val name: CirName,
val valueParametersTypes: Array<CirTypeSignature>,
private val additionalValueParametersNamesHash: Int,
val extensionReceiverParameterType: CirTypeSignature?
) {
constructor(function: SimpleFunctionDescriptor) : this(
CirName.create(function.name),
function.valueParameters.toTypeSignatures(),
additionalValueParameterNamesHash(function),
function.extensionReceiverParameter?.type?.signature
)
constructor(function: KmFunction, typeParameterResolver: TypeParameterResolver) : this(
CirName.create(function.name),
function.valueParameters.computeSignatures(typeParameterResolver),
@@ -67,16 +56,11 @@ data class FunctionApproximationKey(
.appendHashCode(additionalValueParametersNamesHash)
}
/** Used for approximation of [ConstructorDescriptor]s before running concrete [Commonizer]s */
/** Used for approximation of [KmConstructor]s before running concrete [Commonizer]s */
data class ConstructorApproximationKey(
val valueParametersTypes: Array<CirTypeSignature>,
private val additionalValueParametersNamesHash: Int
) {
constructor(constructor: ConstructorDescriptor) : this(
constructor.valueParameters.toTypeSignatures(),
additionalValueParameterNamesHash(constructor)
)
constructor(constructor: KmConstructor, typeParameterResolver: TypeParameterResolver) : this(
constructor.valueParameters.computeSignatures(typeParameterResolver),
additionalValueParameterNamesHash(constructor.annotations, constructor.valueParameters)
@@ -96,31 +80,12 @@ data class ConstructorApproximationKey(
interface TypeParameterResolver {
fun resolveTypeParameter(id: Int): KmTypeParameter?
companion object {
val EMPTY = object : TypeParameterResolver {
override fun resolveTypeParameter(id: Int): KmTypeParameter? = null
}
}
}
@JvmName("toTypeSignaturesDescriptors")
@Suppress("NOTHING_TO_INLINE")
private inline fun List<ValueParameterDescriptor>.toTypeSignatures(): Array<CirTypeSignature> =
if (isEmpty()) emptyArray() else Array(size) { index -> this[index].type.signature }
@Suppress("NOTHING_TO_INLINE")
private inline fun List<KmValueParameter>.computeSignatures(typeParameterResolver: TypeParameterResolver): Array<CirTypeSignature> =
if (isEmpty()) emptyArray() else Array(size) { index -> this[index].type?.computeSignature(typeParameterResolver).orEmpty() }
private fun additionalValueParameterNamesHash(callable: FunctionDescriptor): Int {
// TODO: add more precise checks when more languages than C & ObjC are supported
if (callable.annotations.none { it.isObjCInteropCallableAnnotation })
return 0 // do not calculate hash for non-ObjC callables
return callable.valueParameters.fold(0) { acc, next -> acc.appendHashCode(next.name.asString()) }
}
private fun additionalValueParameterNamesHash(annotations: List<KmAnnotation>, valueParameters: List<KmValueParameter>): Int {
// TODO: add more precise checks when more languages than C & ObjC are supported
if (annotations.none { it.isObjCInteropCallableAnnotation })
@@ -10,6 +10,7 @@ import org.jetbrains.kotlin.backend.common.serialization.metadata.impl.ExportedF
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirPackageName
import org.jetbrains.kotlin.descriptors.commonizer.utils.*
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.resolve.scopes.ChainedMemberScope
import org.jetbrains.kotlin.resolve.scopes.MemberScope
@@ -38,19 +39,6 @@ internal inline fun ClassCollector(
crossinline typedCollector: (ClassDescriptor) -> Unit
): (DeclarationDescriptor) -> Boolean = Collector(typedCollector)
@Suppress("FunctionName")
internal inline fun TypeAliasCollector(
crossinline typedCollector: (TypeAliasDescriptor) -> Unit
): (DeclarationDescriptor) -> Boolean = Collector(typedCollector)
@Suppress("FunctionName")
internal inline fun PropertyCollector(
crossinline typedCollector: (PropertyDescriptor) -> Unit
): (DeclarationDescriptor) -> Boolean = Collector<PropertyDescriptor> { candidate ->
if (candidate.kind.isReal) // omit fake overrides
typedCollector(candidate)
}
@Suppress("FunctionName")
internal inline fun FunctionCollector(
crossinline typedCollector: (SimpleFunctionDescriptor) -> Unit
@@ -67,7 +55,7 @@ internal inline fun FunctionCollector(
internal fun ModuleDescriptor.collectNonEmptyPackageMemberScopes(collector: (CirPackageName, MemberScope) -> Unit) {
// we don's need to process fragments from other modules which are the dependencies of this module, so
// let's use the appropriate package fragment provider
val packageFragmentProvider = this.packageFragmentProvider
val packageFragmentProvider = (this as ModuleDescriptorImpl).packageFragmentProviderForModuleContentWithoutDependencies
fun recurse(packageFqName: FqName) {
val ownPackageMemberScopes = packageFragmentProvider.packageFragments(packageFqName)
@@ -1,62 +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.descriptors.commonizer.utils
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.builtins.konan.KonanBuiltIns
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirName
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.konan.util.KlibMetadataFactories
import org.jetbrains.kotlin.library.metadata.NativeTypeTransformer
import org.jetbrains.kotlin.library.metadata.NullFlexibleTypeDeserializer
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.scopes.MemberScope
import org.jetbrains.kotlin.serialization.konan.impl.KlibResolvedModuleDescriptorsFactoryImpl
import org.jetbrains.kotlin.storage.StorageManager
internal val ModuleDescriptor.packageFragmentProvider: PackageFragmentProvider
get() = (this as ModuleDescriptorImpl).packageFragmentProviderForModuleContentWithoutDependencies
internal fun createKotlinNativeForwardDeclarationsModule(
storageManager: StorageManager,
builtIns: KotlinBuiltIns
): ModuleDescriptorImpl =
(NativeFactories.createDefaultKonanResolvedModuleDescriptorsFactory(NativeFactories.DefaultDeserializedDescriptorFactory) as KlibResolvedModuleDescriptorsFactoryImpl)
.createForwardDeclarationsModule(
builtIns = builtIns,
storageManager = storageManager
)
internal fun MemberScope.resolveClassOrTypeAlias(relativeNameSegments: Array<CirName>): ClassifierDescriptorWithTypeParameters? {
var memberScope: MemberScope = this
if (memberScope is MemberScope.Empty)
return null
val classifierName = when (relativeNameSegments.size) {
0 -> return null
1 -> relativeNameSegments[0]
else -> {
// resolve member scope of the nested class
relativeNameSegments.reduce { first, second ->
memberScope = (memberScope.getContributedClassifier(
Name.identifier(first.name),
NoLookupLocation.FOR_ALREADY_TRACKED
) as? ClassDescriptor)?.unsubstitutedMemberScope ?: return null
second
}
}
}
return memberScope.getContributedClassifier(
Name.identifier(classifierName.name),
NoLookupLocation.FOR_ALREADY_TRACKED
) as? ClassifierDescriptorWithTypeParameters
}
internal val NativeFactories = KlibMetadataFactories(::KonanBuiltIns, NullFlexibleTypeDeserializer, NativeTypeTransformer())
@@ -14,10 +14,8 @@ import org.jetbrains.kotlin.descriptors.commonizer.cir.CirName
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirPackageName
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirTypeSignature
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.TypeParameterResolver
import org.jetbrains.kotlin.resolve.descriptorUtil.classId
import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.typeUtil.isNullableAny
import org.jetbrains.kotlin.types.typeUtil.makeNotNullable
internal inline val KotlinType.declarationDescriptor: ClassifierDescriptor
get() = (constructor.declarationDescriptor ?: error("No declaration descriptor found for $constructor"))
@@ -62,58 +60,6 @@ private inline val KmType.isNullableAny: Boolean
private inline val KmType.isAny: Boolean
get() = (classifier as? KmClassifier.Class)?.name == ANY_CLASS_FULL_NAME && !Flag.Type.IS_NULLABLE(flags)
internal val KotlinType.signature: CirTypeSignature
get() {
// use of interner saves up to 95% of duplicates
return typeSignatureInterner.intern(buildString { buildTypeSignature(this@signature, HashSet()) })
}
private fun StringBuilder.buildTypeSignature(type: KotlinType, exploredTypeParameters: MutableSet<KotlinType>) {
val typeParameterDescriptor = TypeUtils.getTypeParameterDescriptorOrNull(type)
if (typeParameterDescriptor != null) {
// N.B this is type parameter type
append(typeParameterDescriptor.name.asString())
if (exploredTypeParameters.add(type.makeNotNullable())) { // print upper bounds once the first time when type parameter type is met
append(':').append('[')
typeParameterDescriptor.filteredUpperBounds.forEachIndexed { index, upperBound ->
if (index > 0)
append(',')
buildTypeSignature(upperBound, exploredTypeParameters)
}
append(']')
}
if (type.isMarkedNullable)
append('?')
} else {
// N.B. this is classifier type
val abbreviation = (type as? AbbreviatedType)?.abbreviation ?: type
append(abbreviation.declarationDescriptor.classId!!.asString())
val arguments = abbreviation.arguments
if (arguments.isNotEmpty()) {
append('<')
arguments.forEachIndexed { index, argument ->
if (index > 0)
append(',')
if (argument.isStarProjection)
append('*')
else {
val variance = argument.projectionKind
if (variance != Variance.INVARIANT)
append(variance.label).append(' ')
buildTypeSignature(argument.type, exploredTypeParameters)
}
}
append('>')
}
if (abbreviation.isMarkedNullable)
append('?')
}
}
internal fun KmType.computeSignature(typeParameterResolver: TypeParameterResolver): CirTypeSignature {
// use of interner saves up to 95% of duplicates
@@ -168,8 +168,6 @@ internal class MockModulesProvider private constructor(
return SERIALIZER.serializeModule(module)
}
override fun loadModules(dependencies: Collection<ModuleDescriptor>) = modules
private fun fakeModuleInfo(name: String) = ModuleInfo(name, File("/tmp/commonizer/mocks/$name"), null)
companion object {