[IR] Support of @OptionalExpectation in IrActualizer

^KT-56579 Fixed
This commit is contained in:
Ivan Kochurkin
2023-02-16 22:59:45 +01:00
committed by Space Team
parent c10bd1e3f0
commit 5b2a1feaf0
3 changed files with 27 additions and 6 deletions
@@ -112,7 +112,7 @@ private class ClassifiersLinkCollector(
val actualClassifier = actualClassifiers[actualTypeId] val actualClassifier = actualClassifiers[actualTypeId]
if (actualClassifier != null) { if (actualClassifier != null) {
expectActualMap[expectElement.symbol] = actualClassifier expectActualMap[expectElement.symbol] = actualClassifier
} else { } else if (!expectElement.containsOptionalExpectation()) {
reportMissingActual(expectElement) reportMissingActual(expectElement)
} }
} }
@@ -181,7 +181,7 @@ private class CallablesLinkCollector(
declaration.getter?.symbol?.let { expectActualMap[it] = actualProperty.getter!!.symbol } declaration.getter?.symbol?.let { expectActualMap[it] = actualProperty.getter!!.symbol }
declaration.setter?.symbol?.let { expectActualMap[it] = actualProperty.setter!!.symbol } declaration.setter?.symbol?.let { expectActualMap[it] = actualProperty.setter!!.symbol }
} }
} else { } else if (!declaration.parent.containsOptionalExpectation()) {
reportMissingActual(declaration) reportMissingActual(declaration)
} }
} }
@@ -14,20 +14,29 @@ object IrActualizer {
fun actualize(mainFragment: IrModuleFragment, dependentFragments: List<IrModuleFragment>) { fun actualize(mainFragment: IrModuleFragment, dependentFragments: List<IrModuleFragment>) {
val (expectActualMap, typeAliasMap) = ExpectActualCollector(mainFragment, dependentFragments).collect() val (expectActualMap, typeAliasMap) = ExpectActualCollector(mainFragment, dependentFragments).collect()
FunctionDefaultParametersActualizer(expectActualMap).actualize() FunctionDefaultParametersActualizer(expectActualMap).actualize()
removeExpectDeclarations(dependentFragments) removeExpectDeclarations(dependentFragments, expectActualMap)
addMissingFakeOverrides(expectActualMap, dependentFragments, typeAliasMap) addMissingFakeOverrides(expectActualMap, dependentFragments, typeAliasMap)
linkExpectToActual(expectActualMap, dependentFragments) linkExpectToActual(expectActualMap, dependentFragments)
mergeIrFragments(mainFragment, dependentFragments) mergeIrFragments(mainFragment, dependentFragments)
} }
private fun removeExpectDeclarations(dependentFragments: List<IrModuleFragment>) { private fun removeExpectDeclarations(dependentFragments: List<IrModuleFragment>, expectActualMap: Map<IrSymbol, IrSymbol>) {
for (fragment in dependentFragments) { for (fragment in dependentFragments) {
for (file in fragment.files) { for (file in fragment.files) {
file.declarations.removeAll { it.isProperExpect } file.declarations.removeIf { shouldRemoveExpectDeclaration(it, expectActualMap) }
} }
} }
} }
private fun shouldRemoveExpectDeclaration(irDeclaration: IrDeclaration, expectActualMap: Map<IrSymbol, IrSymbol>): Boolean {
return when (irDeclaration) {
is IrClass -> irDeclaration.isExpect && (!irDeclaration.containsOptionalExpectation() || expectActualMap.containsKey(irDeclaration.symbol))
is IrProperty -> irDeclaration.isExpect
is IrFunction -> irDeclaration.isExpect
else -> false
}
}
private fun addMissingFakeOverrides( private fun addMissingFakeOverrides(
expectActualMap: Map<IrSymbol, IrSymbol>, expectActualMap: Map<IrSymbol, IrSymbol>,
dependentFragments: List<IrModuleFragment>, dependentFragments: List<IrModuleFragment>,
@@ -5,14 +5,20 @@
package org.jetbrains.kotlin.backend.common.actualizer package org.jetbrains.kotlin.backend.common.actualizer
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrDeclarationBase
import org.jetbrains.kotlin.ir.declarations.IrDeclarationWithName
import org.jetbrains.kotlin.ir.declarations.IrFunction
import org.jetbrains.kotlin.ir.symbols.IrSymbol import org.jetbrains.kotlin.ir.symbols.IrSymbol
import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.classifierOrFail import org.jetbrains.kotlin.ir.types.classifierOrFail
import org.jetbrains.kotlin.ir.util.hasAnnotation
import org.jetbrains.kotlin.ir.util.kotlinFqName import org.jetbrains.kotlin.ir.util.kotlinFqName
import org.jetbrains.kotlin.ir.util.render import org.jetbrains.kotlin.ir.util.render
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.resolve.multiplatform.OptionalAnnotationUtil
fun generateIrElementFullName( fun generateIrElementFullName(
declaration: IrElement, declaration: IrElement,
@@ -73,4 +79,10 @@ fun reportMissingActual(irElement: IrElement) {
fun reportManyInterfacesMembersNotImplemented(declaration: IrClass, actualMember: IrDeclarationWithName) { fun reportManyInterfacesMembersNotImplemented(declaration: IrClass, actualMember: IrDeclarationWithName) {
// TODO: setup diagnostics reporting // TODO: setup diagnostics reporting
throw AssertionError("${declaration.name} must override ${actualMember.name} because it inherits multiple interface methods of it") throw AssertionError("${declaration.name} must override ${actualMember.name} because it inherits multiple interface methods of it")
}
internal fun IrElement.containsOptionalExpectation(): Boolean {
return this is IrClass &&
this.kind == ClassKind.ANNOTATION_CLASS &&
this.hasAnnotation(OptionalAnnotationUtil.OPTIONAL_EXPECTATION_FQ_NAME)
} }