[K2, MPP] implement IR errors reporting and test infrastructure

Fix test data

^KT-56344 Fixed
This commit is contained in:
Ilya Chernikov
2023-02-09 12:34:30 +01:00
committed by Space Team
parent 3b1071b42b
commit 59b88f33b2
48 changed files with 2583 additions and 2146 deletions
@@ -0,0 +1,31 @@
/*
* 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.backend.common
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.diagnostics.KtDiagnosticFactoryToRendererMap
import org.jetbrains.kotlin.diagnostics.error1
import org.jetbrains.kotlin.diagnostics.rendering.BaseDiagnosticRendererFactory
import org.jetbrains.kotlin.diagnostics.rendering.CommonRenderers.STRING
import org.jetbrains.kotlin.diagnostics.rendering.Renderers.MODULE_WITH_PLATFORM
import org.jetbrains.kotlin.diagnostics.rendering.RootDiagnosticRendererFactory
object CommonBackendErrors {
val NO_ACTUAL_FOR_EXPECT by error1<PsiElement, ModuleDescriptor>()
val MANY_INTERFACES_MEMBER_NOT_IMPLEMENTED by error1<PsiElement, String>()
init {
RootDiagnosticRendererFactory.registerFactory(KtDefaultCommonBackendErrorMessages)
}
}
object KtDefaultCommonBackendErrorMessages : BaseDiagnosticRendererFactory() {
override val MAP = KtDiagnosticFactoryToRendererMap("KT").also { map ->
map.put(CommonBackendErrors.NO_ACTUAL_FOR_EXPECT, "Expected {0} has no actual declaration in module {1}", MODULE_WITH_PLATFORM)
map.put(CommonBackendErrors.MANY_INTERFACES_MEMBER_NOT_IMPLEMENTED, "{0} must override {1} because it inherits multiple interface methods of it", STRING)
}
}
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.backend.common.actualizer
import org.jetbrains.kotlin.KtDiagnosticReporterWithImplicitIrBasedContext
import org.jetbrains.kotlin.backend.common.ir.isExpect
import org.jetbrains.kotlin.backend.common.ir.isProperExpect
import org.jetbrains.kotlin.ir.IrElement
@@ -18,7 +19,11 @@ import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
import org.jetbrains.kotlin.name.FqName
internal class ExpectActualCollector(private val mainFragment: IrModuleFragment, private val dependentFragments: List<IrModuleFragment>) {
internal class ExpectActualCollector(
private val mainFragment: IrModuleFragment,
private val dependentFragments: List<IrModuleFragment>,
private val diagnosticsReporter: KtDiagnosticReporterWithImplicitIrBasedContext
) {
fun collect(): Pair<Map<IrSymbol, IrSymbol>, Map<FqName, FqName>> {
val result = mutableMapOf<IrSymbol, IrSymbol>()
// Collect and link classifiers at first to make it possible to expand type aliases on the callables linking
@@ -38,7 +43,7 @@ internal class ExpectActualCollector(private val mainFragment: IrModuleFragment,
ActualClassifiersCollector(actualClassifiers, allActualDeclarations, typeAliasMap).visitModuleFragment(fragment, false)
}
val linkCollector = ClassifiersLinkCollector(this, actualClassifiers)
val linkCollector = ClassifiersLinkCollector(this, actualClassifiers, diagnosticsReporter)
dependentFragments.forEach { linkCollector.visitModuleFragment(it) }
return allActualDeclarations to typeAliasMap
@@ -51,7 +56,7 @@ internal class ExpectActualCollector(private val mainFragment: IrModuleFragment,
val actualMembers = mutableMapOf<String, IrDeclarationBase>()
collectActualCallables(this, actualMembers, allActualDeclarations)
val collector = CallablesLinkCollector(this, actualMembers, typeAliasMap)
val collector = CallablesLinkCollector(this, actualMembers, typeAliasMap, diagnosticsReporter)
dependentFragments.forEach { collector.visitModuleFragment(it) }
}
}
@@ -106,14 +111,15 @@ private class ActualClassifiersCollector(
private class ClassifiersLinkCollector(
private val expectActualMap: MutableMap<IrSymbol, IrSymbol>,
private val actualClassifiers: Map<FqName, IrSymbol>
private val actualClassifiers: Map<FqName, IrSymbol>,
private val diagnosticsReporter: KtDiagnosticReporterWithImplicitIrBasedContext
) : IrElementVisitorVoid {
private fun addLinkOrReportMissing(expectElement: IrSymbolOwner, actualTypeId: FqName) {
private fun addLinkOrReportMissing(expectElement: IrDeclaration, actualTypeId: FqName) {
val actualClassifier = actualClassifiers[actualTypeId]
if (actualClassifier != null) {
expectActualMap[expectElement.symbol] = actualClassifier
} else if (!expectElement.containsOptionalExpectation()) {
reportMissingActual(expectElement)
diagnosticsReporter.reportMissingActual(expectElement)
}
}
@@ -165,7 +171,8 @@ private fun collectActualCallables(
private class CallablesLinkCollector(
private val expectActualMap: MutableMap<IrSymbol, IrSymbol>,
private val actualMembers: Map<String, IrDeclarationBase>,
private val typeAliasMap: Map<FqName, FqName>
private val typeAliasMap: Map<FqName, FqName>,
private val diagnosticsReporter: KtDiagnosticReporterWithImplicitIrBasedContext
) : IrElementVisitorVoid {
override fun visitFunction(declaration: IrFunction) = addLink(declaration)
@@ -182,7 +189,7 @@ private class CallablesLinkCollector(
declaration.setter?.symbol?.let { expectActualMap[it] = actualProperty.setter!!.symbol }
}
} else if (!declaration.parent.containsOptionalExpectation()) {
reportMissingActual(declaration)
diagnosticsReporter.reportMissingActual(declaration)
}
}
@@ -5,17 +5,25 @@
package org.jetbrains.kotlin.backend.common.actualizer
import org.jetbrains.kotlin.backend.common.ir.isProperExpect
import org.jetbrains.kotlin.KtDiagnosticReporterWithImplicitIrBasedContext
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.symbols.IrSymbol
import org.jetbrains.kotlin.name.FqName
object IrActualizer {
fun actualize(mainFragment: IrModuleFragment, dependentFragments: List<IrModuleFragment>) {
val (expectActualMap, typeAliasMap) = ExpectActualCollector(mainFragment, dependentFragments).collect()
fun actualize(
mainFragment: IrModuleFragment,
dependentFragments: List<IrModuleFragment>,
diagnosticReporter: DiagnosticReporter,
languageVersionSettings: LanguageVersionSettings
) {
val ktDiagnosticReporter = KtDiagnosticReporterWithImplicitIrBasedContext(diagnosticReporter, languageVersionSettings)
val (expectActualMap, typeAliasMap) = ExpectActualCollector(mainFragment, dependentFragments, ktDiagnosticReporter).collect()
FunctionDefaultParametersActualizer(expectActualMap).actualize()
removeExpectDeclarations(dependentFragments, expectActualMap)
addMissingFakeOverrides(expectActualMap, dependentFragments, typeAliasMap)
addMissingFakeOverrides(expectActualMap, dependentFragments, typeAliasMap, ktDiagnosticReporter)
linkExpectToActual(expectActualMap, dependentFragments)
mergeIrFragments(mainFragment, dependentFragments)
}
@@ -40,9 +48,10 @@ object IrActualizer {
private fun addMissingFakeOverrides(
expectActualMap: Map<IrSymbol, IrSymbol>,
dependentFragments: List<IrModuleFragment>,
typeAliasMap: Map<FqName, FqName>
typeAliasMap: Map<FqName, FqName>,
diagnosticsReporter: KtDiagnosticReporterWithImplicitIrBasedContext
) {
MissingFakeOverridesAdder(expectActualMap, typeAliasMap).apply { dependentFragments.forEach { visitModuleFragment(it) } }
MissingFakeOverridesAdder(expectActualMap, typeAliasMap, diagnosticsReporter).apply { dependentFragments.forEach { visitModuleFragment(it) } }
}
private fun linkExpectToActual(expectActualMap: Map<IrSymbol, IrSymbol>, dependentFragments: List<IrModuleFragment>) {
@@ -5,18 +5,18 @@
package org.jetbrains.kotlin.backend.common.actualizer
import org.jetbrains.kotlin.KtDiagnosticReporterWithImplicitIrBasedContext
import org.jetbrains.kotlin.backend.common.CommonBackendErrors
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.ir.IrElement
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.ObsoleteDescriptorBasedAPI
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.symbols.IrSymbol
import org.jetbrains.kotlin.ir.types.IrType
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.render
import org.jetbrains.kotlin.ir.util.module
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.resolve.multiplatform.OptionalAnnotationUtil
@@ -71,14 +71,13 @@ private fun appendElementFullName(
}
}
fun reportMissingActual(irElement: IrElement) {
// TODO: setup diagnostics reporting
throw AssertionError("Missing actual for ${irElement.render()}")
@OptIn(ObsoleteDescriptorBasedAPI::class)
fun KtDiagnosticReporterWithImplicitIrBasedContext.reportMissingActual(irDeclaration: IrDeclaration) {
at(irDeclaration).report(CommonBackendErrors.NO_ACTUAL_FOR_EXPECT, irDeclaration.module)
}
fun reportManyInterfacesMembersNotImplemented(declaration: IrClass, actualMember: IrDeclarationWithName) {
// TODO: setup diagnostics reporting
throw AssertionError("${declaration.name} must override ${actualMember.name} because it inherits multiple interface methods of it")
fun KtDiagnosticReporterWithImplicitIrBasedContext.reportManyInterfacesMembersNotImplemented(declaration: IrClass, actualMember: IrDeclarationWithName) {
at(declaration).report(CommonBackendErrors.MANY_INTERFACES_MEMBER_NOT_IMPLEMENTED, actualMember.name.asString())
}
internal fun IrElement.containsOptionalExpectation(): Boolean {
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.backend.common.actualizer
import org.jetbrains.kotlin.KtDiagnosticReporterWithImplicitIrBasedContext
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.builders.declarations.buildFun
import org.jetbrains.kotlin.ir.builders.declarations.buildProperty
@@ -22,7 +23,8 @@ import org.jetbrains.kotlin.name.FqName
class MissingFakeOverridesAdder(
private val expectActualMap: Map<IrSymbol, IrSymbol>,
private val typeAliasMap: Map<FqName, FqName>
private val typeAliasMap: Map<FqName, FqName>,
private val diagnosticsReporter: KtDiagnosticReporterWithImplicitIrBasedContext
) : IrElementVisitorVoid {
override fun visitClass(declaration: IrClass) {
if (!declaration.isExpect) {
@@ -75,7 +77,7 @@ class MissingFakeOverridesAdder(
is IrFunctionImpl,
is IrPropertyImpl -> {
if (members[generateIrElementFullName(actualMember, expectActualMap, typeAliasMap)] != null) {
reportManyInterfacesMembersNotImplemented(declaration, actualMember as IrDeclarationWithName)
diagnosticsReporter.reportManyInterfacesMembersNotImplemented(declaration, actualMember as IrDeclarationWithName)
return
}