[Commonizer] Introduce various types of classifier caches

- New CirCommonizedClassifiers and CirForwardDeclarations caches
- New CirProvidedClassifiers cache with classifier names loaded from arbitrary modules
- CirClassifiersCache is replaced by CirKnownClassifiers umbrella
- Replace the remaining usages of 'isUnderStandardKotlinPackages' by delegation to
  CirKnownClassifiers.commonDependeeLibraries
This commit is contained in:
Dmitriy Dolovov
2020-11-30 23:48:15 +03:00
parent dce3d4d1b7
commit 68f8e88d8b
32 changed files with 407 additions and 266 deletions
@@ -15,6 +15,7 @@ class Parameters(
private val _targetProviders = LinkedHashMap<LeafTarget, TargetProvider>() private val _targetProviders = LinkedHashMap<LeafTarget, TargetProvider>()
val targetProviders: List<TargetProvider> get() = _targetProviders.values.toList() val targetProviders: List<TargetProvider> get() = _targetProviders.values.toList()
val sharedTarget: SharedTarget get() = SharedTarget(_targetProviders.keys)
// common module dependencies (ex: Kotlin stdlib) // common module dependencies (ex: Kotlin stdlib)
var dependeeModulesProvider: ModulesProvider? = null var dependeeModulesProvider: ModulesProvider? = null
@@ -9,19 +9,19 @@ import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind.DELEGATION import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind.DELEGATION
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind.SYNTHESIZED import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind.SYNTHESIZED
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirFunctionOrProperty import org.jetbrains.kotlin.descriptors.commonizer.cir.CirFunctionOrProperty
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.CirClassifiersCache import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.CirKnownClassifiers
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
abstract class AbstractFunctionOrPropertyCommonizer<T : CirFunctionOrProperty>( abstract class AbstractFunctionOrPropertyCommonizer<T : CirFunctionOrProperty>(
cache: CirClassifiersCache classifiers: CirKnownClassifiers
) : AbstractStandardCommonizer<T, T>() { ) : AbstractStandardCommonizer<T, T>() {
protected lateinit var name: Name protected lateinit var name: Name
protected val modality = ModalityCommonizer() protected val modality = ModalityCommonizer()
protected val visibility = VisibilityCommonizer.lowering() protected val visibility = VisibilityCommonizer.lowering()
protected val extensionReceiver = ExtensionReceiverCommonizer(cache) protected val extensionReceiver = ExtensionReceiverCommonizer(classifiers)
protected val returnType = TypeCommonizer(cache) protected val returnType = TypeCommonizer(classifiers)
protected lateinit var kind: CallableMemberDescriptor.Kind protected lateinit var kind: CallableMemberDescriptor.Kind
protected val typeParameters = TypeParameterListCommonizer(cache) protected val typeParameters = TypeParameterListCommonizer(classifiers)
override fun initialize(first: T) { override fun initialize(first: T) {
name = first.name name = first.name
@@ -12,14 +12,14 @@ import org.jetbrains.kotlin.descriptors.commonizer.cir.CirValueParameter
import org.jetbrains.kotlin.descriptors.commonizer.cir.factory.CirValueParameterFactory import org.jetbrains.kotlin.descriptors.commonizer.cir.factory.CirValueParameterFactory
import org.jetbrains.kotlin.descriptors.commonizer.core.CallableValueParametersCommonizer.CallableToPatch.Companion.doNothing import org.jetbrains.kotlin.descriptors.commonizer.core.CallableValueParametersCommonizer.CallableToPatch.Companion.doNothing
import org.jetbrains.kotlin.descriptors.commonizer.core.CallableValueParametersCommonizer.CallableToPatch.Companion.patchCallables import org.jetbrains.kotlin.descriptors.commonizer.core.CallableValueParametersCommonizer.CallableToPatch.Companion.patchCallables
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.CirClassifiersCache import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.CirKnownClassifiers
import org.jetbrains.kotlin.descriptors.commonizer.utils.compactMapIndexed import org.jetbrains.kotlin.descriptors.commonizer.utils.compactMapIndexed
import org.jetbrains.kotlin.descriptors.commonizer.utils.intern import org.jetbrains.kotlin.descriptors.commonizer.utils.intern
import org.jetbrains.kotlin.descriptors.commonizer.utils.isObjCInteropCallableAnnotation import org.jetbrains.kotlin.descriptors.commonizer.utils.isObjCInteropCallableAnnotation
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
class CallableValueParametersCommonizer( class CallableValueParametersCommonizer(
cache: CirClassifiersCache classifiers: CirKnownClassifiers
) : Commonizer<CirCallableMemberWithParameters, CallableValueParametersCommonizer.Result> { ) : Commonizer<CirCallableMemberWithParameters, CallableValueParametersCommonizer.Result> {
class Result( class Result(
val hasStableParameterNames: Boolean, val hasStableParameterNames: Boolean,
@@ -118,7 +118,7 @@ class CallableValueParametersCommonizer(
} }
} }
private val valueParameters = ValueParameterListCommonizer(cache) private val valueParameters = ValueParameterListCommonizer(classifiers)
private val callables: MutableList<CallableToPatch> = mutableListOf() private val callables: MutableList<CallableToPatch> = mutableListOf()
private var hasStableParameterNames = true private var hasStableParameterNames = true
private var valueParameterNames: ValueParameterNames? = null private var valueParameterNames: ValueParameterNames? = null
@@ -8,13 +8,13 @@ package org.jetbrains.kotlin.descriptors.commonizer.core
import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirClass import org.jetbrains.kotlin.descriptors.commonizer.cir.CirClass
import org.jetbrains.kotlin.descriptors.commonizer.cir.factory.CirClassFactory import org.jetbrains.kotlin.descriptors.commonizer.cir.factory.CirClassFactory
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.CirClassifiersCache import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.CirKnownClassifiers
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
class ClassCommonizer(cache: CirClassifiersCache) : AbstractStandardCommonizer<CirClass, CirClass>() { class ClassCommonizer(classifiers: CirKnownClassifiers) : AbstractStandardCommonizer<CirClass, CirClass>() {
private lateinit var name: Name private lateinit var name: Name
private lateinit var kind: ClassKind private lateinit var kind: ClassKind
private val typeParameters = TypeParameterListCommonizer(cache) private val typeParameters = TypeParameterListCommonizer(classifiers)
private val modality = ModalityCommonizer() private val modality = ModalityCommonizer()
private val visibility = VisibilityCommonizer.equalizing() private val visibility = VisibilityCommonizer.equalizing()
private var isInner = false private var isInner = false
@@ -9,13 +9,15 @@ import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirClassConstructor import org.jetbrains.kotlin.descriptors.commonizer.cir.CirClassConstructor
import org.jetbrains.kotlin.descriptors.commonizer.cir.factory.CirClassConstructorFactory import org.jetbrains.kotlin.descriptors.commonizer.cir.factory.CirClassConstructorFactory
import org.jetbrains.kotlin.descriptors.commonizer.cir.factory.CirContainingClassDetailsFactory import org.jetbrains.kotlin.descriptors.commonizer.cir.factory.CirContainingClassDetailsFactory
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.CirClassifiersCache import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.CirKnownClassifiers
class ClassConstructorCommonizer(cache: CirClassifiersCache) : AbstractStandardCommonizer<CirClassConstructor, CirClassConstructor>() { class ClassConstructorCommonizer(
classifiers: CirKnownClassifiers
) : AbstractStandardCommonizer<CirClassConstructor, CirClassConstructor>() {
private var isPrimary = false private var isPrimary = false
private val visibility = VisibilityCommonizer.equalizing() private val visibility = VisibilityCommonizer.equalizing()
private val typeParameters = TypeParameterListCommonizer(cache) private val typeParameters = TypeParameterListCommonizer(classifiers)
private val valueParameters = CallableValueParametersCommonizer(cache) private val valueParameters = CallableValueParametersCommonizer(classifiers)
override fun commonizationResult(): CirClassConstructor { override fun commonizationResult(): CirClassConstructor {
val valueParameters = valueParameters.result val valueParameters = valueParameters.result
@@ -11,10 +11,9 @@ import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.*
import org.jetbrains.kotlin.descriptors.commonizer.utils.CommonizedGroup import org.jetbrains.kotlin.descriptors.commonizer.utils.CommonizedGroup
import org.jetbrains.kotlin.descriptors.commonizer.utils.compactMapNotNull import org.jetbrains.kotlin.descriptors.commonizer.utils.compactMapNotNull
import org.jetbrains.kotlin.descriptors.commonizer.utils.internedClassId import org.jetbrains.kotlin.descriptors.commonizer.utils.internedClassId
import org.jetbrains.kotlin.descriptors.commonizer.utils.isUnderStandardKotlinPackages
internal class CommonizationVisitor( internal class CommonizationVisitor(
private val cache: CirClassifiersCache, private val classifiers: CirKnownClassifiers,
private val root: CirRootNode private val root: CirRootNode
) : CirNodeVisitor<Unit, Unit> { ) : CirNodeVisitor<Unit, Unit> {
override fun visitRootNode(node: CirRootNode, data: Unit) { override fun visitRootNode(node: CirRootNode, data: Unit) {
@@ -88,7 +87,7 @@ internal class CommonizationVisitor(
val companionObjectName = node.targetDeclarations.mapTo(HashSet()) { it!!.companion }.singleOrNull() val companionObjectName = node.targetDeclarations.mapTo(HashSet()) { it!!.companion }.singleOrNull()
if (companionObjectName != null) { if (companionObjectName != null) {
val companionObjectClassId = internedClassId(node.classId, companionObjectName) val companionObjectClassId = internedClassId(node.classId, companionObjectName)
val companionObjectNode = cache.classNode(companionObjectClassId) val companionObjectNode = classifiers.commonized.classNode(companionObjectClassId)
?: error("Can't find companion object with class ID $companionObjectClassId") ?: error("Can't find companion object with class ID $companionObjectClassId")
if (companionObjectNode.commonDeclaration() != null) { if (companionObjectNode.commonDeclaration() != null) {
@@ -129,10 +128,10 @@ internal class CommonizationVisitor(
val supertypesMap: MutableMap<CirType, CommonizedGroup<CirType>> = linkedMapOf() // preserve supertype order val supertypesMap: MutableMap<CirType, CommonizedGroup<CirType>> = linkedMapOf() // preserve supertype order
for ((index, typeAlias) in targetDeclarations.withIndex()) { for ((index, typeAlias) in targetDeclarations.withIndex()) {
val expandedClassId = typeAlias!!.expandedType.classifierId val expandedClassId = typeAlias!!.expandedType.classifierId
if (expandedClassId.packageFqName.isUnderStandardKotlinPackages) if (classifiers.commonDependeeLibraries?.hasClassifier(expandedClassId) == true)
return null // this case is not supported return null // this case is not supported yet
val expandedClassNode = cache.classNode(expandedClassId) ?: return null val expandedClassNode = classifiers.commonized.classNode(expandedClassId) ?: return null
val expandedClass = expandedClassNode.targetDeclarations[index] val expandedClass = expandedClassNode.targetDeclarations[index]
?: error("Can't find expanded class with class ID $expandedClassId and index $index for type alias $classId") ?: error("Can't find expanded class with class ID $expandedClassId and index $index for type alias $classId")
@@ -148,7 +147,7 @@ internal class CommonizationVisitor(
if (supertypesMap.isNullOrEmpty()) if (supertypesMap.isNullOrEmpty())
emptyList() emptyList()
else else
supertypesMap.values.compactMapNotNull { supertypesGroup -> commonize(supertypesGroup, TypeCommonizer(cache)) } supertypesMap.values.compactMapNotNull { supertypesGroup -> commonize(supertypesGroup, TypeCommonizer(classifiers)) }
) )
} }
} }
@@ -8,11 +8,11 @@ package org.jetbrains.kotlin.descriptors.commonizer.core
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirExtensionReceiver import org.jetbrains.kotlin.descriptors.commonizer.cir.CirExtensionReceiver
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirType import org.jetbrains.kotlin.descriptors.commonizer.cir.CirType
import org.jetbrains.kotlin.descriptors.commonizer.cir.factory.CirExtensionReceiverFactory import org.jetbrains.kotlin.descriptors.commonizer.cir.factory.CirExtensionReceiverFactory
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.CirClassifiersCache import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.CirKnownClassifiers
class ExtensionReceiverCommonizer(cache: CirClassifiersCache) : class ExtensionReceiverCommonizer(classifiers: CirKnownClassifiers) :
AbstractNullableCommonizer<CirExtensionReceiver, CirExtensionReceiver, CirType, CirType>( AbstractNullableCommonizer<CirExtensionReceiver, CirExtensionReceiver, CirType, CirType>(
wrappedCommonizerFactory = { TypeCommonizer(cache) }, wrappedCommonizerFactory = { TypeCommonizer(classifiers) },
extractor = { it.type }, extractor = { it.type },
builder = { receiverType -> builder = { receiverType ->
CirExtensionReceiverFactory.create( CirExtensionReceiverFactory.create(
@@ -7,12 +7,12 @@ package org.jetbrains.kotlin.descriptors.commonizer.core
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirFunction import org.jetbrains.kotlin.descriptors.commonizer.cir.CirFunction
import org.jetbrains.kotlin.descriptors.commonizer.cir.factory.CirFunctionFactory import org.jetbrains.kotlin.descriptors.commonizer.cir.factory.CirFunctionFactory
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.CirClassifiersCache import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.CirKnownClassifiers
class FunctionCommonizer(cache: CirClassifiersCache) : AbstractFunctionOrPropertyCommonizer<CirFunction>(cache) { class FunctionCommonizer(classifiers: CirKnownClassifiers) : AbstractFunctionOrPropertyCommonizer<CirFunction>(classifiers) {
private val annotations = AnnotationsCommonizer() private val annotations = AnnotationsCommonizer()
private val modifiers = FunctionModifiersCommonizer() private val modifiers = FunctionModifiersCommonizer()
private val valueParameters = CallableValueParametersCommonizer(cache) private val valueParameters = CallableValueParametersCommonizer(classifiers)
override fun commonizationResult(): CirFunction { override fun commonizationResult(): CirFunction {
val valueParameters = valueParameters.result val valueParameters = valueParameters.result
@@ -9,10 +9,10 @@ import org.jetbrains.kotlin.descriptors.commonizer.cir.CirProperty
import org.jetbrains.kotlin.descriptors.commonizer.cir.factory.CirPropertyFactory import org.jetbrains.kotlin.descriptors.commonizer.cir.factory.CirPropertyFactory
import org.jetbrains.kotlin.descriptors.commonizer.cir.factory.CirPropertyGetterFactory import org.jetbrains.kotlin.descriptors.commonizer.cir.factory.CirPropertyGetterFactory
import org.jetbrains.kotlin.descriptors.commonizer.core.PropertyCommonizer.ConstCommonizationState.* import org.jetbrains.kotlin.descriptors.commonizer.core.PropertyCommonizer.ConstCommonizationState.*
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.CirClassifiersCache import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.CirKnownClassifiers
import org.jetbrains.kotlin.resolve.constants.ConstantValue import org.jetbrains.kotlin.resolve.constants.ConstantValue
class PropertyCommonizer(cache: CirClassifiersCache) : AbstractFunctionOrPropertyCommonizer<CirProperty>(cache) { class PropertyCommonizer(classifiers: CirKnownClassifiers) : AbstractFunctionOrPropertyCommonizer<CirProperty>(classifiers) {
private val setter = PropertySetterCommonizer() private val setter = PropertySetterCommonizer()
private var isExternal = true private var isExternal = true
private lateinit var constCommonizationState: ConstCommonizationState private lateinit var constCommonizationState: ConstCommonizationState
@@ -10,8 +10,7 @@ import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.commonizer.cir.* import org.jetbrains.kotlin.descriptors.commonizer.cir.*
import org.jetbrains.kotlin.descriptors.commonizer.cir.factory.CirClassFactory import org.jetbrains.kotlin.descriptors.commonizer.cir.factory.CirClassFactory
import org.jetbrains.kotlin.descriptors.commonizer.cir.factory.CirTypeAliasFactory import org.jetbrains.kotlin.descriptors.commonizer.cir.factory.CirTypeAliasFactory
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.CirClassifiersCache import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.CirKnownClassifiers
import org.jetbrains.kotlin.descriptors.commonizer.utils.isUnderStandardKotlinPackages
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
/** /**
@@ -24,9 +23,9 @@ import org.jetbrains.kotlin.name.Name
* Tertiary (backup) branch: * Tertiary (backup) branch:
* - Produce an "expect class" for "common" fragment and the corresponding "actual typealias" declarations for each platform fragment. * - Produce an "expect class" for "common" fragment and the corresponding "actual typealias" declarations for each platform fragment.
*/ */
class TypeAliasCommonizer(cache: CirClassifiersCache) : AbstractStandardCommonizer<CirTypeAlias, CirClassifier>() { class TypeAliasCommonizer(classifiers: CirKnownClassifiers) : AbstractStandardCommonizer<CirTypeAlias, CirClassifier>() {
private val primary = TypeAliasShortCircuitingCommonizer(cache) private val primary = TypeAliasShortCircuitingCommonizer(classifiers)
private val secondary = TypeAliasLiftingUpCommonizer(cache) private val secondary = TypeAliasLiftingUpCommonizer(classifiers)
private val tertiary = TypeAliasExpectClassCommonizer() private val tertiary = TypeAliasExpectClassCommonizer()
override fun commonizationResult(): CirClassifier = primary.resultOrNull ?: secondary.resultOrNull ?: tertiary.result override fun commonizationResult(): CirClassifier = primary.resultOrNull ?: secondary.resultOrNull ?: tertiary.result
@@ -43,11 +42,13 @@ class TypeAliasCommonizer(cache: CirClassifiersCache) : AbstractStandardCommoniz
} }
} }
private class TypeAliasShortCircuitingCommonizer(cache: CirClassifiersCache) : AbstractStandardCommonizer<CirTypeAlias, CirTypeAlias>() { private class TypeAliasShortCircuitingCommonizer(
private val classifiers: CirKnownClassifiers
) : AbstractStandardCommonizer<CirTypeAlias, CirTypeAlias>() {
private lateinit var name: Name private lateinit var name: Name
private val typeParameters = TypeParameterListCommonizer(cache) private val typeParameters = TypeParameterListCommonizer(classifiers)
private lateinit var underlyingType: CirClassOrTypeAliasType private lateinit var underlyingType: CirClassOrTypeAliasType
private val expandedType = TypeCommonizer(cache) private val expandedType = TypeCommonizer(classifiers)
private val visibility = VisibilityCommonizer.lowering() private val visibility = VisibilityCommonizer.lowering()
override fun commonizationResult() = CirTypeAliasFactory.create( override fun commonizationResult() = CirTypeAliasFactory.create(
@@ -75,7 +76,7 @@ private class TypeAliasShortCircuitingCommonizer(cache: CirClassifiersCache) : A
private tailrec fun computeCommonizedUnderlyingType(underlyingType: CirClassOrTypeAliasType): CirClassOrTypeAliasType { private tailrec fun computeCommonizedUnderlyingType(underlyingType: CirClassOrTypeAliasType): CirClassOrTypeAliasType {
return when (underlyingType) { return when (underlyingType) {
is CirClassType -> underlyingType is CirClassType -> underlyingType
is CirTypeAliasType -> if (underlyingType.classifierId.packageFqName.isUnderStandardKotlinPackages) is CirTypeAliasType -> if (classifiers.commonDependeeLibraries?.hasClassifier(underlyingType.classifierId) == true)
underlyingType underlyingType
else else
computeCommonizedUnderlyingType(underlyingType.underlyingType) computeCommonizedUnderlyingType(underlyingType.underlyingType)
@@ -83,10 +84,10 @@ private class TypeAliasShortCircuitingCommonizer(cache: CirClassifiersCache) : A
} }
} }
private class TypeAliasLiftingUpCommonizer(cache: CirClassifiersCache) : AbstractStandardCommonizer<CirTypeAlias, CirTypeAlias>() { private class TypeAliasLiftingUpCommonizer(classifiers: CirKnownClassifiers) : AbstractStandardCommonizer<CirTypeAlias, CirTypeAlias>() {
private lateinit var name: Name private lateinit var name: Name
private val typeParameters = TypeParameterListCommonizer(cache) private val typeParameters = TypeParameterListCommonizer(classifiers)
private val underlyingType = TypeCommonizer(cache) private val underlyingType = TypeCommonizer(classifiers)
private val visibility = VisibilityCommonizer.lowering() private val visibility = VisibilityCommonizer.lowering()
override fun commonizationResult(): CirTypeAlias { override fun commonizationResult(): CirTypeAlias {
@@ -10,13 +10,12 @@ import org.jetbrains.kotlin.descriptors.commonizer.cir.*
import org.jetbrains.kotlin.descriptors.commonizer.cir.factory.CirTypeFactory import org.jetbrains.kotlin.descriptors.commonizer.cir.factory.CirTypeFactory
import org.jetbrains.kotlin.descriptors.commonizer.core.CommonizedTypeAliasAnswer.Companion.FAILURE_MISSING_IN_SOME_TARGET import org.jetbrains.kotlin.descriptors.commonizer.core.CommonizedTypeAliasAnswer.Companion.FAILURE_MISSING_IN_SOME_TARGET
import org.jetbrains.kotlin.descriptors.commonizer.core.CommonizedTypeAliasAnswer.Companion.SUCCESS_FROM_DEPENDEE_LIBRARY import org.jetbrains.kotlin.descriptors.commonizer.core.CommonizedTypeAliasAnswer.Companion.SUCCESS_FROM_DEPENDEE_LIBRARY
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.CirClassifiersCache import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.CirKnownClassifiers
import org.jetbrains.kotlin.descriptors.commonizer.utils.isUnderKotlinNativeSyntheticPackages import org.jetbrains.kotlin.descriptors.commonizer.utils.isUnderKotlinNativeSyntheticPackages
import org.jetbrains.kotlin.descriptors.commonizer.utils.isUnderStandardKotlinPackages
import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.types.Variance import org.jetbrains.kotlin.types.Variance
class TypeCommonizer(private val cache: CirClassifiersCache) : AbstractStandardCommonizer<CirType, CirType>() { class TypeCommonizer(private val classifiers: CirKnownClassifiers) : AbstractStandardCommonizer<CirType, CirType>() {
private lateinit var wrapped: Commonizer<*, CirType> private lateinit var wrapped: Commonizer<*, CirType>
override fun commonizationResult() = wrapped.result override fun commonizationResult() = wrapped.result
@@ -24,10 +23,10 @@ class TypeCommonizer(private val cache: CirClassifiersCache) : AbstractStandardC
override fun initialize(first: CirType) { override fun initialize(first: CirType) {
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
wrapped = when (first) { wrapped = when (first) {
is CirClassType -> ClassTypeCommonizer(cache) is CirClassType -> ClassTypeCommonizer(classifiers)
is CirTypeAliasType -> TypeAliasTypeCommonizer(cache) is CirTypeAliasType -> TypeAliasTypeCommonizer(classifiers)
is CirTypeParameterType -> TypeParameterTypeCommonizer() is CirTypeParameterType -> TypeParameterTypeCommonizer()
is CirFlexibleType -> FlexibleTypeCommonizer(cache) is CirFlexibleType -> FlexibleTypeCommonizer(classifiers)
} as Commonizer<*, CirType> } as Commonizer<*, CirType>
} }
@@ -39,11 +38,11 @@ class TypeCommonizer(private val cache: CirClassifiersCache) : AbstractStandardC
} }
} }
private class ClassTypeCommonizer(private val cache: CirClassifiersCache) : AbstractStandardCommonizer<CirClassType, CirClassType>() { private class ClassTypeCommonizer(private val classifiers: CirKnownClassifiers) : AbstractStandardCommonizer<CirClassType, CirClassType>() {
private lateinit var classId: ClassId private lateinit var classId: ClassId
private val outerType = OuterClassTypeCommonizer(cache) private val outerType = OuterClassTypeCommonizer(classifiers)
private lateinit var anyVisibility: DescriptorVisibility private lateinit var anyVisibility: DescriptorVisibility
private val arguments = TypeArgumentListCommonizer(cache) private val arguments = TypeArgumentListCommonizer(classifiers)
private var isMarkedNullable = false private var isMarkedNullable = false
override fun commonizationResult() = CirTypeFactory.createClassType( override fun commonizationResult() = CirTypeFactory.createClassType(
@@ -68,22 +67,22 @@ private class ClassTypeCommonizer(private val cache: CirClassifiersCache) : Abst
isMarkedNullable == next.isMarkedNullable isMarkedNullable == next.isMarkedNullable
&& classId == next.classifierId && classId == next.classifierId
&& outerType.commonizeWith(next.outerType) && outerType.commonizeWith(next.outerType)
&& commonizeClass(classId, cache) && commonizeClass(classId, classifiers)
&& arguments.commonizeWith(next.arguments) && arguments.commonizeWith(next.arguments)
} }
private class OuterClassTypeCommonizer(cache: CirClassifiersCache) : private class OuterClassTypeCommonizer(classifiers: CirKnownClassifiers) :
AbstractNullableCommonizer<CirClassType, CirClassType, CirClassType, CirClassType>( AbstractNullableCommonizer<CirClassType, CirClassType, CirClassType, CirClassType>(
wrappedCommonizerFactory = { ClassTypeCommonizer(cache) }, wrappedCommonizerFactory = { ClassTypeCommonizer(classifiers) },
extractor = { it }, extractor = { it },
builder = { it } builder = { it }
) )
private class TypeAliasTypeCommonizer(private val cache: CirClassifiersCache) : private class TypeAliasTypeCommonizer(private val classifiers: CirKnownClassifiers) :
AbstractStandardCommonizer<CirTypeAliasType, CirClassOrTypeAliasType>() { AbstractStandardCommonizer<CirTypeAliasType, CirClassOrTypeAliasType>() {
private lateinit var typeAliasId: ClassId private lateinit var typeAliasId: ClassId
private val arguments = TypeArgumentListCommonizer(cache) private val arguments = TypeArgumentListCommonizer(classifiers)
private var isMarkedNullable = false private var isMarkedNullable = false
private var commonizedTypeBuilder: CommonizedTypeAliasTypeBuilder? = null // null means not selected yet private var commonizedTypeBuilder: CommonizedTypeAliasTypeBuilder? = null // null means not selected yet
@@ -104,7 +103,7 @@ private class TypeAliasTypeCommonizer(private val cache: CirClassifiersCache) :
return false return false
if (commonizedTypeBuilder == null) { if (commonizedTypeBuilder == null) {
val answer = commonizeTypeAlias(typeAliasId, cache) val answer = commonizeTypeAlias(typeAliasId, classifiers)
if (!answer.commonized) if (!answer.commonized)
return false return false
@@ -176,9 +175,9 @@ private class TypeParameterTypeCommonizer : AbstractStandardCommonizer<CirTypePa
} }
} }
private class FlexibleTypeCommonizer(cache: CirClassifiersCache) : AbstractStandardCommonizer<CirFlexibleType, CirFlexibleType>() { private class FlexibleTypeCommonizer(classifiers: CirKnownClassifiers) : AbstractStandardCommonizer<CirFlexibleType, CirFlexibleType>() {
private val lowerBound = TypeCommonizer(cache) private val lowerBound = TypeCommonizer(classifiers)
private val upperBound = TypeCommonizer(cache) private val upperBound = TypeCommonizer(classifiers)
override fun commonizationResult() = CirFlexibleType( override fun commonizationResult() = CirFlexibleType(
lowerBound = lowerBound.result as CirSimpleType, lowerBound = lowerBound.result as CirSimpleType,
@@ -191,10 +190,12 @@ private class FlexibleTypeCommonizer(cache: CirClassifiersCache) : AbstractStand
lowerBound.commonizeWith(next.lowerBound) && upperBound.commonizeWith(next.upperBound) lowerBound.commonizeWith(next.lowerBound) && upperBound.commonizeWith(next.upperBound)
} }
private class TypeArgumentCommonizer(cache: CirClassifiersCache) : AbstractStandardCommonizer<CirTypeProjection, CirTypeProjection>() { private class TypeArgumentCommonizer(
classifiers: CirKnownClassifiers
) : AbstractStandardCommonizer<CirTypeProjection, CirTypeProjection>() {
private var isStar = false private var isStar = false
private lateinit var projectionKind: Variance private lateinit var projectionKind: Variance
private val type = TypeCommonizer(cache) private val type = TypeCommonizer(classifiers)
override fun commonizationResult() = if (isStar) CirStarTypeProjection else CirTypeProjectionImpl( override fun commonizationResult() = if (isStar) CirStarTypeProjection else CirTypeProjectionImpl(
projectionKind = projectionKind, projectionKind = projectionKind,
@@ -214,16 +215,15 @@ private class TypeArgumentCommonizer(cache: CirClassifiersCache) : AbstractStand
} }
} }
private class TypeArgumentListCommonizer(cache: CirClassifiersCache) : AbstractListCommonizer<CirTypeProjection, CirTypeProjection>( private class TypeArgumentListCommonizer(classifiers: CirKnownClassifiers) : AbstractListCommonizer<CirTypeProjection, CirTypeProjection>(
singleElementCommonizerFactory = { TypeArgumentCommonizer(cache) } singleElementCommonizerFactory = { TypeArgumentCommonizer(classifiers) }
) )
private fun commonizeClass(classId: ClassId, cache: CirClassifiersCache): Boolean { private fun commonizeClass(classId: ClassId, classifiers: CirKnownClassifiers): Boolean {
val packageFqName = classId.packageFqName if (classifiers.commonDependeeLibraries?.hasClassifier(classId) == true) {
if (packageFqName.isUnderStandardKotlinPackages) { // The class is from common fragment of dependee library (ex: stdlib). Already commonized.
// The class is from Kotlin stdlib. Already commonized.
return true return true
} else if (packageFqName.isUnderKotlinNativeSyntheticPackages) { } else if (classId.packageFqName.isUnderKotlinNativeSyntheticPackages) {
// C/Obj-C forward declarations are: // C/Obj-C forward declarations are:
// - Either resolved to real classes/interfaces from other interop libraries (which are generated by C-interop tool and // - Either resolved to real classes/interfaces from other interop libraries (which are generated by C-interop tool and
// are known to have modality/visibility/other attributes to successfully pass commonization). // are known to have modality/visibility/other attributes to successfully pass commonization).
@@ -232,12 +232,12 @@ private fun commonizeClass(classId: ClassId, cache: CirClassifiersCache): Boolea
return true return true
} }
return when (val node = cache.classNode(classId)) { return when (val node = classifiers.commonized.classNode(classId)) {
null -> { null -> {
// No node means that the class was not subject for commonization. // No node means that the class was not subject for commonization.
// - Either it is missing in certain targets at all => not commonized. // - Either it is missing in certain targets at all => not commonized.
// - Or it is a known forward declaration => consider it as commonized. // - Or it is a known forward declaration => consider it as commonized.
cache.isExportedForwardDeclaration(classId) classifiers.forwardDeclarations.isExportedForwardDeclaration(classId)
} }
else -> { else -> {
// Common declaration in node is not null -> successfully commonized. // Common declaration in node is not null -> successfully commonized.
@@ -246,14 +246,13 @@ private fun commonizeClass(classId: ClassId, cache: CirClassifiersCache): Boolea
} }
} }
private fun commonizeTypeAlias(typeAliasId: ClassId, cache: CirClassifiersCache): CommonizedTypeAliasAnswer { private fun commonizeTypeAlias(typeAliasId: ClassId, classifiers: CirKnownClassifiers): CommonizedTypeAliasAnswer {
val packageFqName = typeAliasId.packageFqName if (classifiers.commonDependeeLibraries?.hasClassifier(typeAliasId) == true) {
if (packageFqName.isUnderStandardKotlinPackages) { // The type alias is from common fragment of dependee library (ex: stdlib). Already commonized.
// The type alias is from Kotlin stdlib. Already commonized.
return SUCCESS_FROM_DEPENDEE_LIBRARY return SUCCESS_FROM_DEPENDEE_LIBRARY
} }
return when (val node = cache.typeAliasNode(typeAliasId)) { return when (val node = classifiers.commonized.typeAliasNode(typeAliasId)) {
null -> { null -> {
// No node means that the type alias was not subject for commonization. It is missing in some target(s) => not commonized. // No node means that the type alias was not subject for commonization. It is missing in some target(s) => not commonized.
FAILURE_MISSING_IN_SOME_TARGET FAILURE_MISSING_IN_SOME_TARGET
@@ -8,15 +8,15 @@ package org.jetbrains.kotlin.descriptors.commonizer.core
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirType import org.jetbrains.kotlin.descriptors.commonizer.cir.CirType
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirTypeParameter import org.jetbrains.kotlin.descriptors.commonizer.cir.CirTypeParameter
import org.jetbrains.kotlin.descriptors.commonizer.cir.factory.CirTypeParameterFactory import org.jetbrains.kotlin.descriptors.commonizer.cir.factory.CirTypeParameterFactory
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.CirClassifiersCache import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.CirKnownClassifiers
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.types.Variance import org.jetbrains.kotlin.types.Variance
class TypeParameterCommonizer(cache: CirClassifiersCache) : AbstractStandardCommonizer<CirTypeParameter, CirTypeParameter>() { class TypeParameterCommonizer(classifiers: CirKnownClassifiers) : AbstractStandardCommonizer<CirTypeParameter, CirTypeParameter>() {
private lateinit var name: Name private lateinit var name: Name
private var isReified = false private var isReified = false
private lateinit var variance: Variance private lateinit var variance: Variance
private val upperBounds = TypeParameterUpperBoundsCommonizer(cache) private val upperBounds = TypeParameterUpperBoundsCommonizer(classifiers)
override fun commonizationResult() = CirTypeParameterFactory.create( override fun commonizationResult() = CirTypeParameterFactory.create(
annotations = emptyList(), annotations = emptyList(),
@@ -39,6 +39,6 @@ class TypeParameterCommonizer(cache: CirClassifiersCache) : AbstractStandardComm
&& upperBounds.commonizeWith(next.upperBounds) && upperBounds.commonizeWith(next.upperBounds)
} }
private class TypeParameterUpperBoundsCommonizer(cache: CirClassifiersCache) : AbstractListCommonizer<CirType, CirType>( private class TypeParameterUpperBoundsCommonizer(classifiers: CirKnownClassifiers) : AbstractListCommonizer<CirType, CirType>(
singleElementCommonizerFactory = { TypeCommonizer(cache) } singleElementCommonizerFactory = { TypeCommonizer(classifiers) }
) )
@@ -6,8 +6,8 @@
package org.jetbrains.kotlin.descriptors.commonizer.core package org.jetbrains.kotlin.descriptors.commonizer.core
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirTypeParameter import org.jetbrains.kotlin.descriptors.commonizer.cir.CirTypeParameter
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.CirClassifiersCache import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.CirKnownClassifiers
class TypeParameterListCommonizer(cache: CirClassifiersCache) : AbstractListCommonizer<CirTypeParameter, CirTypeParameter>( class TypeParameterListCommonizer(classifiers: CirKnownClassifiers) : AbstractListCommonizer<CirTypeParameter, CirTypeParameter>(
singleElementCommonizerFactory = { TypeParameterCommonizer(cache) } singleElementCommonizerFactory = { TypeParameterCommonizer(classifiers) }
) )
@@ -8,13 +8,13 @@ package org.jetbrains.kotlin.descriptors.commonizer.core
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirType import org.jetbrains.kotlin.descriptors.commonizer.cir.CirType
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirValueParameter import org.jetbrains.kotlin.descriptors.commonizer.cir.CirValueParameter
import org.jetbrains.kotlin.descriptors.commonizer.cir.factory.CirValueParameterFactory import org.jetbrains.kotlin.descriptors.commonizer.cir.factory.CirValueParameterFactory
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.CirClassifiersCache import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.CirKnownClassifiers
import org.jetbrains.kotlin.descriptors.commonizer.utils.isNull import org.jetbrains.kotlin.descriptors.commonizer.utils.isNull
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
class ValueParameterCommonizer(cache: CirClassifiersCache) : AbstractStandardCommonizer<CirValueParameter, CirValueParameter>() { class ValueParameterCommonizer(classifiers: CirKnownClassifiers) : AbstractStandardCommonizer<CirValueParameter, CirValueParameter>() {
private lateinit var name: Name private lateinit var name: Name
private val returnType = TypeCommonizer(cache) private val returnType = TypeCommonizer(classifiers)
private var varargElementType: CirType? = null private var varargElementType: CirType? = null
private var isCrossinline = true private var isCrossinline = true
private var isNoinline = true private var isNoinline = true
@@ -6,11 +6,11 @@
package org.jetbrains.kotlin.descriptors.commonizer.core package org.jetbrains.kotlin.descriptors.commonizer.core
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirValueParameter import org.jetbrains.kotlin.descriptors.commonizer.cir.CirValueParameter
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.CirClassifiersCache import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.CirKnownClassifiers
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
class ValueParameterListCommonizer(cache: CirClassifiersCache) : AbstractListCommonizer<CirValueParameter, CirValueParameter>( class ValueParameterListCommonizer(classifiers: CirKnownClassifiers) : AbstractListCommonizer<CirValueParameter, CirValueParameter>(
singleElementCommonizerFactory = { ValueParameterCommonizer(cache) } singleElementCommonizerFactory = { ValueParameterCommonizer(classifiers) }
) { ) {
fun overwriteNames(names: List<Name>) { fun overwriteNames(names: List<Name>) {
forEachSingleElementCommonizer { index, singleElementCommonizer -> forEachSingleElementCommonizer { index, singleElementCommonizer ->
@@ -9,9 +9,10 @@ import org.jetbrains.kotlin.descriptors.commonizer.builder.DeclarationsBuilderVi
import org.jetbrains.kotlin.descriptors.commonizer.builder.DeclarationsBuilderVisitor2 import org.jetbrains.kotlin.descriptors.commonizer.builder.DeclarationsBuilderVisitor2
import org.jetbrains.kotlin.descriptors.commonizer.builder.createGlobalBuilderComponents import org.jetbrains.kotlin.descriptors.commonizer.builder.createGlobalBuilderComponents
import org.jetbrains.kotlin.descriptors.commonizer.core.CommonizationVisitor import org.jetbrains.kotlin.descriptors.commonizer.core.CommonizationVisitor
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.CirTreeMerger import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.*
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.DefaultCirClassifiersCache import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.CirTreeMerger.CirTreeMergeResult
import org.jetbrains.kotlin.storage.LockBasedStorageManager import org.jetbrains.kotlin.storage.LockBasedStorageManager
import org.jetbrains.kotlin.storage.StorageManager
fun runCommonization(parameters: Parameters): Result { fun runCommonization(parameters: Parameters): Result {
if (!parameters.hasAnythingToCommonize()) if (!parameters.hasAnythingToCommonize())
@@ -19,14 +20,8 @@ fun runCommonization(parameters: Parameters): Result {
val storageManager = LockBasedStorageManager("Declaration descriptors commonization") val storageManager = LockBasedStorageManager("Declaration descriptors commonization")
// build merged tree: val mergeResult = mergeAndCommonize(storageManager, parameters)
val cache = DefaultCirClassifiersCache()
val mergeResult = CirTreeMerger(storageManager, cache, parameters).merge()
// commonize:
val mergedTree = mergeResult.root val mergedTree = mergeResult.root
mergedTree.accept(CommonizationVisitor(cache, mergedTree), Unit)
parameters.progressLogger?.invoke("Commonized declarations")
// build resulting descriptors: // build resulting descriptors:
val components = mergedTree.createGlobalBuilderComponents(storageManager, parameters) val components = mergedTree.createGlobalBuilderComponents(storageManager, parameters)
@@ -51,3 +46,25 @@ fun runCommonization(parameters: Parameters): Result {
return Result.Commonized(modulesByTargets) return Result.Commonized(modulesByTargets)
} }
private fun mergeAndCommonize(storageManager: StorageManager, parameters: Parameters): CirTreeMergeResult {
// build merged tree:
val classifiers = CirKnownClassifiers(
commonized = CirCommonizedClassifiers.default(),
forwardDeclarations = CirForwardDeclarations.default(),
dependeeLibraries = mapOf(
// for now, supply only common dependee libraries (ex: Kotlin stdlib)
parameters.sharedTarget to CirProvidedClassifiers.fromModules(storageManager) {
parameters.dependeeModulesProvider?.loadModules(emptyList())?.values.orEmpty()
}
)
)
val mergeResult = CirTreeMerger(storageManager, classifiers, parameters).merge()
// commonize:
val mergedTree = mergeResult.root
mergedTree.accept(CommonizationVisitor(classifiers, mergedTree), Unit)
parameters.progressLogger?.invoke("Commonized declarations")
return mergeResult
}
@@ -7,42 +7,122 @@ package org.jetbrains.kotlin.descriptors.commonizer.mergedtree
import gnu.trove.THashMap import gnu.trove.THashMap
import gnu.trove.THashSet import gnu.trove.THashSet
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.descriptors.commonizer.SharedTarget
import org.jetbrains.kotlin.descriptors.commonizer.Target
import org.jetbrains.kotlin.descriptors.commonizer.utils.intern
import org.jetbrains.kotlin.descriptors.commonizer.utils.isUnderKotlinNativeSyntheticPackages import org.jetbrains.kotlin.descriptors.commonizer.utils.isUnderKotlinNativeSyntheticPackages
import org.jetbrains.kotlin.descriptors.commonizer.utils.resolveClassOrTypeAlias
import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.resolve.scopes.MemberScope
import org.jetbrains.kotlin.storage.StorageManager
import org.jetbrains.kotlin.storage.getValue
interface CirClassifiersCache { class CirKnownClassifiers(
fun isExportedForwardDeclaration(classId: ClassId): Boolean val commonized: CirCommonizedClassifiers,
val forwardDeclarations: CirForwardDeclarations,
val dependeeLibraries: Map<Target, CirProvidedClassifiers>
) {
// a shortcut for fast access
val commonDependeeLibraries: CirProvidedClassifiers? = dependeeLibraries.filterKeys { it is SharedTarget }.values.singleOrNull()
}
interface CirCommonizedClassifiers {
/* Accessors */
fun classNode(classId: ClassId): CirClassNode? fun classNode(classId: ClassId): CirClassNode?
fun typeAliasNode(typeAliasId: ClassId): CirTypeAliasNode? fun typeAliasNode(typeAliasId: ClassId): CirTypeAliasNode?
fun addExportedForwardDeclaration(classId: ClassId) /* Mutators */
fun addClassNode(classId: ClassId, node: CirClassNode) fun addClassNode(classId: ClassId, node: CirClassNode)
fun addTypeAliasNode(typeAliasId: ClassId, node: CirTypeAliasNode) fun addTypeAliasNode(typeAliasId: ClassId, node: CirTypeAliasNode)
}
class DefaultCirClassifiersCache : CirClassifiersCache { companion object {
private val exportedForwardDeclarations = THashSet<ClassId>() fun default() = object : CirCommonizedClassifiers {
private val classNodes = THashMap<ClassId, CirClassNode>() private val classNodes = THashMap<ClassId, CirClassNode>()
private val typeAliases = THashMap<ClassId, CirTypeAliasNode>() private val typeAliases = THashMap<ClassId, CirTypeAliasNode>()
override fun isExportedForwardDeclaration(classId: ClassId) = classId in exportedForwardDeclarations override fun classNode(classId: ClassId) = classNodes[classId]
override fun classNode(classId: ClassId) = classNodes[classId] override fun typeAliasNode(typeAliasId: ClassId) = typeAliases[typeAliasId]
override fun typeAliasNode(typeAliasId: ClassId) = typeAliases[typeAliasId]
override fun addExportedForwardDeclaration(classId: ClassId) { override fun addClassNode(classId: ClassId, node: CirClassNode) {
check(!classId.packageFqName.isUnderKotlinNativeSyntheticPackages) val oldNode = classNodes.put(classId, node)
exportedForwardDeclarations += classId check(oldNode == null) { "Rewriting class node $classId" }
} }
override fun addClassNode(classId: ClassId, node: CirClassNode) { override fun addTypeAliasNode(typeAliasId: ClassId, node: CirTypeAliasNode) {
val oldNode = classNodes.put(classId, node) val oldNode = typeAliases.put(typeAliasId, node)
check(oldNode == null) { "Rewriting class node $classId" } check(oldNode == null) { "Rewriting type alias node $typeAliasId" }
} }
}
override fun addTypeAliasNode(typeAliasId: ClassId, node: CirTypeAliasNode) { }
val oldNode = typeAliases.put(typeAliasId, node) }
check(oldNode == null) { "Rewriting type alias node $typeAliasId" }
interface CirForwardDeclarations {
/* Accessors */
fun isExportedForwardDeclaration(classId: ClassId): Boolean
/* Mutators */
fun addExportedForwardDeclaration(classId: ClassId)
companion object {
fun default() = object : CirForwardDeclarations {
private val exportedForwardDeclarations = THashSet<ClassId>()
override fun isExportedForwardDeclaration(classId: ClassId) = classId in exportedForwardDeclarations
override fun addExportedForwardDeclaration(classId: ClassId) {
check(!classId.packageFqName.isUnderKotlinNativeSyntheticPackages)
exportedForwardDeclarations += classId
}
}
}
}
interface CirProvidedClassifiers {
fun hasClassifier(classifierId: ClassId): Boolean
// TODO: implement later
//fun classifier(classifierId: ClassId): Any?
companion object {
// N.B. This is suboptimal implementation. It will be replaced by another implementation that will
// retrieve classifier information directly from the metadata.
fun fromModules(storageManager: StorageManager, modules: () -> Collection<ModuleDescriptor>) = object : CirProvidedClassifiers {
private val nonEmptyMemberScopes: Map<FqName, MemberScope> by storageManager.createLazyValue {
THashMap<FqName, MemberScope>().apply {
for (module in modules()) {
module.collectNonEmptyPackageMemberScopes(probeRootPackageForEmptiness = true) { packageFqName, memberScope ->
this[packageFqName.intern()] = memberScope
}
}
}
}
private val presentClassifiers = THashSet<ClassId>()
private val missingClassifiers = THashSet<ClassId>()
override fun hasClassifier(classifierId: ClassId): Boolean {
val relativeClassName: FqName = classifierId.relativeClassName
if (relativeClassName.isRoot)
return false
val packageFqName = classifierId.packageFqName
val memberScope = nonEmptyMemberScopes[packageFqName] ?: return false
return when (classifierId) {
in presentClassifiers -> true
in missingClassifiers -> false
else -> {
val found = memberScope.resolveClassOrTypeAlias(relativeClassName) != null
when (found) {
true -> presentClassifiers += classifierId
false -> missingClassifiers += classifierId
}
found
}
}
}
}
} }
} }
@@ -48,7 +48,7 @@ import org.jetbrains.kotlin.storage.StorageManager
*/ */
class CirTreeMerger( class CirTreeMerger(
private val storageManager: StorageManager, private val storageManager: StorageManager,
private val cache: CirClassifiersCache, private val classifiers: CirKnownClassifiers,
private val parameters: Parameters private val parameters: Parameters
) { ) {
class CirTreeMergeResult( class CirTreeMergeResult(
@@ -183,7 +183,7 @@ class CirTreeMerger(
parentCommonDeclaration: NullableLazyValue<*>? parentCommonDeclaration: NullableLazyValue<*>?
) { ) {
val propertyNode: CirPropertyNode = properties.getOrPut(PropertyApproximationKey(propertyDescriptor)) { val propertyNode: CirPropertyNode = properties.getOrPut(PropertyApproximationKey(propertyDescriptor)) {
buildPropertyNode(storageManager, size, cache, parentCommonDeclaration) buildPropertyNode(storageManager, size, classifiers, parentCommonDeclaration)
} }
propertyNode.targetDeclarations[targetIndex] = CirPropertyFactory.create(propertyDescriptor) propertyNode.targetDeclarations[targetIndex] = CirPropertyFactory.create(propertyDescriptor)
} }
@@ -195,7 +195,7 @@ class CirTreeMerger(
parentCommonDeclaration: NullableLazyValue<*>? parentCommonDeclaration: NullableLazyValue<*>?
) { ) {
val functionNode: CirFunctionNode = functions.getOrPut(FunctionApproximationKey(functionDescriptor)) { val functionNode: CirFunctionNode = functions.getOrPut(FunctionApproximationKey(functionDescriptor)) {
buildFunctionNode(storageManager, size, cache, parentCommonDeclaration) buildFunctionNode(storageManager, size, classifiers, parentCommonDeclaration)
} }
functionNode.targetDeclarations[targetIndex] = CirFunctionFactory.create(functionDescriptor) functionNode.targetDeclarations[targetIndex] = CirFunctionFactory.create(functionDescriptor)
} }
@@ -211,7 +211,7 @@ class CirTreeMerger(
val classId = classIdFunction(className) val classId = classIdFunction(className)
val classNode: CirClassNode = classes.getOrPut(className) { val classNode: CirClassNode = classes.getOrPut(className) {
buildClassNode(storageManager, size, cache, parentCommonDeclaration, classId) buildClassNode(storageManager, size, classifiers, parentCommonDeclaration, classId)
} }
classNode.targetDeclarations[targetIndex] = CirClassFactory.create(classDescriptor) classNode.targetDeclarations[targetIndex] = CirClassFactory.create(classDescriptor)
@@ -246,7 +246,7 @@ class CirTreeMerger(
parentCommonDeclaration: NullableLazyValue<*>? parentCommonDeclaration: NullableLazyValue<*>?
) { ) {
val constructorNode: CirClassConstructorNode = constructors.getOrPut(ConstructorApproximationKey(constructorDescriptor)) { val constructorNode: CirClassConstructorNode = constructors.getOrPut(ConstructorApproximationKey(constructorDescriptor)) {
buildClassConstructorNode(storageManager, size, cache, parentCommonDeclaration) buildClassConstructorNode(storageManager, size, classifiers, parentCommonDeclaration)
} }
constructorNode.targetDeclarations[targetIndex] = CirClassConstructorFactory.create(constructorDescriptor) constructorNode.targetDeclarations[targetIndex] = CirClassConstructorFactory.create(constructorDescriptor)
} }
@@ -261,7 +261,7 @@ class CirTreeMerger(
val typeAliasClassId = internedClassId(packageFqName, typeAliasName) val typeAliasClassId = internedClassId(packageFqName, typeAliasName)
val typeAliasNode: CirTypeAliasNode = typeAliases.getOrPut(typeAliasName) { val typeAliasNode: CirTypeAliasNode = typeAliases.getOrPut(typeAliasName) {
buildTypeAliasNode(storageManager, size, cache, typeAliasClassId) buildTypeAliasNode(storageManager, size, classifiers, typeAliasClassId)
} }
typeAliasNode.targetDeclarations[targetIndex] = CirTypeAliasFactory.create(typeAliasDescriptor) typeAliasNode.targetDeclarations[targetIndex] = CirTypeAliasFactory.create(typeAliasDescriptor)
} }
@@ -274,7 +274,7 @@ class CirTreeMerger(
exportForwardDeclarations.forEach { classFqName -> exportForwardDeclarations.forEach { classFqName ->
// Class has synthetic package FQ name (cnames/objcnames). Need to transfer it to the main package. // Class has synthetic package FQ name (cnames/objcnames). Need to transfer it to the main package.
val className = Name.identifier(classFqName.substringAfterLast('.')).intern() val className = Name.identifier(classFqName.substringAfterLast('.')).intern()
cache.addExportedForwardDeclaration(internedClassId(mainPackageFqName, className)) classifiers.forwardDeclarations.addExportedForwardDeclaration(internedClassId(mainPackageFqName, className))
} }
} }
} }
@@ -64,18 +64,24 @@ internal inline fun FunctionCollector(
} }
// collects member scopes for every non-empty package provided by this module // collects member scopes for every non-empty package provided by this module
internal fun ModuleDescriptor.collectNonEmptyPackageMemberScopes(collector: (FqName, MemberScope) -> Unit) { internal fun ModuleDescriptor.collectNonEmptyPackageMemberScopes(
probeRootPackageForEmptiness: Boolean = false, // false is the default as probing might be expensive and is not always necessary
collector: (FqName, MemberScope) -> Unit
) {
// we don's need to process fragments from other modules which are the dependencies of this module, so // 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 // let's use the appropriate package fragment provider
val packageFragmentProvider = this.packageFragmentProvider val packageFragmentProvider = this.packageFragmentProvider
fun recurse(packageFqName: FqName) { fun recurse(packageFqName: FqName) {
val ownPackageFragments = packageFragmentProvider.packageFragments(packageFqName) val probeForEmptiness = probeRootPackageForEmptiness && packageFqName.isRoot
val ownPackageMemberScopes = ownPackageFragments.asSequence()
val ownPackageMemberScopes = packageFragmentProvider.packageFragments(packageFqName)
.asSequence()
.filter { it !is ExportedForwardDeclarationsPackageFragmentDescriptor && it !is ClassifierAliasingPackageFragmentDescriptor } .filter { it !is ExportedForwardDeclarationsPackageFragmentDescriptor && it !is ClassifierAliasingPackageFragmentDescriptor }
.map { it.getMemberScope() } .map { it.getMemberScope() }
.filter { it != MemberScope.Empty } .filter { it != MemberScope.Empty }
.toList(ownPackageFragments.size) .filter { !probeForEmptiness || it.getContributedDescriptors().isNotEmpty() }
.toList()
if (ownPackageMemberScopes.isNotEmpty()) { if (ownPackageMemberScopes.isNotEmpty()) {
// don't include subpackages into chained member scope // don't include subpackages into chained member scope
@@ -53,44 +53,44 @@ internal fun buildPackageNode(
internal fun buildPropertyNode( internal fun buildPropertyNode(
storageManager: StorageManager, storageManager: StorageManager,
size: Int, size: Int,
cache: CirClassifiersCache, classifiers: CirKnownClassifiers,
parentCommonDeclaration: NullableLazyValue<*>? parentCommonDeclaration: NullableLazyValue<*>?
): CirPropertyNode = buildNode( ): CirPropertyNode = buildNode(
storageManager = storageManager, storageManager = storageManager,
size = size, size = size,
parentCommonDeclaration = parentCommonDeclaration, parentCommonDeclaration = parentCommonDeclaration,
commonizerProducer = { PropertyCommonizer(cache) }, commonizerProducer = { PropertyCommonizer(classifiers) },
nodeProducer = ::CirPropertyNode nodeProducer = ::CirPropertyNode
) )
internal fun buildFunctionNode( internal fun buildFunctionNode(
storageManager: StorageManager, storageManager: StorageManager,
size: Int, size: Int,
cache: CirClassifiersCache, classifiers: CirKnownClassifiers,
parentCommonDeclaration: NullableLazyValue<*>? parentCommonDeclaration: NullableLazyValue<*>?
): CirFunctionNode = buildNode( ): CirFunctionNode = buildNode(
storageManager = storageManager, storageManager = storageManager,
size = size, size = size,
parentCommonDeclaration = parentCommonDeclaration, parentCommonDeclaration = parentCommonDeclaration,
commonizerProducer = { FunctionCommonizer(cache) }, commonizerProducer = { FunctionCommonizer(classifiers) },
nodeProducer = ::CirFunctionNode nodeProducer = ::CirFunctionNode
) )
internal fun buildClassNode( internal fun buildClassNode(
storageManager: StorageManager, storageManager: StorageManager,
size: Int, size: Int,
cache: CirClassifiersCache, classifiers: CirKnownClassifiers,
parentCommonDeclaration: NullableLazyValue<*>?, parentCommonDeclaration: NullableLazyValue<*>?,
classId: ClassId classId: ClassId
): CirClassNode = buildNode( ): CirClassNode = buildNode(
storageManager = storageManager, storageManager = storageManager,
size = size, size = size,
parentCommonDeclaration = parentCommonDeclaration, parentCommonDeclaration = parentCommonDeclaration,
commonizerProducer = { ClassCommonizer(cache) }, commonizerProducer = { ClassCommonizer(classifiers) },
recursionMarker = CirClassRecursionMarker, recursionMarker = CirClassRecursionMarker,
nodeProducer = { targetDeclarations, commonDeclaration -> nodeProducer = { targetDeclarations, commonDeclaration ->
CirClassNode(targetDeclarations, commonDeclaration, classId).also { CirClassNode(targetDeclarations, commonDeclaration, classId).also {
cache.addClassNode(classId, it) classifiers.commonized.addClassNode(classId, it)
} }
} }
) )
@@ -98,29 +98,29 @@ internal fun buildClassNode(
internal fun buildClassConstructorNode( internal fun buildClassConstructorNode(
storageManager: StorageManager, storageManager: StorageManager,
size: Int, size: Int,
cache: CirClassifiersCache, classifiers: CirKnownClassifiers,
parentCommonDeclaration: NullableLazyValue<*>? parentCommonDeclaration: NullableLazyValue<*>?
): CirClassConstructorNode = buildNode( ): CirClassConstructorNode = buildNode(
storageManager = storageManager, storageManager = storageManager,
size = size, size = size,
parentCommonDeclaration = parentCommonDeclaration, parentCommonDeclaration = parentCommonDeclaration,
commonizerProducer = { ClassConstructorCommonizer(cache) }, commonizerProducer = { ClassConstructorCommonizer(classifiers) },
nodeProducer = ::CirClassConstructorNode nodeProducer = ::CirClassConstructorNode
) )
internal fun buildTypeAliasNode( internal fun buildTypeAliasNode(
storageManager: StorageManager, storageManager: StorageManager,
size: Int, size: Int,
cache: CirClassifiersCache, classifiers: CirKnownClassifiers,
typeAliasId: ClassId typeAliasId: ClassId
): CirTypeAliasNode = buildNode( ): CirTypeAliasNode = buildNode(
storageManager = storageManager, storageManager = storageManager,
size = size, size = size,
commonizerProducer = { TypeAliasCommonizer(cache) }, commonizerProducer = { TypeAliasCommonizer(classifiers) },
recursionMarker = CirClassifierRecursionMarker, recursionMarker = CirClassifierRecursionMarker,
nodeProducer = { targetDeclarations, commonDeclaration -> nodeProducer = { targetDeclarations, commonDeclaration ->
CirTypeAliasNode(targetDeclarations, commonDeclaration, typeAliasId).also { CirTypeAliasNode(targetDeclarations, commonDeclaration, typeAliasId).also {
cache.addTypeAliasNode(typeAliasId, it) classifiers.commonized.addTypeAliasNode(typeAliasId, it)
} }
} }
) )
@@ -43,8 +43,6 @@ private fun checkConstantSupportedInCommonization(
} }
is AnnotationValue -> { is AnnotationValue -> {
if (allowAnnotationValues) { if (allowAnnotationValues) {
if (constantValue.value.fqName?.isUnderStandardKotlinPackages != true)
onError("Only ${constantValue::class.java} const values from Kotlin standard packages are supported, $constantValue at ${location()}")
return // OK return // OK
} // else fail (see below) } // else fail (see below)
} }
@@ -15,12 +15,6 @@ import java.util.Collections.singletonList
import java.util.Collections.singletonMap import java.util.Collections.singletonMap
import kotlin.collections.ArrayList import kotlin.collections.ArrayList
internal fun <T> Sequence<T>.toList(expectedCapacity: Int): List<T> {
val result = ArrayList<T>(expectedCapacity)
toCollection(result)
return result
}
internal infix fun <K, V> Map<K, V>.compactConcat(other: Map<K, V>): Map<K, V> = internal infix fun <K, V> Map<K, V>.compactConcat(other: Map<K, V>): Map<K, V> =
when { when {
isEmpty() -> other isEmpty() -> other
@@ -15,6 +15,7 @@ import org.jetbrains.kotlin.library.metadata.NativeTypeTransformer
import org.jetbrains.kotlin.library.metadata.NullFlexibleTypeDeserializer import org.jetbrains.kotlin.library.metadata.NullFlexibleTypeDeserializer
import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.resolve.scopes.MemberScope
import org.jetbrains.kotlin.serialization.konan.impl.KlibResolvedModuleDescriptorsFactoryImpl import org.jetbrains.kotlin.serialization.konan.impl.KlibResolvedModuleDescriptorsFactoryImpl
import org.jetbrains.kotlin.storage.StorageManager import org.jetbrains.kotlin.storage.StorageManager
@@ -38,29 +39,35 @@ internal fun ModuleDescriptor.resolveClassOrTypeAlias(classId: ClassId): Classif
return null return null
return packageFragmentProvider.packageFragments(classId.packageFqName).asSequence().mapNotNull { packageFragment -> return packageFragmentProvider.packageFragments(classId.packageFqName).asSequence().mapNotNull { packageFragment ->
var memberScope = packageFragment.getMemberScope() packageFragment.getMemberScope().resolveClassOrTypeAlias(relativeClassName)
val classifierName = if ('.' in relativeClassName.asString()) {
// resolve member scope of the nested class
relativeClassName.pathSegments().reduce { first, second ->
memberScope = (memberScope.getContributedClassifier(
first,
NoLookupLocation.FOR_ALREADY_TRACKED
) as? ClassDescriptor)?.unsubstitutedMemberScope ?: return@mapNotNull null
second
}
} else {
relativeClassName.shortName()
}
memberScope.getContributedClassifier(
classifierName,
NoLookupLocation.FOR_ALREADY_TRACKED
) as? ClassifierDescriptorWithTypeParameters
}.firstOrNull() }.firstOrNull()
} }
internal fun MemberScope.resolveClassOrTypeAlias(relativeClassName: FqName): ClassifierDescriptorWithTypeParameters? {
var memberScope: MemberScope = this
if (memberScope is MemberScope.Empty)
return null
val classifierName = if ('.' in relativeClassName.asString()) {
// resolve member scope of the nested class
relativeClassName.pathSegments().reduce { first, second ->
memberScope = (memberScope.getContributedClassifier(
first,
NoLookupLocation.FOR_ALREADY_TRACKED
) as? ClassDescriptor)?.unsubstitutedMemberScope ?: return null
second
}
} else {
relativeClassName.shortName()
}
return memberScope.getContributedClassifier(
classifierName,
NoLookupLocation.FOR_ALREADY_TRACKED
) as? ClassifierDescriptorWithTypeParameters
}
internal const val MODULE_NAME_PREFIX = "module:" internal const val MODULE_NAME_PREFIX = "module:"
internal val NativeFactories = KlibMetadataFactories(::KonanBuiltIns, NullFlexibleTypeDeserializer, NativeTypeTransformer()) internal val NativeFactories = KlibMetadataFactories(::KonanBuiltIns, NullFlexibleTypeDeserializer, NativeTypeTransformer())
@@ -11,6 +11,7 @@ import org.jetbrains.kotlin.analyzer.ModuleInfo
import org.jetbrains.kotlin.analyzer.common.CommonDependenciesContainer import org.jetbrains.kotlin.analyzer.common.CommonDependenciesContainer
import org.jetbrains.kotlin.analyzer.common.CommonPlatformAnalyzerServices import org.jetbrains.kotlin.analyzer.common.CommonPlatformAnalyzerServices
import org.jetbrains.kotlin.analyzer.common.CommonResolverForModuleFactory import org.jetbrains.kotlin.analyzer.common.CommonResolverForModuleFactory
import org.jetbrains.kotlin.builtins.DefaultBuiltIns
import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
import org.jetbrains.kotlin.config.CommonConfigurationKeys import org.jetbrains.kotlin.config.CommonConfigurationKeys
@@ -174,16 +175,13 @@ private class AnalyzedModuleDependencies(
companion object { companion object {
val EMPTY = AnalyzedModuleDependencies(emptyMap(), emptyList()) val EMPTY = AnalyzedModuleDependencies(emptyMap(), emptyList())
fun create(regularDependencies: Map<Target, ModuleDescriptor>, expectByDependencies: List<ModuleDescriptor>) =
AnalyzedModuleDependencies(regularDependencies.mapValues { listOf(it.value) }, expectByDependencies)
} }
} }
private class AnalyzedModules( private class AnalyzedModules(
val originalModules: Map<Target, ModuleDescriptor>, val originalModules: Map<Target, ModuleDescriptor>,
val commonizedModules: Map<Target, ModuleDescriptor>, val commonizedModules: Map<Target, ModuleDescriptor>,
val dependeeModules: Map<Target, ModuleDescriptor> val dependeeModules: Map<Target, List<ModuleDescriptor>>
) { ) {
val leafTargets: Set<LeafTarget> val leafTargets: Set<LeafTarget>
val sharedTarget: SharedTarget val sharedTarget: SharedTarget
@@ -214,13 +212,13 @@ private class AnalyzedModules(
target = leafTarget, target = leafTarget,
builtInsClass = originalModule.builtIns::class.java, builtInsClass = originalModule.builtIns::class.java,
builtInsProvider = MockBuiltInsProvider(originalModule.builtIns), builtInsProvider = MockBuiltInsProvider(originalModule.builtIns),
modulesProvider = MockModulesProvider(originalModule), modulesProvider = MockModulesProvider.create(originalModule),
dependeeModulesProvider = dependeeModules[leafTarget]?.let(::MockModulesProvider) dependeeModulesProvider = dependeeModules[leafTarget]?.let(MockModulesProvider::create)
) )
) )
} }
parameters.dependeeModulesProvider = dependeeModules[sharedTarget]?.let(::MockModulesProvider) parameters.dependeeModulesProvider = dependeeModules[sharedTarget]?.let(MockModulesProvider::create)
return parameters return parameters
} }
@@ -230,22 +228,37 @@ private class AnalyzedModules(
sourceModuleRoots: SourceModuleRoots, sourceModuleRoots: SourceModuleRoots,
parentDisposable: Disposable parentDisposable: Disposable
): AnalyzedModules = with(sourceModuleRoots) { ): AnalyzedModules = with(sourceModuleRoots) {
// first, build the modules that are are the dependencies for "original" and "commonized" modules // phase 1: provide the modules that are the dependencies for "original" and "commonized" modules
val dependeeModules = val (dependeeModules, dependencies) = createDependeeModules(sharedTarget, dependeeRoots, parentDisposable)
createModules(sharedTarget, dependeeRoots, AnalyzedModuleDependencies.EMPTY, parentDisposable, isDependeeModule = true)
val dependencies = AnalyzedModuleDependencies.create( // phase 2: build "original" and "commonized" modules
regularDependencies = dependeeModules,
expectByDependencies = listOfNotNull(dependeeModules[sharedTarget])
)
// then, build "original" and "commonized" modules
val originalModules = createModules(sharedTarget, originalRoots, dependencies, parentDisposable) val originalModules = createModules(sharedTarget, originalRoots, dependencies, parentDisposable)
val commonizedModules = createModules(sharedTarget, commonizedRoots, dependencies, parentDisposable) val commonizedModules = createModules(sharedTarget, commonizedRoots, dependencies, parentDisposable)
return AnalyzedModules(originalModules, commonizedModules, dependeeModules) return AnalyzedModules(originalModules, commonizedModules, dependeeModules)
} }
private fun createDependeeModules(
sharedTarget: SharedTarget,
dependeeRoots: Map<out Target, SourceModuleRoot>,
parentDisposable: Disposable
): Pair<Map<Target, List<ModuleDescriptor>>, AnalyzedModuleDependencies> {
val customDependeeModules =
createModules(sharedTarget, dependeeRoots, AnalyzedModuleDependencies.EMPTY, parentDisposable, isDependeeModule = true)
val stdlibModule = DefaultBuiltIns.Instance.builtInsModule
val dependeeModules = (sharedTarget.targets + sharedTarget).associateWith { target ->
// prepend stdlib for each target explicitly, so that the commonizer can see symbols from the stdlib
listOfNotNull(stdlibModule, customDependeeModules[target])
}
return dependeeModules to AnalyzedModuleDependencies(
regularDependencies = dependeeModules,
expectByDependencies = dependeeModules.getValue(sharedTarget).filter { module -> module !== stdlibModule }
)
}
private fun createModules( private fun createModules(
sharedTarget: SharedTarget, sharedTarget: SharedTarget,
moduleRoots: Map<out Target, SourceModuleRoot>, moduleRoots: Map<out Target, SourceModuleRoot>,
@@ -67,7 +67,7 @@ class CommonizerFacadeTest {
target = LeafTarget(targetName), target = LeafTarget(targetName),
builtInsClass = DefaultBuiltIns::class.java, builtInsClass = DefaultBuiltIns::class.java,
builtInsProvider = BuiltInsProvider.defaultBuiltInsProvider, builtInsProvider = BuiltInsProvider.defaultBuiltInsProvider,
modulesProvider = MockModulesProvider(moduleNames), modulesProvider = MockModulesProvider.create(moduleNames),
dependeeModulesProvider = null dependeeModulesProvider = null
) )
) )
@@ -8,7 +8,7 @@ package org.jetbrains.kotlin.descriptors.commonizer.core
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirExtensionReceiver import org.jetbrains.kotlin.descriptors.commonizer.cir.CirExtensionReceiver
import org.jetbrains.kotlin.descriptors.commonizer.cir.factory.CirExtensionReceiverFactory import org.jetbrains.kotlin.descriptors.commonizer.cir.factory.CirExtensionReceiverFactory
import org.jetbrains.kotlin.descriptors.commonizer.cir.factory.CirTypeFactory import org.jetbrains.kotlin.descriptors.commonizer.cir.factory.CirTypeFactory
import org.jetbrains.kotlin.descriptors.commonizer.utils.MOCK_CLASSIFIERS_CACHE import org.jetbrains.kotlin.descriptors.commonizer.utils.MOCK_CLASSIFIERS
import org.jetbrains.kotlin.descriptors.commonizer.utils.mockClassType import org.jetbrains.kotlin.descriptors.commonizer.utils.mockClassType
import org.junit.Test import org.junit.Test
@@ -49,7 +49,7 @@ class ExtensionReceiverCommonizerTest : AbstractCommonizerTest<CirExtensionRecei
mockExtensionReceiver("kotlin.String") mockExtensionReceiver("kotlin.String")
) )
override fun createCommonizer() = ExtensionReceiverCommonizer(MOCK_CLASSIFIERS_CACHE) override fun createCommonizer() = ExtensionReceiverCommonizer(MOCK_CLASSIFIERS)
} }
private fun mockExtensionReceiver(typeFqName: String) = CirExtensionReceiverFactory.create( private fun mockExtensionReceiver(typeFqName: String) = CirExtensionReceiverFactory.create(
@@ -7,11 +7,14 @@ package org.jetbrains.kotlin.descriptors.commonizer.core
import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.TypeAliasDescriptor import org.jetbrains.kotlin.descriptors.TypeAliasDescriptor
import org.jetbrains.kotlin.descriptors.commonizer.LeafTarget
import org.jetbrains.kotlin.descriptors.commonizer.SharedTarget
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirType import org.jetbrains.kotlin.descriptors.commonizer.cir.CirType
import org.jetbrains.kotlin.descriptors.commonizer.cir.factory.CirClassFactory import org.jetbrains.kotlin.descriptors.commonizer.cir.factory.CirClassFactory
import org.jetbrains.kotlin.descriptors.commonizer.cir.factory.CirTypeAliasFactory import org.jetbrains.kotlin.descriptors.commonizer.cir.factory.CirTypeAliasFactory
import org.jetbrains.kotlin.descriptors.commonizer.cir.factory.CirTypeFactory import org.jetbrains.kotlin.descriptors.commonizer.cir.factory.CirTypeFactory
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.* import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.*
import org.jetbrains.kotlin.descriptors.commonizer.utils.isUnderStandardKotlinPackages
import org.jetbrains.kotlin.descriptors.commonizer.utils.mockClassType import org.jetbrains.kotlin.descriptors.commonizer.utils.mockClassType
import org.jetbrains.kotlin.descriptors.commonizer.utils.mockTAType import org.jetbrains.kotlin.descriptors.commonizer.utils.mockTAType
import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.ClassId
@@ -24,11 +27,20 @@ import org.junit.Test
class TypeCommonizerTest : AbstractCommonizerTest<CirType, CirType>() { class TypeCommonizerTest : AbstractCommonizerTest<CirType, CirType>() {
private lateinit var cache: CirClassifiersCache private lateinit var classifiers: CirKnownClassifiers
@Before @Before
fun initialize() { fun initialize() {
cache = DefaultCirClassifiersCache() // reset cache // reset cache
classifiers = CirKnownClassifiers(
commonized = CirCommonizedClassifiers.default(),
forwardDeclarations = CirForwardDeclarations.default(),
dependeeLibraries = mapOf(
FAKE_SHARED_TARGET to object : CirProvidedClassifiers {
override fun hasClassifier(classifierId: ClassId): Boolean = classifierId.packageFqName.isUnderStandardKotlinPackages
}
)
)
} }
@Test @Test
@@ -465,11 +477,11 @@ class TypeCommonizerTest : AbstractCommonizerTest<CirType, CirType>() {
when (descriptor) { when (descriptor) {
is ClassDescriptor -> { is ClassDescriptor -> {
val classId = descriptor.classId ?: error("No class ID for ${descriptor::class.java}, $descriptor") val classId = descriptor.classId ?: error("No class ID for ${descriptor::class.java}, $descriptor")
val node = cache.classNode(classId) { val node = classifiers.classNode(classId) {
buildClassNode( buildClassNode(
storageManager = LockBasedStorageManager.NO_LOCKS, storageManager = LockBasedStorageManager.NO_LOCKS,
size = variants.size, size = variants.size,
cache = cache, classifiers = classifiers,
parentCommonDeclaration = null, parentCommonDeclaration = null,
classId = classId classId = classId
) )
@@ -478,11 +490,11 @@ class TypeCommonizerTest : AbstractCommonizerTest<CirType, CirType>() {
} }
is TypeAliasDescriptor -> { is TypeAliasDescriptor -> {
val typeAliasId = descriptor.classId ?: error("No class ID for ${descriptor::class.java}, $descriptor") val typeAliasId = descriptor.classId ?: error("No class ID for ${descriptor::class.java}, $descriptor")
val node = cache.typeAliasNode(typeAliasId) { val node = classifiers.typeAliasNode(typeAliasId) {
buildTypeAliasNode( buildTypeAliasNode(
storageManager = LockBasedStorageManager.NO_LOCKS, storageManager = LockBasedStorageManager.NO_LOCKS,
size = variants.size, size = variants.size,
cache = cache, classifiers = classifiers,
typeAliasId = typeAliasId typeAliasId = typeAliasId
) )
} }
@@ -517,18 +529,20 @@ class TypeCommonizerTest : AbstractCommonizerTest<CirType, CirType>() {
) )
} }
override fun createCommonizer() = TypeCommonizer(cache) override fun createCommonizer() = TypeCommonizer(classifiers)
override fun isEqual(a: CirType?, b: CirType?) = (a === b) || (a != null && b != null && areEqual(cache, a, b)) override fun isEqual(a: CirType?, b: CirType?) = (a === b) || (a != null && b != null && areEqual(classifiers, a, b))
companion object { companion object {
fun areEqual(cache: CirClassifiersCache, a: CirType, b: CirType): Boolean = fun areEqual(classifiers: CirKnownClassifiers, a: CirType, b: CirType): Boolean =
TypeCommonizer(cache).run { commonizeWith(a) && commonizeWith(b) } TypeCommonizer(classifiers).run { commonizeWith(a) && commonizeWith(b) }
private fun CirClassifiersCache.classNode(classId: ClassId, computation: () -> CirClassNode) = private val FAKE_SHARED_TARGET = SharedTarget(setOf(LeafTarget("a"), LeafTarget("b")))
classNode(classId) ?: computation()
private fun CirClassifiersCache.typeAliasNode(typeAliasId: ClassId, computation: () -> CirTypeAliasNode) = private fun CirKnownClassifiers.classNode(classId: ClassId, computation: () -> CirClassNode) =
typeAliasNode(typeAliasId) ?: computation() commonized.classNode(classId) ?: computation()
private fun CirKnownClassifiers.typeAliasNode(typeAliasId: ClassId, computation: () -> CirTypeAliasNode) =
commonized.typeAliasNode(typeAliasId) ?: computation()
} }
} }
@@ -8,14 +8,14 @@ package org.jetbrains.kotlin.descriptors.commonizer.core
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirTypeParameter import org.jetbrains.kotlin.descriptors.commonizer.cir.CirTypeParameter
import org.jetbrains.kotlin.descriptors.commonizer.cir.factory.CirTypeFactory import org.jetbrains.kotlin.descriptors.commonizer.cir.factory.CirTypeFactory
import org.jetbrains.kotlin.descriptors.commonizer.cir.factory.CirTypeParameterFactory import org.jetbrains.kotlin.descriptors.commonizer.cir.factory.CirTypeParameterFactory
import org.jetbrains.kotlin.descriptors.commonizer.utils.MOCK_CLASSIFIERS_CACHE import org.jetbrains.kotlin.descriptors.commonizer.utils.MOCK_CLASSIFIERS
import org.jetbrains.kotlin.descriptors.commonizer.utils.mockClassType import org.jetbrains.kotlin.descriptors.commonizer.utils.mockClassType
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.types.Variance import org.jetbrains.kotlin.types.Variance
import org.junit.Test import org.junit.Test
class TypeParameterCommonizerTest : AbstractCommonizerTest<CirTypeParameter, CirTypeParameter>() { class TypeParameterCommonizerTest : AbstractCommonizerTest<CirTypeParameter, CirTypeParameter>() {
override fun createCommonizer() = TypeParameterCommonizer(MOCK_CLASSIFIERS_CACHE) override fun createCommonizer() = TypeParameterCommonizer(MOCK_CLASSIFIERS)
@Test @Test
fun allAreReified() = doTestSuccess( fun allAreReified() = doTestSuccess(
@@ -6,7 +6,7 @@
package org.jetbrains.kotlin.descriptors.commonizer.core package org.jetbrains.kotlin.descriptors.commonizer.core
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirTypeParameter import org.jetbrains.kotlin.descriptors.commonizer.cir.CirTypeParameter
import org.jetbrains.kotlin.descriptors.commonizer.utils.MOCK_CLASSIFIERS_CACHE import org.jetbrains.kotlin.descriptors.commonizer.utils.MOCK_CLASSIFIERS
import org.junit.Test import org.junit.Test
class TypeParameterListCommonizerTest : AbstractCommonizerTest<List<CirTypeParameter>, List<CirTypeParameter>>() { class TypeParameterListCommonizerTest : AbstractCommonizerTest<List<CirTypeParameter>, List<CirTypeParameter>>() {
@@ -108,7 +108,7 @@ class TypeParameterListCommonizerTest : AbstractCommonizerTest<List<CirTypeParam
) )
) )
override fun createCommonizer() = TypeParameterListCommonizer(MOCK_CLASSIFIERS_CACHE) override fun createCommonizer() = TypeParameterListCommonizer(MOCK_CLASSIFIERS)
private companion object { private companion object {
fun mockTypeParams(vararg params: Pair<String, String>): List<CirTypeParameter> { fun mockTypeParams(vararg params: Pair<String, String>): List<CirTypeParameter> {
@@ -11,8 +11,8 @@ import org.jetbrains.kotlin.descriptors.commonizer.cir.CirValueParameter
import org.jetbrains.kotlin.descriptors.commonizer.cir.factory.CirTypeFactory import org.jetbrains.kotlin.descriptors.commonizer.cir.factory.CirTypeFactory
import org.jetbrains.kotlin.descriptors.commonizer.core.CirTestValueParameter.Companion.areEqual import org.jetbrains.kotlin.descriptors.commonizer.core.CirTestValueParameter.Companion.areEqual
import org.jetbrains.kotlin.descriptors.commonizer.core.TypeCommonizerTest.Companion.areEqual import org.jetbrains.kotlin.descriptors.commonizer.core.TypeCommonizerTest.Companion.areEqual
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.CirClassifiersCache import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.CirKnownClassifiers
import org.jetbrains.kotlin.descriptors.commonizer.utils.MOCK_CLASSIFIERS_CACHE import org.jetbrains.kotlin.descriptors.commonizer.utils.MOCK_CLASSIFIERS
import org.jetbrains.kotlin.descriptors.commonizer.utils.mockClassType import org.jetbrains.kotlin.descriptors.commonizer.utils.mockClassType
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.junit.Test import org.junit.Test
@@ -141,10 +141,10 @@ class ValueParameterCommonizerTest : AbstractCommonizerTest<CirValueParameter, C
mockValueParam("kotlin.String", declaresDefaultValue = true) mockValueParam("kotlin.String", declaresDefaultValue = true)
) )
override fun createCommonizer() = ValueParameterCommonizer(MOCK_CLASSIFIERS_CACHE) override fun createCommonizer() = ValueParameterCommonizer(MOCK_CLASSIFIERS)
override fun isEqual(a: CirValueParameter?, b: CirValueParameter?) = override fun isEqual(a: CirValueParameter?, b: CirValueParameter?) =
(a === b) || (a != null && b != null && areEqual(MOCK_CLASSIFIERS_CACHE, a, b)) (a === b) || (a != null && b != null && areEqual(MOCK_CLASSIFIERS, a, b))
internal companion object { internal companion object {
fun mockValueParam( fun mockValueParam(
@@ -180,9 +180,9 @@ internal data class CirTestValueParameter(
override val isNoinline: Boolean override val isNoinline: Boolean
) : CirValueParameter { ) : CirValueParameter {
companion object { companion object {
fun areEqual(cache: CirClassifiersCache, a: CirValueParameter, b: CirValueParameter): Boolean { fun areEqual(classifiers: CirKnownClassifiers, a: CirValueParameter, b: CirValueParameter): Boolean {
if (a.name != b.name if (a.name != b.name
|| !areEqual(cache, a.returnType, b.returnType) || !areEqual(classifiers, a.returnType, b.returnType)
|| a.declaresDefaultValue != b.declaresDefaultValue || a.declaresDefaultValue != b.declaresDefaultValue
|| a.isCrossinline != b.isCrossinline || a.isCrossinline != b.isCrossinline
|| a.isNoinline != b.isNoinline || a.isNoinline != b.isNoinline
@@ -195,7 +195,7 @@ internal data class CirTestValueParameter(
return (aVarargElementType === bVarargElementType) return (aVarargElementType === bVarargElementType)
|| (aVarargElementType != null && bVarargElementType != null || (aVarargElementType != null && bVarargElementType != null
&& areEqual(cache, aVarargElementType, bVarargElementType)) && areEqual(classifiers, aVarargElementType, bVarargElementType))
} }
} }
} }
@@ -7,7 +7,7 @@ package org.jetbrains.kotlin.descriptors.commonizer.core
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirValueParameter import org.jetbrains.kotlin.descriptors.commonizer.cir.CirValueParameter
import org.jetbrains.kotlin.descriptors.commonizer.core.CirTestValueParameter.Companion.areEqual import org.jetbrains.kotlin.descriptors.commonizer.core.CirTestValueParameter.Companion.areEqual
import org.jetbrains.kotlin.descriptors.commonizer.utils.MOCK_CLASSIFIERS_CACHE import org.jetbrains.kotlin.descriptors.commonizer.utils.MOCK_CLASSIFIERS
import org.junit.Test import org.junit.Test
class ValueParameterListCommonizerTest : AbstractCommonizerTest<List<CirValueParameter>, List<CirValueParameter>>() { class ValueParameterListCommonizerTest : AbstractCommonizerTest<List<CirValueParameter>, List<CirValueParameter>>() {
@@ -150,7 +150,7 @@ class ValueParameterListCommonizerTest : AbstractCommonizerTest<List<CirValuePar
) )
) )
override fun createCommonizer() = ValueParameterListCommonizer(MOCK_CLASSIFIERS_CACHE) override fun createCommonizer() = ValueParameterListCommonizer(MOCK_CLASSIFIERS)
override fun isEqual(a: List<CirValueParameter>?, b: List<CirValueParameter>?): Boolean { override fun isEqual(a: List<CirValueParameter>?, b: List<CirValueParameter>?): Boolean {
if (a === b) if (a === b)
@@ -159,7 +159,7 @@ class ValueParameterListCommonizerTest : AbstractCommonizerTest<List<CirValuePar
return false return false
for (i in a.indices) { for (i in a.indices) {
if (!areEqual(MOCK_CLASSIFIERS_CACHE, a[i], b[i])) if (!areEqual(MOCK_CLASSIFIERS, a[i], b[i]))
return false return false
} }
@@ -15,9 +15,7 @@ import org.jetbrains.kotlin.descriptors.commonizer.ModulesProvider
import org.jetbrains.kotlin.descriptors.commonizer.ModulesProvider.ModuleInfo import org.jetbrains.kotlin.descriptors.commonizer.ModulesProvider.ModuleInfo
import org.jetbrains.kotlin.descriptors.commonizer.builder.* import org.jetbrains.kotlin.descriptors.commonizer.builder.*
import org.jetbrains.kotlin.descriptors.commonizer.cir.factory.CirClassFactory import org.jetbrains.kotlin.descriptors.commonizer.cir.factory.CirClassFactory
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.CirClassNode import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.*
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.CirClassifiersCache
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.CirTypeAliasNode
import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
@@ -122,57 +120,69 @@ private fun createPackageFragmentForClassifier(classifierFqName: FqName): Packag
override fun toString() = "package $name" override fun toString() = "package $name"
} }
internal val MOCK_CLASSIFIERS_CACHE = object : CirClassifiersCache { internal val MOCK_CLASSIFIERS = CirKnownClassifiers(
private val MOCK_CLASS_NODE = CirClassNode( commonized = object : CirCommonizedClassifiers {
CommonizedGroup(0), private val MOCK_CLASS_NODE = CirClassNode(
LockBasedStorageManager.NO_LOCKS.createNullableLazyValue { CommonizedGroup(0),
CirClassFactory.create( LockBasedStorageManager.NO_LOCKS.createNullableLazyValue {
annotations = emptyList(), CirClassFactory.create(
name = Name.identifier("kotlin.Any"), annotations = emptyList(),
typeParameters = emptyList(), name = Name.identifier("kotlin.Any"),
visibility = DescriptorVisibilities.PUBLIC, typeParameters = emptyList(),
modality = Modality.OPEN, visibility = DescriptorVisibilities.PUBLIC,
kind = ClassKind.CLASS, modality = Modality.OPEN,
companion = null, kind = ClassKind.CLASS,
isCompanion = false, companion = null,
isData = false, isCompanion = false,
isInline = false, isData = false,
isInner = false, isInline = false,
isExternal = false isInner = false,
) isExternal = false
}, )
ClassId.fromString("kotlin/Any") },
) ClassId.fromString("kotlin/Any")
)
override fun isExportedForwardDeclaration(classId: ClassId) = false override fun classNode(classId: ClassId) = MOCK_CLASS_NODE
override fun classNode(classId: ClassId) = MOCK_CLASS_NODE override fun typeAliasNode(typeAliasId: ClassId) = error("This method should not be called")
override fun typeAliasNode(typeAliasId: ClassId) = error("This method should not be called") override fun addClassNode(classId: ClassId, node: CirClassNode) = error("This method should not be called")
override fun addExportedForwardDeclaration(classId: ClassId) = error("This method should not be called") override fun addTypeAliasNode(typeAliasId: ClassId, node: CirTypeAliasNode) = error("This method should not be called")
override fun addClassNode(classId: ClassId, node: CirClassNode) = error("This method should not be called") },
override fun addTypeAliasNode(typeAliasId: ClassId, node: CirTypeAliasNode) = error("This method should not be called") forwardDeclarations = object : CirForwardDeclarations {
} override fun isExportedForwardDeclaration(classId: ClassId) = false
override fun addExportedForwardDeclaration(classId: ClassId) = error("This method should not be called")
},
dependeeLibraries = emptyMap()
)
internal class MockBuiltInsProvider(private val builtIns: KotlinBuiltIns) : BuiltInsProvider { internal class MockBuiltInsProvider(private val builtIns: KotlinBuiltIns) : BuiltInsProvider {
override fun loadBuiltIns() = builtIns override fun loadBuiltIns() = builtIns
} }
internal class MockModulesProvider : ModulesProvider { internal class MockModulesProvider private constructor(
private val moduleInfos: Map<String, ModuleInfo> private val modules: Map<String, ModuleDescriptor>,
private val modules: Map<String, ModuleDescriptor> ) : ModulesProvider {
private val moduleInfos: Map<String, ModuleInfo> = modules.mapValues { (name, _) -> fakeModuleInfo(name) }
constructor(moduleNames: Collection<String>) {
moduleInfos = moduleNames.associateWith { name -> fakeModuleInfo(name) }
modules = moduleNames.associateWith { name -> mockEmptyModule("<$name>") }
}
constructor(module: ModuleDescriptor) {
val name = module.name.asString().removeSurrounding("<", ">")
moduleInfos = mapOf(name to fakeModuleInfo(name))
modules = mapOf(name to module)
}
override fun loadModuleInfos() = moduleInfos override fun loadModuleInfos() = moduleInfos
override fun loadModules(dependencies: Collection<ModuleDescriptor>): Map<String, ModuleDescriptor> = modules override fun loadModules(dependencies: Collection<ModuleDescriptor>): Map<String, ModuleDescriptor> = modules
private fun fakeModuleInfo(name: String) = ModuleInfo(name, File("/tmp/commonizer/mocks/$name"), null) private fun fakeModuleInfo(name: String) = ModuleInfo(name, File("/tmp/commonizer/mocks/$name"), null)
companion object {
@JvmName("createByModuleNames")
fun create(moduleNames: List<String>) = MockModulesProvider(
moduleNames.associateWith { name -> mockEmptyModule("<$name>") }
)
@JvmName("createByModules")
fun create(modules: List<ModuleDescriptor>) = MockModulesProvider(
modules.associateBy { module -> module.name.strip() }
)
@JvmName("createBySingleModule")
fun create(module: ModuleDescriptor) = MockModulesProvider(
mapOf(module.name.strip() to module)
)
}
} }