[FE, IR] Make expect actual annotations diagnostic message more friendly
Print which annotation exactly has a problem instead of printing whole declarations with all annotations. ^KT-58551
This commit is contained in:
committed by
Space Team
parent
11ccad7e40
commit
6943d03883
-10
@@ -179,14 +179,4 @@ object FirDiagnosticRenderers {
|
||||
}
|
||||
|
||||
val FUNCTIONAL_TYPE_KINDS = KtDiagnosticRenderers.COLLECTION(FUNCTIONAL_TYPE_KIND)
|
||||
|
||||
@OptIn(SymbolInternals::class)
|
||||
val SYMBOL_WITH_ANNOTATIONS = Renderer { s: FirBasedSymbol<*> ->
|
||||
FirRenderer(
|
||||
typeRenderer = ConeTypeRenderer(),
|
||||
idRenderer = ConeIdShortRenderer(),
|
||||
classMemberRenderer = null,
|
||||
bodyRenderer = null,
|
||||
).renderElementAsString(s.fir, trim = true)
|
||||
}
|
||||
}
|
||||
|
||||
+5
-5
@@ -1886,11 +1886,11 @@ object FirErrorsDefaultMessages : BaseDiagnosticRendererFactory() {
|
||||
)
|
||||
map.put(
|
||||
ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT,
|
||||
"All annotations from `expect` must be presented with same arguments on `actual`, otherwise they have no effect.\n" +
|
||||
"Expected: {0}\n" +
|
||||
"Actual: {1}",
|
||||
FirDiagnosticRenderers.SYMBOL_WITH_ANNOTATIONS, FirDiagnosticRenderers.SYMBOL_WITH_ANNOTATIONS,
|
||||
TO_STRING
|
||||
"{2}.\n" +
|
||||
"All annotations from expect `{0}` must be present with the same arguments on actual `{1}`, otherwise they might behave incorrectly.",
|
||||
FirExpectActualAnnotationIncompatibilityDiagnosticRenderers.SYMBOL_RENDERER,
|
||||
FirExpectActualAnnotationIncompatibilityDiagnosticRenderers.SYMBOL_RENDERER,
|
||||
FirExpectActualAnnotationIncompatibilityDiagnosticRenderers.INCOMPATIBILITY,
|
||||
)
|
||||
|
||||
// Destructuring declaration
|
||||
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* 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.fir.analysis.diagnostics
|
||||
|
||||
import org.jetbrains.kotlin.diagnostics.rendering.Renderer
|
||||
import org.jetbrains.kotlin.fir.expressions.FirAnnotation
|
||||
import org.jetbrains.kotlin.fir.renderer.ConeIdShortRenderer
|
||||
import org.jetbrains.kotlin.fir.renderer.ConeTypeRenderer
|
||||
import org.jetbrains.kotlin.fir.renderer.FirRenderer
|
||||
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.SymbolInternals
|
||||
import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualAnnotationsIncompatibilityType
|
||||
|
||||
internal object FirExpectActualAnnotationIncompatibilityDiagnosticRenderers {
|
||||
@OptIn(SymbolInternals::class)
|
||||
val SYMBOL_RENDERER = Renderer<FirBasedSymbol<*>> {
|
||||
FirRenderer(
|
||||
typeRenderer = ConeTypeRenderer(),
|
||||
idRenderer = ConeIdShortRenderer(),
|
||||
classMemberRenderer = null,
|
||||
bodyRenderer = null,
|
||||
annotationRenderer = null,
|
||||
modifierRenderer = null,
|
||||
contractRenderer = null,
|
||||
).renderElementAsString(it.fir, trim = true)
|
||||
}
|
||||
|
||||
val INCOMPATIBILITY = Renderer { incompatibilityType: ExpectActualAnnotationsIncompatibilityType<FirAnnotation> ->
|
||||
val sb = StringBuilder("Annotation `")
|
||||
.append(renderAnnotation(incompatibilityType.expectAnnotation))
|
||||
.append("` ")
|
||||
when (incompatibilityType) {
|
||||
is ExpectActualAnnotationsIncompatibilityType.MissingOnActual -> {
|
||||
sb.append("is missing on actual declaration")
|
||||
}
|
||||
is ExpectActualAnnotationsIncompatibilityType.DifferentOnActual -> {
|
||||
sb.append("has different arguments on actual declaration: `")
|
||||
.append(renderAnnotation(incompatibilityType.actualAnnotation))
|
||||
.append("`")
|
||||
}
|
||||
}
|
||||
sb.toString()
|
||||
}
|
||||
|
||||
private fun renderAnnotation(ann: FirAnnotation): String {
|
||||
return FirRenderer(
|
||||
typeRenderer = ConeTypeRenderer(),
|
||||
idRenderer = ConeIdShortRenderer(),
|
||||
).renderElementAsString(ann, trim = true)
|
||||
}
|
||||
}
|
||||
+5
-4
@@ -404,10 +404,11 @@ public class DefaultErrorMessages {
|
||||
"`actual typealias` to annotation which affects code compilation can lead to incorrect behavior. Instead, use ''{0}'' annotation directly.",
|
||||
TO_STRING);
|
||||
MAP.put(ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT,
|
||||
"All annotations from `expect` must be presented with same arguments on `actual`, otherwise they have no effect.\n" +
|
||||
" Expected: {0}\n" +
|
||||
" Actual: {1}",
|
||||
DESCRIPTOR_WITH_ANNOTATIONS, DESCRIPTOR_WITH_ANNOTATIONS, TO_STRING);
|
||||
"{2}.\n" +
|
||||
"All annotations from expect `{0}` must be present with the same arguments on actual `{1}`, otherwise they might behave incorrectly.",
|
||||
ExpectActualAnnotationIncompatibilityDiagnosticRenderers.DESCRIPTOR_RENDERER,
|
||||
ExpectActualAnnotationIncompatibilityDiagnosticRenderers.DESCRIPTOR_RENDERER,
|
||||
ExpectActualAnnotationIncompatibilityDiagnosticRenderers.INCOMPATIBILITY);
|
||||
|
||||
MAP.put(PROJECTION_ON_NON_CLASS_TYPE_ARGUMENT, "Projections are not allowed on type arguments of functions and properties");
|
||||
MAP.put(SUPERTYPE_NOT_INITIALIZED, "This type has a constructor, and thus must be initialized here");
|
||||
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* 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.diagnostics.rendering
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
||||
import org.jetbrains.kotlin.renderer.AnnotationArgumentsRenderingPolicy
|
||||
import org.jetbrains.kotlin.renderer.ClassifierNamePolicy
|
||||
import org.jetbrains.kotlin.renderer.DescriptorRenderer
|
||||
import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualAnnotationsIncompatibilityType
|
||||
|
||||
internal object ExpectActualAnnotationIncompatibilityDiagnosticRenderers {
|
||||
private val descriptorRender = DescriptorRenderer.withOptions {
|
||||
annotationArgumentsRenderingPolicy = AnnotationArgumentsRenderingPolicy.UNLESS_EMPTY
|
||||
modifiers = emptySet()
|
||||
withDefinedIn = true
|
||||
classifierNamePolicy = ClassifierNamePolicy.SHORT
|
||||
}
|
||||
|
||||
@JvmField
|
||||
val DESCRIPTOR_RENDERER = descriptorRender.asRenderer()
|
||||
|
||||
@JvmField
|
||||
val INCOMPATIBILITY = Renderer { incompatibilityType: ExpectActualAnnotationsIncompatibilityType<AnnotationDescriptor> ->
|
||||
val sb = StringBuilder("Annotation `")
|
||||
.append(descriptorRender.renderAnnotation(incompatibilityType.expectAnnotation))
|
||||
.append("` ")
|
||||
when (incompatibilityType) {
|
||||
is ExpectActualAnnotationsIncompatibilityType.MissingOnActual -> {
|
||||
sb.append("is missing on actual declaration")
|
||||
}
|
||||
is ExpectActualAnnotationsIncompatibilityType.DifferentOnActual -> {
|
||||
sb.append("has different arguments on actual declaration: `")
|
||||
.append(descriptorRender.renderAnnotation(incompatibilityType.actualAnnotation))
|
||||
.append("`")
|
||||
}
|
||||
}
|
||||
sb.toString()
|
||||
}
|
||||
}
|
||||
@@ -711,13 +711,6 @@ object Renderers {
|
||||
@JvmField
|
||||
val COMPACT_WITH_MODIFIERS = DescriptorRenderer.COMPACT_WITH_MODIFIERS.asRenderer()
|
||||
|
||||
@JvmField
|
||||
val DESCRIPTOR_WITH_ANNOTATIONS = DescriptorRenderer.withOptions {
|
||||
annotationArgumentsRenderingPolicy = AnnotationArgumentsRenderingPolicy.UNLESS_EMPTY
|
||||
modifiers = modifiers.plus(DescriptorRendererModifier.ANNOTATIONS)
|
||||
withDefinedIn = true
|
||||
}.asRenderer()
|
||||
|
||||
@JvmField
|
||||
val DEPRECATION_RENDERER = DescriptorRenderer.ONLY_NAMES_WITH_SHORT_TYPES.withOptions {
|
||||
withoutTypeParameters = false
|
||||
|
||||
+14
-2
@@ -6,6 +6,7 @@
|
||||
package org.jetbrains.kotlin.backend.common
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
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.SYMBOL_OWNER_DECLARATION_FQ_NAME
|
||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||
@@ -18,6 +19,7 @@ import org.jetbrains.kotlin.diagnostics.rendering.RootDiagnosticRendererFactory
|
||||
import org.jetbrains.kotlin.ir.declarations.IrDeclarationWithName
|
||||
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.ExpectActualCompatibility
|
||||
@@ -64,10 +66,11 @@ object KtDefaultCommonBackendErrorMessages : BaseDiagnosticRendererFactory() {
|
||||
)
|
||||
map.put(
|
||||
CommonBackendErrors.ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT,
|
||||
"All annotations from expect declaration `{0}` must be present with the same arguments on actual declaration `{1}` otherwise they have no effect",
|
||||
"{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,
|
||||
STRING,
|
||||
EXPECT_ACTUAL_ANNOTATION_INCOMPATIBILITY,
|
||||
)
|
||||
map.put(
|
||||
CommonBackendErrors.EVALUATION_ERROR,
|
||||
@@ -84,4 +87,13 @@ object BackendDiagnosticRenderers {
|
||||
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"
|
||||
}
|
||||
}
|
||||
|
||||
+10
-9
@@ -1,19 +1,20 @@
|
||||
// -- Module: <m1-common> --
|
||||
|
||||
// -- Module: <m1-jvm> --
|
||||
/jvm.kt:23:14: warning: all annotations from `expect` must be presented with same arguments on `actual`, otherwise they have no effect.
|
||||
Expected: @Ann public final expect class OnClass defined in root package in file common.kt
|
||||
Actual: public final actual class OnClass defined in root package in file jvm.kt
|
||||
/jvm.kt:27:14: warning: annotation `@Ann` is missing on actual declaration.
|
||||
All annotations from expect `class OnClass defined in root package in file common.kt` must be present with the same arguments on actual `class OnClass defined in root package in file jvm.kt`, otherwise they might behave incorrectly.
|
||||
actual class OnClass
|
||||
^
|
||||
/jvm.kt:26:16: warning: all annotations from `expect` must be presented with same arguments on `actual`, otherwise they have no effect.
|
||||
Expected: @Ann public final expect fun onMember(): Unit defined in OnMember
|
||||
Actual: public final actual fun onMember(): Unit defined in OnMember
|
||||
/jvm.kt:30:16: warning: annotation `@Ann` is missing on actual declaration.
|
||||
All annotations from expect `fun onMember(): Unit defined in OnMember` must be present with the same arguments on actual `fun onMember(): Unit defined in OnMember`, otherwise they might behave incorrectly.
|
||||
actual fun onMember() {}
|
||||
^
|
||||
/jvm.kt:33:18: warning: all annotations from `expect` must be presented with same arguments on `actual`, otherwise they have no effect.
|
||||
Expected: @Ann public final expect class ViaTypealias defined in root package in file common.kt
|
||||
Actual: public final class ViaTypealiasImpl defined in root package in file jvm.kt
|
||||
/jvm.kt:37:18: warning: annotation `@Ann` is missing on actual declaration.
|
||||
All annotations from expect `class ViaTypealias defined in root package in file common.kt` must be present with the same arguments on actual `class ViaTypealiasImpl defined in root package in file jvm.kt`, otherwise they might behave incorrectly.
|
||||
actual typealias ViaTypealias = ViaTypealiasImpl
|
||||
^
|
||||
/jvm.kt:40:12: warning: annotation `@WithArg(s = "str")` has different arguments on actual declaration: `@WithArg(s = "other str")`.
|
||||
All annotations from expect `fun withDifferentArg(): Unit defined in root package in file common.kt` must be present with the same arguments on actual `fun withDifferentArg(): Unit defined in root package in file jvm.kt`, otherwise they might behave incorrectly.
|
||||
actual fun withDifferentArg() {}
|
||||
^
|
||||
|
||||
|
||||
+9
-9
@@ -1,11 +1,11 @@
|
||||
/jvm.kt:(82,89): warning: All annotations from `expect` must be presented with same arguments on `actual`, otherwise they have no effect.
|
||||
Expected: @Ann() public final expect class OnClass : Any
|
||||
Actual: public final actual class OnClass : Any
|
||||
/jvm.kt:(86,93): warning: Annotation `@Ann()` is missing on actual declaration.
|
||||
All annotations from expect `class OnClass : Any` must be present with the same arguments on actual `class OnClass : Any`, otherwise they might behave incorrectly.
|
||||
|
||||
/jvm.kt:(130,138): warning: All annotations from `expect` must be presented with same arguments on `actual`, otherwise they have no effect.
|
||||
Expected: @Ann() public final expect fun onMember(): Unit
|
||||
Actual: public final actual fun onMember(): Unit
|
||||
/jvm.kt:(134,142): warning: Annotation `@Ann()` is missing on actual declaration.
|
||||
All annotations from expect `fun onMember(): Unit` must be present with the same arguments on actual `fun onMember(): Unit`, otherwise they might behave incorrectly.
|
||||
|
||||
/jvm.kt:(209,221): warning: All annotations from `expect` must be presented with same arguments on `actual`, otherwise they have no effect.
|
||||
Expected: @Ann() public final expect class ViaTypealias : Any
|
||||
Actual: public final class ViaTypealiasImpl : Any
|
||||
/jvm.kt:(213,225): warning: Annotation `@Ann()` is missing on actual declaration.
|
||||
All annotations from expect `class ViaTypealias : Any` must be present with the same arguments on actual `class ViaTypealiasImpl : Any`, otherwise they might behave incorrectly.
|
||||
|
||||
/jvm.kt:(279,295): warning: Annotation `@WithArg(s = String(str))` has different arguments on actual declaration: `@WithArg(s = String(other str))`.
|
||||
All annotations from expect `fun withDifferentArg(): Unit` must be present with the same arguments on actual `fun withDifferentArg(): Unit`, otherwise they might behave incorrectly.
|
||||
|
||||
Vendored
+7
@@ -17,6 +17,10 @@ expect class ViaTypealias {
|
||||
fun foo()
|
||||
}
|
||||
|
||||
annotation class WithArg(val s: String)
|
||||
|
||||
@WithArg("str")
|
||||
expect fun withDifferentArg()
|
||||
|
||||
// MODULE: m1-jvm()()(m1-common)
|
||||
// FILE: jvm.kt
|
||||
@@ -31,3 +35,6 @@ class ViaTypealiasImpl {
|
||||
}
|
||||
|
||||
<!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT, ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>actual typealias <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>ViaTypealias<!> = ViaTypealiasImpl<!>
|
||||
|
||||
<!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>@WithArg("other str")
|
||||
actual fun <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>withDifferentArg<!>() {}<!>
|
||||
|
||||
Vendored
+7
@@ -17,6 +17,10 @@ expect class ViaTypealias {
|
||||
fun foo()
|
||||
}
|
||||
|
||||
annotation class WithArg(val s: String)
|
||||
|
||||
@WithArg("str")
|
||||
expect fun withDifferentArg()
|
||||
|
||||
// MODULE: m1-jvm()()(m1-common)
|
||||
// FILE: jvm.kt
|
||||
@@ -31,3 +35,6 @@ class ViaTypealiasImpl {
|
||||
}
|
||||
|
||||
actual typealias <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>ViaTypealias<!> = ViaTypealiasImpl
|
||||
|
||||
@WithArg("other str")
|
||||
actual fun <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>withDifferentArg<!>() {}
|
||||
|
||||
Reference in New Issue
Block a user