[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>()
val targetProviders: List<TargetProvider> get() = _targetProviders.values.toList()
val sharedTarget: SharedTarget get() = SharedTarget(_targetProviders.keys)
// common module dependencies (ex: Kotlin stdlib)
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.SYNTHESIZED
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
abstract class AbstractFunctionOrPropertyCommonizer<T : CirFunctionOrProperty>(
cache: CirClassifiersCache
classifiers: CirKnownClassifiers
) : AbstractStandardCommonizer<T, T>() {
protected lateinit var name: Name
protected val modality = ModalityCommonizer()
protected val visibility = VisibilityCommonizer.lowering()
protected val extensionReceiver = ExtensionReceiverCommonizer(cache)
protected val returnType = TypeCommonizer(cache)
protected val extensionReceiver = ExtensionReceiverCommonizer(classifiers)
protected val returnType = TypeCommonizer(classifiers)
protected lateinit var kind: CallableMemberDescriptor.Kind
protected val typeParameters = TypeParameterListCommonizer(cache)
protected val typeParameters = TypeParameterListCommonizer(classifiers)
override fun initialize(first: T) {
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.core.CallableValueParametersCommonizer.CallableToPatch.Companion.doNothing
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.intern
import org.jetbrains.kotlin.descriptors.commonizer.utils.isObjCInteropCallableAnnotation
import org.jetbrains.kotlin.name.Name
class CallableValueParametersCommonizer(
cache: CirClassifiersCache
classifiers: CirKnownClassifiers
) : Commonizer<CirCallableMemberWithParameters, CallableValueParametersCommonizer.Result> {
class Result(
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 var hasStableParameterNames = true
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.commonizer.cir.CirClass
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
class ClassCommonizer(cache: CirClassifiersCache) : AbstractStandardCommonizer<CirClass, CirClass>() {
class ClassCommonizer(classifiers: CirKnownClassifiers) : AbstractStandardCommonizer<CirClass, CirClass>() {
private lateinit var name: Name
private lateinit var kind: ClassKind
private val typeParameters = TypeParameterListCommonizer(cache)
private val typeParameters = TypeParameterListCommonizer(classifiers)
private val modality = ModalityCommonizer()
private val visibility = VisibilityCommonizer.equalizing()
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.factory.CirClassConstructorFactory
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 val visibility = VisibilityCommonizer.equalizing()
private val typeParameters = TypeParameterListCommonizer(cache)
private val valueParameters = CallableValueParametersCommonizer(cache)
private val typeParameters = TypeParameterListCommonizer(classifiers)
private val valueParameters = CallableValueParametersCommonizer(classifiers)
override fun commonizationResult(): CirClassConstructor {
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.compactMapNotNull
import org.jetbrains.kotlin.descriptors.commonizer.utils.internedClassId
import org.jetbrains.kotlin.descriptors.commonizer.utils.isUnderStandardKotlinPackages
internal class CommonizationVisitor(
private val cache: CirClassifiersCache,
private val classifiers: CirKnownClassifiers,
private val root: CirRootNode
) : CirNodeVisitor<Unit, Unit> {
override fun visitRootNode(node: CirRootNode, data: Unit) {
@@ -88,7 +87,7 @@ internal class CommonizationVisitor(
val companionObjectName = node.targetDeclarations.mapTo(HashSet()) { it!!.companion }.singleOrNull()
if (companionObjectName != null) {
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")
if (companionObjectNode.commonDeclaration() != null) {
@@ -129,10 +128,10 @@ internal class CommonizationVisitor(
val supertypesMap: MutableMap<CirType, CommonizedGroup<CirType>> = linkedMapOf() // preserve supertype order
for ((index, typeAlias) in targetDeclarations.withIndex()) {
val expandedClassId = typeAlias!!.expandedType.classifierId
if (expandedClassId.packageFqName.isUnderStandardKotlinPackages)
return null // this case is not supported
if (classifiers.commonDependeeLibraries?.hasClassifier(expandedClassId) == true)
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]
?: 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())
emptyList()
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.CirType
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>(
wrappedCommonizerFactory = { TypeCommonizer(cache) },
wrappedCommonizerFactory = { TypeCommonizer(classifiers) },
extractor = { it.type },
builder = { receiverType ->
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.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 modifiers = FunctionModifiersCommonizer()
private val valueParameters = CallableValueParametersCommonizer(cache)
private val valueParameters = CallableValueParametersCommonizer(classifiers)
override fun commonizationResult(): CirFunction {
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.CirPropertyGetterFactory
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
class PropertyCommonizer(cache: CirClassifiersCache) : AbstractFunctionOrPropertyCommonizer<CirProperty>(cache) {
class PropertyCommonizer(classifiers: CirKnownClassifiers) : AbstractFunctionOrPropertyCommonizer<CirProperty>(classifiers) {
private val setter = PropertySetterCommonizer()
private var isExternal = true
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.factory.CirClassFactory
import org.jetbrains.kotlin.descriptors.commonizer.cir.factory.CirTypeAliasFactory
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.CirClassifiersCache
import org.jetbrains.kotlin.descriptors.commonizer.utils.isUnderStandardKotlinPackages
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.CirKnownClassifiers
import org.jetbrains.kotlin.name.Name
/**
@@ -24,9 +23,9 @@ import org.jetbrains.kotlin.name.Name
* Tertiary (backup) branch:
* - Produce an "expect class" for "common" fragment and the corresponding "actual typealias" declarations for each platform fragment.
*/
class TypeAliasCommonizer(cache: CirClassifiersCache) : AbstractStandardCommonizer<CirTypeAlias, CirClassifier>() {
private val primary = TypeAliasShortCircuitingCommonizer(cache)
private val secondary = TypeAliasLiftingUpCommonizer(cache)
class TypeAliasCommonizer(classifiers: CirKnownClassifiers) : AbstractStandardCommonizer<CirTypeAlias, CirClassifier>() {
private val primary = TypeAliasShortCircuitingCommonizer(classifiers)
private val secondary = TypeAliasLiftingUpCommonizer(classifiers)
private val tertiary = TypeAliasExpectClassCommonizer()
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 val typeParameters = TypeParameterListCommonizer(cache)
private val typeParameters = TypeParameterListCommonizer(classifiers)
private lateinit var underlyingType: CirClassOrTypeAliasType
private val expandedType = TypeCommonizer(cache)
private val expandedType = TypeCommonizer(classifiers)
private val visibility = VisibilityCommonizer.lowering()
override fun commonizationResult() = CirTypeAliasFactory.create(
@@ -75,7 +76,7 @@ private class TypeAliasShortCircuitingCommonizer(cache: CirClassifiersCache) : A
private tailrec fun computeCommonizedUnderlyingType(underlyingType: CirClassOrTypeAliasType): CirClassOrTypeAliasType {
return when (underlyingType) {
is CirClassType -> underlyingType
is CirTypeAliasType -> if (underlyingType.classifierId.packageFqName.isUnderStandardKotlinPackages)
is CirTypeAliasType -> if (classifiers.commonDependeeLibraries?.hasClassifier(underlyingType.classifierId) == true)
underlyingType
else
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 val typeParameters = TypeParameterListCommonizer(cache)
private val underlyingType = TypeCommonizer(cache)
private val typeParameters = TypeParameterListCommonizer(classifiers)
private val underlyingType = TypeCommonizer(classifiers)
private val visibility = VisibilityCommonizer.lowering()
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.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.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.isUnderStandardKotlinPackages
import org.jetbrains.kotlin.name.ClassId
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>
override fun commonizationResult() = wrapped.result
@@ -24,10 +23,10 @@ class TypeCommonizer(private val cache: CirClassifiersCache) : AbstractStandardC
override fun initialize(first: CirType) {
@Suppress("UNCHECKED_CAST")
wrapped = when (first) {
is CirClassType -> ClassTypeCommonizer(cache)
is CirTypeAliasType -> TypeAliasTypeCommonizer(cache)
is CirClassType -> ClassTypeCommonizer(classifiers)
is CirTypeAliasType -> TypeAliasTypeCommonizer(classifiers)
is CirTypeParameterType -> TypeParameterTypeCommonizer()
is CirFlexibleType -> FlexibleTypeCommonizer(cache)
is CirFlexibleType -> FlexibleTypeCommonizer(classifiers)
} 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 val outerType = OuterClassTypeCommonizer(cache)
private val outerType = OuterClassTypeCommonizer(classifiers)
private lateinit var anyVisibility: DescriptorVisibility
private val arguments = TypeArgumentListCommonizer(cache)
private val arguments = TypeArgumentListCommonizer(classifiers)
private var isMarkedNullable = false
override fun commonizationResult() = CirTypeFactory.createClassType(
@@ -68,22 +67,22 @@ private class ClassTypeCommonizer(private val cache: CirClassifiersCache) : Abst
isMarkedNullable == next.isMarkedNullable
&& classId == next.classifierId
&& outerType.commonizeWith(next.outerType)
&& commonizeClass(classId, cache)
&& commonizeClass(classId, classifiers)
&& arguments.commonizeWith(next.arguments)
}
private class OuterClassTypeCommonizer(cache: CirClassifiersCache) :
private class OuterClassTypeCommonizer(classifiers: CirKnownClassifiers) :
AbstractNullableCommonizer<CirClassType, CirClassType, CirClassType, CirClassType>(
wrappedCommonizerFactory = { ClassTypeCommonizer(cache) },
wrappedCommonizerFactory = { ClassTypeCommonizer(classifiers) },
extractor = { it },
builder = { it }
)
private class TypeAliasTypeCommonizer(private val cache: CirClassifiersCache) :
private class TypeAliasTypeCommonizer(private val classifiers: CirKnownClassifiers) :
AbstractStandardCommonizer<CirTypeAliasType, CirClassOrTypeAliasType>() {
private lateinit var typeAliasId: ClassId
private val arguments = TypeArgumentListCommonizer(cache)
private val arguments = TypeArgumentListCommonizer(classifiers)
private var isMarkedNullable = false
private var commonizedTypeBuilder: CommonizedTypeAliasTypeBuilder? = null // null means not selected yet
@@ -104,7 +103,7 @@ private class TypeAliasTypeCommonizer(private val cache: CirClassifiersCache) :
return false
if (commonizedTypeBuilder == null) {
val answer = commonizeTypeAlias(typeAliasId, cache)
val answer = commonizeTypeAlias(typeAliasId, classifiers)
if (!answer.commonized)
return false
@@ -176,9 +175,9 @@ private class TypeParameterTypeCommonizer : AbstractStandardCommonizer<CirTypePa
}
}
private class FlexibleTypeCommonizer(cache: CirClassifiersCache) : AbstractStandardCommonizer<CirFlexibleType, CirFlexibleType>() {
private val lowerBound = TypeCommonizer(cache)
private val upperBound = TypeCommonizer(cache)
private class FlexibleTypeCommonizer(classifiers: CirKnownClassifiers) : AbstractStandardCommonizer<CirFlexibleType, CirFlexibleType>() {
private val lowerBound = TypeCommonizer(classifiers)
private val upperBound = TypeCommonizer(classifiers)
override fun commonizationResult() = CirFlexibleType(
lowerBound = lowerBound.result as CirSimpleType,
@@ -191,10 +190,12 @@ private class FlexibleTypeCommonizer(cache: CirClassifiersCache) : AbstractStand
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 lateinit var projectionKind: Variance
private val type = TypeCommonizer(cache)
private val type = TypeCommonizer(classifiers)
override fun commonizationResult() = if (isStar) CirStarTypeProjection else CirTypeProjectionImpl(
projectionKind = projectionKind,
@@ -214,16 +215,15 @@ private class TypeArgumentCommonizer(cache: CirClassifiersCache) : AbstractStand
}
}
private class TypeArgumentListCommonizer(cache: CirClassifiersCache) : AbstractListCommonizer<CirTypeProjection, CirTypeProjection>(
singleElementCommonizerFactory = { TypeArgumentCommonizer(cache) }
private class TypeArgumentListCommonizer(classifiers: CirKnownClassifiers) : AbstractListCommonizer<CirTypeProjection, CirTypeProjection>(
singleElementCommonizerFactory = { TypeArgumentCommonizer(classifiers) }
)
private fun commonizeClass(classId: ClassId, cache: CirClassifiersCache): Boolean {
val packageFqName = classId.packageFqName
if (packageFqName.isUnderStandardKotlinPackages) {
// The class is from Kotlin stdlib. Already commonized.
private fun commonizeClass(classId: ClassId, classifiers: CirKnownClassifiers): Boolean {
if (classifiers.commonDependeeLibraries?.hasClassifier(classId) == true) {
// The class is from common fragment of dependee library (ex: stdlib). Already commonized.
return true
} else if (packageFqName.isUnderKotlinNativeSyntheticPackages) {
} else if (classId.packageFqName.isUnderKotlinNativeSyntheticPackages) {
// C/Obj-C forward declarations are:
// - 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).
@@ -232,12 +232,12 @@ private fun commonizeClass(classId: ClassId, cache: CirClassifiersCache): Boolea
return true
}
return when (val node = cache.classNode(classId)) {
return when (val node = classifiers.commonized.classNode(classId)) {
null -> {
// No node means that the class was not subject for commonization.
// - Either it is missing in certain targets at all => not commonized.
// - Or it is a known forward declaration => consider it as commonized.
cache.isExportedForwardDeclaration(classId)
classifiers.forwardDeclarations.isExportedForwardDeclaration(classId)
}
else -> {
// 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 {
val packageFqName = typeAliasId.packageFqName
if (packageFqName.isUnderStandardKotlinPackages) {
// The type alias is from Kotlin stdlib. Already commonized.
private fun commonizeTypeAlias(typeAliasId: ClassId, classifiers: CirKnownClassifiers): CommonizedTypeAliasAnswer {
if (classifiers.commonDependeeLibraries?.hasClassifier(typeAliasId) == true) {
// The type alias is from common fragment of dependee library (ex: stdlib). Already commonized.
return SUCCESS_FROM_DEPENDEE_LIBRARY
}
return when (val node = cache.typeAliasNode(typeAliasId)) {
return when (val node = classifiers.commonized.typeAliasNode(typeAliasId)) {
null -> {
// 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
@@ -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.CirTypeParameter
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.types.Variance
class TypeParameterCommonizer(cache: CirClassifiersCache) : AbstractStandardCommonizer<CirTypeParameter, CirTypeParameter>() {
class TypeParameterCommonizer(classifiers: CirKnownClassifiers) : AbstractStandardCommonizer<CirTypeParameter, CirTypeParameter>() {
private lateinit var name: Name
private var isReified = false
private lateinit var variance: Variance
private val upperBounds = TypeParameterUpperBoundsCommonizer(cache)
private val upperBounds = TypeParameterUpperBoundsCommonizer(classifiers)
override fun commonizationResult() = CirTypeParameterFactory.create(
annotations = emptyList(),
@@ -39,6 +39,6 @@ class TypeParameterCommonizer(cache: CirClassifiersCache) : AbstractStandardComm
&& upperBounds.commonizeWith(next.upperBounds)
}
private class TypeParameterUpperBoundsCommonizer(cache: CirClassifiersCache) : AbstractListCommonizer<CirType, CirType>(
singleElementCommonizerFactory = { TypeCommonizer(cache) }
private class TypeParameterUpperBoundsCommonizer(classifiers: CirKnownClassifiers) : AbstractListCommonizer<CirType, CirType>(
singleElementCommonizerFactory = { TypeCommonizer(classifiers) }
)
@@ -6,8 +6,8 @@
package org.jetbrains.kotlin.descriptors.commonizer.core
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>(
singleElementCommonizerFactory = { TypeParameterCommonizer(cache) }
class TypeParameterListCommonizer(classifiers: CirKnownClassifiers) : AbstractListCommonizer<CirTypeParameter, CirTypeParameter>(
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.CirValueParameter
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.name.Name
class ValueParameterCommonizer(cache: CirClassifiersCache) : AbstractStandardCommonizer<CirValueParameter, CirValueParameter>() {
class ValueParameterCommonizer(classifiers: CirKnownClassifiers) : AbstractStandardCommonizer<CirValueParameter, CirValueParameter>() {
private lateinit var name: Name
private val returnType = TypeCommonizer(cache)
private val returnType = TypeCommonizer(classifiers)
private var varargElementType: CirType? = null
private var isCrossinline = true
private var isNoinline = true
@@ -6,11 +6,11 @@
package org.jetbrains.kotlin.descriptors.commonizer.core
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
class ValueParameterListCommonizer(cache: CirClassifiersCache) : AbstractListCommonizer<CirValueParameter, CirValueParameter>(
singleElementCommonizerFactory = { ValueParameterCommonizer(cache) }
class ValueParameterListCommonizer(classifiers: CirKnownClassifiers) : AbstractListCommonizer<CirValueParameter, CirValueParameter>(
singleElementCommonizerFactory = { ValueParameterCommonizer(classifiers) }
) {
fun overwriteNames(names: List<Name>) {
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.createGlobalBuilderComponents
import org.jetbrains.kotlin.descriptors.commonizer.core.CommonizationVisitor
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.CirTreeMerger
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.DefaultCirClassifiersCache
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.*
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.CirTreeMerger.CirTreeMergeResult
import org.jetbrains.kotlin.storage.LockBasedStorageManager
import org.jetbrains.kotlin.storage.StorageManager
fun runCommonization(parameters: Parameters): Result {
if (!parameters.hasAnythingToCommonize())
@@ -19,14 +20,8 @@ fun runCommonization(parameters: Parameters): Result {
val storageManager = LockBasedStorageManager("Declaration descriptors commonization")
// build merged tree:
val cache = DefaultCirClassifiersCache()
val mergeResult = CirTreeMerger(storageManager, cache, parameters).merge()
// commonize:
val mergeResult = mergeAndCommonize(storageManager, parameters)
val mergedTree = mergeResult.root
mergedTree.accept(CommonizationVisitor(cache, mergedTree), Unit)
parameters.progressLogger?.invoke("Commonized declarations")
// build resulting descriptors:
val components = mergedTree.createGlobalBuilderComponents(storageManager, parameters)
@@ -51,3 +46,25 @@ fun runCommonization(parameters: Parameters): Result {
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.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.resolveClassOrTypeAlias
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 {
fun isExportedForwardDeclaration(classId: ClassId): Boolean
class CirKnownClassifiers(
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 typeAliasNode(typeAliasId: ClassId): CirTypeAliasNode?
fun addExportedForwardDeclaration(classId: ClassId)
/* Mutators */
fun addClassNode(classId: ClassId, node: CirClassNode)
fun addTypeAliasNode(typeAliasId: ClassId, node: CirTypeAliasNode)
}
class DefaultCirClassifiersCache : CirClassifiersCache {
private val exportedForwardDeclarations = THashSet<ClassId>()
private val classNodes = THashMap<ClassId, CirClassNode>()
private val typeAliases = THashMap<ClassId, CirTypeAliasNode>()
companion object {
fun default() = object : CirCommonizedClassifiers {
private val classNodes = THashMap<ClassId, CirClassNode>()
private val typeAliases = THashMap<ClassId, CirTypeAliasNode>()
override fun isExportedForwardDeclaration(classId: ClassId) = classId in exportedForwardDeclarations
override fun classNode(classId: ClassId) = classNodes[classId]
override fun typeAliasNode(typeAliasId: ClassId) = typeAliases[typeAliasId]
override fun classNode(classId: ClassId) = classNodes[classId]
override fun typeAliasNode(typeAliasId: ClassId) = typeAliases[typeAliasId]
override fun addExportedForwardDeclaration(classId: ClassId) {
check(!classId.packageFqName.isUnderKotlinNativeSyntheticPackages)
exportedForwardDeclarations += classId
}
override fun addClassNode(classId: ClassId, node: CirClassNode) {
val oldNode = classNodes.put(classId, node)
check(oldNode == null) { "Rewriting class node $classId" }
}
override fun addClassNode(classId: ClassId, node: CirClassNode) {
val oldNode = classNodes.put(classId, node)
check(oldNode == null) { "Rewriting class node $classId" }
}
override fun addTypeAliasNode(typeAliasId: ClassId, node: CirTypeAliasNode) {
val oldNode = typeAliases.put(typeAliasId, node)
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(
private val storageManager: StorageManager,
private val cache: CirClassifiersCache,
private val classifiers: CirKnownClassifiers,
private val parameters: Parameters
) {
class CirTreeMergeResult(
@@ -183,7 +183,7 @@ class CirTreeMerger(
parentCommonDeclaration: NullableLazyValue<*>?
) {
val propertyNode: CirPropertyNode = properties.getOrPut(PropertyApproximationKey(propertyDescriptor)) {
buildPropertyNode(storageManager, size, cache, parentCommonDeclaration)
buildPropertyNode(storageManager, size, classifiers, parentCommonDeclaration)
}
propertyNode.targetDeclarations[targetIndex] = CirPropertyFactory.create(propertyDescriptor)
}
@@ -195,7 +195,7 @@ class CirTreeMerger(
parentCommonDeclaration: NullableLazyValue<*>?
) {
val functionNode: CirFunctionNode = functions.getOrPut(FunctionApproximationKey(functionDescriptor)) {
buildFunctionNode(storageManager, size, cache, parentCommonDeclaration)
buildFunctionNode(storageManager, size, classifiers, parentCommonDeclaration)
}
functionNode.targetDeclarations[targetIndex] = CirFunctionFactory.create(functionDescriptor)
}
@@ -211,7 +211,7 @@ class CirTreeMerger(
val classId = classIdFunction(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)
@@ -246,7 +246,7 @@ class CirTreeMerger(
parentCommonDeclaration: NullableLazyValue<*>?
) {
val constructorNode: CirClassConstructorNode = constructors.getOrPut(ConstructorApproximationKey(constructorDescriptor)) {
buildClassConstructorNode(storageManager, size, cache, parentCommonDeclaration)
buildClassConstructorNode(storageManager, size, classifiers, parentCommonDeclaration)
}
constructorNode.targetDeclarations[targetIndex] = CirClassConstructorFactory.create(constructorDescriptor)
}
@@ -261,7 +261,7 @@ class CirTreeMerger(
val typeAliasClassId = internedClassId(packageFqName, typeAliasName)
val typeAliasNode: CirTypeAliasNode = typeAliases.getOrPut(typeAliasName) {
buildTypeAliasNode(storageManager, size, cache, typeAliasClassId)
buildTypeAliasNode(storageManager, size, classifiers, typeAliasClassId)
}
typeAliasNode.targetDeclarations[targetIndex] = CirTypeAliasFactory.create(typeAliasDescriptor)
}
@@ -274,7 +274,7 @@ class CirTreeMerger(
exportForwardDeclarations.forEach { classFqName ->
// Class has synthetic package FQ name (cnames/objcnames). Need to transfer it to the main package.
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
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
// let's use the appropriate package fragment provider
val packageFragmentProvider = this.packageFragmentProvider
fun recurse(packageFqName: FqName) {
val ownPackageFragments = packageFragmentProvider.packageFragments(packageFqName)
val ownPackageMemberScopes = ownPackageFragments.asSequence()
val probeForEmptiness = probeRootPackageForEmptiness && packageFqName.isRoot
val ownPackageMemberScopes = packageFragmentProvider.packageFragments(packageFqName)
.asSequence()
.filter { it !is ExportedForwardDeclarationsPackageFragmentDescriptor && it !is ClassifierAliasingPackageFragmentDescriptor }
.map { it.getMemberScope() }
.filter { it != MemberScope.Empty }
.toList(ownPackageFragments.size)
.filter { !probeForEmptiness || it.getContributedDescriptors().isNotEmpty() }
.toList()
if (ownPackageMemberScopes.isNotEmpty()) {
// don't include subpackages into chained member scope
@@ -53,44 +53,44 @@ internal fun buildPackageNode(
internal fun buildPropertyNode(
storageManager: StorageManager,
size: Int,
cache: CirClassifiersCache,
classifiers: CirKnownClassifiers,
parentCommonDeclaration: NullableLazyValue<*>?
): CirPropertyNode = buildNode(
storageManager = storageManager,
size = size,
parentCommonDeclaration = parentCommonDeclaration,
commonizerProducer = { PropertyCommonizer(cache) },
commonizerProducer = { PropertyCommonizer(classifiers) },
nodeProducer = ::CirPropertyNode
)
internal fun buildFunctionNode(
storageManager: StorageManager,
size: Int,
cache: CirClassifiersCache,
classifiers: CirKnownClassifiers,
parentCommonDeclaration: NullableLazyValue<*>?
): CirFunctionNode = buildNode(
storageManager = storageManager,
size = size,
parentCommonDeclaration = parentCommonDeclaration,
commonizerProducer = { FunctionCommonizer(cache) },
commonizerProducer = { FunctionCommonizer(classifiers) },
nodeProducer = ::CirFunctionNode
)
internal fun buildClassNode(
storageManager: StorageManager,
size: Int,
cache: CirClassifiersCache,
classifiers: CirKnownClassifiers,
parentCommonDeclaration: NullableLazyValue<*>?,
classId: ClassId
): CirClassNode = buildNode(
storageManager = storageManager,
size = size,
parentCommonDeclaration = parentCommonDeclaration,
commonizerProducer = { ClassCommonizer(cache) },
commonizerProducer = { ClassCommonizer(classifiers) },
recursionMarker = CirClassRecursionMarker,
nodeProducer = { targetDeclarations, commonDeclaration ->
CirClassNode(targetDeclarations, commonDeclaration, classId).also {
cache.addClassNode(classId, it)
classifiers.commonized.addClassNode(classId, it)
}
}
)
@@ -98,29 +98,29 @@ internal fun buildClassNode(
internal fun buildClassConstructorNode(
storageManager: StorageManager,
size: Int,
cache: CirClassifiersCache,
classifiers: CirKnownClassifiers,
parentCommonDeclaration: NullableLazyValue<*>?
): CirClassConstructorNode = buildNode(
storageManager = storageManager,
size = size,
parentCommonDeclaration = parentCommonDeclaration,
commonizerProducer = { ClassConstructorCommonizer(cache) },
commonizerProducer = { ClassConstructorCommonizer(classifiers) },
nodeProducer = ::CirClassConstructorNode
)
internal fun buildTypeAliasNode(
storageManager: StorageManager,
size: Int,
cache: CirClassifiersCache,
classifiers: CirKnownClassifiers,
typeAliasId: ClassId
): CirTypeAliasNode = buildNode(
storageManager = storageManager,
size = size,
commonizerProducer = { TypeAliasCommonizer(cache) },
commonizerProducer = { TypeAliasCommonizer(classifiers) },
recursionMarker = CirClassifierRecursionMarker,
nodeProducer = { targetDeclarations, commonDeclaration ->
CirTypeAliasNode(targetDeclarations, commonDeclaration, typeAliasId).also {
cache.addTypeAliasNode(typeAliasId, it)
classifiers.commonized.addTypeAliasNode(typeAliasId, it)
}
}
)
@@ -43,8 +43,6 @@ private fun checkConstantSupportedInCommonization(
}
is AnnotationValue -> {
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
} // else fail (see below)
}
@@ -15,12 +15,6 @@ import java.util.Collections.singletonList
import java.util.Collections.singletonMap
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> =
when {
isEmpty() -> other
@@ -15,6 +15,7 @@ import org.jetbrains.kotlin.library.metadata.NativeTypeTransformer
import org.jetbrains.kotlin.library.metadata.NullFlexibleTypeDeserializer
import org.jetbrains.kotlin.name.ClassId
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.storage.StorageManager
@@ -38,29 +39,35 @@ internal fun ModuleDescriptor.resolveClassOrTypeAlias(classId: ClassId): Classif
return null
return packageFragmentProvider.packageFragments(classId.packageFqName).asSequence().mapNotNull { packageFragment ->
var memberScope = packageFragment.getMemberScope()
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
packageFragment.getMemberScope().resolveClassOrTypeAlias(relativeClassName)
}.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 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.CommonPlatformAnalyzerServices
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.KotlinCoreEnvironment
import org.jetbrains.kotlin.config.CommonConfigurationKeys
@@ -174,16 +175,13 @@ private class AnalyzedModuleDependencies(
companion object {
val EMPTY = AnalyzedModuleDependencies(emptyMap(), emptyList())
fun create(regularDependencies: Map<Target, ModuleDescriptor>, expectByDependencies: List<ModuleDescriptor>) =
AnalyzedModuleDependencies(regularDependencies.mapValues { listOf(it.value) }, expectByDependencies)
}
}
private class AnalyzedModules(
val originalModules: Map<Target, ModuleDescriptor>,
val commonizedModules: Map<Target, ModuleDescriptor>,
val dependeeModules: Map<Target, ModuleDescriptor>
val dependeeModules: Map<Target, List<ModuleDescriptor>>
) {
val leafTargets: Set<LeafTarget>
val sharedTarget: SharedTarget
@@ -214,13 +212,13 @@ private class AnalyzedModules(
target = leafTarget,
builtInsClass = originalModule.builtIns::class.java,
builtInsProvider = MockBuiltInsProvider(originalModule.builtIns),
modulesProvider = MockModulesProvider(originalModule),
dependeeModulesProvider = dependeeModules[leafTarget]?.let(::MockModulesProvider)
modulesProvider = MockModulesProvider.create(originalModule),
dependeeModulesProvider = dependeeModules[leafTarget]?.let(MockModulesProvider::create)
)
)
}
parameters.dependeeModulesProvider = dependeeModules[sharedTarget]?.let(::MockModulesProvider)
parameters.dependeeModulesProvider = dependeeModules[sharedTarget]?.let(MockModulesProvider::create)
return parameters
}
@@ -230,22 +228,37 @@ private class AnalyzedModules(
sourceModuleRoots: SourceModuleRoots,
parentDisposable: Disposable
): AnalyzedModules = with(sourceModuleRoots) {
// first, build the modules that are are the dependencies for "original" and "commonized" modules
val dependeeModules =
createModules(sharedTarget, dependeeRoots, AnalyzedModuleDependencies.EMPTY, parentDisposable, isDependeeModule = true)
// phase 1: provide the modules that are the dependencies for "original" and "commonized" modules
val (dependeeModules, dependencies) = createDependeeModules(sharedTarget, dependeeRoots, parentDisposable)
val dependencies = AnalyzedModuleDependencies.create(
regularDependencies = dependeeModules,
expectByDependencies = listOfNotNull(dependeeModules[sharedTarget])
)
// then, build "original" and "commonized" modules
// phase 2: build "original" and "commonized" modules
val originalModules = createModules(sharedTarget, originalRoots, dependencies, parentDisposable)
val commonizedModules = createModules(sharedTarget, commonizedRoots, dependencies, parentDisposable)
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(
sharedTarget: SharedTarget,
moduleRoots: Map<out Target, SourceModuleRoot>,
@@ -67,7 +67,7 @@ class CommonizerFacadeTest {
target = LeafTarget(targetName),
builtInsClass = DefaultBuiltIns::class.java,
builtInsProvider = BuiltInsProvider.defaultBuiltInsProvider,
modulesProvider = MockModulesProvider(moduleNames),
modulesProvider = MockModulesProvider.create(moduleNames),
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.factory.CirExtensionReceiverFactory
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.junit.Test
@@ -49,7 +49,7 @@ class ExtensionReceiverCommonizerTest : AbstractCommonizerTest<CirExtensionRecei
mockExtensionReceiver("kotlin.String")
)
override fun createCommonizer() = ExtensionReceiverCommonizer(MOCK_CLASSIFIERS_CACHE)
override fun createCommonizer() = ExtensionReceiverCommonizer(MOCK_CLASSIFIERS)
}
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.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.factory.CirClassFactory
import org.jetbrains.kotlin.descriptors.commonizer.cir.factory.CirTypeAliasFactory
import org.jetbrains.kotlin.descriptors.commonizer.cir.factory.CirTypeFactory
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.mockTAType
import org.jetbrains.kotlin.name.ClassId
@@ -24,11 +27,20 @@ import org.junit.Test
class TypeCommonizerTest : AbstractCommonizerTest<CirType, CirType>() {
private lateinit var cache: CirClassifiersCache
private lateinit var classifiers: CirKnownClassifiers
@Before
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
@@ -465,11 +477,11 @@ class TypeCommonizerTest : AbstractCommonizerTest<CirType, CirType>() {
when (descriptor) {
is ClassDescriptor -> {
val classId = descriptor.classId ?: error("No class ID for ${descriptor::class.java}, $descriptor")
val node = cache.classNode(classId) {
val node = classifiers.classNode(classId) {
buildClassNode(
storageManager = LockBasedStorageManager.NO_LOCKS,
size = variants.size,
cache = cache,
classifiers = classifiers,
parentCommonDeclaration = null,
classId = classId
)
@@ -478,11 +490,11 @@ class TypeCommonizerTest : AbstractCommonizerTest<CirType, CirType>() {
}
is TypeAliasDescriptor -> {
val typeAliasId = descriptor.classId ?: error("No class ID for ${descriptor::class.java}, $descriptor")
val node = cache.typeAliasNode(typeAliasId) {
val node = classifiers.typeAliasNode(typeAliasId) {
buildTypeAliasNode(
storageManager = LockBasedStorageManager.NO_LOCKS,
size = variants.size,
cache = cache,
classifiers = classifiers,
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 {
fun areEqual(cache: CirClassifiersCache, a: CirType, b: CirType): Boolean =
TypeCommonizer(cache).run { commonizeWith(a) && commonizeWith(b) }
fun areEqual(classifiers: CirKnownClassifiers, a: CirType, b: CirType): Boolean =
TypeCommonizer(classifiers).run { commonizeWith(a) && commonizeWith(b) }
private fun CirClassifiersCache.classNode(classId: ClassId, computation: () -> CirClassNode) =
classNode(classId) ?: computation()
private val FAKE_SHARED_TARGET = SharedTarget(setOf(LeafTarget("a"), LeafTarget("b")))
private fun CirClassifiersCache.typeAliasNode(typeAliasId: ClassId, computation: () -> CirTypeAliasNode) =
typeAliasNode(typeAliasId) ?: computation()
private fun CirKnownClassifiers.classNode(classId: ClassId, computation: () -> CirClassNode) =
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.factory.CirTypeFactory
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.name.Name
import org.jetbrains.kotlin.types.Variance
import org.junit.Test
class TypeParameterCommonizerTest : AbstractCommonizerTest<CirTypeParameter, CirTypeParameter>() {
override fun createCommonizer() = TypeParameterCommonizer(MOCK_CLASSIFIERS_CACHE)
override fun createCommonizer() = TypeParameterCommonizer(MOCK_CLASSIFIERS)
@Test
fun allAreReified() = doTestSuccess(
@@ -6,7 +6,7 @@
package org.jetbrains.kotlin.descriptors.commonizer.core
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
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 {
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.core.CirTestValueParameter.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.utils.MOCK_CLASSIFIERS_CACHE
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.CirKnownClassifiers
import org.jetbrains.kotlin.descriptors.commonizer.utils.MOCK_CLASSIFIERS
import org.jetbrains.kotlin.descriptors.commonizer.utils.mockClassType
import org.jetbrains.kotlin.name.Name
import org.junit.Test
@@ -141,10 +141,10 @@ class ValueParameterCommonizerTest : AbstractCommonizerTest<CirValueParameter, C
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?) =
(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 {
fun mockValueParam(
@@ -180,9 +180,9 @@ internal data class CirTestValueParameter(
override val isNoinline: Boolean
) : CirValueParameter {
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
|| !areEqual(cache, a.returnType, b.returnType)
|| !areEqual(classifiers, a.returnType, b.returnType)
|| a.declaresDefaultValue != b.declaresDefaultValue
|| a.isCrossinline != b.isCrossinline
|| a.isNoinline != b.isNoinline
@@ -195,7 +195,7 @@ internal data class CirTestValueParameter(
return (aVarargElementType === bVarargElementType)
|| (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.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
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 {
if (a === b)
@@ -159,7 +159,7 @@ class ValueParameterListCommonizerTest : AbstractCommonizerTest<List<CirValuePar
return false
for (i in a.indices) {
if (!areEqual(MOCK_CLASSIFIERS_CACHE, a[i], b[i]))
if (!areEqual(MOCK_CLASSIFIERS, a[i], b[i]))
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.builder.*
import org.jetbrains.kotlin.descriptors.commonizer.cir.factory.CirClassFactory
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.CirClassNode
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.CirClassifiersCache
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.CirTypeAliasNode
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.*
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
@@ -122,57 +120,69 @@ private fun createPackageFragmentForClassifier(classifierFqName: FqName): Packag
override fun toString() = "package $name"
}
internal val MOCK_CLASSIFIERS_CACHE = object : CirClassifiersCache {
private val MOCK_CLASS_NODE = CirClassNode(
CommonizedGroup(0),
LockBasedStorageManager.NO_LOCKS.createNullableLazyValue {
CirClassFactory.create(
annotations = emptyList(),
name = Name.identifier("kotlin.Any"),
typeParameters = emptyList(),
visibility = DescriptorVisibilities.PUBLIC,
modality = Modality.OPEN,
kind = ClassKind.CLASS,
companion = null,
isCompanion = false,
isData = false,
isInline = false,
isInner = false,
isExternal = false
)
},
ClassId.fromString("kotlin/Any")
)
internal val MOCK_CLASSIFIERS = CirKnownClassifiers(
commonized = object : CirCommonizedClassifiers {
private val MOCK_CLASS_NODE = CirClassNode(
CommonizedGroup(0),
LockBasedStorageManager.NO_LOCKS.createNullableLazyValue {
CirClassFactory.create(
annotations = emptyList(),
name = Name.identifier("kotlin.Any"),
typeParameters = emptyList(),
visibility = DescriptorVisibilities.PUBLIC,
modality = Modality.OPEN,
kind = ClassKind.CLASS,
companion = null,
isCompanion = false,
isData = false,
isInline = false,
isInner = false,
isExternal = false
)
},
ClassId.fromString("kotlin/Any")
)
override fun isExportedForwardDeclaration(classId: ClassId) = false
override fun classNode(classId: ClassId) = MOCK_CLASS_NODE
override fun typeAliasNode(typeAliasId: ClassId) = error("This method should not be called")
override fun addExportedForwardDeclaration(classId: ClassId) = 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")
}
override fun classNode(classId: ClassId) = MOCK_CLASS_NODE
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 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 {
override fun loadBuiltIns() = builtIns
}
internal class MockModulesProvider : ModulesProvider {
private val moduleInfos: Map<String, ModuleInfo>
private val modules: Map<String, ModuleDescriptor>
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)
}
internal class MockModulesProvider private constructor(
private val modules: Map<String, ModuleDescriptor>,
) : ModulesProvider {
private val moduleInfos: Map<String, ModuleInfo> = modules.mapValues { (name, _) -> fakeModuleInfo(name) }
override fun loadModuleInfos() = moduleInfos
override fun loadModules(dependencies: Collection<ModuleDescriptor>): Map<String, ModuleDescriptor> = modules
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)
)
}
}