[IR] Extract IrActualizationErrors from CommonBackendErrors

^KT-62292
This commit is contained in:
Pavel Kunyavskiy
2023-11-14 14:06:43 +01:00
committed by Space Team
parent 763d2ec2fe
commit 55e7ff18c6
4 changed files with 105 additions and 81 deletions
@@ -6,36 +6,14 @@
package org.jetbrains.kotlin.backend.common
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.backend.common.BackendDiagnosticRenderers.DECLARATION_NAME
import org.jetbrains.kotlin.backend.common.BackendDiagnosticRenderers.EXPECT_ACTUAL_ANNOTATION_INCOMPATIBILITY
import org.jetbrains.kotlin.backend.common.BackendDiagnosticRenderers.INCOMPATIBILITY
import org.jetbrains.kotlin.backend.common.BackendDiagnosticRenderers.MISMATCH
import org.jetbrains.kotlin.backend.common.BackendDiagnosticRenderers.EVALUATION_ERROR_EXPLANATION
import org.jetbrains.kotlin.backend.common.BackendDiagnosticRenderers.SYMBOL_OWNER_DECLARATION_FQ_NAME
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.diagnostics.*
import org.jetbrains.kotlin.diagnostics.rendering.BaseDiagnosticRendererFactory
import org.jetbrains.kotlin.diagnostics.rendering.CommonRenderers.STRING
import org.jetbrains.kotlin.diagnostics.rendering.Renderer
import org.jetbrains.kotlin.diagnostics.rendering.Renderers.MODULE_WITH_PLATFORM
import org.jetbrains.kotlin.diagnostics.rendering.RootDiagnosticRendererFactory
import org.jetbrains.kotlin.ir.declarations.IrDeclarationWithName
import org.jetbrains.kotlin.ir.declarations.IrValueParameter
import org.jetbrains.kotlin.ir.expressions.IrConstructorCall
import org.jetbrains.kotlin.ir.symbols.IrSymbol
import org.jetbrains.kotlin.ir.types.classFqName
import org.jetbrains.kotlin.ir.util.fqNameWhenAvailable
import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualAnnotationsIncompatibilityType
import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualCheckingCompatibility
import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualMatchingCompatibility
object CommonBackendErrors {
val NO_ACTUAL_FOR_EXPECT by error2<PsiElement, String, ModuleDescriptor>()
val EXPECT_ACTUAL_MISMATCH by error3<PsiElement, String, String, ExpectActualMatchingCompatibility.Mismatch>()
val EXPECT_ACTUAL_INCOMPATIBILITY by error3<PsiElement, String, String, ExpectActualCheckingCompatibility.Incompatible<*>>()
val ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT by warning3<PsiElement, IrSymbol, IrSymbol, ExpectActualAnnotationsIncompatibilityType<IrConstructorCall>>()
val EVALUATION_ERROR by error1<PsiElement, String>()
val ACTUAL_ANNOTATION_CONFLICTING_DEFAULT_ARGUMENT_VALUE by error1<PsiElement, IrValueParameter>()
init {
RootDiagnosticRendererFactory.registerFactory(KtDefaultCommonBackendErrorMessages)
@@ -44,67 +22,15 @@ object CommonBackendErrors {
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}",
STRING,
MODULE_WITH_PLATFORM,
)
map.put(
CommonBackendErrors.EXPECT_ACTUAL_MISMATCH,
"Expect declaration `{0}` doesn''t match actual `{1}` because {2}",
STRING,
STRING,
MISMATCH
)
map.put(
CommonBackendErrors.EXPECT_ACTUAL_INCOMPATIBILITY,
"Expect declaration `{0}` is incompatible with actual `{1}` because {2}",
STRING,
STRING,
INCOMPATIBILITY
)
map.put(
CommonBackendErrors.ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT,
"{2}.\n" +
"All annotations from expect `{0}` must be present with the same arguments on actual `{1}`, otherwise they might behave incorrectly.",
SYMBOL_OWNER_DECLARATION_FQ_NAME,
SYMBOL_OWNER_DECLARATION_FQ_NAME,
EXPECT_ACTUAL_ANNOTATION_INCOMPATIBILITY,
)
map.put(
CommonBackendErrors.EVALUATION_ERROR,
"Cannot evaluate constant expression: {0}",
EVALUATION_ERROR_EXPLANATION,
)
map.put(
CommonBackendErrors.ACTUAL_ANNOTATION_CONFLICTING_DEFAULT_ARGUMENT_VALUE,
"Parameter ''{0}'' has conflicting values in expected and actual annotations.",
DECLARATION_NAME,
)
}
}
object BackendDiagnosticRenderers {
val MISMATCH = Renderer<ExpectActualMatchingCompatibility.Mismatch> {
it.reason ?: "<unknown>"
}
val INCOMPATIBILITY = Renderer<ExpectActualCheckingCompatibility.Incompatible<*>> {
it.reason ?: "<unknown>"
}
val SYMBOL_OWNER_DECLARATION_FQ_NAME = Renderer<IrSymbol> {
(it.owner as? IrDeclarationWithName)?.fqNameWhenAvailable?.asString() ?: "unknown name"
}
val EXPECT_ACTUAL_ANNOTATION_INCOMPATIBILITY =
Renderer { incompatibilityType: ExpectActualAnnotationsIncompatibilityType<IrConstructorCall> ->
val expectAnnotationFqName = incompatibilityType.expectAnnotation.type.classFqName ?: "<unknown>"
val reason = when (incompatibilityType) {
is ExpectActualAnnotationsIncompatibilityType.MissingOnActual -> "is missing on actual declaration"
is ExpectActualAnnotationsIncompatibilityType.DifferentOnActual -> "has different arguments on actual declaration"
}
"Annotation `$expectAnnotationFqName` $reason"
}
val DECLARATION_NAME = Renderer<IrDeclarationWithName> { it.name.asString() }
val EVALUATION_ERROR_EXPLANATION = Renderer<String> {
val result = Regex("Exception (\\S+)(: (.*))?").matchEntire(it)?.groupValues
val exceptionName = result?.getOrNull(1)
@@ -0,0 +1,88 @@
/*
* 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.actualizer
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.diagnostics.*
import org.jetbrains.kotlin.diagnostics.rendering.*
import org.jetbrains.kotlin.ir.IrDiagnosticRenderers
import org.jetbrains.kotlin.ir.declarations.IrValueParameter
import org.jetbrains.kotlin.ir.expressions.IrConstructorCall
import org.jetbrains.kotlin.ir.symbols.IrSymbol
import org.jetbrains.kotlin.ir.types.classFqName
import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualAnnotationsIncompatibilityType
import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualCheckingCompatibility
import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualMatchingCompatibility
object IrActualizationErrors {
val NO_ACTUAL_FOR_EXPECT by error2<PsiElement, String, ModuleDescriptor>()
val EXPECT_ACTUAL_MISMATCH by error3<PsiElement, String, String, ExpectActualMatchingCompatibility.Mismatch>()
val EXPECT_ACTUAL_INCOMPATIBILITY by error3<PsiElement, String, String, ExpectActualCheckingCompatibility.Incompatible<*>>()
val ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT by warning3<PsiElement, IrSymbol, IrSymbol, ExpectActualAnnotationsIncompatibilityType<IrConstructorCall>>()
val ACTUAL_ANNOTATION_CONFLICTING_DEFAULT_ARGUMENT_VALUE by error1<PsiElement, IrValueParameter>()
init {
RootDiagnosticRendererFactory.registerFactory(KtDefaultIrActualizationErrorMessages)
}
}
object KtDefaultIrActualizationErrorMessages : BaseDiagnosticRendererFactory() {
override val MAP = KtDiagnosticFactoryToRendererMap("KT").also { map ->
map.put(
IrActualizationErrors.NO_ACTUAL_FOR_EXPECT,
"Expected {0} has no actual declaration in module {1}",
CommonRenderers.STRING,
Renderers.MODULE_WITH_PLATFORM,
)
map.put(
IrActualizationErrors.EXPECT_ACTUAL_MISMATCH,
"Expect declaration `{0}` doesn''t match actual `{1}` because {2}",
CommonRenderers.STRING,
CommonRenderers.STRING,
IrActualizationDiagnosticRenderers.MISMATCH
)
map.put(
IrActualizationErrors.EXPECT_ACTUAL_INCOMPATIBILITY,
"Expect declaration `{0}` is incompatible with actual `{1}` because {2}",
CommonRenderers.STRING,
CommonRenderers.STRING,
IrActualizationDiagnosticRenderers.INCOMPATIBILITY
)
map.put(
IrActualizationErrors.ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT,
"{2}.\n" +
"All annotations from expect `{0}` must be present with the same arguments on actual `{1}`, otherwise they might behave incorrectly.",
IrDiagnosticRenderers.SYMBOL_OWNER_DECLARATION_FQ_NAME,
IrDiagnosticRenderers.SYMBOL_OWNER_DECLARATION_FQ_NAME,
IrActualizationDiagnosticRenderers.EXPECT_ACTUAL_ANNOTATION_INCOMPATIBILITY,
)
map.put(
IrActualizationErrors.ACTUAL_ANNOTATION_CONFLICTING_DEFAULT_ARGUMENT_VALUE,
"Parameter ''{0}'' has conflicting values in expected and actual annotations.",
IrDiagnosticRenderers.DECLARATION_NAME,
)
}
}
object IrActualizationDiagnosticRenderers {
val MISMATCH = Renderer<ExpectActualMatchingCompatibility.Mismatch> {
it.reason ?: "<unknown>"
}
val INCOMPATIBILITY = Renderer<ExpectActualCheckingCompatibility.Incompatible<*>> {
it.reason ?: "<unknown>"
}
val EXPECT_ACTUAL_ANNOTATION_INCOMPATIBILITY =
Renderer { incompatibilityType: ExpectActualAnnotationsIncompatibilityType<IrConstructorCall> ->
val expectAnnotationFqName = incompatibilityType.expectAnnotation.type.classFqName ?: "<unknown>"
val reason = when (incompatibilityType) {
is ExpectActualAnnotationsIncompatibilityType.MissingOnActual -> "is missing on actual declaration"
is ExpectActualAnnotationsIncompatibilityType.DifferentOnActual -> "has different arguments on actual declaration"
}
"Annotation `$expectAnnotationFqName` $reason"
}
}
@@ -6,7 +6,6 @@
package org.jetbrains.kotlin.backend.common.actualizer
import org.jetbrains.kotlin.ir.IrDiagnosticReporter
import org.jetbrains.kotlin.backend.common.CommonBackendErrors
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
@@ -101,7 +100,7 @@ internal fun IrDiagnosticReporter.reportMissingActual(expectSymbol: IrSymbol) {
@OptIn(ObsoleteDescriptorBasedAPI::class)
internal fun IrDiagnosticReporter.reportMissingActual(irDeclaration: IrDeclaration) {
at(irDeclaration).report(
CommonBackendErrors.NO_ACTUAL_FOR_EXPECT,
IrActualizationErrors.NO_ACTUAL_FOR_EXPECT,
(irDeclaration as? IrDeclarationWithName)?.name?.asString().orEmpty(),
irDeclaration.module
)
@@ -115,7 +114,7 @@ internal fun IrDiagnosticReporter.reportExpectActualIncompatibility(
val expectDeclaration = expectSymbol.owner as IrDeclaration
val actualDeclaration = actualSymbol.owner as IrDeclaration
at(expectDeclaration).report(
CommonBackendErrors.EXPECT_ACTUAL_INCOMPATIBILITY,
IrActualizationErrors.EXPECT_ACTUAL_INCOMPATIBILITY,
expectDeclaration.getNameWithAssert().asString(),
actualDeclaration.getNameWithAssert().asString(),
incompatibility
@@ -130,7 +129,7 @@ internal fun IrDiagnosticReporter.reportExpectActualMismatch(
val expectDeclaration = expectSymbol.owner as IrDeclaration
val actualDeclaration = actualSymbol.owner as IrDeclaration
at(expectDeclaration).report(
CommonBackendErrors.EXPECT_ACTUAL_MISMATCH,
IrActualizationErrors.EXPECT_ACTUAL_MISMATCH,
expectDeclaration.getNameWithAssert().asString(),
actualDeclaration.getNameWithAssert().asString(),
incompatibility
@@ -144,7 +143,7 @@ internal fun IrDiagnosticReporter.reportActualAnnotationsNotMatchExpect(
reportOn: IrSymbol,
) {
at(reportOn.owner as IrDeclaration).report(
CommonBackendErrors.ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT,
IrActualizationErrors.ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT,
expectSymbol,
actualSymbol,
incompatibilityType,
@@ -157,7 +156,7 @@ internal fun IrDiagnosticReporter.reportActualAnnotationConflictingDefaultArgume
actualParam: IrValueParameter,
) {
at(reportOn, file).report(
CommonBackendErrors.ACTUAL_ANNOTATION_CONFLICTING_DEFAULT_ARGUMENT_VALUE,
IrActualizationErrors.ACTUAL_ANNOTATION_CONFLICTING_DEFAULT_ARGUMENT_VALUE,
actualParam,
)
}
@@ -7,12 +7,23 @@ package org.jetbrains.kotlin.ir
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.diagnostics.KtDiagnosticReporterWithContext.DiagnosticContextImpl
import org.jetbrains.kotlin.diagnostics.rendering.Renderer
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
import org.jetbrains.kotlin.ir.declarations.IrDeclarationWithName
import org.jetbrains.kotlin.ir.declarations.IrFile
import org.jetbrains.kotlin.ir.symbols.IrSymbol
import org.jetbrains.kotlin.ir.util.fqNameWhenAvailable
interface IrDiagnosticReporter {
val languageVersionSettings: LanguageVersionSettings
fun at(irDeclaration: IrDeclaration): DiagnosticContextImpl
fun at(irElement: IrElement, containingIrFile: IrFile): DiagnosticContextImpl
fun at(irElement: IrElement, containingIrDeclaration: IrDeclaration): DiagnosticContextImpl
}
}
object IrDiagnosticRenderers {
val SYMBOL_OWNER_DECLARATION_FQ_NAME = Renderer<IrSymbol> {
(it.owner as? IrDeclarationWithName)?.fqNameWhenAvailable?.asString() ?: "unknown name"
}
val DECLARATION_NAME = Renderer<IrDeclarationWithName> { it.name.asString() }
}