diff --git a/compiler-plugin/compiler-plugin-k2/src/main/core/kotlinx/rpc/codegen/checkers/FirCheckedAnnotationCheckers.kt b/compiler-plugin/compiler-plugin-k2/src/main/core/kotlinx/rpc/codegen/checkers/FirCheckedAnnotationCheckers.kt index e9bb8aa39..8760fe81a 100644 --- a/compiler-plugin/compiler-plugin-k2/src/main/core/kotlinx/rpc/codegen/checkers/FirCheckedAnnotationCheckers.kt +++ b/compiler-plugin/compiler-plugin-k2/src/main/core/kotlinx/rpc/codegen/checkers/FirCheckedAnnotationCheckers.kt @@ -1,5 +1,5 @@ /* - * Copyright 2023-2024 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2023-2025 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.rpc.codegen.checkers @@ -231,6 +231,7 @@ object FirCheckedAnnotationHelper { source = source, context = context, reporter = reporter, + typeArgumentIndex = i, ) } @@ -304,6 +305,7 @@ object FirCheckedAnnotationHelper { source: KtSourceElement?, context: CheckerContext, reporter: DiagnosticReporter, + typeArgumentIndex: Int, ) { for (annotationClass in annotations) { val hasCheckedAnnotation = hasCheckedAnnotation( @@ -316,7 +318,9 @@ object FirCheckedAnnotationHelper { reporter.reportOn( source = source, factory = FirRpcDiagnostics.CHECKED_ANNOTATION_VIOLATION, - a = annotationClass.defaultType(), + a = typeArgumentIndex, + b = annotationClass.defaultType(), + c = classSymbol, context = context, ) } diff --git a/compiler-plugin/compiler-plugin-k2/src/main/core/kotlinx/rpc/codegen/checkers/diagnostics/FirRpcDiagnostics.kt b/compiler-plugin/compiler-plugin-k2/src/main/core/kotlinx/rpc/codegen/checkers/diagnostics/FirRpcDiagnostics.kt index 2af4aa1ab..5a9e913e3 100644 --- a/compiler-plugin/compiler-plugin-k2/src/main/core/kotlinx/rpc/codegen/checkers/diagnostics/FirRpcDiagnostics.kt +++ b/compiler-plugin/compiler-plugin-k2/src/main/core/kotlinx/rpc/codegen/checkers/diagnostics/FirRpcDiagnostics.kt @@ -11,7 +11,9 @@ import org.jetbrains.kotlin.diagnostics.SourceElementPositioningStrategies import org.jetbrains.kotlin.diagnostics.error0 import org.jetbrains.kotlin.diagnostics.error1 import org.jetbrains.kotlin.diagnostics.error2 +import org.jetbrains.kotlin.diagnostics.error3 import org.jetbrains.kotlin.diagnostics.rendering.RootDiagnosticRendererFactory +import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol import org.jetbrains.kotlin.fir.types.ConeKotlinType import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.psi.KtAnnotated @@ -27,7 +29,7 @@ object FirRpcDiagnostics { val MISSING_RPC_ANNOTATION by error0() val MISSING_SERIALIZATION_MODULE by error0() val WRONG_RPC_ANNOTATION_TARGET by error1() - val CHECKED_ANNOTATION_VIOLATION by error1() + val CHECKED_ANNOTATION_VIOLATION by error3>() val NON_SUSPENDING_REQUEST_WITHOUT_STREAMING_RETURN_TYPE by error0() val AD_HOC_POLYMORPHISM_IN_RPC_SERVICE by error2() val TYPE_PARAMETERS_IN_RPC_FUNCTION by error0(SourceElementPositioningStrategies.TYPE_PARAMETERS_LIST) diff --git a/compiler-plugin/compiler-plugin-k2/src/main/core/kotlinx/rpc/codegen/checkers/diagnostics/RpcDiagnosticRendererFactory.kt b/compiler-plugin/compiler-plugin-k2/src/main/core/kotlinx/rpc/codegen/checkers/diagnostics/RpcDiagnosticRendererFactory.kt index 20ca86bed..17851071c 100644 --- a/compiler-plugin/compiler-plugin-k2/src/main/core/kotlinx/rpc/codegen/checkers/diagnostics/RpcDiagnosticRendererFactory.kt +++ b/compiler-plugin/compiler-plugin-k2/src/main/core/kotlinx/rpc/codegen/checkers/diagnostics/RpcDiagnosticRendererFactory.kt @@ -35,9 +35,12 @@ object RpcDiagnosticRendererFactory : BaseDiagnosticRendererFactory() { put( factory = FirRpcDiagnostics.CHECKED_ANNOTATION_VIOLATION, - message = "Type argument marked with {0} annotation " + - "must be annotated with {0} or an annotation annotated with {0}.", - rendererA = FirDiagnosticRenderers.RENDER_TYPE, + message = "{0} type argument is marked with @{1} annotation, but inferred type is {2}. " + + "Provide a type that is marked with @{1} annotation explicitly " + + "or remove the annotation from the type argument declaration.", + rendererA = Renderer { it.indexPositionSpelled() }, + rendererB = FirDiagnosticRenderers.RENDER_TYPE, + rendererC = FirDiagnosticRenderers.SYMBOL, ) put( @@ -64,6 +67,18 @@ object RpcDiagnosticRendererFactory : BaseDiagnosticRendererFactory() { } } +private fun Int.indexPositionSpelled(): String { + val padded = this + 1 + val suffix = when (padded % 10) { + 1 -> "st" + 2 -> "nd" + 3 -> "rd" + else -> "th" + } + + return "$padded$suffix" +} + class RpcStrictModeDiagnosticRendererFactory( private val diagnostics: FirRpcStrictModeDiagnostics, ) : BaseDiagnosticRendererFactory() {