diff --git a/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/DiagnosticList.kt b/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/DiagnosticList.kt index 8d702b5dac8..24fcf10648a 100644 --- a/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/DiagnosticList.kt +++ b/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/DiagnosticList.kt @@ -47,8 +47,8 @@ class DiagnosticBuilder( @OptIn(PrivateForInline::class, ExperimentalStdlibApi::class) inline fun parameter(name: String) { - if (parameters.size == 3) { - error("Diagnostic cannot have more than 3 parameters") + if (parameters.size >= MAX_DIAGNOSTIC_PARAMETER_COUNT) { + error("Diagnostic cannot have more than $MAX_DIAGNOSTIC_PARAMETER_COUNT parameters") } parameters += DiagnosticParameter( name = name, @@ -64,4 +64,8 @@ class DiagnosticBuilder( parameters, positioningStrategy, ) + + companion object { + const val MAX_DIAGNOSTIC_PARAMETER_COUNT = 4 + } } diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDiagnostic.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDiagnostic.kt index 1f8961bfb88..12a77829b42 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDiagnostic.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDiagnostic.kt @@ -51,6 +51,14 @@ sealed class FirDiagnosticWithParameters3 } +sealed class FirDiagnosticWithParameters4 : FirDiagnostic() { + abstract val a: A + abstract val b: B + abstract val c: C + abstract val d: D + abstract override val factory: FirDiagnosticFactory4<*, A, B, C, D> +} + // ------------------------------ psi diagnostics ------------------------------ interface FirPsiDiagnostic

: Diagnostic { @@ -93,6 +101,16 @@ data class FirPsiDiagnosticWithParameters3

) : FirDiagnosticWithParameters3, A, B, C>(), FirPsiDiagnostic

+data class FirPsiDiagnosticWithParameters4

( + override val element: FirPsiSourceElement

, + override val a: A, + override val b: B, + override val c: C, + override val d: D, + override val severity: Severity, + override val factory: FirDiagnosticFactory4 +) : FirDiagnosticWithParameters4, A, B, C, D>(), FirPsiDiagnostic

+ // ------------------------------ light tree diagnostics ------------------------------ interface FirLightDiagnostic : UnboundDiagnostic { @@ -128,3 +146,13 @@ data class FirLightDiagnosticWithParameters3( override val severity: Severity, override val factory: FirDiagnosticFactory3<*, A, B, C> ) : FirDiagnosticWithParameters3(), FirLightDiagnostic + +data class FirLightDiagnosticWithParameters4( + override val element: FirLightSourceElement, + override val a: A, + override val b: B, + override val c: C, + override val d: D, + override val severity: Severity, + override val factory: FirDiagnosticFactory4<*, A, B, C, D> +) : FirDiagnosticWithParameters4(), FirLightDiagnostic diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDiagnosticFactory.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDiagnosticFactory.kt index cc461857224..29329317f03 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDiagnosticFactory.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDiagnosticFactory.kt @@ -9,7 +9,8 @@ package org.jetbrains.kotlin.fir.analysis.diagnostics import com.intellij.openapi.util.TextRange import com.intellij.psi.PsiElement -import org.jetbrains.kotlin.diagnostics.* +import org.jetbrains.kotlin.diagnostics.DiagnosticFactory +import org.jetbrains.kotlin.diagnostics.Severity import org.jetbrains.kotlin.diagnostics.rendering.DiagnosticRenderer import org.jetbrains.kotlin.fir.FirLightSourceElement import org.jetbrains.kotlin.fir.FirPsiSourceElement @@ -120,6 +121,29 @@ class FirDiagnosticFactory3

( } } +class FirDiagnosticFactory4

( + name: String, + severity: Severity, + positioningStrategy: SourceElementPositioningStrategy

= SourceElementPositioningStrategy.DEFAULT, +) : AbstractFirDiagnosticFactory, P>(name, severity, positioningStrategy) { + override val firRenderer: FirDiagnosticRenderer> = FirDiagnosticWithParameters4Renderer( + "{0}, {1}, {2}, {3}", + FirDiagnosticRenderers.TO_STRING, + FirDiagnosticRenderers.TO_STRING, + FirDiagnosticRenderers.TO_STRING, + FirDiagnosticRenderers.TO_STRING + ) + + fun on(element: FirSourceElement, a: A, b: B, c: C, d: D): FirDiagnosticWithParameters4<*, A, B, C, D> { + return when (element) { + is FirPsiSourceElement<*> -> FirPsiDiagnosticWithParameters4( + element as FirPsiSourceElement

, a, b, c, d, severity, this + ) + is FirLightSourceElement -> FirLightDiagnosticWithParameters4(element, a, b, c, d, severity, this) + else -> incorrectElement(element) + } + } +} private fun incorrectElement(element: FirSourceElement): Nothing { throw IllegalArgumentException("Unknown element type: ${element::class}") } diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDiagnosticFactoryDsl.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDiagnosticFactoryDsl.kt index 25319851641..0eae8482d34 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDiagnosticFactoryDsl.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDiagnosticFactoryDsl.kt @@ -6,7 +6,7 @@ package org.jetbrains.kotlin.fir.analysis.diagnostics import com.intellij.psi.PsiElement -import org.jetbrains.kotlin.diagnostics.* +import org.jetbrains.kotlin.diagnostics.Severity import kotlin.properties.ReadOnlyProperty import kotlin.reflect.KProperty @@ -58,6 +58,11 @@ fun

error3( return DiagnosticFactory3DelegateProvider(Severity.ERROR, positioningStrategy) } +fun

error4( + positioningStrategy: SourceElementPositioningStrategy

= SourceElementPositioningStrategy.DEFAULT +): DiagnosticFactory4DelegateProvider { + return DiagnosticFactory4DelegateProvider(Severity.ERROR, positioningStrategy) +} // ------------------------------ Providers ------------------------------ @@ -97,6 +102,16 @@ class DiagnosticFactory3DelegateProvider

( + private val severity: Severity, + private val positioningStrategy: SourceElementPositioningStrategy

+) { + operator fun provideDelegate(thisRef: Any?, prop: KProperty<*>): ReadOnlyProperty> { + return DummyDelegate(FirDiagnosticFactory4(prop.name, severity, positioningStrategy)) + } +} + + private class DummyDelegate(val value: T) : ReadOnlyProperty { override fun getValue(thisRef: Any?, property: KProperty<*>): T { return value diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDiagnosticFactoryToRendererMap.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDiagnosticFactoryToRendererMap.kt index d7a88bd5da5..8c7041b0a27 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDiagnosticFactoryToRendererMap.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDiagnosticFactoryToRendererMap.kt @@ -45,6 +45,17 @@ class FirDiagnosticFactoryToRendererMap(val name: String) { put(factory, FirDiagnosticWithParameters3Renderer(message, rendererA, rendererB, rendererC)) } + fun put( + factory: FirDiagnosticFactory4<*, A, B, C, D>, + message: String, + rendererA: DiagnosticParameterRenderer?, + rendererB: DiagnosticParameterRenderer?, + rendererC: DiagnosticParameterRenderer?, + rendererD: DiagnosticParameterRenderer? + ) { + put(factory, FirDiagnosticWithParameters4Renderer(message, rendererA, rendererB, rendererC, rendererD)) + } + private fun put(factory: AbstractFirDiagnosticFactory<*, *>, renderer: FirDiagnosticRenderer<*>) { renderersMap[factory] = renderer psiDiagnosticMap.put(factory, renderer) diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDiagnosticRenderer.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDiagnosticRenderer.kt index 8cb60dd1cf8..2473f08d754 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDiagnosticRenderer.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDiagnosticRenderer.kt @@ -60,3 +60,21 @@ class FirDiagnosticWithParameters3Renderer( ) } } + +class FirDiagnosticWithParameters4Renderer( + message: String, + private val rendererForA: DiagnosticParameterRenderer?, + private val rendererForB: DiagnosticParameterRenderer?, + private val rendererForC: DiagnosticParameterRenderer?, + private val rendererForD: DiagnosticParameterRenderer?, +) : AbstractFirDiagnosticWithParametersRenderer>(message) { + override fun renderParameters(diagnostic: FirDiagnosticWithParameters4<*, A, B, C, D>): Array { + val context = RenderingContext.of(diagnostic.a, diagnostic.b, diagnostic.c) + return arrayOf( + renderParameter(diagnostic.a, rendererForA, context), + renderParameter(diagnostic.b, rendererForB, context), + renderParameter(diagnostic.c, rendererForC, context), + renderParameter(diagnostic.d, rendererForD, context), + ) + } +} diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDiagnosticRenderers.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDiagnosticRenderers.kt index f70b7f099f7..118bdd56832 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDiagnosticRenderers.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDiagnosticRenderers.kt @@ -13,7 +13,10 @@ import org.jetbrains.kotlin.fir.FirRenderer import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.render import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol -import org.jetbrains.kotlin.fir.symbols.impl.* +import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol +import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol +import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol +import org.jetbrains.kotlin.fir.symbols.impl.FirVariableSymbol import org.jetbrains.kotlin.fir.types.ConeKotlinType import org.jetbrains.kotlin.fir.types.render @@ -105,4 +108,8 @@ object FirDiagnosticRenderers { "$list $branches or 'else' branch instead" } } + + val NOT_RENDERED = Renderer { + "" + } } diff --git a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/diagnostics/FirIdeDiagnosticReporter.kt b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/diagnostics/FirIdeDiagnosticReporter.kt index 43d2cd8a5c9..5e006d29b4b 100644 --- a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/diagnostics/FirIdeDiagnosticReporter.kt +++ b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/diagnostics/FirIdeDiagnosticReporter.kt @@ -57,6 +57,13 @@ private fun FirLightDiagnostic.toPsiDiagnostic(): FirPsiDiagnostic<*> { severity, factory as FirDiagnosticFactory3 ) + + is FirLightDiagnosticWithParameters4<*, *, *, *> -> FirPsiDiagnosticWithParameters4( + psiSourceElement, + a, b, c, d, + severity, + factory as FirDiagnosticFactory4 + ) else -> error("Unknown diagnostic type ${this::class.simpleName}") } } \ No newline at end of file diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtDiagnosticConverter.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtDiagnosticConverter.kt index 5c1e52a7872..476802d01c5 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtDiagnosticConverter.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtDiagnosticConverter.kt @@ -27,6 +27,10 @@ internal fun interface KtFirDiagnostic3Creator : KtFi fun KtFirAnalysisSession.create(diagnostic: FirDiagnosticWithParameters3<*, A, B, C>): KtFirDiagnostic<*> } +internal fun interface KtFirDiagnostic4Creator : KtFirDiagnosticCreator { + fun KtFirAnalysisSession.create(diagnostic: FirDiagnosticWithParameters4<*, A, B, C, D>): KtFirDiagnostic<*> +} + internal class KtDiagnosticConverter(private val conversions: Map, KtFirDiagnosticCreator>) { fun convert(analysisSession: KtFirAnalysisSession, diagnostic: FirDiagnostic<*>): KtFirDiagnostic<*> { val creator = conversions[diagnostic.factory] @@ -47,6 +51,9 @@ internal class KtDiagnosticConverter(private val conversions: Map -> with(creator as KtFirDiagnostic3Creator) { create(diagnostic as FirDiagnosticWithParameters3) } + is KtFirDiagnostic4Creator<*, *, *, *> -> with(creator as KtFirDiagnostic4Creator) { + create(diagnostic as FirDiagnosticWithParameters4) + } else -> error("Invalid KtFirDiagnosticCreator ${creator::class.simpleName}") } } @@ -72,6 +79,10 @@ internal class KtDiagnosticConverterBuilder private constructor() { conversions[diagnostic] = creator } + fun add(diagnostic: FirDiagnosticFactory4<*, A, B, C, D>, creator: KtFirDiagnostic4Creator) { + conversions[diagnostic] = creator + } + private fun build() = KtDiagnosticConverter(conversions) companion object {