[FE] Implement FE logic of expect actual annotations matching

This implementation only checks annotations set on expect/actual
declarations and requires further refinement (e.g. checking of other
annotation targets, class scopes within typealiases).

^KT-58551
This commit is contained in:
Roman Efremov
2023-06-22 15:22:17 +02:00
committed by Space Team
parent b1bdb619d8
commit 1a4ab9bb4b
49 changed files with 1481 additions and 25 deletions
@@ -6,6 +6,7 @@
package org.jetbrains.kotlin.resolve.multiplatform
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.mpp.*
import org.jetbrains.kotlin.name.CallableId
@@ -14,9 +15,8 @@ import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.calls.components.ClassicTypeSystemContextForCS
import org.jetbrains.kotlin.resolve.calls.mpp.ExpectActualMatchingContext
import org.jetbrains.kotlin.resolve.descriptorUtil.classId
import org.jetbrains.kotlin.resolve.descriptorUtil.getKotlinTypeRefiner
import org.jetbrains.kotlin.resolve.descriptorUtil.isTypeRefinementEnabled
import org.jetbrains.kotlin.resolve.calls.mpp.ExpectActualMatchingContext.AnnotationCallInfo
import org.jetbrains.kotlin.resolve.descriptorUtil.*
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
import org.jetbrains.kotlin.resolve.scopes.MemberScope
import org.jetbrains.kotlin.resolve.scopes.getDescriptorsFiltered
@@ -35,6 +35,7 @@ class ClassicExpectActualMatchingContext(val platformModule: ModuleDescriptor) :
override val shouldCheckReturnTypesOfCallables: Boolean
get() = true
private fun DeclarationSymbolMarker.asDescriptor(): DeclarationDescriptor = this as DeclarationDescriptor
private fun CallableSymbolMarker.asDescriptor(): CallableDescriptor = this as CallableDescriptor
private fun FunctionSymbolMarker.asDescriptor(): FunctionDescriptor = this as FunctionDescriptor
private fun PropertySymbolMarker.asDescriptor(): PropertyDescriptor = this as PropertyDescriptor
@@ -328,4 +329,21 @@ class ClassicExpectActualMatchingContext(val platformModule: ModuleDescriptor) :
override val CallableSymbolMarker.hasStableParameterNames: Boolean
get() = asDescriptor().hasStableParameterNames()
override val DeclarationSymbolMarker.annotations: List<AnnotationCallInfo>
get() = asDescriptor().annotations.map(::AnnotationCallInfoImpl)
override fun areAnnotationArgumentsEqual(annotation1: AnnotationCallInfo, annotation2: AnnotationCallInfo): Boolean {
fun AnnotationCallInfo.getDescriptor(): AnnotationDescriptor = (this as AnnotationCallInfoImpl).annotationDescriptor
return areExpressionConstValuesEqual(annotation1.getDescriptor(), annotation2.getDescriptor())
}
private class AnnotationCallInfoImpl(
val annotationDescriptor: AnnotationDescriptor,
) : AnnotationCallInfo {
override val classId: ClassId?
get() = annotationDescriptor.annotationClass?.classId
}
}
@@ -0,0 +1,33 @@
/*
* Copyright 2010-2023 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.resolve.multiplatform
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
import org.jetbrains.kotlin.resolve.calls.mpp.ExpectActualMatchingContext
import org.jetbrains.kotlin.resolve.constants.ConstantValue
internal fun ExpectActualMatchingContext<*>.areExpressionConstValuesEqual(a: Any?, b: Any?): Boolean {
return when {
a is AnnotationDescriptor && b is AnnotationDescriptor -> {
val aArgs = a.allValueArguments
val bArgs = b.allValueArguments
a.fqName == b.fqName &&
aArgs.size == bArgs.size &&
areCompatibleExpectActualTypes(a.type, b.type) &&
aArgs.keys.all { k -> areExpressionConstValuesEqual(aArgs[k], bArgs[k]) }
}
a is ConstantValue<*> && b is ConstantValue<*> -> {
areExpressionConstValuesEqual(a.value, b.value)
}
a is Collection<*> && b is Collection<*> -> {
a.size == b.size && a.zip(b).all { (f, s) -> areExpressionConstValuesEqual(f, s) }
}
a is Array<*> && b is Array<*> -> {
a.size == b.size && a.zip(b).all { (f, s) -> areExpressionConstValuesEqual(f, s) }
}
else -> a == b
}
}