[Commonizer] Build CIR tree directly from metadata
This commit is contained in:
+59
-4
@@ -6,12 +6,14 @@
|
||||
package org.jetbrains.kotlin.descriptors.commonizer.cir.factory
|
||||
|
||||
import gnu.trove.THashMap
|
||||
import kotlinx.metadata.Flag
|
||||
import kotlinx.metadata.Flags
|
||||
import kotlinx.metadata.KmAnnotation
|
||||
import kotlinx.metadata.KmAnnotationArgument
|
||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirAnnotation
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirClassType
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirConstantValue
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirName
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.cir.*
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.cir.impl.CirAnnotationImpl
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.CirProvided
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.utils.*
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.utils.compact
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
@@ -50,6 +52,59 @@ object CirAnnotationFactory {
|
||||
)
|
||||
}
|
||||
|
||||
fun createAnnotations(flags: Flags, typeResolver: CirTypeResolver, annotations: () -> List<KmAnnotation>): List<CirAnnotation> {
|
||||
return if (!Flag.Common.HAS_ANNOTATIONS(flags))
|
||||
emptyList()
|
||||
else
|
||||
annotations().compactMap { create(it, typeResolver) }
|
||||
}
|
||||
|
||||
fun create(source: KmAnnotation, typeResolver: CirTypeResolver): CirAnnotation {
|
||||
val classId = CirEntityId.create(source.className)
|
||||
val clazz: CirProvided.Class = typeResolver.resolveClassifier(classId)
|
||||
|
||||
val type = CirTypeFactory.createClassType(
|
||||
classId = classId,
|
||||
outerType = null, // annotation class can't be inner class
|
||||
visibility = clazz.visibility,
|
||||
arguments = clazz.typeParameters.compactMap { typeParameter ->
|
||||
CirTypeProjectionImpl(
|
||||
projectionKind = typeParameter.variance,
|
||||
type = CirTypeFactory.createTypeParameterType(
|
||||
index = typeParameter.index,
|
||||
isMarkedNullable = false
|
||||
)
|
||||
)
|
||||
},
|
||||
isMarkedNullable = false
|
||||
)
|
||||
|
||||
val allValueArguments: Map<String, KmAnnotationArgument<*>> = source.arguments
|
||||
if (allValueArguments.isEmpty())
|
||||
return create(type = type, constantValueArguments = emptyMap(), annotationValueArguments = emptyMap())
|
||||
|
||||
val constantValueArguments: MutableMap<CirName, CirConstantValue<*>> = THashMap(allValueArguments.size)
|
||||
val annotationValueArguments: MutableMap<CirName, CirAnnotation> = THashMap(allValueArguments.size)
|
||||
|
||||
allValueArguments.forEach { (name, constantValue) ->
|
||||
val cirName = CirName.create(name)
|
||||
if (constantValue is KmAnnotationArgument.AnnotationValue)
|
||||
annotationValueArguments[cirName] = create(source = constantValue.value, typeResolver)
|
||||
else
|
||||
constantValueArguments[cirName] = CirConstantValueFactory.createSafely(
|
||||
constantValue = constantValue,
|
||||
constantName = cirName,
|
||||
owner = source,
|
||||
)
|
||||
}
|
||||
|
||||
return create(
|
||||
type = type,
|
||||
constantValueArguments = constantValueArguments.compact(),
|
||||
annotationValueArguments = annotationValueArguments.compact()
|
||||
)
|
||||
}
|
||||
|
||||
fun create(
|
||||
type: CirClassType,
|
||||
constantValueArguments: Map<CirName, CirConstantValue<*>>,
|
||||
|
||||
+16
@@ -5,11 +5,15 @@
|
||||
|
||||
package org.jetbrains.kotlin.descriptors.commonizer.cir.factory
|
||||
|
||||
import kotlinx.metadata.Flag
|
||||
import kotlinx.metadata.KmConstructor
|
||||
import kotlinx.metadata.klib.annotations
|
||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ClassConstructorDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.DescriptorVisibility
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.cir.*
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.cir.impl.CirClassConstructorImpl
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.metadata.decodeVisibility
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.utils.compactMap
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.utils.compactMapNotNull
|
||||
|
||||
@@ -33,6 +37,18 @@ object CirClassConstructorFactory {
|
||||
)
|
||||
}
|
||||
|
||||
fun create(source: KmConstructor, containingClass: CirContainingClass, typeResolver: CirTypeResolver): CirClassConstructor {
|
||||
return create(
|
||||
annotations = CirAnnotationFactory.createAnnotations(source.flags, typeResolver, source::annotations),
|
||||
typeParameters = emptyList(), // TODO: nowhere to read constructor type parameters from
|
||||
visibility = decodeVisibility(source.flags),
|
||||
containingClass = containingClass,
|
||||
valueParameters = source.valueParameters.compactMap { CirValueParameterFactory.create(it, typeResolver) },
|
||||
hasStableParameterNames = !Flag.Constructor.HAS_NON_STABLE_PARAMETER_NAMES(source.flags),
|
||||
isPrimary = !Flag.Constructor.IS_SECONDARY(source.flags)
|
||||
)
|
||||
}
|
||||
|
||||
@Suppress("NOTHING_TO_INLINE")
|
||||
inline fun create(
|
||||
annotations: List<CirAnnotation>,
|
||||
|
||||
+56
-8
@@ -5,15 +5,16 @@
|
||||
|
||||
package org.jetbrains.kotlin.descriptors.commonizer.cir.factory
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.descriptors.DescriptorVisibility
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirAnnotation
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirClass
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirName
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirTypeParameter
|
||||
import kotlinx.metadata.Flag
|
||||
import kotlinx.metadata.KmAnnotation
|
||||
import kotlinx.metadata.KmClass
|
||||
import kotlinx.metadata.klib.annotations
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.cir.*
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.cir.impl.CirClassImpl
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.metadata.decodeClassKind
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.metadata.decodeModality
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.metadata.decodeVisibility
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.utils.compactMap
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.utils.filteredSupertypes
|
||||
import org.jetbrains.kotlin.resolve.isInlineClass
|
||||
@@ -36,6 +37,53 @@ object CirClassFactory {
|
||||
setSupertypes(source.filteredSupertypes.compactMap { CirTypeFactory.create(it) })
|
||||
}
|
||||
|
||||
fun create(name: CirName, source: KmClass, typeResolver: CirTypeResolver): CirClass = create(
|
||||
annotations = CirAnnotationFactory.createAnnotations(source.flags, typeResolver, source::annotations),
|
||||
name = name,
|
||||
typeParameters = source.typeParameters.compactMap { CirTypeParameterFactory.create(it, typeResolver) },
|
||||
visibility = decodeVisibility(source.flags),
|
||||
modality = decodeModality(source.flags),
|
||||
kind = decodeClassKind(source.flags),
|
||||
companion = source.companionObject?.let(CirName::create),
|
||||
isCompanion = Flag.Class.IS_COMPANION_OBJECT(source.flags),
|
||||
isData = Flag.Class.IS_DATA(source.flags),
|
||||
isInline = Flag.Class.IS_INLINE(source.flags),
|
||||
isInner = Flag.Class.IS_INNER(source.flags),
|
||||
isExternal = Flag.Class.IS_EXTERNAL(source.flags)
|
||||
).apply {
|
||||
setSupertypes(source.filteredSupertypes.compactMap { CirTypeFactory.create(it, typeResolver) })
|
||||
}
|
||||
|
||||
fun createDefaultEnumEntry(
|
||||
name: CirName,
|
||||
annotations: List<KmAnnotation>,
|
||||
enumClassId: CirEntityId,
|
||||
enumClass: KmClass,
|
||||
typeResolver: CirTypeResolver
|
||||
): CirClass = create(
|
||||
annotations = annotations.compactMap { CirAnnotationFactory.create(it, typeResolver) },
|
||||
name = name,
|
||||
typeParameters = emptyList(),
|
||||
visibility = DescriptorVisibilities.PUBLIC,
|
||||
modality = Modality.FINAL,
|
||||
kind = ClassKind.ENUM_ENTRY,
|
||||
companion = null,
|
||||
isCompanion = false,
|
||||
isData = false,
|
||||
isInline = false,
|
||||
isInner = false,
|
||||
isExternal = false
|
||||
).apply {
|
||||
val enumClassType = CirTypeFactory.createClassType(
|
||||
classId = enumClassId,
|
||||
outerType = null,
|
||||
visibility = decodeVisibility(enumClass.flags),
|
||||
arguments = emptyList(),
|
||||
isMarkedNullable = false
|
||||
)
|
||||
setSupertypes(listOf(enumClassType))
|
||||
}
|
||||
|
||||
@Suppress("NOTHING_TO_INLINE")
|
||||
inline fun create(
|
||||
annotations: List<CirAnnotation>,
|
||||
|
||||
+54
-2
@@ -5,6 +5,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.descriptors.commonizer.cir.factory
|
||||
|
||||
import kotlinx.metadata.KmAnnotationArgument
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirConstantValue
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirEntityId
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirName
|
||||
@@ -25,6 +26,8 @@ object CirConstantValueFactory {
|
||||
constantValue: ConstantValue<*>,
|
||||
location: () -> String
|
||||
): CirConstantValue<*> = when (constantValue) {
|
||||
is NullValue -> CirConstantValue.NullValue
|
||||
|
||||
is StringValue -> CirConstantValue.StringValue(constantValue.value)
|
||||
is CharValue -> CirConstantValue.CharValue(constantValue.value)
|
||||
|
||||
@@ -46,7 +49,6 @@ object CirConstantValueFactory {
|
||||
CirEntityId.create(constantValue.enumClassId),
|
||||
CirName.create(constantValue.enumEntryName)
|
||||
)
|
||||
is NullValue -> CirConstantValue.NullValue
|
||||
|
||||
is ArrayValue -> CirConstantValue.ArrayValue(
|
||||
constantValue.value.compactMapIndexed { index, innerConstantValue ->
|
||||
@@ -54,8 +56,58 @@ object CirConstantValueFactory {
|
||||
constantValue = innerConstantValue,
|
||||
location = { "${location()}[$index]" }
|
||||
)
|
||||
})
|
||||
}
|
||||
)
|
||||
|
||||
else -> error("Unsupported const value type: ${constantValue::class.java}, $constantValue at ${location()}")
|
||||
}
|
||||
|
||||
fun createSafely(
|
||||
constantValue: KmAnnotationArgument<*>?,
|
||||
constantName: CirName? = null,
|
||||
owner: Any,
|
||||
): CirConstantValue<*> = createSafely(
|
||||
constantValue = constantValue,
|
||||
location = { "${owner::class.java}, $owner" + constantName?.toString()?.let { "[$it]" } }
|
||||
)
|
||||
|
||||
private fun createSafely(
|
||||
constantValue: KmAnnotationArgument<*>?,
|
||||
location: () -> String
|
||||
): CirConstantValue<*> = when (constantValue) {
|
||||
null -> CirConstantValue.NullValue
|
||||
|
||||
is KmAnnotationArgument.StringValue -> CirConstantValue.StringValue(constantValue.value)
|
||||
is KmAnnotationArgument.CharValue -> CirConstantValue.CharValue(constantValue.value)
|
||||
|
||||
is KmAnnotationArgument.ByteValue -> CirConstantValue.ByteValue(constantValue.value)
|
||||
is KmAnnotationArgument.ShortValue -> CirConstantValue.ShortValue(constantValue.value)
|
||||
is KmAnnotationArgument.IntValue -> CirConstantValue.IntValue(constantValue.value)
|
||||
is KmAnnotationArgument.LongValue -> CirConstantValue.LongValue(constantValue.value)
|
||||
|
||||
is KmAnnotationArgument.UByteValue -> CirConstantValue.UByteValue(constantValue.value)
|
||||
is KmAnnotationArgument.UShortValue -> CirConstantValue.UShortValue(constantValue.value)
|
||||
is KmAnnotationArgument.UIntValue -> CirConstantValue.UIntValue(constantValue.value)
|
||||
is KmAnnotationArgument.ULongValue -> CirConstantValue.ULongValue(constantValue.value)
|
||||
|
||||
is KmAnnotationArgument.FloatValue -> CirConstantValue.FloatValue(constantValue.value)
|
||||
is KmAnnotationArgument.DoubleValue -> CirConstantValue.DoubleValue(constantValue.value)
|
||||
is KmAnnotationArgument.BooleanValue -> CirConstantValue.BooleanValue(constantValue.value)
|
||||
|
||||
is KmAnnotationArgument.EnumValue -> CirConstantValue.EnumValue(
|
||||
CirEntityId.create(constantValue.enumClassName),
|
||||
CirName.create(constantValue.enumEntryName)
|
||||
)
|
||||
|
||||
is KmAnnotationArgument.ArrayValue -> CirConstantValue.ArrayValue(
|
||||
constantValue.value.compactMapIndexed { index, innerConstantValue ->
|
||||
createSafely(
|
||||
constantValue = innerConstantValue,
|
||||
location = { "${location()}[$index]" }
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
else -> error("Unsupported annotation argument type: ${constantValue::class.java}, $constantValue")
|
||||
}
|
||||
}
|
||||
|
||||
+6
@@ -5,6 +5,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.descriptors.commonizer.cir.factory
|
||||
|
||||
import kotlinx.metadata.KmType
|
||||
import org.jetbrains.kotlin.descriptors.ReceiverParameterDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirAnnotation
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirExtensionReceiver
|
||||
@@ -18,6 +19,11 @@ object CirExtensionReceiverFactory {
|
||||
type = CirTypeFactory.create(source.type)
|
||||
)
|
||||
|
||||
fun create(receiverParameterType: KmType, typeResolver: CirTypeResolver): CirExtensionReceiver = create(
|
||||
annotations = emptyList(), // TODO nowhere to read receiver annotations from, see KT-42490
|
||||
type = CirTypeFactory.create(receiverParameterType, typeResolver)
|
||||
)
|
||||
|
||||
@Suppress("NOTHING_TO_INLINE")
|
||||
inline fun create(
|
||||
annotations: List<CirAnnotation>,
|
||||
|
||||
+23
@@ -5,9 +5,15 @@
|
||||
|
||||
package org.jetbrains.kotlin.descriptors.commonizer.cir.factory
|
||||
|
||||
import kotlinx.metadata.Flag
|
||||
import kotlinx.metadata.KmFunction
|
||||
import kotlinx.metadata.klib.annotations
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.cir.*
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.cir.impl.CirFunctionImpl
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.metadata.decodeCallableKind
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.metadata.decodeModality
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.metadata.decodeVisibility
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.utils.compactMap
|
||||
|
||||
object CirFunctionFactory {
|
||||
@@ -26,6 +32,23 @@ object CirFunctionFactory {
|
||||
modifiers = CirFunctionModifiersFactory.create(source),
|
||||
)
|
||||
|
||||
fun create(name: CirName, source: KmFunction, containingClass: CirContainingClass?, typeResolver: CirTypeResolver): CirFunction {
|
||||
return create(
|
||||
annotations = CirAnnotationFactory.createAnnotations(source.flags, typeResolver, source::annotations),
|
||||
name = name,
|
||||
typeParameters = source.typeParameters.compactMap { CirTypeParameterFactory.create(it, typeResolver) },
|
||||
visibility = decodeVisibility(source.flags),
|
||||
modality = decodeModality(source.flags),
|
||||
containingClass = containingClass,
|
||||
valueParameters = source.valueParameters.compactMap { CirValueParameterFactory.create(it, typeResolver) },
|
||||
hasStableParameterNames = !Flag.Function.HAS_NON_STABLE_PARAMETER_NAMES(source.flags),
|
||||
extensionReceiver = source.receiverParameterType?.let { CirExtensionReceiverFactory.create(it, typeResolver) },
|
||||
returnType = CirTypeFactory.create(source.returnType, typeResolver),
|
||||
kind = decodeCallableKind(source.flags),
|
||||
modifiers = CirFunctionModifiersFactory.create(source),
|
||||
)
|
||||
}
|
||||
|
||||
@Suppress("NOTHING_TO_INLINE")
|
||||
inline fun create(
|
||||
annotations: List<CirAnnotation>,
|
||||
|
||||
+11
@@ -5,6 +5,8 @@
|
||||
|
||||
package org.jetbrains.kotlin.descriptors.commonizer.cir.factory
|
||||
|
||||
import kotlinx.metadata.Flag
|
||||
import kotlinx.metadata.KmFunction
|
||||
import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirFunctionModifiers
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.cir.impl.CirFunctionModifiersImpl
|
||||
@@ -22,6 +24,15 @@ object CirFunctionModifiersFactory {
|
||||
isExternal = source.isExternal
|
||||
)
|
||||
|
||||
fun create(source: KmFunction): CirFunctionModifiers = create(
|
||||
isOperator = Flag.Function.IS_OPERATOR(source.flags),
|
||||
isInfix = Flag.Function.IS_INFIX(source.flags),
|
||||
isInline = Flag.Function.IS_INLINE(source.flags),
|
||||
isTailrec = Flag.Function.IS_TAILREC(source.flags),
|
||||
isSuspend = Flag.Function.IS_SUSPEND(source.flags),
|
||||
isExternal = Flag.Function.IS_EXTERNAL(source.flags)
|
||||
)
|
||||
|
||||
fun create(
|
||||
isOperator: Boolean,
|
||||
isInfix: Boolean,
|
||||
|
||||
+38
@@ -5,12 +5,19 @@
|
||||
|
||||
package org.jetbrains.kotlin.descriptors.commonizer.cir.factory
|
||||
|
||||
import kotlinx.metadata.Flag
|
||||
import kotlinx.metadata.KmProperty
|
||||
import kotlinx.metadata.klib.annotations
|
||||
import kotlinx.metadata.klib.compileTimeValue
|
||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.DescriptorVisibility
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.cir.*
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.cir.impl.CirPropertyImpl
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.metadata.decodeCallableKind
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.metadata.decodeModality
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.metadata.decodeVisibility
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.utils.compactMap
|
||||
|
||||
object CirPropertyFactory {
|
||||
@@ -45,6 +52,37 @@ object CirPropertyFactory {
|
||||
)
|
||||
}
|
||||
|
||||
fun create(name: CirName, source: KmProperty, containingClass: CirContainingClass?, typeResolver: CirTypeResolver): CirProperty {
|
||||
val compileTimeInitializer = if (Flag.Property.HAS_CONSTANT(source.flags)) {
|
||||
CirConstantValueFactory.createSafely(
|
||||
constantValue = source.compileTimeValue,
|
||||
owner = source,
|
||||
)
|
||||
} else CirConstantValue.NullValue
|
||||
|
||||
return create(
|
||||
annotations = CirAnnotationFactory.createAnnotations(source.flags, typeResolver, source::annotations),
|
||||
name = name,
|
||||
typeParameters = source.typeParameters.compactMap { CirTypeParameterFactory.create(it, typeResolver) },
|
||||
visibility = decodeVisibility(source.flags),
|
||||
modality = decodeModality(source.flags),
|
||||
containingClass = containingClass,
|
||||
isExternal = Flag.Property.IS_EXTERNAL(source.flags),
|
||||
extensionReceiver = source.receiverParameterType?.let { CirExtensionReceiverFactory.create(it, typeResolver) },
|
||||
returnType = CirTypeFactory.create(source.returnType, typeResolver),
|
||||
kind = decodeCallableKind(source.flags),
|
||||
isVar = Flag.Property.IS_VAR(source.flags),
|
||||
isLateInit = Flag.Property.IS_LATEINIT(source.flags),
|
||||
isConst = Flag.Property.IS_CONST(source.flags),
|
||||
isDelegate = Flag.Property.IS_DELEGATED(source.flags),
|
||||
getter = CirPropertyGetterFactory.create(source, typeResolver),
|
||||
setter = CirPropertySetterFactory.create(source, typeResolver),
|
||||
backingFieldAnnotations = emptyList(), // TODO unclear where to read backing/delegate field annotations from, see KT-44625
|
||||
delegateFieldAnnotations = emptyList(), // TODO unclear where to read backing/delegate field annotations from, see KT-44625
|
||||
compileTimeInitializer = compileTimeInitializer
|
||||
)
|
||||
}
|
||||
|
||||
@Suppress("NOTHING_TO_INLINE")
|
||||
inline fun create(
|
||||
annotations: List<CirAnnotation>,
|
||||
|
||||
+23
@@ -5,6 +5,9 @@
|
||||
|
||||
package org.jetbrains.kotlin.descriptors.commonizer.cir.factory
|
||||
|
||||
import kotlinx.metadata.Flag
|
||||
import kotlinx.metadata.KmProperty
|
||||
import kotlinx.metadata.klib.getterAnnotations
|
||||
import org.jetbrains.kotlin.descriptors.PropertyGetterDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirAnnotation
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirPropertyGetter
|
||||
@@ -35,6 +38,26 @@ object CirPropertyGetterFactory {
|
||||
)
|
||||
}
|
||||
|
||||
fun create(source: KmProperty, typeResolver: CirTypeResolver): CirPropertyGetter? {
|
||||
if (!Flag.Property.HAS_GETTER(source.flags))
|
||||
return null
|
||||
|
||||
val getterFlags = source.getterFlags
|
||||
|
||||
val isDefault = !Flag.PropertyAccessor.IS_NOT_DEFAULT(getterFlags)
|
||||
val annotations = CirAnnotationFactory.createAnnotations(getterFlags, typeResolver, source::getterAnnotations)
|
||||
|
||||
if (isDefault && annotations.isEmpty())
|
||||
return DEFAULT_NO_ANNOTATIONS
|
||||
|
||||
return create(
|
||||
annotations = annotations,
|
||||
isDefault = isDefault,
|
||||
isExternal = Flag.PropertyAccessor.IS_EXTERNAL(getterFlags),
|
||||
isInline = Flag.PropertyAccessor.IS_INLINE(getterFlags)
|
||||
)
|
||||
}
|
||||
|
||||
fun create(
|
||||
annotations: List<CirAnnotation>,
|
||||
isDefault: Boolean,
|
||||
|
||||
+23
@@ -5,12 +5,17 @@
|
||||
|
||||
package org.jetbrains.kotlin.descriptors.commonizer.cir.factory
|
||||
|
||||
import kotlinx.metadata.Flag
|
||||
import kotlinx.metadata.KmProperty
|
||||
import kotlinx.metadata.klib.annotations
|
||||
import kotlinx.metadata.klib.setterAnnotations
|
||||
import org.jetbrains.kotlin.descriptors.PropertySetterDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
|
||||
import org.jetbrains.kotlin.descriptors.DescriptorVisibility
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirAnnotation
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirPropertySetter
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.cir.impl.CirPropertySetterImpl
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.metadata.decodeVisibility
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.utils.Interner
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.utils.compactMap
|
||||
|
||||
@@ -26,6 +31,24 @@ object CirPropertySetterFactory {
|
||||
isInline = source.isInline
|
||||
)
|
||||
|
||||
fun create(source: KmProperty, typeResolver: CirTypeResolver): CirPropertySetter? {
|
||||
if (!Flag.Property.HAS_SETTER(source.flags))
|
||||
return null
|
||||
|
||||
val setterFlags = source.setterFlags
|
||||
|
||||
return create(
|
||||
annotations = CirAnnotationFactory.createAnnotations(setterFlags, typeResolver, source::setterAnnotations),
|
||||
parameterAnnotations = source.setterParameter?.let { setterParameter ->
|
||||
CirAnnotationFactory.createAnnotations(setterParameter.flags, typeResolver, setterParameter::annotations)
|
||||
}.orEmpty(),
|
||||
visibility = decodeVisibility(setterFlags),
|
||||
isDefault = !Flag.PropertyAccessor.IS_NOT_DEFAULT(setterFlags),
|
||||
isExternal = Flag.PropertyAccessor.IS_EXTERNAL(setterFlags),
|
||||
isInline = Flag.PropertyAccessor.IS_INLINE(setterFlags)
|
||||
)
|
||||
}
|
||||
|
||||
fun create(
|
||||
annotations: List<CirAnnotation>,
|
||||
parameterAnnotations: List<CirAnnotation>,
|
||||
|
||||
+181
@@ -0,0 +1,181 @@
|
||||
/*
|
||||
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.descriptors.commonizer.cir.factory
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.cir.*
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.CirProvided
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.utils.compactMapIndexed
|
||||
import org.jetbrains.kotlin.types.Variance
|
||||
|
||||
class CirTypeAliasExpansion(
|
||||
val typeAlias: CirProvided.TypeAlias,
|
||||
val arguments: List<CirTypeProjection>,
|
||||
val isMarkedNullable: Boolean,
|
||||
val typeResolver: CirTypeResolver
|
||||
) {
|
||||
companion object {
|
||||
fun create(
|
||||
typeAliasId: CirEntityId,
|
||||
arguments: List<CirTypeProjection>,
|
||||
isMarkedNullable: Boolean,
|
||||
typeResolver: CirTypeResolver
|
||||
): CirTypeAliasExpansion {
|
||||
val typeAlias: CirProvided.TypeAlias = typeResolver.resolveClassifier(typeAliasId)
|
||||
checkArgumentsCount(typeAlias, typeAliasId, arguments)
|
||||
|
||||
return CirTypeAliasExpansion(
|
||||
typeAlias = typeAlias,
|
||||
arguments = arguments,
|
||||
isMarkedNullable = isMarkedNullable,
|
||||
typeResolver = typeResolver
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
object CirTypeAliasExpander {
|
||||
fun expand(expansion: CirTypeAliasExpansion): CirClassOrTypeAliasType {
|
||||
val underlyingType = expansion.typeAlias.underlyingType
|
||||
val underlyingProjection = CirProvided.RegularTypeProjection(Variance.INVARIANT, underlyingType)
|
||||
|
||||
val expandedProjection = expandTypeProjection(expansion, underlyingProjection, Variance.INVARIANT)
|
||||
check(expandedProjection is CirTypeProjectionImpl) {
|
||||
"Type alias expansion: result for $underlyingType is $expandedProjection, should not be a star projection"
|
||||
}
|
||||
check(expandedProjection.projectionKind == Variance.INVARIANT) {
|
||||
"Type alias expansion: result for $underlyingType is $expandedProjection, should be invariant"
|
||||
}
|
||||
|
||||
val expandedType = expandedProjection.type as CirClassOrTypeAliasType
|
||||
return CirTypeFactory.makeNullableIfNecessary(expandedType, expansion.isMarkedNullable)
|
||||
}
|
||||
|
||||
private fun expandTypeProjection(
|
||||
expansion: CirTypeAliasExpansion,
|
||||
projection: CirProvided.TypeProjection,
|
||||
typeParameterVariance: Variance
|
||||
): CirTypeProjection {
|
||||
val type = when (projection) {
|
||||
is CirProvided.StarTypeProjection -> return CirStarTypeProjection
|
||||
is CirProvided.RegularTypeProjection -> projection.type
|
||||
}
|
||||
|
||||
val argument = when (type) {
|
||||
is CirProvided.TypeParameterType -> expansion.arguments[type.index]
|
||||
is CirProvided.TypeAliasType -> {
|
||||
val substitutedType = expandTypeAliasType(expansion, type)
|
||||
CirTypeProjectionImpl(projection.variance, substitutedType)
|
||||
}
|
||||
is CirProvided.ClassType -> {
|
||||
val substitutedType = expandClassType(expansion, type)
|
||||
CirTypeProjectionImpl(projection.variance, substitutedType)
|
||||
}
|
||||
}
|
||||
|
||||
return when (argument) {
|
||||
is CirStarTypeProjection -> CirStarTypeProjection
|
||||
is CirTypeProjectionImpl -> {
|
||||
val argumentType = argument.type as CirSimpleType
|
||||
|
||||
val resultingVariance = run {
|
||||
val argumentVariance = argument.projectionKind
|
||||
val underlyingVariance = projection.variance
|
||||
|
||||
val substitutionVariance = when {
|
||||
underlyingVariance == argumentVariance -> argumentVariance
|
||||
underlyingVariance == Variance.INVARIANT -> argumentVariance
|
||||
argumentVariance == Variance.INVARIANT -> underlyingVariance
|
||||
else -> argumentVariance
|
||||
}
|
||||
|
||||
when {
|
||||
typeParameterVariance == substitutionVariance -> substitutionVariance
|
||||
typeParameterVariance == Variance.INVARIANT -> substitutionVariance
|
||||
substitutionVariance == Variance.INVARIANT -> Variance.INVARIANT
|
||||
else -> substitutionVariance
|
||||
}
|
||||
}
|
||||
|
||||
val substitutedType = CirTypeFactory.makeNullableIfNecessary(argumentType, type.isMarkedNullable)
|
||||
|
||||
CirTypeProjectionImpl(resultingVariance, substitutedType)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun expandTypeAliasType(
|
||||
expansion: CirTypeAliasExpansion,
|
||||
type: CirProvided.TypeAliasType
|
||||
): CirTypeAliasType {
|
||||
val typeAlias: CirProvided.TypeAlias = expansion.typeResolver.resolveClassifier(type.typeAliasId)
|
||||
checkArgumentsCount(typeAlias, type.typeAliasId, type.arguments)
|
||||
|
||||
val expandedArguments = type.arguments.compactMapIndexed { index, argument ->
|
||||
val projection = expandTypeProjection(expansion, argument, typeAlias.typeParameters[index].variance)
|
||||
makeNullableTypeIfNecessary(projection, argument)
|
||||
}
|
||||
|
||||
val nestedExpansion = CirTypeAliasExpansion(typeAlias, expandedArguments, type.isMarkedNullable, expansion.typeResolver)
|
||||
val nestedExpandedType = expand(nestedExpansion)
|
||||
|
||||
return CirTypeFactory.createTypeAliasType(
|
||||
typeAliasId = type.typeAliasId,
|
||||
underlyingType = nestedExpandedType,
|
||||
arguments = expandedArguments,
|
||||
isMarkedNullable = type.isMarkedNullable
|
||||
)
|
||||
}
|
||||
|
||||
private fun expandClassType(
|
||||
expansion: CirTypeAliasExpansion,
|
||||
type: CirProvided.ClassType
|
||||
): CirClassType {
|
||||
val clazz: CirProvided.Class = expansion.typeResolver.resolveClassifier(type.classId)
|
||||
checkArgumentsCount(clazz, type.classId, type.arguments)
|
||||
|
||||
val expandedArguments = type.arguments.compactMapIndexed { index, argument ->
|
||||
val projection = expandTypeProjection(expansion, argument, clazz.typeParameters[index].variance)
|
||||
makeNullableTypeIfNecessary(projection, argument)
|
||||
}
|
||||
|
||||
return CirTypeFactory.createClassType(
|
||||
classId = type.classId,
|
||||
outerType = type.outerType?.let { expandClassType(expansion, it) },
|
||||
visibility = clazz.visibility,
|
||||
arguments = expandedArguments,
|
||||
isMarkedNullable = type.isMarkedNullable
|
||||
)
|
||||
}
|
||||
|
||||
@Suppress("NOTHING_TO_INLINE")
|
||||
private inline fun makeNullableTypeIfNecessary(
|
||||
projection: CirTypeProjection,
|
||||
originalArgument: CirProvided.TypeProjection
|
||||
): CirTypeProjection {
|
||||
return when (projection) {
|
||||
is CirStarTypeProjection -> CirStarTypeProjection
|
||||
is CirTypeProjectionImpl -> {
|
||||
val originalTypeIsNullable = (originalArgument as? CirProvided.RegularTypeProjection)?.type?.isMarkedNullable == true
|
||||
if (!originalTypeIsNullable)
|
||||
return projection
|
||||
|
||||
val projectionType = projection.type as CirSimpleType
|
||||
if (projectionType.isMarkedNullable)
|
||||
return projection
|
||||
|
||||
CirTypeProjectionImpl(
|
||||
projectionKind = projection.projectionKind,
|
||||
type = CirTypeFactory.makeNullable(projectionType)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkArgumentsCount(classifier: CirProvided.Classifier, classifierId: CirEntityId, arguments: List<*>) =
|
||||
check(classifier.typeParameters.size == arguments.size) {
|
||||
"${classifier::class.java.simpleName} $classifierId has different number of type parameters than the number of supplied arguments: ${classifier.typeParameters.size} != ${arguments.size}"
|
||||
}
|
||||
+16
@@ -5,10 +5,12 @@
|
||||
|
||||
package org.jetbrains.kotlin.descriptors.commonizer.cir.factory
|
||||
|
||||
import kotlinx.metadata.KmTypeAlias
|
||||
import org.jetbrains.kotlin.descriptors.TypeAliasDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.DescriptorVisibility
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.cir.*
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.cir.impl.CirTypeAliasImpl
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.metadata.decodeVisibility
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.utils.compactMap
|
||||
|
||||
object CirTypeAliasFactory {
|
||||
@@ -26,6 +28,20 @@ object CirTypeAliasFactory {
|
||||
)
|
||||
}
|
||||
|
||||
fun create(name: CirName, source: KmTypeAlias, typeResolver: CirTypeResolver): CirTypeAlias {
|
||||
val underlyingType = CirTypeFactory.create(source.underlyingType, typeResolver) as CirClassOrTypeAliasType
|
||||
val expandedType = CirTypeFactory.unabbreviate(underlyingType)
|
||||
|
||||
return create(
|
||||
annotations = CirAnnotationFactory.createAnnotations(source.flags, typeResolver, source::annotations),
|
||||
name = name,
|
||||
typeParameters = source.typeParameters.compactMap { CirTypeParameterFactory.create(it, typeResolver) },
|
||||
visibility = decodeVisibility(source.flags),
|
||||
underlyingType = underlyingType,
|
||||
expandedType = expandedType
|
||||
)
|
||||
}
|
||||
|
||||
@Suppress("NOTHING_TO_INLINE")
|
||||
inline fun create(
|
||||
annotations: List<CirAnnotation>,
|
||||
|
||||
+140
@@ -5,11 +5,16 @@
|
||||
|
||||
package org.jetbrains.kotlin.descriptors.commonizer.cir.factory
|
||||
|
||||
import gnu.trove.TIntObjectHashMap
|
||||
import kotlinx.metadata.*
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.cir.*
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.cir.impl.CirClassTypeImpl
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.cir.impl.CirTypeAliasTypeImpl
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.CirProvided
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.CirProvidedClassifiers
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.TypeParameterResolver
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.core.computeExpandedType
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.utils.*
|
||||
import org.jetbrains.kotlin.types.*
|
||||
@@ -29,6 +34,56 @@ object CirTypeFactory {
|
||||
private val typeAliasTypeInterner = Interner<CirTypeAliasType>()
|
||||
private val typeParameterTypeInterner = Interner<CirTypeParameterType>()
|
||||
|
||||
fun create(source: KmType, typeResolver: CirTypeResolver): CirType {
|
||||
@Suppress("NAME_SHADOWING")
|
||||
val source = source.abbreviatedType ?: source
|
||||
val isMarkedNullable = Flag.Type.IS_NULLABLE(source.flags)
|
||||
|
||||
return when (val classifier = source.classifier) {
|
||||
is KmClassifier.Class -> {
|
||||
val classId = CirEntityId.create(classifier.name)
|
||||
|
||||
val outerType = source.outerType?.let { outerType ->
|
||||
val outerClassType = create(outerType, typeResolver)
|
||||
check(outerClassType is CirClassType) { "Outer type of $classId is not a class: $outerClassType" }
|
||||
outerClassType
|
||||
}
|
||||
|
||||
val clazz: CirProvided.Class = typeResolver.resolveClassifier(classId)
|
||||
|
||||
createClassType(
|
||||
classId = classId,
|
||||
outerType = outerType,
|
||||
visibility = clazz.visibility,
|
||||
arguments = createArguments(source.arguments, typeResolver),
|
||||
isMarkedNullable = isMarkedNullable
|
||||
)
|
||||
}
|
||||
is KmClassifier.TypeAlias -> {
|
||||
val typeAliasId = CirEntityId.create(classifier.name)
|
||||
|
||||
val arguments = createArguments(source.arguments, typeResolver)
|
||||
|
||||
val underlyingType = CirTypeAliasExpander.expand(
|
||||
CirTypeAliasExpansion.create(typeAliasId, arguments, isMarkedNullable, typeResolver)
|
||||
)
|
||||
|
||||
createTypeAliasType(
|
||||
typeAliasId = typeAliasId,
|
||||
underlyingType = underlyingType,
|
||||
arguments = arguments,
|
||||
isMarkedNullable = isMarkedNullable
|
||||
)
|
||||
}
|
||||
is KmClassifier.TypeParameter -> {
|
||||
createTypeParameterType(
|
||||
index = typeResolver.resolveTypeParameterIndex(classifier.id),
|
||||
isMarkedNullable = isMarkedNullable
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun create(source: KotlinType): CirType = source.unwrap().run {
|
||||
when (this) {
|
||||
is SimpleType -> create(this)
|
||||
@@ -161,6 +216,13 @@ object CirTypeFactory {
|
||||
inline fun <T : CirSimpleType> makeNullableIfNecessary(type: T, necessary: Boolean): T =
|
||||
if (!necessary) type else makeNullable(type)
|
||||
|
||||
@Suppress("NOTHING_TO_INLINE")
|
||||
inline fun decodeVariance(variance: KmVariance): Variance = when (variance) {
|
||||
KmVariance.INVARIANT -> Variance.INVARIANT
|
||||
KmVariance.IN -> Variance.IN_VARIANCE
|
||||
KmVariance.OUT -> Variance.OUT_VARIANCE
|
||||
}
|
||||
|
||||
fun unabbreviate(type: CirClassOrTypeAliasType): CirClassType = when (type) {
|
||||
is CirClassType -> {
|
||||
var hasAbbreviationsInArguments = false
|
||||
@@ -239,6 +301,19 @@ object CirTypeFactory {
|
||||
)
|
||||
}
|
||||
|
||||
@Suppress("NOTHING_TO_INLINE")
|
||||
private inline fun createArguments(arguments: List<KmTypeProjection>, typeResolver: CirTypeResolver): List<CirTypeProjection> {
|
||||
return arguments.compactMap { argument ->
|
||||
val variance = argument.variance ?: return@compactMap CirStarTypeProjection
|
||||
val argumentType = argument.type ?: return@compactMap CirStarTypeProjection
|
||||
|
||||
CirTypeProjectionImpl(
|
||||
projectionKind = decodeVariance(variance),
|
||||
type = create(argumentType, typeResolver)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private inline val TypeParameterDescriptor.typeParameterIndex: Int
|
||||
get() {
|
||||
var index = index
|
||||
@@ -257,3 +332,68 @@ object CirTypeFactory {
|
||||
return index
|
||||
}
|
||||
}
|
||||
|
||||
typealias TypeParameterId = Int
|
||||
typealias TypeParameterIndex = Int
|
||||
|
||||
abstract class CirTypeResolver : TypeParameterResolver {
|
||||
abstract val providedClassifiers: CirProvidedClassifiers
|
||||
protected abstract val typeParameterIndexOffset: Int
|
||||
|
||||
inline fun <reified T : CirProvided.Classifier> resolveClassifier(classifierId: CirEntityId): T {
|
||||
val classifier = providedClassifiers.classifier(classifierId)
|
||||
?: error("Unresolved classifier: $classifierId")
|
||||
|
||||
check(classifier is T) {
|
||||
"Resolved classifier $classifierId of type ${classifier::class.java.simpleName}. Expected: ${T::class.java.simpleName}."
|
||||
}
|
||||
|
||||
return classifier
|
||||
}
|
||||
|
||||
abstract fun resolveTypeParameterIndex(id: TypeParameterId): TypeParameterIndex
|
||||
abstract override fun resolveTypeParameter(id: TypeParameterId): KmTypeParameter
|
||||
|
||||
private class TopLevel(override val providedClassifiers: CirProvidedClassifiers) : CirTypeResolver() {
|
||||
override val typeParameterIndexOffset get() = 0
|
||||
|
||||
override fun resolveTypeParameterIndex(id: TypeParameterId) = error("Unresolved type parameter: id=$id")
|
||||
override fun resolveTypeParameter(id: TypeParameterId) = error("Unresolved type parameter: id=$id")
|
||||
}
|
||||
|
||||
private class Nested(
|
||||
private val parent: CirTypeResolver,
|
||||
private val typeParameterMapping: TIntObjectHashMap<TypeParameterInfo>
|
||||
) : CirTypeResolver() {
|
||||
override val providedClassifiers get() = parent.providedClassifiers
|
||||
override val typeParameterIndexOffset = typeParameterMapping.size() + parent.typeParameterIndexOffset
|
||||
|
||||
override fun resolveTypeParameterIndex(id: TypeParameterId) =
|
||||
typeParameterMapping[id]?.index ?: parent.resolveTypeParameterIndex(id)
|
||||
|
||||
override fun resolveTypeParameter(id: TypeParameterId) =
|
||||
typeParameterMapping[id]?.typeParameter ?: parent.resolveTypeParameter(id)
|
||||
}
|
||||
|
||||
private class TypeParameterInfo(val index: TypeParameterIndex, val typeParameter: KmTypeParameter)
|
||||
|
||||
fun create(typeParameters: List<KmTypeParameter>): CirTypeResolver =
|
||||
if (typeParameters.isEmpty())
|
||||
this
|
||||
else {
|
||||
val mapping = TIntObjectHashMap<TypeParameterInfo>(typeParameters.size * 2)
|
||||
typeParameters.forEachIndexed { localIndex, typeParameter ->
|
||||
val typeParameterInfo = TypeParameterInfo(
|
||||
index = localIndex + typeParameterIndexOffset,
|
||||
typeParameter = typeParameter
|
||||
)
|
||||
mapping.put(typeParameter.id, typeParameterInfo)
|
||||
}
|
||||
|
||||
Nested(this, mapping)
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun create(providedClassifiers: CirProvidedClassifiers): CirTypeResolver = TopLevel(providedClassifiers)
|
||||
}
|
||||
}
|
||||
|
||||
+13
@@ -5,12 +5,17 @@
|
||||
|
||||
package org.jetbrains.kotlin.descriptors.commonizer.cir.factory
|
||||
|
||||
import kotlinx.metadata.Flag
|
||||
import kotlinx.metadata.KmTypeParameter
|
||||
import kotlinx.metadata.klib.annotations
|
||||
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirAnnotation
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirName
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirType
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirTypeParameter
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.cir.factory.CirTypeFactory.decodeVariance
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.cir.impl.CirTypeParameterImpl
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.metadata.ALWAYS_HAS_ANNOTATIONS
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.utils.compactMap
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.utils.filteredUpperBounds
|
||||
import org.jetbrains.kotlin.types.Variance
|
||||
@@ -24,6 +29,14 @@ object CirTypeParameterFactory {
|
||||
upperBounds = source.filteredUpperBounds.compactMap(CirTypeFactory::create)
|
||||
)
|
||||
|
||||
fun create(source: KmTypeParameter, typeResolver: CirTypeResolver): CirTypeParameter = create(
|
||||
annotations = CirAnnotationFactory.createAnnotations(ALWAYS_HAS_ANNOTATIONS, typeResolver, source::annotations),
|
||||
name = CirName.create(source.name),
|
||||
isReified = Flag.TypeParameter.IS_REIFIED(source.flags),
|
||||
variance = decodeVariance(source.variance),
|
||||
upperBounds = source.filteredUpperBounds.compactMap { CirTypeFactory.create(it, typeResolver) }
|
||||
)
|
||||
|
||||
@Suppress("NOTHING_TO_INLINE")
|
||||
inline fun create(
|
||||
annotations: List<CirAnnotation>,
|
||||
|
||||
+13
@@ -5,6 +5,9 @@
|
||||
|
||||
package org.jetbrains.kotlin.descriptors.commonizer.cir.factory
|
||||
|
||||
import kotlinx.metadata.Flag
|
||||
import kotlinx.metadata.KmValueParameter
|
||||
import kotlinx.metadata.klib.annotations
|
||||
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirAnnotation
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirName
|
||||
@@ -27,6 +30,16 @@ object CirValueParameterFactory {
|
||||
isNoinline = source.isNoinline
|
||||
)
|
||||
|
||||
fun create(source: KmValueParameter, typeResolver: CirTypeResolver): CirValueParameter = create(
|
||||
annotations = CirAnnotationFactory.createAnnotations(source.flags, typeResolver, source::annotations),
|
||||
name = CirName.create(source.name),
|
||||
returnType = CirTypeFactory.create(source.type!!, typeResolver),
|
||||
varargElementType = source.varargElementType?.let { CirTypeFactory.create(it, typeResolver) },
|
||||
declaresDefaultValue = Flag.ValueParameter.DECLARES_DEFAULT_VALUE(source.flags),
|
||||
isCrossinline = Flag.ValueParameter.IS_CROSSINLINE(source.flags),
|
||||
isNoinline = Flag.ValueParameter.IS_NOINLINE(source.flags)
|
||||
)
|
||||
|
||||
fun create(
|
||||
annotations: List<CirAnnotation>,
|
||||
name: CirName,
|
||||
|
||||
@@ -11,7 +11,7 @@ import org.jetbrains.kotlin.descriptors.commonizer.ResultsConsumer.Status
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.core.CommonizationVisitor
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.*
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.CirNode.Companion.dimension
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.CirTreeMerger.CirTreeMergeResult
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.CirTreeMergerV2.CirTreeMergeResult
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.metadata.MetadataBuilder
|
||||
import org.jetbrains.kotlin.library.SerializedMetadata
|
||||
import org.jetbrains.kotlin.storage.LockBasedStorageManager
|
||||
@@ -46,7 +46,7 @@ private fun mergeAndCommonize(storageManager: StorageManager, parameters: Common
|
||||
CirProvidedClassifiers.by(parameters.dependencyModulesProvider)
|
||||
)
|
||||
)
|
||||
val mergeResult = CirTreeMerger(storageManager, classifiers, parameters).merge()
|
||||
val mergeResult = CirTreeMergerV2(storageManager, classifiers, parameters).build()
|
||||
|
||||
// commonize:
|
||||
val mergedTree = mergeResult.root
|
||||
|
||||
+20
-6
@@ -5,10 +5,12 @@
|
||||
|
||||
package org.jetbrains.kotlin.descriptors.commonizer.mergedtree
|
||||
|
||||
import gnu.trove.THashSet
|
||||
import gnu.trove.THashMap
|
||||
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirEntityId
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirName
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirPackageName
|
||||
import org.jetbrains.kotlin.types.Variance
|
||||
|
||||
object CirFictitiousFunctionClassifiers : CirProvidedClassifiers {
|
||||
private const val MIN_ARITY = 0
|
||||
@@ -17,16 +19,28 @@ object CirFictitiousFunctionClassifiers : CirProvidedClassifiers {
|
||||
private val FUNCTION_PREFIXES = arrayOf("Function", "SuspendFunction")
|
||||
private val PACKAGE_NAME = CirPackageName.create("kotlin")
|
||||
|
||||
private val classifiers: Set<CirEntityId> = THashSet<CirEntityId>().apply {
|
||||
private val classifiers: Map<CirEntityId, CirProvided.Class> = THashMap<CirEntityId, CirProvided.Class>().apply {
|
||||
(MIN_ARITY..MAX_ARITY).forEach { arity ->
|
||||
FUNCTION_PREFIXES.forEach { prefix ->
|
||||
this += buildFictitiousFunctionClass(prefix, arity)
|
||||
buildFictitiousFunctionClass(prefix, arity, this::set)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun hasClassifier(classifierId: CirEntityId): Boolean = classifierId in classifiers
|
||||
override fun hasClassifier(classifierId: CirEntityId) = classifierId in classifiers
|
||||
override fun classifier(classifierId: CirEntityId): CirProvided.Class? = classifiers[classifierId]
|
||||
|
||||
private fun buildFictitiousFunctionClass(prefix: String, arity: Int): CirEntityId =
|
||||
CirEntityId.create(PACKAGE_NAME, CirName.create("$prefix$arity"))
|
||||
private inline fun buildFictitiousFunctionClass(prefix: String, arity: Int, consumer: (CirEntityId, CirProvided.Class) -> Unit) {
|
||||
val typeParameters = List(arity + 1) { index ->
|
||||
CirProvided.TypeParameter(
|
||||
index = index,
|
||||
variance = if (index == arity) Variance.OUT_VARIANCE else Variance.IN_VARIANCE
|
||||
)
|
||||
}
|
||||
|
||||
val classId = CirEntityId.create(PACKAGE_NAME, CirName.create("$prefix$arity"))
|
||||
val clazz = CirProvided.Class(typeParameters, DescriptorVisibilities.PUBLIC)
|
||||
|
||||
consumer(classId, clazz)
|
||||
}
|
||||
}
|
||||
|
||||
+60
-4
@@ -5,22 +5,29 @@
|
||||
|
||||
package org.jetbrains.kotlin.descriptors.commonizer.mergedtree
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.DescriptorVisibility
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.ModulesProvider
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirEntityId
|
||||
import org.jetbrains.kotlin.types.Variance
|
||||
|
||||
/** A set of classes and type aliases provided by libraries (either the libraries to commonize, or their dependency libraries)/ */
|
||||
interface CirProvidedClassifiers {
|
||||
fun hasClassifier(classifierId: CirEntityId): Boolean
|
||||
|
||||
// TODO: implement later
|
||||
//fun classifier(classifierId: ClassId): Any?
|
||||
fun classifier(classifierId: CirEntityId): CirProvided.Classifier?
|
||||
|
||||
object EMPTY : CirProvidedClassifiers {
|
||||
override fun hasClassifier(classifierId: CirEntityId) = false
|
||||
override fun classifier(classifierId: CirEntityId): CirProvided.Classifier? = null
|
||||
}
|
||||
|
||||
private class CompositeClassifiers(val delegates: List<CirProvidedClassifiers>) : CirProvidedClassifiers {
|
||||
override fun hasClassifier(classifierId: CirEntityId) = delegates.any { it.hasClassifier(classifierId) }
|
||||
override fun classifier(classifierId: CirEntityId): CirProvided.Classifier? {
|
||||
for (delegate in delegates) {
|
||||
delegate.classifier(classifierId)?.let { return it }
|
||||
}
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
@@ -42,6 +49,55 @@ interface CirProvidedClassifiers {
|
||||
}
|
||||
|
||||
fun by(modulesProvider: ModulesProvider?): CirProvidedClassifiers =
|
||||
if (modulesProvider != null) CirProvidedClassifiersByModules(modulesProvider) else EMPTY
|
||||
if (modulesProvider != null) CirProvidedClassifiersByModules.load(modulesProvider) else EMPTY
|
||||
}
|
||||
}
|
||||
|
||||
object CirProvided {
|
||||
/* Classifiers */
|
||||
sealed interface Classifier {
|
||||
val typeParameters: List<TypeParameter>
|
||||
}
|
||||
|
||||
data class Class(
|
||||
override val typeParameters: List<TypeParameter>,
|
||||
val visibility: DescriptorVisibility
|
||||
) : Classifier
|
||||
|
||||
data class TypeAlias(
|
||||
override val typeParameters: List<TypeParameter>,
|
||||
val underlyingType: Type
|
||||
) : Classifier
|
||||
|
||||
/* Type parameter */
|
||||
data class TypeParameter(val index: Int, val variance: Variance)
|
||||
|
||||
/* Types */
|
||||
sealed interface Type {
|
||||
val isMarkedNullable: Boolean
|
||||
}
|
||||
|
||||
data class TypeParameterType(
|
||||
val index: Int,
|
||||
override val isMarkedNullable: Boolean
|
||||
) : Type
|
||||
|
||||
data class ClassType(
|
||||
val classId: CirEntityId,
|
||||
val outerType: ClassType?,
|
||||
val arguments: List<TypeProjection>,
|
||||
override val isMarkedNullable: Boolean
|
||||
) : Type
|
||||
|
||||
data class TypeAliasType(
|
||||
val typeAliasId: CirEntityId,
|
||||
val arguments: List<TypeProjection>,
|
||||
override val isMarkedNullable: Boolean
|
||||
) : Type
|
||||
|
||||
/* Type projections */
|
||||
sealed interface TypeProjection
|
||||
object StarTypeProjection : TypeProjection
|
||||
data class RegularTypeProjection(val variance: Variance, val type: Type) : TypeProjection
|
||||
}
|
||||
|
||||
|
||||
+236
-37
@@ -5,58 +5,257 @@
|
||||
|
||||
package org.jetbrains.kotlin.descriptors.commonizer.mergedtree
|
||||
|
||||
import gnu.trove.THashSet
|
||||
import com.intellij.util.containers.FactoryMap
|
||||
import gnu.trove.THashMap
|
||||
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.ModulesProvider
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirEntityId
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirName
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirPackageName
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.utils.NON_EXISTING_CLASSIFIER_ID
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.utils.compactMap
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.utils.compactMapIndexed
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.utils.isUnderKotlinNativeSyntheticPackages
|
||||
import org.jetbrains.kotlin.library.SerializedMetadata
|
||||
import org.jetbrains.kotlin.library.metadata.parsePackageFragment
|
||||
import org.jetbrains.kotlin.metadata.ProtoBuf
|
||||
import org.jetbrains.kotlin.metadata.deserialization.NameResolverImpl
|
||||
import org.jetbrains.kotlin.metadata.deserialization.*
|
||||
import org.jetbrains.kotlin.serialization.deserialization.ProtoEnumFlags
|
||||
import org.jetbrains.kotlin.serialization.deserialization.descriptorVisibility
|
||||
import org.jetbrains.kotlin.types.Variance
|
||||
|
||||
internal class CirProvidedClassifiersByModules(modulesProvider: ModulesProvider) : CirProvidedClassifiers {
|
||||
private val classifiers: Set<CirEntityId> = loadClassifiers(modulesProvider)
|
||||
internal class CirProvidedClassifiersByModules private constructor(
|
||||
private val hasForwardDeclarations: Boolean,
|
||||
private val classifiers: Map<CirEntityId, CirProvided.Classifier>,
|
||||
) : CirProvidedClassifiers {
|
||||
override fun hasClassifier(classifierId: CirEntityId) =
|
||||
if (classifierId.packageName.isUnderKotlinNativeSyntheticPackages) {
|
||||
hasForwardDeclarations
|
||||
} else {
|
||||
classifierId in classifiers
|
||||
}
|
||||
|
||||
override fun hasClassifier(classifierId: CirEntityId): Boolean = classifierId in classifiers
|
||||
}
|
||||
override fun classifier(classifierId: CirEntityId) =
|
||||
if (classifierId.packageName.isUnderKotlinNativeSyntheticPackages) {
|
||||
if (hasForwardDeclarations) FALLBACK_FORWARD_DECLARATION_CLASS else null
|
||||
} else {
|
||||
classifiers[classifierId]
|
||||
}
|
||||
|
||||
private fun loadClassifiers(modulesProvider: ModulesProvider): Set<CirEntityId> {
|
||||
val result = THashSet<CirEntityId>()
|
||||
companion object {
|
||||
fun load(modulesProvider: ModulesProvider): CirProvidedClassifiers {
|
||||
val classifiers = THashMap<CirEntityId, CirProvided.Classifier>()
|
||||
var hasForwardDeclarations = false
|
||||
|
||||
modulesProvider.loadModuleInfos().forEach { moduleInfo ->
|
||||
val metadata = modulesProvider.loadModuleMetadata(moduleInfo.name)
|
||||
|
||||
for (i in metadata.fragmentNames.indices) {
|
||||
val packageFqName = metadata.fragmentNames[i]
|
||||
val packageFragments = metadata.fragments[i]
|
||||
|
||||
for (j in packageFragments.indices) {
|
||||
val packageFragment: ProtoBuf.PackageFragment = parsePackageFragment(packageFragments[j])
|
||||
|
||||
val classes: List<ProtoBuf.Class> = packageFragment.class_List
|
||||
val typeAliases: List<ProtoBuf.TypeAlias> = packageFragment.`package`?.typeAliasList.orEmpty()
|
||||
|
||||
if (classes.isEmpty() && typeAliases.isEmpty())
|
||||
break // this and next package fragments do not contain classifiers and can be skipped
|
||||
|
||||
val packageName = CirPackageName.create(packageFqName)
|
||||
val nameResolver = NameResolverImpl(packageFragment.strings, packageFragment.qualifiedNames)
|
||||
|
||||
for (clazz in classes) {
|
||||
if (!nameResolver.isLocalClassName(clazz.fqName)) {
|
||||
val classId = CirEntityId.create(nameResolver.getQualifiedClassName(clazz.fqName))
|
||||
check(classId.packageName == packageName)
|
||||
result += classId
|
||||
}
|
||||
modulesProvider.loadModuleInfos().forEach { moduleInfo ->
|
||||
if (moduleInfo.cInteropAttributes != null) {
|
||||
// this is a C-interop module
|
||||
hasForwardDeclarations = true
|
||||
}
|
||||
|
||||
for (typeAlias in typeAliases) {
|
||||
val typeAliasId = CirEntityId.create(packageName, CirName.create(nameResolver.getString(typeAlias.name)))
|
||||
result += typeAliasId
|
||||
val metadata = modulesProvider.loadModuleMetadata(moduleInfo.name)
|
||||
readModule(metadata, classifiers::set)
|
||||
}
|
||||
|
||||
if (classifiers.isEmpty)
|
||||
return CirProvidedClassifiers.EMPTY
|
||||
|
||||
return CirProvidedClassifiersByModules(hasForwardDeclarations, classifiers)
|
||||
}
|
||||
|
||||
private val FALLBACK_FORWARD_DECLARATION_CLASS = CirProvided.Class(emptyList(), DescriptorVisibilities.PUBLIC)
|
||||
}
|
||||
}
|
||||
|
||||
private fun readModule(metadata: SerializedMetadata, consumer: (CirEntityId, CirProvided.Classifier) -> Unit) {
|
||||
for (i in metadata.fragmentNames.indices) {
|
||||
val packageFqName = metadata.fragmentNames[i]
|
||||
val packageFragments = metadata.fragments[i]
|
||||
|
||||
val classProtosToRead = ClassProtosToRead()
|
||||
|
||||
for (j in packageFragments.indices) {
|
||||
val packageFragmentProto = parsePackageFragment(packageFragments[j])
|
||||
|
||||
val classProtos: List<ProtoBuf.Class> = packageFragmentProto.class_List
|
||||
val typeAliasProtos: List<ProtoBuf.TypeAlias> = packageFragmentProto.`package`?.typeAliasList.orEmpty()
|
||||
|
||||
if (classProtos.isEmpty() && typeAliasProtos.isEmpty())
|
||||
continue
|
||||
|
||||
val packageName = CirPackageName.create(packageFqName)
|
||||
val strings = NameResolverImpl(packageFragmentProto.strings, packageFragmentProto.qualifiedNames)
|
||||
|
||||
classProtosToRead.addClasses(classProtos, strings)
|
||||
|
||||
if (typeAliasProtos.isNotEmpty()) {
|
||||
val types = TypeTable(packageFragmentProto.`package`.typeTable)
|
||||
for (typeAliasProto in typeAliasProtos) {
|
||||
readTypeAlias(typeAliasProto, packageName, strings, types, consumer)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
classProtosToRead.forEachClassInScope(parentClassId = null) { classEntry ->
|
||||
readClass(classEntry, classProtosToRead, typeParameterIndexOffset = 0, consumer)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class ClassProtosToRead {
|
||||
data class ClassEntry(val classId: CirEntityId, val proto: ProtoBuf.Class)
|
||||
|
||||
// key = parent class ID (or NON_EXISTING_CLASSIFIER_ID for top-level classes)
|
||||
// value = class protos under this parent class (MutableList to preserve order of classes)
|
||||
private val groupedByParentClassId = FactoryMap.create<CirEntityId, MutableList<ClassEntry>> { ArrayList() }
|
||||
|
||||
fun addClasses(classProtos: List<ProtoBuf.Class>, strings: NameResolver) {
|
||||
classProtos.forEach { classProto ->
|
||||
if (strings.isLocalClassName(classProto.fqName)) return@forEach
|
||||
|
||||
val classId = CirEntityId.create(strings.getQualifiedClassName(classProto.fqName))
|
||||
val parentClassId: CirEntityId = classId.getParentEntityId() ?: NON_EXISTING_CLASSIFIER_ID
|
||||
|
||||
groupedByParentClassId.getValue(parentClassId) += ClassEntry(classId, classProto)
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
fun forEachClassInScope(parentClassId: CirEntityId?, block: (ClassEntry) -> Unit) {
|
||||
groupedByParentClassId[parentClassId ?: NON_EXISTING_CLASSIFIER_ID]?.forEach { classEntry -> block(classEntry) }
|
||||
}
|
||||
}
|
||||
|
||||
private fun readClass(
|
||||
classEntry: ClassProtosToRead.ClassEntry,
|
||||
classProtosToRead: ClassProtosToRead,
|
||||
typeParameterIndexOffset: Int,
|
||||
consumer: (CirEntityId, CirProvided.Classifier) -> Unit
|
||||
) {
|
||||
val (classId, classProto) = classEntry
|
||||
|
||||
val typeParameters = readTypeParameters(
|
||||
typeParameterProtos = classProto.typeParameterList,
|
||||
typeParameterIndexOffset = typeParameterIndexOffset
|
||||
)
|
||||
val visibility = ProtoEnumFlags.descriptorVisibility(Flags.VISIBILITY.get(classProto.flags))
|
||||
val clazz = CirProvided.Class(typeParameters, visibility)
|
||||
|
||||
consumer(classId, clazz)
|
||||
|
||||
classProtosToRead.forEachClassInScope(parentClassId = classId) { nestedClassEntry ->
|
||||
readClass(nestedClassEntry, classProtosToRead, typeParameterIndexOffset = typeParameters.size + typeParameterIndexOffset, consumer)
|
||||
}
|
||||
}
|
||||
|
||||
private inline fun readTypeAlias(
|
||||
typeAliasProto: ProtoBuf.TypeAlias,
|
||||
packageName: CirPackageName,
|
||||
strings: NameResolver,
|
||||
types: TypeTable,
|
||||
consumer: (CirEntityId, CirProvided.Classifier) -> Unit
|
||||
) {
|
||||
val typeAliasId = CirEntityId.create(packageName, CirName.create(strings.getString(typeAliasProto.name)))
|
||||
|
||||
val typeParameterNameToIndex = HashMap<Int, Int>()
|
||||
val typeParameters = readTypeParameters(
|
||||
typeParameterProtos = typeAliasProto.typeParameterList,
|
||||
typeParameterIndexOffset = 0,
|
||||
nameToIndexMapper = typeParameterNameToIndex::set
|
||||
)
|
||||
|
||||
val underlyingType = readType(typeAliasProto.underlyingType(types), TypeReadContext(strings, types, typeParameterNameToIndex))
|
||||
val typeAlias = CirProvided.TypeAlias(typeParameters, underlyingType)
|
||||
|
||||
consumer(typeAliasId, typeAlias)
|
||||
}
|
||||
|
||||
private inline fun readTypeParameters(
|
||||
typeParameterProtos: List<ProtoBuf.TypeParameter>,
|
||||
typeParameterIndexOffset: Int,
|
||||
nameToIndexMapper: (name: Int, id: Int) -> Unit = { _, _ -> }
|
||||
): List<CirProvided.TypeParameter> =
|
||||
typeParameterProtos.compactMapIndexed { localIndex, typeParameterProto ->
|
||||
val index = localIndex + typeParameterIndexOffset
|
||||
val typeParameter = CirProvided.TypeParameter(
|
||||
index = index,
|
||||
variance = readVariance(typeParameterProto.variance)
|
||||
)
|
||||
nameToIndexMapper(typeParameterProto.name, index)
|
||||
typeParameter
|
||||
}
|
||||
|
||||
private class TypeReadContext(
|
||||
val strings: NameResolver,
|
||||
val types: TypeTable,
|
||||
private val _typeParameterNameToIndex: Map<Int, Int>
|
||||
) {
|
||||
val typeParameterNameToIndex: (Int) -> Int = { name ->
|
||||
_typeParameterNameToIndex[name] ?: error("No type parameter index for ${strings.getString(name)}")
|
||||
}
|
||||
|
||||
private val _typeParameterIdToIndex = HashMap<Int, Int>()
|
||||
val typeParameterIdToIndex: (Int) -> Int = { id -> _typeParameterIdToIndex.getOrPut(id) { _typeParameterIdToIndex.size } }
|
||||
}
|
||||
|
||||
private fun readType(typeProto: ProtoBuf.Type, context: TypeReadContext): CirProvided.Type =
|
||||
with(typeProto.abbreviatedType(context.types) ?: typeProto) {
|
||||
when {
|
||||
hasClassName() -> {
|
||||
val classId = CirEntityId.create(context.strings.getQualifiedClassName(className))
|
||||
val outerType = typeProto.outerType(context.types)?.let { outerType ->
|
||||
val outerClassType = readType(outerType, context)
|
||||
check(outerClassType is CirProvided.ClassType) { "Outer type of $classId is not a class: $outerClassType" }
|
||||
outerClassType
|
||||
}
|
||||
|
||||
CirProvided.ClassType(
|
||||
classId = classId,
|
||||
outerType = outerType,
|
||||
arguments = readTypeArguments(argumentList, context),
|
||||
isMarkedNullable = nullable
|
||||
)
|
||||
}
|
||||
hasTypeAliasName() -> CirProvided.TypeAliasType(
|
||||
typeAliasId = CirEntityId.create(context.strings.getQualifiedClassName(typeAliasName)),
|
||||
arguments = readTypeArguments(argumentList, context),
|
||||
isMarkedNullable = nullable
|
||||
)
|
||||
hasTypeParameter() -> CirProvided.TypeParameterType(
|
||||
index = context.typeParameterIdToIndex(typeParameter),
|
||||
isMarkedNullable = nullable
|
||||
)
|
||||
hasTypeParameterName() -> CirProvided.TypeParameterType(
|
||||
index = context.typeParameterNameToIndex(typeParameterName),
|
||||
isMarkedNullable = nullable
|
||||
)
|
||||
else -> error("No classifier (class, type alias or type parameter) recorded for Type")
|
||||
}
|
||||
}
|
||||
|
||||
private fun readTypeArguments(argumentProtos: List<ProtoBuf.Type.Argument>, context: TypeReadContext): List<CirProvided.TypeProjection> =
|
||||
argumentProtos.compactMap { argumentProto ->
|
||||
val variance = readVariance(argumentProto.projection!!) ?: return@compactMap CirProvided.StarTypeProjection
|
||||
val typeProto = argumentProto.type(context.types) ?: error("No type argument for non-STAR projection in Type")
|
||||
|
||||
CirProvided.RegularTypeProjection(
|
||||
variance = variance,
|
||||
type = readType(typeProto, context)
|
||||
)
|
||||
}
|
||||
|
||||
@Suppress("NOTHING_TO_INLINE")
|
||||
private inline fun readVariance(varianceProto: ProtoBuf.TypeParameter.Variance): Variance =
|
||||
when (varianceProto) {
|
||||
ProtoBuf.TypeParameter.Variance.IN -> Variance.IN_VARIANCE
|
||||
ProtoBuf.TypeParameter.Variance.OUT -> Variance.OUT_VARIANCE
|
||||
ProtoBuf.TypeParameter.Variance.INV -> Variance.INVARIANT
|
||||
}
|
||||
|
||||
@Suppress("NOTHING_TO_INLINE")
|
||||
private inline fun readVariance(varianceProto: ProtoBuf.Type.Argument.Projection): Variance? =
|
||||
when (varianceProto) {
|
||||
ProtoBuf.Type.Argument.Projection.IN -> Variance.IN_VARIANCE
|
||||
ProtoBuf.Type.Argument.Projection.OUT -> Variance.OUT_VARIANCE
|
||||
ProtoBuf.Type.Argument.Projection.INV -> Variance.INVARIANT
|
||||
ProtoBuf.Type.Argument.Projection.STAR -> null
|
||||
}
|
||||
|
||||
+414
@@ -0,0 +1,414 @@
|
||||
/*
|
||||
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.descriptors.commonizer.mergedtree
|
||||
|
||||
import com.intellij.util.containers.FactoryMap
|
||||
import kotlinx.metadata.*
|
||||
import kotlinx.metadata.klib.KlibModuleMetadata
|
||||
import kotlinx.metadata.klib.fqName
|
||||
import kotlinx.metadata.klib.klibEnumEntries
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.CommonizerParameters
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.LeafCommonizerTarget
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.ModulesProvider.ModuleInfo
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.TargetProvider
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirEntityId
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirName
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirPackageName
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.cir.factory.*
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ClassesToProcess.ClassEntry
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.metadata.utils.SerializedMetadataLibraryProvider
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.prettyName
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.utils.*
|
||||
import org.jetbrains.kotlin.storage.StorageManager
|
||||
|
||||
/**
|
||||
* N.B. Limitations on C/Obj-C interop.
|
||||
*
|
||||
* [Case 1]: An interop library with two fragments for two targets. The first fragment has a forward declaration of classifier A.
|
||||
* The second one has a definition of class A. Both fragments have a top-level callable (ex: function)
|
||||
* with the same signature that refers to type "A" as its return type.
|
||||
*
|
||||
* What will happen: Forward declarations will be ignored during building CIR merged tree. So the node for class A
|
||||
* will contain CirClass "A" for the second target only. This node will not succeed in commonization, and no common class
|
||||
* declaration will be produced. As a result the top-level callable will not be commonized, as it refers to the type "A"
|
||||
* that is not formally commonized.
|
||||
*
|
||||
* This is not strictly correct: The classifier "A" exists in both targets though in different form. So if the user
|
||||
* would write shared source code that uses "A" and the callable, then this code would successfully compile against both targets.
|
||||
*
|
||||
* The reason why commonization of such classifiers is not supported yet is that this is quite a rare case that requires
|
||||
* a complex implementation with potential performance penalty.
|
||||
*
|
||||
* [Case 2]: A library with two fragments for two targets. The first fragment is interop. The second one is not.
|
||||
* Similarly to case 1, the 1st fragment has a forward declaration of a classifier, and the 2nd has a real classifier.
|
||||
*
|
||||
* At the moment, this is an exotic case. It could happen if someone tries to commonize an MPP library for Native and non-Native
|
||||
* targets (which is not supported yet), or a Native library where one fragment is produced via C-interop tool and the other one
|
||||
* is compiled from Kotlin/Native source code (not sure this should be supported at all).
|
||||
*/
|
||||
class CirTreeMergerV2(
|
||||
private val storageManager: StorageManager,
|
||||
private val classifiers: CirKnownClassifiers,
|
||||
private val parameters: CommonizerParameters
|
||||
) {
|
||||
class CirTreeMergeResult(
|
||||
val root: CirRootNode,
|
||||
val missingModuleInfos: Map<LeafCommonizerTarget, Collection<ModuleInfo>>
|
||||
)
|
||||
|
||||
private class CirTreeMergingContext(
|
||||
val targetIndex: Int,
|
||||
val typeResolver: CirTypeResolver
|
||||
) {
|
||||
fun create(classEntry: ClassEntry): CirTreeMergingContext = when (classEntry) {
|
||||
is ClassEntry.RegularClassEntry -> create(classEntry.clazz.typeParameters)
|
||||
is ClassEntry.EnumEntry -> this
|
||||
}
|
||||
|
||||
fun create(typeParameters: List<KmTypeParameter>): CirTreeMergingContext {
|
||||
val newTypeResolver = typeResolver.create(typeParameters)
|
||||
return if (newTypeResolver !== typeResolver)
|
||||
CirTreeMergingContext(targetIndex, newTypeResolver)
|
||||
else
|
||||
this
|
||||
}
|
||||
}
|
||||
|
||||
private val leafTargetsSize = parameters.targetProviders.size
|
||||
|
||||
fun build(): CirTreeMergeResult {
|
||||
val result = processRoot()
|
||||
System.gc()
|
||||
return result
|
||||
}
|
||||
|
||||
private fun processRoot(): CirTreeMergeResult {
|
||||
val rootNode: CirRootNode = buildRootNode(storageManager, leafTargetsSize)
|
||||
|
||||
// remember any exported forward declarations from common fragments of dependee modules
|
||||
parameters.dependencyModulesProvider?.loadModuleInfos()?.forEach(::processCInteropModuleAttributes)
|
||||
|
||||
val commonModuleNames = parameters.getCommonModuleNames()
|
||||
val missingModuleInfosByTargets = mutableMapOf<LeafCommonizerTarget, Collection<ModuleInfo>>()
|
||||
|
||||
parameters.targetProviders.forEachIndexed { targetIndex, targetProvider ->
|
||||
val allModuleInfos = targetProvider.modulesProvider.loadModuleInfos()
|
||||
|
||||
val (commonModuleInfos, missingModuleInfos) = allModuleInfos.partition { it.name in commonModuleNames }
|
||||
processTarget(targetIndex, rootNode, targetProvider, commonModuleInfos)
|
||||
|
||||
missingModuleInfosByTargets[targetProvider.target] = missingModuleInfos
|
||||
|
||||
parameters.progressLogger?.invoke("Loaded declarations for ${targetProvider.target.prettyName}")
|
||||
System.gc()
|
||||
}
|
||||
|
||||
return CirTreeMergeResult(
|
||||
root = rootNode,
|
||||
missingModuleInfos = missingModuleInfosByTargets
|
||||
)
|
||||
}
|
||||
|
||||
private fun processTarget(
|
||||
targetIndex: Int,
|
||||
rootNode: CirRootNode,
|
||||
targetProvider: TargetProvider,
|
||||
commonModuleInfos: Collection<ModuleInfo>
|
||||
) {
|
||||
rootNode.targetDeclarations[targetIndex] = CirRootFactory.create(targetProvider.target)
|
||||
|
||||
if (commonModuleInfos.isEmpty())
|
||||
return
|
||||
|
||||
val context = CirTreeMergingContext(
|
||||
targetIndex = targetIndex,
|
||||
// all classifiers "visible" for the target:
|
||||
typeResolver = CirTypeResolver.create(
|
||||
providedClassifiers = CirProvidedClassifiers.of(
|
||||
classifiers.commonDependencies,
|
||||
CirProvidedClassifiers.by(targetProvider.dependencyModulesProvider),
|
||||
CirProvidedClassifiers.by(targetProvider.modulesProvider)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
commonModuleInfos.forEach { moduleInfo ->
|
||||
val metadata = targetProvider.modulesProvider.loadModuleMetadata(moduleInfo.name)
|
||||
val module = KlibModuleMetadata.read(SerializedMetadataLibraryProvider(metadata))
|
||||
processModule(context, rootNode, moduleInfo, module)
|
||||
}
|
||||
}
|
||||
|
||||
private fun processModule(
|
||||
context: CirTreeMergingContext,
|
||||
rootNode: CirRootNode,
|
||||
moduleInfo: ModuleInfo,
|
||||
module: KlibModuleMetadata
|
||||
) {
|
||||
processCInteropModuleAttributes(moduleInfo)
|
||||
|
||||
val moduleName: CirName = CirName.create(module.name)
|
||||
val moduleNode: CirModuleNode = rootNode.modules.getOrPut(moduleName) {
|
||||
buildModuleNode(storageManager, leafTargetsSize)
|
||||
}
|
||||
moduleNode.targetDeclarations[context.targetIndex] = CirModuleFactory.create(moduleName)
|
||||
|
||||
val groupedFragments: Map<CirPackageName, Collection<KmModuleFragment>> = module.fragments.foldToMap { fragment ->
|
||||
fragment.fqName?.let(CirPackageName::create) ?: error("A fragment without FQ name in module $moduleName: $fragment")
|
||||
}
|
||||
|
||||
groupedFragments.forEach { (packageName, fragments) ->
|
||||
processFragments(context, moduleNode, fragments, packageName)
|
||||
}
|
||||
}
|
||||
|
||||
private fun processFragments(
|
||||
context: CirTreeMergingContext,
|
||||
moduleNode: CirModuleNode,
|
||||
fragments: Collection<KmModuleFragment>,
|
||||
packageName: CirPackageName
|
||||
) {
|
||||
val packageNode: CirPackageNode = moduleNode.packages.getOrPut(packageName) {
|
||||
buildPackageNode(storageManager, leafTargetsSize)
|
||||
}
|
||||
packageNode.targetDeclarations[context.targetIndex] = CirPackageFactory.create(packageName)
|
||||
|
||||
val classesToProcess = ClassesToProcess()
|
||||
fragments.forEach { fragment ->
|
||||
classesToProcess.addClassesFromFragment(fragment)
|
||||
|
||||
fragment.pkg?.let { pkg ->
|
||||
pkg.properties.forEach { property ->
|
||||
val propertyContext = context.create(property.typeParameters)
|
||||
processProperty(propertyContext, packageNode, property)
|
||||
}
|
||||
pkg.functions.forEach { function ->
|
||||
val functionContext = context.create(function.typeParameters)
|
||||
processFunction(functionContext, packageNode, function)
|
||||
}
|
||||
pkg.typeAliases.forEach { typeAlias ->
|
||||
val typeAliasContext = context.create(typeAlias.typeParameters)
|
||||
processTypeAlias(typeAliasContext, packageNode, typeAlias)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
classesToProcess.forEachClassInScope(parentClassId = null) { classEntry ->
|
||||
val classContext = context.create(classEntry)
|
||||
processClass(classContext, packageNode, classEntry, classesToProcess)
|
||||
}
|
||||
}
|
||||
|
||||
private fun processProperty(
|
||||
context: CirTreeMergingContext,
|
||||
ownerNode: CirNodeWithMembers<*, *>,
|
||||
property: KmProperty
|
||||
) {
|
||||
if (property.isFakeOverride())
|
||||
return
|
||||
|
||||
val maybeClassOwnerNode: CirClassNode? = ownerNode as? CirClassNode
|
||||
|
||||
val approximationKey = PropertyApproximationKey(property, context.typeResolver)
|
||||
val propertyNode: CirPropertyNode = ownerNode.properties.getOrPut(approximationKey) {
|
||||
buildPropertyNode(storageManager, leafTargetsSize, classifiers, maybeClassOwnerNode?.commonDeclaration)
|
||||
}
|
||||
propertyNode.targetDeclarations[context.targetIndex] = CirPropertyFactory.create(
|
||||
name = approximationKey.name,
|
||||
source = property,
|
||||
containingClass = maybeClassOwnerNode?.targetDeclarations?.get(context.targetIndex),
|
||||
typeResolver = context.typeResolver
|
||||
)
|
||||
}
|
||||
|
||||
private fun processFunction(
|
||||
context: CirTreeMergingContext,
|
||||
ownerNode: CirNodeWithMembers<*, *>,
|
||||
function: KmFunction
|
||||
) {
|
||||
if (function.isFakeOverride()
|
||||
|| function.isKniBridgeFunction()
|
||||
|| function.isTopLevelDeprecatedFunction(isTopLevel = ownerNode !is CirClassNode)
|
||||
) {
|
||||
return
|
||||
}
|
||||
|
||||
val maybeClassOwnerNode: CirClassNode? = ownerNode as? CirClassNode
|
||||
|
||||
val approximationKey = FunctionApproximationKey(function, context.typeResolver)
|
||||
val functionNode: CirFunctionNode = ownerNode.functions.getOrPut(approximationKey) {
|
||||
buildFunctionNode(storageManager, leafTargetsSize, classifiers, maybeClassOwnerNode?.commonDeclaration)
|
||||
}
|
||||
functionNode.targetDeclarations[context.targetIndex] = CirFunctionFactory.create(
|
||||
name = approximationKey.name,
|
||||
source = function,
|
||||
containingClass = maybeClassOwnerNode?.targetDeclarations?.get(context.targetIndex),
|
||||
typeResolver = context.typeResolver
|
||||
)
|
||||
}
|
||||
|
||||
private fun processClass(
|
||||
context: CirTreeMergingContext,
|
||||
ownerNode: CirNodeWithMembers<*, *>,
|
||||
classEntry: ClassEntry,
|
||||
classesToProcess: ClassesToProcess
|
||||
) {
|
||||
val classId = classEntry.classId
|
||||
val className = classId.relativeNameSegments.last()
|
||||
|
||||
val maybeClassOwnerNode: CirClassNode? = ownerNode as? CirClassNode
|
||||
val classNode: CirClassNode = ownerNode.classes.getOrPut(className) {
|
||||
buildClassNode(storageManager, leafTargetsSize, classifiers, maybeClassOwnerNode?.commonDeclaration, classId)
|
||||
}
|
||||
|
||||
val clazz: KmClass?
|
||||
val isEnumEntry: Boolean
|
||||
|
||||
classNode.targetDeclarations[context.targetIndex] = when (classEntry) {
|
||||
is ClassEntry.RegularClassEntry -> {
|
||||
clazz = classEntry.clazz
|
||||
isEnumEntry = Flag.Class.IS_ENUM_ENTRY(clazz.flags)
|
||||
|
||||
CirClassFactory.create(className, clazz, context.typeResolver)
|
||||
}
|
||||
is ClassEntry.EnumEntry -> {
|
||||
clazz = null
|
||||
isEnumEntry = true
|
||||
|
||||
CirClassFactory.createDefaultEnumEntry(
|
||||
name = className,
|
||||
annotations = classEntry.annotations,
|
||||
enumClassId = classEntry.enumClassId,
|
||||
enumClass = classEntry.enumClass,
|
||||
typeResolver = context.typeResolver
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
if (!isEnumEntry) {
|
||||
clazz?.constructors?.forEach { constructor ->
|
||||
// TODO: nowhere to read constructor type parameters from
|
||||
//val constructorContext = context.create(constructor.typeParameters)
|
||||
|
||||
processClassConstructor(context, classNode, constructor)
|
||||
}
|
||||
}
|
||||
|
||||
clazz?.properties?.forEach { property ->
|
||||
val propertyContext = context.create(property.typeParameters)
|
||||
processProperty(propertyContext, classNode, property)
|
||||
}
|
||||
clazz?.functions?.forEach { function ->
|
||||
val functionContext = context.create(function.typeParameters)
|
||||
processFunction(functionContext, classNode, function)
|
||||
}
|
||||
|
||||
classesToProcess.forEachClassInScope(parentClassId = classId) { nestedClassEntry ->
|
||||
val nestedClassContext = context.create(nestedClassEntry)
|
||||
processClass(nestedClassContext, classNode, nestedClassEntry, classesToProcess)
|
||||
}
|
||||
}
|
||||
|
||||
private fun processClassConstructor(
|
||||
context: CirTreeMergingContext,
|
||||
classNode: CirClassNode,
|
||||
constructor: KmConstructor
|
||||
) {
|
||||
val approximationKey = ConstructorApproximationKey(constructor, context.typeResolver)
|
||||
val constructorNode: CirClassConstructorNode = classNode.constructors.getOrPut(approximationKey) {
|
||||
buildClassConstructorNode(storageManager, leafTargetsSize, classifiers, classNode.commonDeclaration)
|
||||
}
|
||||
constructorNode.targetDeclarations[context.targetIndex] = CirClassConstructorFactory.create(
|
||||
source = constructor,
|
||||
containingClass = classNode.targetDeclarations[context.targetIndex]!!,
|
||||
typeResolver = context.typeResolver
|
||||
)
|
||||
}
|
||||
|
||||
private fun processTypeAlias(
|
||||
context: CirTreeMergingContext,
|
||||
packageNode: CirPackageNode,
|
||||
typeAlias: KmTypeAlias
|
||||
) {
|
||||
val typeAliasName = CirName.create(typeAlias.name)
|
||||
val typeAliasId = CirEntityId.create(packageNode.packageName, typeAliasName)
|
||||
|
||||
val typeAliasNode: CirTypeAliasNode = packageNode.typeAliases.getOrPut(typeAliasName) {
|
||||
buildTypeAliasNode(storageManager, leafTargetsSize, classifiers, typeAliasId)
|
||||
}
|
||||
typeAliasNode.targetDeclarations[context.targetIndex] = CirTypeAliasFactory.create(
|
||||
name = typeAliasName,
|
||||
source = typeAlias,
|
||||
typeResolver = context.typeResolver
|
||||
)
|
||||
}
|
||||
|
||||
private fun processCInteropModuleAttributes(moduleInfo: ModuleInfo) {
|
||||
val cInteropAttributes = moduleInfo.cInteropAttributes ?: return
|
||||
val exportForwardDeclarations = cInteropAttributes.exportForwardDeclarations.takeIf { it.isNotEmpty() } ?: return
|
||||
|
||||
exportForwardDeclarations.forEach { classFqName ->
|
||||
// Class has synthetic package FQ name (cnames/objcnames). Need to transfer it to the main package.
|
||||
val packageName = CirPackageName.create(classFqName.substringBeforeLast('.', missingDelimiterValue = ""))
|
||||
val className = CirName.create(classFqName.substringAfterLast('.'))
|
||||
|
||||
classifiers.forwardDeclarations.addExportedForwardDeclaration(CirEntityId.create(packageName, className))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class ClassesToProcess {
|
||||
sealed class ClassEntry {
|
||||
abstract val classId: CirEntityId
|
||||
|
||||
data class RegularClassEntry(
|
||||
override val classId: CirEntityId,
|
||||
val clazz: KmClass
|
||||
) : ClassEntry()
|
||||
|
||||
data class EnumEntry(
|
||||
override val classId: CirEntityId,
|
||||
val annotations: List<KmAnnotation>,
|
||||
val enumClassId: CirEntityId,
|
||||
val enumClass: KmClass
|
||||
) : ClassEntry()
|
||||
}
|
||||
|
||||
// key = parent class ID (or NON_EXISTING_CLASSIFIER_ID for top-level classes)
|
||||
// value = classes under this parent class (MutableList to preserve order of classes)
|
||||
private val groupedByParentClassId = FactoryMap.create<CirEntityId, MutableList<ClassEntry>> { ArrayList() }
|
||||
|
||||
fun addClassesFromFragment(fragment: KmModuleFragment) {
|
||||
val klibEnumEntries = LinkedHashMap<CirEntityId, ClassEntry.EnumEntry>() // linked hash map to preserve order
|
||||
val regularClassIds = HashSet<CirEntityId>()
|
||||
|
||||
fragment.classes.forEach { clazz ->
|
||||
val classId: CirEntityId = CirEntityId.create(clazz.name)
|
||||
val parentClassId: CirEntityId = classId.getParentEntityId() ?: NON_EXISTING_CLASSIFIER_ID
|
||||
|
||||
if (Flag.Class.IS_ENUM_CLASS(clazz.flags)) {
|
||||
clazz.klibEnumEntries.forEach { entry ->
|
||||
val enumEntryId = classId.createNestedEntityId(CirName.create(entry.name))
|
||||
klibEnumEntries[enumEntryId] = ClassEntry.EnumEntry(enumEntryId, entry.annotations, classId, clazz)
|
||||
}
|
||||
}
|
||||
|
||||
groupedByParentClassId.getValue(parentClassId) += ClassEntry.RegularClassEntry(classId, clazz)
|
||||
regularClassIds += classId
|
||||
}
|
||||
|
||||
// add enum entries that are not stored in module as KmClass records
|
||||
klibEnumEntries.forEach { (enumEntryId, enumEntry) ->
|
||||
if (enumEntryId !in regularClassIds) {
|
||||
groupedByParentClassId.getValue(enumEntry.enumClassId) += enumEntry
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun forEachClassInScope(parentClassId: CirEntityId?, block: (ClassEntry) -> Unit) {
|
||||
groupedByParentClassId[parentClassId ?: NON_EXISTING_CLASSIFIER_ID]?.forEach { classEntry -> block(classEntry) }
|
||||
}
|
||||
}
|
||||
+43
-1
@@ -5,6 +5,8 @@
|
||||
|
||||
package org.jetbrains.kotlin.descriptors.commonizer.mergedtree
|
||||
|
||||
import kotlinx.metadata.*
|
||||
import kotlinx.metadata.klib.annotations
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirName
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirTypeSignature
|
||||
@@ -21,6 +23,11 @@ data class PropertyApproximationKey(
|
||||
CirName.create(property.name),
|
||||
property.extensionReceiverParameter?.type?.signature
|
||||
)
|
||||
|
||||
constructor(property: KmProperty, typeParameterResolver: TypeParameterResolver) : this(
|
||||
CirName.create(property.name),
|
||||
property.receiverParameterType?.computeSignature(typeParameterResolver)
|
||||
)
|
||||
}
|
||||
|
||||
/** Used for approximation of [SimpleFunctionDescriptor]s before running concrete [Commonizer]s */
|
||||
@@ -37,6 +44,13 @@ data class FunctionApproximationKey(
|
||||
function.extensionReceiverParameter?.type?.signature
|
||||
)
|
||||
|
||||
constructor(function: KmFunction, typeParameterResolver: TypeParameterResolver) : this(
|
||||
CirName.create(function.name),
|
||||
function.valueParameters.computeSignatures(typeParameterResolver),
|
||||
additionalValueParameterNamesHash(function.annotations, function.valueParameters),
|
||||
function.receiverParameterType?.computeSignature(typeParameterResolver)
|
||||
)
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (other !is FunctionApproximationKey)
|
||||
return false
|
||||
@@ -63,6 +77,11 @@ data class ConstructorApproximationKey(
|
||||
additionalValueParameterNamesHash(constructor)
|
||||
)
|
||||
|
||||
constructor(constructor: KmConstructor, typeParameterResolver: TypeParameterResolver) : this(
|
||||
constructor.valueParameters.computeSignatures(typeParameterResolver),
|
||||
additionalValueParameterNamesHash(constructor.annotations, constructor.valueParameters)
|
||||
)
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (other !is ConstructorApproximationKey)
|
||||
return false
|
||||
@@ -75,9 +94,24 @@ data class ConstructorApproximationKey(
|
||||
.appendHashCode(additionalValueParametersNamesHash)
|
||||
}
|
||||
|
||||
interface TypeParameterResolver {
|
||||
fun resolveTypeParameter(id: Int): KmTypeParameter?
|
||||
|
||||
companion object {
|
||||
val EMPTY = object : TypeParameterResolver {
|
||||
override fun resolveTypeParameter(id: Int): KmTypeParameter? = null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@JvmName("toTypeSignaturesDescriptors")
|
||||
@Suppress("NOTHING_TO_INLINE")
|
||||
private inline fun List<ValueParameterDescriptor>.toTypeSignatures(): Array<CirTypeSignature> =
|
||||
Array(size) { index -> this[index].type.signature }
|
||||
if (isEmpty()) emptyArray() else Array(size) { index -> this[index].type.signature }
|
||||
|
||||
@Suppress("NOTHING_TO_INLINE")
|
||||
private inline fun List<KmValueParameter>.computeSignatures(typeParameterResolver: TypeParameterResolver): Array<CirTypeSignature> =
|
||||
if (isEmpty()) emptyArray() else Array(size) { index -> this[index].type?.computeSignature(typeParameterResolver).orEmpty() }
|
||||
|
||||
private fun additionalValueParameterNamesHash(callable: FunctionDescriptor): Int {
|
||||
// TODO: add more precise checks when more languages than C & ObjC are supported
|
||||
@@ -86,3 +120,11 @@ private fun additionalValueParameterNamesHash(callable: FunctionDescriptor): Int
|
||||
|
||||
return callable.valueParameters.fold(0) { acc, next -> acc.appendHashCode(next.name.asString()) }
|
||||
}
|
||||
|
||||
private fun additionalValueParameterNamesHash(annotations: List<KmAnnotation>, valueParameters: List<KmValueParameter>): Int {
|
||||
// TODO: add more precise checks when more languages than C & ObjC are supported
|
||||
if (annotations.none { it.isObjCInteropCallableAnnotation })
|
||||
return 0 // do not calculate hash for non-ObjC callables
|
||||
|
||||
return valueParameters.fold(0) { acc, next -> acc.appendHashCode(next.name) }
|
||||
}
|
||||
|
||||
+3
-2
@@ -133,6 +133,7 @@ internal fun CirClassConstructor.buildClassConstructor(
|
||||
flags = classConstructorFlags()
|
||||
).also { constructor ->
|
||||
annotations.mapTo(constructor.annotations) { it.buildAnnotation() }
|
||||
// TODO: nowhere to write constructor type parameters
|
||||
valueParameters.mapTo(constructor.valueParameters) { it.buildValueParameter(context) }
|
||||
}
|
||||
|
||||
@@ -156,11 +157,11 @@ internal fun CirProperty.buildProperty(
|
||||
getterFlags = getter?.propertyAccessorFlags(this, this) ?: NO_FLAGS,
|
||||
setterFlags = setter?.let { setter -> setter.propertyAccessorFlags(setter, this) } ?: NO_FLAGS
|
||||
).also { property ->
|
||||
// TODO unclear where to write backing/delegate field annotations, see KT-44625
|
||||
annotations.mapTo(property.annotations) { it.buildAnnotation() }
|
||||
getter?.annotations?.mapTo(property.getterAnnotations) { it.buildAnnotation() }
|
||||
setter?.annotations?.mapTo(property.setterAnnotations) { it.buildAnnotation() }
|
||||
property.compileTimeValue = compileTimeInitializer?.takeIf { it !is CirConstantValue.NullValue }?.buildAnnotationArgument()
|
||||
// TODO unclear where to write backing/delegate field annotations, see KT-44625
|
||||
property.compileTimeValue = compileTimeInitializer.takeIf { it !is CirConstantValue.NullValue }?.buildAnnotationArgument()
|
||||
typeParameters.buildTypeParameters(context, output = property.typeParameters)
|
||||
extensionReceiver?.let { receiver ->
|
||||
// TODO nowhere to write receiver annotations, see KT-42490
|
||||
|
||||
+44
-4
@@ -8,13 +8,11 @@ package org.jetbrains.kotlin.descriptors.commonizer.metadata
|
||||
import kotlinx.metadata.Flag
|
||||
import kotlinx.metadata.Flags
|
||||
import kotlinx.metadata.flagsOf
|
||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.cir.*
|
||||
|
||||
internal const val NO_FLAGS: Flags = 0
|
||||
internal val ALWAYS_HAS_ANNOTATIONS: Flags = flagsOf(Flag.Common.HAS_ANNOTATIONS)
|
||||
|
||||
internal fun CirFunction.functionFlags(isExpect: Boolean): Flags =
|
||||
flagsOfNotNull(
|
||||
@@ -100,6 +98,48 @@ internal fun CirTypeAlias.typeAliasFlags(): Flags =
|
||||
visibilityFlag
|
||||
)
|
||||
|
||||
@Suppress("NOTHING_TO_INLINE")
|
||||
internal inline fun decodeVisibility(flags: Flags): DescriptorVisibility =
|
||||
when {
|
||||
Flag.Common.IS_PUBLIC(flags) -> DescriptorVisibilities.PUBLIC
|
||||
Flag.Common.IS_PROTECTED(flags) -> DescriptorVisibilities.PROTECTED
|
||||
Flag.Common.IS_INTERNAL(flags) -> DescriptorVisibilities.INTERNAL
|
||||
Flag.Common.IS_PRIVATE(flags) -> DescriptorVisibilities.PRIVATE
|
||||
else -> error("Can't decode visibility from flags: $flags")
|
||||
}
|
||||
|
||||
@Suppress("NOTHING_TO_INLINE")
|
||||
internal inline fun decodeModality(flags: Flags): Modality =
|
||||
when {
|
||||
Flag.Common.IS_FINAL(flags) -> Modality.FINAL
|
||||
Flag.Common.IS_ABSTRACT(flags) -> Modality.ABSTRACT
|
||||
Flag.Common.IS_OPEN(flags) -> Modality.OPEN
|
||||
Flag.Common.IS_SEALED(flags) -> Modality.SEALED
|
||||
else -> error("Can't decode modality from flags: $flags")
|
||||
}
|
||||
|
||||
@Suppress("NOTHING_TO_INLINE")
|
||||
internal inline fun decodeCallableKind(flags: Flags): CallableMemberDescriptor.Kind =
|
||||
when {
|
||||
Flag.Property.IS_DECLARATION(flags) /*|| Flag.Function.IS_DECLARATION(flags)*/ -> CallableMemberDescriptor.Kind.DECLARATION
|
||||
Flag.Property.IS_FAKE_OVERRIDE(flags) /*|| Flag.Function.IS_FAKE_OVERRIDE(flags)*/ -> CallableMemberDescriptor.Kind.FAKE_OVERRIDE
|
||||
Flag.Property.IS_DELEGATION(flags) /*|| Flag.Function.IS_DELEGATION(flags)*/ -> CallableMemberDescriptor.Kind.DELEGATION
|
||||
Flag.Property.IS_SYNTHESIZED(flags) /*|| Flag.Function.IS_SYNTHESIZED(flags)*/ -> CallableMemberDescriptor.Kind.SYNTHESIZED
|
||||
else -> error("Can't decode callable kind from flags: $flags")
|
||||
}
|
||||
|
||||
@Suppress("NOTHING_TO_INLINE")
|
||||
internal inline fun decodeClassKind(flags: Flags): ClassKind =
|
||||
when {
|
||||
Flag.Class.IS_CLASS(flags) -> ClassKind.CLASS
|
||||
Flag.Class.IS_INTERFACE(flags) -> ClassKind.INTERFACE
|
||||
Flag.Class.IS_ENUM_CLASS(flags) -> ClassKind.ENUM_CLASS
|
||||
Flag.Class.IS_ENUM_ENTRY(flags) -> ClassKind.ENUM_ENTRY
|
||||
Flag.Class.IS_ANNOTATION_CLASS(flags) -> ClassKind.ANNOTATION_CLASS
|
||||
Flag.Class.IS_OBJECT(flags) || Flag.Class.IS_COMPANION_OBJECT(flags) -> ClassKind.OBJECT
|
||||
else -> error("Can't decode class kind from flags: $flags")
|
||||
}
|
||||
|
||||
private inline val CirHasAnnotations.hasAnnotationsFlag: Flag?
|
||||
get() = if (annotations.isNotEmpty()) Flag.Common.HAS_ANNOTATIONS else null
|
||||
|
||||
|
||||
@@ -5,6 +5,10 @@
|
||||
|
||||
package org.jetbrains.kotlin.descriptors.commonizer.utils
|
||||
|
||||
import kotlinx.metadata.Flag
|
||||
import kotlinx.metadata.KmFunction
|
||||
import kotlinx.metadata.KmProperty
|
||||
import kotlinx.metadata.klib.annotations
|
||||
import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor
|
||||
|
||||
@@ -13,5 +17,21 @@ internal const val KNI_BRIDGE_FUNCTION_PREFIX = "kniBridge"
|
||||
internal fun SimpleFunctionDescriptor.isKniBridgeFunction() =
|
||||
name.asString().startsWith(KNI_BRIDGE_FUNCTION_PREFIX)
|
||||
|
||||
@Suppress("NOTHING_TO_INLINE")
|
||||
internal inline fun KmFunction.isKniBridgeFunction() =
|
||||
name.startsWith(KNI_BRIDGE_FUNCTION_PREFIX)
|
||||
|
||||
internal fun SimpleFunctionDescriptor.isDeprecatedTopLevelFunction() =
|
||||
containingDeclaration is PackageFragmentDescriptor && annotations.hasAnnotation(DEPRECATED_ANNOTATION_FQN)
|
||||
|
||||
@Suppress("NOTHING_TO_INLINE")
|
||||
internal inline fun KmFunction.isTopLevelDeprecatedFunction(isTopLevel: Boolean) =
|
||||
isTopLevel && annotations.any { it.className == DEPRECATED_ANNOTATION_FULL_NAME }
|
||||
|
||||
@Suppress("NOTHING_TO_INLINE")
|
||||
internal inline fun KmProperty.isFakeOverride() =
|
||||
Flag.Property.IS_FAKE_OVERRIDE(flags)
|
||||
|
||||
@Suppress("NOTHING_TO_INLINE")
|
||||
internal inline fun KmFunction.isFakeOverride() =
|
||||
Flag.Function.IS_FAKE_OVERRIDE(flags)
|
||||
|
||||
@@ -95,6 +95,15 @@ internal inline fun <K : Any, V> compactMapOf(key1: K, value1: V, key2: K, value
|
||||
|
||||
internal inline fun <reified T> Iterable<T?>.firstNonNull() = firstIsInstance<T>()
|
||||
|
||||
internal inline fun <reified T, reified K : Any> Collection<T>.foldToMap(keySelector: (T) -> K): Map<K, List<T>> {
|
||||
val result = fold(THashMap<K, MutableList<T>>()) { accumulator, element ->
|
||||
accumulator.getOrPut(keySelector(element)) { ArrayList() } += element
|
||||
accumulator
|
||||
}
|
||||
|
||||
return result.compactMapValues { (_, elements) -> elements.compact() }
|
||||
}
|
||||
|
||||
internal fun Any?.isNull(): Boolean = this == null
|
||||
|
||||
@Suppress("NOTHING_TO_INLINE")
|
||||
|
||||
+16
-4
@@ -6,6 +6,7 @@
|
||||
package org.jetbrains.kotlin.descriptors.commonizer.utils
|
||||
|
||||
import kotlinx.metadata.ClassName
|
||||
import kotlinx.metadata.KmAnnotation
|
||||
import org.jetbrains.kotlin.builtins.StandardNames
|
||||
import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
||||
@@ -17,16 +18,20 @@ import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.serialization.konan.impl.ForwardDeclarationsFqNames
|
||||
|
||||
internal val DEPRECATED_ANNOTATION_FQN: FqName = FqName(Deprecated::class.java.name)
|
||||
internal val DEPRECATED_ANNOTATION_CLASS_ID: CirEntityId = CirEntityId.create("kotlin/Deprecated")
|
||||
internal const val DEPRECATED_ANNOTATION_FULL_NAME: ClassName = "kotlin/Deprecated"
|
||||
internal val DEPRECATED_ANNOTATION_CLASS_ID: CirEntityId = CirEntityId.create(DEPRECATED_ANNOTATION_FULL_NAME)
|
||||
|
||||
internal val ANY_CLASS_ID: CirEntityId = CirEntityId.create("kotlin/Any")
|
||||
private val NOTHING_CLASS_ID: CirEntityId = CirEntityId.create("kotlin/Nothing")
|
||||
internal const val ANY_CLASS_FULL_NAME: ClassName = "kotlin/Any"
|
||||
internal val ANY_CLASS_ID: CirEntityId = CirEntityId.create(ANY_CLASS_FULL_NAME)
|
||||
|
||||
internal val SPECIAL_CLASS_WITHOUT_SUPERTYPES_CLASS_IDS: List<CirEntityId> = listOf(
|
||||
ANY_CLASS_ID,
|
||||
NOTHING_CLASS_ID
|
||||
CirEntityId.create("kotlin/Nothing")
|
||||
)
|
||||
|
||||
// illegal Kotlin classifier name, for special purposes only
|
||||
internal val NON_EXISTING_CLASSIFIER_ID = CirEntityId.create("$0")
|
||||
|
||||
internal val SPECIAL_CLASS_WITHOUT_SUPERTYPES_CLASS_NAMES: List<ClassName> =
|
||||
SPECIAL_CLASS_WITHOUT_SUPERTYPES_CLASS_IDS.map(CirEntityId::toString)
|
||||
|
||||
@@ -49,6 +54,10 @@ private val OBJC_INTEROP_CALLABLE_ANNOTATIONS: List<CirName> = listOf(
|
||||
CirName.create("ObjCFactory")
|
||||
)
|
||||
|
||||
private val OBJC_INTEROP_CALLABLE_ANNOTATION_FULL_NAMES: List<ClassName> = OBJC_INTEROP_CALLABLE_ANNOTATIONS.map { name ->
|
||||
CirEntityId.create(CINTEROP_PACKAGE, name).toString()
|
||||
}
|
||||
|
||||
internal val DEFAULT_CONSTRUCTOR_NAME: CirName = CirName.create("<init>")
|
||||
internal val DEFAULT_SETTER_VALUE_NAME: CirName = CirName.create("value")
|
||||
|
||||
@@ -70,3 +79,6 @@ internal val AnnotationDescriptor.isObjCInteropCallableAnnotation: Boolean
|
||||
return CirName.create(classifier.name) in OBJC_INTEROP_CALLABLE_ANNOTATIONS
|
||||
&& (classifier.containingDeclaration as? PackageFragmentDescriptor)?.fqName?.let(CirPackageName::create) == CINTEROP_PACKAGE
|
||||
}
|
||||
|
||||
internal val KmAnnotation.isObjCInteropCallableAnnotation: Boolean
|
||||
get() = className in OBJC_INTEROP_CALLABLE_ANNOTATION_FULL_NAMES
|
||||
@@ -5,12 +5,15 @@
|
||||
|
||||
package org.jetbrains.kotlin.descriptors.commonizer.utils
|
||||
|
||||
import gnu.trove.TIntHashSet
|
||||
import kotlinx.metadata.*
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirEntityId
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirName
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirPackageName
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirTypeSignature
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.TypeParameterResolver
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.classId
|
||||
import org.jetbrains.kotlin.types.*
|
||||
import org.jetbrains.kotlin.types.typeUtil.isNullableAny
|
||||
@@ -44,9 +47,21 @@ internal val ClassifierDescriptorWithTypeParameters.classifierId: CirEntityId
|
||||
internal inline val TypeParameterDescriptor.filteredUpperBounds: List<KotlinType>
|
||||
get() = upperBounds.takeUnless { it.singleOrNull()?.isNullableAny() == true } ?: emptyList()
|
||||
|
||||
internal inline val KmTypeParameter.filteredUpperBounds: List<KmType>
|
||||
get() = upperBounds.takeUnless { it.singleOrNull()?.isNullableAny == true } ?: emptyList()
|
||||
|
||||
internal inline val ClassDescriptor.filteredSupertypes: Collection<KotlinType>
|
||||
get() = typeConstructor.supertypes.takeUnless { it.size == 1 && KotlinBuiltIns.isAny(it.first()) } ?: emptyList()
|
||||
|
||||
internal inline val KmClass.filteredSupertypes: List<KmType>
|
||||
get() = supertypes.takeUnless { it.singleOrNull()?.isAny == true } ?: emptyList()
|
||||
|
||||
private inline val KmType.isNullableAny: Boolean
|
||||
get() = (classifier as? KmClassifier.Class)?.name == ANY_CLASS_FULL_NAME && Flag.Type.IS_NULLABLE(flags)
|
||||
|
||||
private inline val KmType.isAny: Boolean
|
||||
get() = (classifier as? KmClassifier.Class)?.name == ANY_CLASS_FULL_NAME && !Flag.Type.IS_NULLABLE(flags)
|
||||
|
||||
internal val KotlinType.signature: CirTypeSignature
|
||||
get() {
|
||||
// use of interner saves up to 95% of duplicates
|
||||
@@ -100,5 +115,84 @@ private fun StringBuilder.buildTypeSignature(type: KotlinType, exploredTypeParam
|
||||
}
|
||||
}
|
||||
|
||||
internal fun KmType.computeSignature(typeParameterResolver: TypeParameterResolver): CirTypeSignature {
|
||||
// use of interner saves up to 95% of duplicates
|
||||
return typeSignatureInterner.intern(
|
||||
buildString {
|
||||
buildTypeSignature(
|
||||
type = this@computeSignature,
|
||||
typeParameterResolver = typeParameterResolver,
|
||||
exploredTypeParameters = TIntHashSet()
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
private fun StringBuilder.buildTypeSignature(
|
||||
type: KmType,
|
||||
typeParameterResolver: TypeParameterResolver,
|
||||
exploredTypeParameters: TIntHashSet
|
||||
) {
|
||||
when (val classifier = type.classifier) {
|
||||
is KmClassifier.TypeParameter -> {
|
||||
// N.B this is type parameter type
|
||||
val typeParameter = typeParameterResolver.resolveTypeParameter(classifier.id)
|
||||
?: error("Unresolved type parameter #${classifier.id} in type ${type.classifier}")
|
||||
|
||||
append(typeParameter.name)
|
||||
|
||||
if (exploredTypeParameters.add(classifier.id)) { // print upper bounds once the first time when type parameter type is met
|
||||
append(':').append('[')
|
||||
typeParameter.filteredUpperBounds.forEachIndexed { index, upperBoundType ->
|
||||
if (index > 0)
|
||||
append(',')
|
||||
buildTypeSignature(upperBoundType, typeParameterResolver, exploredTypeParameters)
|
||||
}
|
||||
append(']')
|
||||
}
|
||||
|
||||
if (Flag.Type.IS_NULLABLE(type.flags))
|
||||
append('?')
|
||||
}
|
||||
else -> {
|
||||
val abbreviation = type.abbreviatedType ?: type
|
||||
|
||||
val classifierId = when (val abbreviationClassifier = abbreviation.classifier) {
|
||||
is KmClassifier.Class -> abbreviationClassifier.name
|
||||
is KmClassifier.TypeAlias -> abbreviationClassifier.name
|
||||
else -> error("Unexpected classifier type for non-type-parameter type: ${type.classifier}")
|
||||
}
|
||||
append(classifierId)
|
||||
|
||||
val arguments = abbreviation.arguments
|
||||
if (arguments.isNotEmpty()) {
|
||||
append('<')
|
||||
arguments.forEachIndexed { index, argument ->
|
||||
if (index > 0)
|
||||
append(',')
|
||||
|
||||
val variance = argument.variance
|
||||
val argumentType = argument.type
|
||||
|
||||
if (variance == null || argumentType == null)
|
||||
append('*')
|
||||
else {
|
||||
when (variance) {
|
||||
KmVariance.INVARIANT -> Unit
|
||||
KmVariance.IN -> append("in ")
|
||||
KmVariance.OUT -> append("out ")
|
||||
}
|
||||
buildTypeSignature(argumentType, typeParameterResolver, exploredTypeParameters)
|
||||
}
|
||||
}
|
||||
append('>')
|
||||
}
|
||||
|
||||
if (Flag.Type.IS_NULLABLE(abbreviation.flags))
|
||||
append('?')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// dedicated to hold unique entries of "signature"
|
||||
private val typeSignatureInterner = Interner<CirTypeSignature>()
|
||||
|
||||
Vendored
+1
-2
@@ -43,8 +43,7 @@ typealias Y = V // TA at the RHS with the different nullability of own RHS
|
||||
// Supertypes:
|
||||
expect class FILE : kotlinx.cinterop.CStructVar
|
||||
|
||||
typealias uuid_t = kotlinx.cinterop.CPointer<kotlinx.cinterop.UByteVarOf<kotlinx.cinterop.UByte>>
|
||||
// ^^^ TODO: ideally, it should be CArrayPointer<UByteVar>
|
||||
typealias uuid_t = kotlinx.cinterop.CArrayPointer<kotlinx.cinterop.UByteVar>
|
||||
typealias __darwin_uuid_t = kotlinx.cinterop.CArrayPointer<kotlinx.cinterop.UByteVar>
|
||||
|
||||
expect val uuid: uuid_t
|
||||
|
||||
+2
-1
@@ -34,7 +34,8 @@ class TypeCommonizerTest : AbstractCommonizerTest<CirType, CirType>() {
|
||||
commonizedNodes = CirCommonizedClassifierNodes.default(),
|
||||
forwardDeclarations = CirForwardDeclarations.default(),
|
||||
commonDependencies = object : CirProvidedClassifiers {
|
||||
override fun hasClassifier(classifierId: CirEntityId): Boolean = classifierId.packageName.isUnderStandardKotlinPackages
|
||||
override fun hasClassifier(classifierId: CirEntityId) = classifierId.packageName.isUnderStandardKotlinPackages
|
||||
override fun classifier(classifierId: CirEntityId) = error("This method should not be called")
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
+35
-18
@@ -6,6 +6,7 @@
|
||||
package org.jetbrains.kotlin.descriptors.commonizer.utils
|
||||
|
||||
import kotlinx.metadata.klib.KlibModuleMetadata
|
||||
import kotlinx.metadata.klib.annotations
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.CommonizerTarget
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.identityString
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.metadata.utils.MetadataDeclarationsComparator
|
||||
@@ -52,30 +53,46 @@ fun assertModulesAreEqual(reference: SerializedMetadata, generated: SerializedMe
|
||||
private val FILTER_OUT_ACCEPTABLE_MISMATCHES: (Mismatch) -> Boolean = { mismatch ->
|
||||
var isAcceptableMismatch = false // don't filter it out by default
|
||||
|
||||
if (mismatch is Mismatch.MissingEntity) {
|
||||
if (mismatch.kind == EntityKind.TypeKind.ABBREVIATED) {
|
||||
val usefulPath = mismatch.path
|
||||
.dropWhile { it !is PathElement.Package }
|
||||
.drop(1)
|
||||
when (mismatch) {
|
||||
is Mismatch.MissingEntity -> when (mismatch.kind) {
|
||||
EntityKind.TypeKind.ABBREVIATED -> {
|
||||
val usefulPath = mismatch.path
|
||||
.dropWhile { it !is PathElement.Package }
|
||||
.drop(1)
|
||||
|
||||
if (mismatch.missingInA) {
|
||||
if (usefulPath.size == 2
|
||||
&& usefulPath[0] is PathElement.TypeAlias
|
||||
&& (usefulPath[1] as? PathElement.Type)?.kind == EntityKind.TypeKind.EXPANDED
|
||||
) {
|
||||
// extra abbreviated type appeared in commonized declaration, it's OK
|
||||
isAcceptableMismatch = true
|
||||
if (mismatch.missingInA) {
|
||||
if (usefulPath.size == 2
|
||||
&& usefulPath[0] is PathElement.TypeAlias
|
||||
&& (usefulPath[1] as? PathElement.Type)?.kind == EntityKind.TypeKind.EXPANDED
|
||||
) {
|
||||
// extra abbreviated type appeared in commonized declaration, it's OK
|
||||
isAcceptableMismatch = true
|
||||
}
|
||||
} else /*if (mismatch.missingInB)*/ {
|
||||
if (usefulPath.size > 2
|
||||
&& usefulPath.any { (it as? PathElement.Type)?.kind == EntityKind.TypeKind.RETURN }
|
||||
&& usefulPath[usefulPath.size - 2] is PathElement.TypeArgument
|
||||
&& (usefulPath[usefulPath.size - 1] as? PathElement.Type)?.kind == EntityKind.TypeKind.TYPE_ARGUMENT
|
||||
) {
|
||||
// extra abbreviated type gone in type argument of commonized declaration, it's OK
|
||||
isAcceptableMismatch = true
|
||||
}
|
||||
}
|
||||
} else /*if (mismatch.missingInB)*/ {
|
||||
if (usefulPath.size > 2
|
||||
&& usefulPath.any { (it as? PathElement.Type)?.kind == EntityKind.TypeKind.RETURN }
|
||||
&& usefulPath[usefulPath.size - 2] is PathElement.TypeArgument
|
||||
&& (usefulPath[usefulPath.size - 1] as? PathElement.Type)?.kind == EntityKind.TypeKind.TYPE_ARGUMENT
|
||||
}
|
||||
else -> Unit
|
||||
}
|
||||
is Mismatch.DifferentValues -> when (mismatch.kind) {
|
||||
EntityKind.FlagKind.REGULAR, EntityKind.FlagKind.GETTER, EntityKind.FlagKind.SETTER -> {
|
||||
if (mismatch.name == "HAS_ANNOTATIONS"
|
||||
&& mismatch.valueA == true
|
||||
&& mismatch.valueB == false
|
||||
&& (mismatch.path.last() as? PathElement.Property)?.propertyA?.annotations.isNullOrEmpty()
|
||||
) {
|
||||
// extra abbreviated type gone in type argument of commonized declaration, it's OK
|
||||
// backing or delegate field annotations were not serialized (KT-44625) but the corresponding flag was raised, it's OK
|
||||
isAcceptableMismatch = true
|
||||
}
|
||||
}
|
||||
else -> Unit
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user