[Commonizer] Create approximation keys based on Cir instead of metadata

This commit is contained in:
sebastian.sellmair
2021-07-06 10:36:24 +02:00
committed by Space
parent 09f9a1ce5b
commit f3ff9814a8
21 changed files with 356 additions and 175 deletions
@@ -82,7 +82,7 @@ data class CirPropertyImpl(
override val kind: CallableMemberDescriptor.Kind, override val kind: CallableMemberDescriptor.Kind,
override val isVar: Boolean, override val isVar: Boolean,
override val isLateInit: Boolean, override val isLateInit: Boolean,
override var isConst: Boolean, override val isConst: Boolean,
override val isDelegate: Boolean, override val isDelegate: Boolean,
override val getter: CirPropertyGetter?, override val getter: CirPropertyGetter?,
override val setter: CirPropertySetter?, override val setter: CirPropertySetter?,
@@ -8,9 +8,7 @@ package org.jetbrains.kotlin.commonizer.core
import org.jetbrains.kotlin.commonizer.cir.* import org.jetbrains.kotlin.commonizer.cir.*
import org.jetbrains.kotlin.commonizer.cir.CirConstantValue.* import org.jetbrains.kotlin.commonizer.cir.CirConstantValue.*
import org.jetbrains.kotlin.commonizer.core.AnnotationsCommonizer.Companion.FALLBACK_MESSAGE import org.jetbrains.kotlin.commonizer.core.AnnotationsCommonizer.Companion.FALLBACK_MESSAGE
import org.jetbrains.kotlin.commonizer.utils.DEPRECATED_ANNOTATION_CLASS_ID import org.jetbrains.kotlin.commonizer.utils.*
import org.jetbrains.kotlin.commonizer.utils.compactMap
import org.jetbrains.kotlin.commonizer.utils.compactMapOf
import org.jetbrains.kotlin.descriptors.Visibilities import org.jetbrains.kotlin.descriptors.Visibilities
import kotlin.DeprecationLevel.WARNING import kotlin.DeprecationLevel.WARNING
@@ -19,15 +17,38 @@ import kotlin.DeprecationLevel.WARNING
*/ */
class AnnotationsCommonizer : AbstractStandardCommonizer<List<CirAnnotation>, List<CirAnnotation>>() { class AnnotationsCommonizer : AbstractStandardCommonizer<List<CirAnnotation>, List<CirAnnotation>>() {
private var deprecatedAnnotationCommonizer: DeprecatedAnnotationCommonizer? = null private var deprecatedAnnotationCommonizer: DeprecatedAnnotationCommonizer? = null
private var deprecatedAnnotationCommonizerHasResult: Boolean = true
private val objCInteropCallableAnnotationCommonizer = ObjCInteropCallableAnnotationCommonizer.asCommonizer()
private var objCInteropCallableAnnotationCommonizerHasResult = true
override fun commonizationResult(): List<CirAnnotation> { override fun commonizationResult(): List<CirAnnotation> {
val deprecatedAnnotation = deprecatedAnnotationCommonizer?.result ?: return emptyList() val deprecatedAnnotation = if (deprecatedAnnotationCommonizerHasResult)
return listOf(deprecatedAnnotation) deprecatedAnnotationCommonizer?.result else null
val objCInteropCallableAnnotations = if (objCInteropCallableAnnotationCommonizerHasResult)
objCInteropCallableAnnotationCommonizer.result else emptyList()
return if (deprecatedAnnotation != null) {
objCInteropCallableAnnotations.plus(deprecatedAnnotation)
} else objCInteropCallableAnnotations
} }
override fun initialize(first: List<CirAnnotation>) = Unit override fun initialize(first: List<CirAnnotation>) = Unit
override fun doCommonizeWith(next: List<CirAnnotation>): Boolean { override fun doCommonizeWith(next: List<CirAnnotation>): Boolean {
if (deprecatedAnnotationCommonizerHasResult) {
deprecatedAnnotationCommonizerHasResult = doCommonizeDeprecatedAnnotation(next)
}
if (objCInteropCallableAnnotationCommonizerHasResult) {
objCInteropCallableAnnotationCommonizerHasResult = objCInteropCallableAnnotationCommonizer.commonizeWith(next)
}
return true
}
private fun doCommonizeDeprecatedAnnotation(next: List<CirAnnotation>): Boolean {
val nextDeprecatedAnnotation = next.firstOrNull { it.type.classifierId == DEPRECATED_ANNOTATION_CLASS_ID } ?: return true val nextDeprecatedAnnotation = next.firstOrNull { it.type.classifierId == DEPRECATED_ANNOTATION_CLASS_ID } ?: return true
val deprecatedAnnotationCommonizer = deprecatedAnnotationCommonizer val deprecatedAnnotationCommonizer = deprecatedAnnotationCommonizer
@@ -41,6 +62,27 @@ class AnnotationsCommonizer : AbstractStandardCommonizer<List<CirAnnotation>, Li
} }
} }
object ObjCInteropCallableAnnotationCommonizer : AssociativeCommonizer<List<CirAnnotation>> {
override fun commonize(first: List<CirAnnotation>, second: List<CirAnnotation>): List<CirAnnotation> {
return if (first.any { it.type.classifierId.isObjCInteropCallableAnnotation } &&
second.any { it.type.classifierId.isObjCInteropCallableAnnotation }
) {
objCCallableAnnotationList
} else emptyList()
}
private val objCCallableAnnotation = CirAnnotation.createInterned(
CirClassType.createInterned(
classId = COMMONIZER_OBJC_INTEROP_CALLABLE_ANNOTATION_ID,
outerType = null, visibility = Visibilities.Public, arguments = emptyList(), isMarkedNullable = false
),
constantValueArguments = emptyMap(),
annotationValueArguments = emptyMap()
)
private val objCCallableAnnotationList = listOf(objCCallableAnnotation)
}
private class DeprecatedAnnotationCommonizer : Commonizer<CirAnnotation, CirAnnotation> { private class DeprecatedAnnotationCommonizer : Commonizer<CirAnnotation, CirAnnotation> {
private var level: DeprecationLevel? = null // null level means that state is empty private var level: DeprecationLevel? = null // null level means that state is empty
private var message: String? = null // null -> message is not equal private var message: String? = null // null -> message is not equal
@@ -18,13 +18,14 @@ class ClassConstructorCommonizer(
private val visibility = VisibilityCommonizer.equalizing() private val visibility = VisibilityCommonizer.equalizing()
private val typeParameters = TypeParameterListCommonizer(classifiers) private val typeParameters = TypeParameterListCommonizer(classifiers)
private val valueParameters = CallableValueParametersCommonizer(classifiers) private val valueParameters = CallableValueParametersCommonizer(classifiers)
private val annotationsCommonizer = AnnotationsCommonizer()
override fun commonizationResult(): CirClassConstructor { override fun commonizationResult(): CirClassConstructor {
val valueParameters = valueParameters.result val valueParameters = valueParameters.result
valueParameters.patchCallables() valueParameters.patchCallables()
return CirClassConstructor.create( return CirClassConstructor.create(
annotations = emptyList(), annotations = annotationsCommonizer.result,
typeParameters = typeParameters.result, typeParameters = typeParameters.result,
visibility = visibility.result, visibility = visibility.result,
containingClass = CONTAINING_CLASS_DOES_NOT_MATTER, // does not matter containingClass = CONTAINING_CLASS_DOES_NOT_MATTER, // does not matter
@@ -45,6 +46,7 @@ class ClassConstructorCommonizer(
&& visibility.commonizeWith(next) && visibility.commonizeWith(next)
&& typeParameters.commonizeWith(next.typeParameters) && typeParameters.commonizeWith(next.typeParameters)
&& valueParameters.commonizeWith(next) && valueParameters.commonizeWith(next)
&& annotationsCommonizer.commonizeWith(next.annotations)
} }
companion object { companion object {
@@ -0,0 +1,29 @@
/*
* 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.commonizer.mergedtree
import org.jetbrains.kotlin.commonizer.cir.CirClass
internal class CirMemberContext private constructor(val classes: List<CirClass>) {
companion object {
val empty = CirMemberContext(emptyList())
}
fun withContextOf(clazz: CirClass) = CirMemberContext(classes = classes + clazz)
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false
other as CirMemberContext
if (classes != other.classes) return false
return true
}
override fun hashCode(): Int {
return classes.hashCode()
}
}
@@ -3,50 +3,61 @@
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/ */
@file:Suppress("FunctionName")
package org.jetbrains.kotlin.commonizer.mergedtree package org.jetbrains.kotlin.commonizer.mergedtree
import kotlinx.metadata.* import gnu.trove.TIntHashSet
import kotlinx.metadata.klib.annotations import org.jetbrains.kotlin.commonizer.cir.*
import org.jetbrains.kotlin.commonizer.cir.CirName import org.jetbrains.kotlin.commonizer.utils.Interner
import org.jetbrains.kotlin.commonizer.cir.CirTypeSignature
import org.jetbrains.kotlin.commonizer.core.Commonizer
import org.jetbrains.kotlin.commonizer.metadata.CirTypeParameterResolver
import org.jetbrains.kotlin.commonizer.utils.appendHashCode import org.jetbrains.kotlin.commonizer.utils.appendHashCode
import org.jetbrains.kotlin.commonizer.utils.computeSignature
import org.jetbrains.kotlin.commonizer.utils.hashCode import org.jetbrains.kotlin.commonizer.utils.hashCode
import org.jetbrains.kotlin.commonizer.utils.isObjCInteropCallableAnnotation import org.jetbrains.kotlin.commonizer.utils.isObjCInteropCallableAnnotation
import org.jetbrains.kotlin.types.Variance
typealias ObjCFunctionApproximation = Int
/** Used for approximation of [KmProperty]s before running concrete [Commonizer]s */
data class PropertyApproximationKey( data class PropertyApproximationKey(
val name: CirName, val name: CirName,
val extensionReceiverParameterType: CirTypeSignature? val extensionReceiverParameterType: CirTypeSignature?
) { ) {
constructor(property: KmProperty, typeParameterResolver: CirTypeParameterResolver) : this( companion object {
CirName.create(property.name), internal fun create(context: CirMemberContext, property: CirProperty): PropertyApproximationKey {
property.receiverParameterType?.computeSignature(typeParameterResolver) return PropertyApproximationKey(
) name = property.name,
extensionReceiverParameterType = property.extensionReceiver
?.let { buildApproximationSignature(SignatureBuildingContext.create(context, property), it.type) }
)
}
}
} }
/** Used for approximation of [KmFunction]s before running concrete [Commonizer]s */
data class FunctionApproximationKey( data class FunctionApproximationKey(
val name: CirName, val name: CirName,
val valueParametersTypes: Array<CirTypeSignature>, val valueParametersTypes: Array<CirTypeSignature>,
private val additionalValueParametersNamesHash: Int, val extensionReceiverParameterType: CirTypeSignature?,
val extensionReceiverParameterType: CirTypeSignature? val objCFunctionApproximation: ObjCFunctionApproximation
) { ) {
constructor(function: KmFunction, typeParameterResolver: CirTypeParameterResolver) : this(
CirName.create(function.name), companion object {
function.valueParameters.computeSignatures(typeParameterResolver), internal fun create(context: CirMemberContext, function: CirFunction): FunctionApproximationKey {
additionalValueParameterNamesHash(function.annotations, function.valueParameters), return FunctionApproximationKey(
function.receiverParameterType?.computeSignature(typeParameterResolver) name = function.name,
) valueParametersTypes = valueParameterTypes(context, function),
extensionReceiverParameterType = function.extensionReceiver
?.let { buildApproximationSignature(SignatureBuildingContext.create(context, function), it.type) },
objCFunctionApproximation = objCFunctionApproximation(function)
)
}
}
override fun equals(other: Any?): Boolean { override fun equals(other: Any?): Boolean {
if (other !is FunctionApproximationKey) if (other !is FunctionApproximationKey)
return false return false
return name == other.name return name == other.name
&& additionalValueParametersNamesHash == other.additionalValueParametersNamesHash && objCFunctionApproximation == other.objCFunctionApproximation
&& valueParametersTypes.contentEquals(other.valueParametersTypes) && valueParametersTypes.contentEquals(other.valueParametersTypes)
&& extensionReceiverParameterType == other.extensionReceiverParameterType && extensionReceiverParameterType == other.extensionReceiverParameterType
} }
@@ -54,39 +65,155 @@ data class FunctionApproximationKey(
override fun hashCode() = hashCode(name) override fun hashCode() = hashCode(name)
.appendHashCode(valueParametersTypes) .appendHashCode(valueParametersTypes)
.appendHashCode(extensionReceiverParameterType) .appendHashCode(extensionReceiverParameterType)
.appendHashCode(additionalValueParametersNamesHash) .appendHashCode(objCFunctionApproximation)
} }
/** Used for approximation of [KmConstructor]s before running concrete [Commonizer]s */
data class ConstructorApproximationKey( data class ConstructorApproximationKey(
val valueParametersTypes: Array<CirTypeSignature>, val valueParametersTypes: Array<CirTypeSignature>,
private val additionalValueParametersNamesHash: Int private val objCFunctionApproximation: ObjCFunctionApproximation
) { ) {
constructor(constructor: KmConstructor, typeParameterResolver: CirTypeParameterResolver) : this(
constructor.valueParameters.computeSignatures(typeParameterResolver), companion object {
additionalValueParameterNamesHash(constructor.annotations, constructor.valueParameters) internal fun create(context: CirMemberContext, constructor: CirClassConstructor): ConstructorApproximationKey {
) return ConstructorApproximationKey(
valueParametersTypes = valueParameterTypes(context, constructor),
objCFunctionApproximation = objCFunctionApproximation(constructor)
)
}
}
override fun equals(other: Any?): Boolean { override fun equals(other: Any?): Boolean {
if (other !is ConstructorApproximationKey) if (other !is ConstructorApproximationKey)
return false return false
return additionalValueParametersNamesHash == other.additionalValueParametersNamesHash return objCFunctionApproximation == other.objCFunctionApproximation
&& valueParametersTypes.contentEquals(other.valueParametersTypes) && valueParametersTypes.contentEquals(other.valueParametersTypes)
} }
override fun hashCode() = hashCode(valueParametersTypes) override fun hashCode() = hashCode(valueParametersTypes)
.appendHashCode(additionalValueParametersNamesHash) .appendHashCode(objCFunctionApproximation)
} }
@Suppress("NOTHING_TO_INLINE") private fun <T> objCFunctionApproximation(value: T): ObjCFunctionApproximation
private inline fun List<KmValueParameter>.computeSignatures(typeParameterResolver: CirTypeParameterResolver): Array<CirTypeSignature> = where T : CirHasAnnotations, T : CirCallableMemberWithParameters {
if (isEmpty()) emptyArray() else Array(size) { index -> this[index].type?.computeSignature(typeParameterResolver).orEmpty() } return if (value.annotations.any { it.type.classifierId.isObjCInteropCallableAnnotation }) {
value.valueParameters.fold(0) { acc, next -> acc.appendHashCode(next.name) }
private fun additionalValueParameterNamesHash(annotations: List<KmAnnotation>, valueParameters: List<KmValueParameter>): Int { } else 0
// 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 private fun <T> valueParameterTypes(context: CirMemberContext, callable: T): Array<CirTypeSignature>
where T : CirHasTypeParameters, T : CirCallableMemberWithParameters, T : CirMaybeCallableMemberOfClass {
return valueParameters.fold(0) { acc, next -> acc.appendHashCode(next.name) } if (callable.valueParameters.isEmpty()) return emptyArray()
return Array(callable.valueParameters.size) { index ->
val parameter = callable.valueParameters[index]
buildApproximationSignature(SignatureBuildingContext.create(context, callable), parameter.returnType)
}
}
private val typeSignatureInterner = Interner<CirTypeSignature>()
internal fun buildApproximationSignature(context: SignatureBuildingContext, type: CirType): CirTypeSignature {
return typeSignatureInterner.intern(StringBuilder().apply { appendTypeApproximationSignature(context, type) }.toString())
}
internal fun StringBuilder.appendTypeApproximationSignature(context: SignatureBuildingContext, type: CirType) {
return when (type) {
is CirFlexibleType -> appendFlexibleTypeApproximationSignature(context, type)
is CirTypeParameterType -> appendTypeParameterTypeApproximationSignature(context.forTypeParameterTypes(), type)
is CirClassOrTypeAliasType -> appendClassOrTypeAliasTypeApproximationSignature(context, type)
}
}
internal fun StringBuilder.appendClassOrTypeAliasTypeApproximationSignature(
context: SignatureBuildingContext, type: CirClassOrTypeAliasType
) {
append(type.classifierId.toString())
if (type.arguments.isNotEmpty()) {
append("<")
type.arguments.forEachIndexed { index, argument ->
when (argument) {
is CirRegularTypeProjection -> {
when (argument.projectionKind) {
Variance.INVARIANT -> Unit
Variance.IN_VARIANCE -> append("in ")
Variance.OUT_VARIANCE -> append("out ")
}
appendTypeApproximationSignature(context, argument.type)
}
is CirStarTypeProjection -> append("*")
}
if (index != type.arguments.lastIndex) {
append(", ")
}
}
append(">")
}
if (type.isMarkedNullable) append("?")
}
private fun StringBuilder.appendTypeParameterTypeApproximationSignature(
context: TypeParameterTypeSignatureBuildingContext, type: CirTypeParameterType
) {
val typeParameter = context.resolveTypeParameter(type.index)
append(typeParameter.name)
if (context.isVisitedFirstTime(type.index)) {
append(" : [")
typeParameter.upperBounds.forEachIndexed { index, upperBound ->
appendTypeApproximationSignature(context, upperBound)
if (index != typeParameter.upperBounds.lastIndex) append(", ")
}
}
append("]")
if (type.isMarkedNullable) append("?")
}
private fun StringBuilder.appendFlexibleTypeApproximationSignature(
context: SignatureBuildingContext, type: CirFlexibleType
) {
appendTypeApproximationSignature(context, type.lowerBound)
append("..")
appendTypeApproximationSignature(context, type.upperBound)
}
internal sealed interface SignatureBuildingContext {
companion object {
fun create(memberContext: CirMemberContext, functionOrPropertyOrConstructor: CirHasTypeParameters): SignatureBuildingContext {
return DefaultSignatureBuildingContext(memberContext, functionOrPropertyOrConstructor)
}
}
}
private fun SignatureBuildingContext.forTypeParameterTypes(): TypeParameterTypeSignatureBuildingContext = when (this) {
is DefaultSignatureBuildingContext -> TypeParameterTypeSignatureBuildingContext(memberContext, functionOrPropertyOrConstructor)
is TypeParameterTypeSignatureBuildingContext -> this
}
private class DefaultSignatureBuildingContext(
val memberContext: CirMemberContext,
val functionOrPropertyOrConstructor: CirHasTypeParameters
) : SignatureBuildingContext
private class TypeParameterTypeSignatureBuildingContext(
private val memberContext: CirMemberContext,
private val functionOrPropertyOrConstructor: CirHasTypeParameters
) : SignatureBuildingContext {
private val alreadyVisitedParameterTypeIndices = TIntHashSet()
fun isVisitedFirstTime(typeParameterIndex: Int): Boolean {
return alreadyVisitedParameterTypeIndices.add(typeParameterIndex)
}
fun resolveTypeParameter(index: Int): CirTypeParameter {
var indexOffset = 0
memberContext.classes.forEach { clazz ->
val indexInClass = index - indexOffset
if (indexInClass >= 0 && indexInClass <= clazz.typeParameters.lastIndex) {
return clazz.typeParameters[indexInClass]
}
indexOffset += clazz.typeParameters.size
}
return functionOrPropertyOrConstructor.typeParameters[index - indexOffset]
}
} }
@@ -21,22 +21,12 @@ data class CirTreeModule(
data class CirTreePackage( data class CirTreePackage(
val pkg: CirPackage, val pkg: CirPackage,
val properties: List<CirTreeProperty> = emptyList(), val properties: List<CirProperty> = emptyList(),
val functions: List<CirTreeFunction> = emptyList(), val functions: List<CirFunction> = emptyList(),
val classes: List<CirTreeClass> = emptyList(), val classes: List<CirTreeClass> = emptyList(),
val typeAliases: List<CirTreeTypeAlias> = emptyList() val typeAliases: List<CirTreeTypeAlias> = emptyList()
) )
data class CirTreeProperty(
val approximationKey: PropertyApproximationKey,
val property: CirProperty
)
data class CirTreeFunction(
val approximationKey: FunctionApproximationKey,
val function: CirFunction
)
sealed interface CirTreeClassifier { sealed interface CirTreeClassifier {
val id: CirEntityId val id: CirEntityId
} }
@@ -49,14 +39,10 @@ data class CirTreeTypeAlias(
data class CirTreeClass( data class CirTreeClass(
override val id: CirEntityId, override val id: CirEntityId,
val clazz: CirClass, val clazz: CirClass,
val properties: List<CirTreeProperty> = emptyList(), val properties: List<CirProperty> = emptyList(),
val functions: List<CirTreeFunction> = emptyList(), val functions: List<CirFunction> = emptyList(),
val constructors: List<CirTreeClassConstructor> = emptyList(), val constructors: List<CirClassConstructor> = emptyList(),
val classes: List<CirTreeClass> = emptyList(), val classes: List<CirTreeClass> = emptyList(),
) : CirTreeClassifier ) : CirTreeClassifier
class CirTreeClassConstructor(
val approximationKey: ConstructorApproximationKey,
val constructor: CirClassConstructor
)
@@ -28,8 +28,8 @@ internal fun CirPackageNode.assembleCirTree(): CirTreePackage? {
return CirTreePackage( return CirTreePackage(
pkg = commonizedPackage, pkg = commonizedPackage,
properties = properties.mapNotNull { (key, property) -> property.assembleCirTree(key) }, properties = properties.mapNotNull { (key, property) -> property.commonDeclaration() },
functions = functions.mapNotNull { (key, function) -> function.assembleCirTree(key) }, functions = functions.mapNotNull { (key, function) -> function.commonDeclaration() },
typeAliases = commonizedTypeAliases.filterIsInstance<CirTreeTypeAlias>(), typeAliases = commonizedTypeAliases.filterIsInstance<CirTreeTypeAlias>(),
classes = classes.mapNotNull { (_, clazz) -> clazz.assembleCirTree() } + commonizedTypeAliases.filterIsInstance<CirTreeClass>() classes = classes.mapNotNull { (_, clazz) -> clazz.assembleCirTree() } + commonizedTypeAliases.filterIsInstance<CirTreeClass>()
) )
@@ -39,9 +39,9 @@ internal fun CirClassNode.assembleCirTree(): CirTreeClass? {
return CirTreeClass( return CirTreeClass(
id = id, id = id,
clazz = commonDeclaration() ?: return null, clazz = commonDeclaration() ?: return null,
properties = properties.mapNotNull { (key, property) -> property.assembleCirTree(key) }, properties = properties.mapNotNull { (key, property) -> property.commonDeclaration() },
functions = functions.mapNotNull { (key, function) -> function.assembleCirTree(key) }, functions = functions.mapNotNull { (key, function) -> function.commonDeclaration() },
constructors = constructors.mapNotNull { (key, constructor) -> constructor.assembleCirTree(key) }, constructors = constructors.mapNotNull { (key, constructor) -> constructor.commonDeclaration() },
classes = classes.mapNotNull { (_, clazz) -> clazz.assembleCirTree() } classes = classes.mapNotNull { (_, clazz) -> clazz.assembleCirTree() }
) )
} }
@@ -54,24 +54,3 @@ internal fun CirTypeAliasNode.assembleCirTree(): CirTreeClassifier? {
} }
} }
internal fun CirPropertyNode.assembleCirTree(approximationKey: PropertyApproximationKey): CirTreeProperty? {
return CirTreeProperty(
approximationKey = approximationKey,
property = commonDeclaration() ?: return null,
)
}
internal fun CirFunctionNode.assembleCirTree(approximationKey: FunctionApproximationKey): CirTreeFunction? {
return CirTreeFunction(
approximationKey = approximationKey,
function = commonDeclaration() ?: return null,
)
}
internal fun CirClassConstructorNode.assembleCirTree(approximationKey: ConstructorApproximationKey): CirTreeClassConstructor? {
return CirTreeClassConstructor(
approximationKey = approximationKey,
constructor = commonDeclaration() ?: return null
)
}
@@ -6,23 +6,19 @@
package org.jetbrains.kotlin.commonizer.tree.deserializer package org.jetbrains.kotlin.commonizer.tree.deserializer
import kotlinx.metadata.KmConstructor import kotlinx.metadata.KmConstructor
import org.jetbrains.kotlin.commonizer.cir.CirClassConstructor
import org.jetbrains.kotlin.commonizer.cir.CirContainingClass import org.jetbrains.kotlin.commonizer.cir.CirContainingClass
import org.jetbrains.kotlin.commonizer.mergedtree.ConstructorApproximationKey
import org.jetbrains.kotlin.commonizer.metadata.CirDeserializers import org.jetbrains.kotlin.commonizer.metadata.CirDeserializers
import org.jetbrains.kotlin.commonizer.metadata.CirTypeResolver import org.jetbrains.kotlin.commonizer.metadata.CirTypeResolver
import org.jetbrains.kotlin.commonizer.tree.CirTreeClassConstructor
internal object CirTreeClassConstructorDeserializer { internal object CirTreeClassConstructorDeserializer {
operator fun invoke( operator fun invoke(
constructor: KmConstructor, containingClass: CirContainingClass, typeResolver: CirTypeResolver constructor: KmConstructor, containingClass: CirContainingClass, typeResolver: CirTypeResolver
): CirTreeClassConstructor { ): CirClassConstructor {
return CirTreeClassConstructor( return CirDeserializers.constructor(
approximationKey = ConstructorApproximationKey(constructor, typeResolver), source = constructor,
constructor = CirDeserializers.constructor( containingClass = containingClass,
source = constructor, typeResolver = typeResolver
containingClass = containingClass,
typeResolver = typeResolver
)
) )
} }
} }
@@ -8,16 +8,16 @@ package org.jetbrains.kotlin.commonizer.tree.deserializer
import kotlinx.metadata.KmFunction import kotlinx.metadata.KmFunction
import org.jetbrains.kotlin.commonizer.cir.CirClass import org.jetbrains.kotlin.commonizer.cir.CirClass
import org.jetbrains.kotlin.commonizer.cir.CirContainingClass import org.jetbrains.kotlin.commonizer.cir.CirContainingClass
import org.jetbrains.kotlin.commonizer.mergedtree.FunctionApproximationKey import org.jetbrains.kotlin.commonizer.cir.CirFunction
import org.jetbrains.kotlin.commonizer.cir.CirName
import org.jetbrains.kotlin.commonizer.metadata.CirDeserializers import org.jetbrains.kotlin.commonizer.metadata.CirDeserializers
import org.jetbrains.kotlin.commonizer.metadata.CirTypeResolver import org.jetbrains.kotlin.commonizer.metadata.CirTypeResolver
import org.jetbrains.kotlin.commonizer.tree.CirTreeFunction
import org.jetbrains.kotlin.commonizer.utils.isFakeOverride import org.jetbrains.kotlin.commonizer.utils.isFakeOverride
import org.jetbrains.kotlin.commonizer.utils.isKniBridgeFunction import org.jetbrains.kotlin.commonizer.utils.isKniBridgeFunction
import org.jetbrains.kotlin.commonizer.utils.isTopLevelDeprecatedFunction import org.jetbrains.kotlin.commonizer.utils.isTopLevelDeprecatedFunction
object CirTreeFunctionDeserializer { object CirTreeFunctionDeserializer {
operator fun invoke(function: KmFunction, containingClass: CirContainingClass?, typeResolver: CirTypeResolver): CirTreeFunction? { operator fun invoke(function: KmFunction, containingClass: CirContainingClass?, typeResolver: CirTypeResolver): CirFunction? {
val functionTypeResolver = typeResolver.create(function.typeParameters) val functionTypeResolver = typeResolver.create(function.typeParameters)
if (function.isFakeOverride() if (function.isFakeOverride()
|| function.isKniBridgeFunction() || function.isKniBridgeFunction()
@@ -26,15 +26,11 @@ object CirTreeFunctionDeserializer {
return null return null
} }
val approximationKey = FunctionApproximationKey(function, functionTypeResolver) return CirDeserializers.function(
return CirTreeFunction( name = CirName.create(function.name),
approximationKey = approximationKey, source = function,
function = CirDeserializers.function( containingClass = containingClass,
name = approximationKey.name, typeResolver = functionTypeResolver
source = function,
containingClass = containingClass,
typeResolver = functionTypeResolver
)
) )
} }
} }
@@ -7,25 +7,21 @@ package org.jetbrains.kotlin.commonizer.tree.deserializer
import kotlinx.metadata.KmProperty import kotlinx.metadata.KmProperty
import org.jetbrains.kotlin.commonizer.cir.CirContainingClass import org.jetbrains.kotlin.commonizer.cir.CirContainingClass
import org.jetbrains.kotlin.commonizer.mergedtree.PropertyApproximationKey import org.jetbrains.kotlin.commonizer.cir.CirName
import org.jetbrains.kotlin.commonizer.cir.CirProperty
import org.jetbrains.kotlin.commonizer.metadata.CirDeserializers import org.jetbrains.kotlin.commonizer.metadata.CirDeserializers
import org.jetbrains.kotlin.commonizer.metadata.CirTypeResolver import org.jetbrains.kotlin.commonizer.metadata.CirTypeResolver
import org.jetbrains.kotlin.commonizer.tree.CirTreeProperty
import org.jetbrains.kotlin.commonizer.utils.isFakeOverride import org.jetbrains.kotlin.commonizer.utils.isFakeOverride
object CirTreePropertyDeserializer { object CirTreePropertyDeserializer {
operator fun invoke(property: KmProperty, containingClass: CirContainingClass?, typeResolver: CirTypeResolver): CirTreeProperty? { operator fun invoke(property: KmProperty, containingClass: CirContainingClass?, typeResolver: CirTypeResolver): CirProperty? {
if (property.isFakeOverride()) return null if (property.isFakeOverride()) return null
val propertyTypeResolver = typeResolver.create(property.typeParameters) val propertyTypeResolver = typeResolver.create(property.typeParameters)
val approximationKey = PropertyApproximationKey(property, propertyTypeResolver) return CirDeserializers.property(
return CirTreeProperty( name = CirName.create(property.name),
approximationKey = PropertyApproximationKey(property, propertyTypeResolver), source = property,
property = CirDeserializers.property( containingClass = containingClass,
name = approximationKey.name, typeResolver = propertyTypeResolver
source = property,
containingClass = containingClass,
typeResolver = propertyTypeResolver
)
) )
} }
} }
@@ -6,13 +6,16 @@
package org.jetbrains.kotlin.commonizer.tree package org.jetbrains.kotlin.commonizer.tree
import org.jetbrains.kotlin.commonizer.TargetDependent import org.jetbrains.kotlin.commonizer.TargetDependent
import org.jetbrains.kotlin.commonizer.cir.CirRoot import org.jetbrains.kotlin.commonizer.cir.*
import org.jetbrains.kotlin.commonizer.mergedtree.* import org.jetbrains.kotlin.commonizer.mergedtree.*
import org.jetbrains.kotlin.storage.StorageManager import org.jetbrains.kotlin.storage.StorageManager
internal data class TargetBuildingContext( internal data class TargetBuildingContext(
val storageManager: StorageManager, val classifiers: CirKnownClassifiers, val targets: Int, val targetIndex: Int val storageManager: StorageManager, val classifiers: CirKnownClassifiers, val memberContext: CirMemberContext = CirMemberContext.empty,
) val targets: Int, val targetIndex: Int
) {
fun withMemberContextOf(clazz: CirClass) = copy(memberContext = memberContext.withContextOf(clazz))
}
internal fun mergeCirTree( internal fun mergeCirTree(
storageManager: StorageManager, classifiers: CirKnownClassifiers, roots: TargetDependent<CirTreeRoot> storageManager: StorageManager, classifiers: CirKnownClassifiers, roots: TargetDependent<CirTreeRoot>
@@ -20,7 +23,9 @@ internal fun mergeCirTree(
val node = buildRootNode(storageManager, roots.size) val node = buildRootNode(storageManager, roots.size)
roots.targets.withIndex().forEach { (targetIndex, target) -> roots.targets.withIndex().forEach { (targetIndex, target) ->
node.targetDeclarations[targetIndex] = CirRoot.create(target) node.targetDeclarations[targetIndex] = CirRoot.create(target)
node.buildModules(TargetBuildingContext(storageManager, classifiers, roots.size, targetIndex), roots[target].modules) node.buildModules(
TargetBuildingContext(storageManager, classifiers, CirMemberContext.empty, roots.size, targetIndex), roots[target].modules
)
} }
return node return node
} }
@@ -55,37 +60,38 @@ internal fun CirNodeWithMembers<*, *>.buildClass(
buildClassNode(context.storageManager, context.targets, context.classifiers, CirNodeRelationship.ParentNode(parent), treeClass.id) buildClassNode(context.storageManager, context.targets, context.classifiers, CirNodeRelationship.ParentNode(parent), treeClass.id)
} }
classNode.targetDeclarations[context.targetIndex] = treeClass.clazz classNode.targetDeclarations[context.targetIndex] = treeClass.clazz
treeClass.functions.forEach { function -> classNode.buildFunction(context, function, classNode) } val contextWithClass = context.withMemberContextOf(treeClass.clazz)
treeClass.properties.forEach { property -> classNode.buildProperty(context, property, classNode) } treeClass.functions.forEach { function -> classNode.buildFunction(contextWithClass, function, classNode) }
treeClass.constructors.forEach { constructor -> classNode.buildConstructor(context, constructor, classNode) } treeClass.properties.forEach { property -> classNode.buildProperty(contextWithClass, property, classNode) }
treeClass.classes.forEach { clazz -> classNode.buildClass(context, clazz, classNode) } treeClass.constructors.forEach { constructor -> classNode.buildConstructor(contextWithClass, constructor, classNode) }
treeClass.classes.forEach { clazz -> classNode.buildClass(contextWithClass, clazz, classNode) }
} }
internal fun CirNodeWithMembers<*, *>.buildFunction( internal fun CirNodeWithMembers<*, *>.buildFunction(
context: TargetBuildingContext, treeFunction: CirTreeFunction, parent: CirNode<*, *>? = null context: TargetBuildingContext, function: CirFunction, parent: CirNode<*, *>? = null
) { ) {
val functionNode = functions.getOrPut(treeFunction.approximationKey) { val functionNode = functions.getOrPut(FunctionApproximationKey.create(context.memberContext, function)) {
buildFunctionNode(context.storageManager, context.targets, context.classifiers, CirNodeRelationship.ParentNode(parent)) buildFunctionNode(context.storageManager, context.targets, context.classifiers, CirNodeRelationship.ParentNode(parent))
} }
functionNode.targetDeclarations[context.targetIndex] = treeFunction.function functionNode.targetDeclarations[context.targetIndex] = function
} }
internal fun CirNodeWithMembers<*, *>.buildProperty( internal fun CirNodeWithMembers<*, *>.buildProperty(
context: TargetBuildingContext, treeProperty: CirTreeProperty, parent: CirNode<*, *>? = null context: TargetBuildingContext, property: CirProperty, parent: CirNode<*, *>? = null
) { ) {
val propertyNode = properties.getOrPut(treeProperty.approximationKey) { val propertyNode = properties.getOrPut(PropertyApproximationKey.create(context.memberContext, property)) {
buildPropertyNode(context.storageManager, context.targets, context.classifiers, CirNodeRelationship.ParentNode(parent)) buildPropertyNode(context.storageManager, context.targets, context.classifiers, CirNodeRelationship.ParentNode(parent))
} }
propertyNode.targetDeclarations[context.targetIndex] = treeProperty.property propertyNode.targetDeclarations[context.targetIndex] = property
} }
internal fun CirClassNode.buildConstructor( internal fun CirClassNode.buildConstructor(
context: TargetBuildingContext, treeConstructor: CirTreeClassConstructor, parent: CirNode<*, *> context: TargetBuildingContext, constructor: CirClassConstructor, parent: CirNode<*, *>
) { ) {
val constructorNode = constructors.getOrPut(treeConstructor.approximationKey) { val constructorNode = constructors.getOrPut(ConstructorApproximationKey.create(context.memberContext, constructor)) {
buildClassConstructorNode(context.storageManager, context.targets, context.classifiers, CirNodeRelationship.ParentNode(parent)) buildClassConstructorNode(context.storageManager, context.targets, context.classifiers, CirNodeRelationship.ParentNode(parent))
} }
constructorNode.targetDeclarations[context.targetIndex] = treeConstructor.constructor constructorNode.targetDeclarations[context.targetIndex] = constructor
} }
internal fun CirPackageNode.buildTypeAlias(context: TargetBuildingContext, treeTypeAlias: CirTreeTypeAlias) { internal fun CirPackageNode.buildTypeAlias(context: TargetBuildingContext, treeTypeAlias: CirTreeTypeAlias) {
@@ -25,8 +25,13 @@ class CommonizedGroup<T : Any>(
operator fun set(index: Int, value: T) { operator fun set(index: Int, value: T) {
val oldValue = this[index] val oldValue = this[index]
check(oldValue == null) { "$oldValue can not be overwritten with $value at index $index" } check(oldValue == null) {
"$oldValue can not be overwritten with $value at index $index"
}
elements[index] = value elements[index] = value
} }
} }
interface I<T>
@@ -6,7 +6,6 @@
package org.jetbrains.kotlin.commonizer.utils package org.jetbrains.kotlin.commonizer.utils
import kotlinx.metadata.ClassName import kotlinx.metadata.ClassName
import kotlinx.metadata.KmAnnotation
import org.jetbrains.kotlin.builtins.StandardNames import org.jetbrains.kotlin.builtins.StandardNames
import org.jetbrains.kotlin.commonizer.cir.CirEntityId import org.jetbrains.kotlin.commonizer.cir.CirEntityId
import org.jetbrains.kotlin.commonizer.cir.CirName import org.jetbrains.kotlin.commonizer.cir.CirName
@@ -52,9 +51,8 @@ private val OBJC_INTEROP_CALLABLE_ANNOTATIONS: List<CirName> = listOf(
CirName.create("ObjCFactory") CirName.create("ObjCFactory")
) )
private val OBJC_INTEROP_CALLABLE_ANNOTATION_FULL_NAMES: List<ClassName> = OBJC_INTEROP_CALLABLE_ANNOTATIONS.map { name -> internal val COMMONIZER_OBJC_INTEROP_CALLABLE_ANNOTATION_ID =
CirEntityId.create(CINTEROP_PACKAGE, name).toString() CirEntityId.create(CirPackageName.create("kotlin.commonizer"), CirName.create("ObjCCallable"))
}
internal val DEFAULT_CONSTRUCTOR_NAME: CirName = CirName.create("<init>") internal val DEFAULT_CONSTRUCTOR_NAME: CirName = CirName.create("<init>")
internal val DEFAULT_SETTER_VALUE_NAME: CirName = CirName.create("value") internal val DEFAULT_SETTER_VALUE_NAME: CirName = CirName.create("value")
@@ -69,7 +67,7 @@ internal val CirPackageName.isUnderKotlinNativeSyntheticPackages: Boolean
get() = KOTLIN_NATIVE_SYNTHETIC_PACKAGES.any(::startsWith) get() = KOTLIN_NATIVE_SYNTHETIC_PACKAGES.any(::startsWith)
internal val CirEntityId.isObjCInteropCallableAnnotation: Boolean internal val CirEntityId.isObjCInteropCallableAnnotation: Boolean
get() = packageName == CINTEROP_PACKAGE && relativeNameSegments.singleOrNull() in OBJC_INTEROP_CALLABLE_ANNOTATIONS get() = this == COMMONIZER_OBJC_INTEROP_CALLABLE_ANNOTATION_ID ||
packageName == CINTEROP_PACKAGE && relativeNameSegments.singleOrNull() in OBJC_INTEROP_CALLABLE_ANNOTATIONS
internal val KmAnnotation.isObjCInteropCallableAnnotation: Boolean
get() = className in OBJC_INTEROP_CALLABLE_ANNOTATION_FULL_NAMES
@@ -85,29 +85,41 @@ expect fun functionMismatchedParameterNames29(vararg variadicArguments: Int)
expect fun functionMismatchedParameterNames30(arg0: Int, vararg variadicArguments: Int) expect fun functionMismatchedParameterNames30(arg0: Int, vararg variadicArguments: Int)
expect fun functionMismatchedParameterNames31(i: Int, s: String) expect fun functionMismatchedParameterNames31(i: Int, s: String)
@kotlin.commonizer.ObjCCallable
expect fun functionMismatchedParameterNames34(i: Int, s: String) expect fun functionMismatchedParameterNames34(i: Int, s: String)
@kotlin.commonizer.ObjCCallable
expect fun functionMismatchedParameterNames37(arg0: Int, arg1: String) expect fun functionMismatchedParameterNames37(arg0: Int, arg1: String)
// hasStableParameterNames=false // hasStableParameterNames=false
@kotlin.commonizer.ObjCCallable
expect fun functionMismatchedParameterNames38(i: Int, s: String) expect fun functionMismatchedParameterNames38(i: Int, s: String)
// hasStableParameterNames=false // hasStableParameterNames=false
@kotlin.commonizer.ObjCCallable
expect fun functionMismatchedParameterNames39(i: Int, s: String) expect fun functionMismatchedParameterNames39(i: Int, s: String)
// hasStableParameterNames=false // hasStableParameterNames=false
@kotlin.commonizer.ObjCCallable
expect fun functionMismatchedParameterNames40(i: Int, s: String) expect fun functionMismatchedParameterNames40(i: Int, s: String)
// hasStableParameterNames=false // hasStableParameterNames=false
@kotlin.commonizer.ObjCCallable
expect fun functionMismatchedParameterNames41(arg0: Int, arg1: String) expect fun functionMismatchedParameterNames41(arg0: Int, arg1: String)
// hasStableParameterNames=false // hasStableParameterNames=false
@kotlin.commonizer.ObjCCallable
expect fun functionMismatchedParameterNames42(arg0: Int, arg1: String) expect fun functionMismatchedParameterNames42(arg0: Int, arg1: String)
// hasStableParameterNames=false // hasStableParameterNames=false
@kotlin.commonizer.ObjCCallable
expect fun functionMismatchedParameterNames43(arg0: Int, arg1: String) expect fun functionMismatchedParameterNames43(arg0: Int, arg1: String)
@kotlin.commonizer.ObjCCallable
expect fun overloadedFunctionByParameterNames(i: Int, s: String) expect fun overloadedFunctionByParameterNames(i: Int, s: String)
@kotlin.commonizer.ObjCCallable
expect fun overloadedFunctionByParameterNames(xi: Int, xs: String) expect fun overloadedFunctionByParameterNames(xi: Int, xs: String)
expect inline fun inlineFunction1(lazyMessage: () -> String) expect inline fun inlineFunction1(lazyMessage: () -> String)
@@ -0,0 +1,5 @@
package kotlin.commonizer
@Target(AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY_GETTER, AnnotationTarget.PROPERTY_SETTER)
@Retention(AnnotationRetention.BINARY)
annotation class ObjCCallable()
@@ -4,3 +4,4 @@ package kotlinx.cinterop
@Target(AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY_GETTER, AnnotationTarget.PROPERTY_SETTER) @Target(AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY_GETTER, AnnotationTarget.PROPERTY_SETTER)
@Retention(AnnotationRetention.BINARY) @Retention(AnnotationRetention.BINARY)
annotation class ObjCMethod() // fake annotation class without properties annotation class ObjCMethod() // fake annotation class without properties
@@ -5,6 +5,8 @@
package org.jetbrains.kotlin.commonizer.tree.deserializer package org.jetbrains.kotlin.commonizer.tree.deserializer
import org.jetbrains.kotlin.commonizer.cir.CirFunction
import org.jetbrains.kotlin.commonizer.cir.CirProperty
import org.jetbrains.kotlin.commonizer.tree.* import org.jetbrains.kotlin.commonizer.tree.*
import org.jetbrains.kotlin.commonizer.utils.KtInlineSourceCommonizerTestCase import org.jetbrains.kotlin.commonizer.utils.KtInlineSourceCommonizerTestCase
@@ -14,14 +16,14 @@ abstract class AbstractCirTreeDeserializerTest : KtInlineSourceCommonizerTestCas
?: kotlin.test.fail("Expected single package. Found ${packages.map { it.pkg.packageName }}") ?: kotlin.test.fail("Expected single package. Found ${packages.map { it.pkg.packageName }}")
} }
protected fun CirTreeModule.assertSingleProperty(): CirTreeProperty { protected fun CirTreeModule.assertSingleProperty(): CirProperty {
return assertSinglePackage().properties.singleOrNull() return assertSinglePackage().properties.singleOrNull()
?: kotlin.test.fail("Expected single property. Found ${assertSinglePackage().properties.map { it.property.name }}") ?: kotlin.test.fail("Expected single property. Found ${assertSinglePackage().properties.map { it.name }}")
} }
protected fun CirTreeModule.assertSingleFunction(): CirTreeFunction { protected fun CirTreeModule.assertSingleFunction(): CirFunction {
return assertSinglePackage().functions.singleOrNull() return assertSinglePackage().functions.singleOrNull()
?: kotlin.test.fail("Expected single property. Found ${assertSinglePackage().functions.map { it.function.name }}") ?: kotlin.test.fail("Expected single property. Found ${assertSinglePackage().functions.map { it.name }}")
} }
protected fun CirTreeModule.assertSingleClass(): CirTreeClass { protected fun CirTreeModule.assertSingleClass(): CirTreeClass {
@@ -150,12 +150,12 @@ class CirTreeClassDeserializerTest : AbstractCirTreeDeserializerTest() {
val clazz = module.assertSingleClass() val clazz = module.assertSingleClass()
fun assertContainsProperty(name: String) { fun assertContainsProperty(name: String) {
clazz.properties.singleOrNull { it.property.name.toStrippedString() == name } clazz.properties.singleOrNull { it.name.toStrippedString() == name }
?: kotlin.test.fail("Missing property '$name'") ?: kotlin.test.fail("Missing property '$name'")
} }
fun assertContainsFunction(name: String) { fun assertContainsFunction(name: String) {
clazz.functions.singleOrNull { it.function.name.toStrippedString() == name } clazz.functions.singleOrNull { it.name.toStrippedString() == name }
?: kotlin.test.fail("Missing function '$name'") ?: kotlin.test.fail("Missing function '$name'")
} }
@@ -17,7 +17,7 @@ class CirTreeFunctionDeserializerTest : AbstractCirTreeDeserializerTest() {
fun `test simple function`() { fun `test simple function`() {
val module = createCirTreeFromSourceCode("fun x() = Unit") val module = createCirTreeFromSourceCode("fun x() = Unit")
val (_, function) = module.assertSingleFunction() val function = module.assertSingleFunction()
assertNull(function.containingClass, "Expected function to *not* have containing class") assertNull(function.containingClass, "Expected function to *not* have containing class")
assertEquals(Visibilities.Public, function.visibility, "Expected function to be public") assertEquals(Visibilities.Public, function.visibility, "Expected function to be public")
@@ -30,7 +30,7 @@ class CirTreeFunctionDeserializerTest : AbstractCirTreeDeserializerTest() {
fun `test generic function`() { fun `test generic function`() {
val module = createCirTreeFromSourceCode("""fun <T: Any> T.isHappy(): Boolean = true""") val module = createCirTreeFromSourceCode("""fun <T: Any> T.isHappy(): Boolean = true""")
val (_, function) = module.assertSingleFunction() val function = module.assertSingleFunction()
val extensionReceiver = assertNotNull(function.extensionReceiver, "Expected function being extension receiver") val extensionReceiver = assertNotNull(function.extensionReceiver, "Expected function being extension receiver")
val extensionReceiverType = extensionReceiver.type as? CirTypeParameterType val extensionReceiverType = extensionReceiver.type as? CirTypeParameterType
@@ -59,8 +59,8 @@ class CirTreeFunctionDeserializerTest : AbstractCirTreeDeserializerTest() {
) )
val parent = module.assertSingleClass() val parent = module.assertSingleClass()
val function = parent.functions.singleOrNull()?.function val function = parent.functions.singleOrNull()
?: kotlin.test.fail("Expected single function in parent. Found ${parent.functions.map { it.function.name }}") ?: kotlin.test.fail("Expected single function in parent. Found ${parent.functions.map { it.name }}")
val containingClass = assertIs<CirClass>(kotlin.test.assertNotNull(function.containingClass)) val containingClass = assertIs<CirClass>(kotlin.test.assertNotNull(function.containingClass))
assertEquals(ClassKind.OBJECT, containingClass.kind, "Expected containing class being object") assertEquals(ClassKind.OBJECT, containingClass.kind, "Expected containing class being object")
@@ -58,12 +58,12 @@ class CirTreePackageDeserializerTest : AbstractCirTreeDeserializerTest() {
) )
kotlin.test.assertTrue( kotlin.test.assertTrue(
properties.any { it.property.name.toStrippedString() == "rootProperty" }, properties.any { it.name.toStrippedString() == "rootProperty" },
"Expected 'rootProperty'" "Expected 'rootProperty'"
) )
kotlin.test.assertTrue( kotlin.test.assertTrue(
functions.any { it.function.name.toStrippedString() == "rootFunction" }, functions.any { it.name.toStrippedString() == "rootFunction" },
"Expected 'rootFunction'" "Expected 'rootFunction'"
) )
@@ -80,12 +80,12 @@ class CirTreePackageDeserializerTest : AbstractCirTreeDeserializerTest() {
) )
kotlin.test.assertTrue( kotlin.test.assertTrue(
properties.any { it.property.name.toStrippedString() == "pkg1Property" }, properties.any { it.name.toStrippedString() == "pkg1Property" },
"Expected 'pkg1Property'" "Expected 'pkg1Property'"
) )
kotlin.test.assertTrue( kotlin.test.assertTrue(
functions.any { it.function.name.toStrippedString() == "pkg1Function" }, functions.any { it.name.toStrippedString() == "pkg1Function" },
"Expected 'pkg1Function'" "Expected 'pkg1Function'"
) )
@@ -102,12 +102,12 @@ class CirTreePackageDeserializerTest : AbstractCirTreeDeserializerTest() {
) )
kotlin.test.assertTrue( kotlin.test.assertTrue(
properties.any { it.property.name.toStrippedString() == "pkg2Property" }, properties.any { it.name.toStrippedString() == "pkg2Property" },
"Expected 'pkg2Property'" "Expected 'pkg2Property'"
) )
kotlin.test.assertTrue( kotlin.test.assertTrue(
functions.any { it.function.name.toStrippedString() == "pkg2Function" }, functions.any { it.name.toStrippedString() == "pkg2Function" },
"Expected 'pkg2Function'" "Expected 'pkg2Function'"
) )
@@ -18,8 +18,7 @@ class CirTreePropertyDeserializerTest : AbstractCirTreeDeserializerTest() {
fun `test simple val property`() { fun `test simple val property`() {
val module = createCirTreeFromSourceCode("val x: Int = 42") val module = createCirTreeFromSourceCode("val x: Int = 42")
val (key, property) = module.assertSingleProperty() val property = module.assertSingleProperty()
assertEquals(PropertyApproximationKey(CirName.Companion.create("x"), null), key)
assertEquals("x", property.name.toStrippedString()) assertEquals("x", property.name.toStrippedString())
assertFalse(property.isConst, "Expected property to is *no* const") assertFalse(property.isConst, "Expected property to is *no* const")
@@ -33,7 +32,7 @@ class CirTreePropertyDeserializerTest : AbstractCirTreeDeserializerTest() {
fun `test simple var property`() { fun `test simple var property`() {
val module = createCirTreeFromSourceCode("var x: Int = 42") val module = createCirTreeFromSourceCode("var x: Int = 42")
val (_, property) = module.assertSingleProperty() val property = module.assertSingleProperty()
assertNotNull(property.getter, "Expected property has getter") assertNotNull(property.getter, "Expected property has getter")
assertNotNull(property.setter, "Expected property has setter") assertNotNull(property.setter, "Expected property has setter")
assertFalse(property.isLateInit, "Expected property to be not lateinit") assertFalse(property.isLateInit, "Expected property to be not lateinit")
@@ -42,7 +41,7 @@ class CirTreePropertyDeserializerTest : AbstractCirTreeDeserializerTest() {
fun `test lateinit var property`() { fun `test lateinit var property`() {
val module = createCirTreeFromSourceCode("lateinit var x: Int") val module = createCirTreeFromSourceCode("lateinit var x: Int")
val (_, property) = module.assertSingleProperty() val property = module.assertSingleProperty()
assertNotNull(property.getter, "Expected property has getter") assertNotNull(property.getter, "Expected property has getter")
assertNotNull(property.setter, "Expected property has setter") assertNotNull(property.setter, "Expected property has setter")
@@ -52,7 +51,7 @@ class CirTreePropertyDeserializerTest : AbstractCirTreeDeserializerTest() {
fun `test generic var property`() { fun `test generic var property`() {
val module = createCirTreeFromSourceCode("var <T> T.x: T get() = this") val module = createCirTreeFromSourceCode("var <T> T.x: T get() = this")
val (_, property) = module.assertSingleProperty() val property = module.assertSingleProperty()
assertNotNull(property.extensionReceiver, "Expected property has extension receiver") assertNotNull(property.extensionReceiver, "Expected property has extension receiver")
assertTrue( assertTrue(
@@ -74,8 +73,8 @@ class CirTreePropertyDeserializerTest : AbstractCirTreeDeserializerTest() {
val pkg = module.assertSinglePackage() val pkg = module.assertSinglePackage()
assertEquals(4, pkg.properties.size, "Expected exactly 4 properties in package") assertEquals(4, pkg.properties.size, "Expected exactly 4 properties in package")
val answerProperty = pkg.properties.single { it.property.name.toStrippedString() == "answer" } val answerProperty = pkg.properties.single { it.name.toStrippedString() == "answer" }
val answerReturnType = answerProperty.property.returnType as? CirClassType val answerReturnType = answerProperty.returnType as? CirClassType
?: kotlin.test.fail("Expected answer return type is class") ?: kotlin.test.fail("Expected answer return type is class")
assertEquals("kotlin/Int", answerReturnType.classifierId.toString()) assertEquals("kotlin/Int", answerReturnType.classifierId.toString())
assertTrue(answerReturnType.isMarkedNullable, "Expected answer return type being marked nullable") assertTrue(answerReturnType.isMarkedNullable, "Expected answer return type being marked nullable")