[FIR] Introduce FirDiagnosticRenderers

This commit is contained in:
Dmitriy Novozhilov
2020-11-12 12:39:57 +03:00
parent ed0e5adce7
commit dc662efcf4
4 changed files with 112 additions and 16 deletions
@@ -127,6 +127,10 @@ class FirDefaultErrorMessages : DefaultErrorMessages.Extension {
}
companion object {
fun getRendererForDiagnostic(diagnostic: FirDiagnostic<*>): FirDiagnosticRenderer<*>? {
return MAP[diagnostic.factory]
}
// * - The old FE reports these diagnostics with additional parameters
// & - New diagnostic that has no analogues in the old FE
// + - Better message required
@@ -10,15 +10,15 @@ import org.jetbrains.kotlin.diagnostics.rendering.DiagnosticParameterRenderer
import org.jetbrains.kotlin.diagnostics.rendering.DiagnosticRenderer
class FirDiagnosticFactoryToRendererMap(val name: String) {
private val diagnosticsMap: MutableMap<AbstractFirDiagnosticFactory<*, *>, DiagnosticRenderer<*>> = mutableMapOf()
val psiDiagnosticMap: DiagnosticFactoryToRendererMap =
DiagnosticFactoryToRendererMap()
private val classicRenderersMap: MutableMap<AbstractFirDiagnosticFactory<*, *>, DiagnosticRenderer<*>> = mutableMapOf()
private val renderersMap: MutableMap<AbstractFirDiagnosticFactory<*, *>, FirDiagnosticRenderer<*>> = mutableMapOf()
val psiDiagnosticMap: DiagnosticFactoryToRendererMap = DiagnosticFactoryToRendererMap()
operator fun get(factory: AbstractFirDiagnosticFactory<*, *>): DiagnosticRenderer<*>? = diagnosticsMap[factory]
operator fun get(factory: AbstractFirDiagnosticFactory<*, *>): FirDiagnosticRenderer<*>? = renderersMap[factory]
fun getClassicRenderer(factory: AbstractFirDiagnosticFactory<*, *>): DiagnosticRenderer<*>? = classicRenderersMap[factory]
fun put(factory: FirDiagnosticFactory0<*, *>, message: String) {
psiDiagnosticMap.put(factory.psiDiagnosticFactory, message)
putToFirMap(factory)
put(factory, SimpleFirDiagnosticRenderer(message))
}
fun <A : Any> put(
@@ -26,8 +26,7 @@ class FirDiagnosticFactoryToRendererMap(val name: String) {
message: String,
rendererA: DiagnosticParameterRenderer<A>?
) {
psiDiagnosticMap.put(factory.psiDiagnosticFactory, message, rendererA)
putToFirMap(factory)
put(factory, FirDiagnosticWithParameters1Renderer(message, rendererA))
}
fun <A : Any, B : Any> put(
@@ -36,8 +35,7 @@ class FirDiagnosticFactoryToRendererMap(val name: String) {
rendererA: DiagnosticParameterRenderer<A>?,
rendererB: DiagnosticParameterRenderer<B>?
) {
psiDiagnosticMap.put(factory.psiDiagnosticFactory, message, rendererA, rendererB)
putToFirMap(factory)
put(factory, FirDiagnosticWithParameters2Renderer(message, rendererA, rendererB))
}
fun <A : Any, B : Any, C : Any> put(
@@ -47,13 +45,13 @@ class FirDiagnosticFactoryToRendererMap(val name: String) {
rendererB: DiagnosticParameterRenderer<B>?,
rendererC: DiagnosticParameterRenderer<C>?
) {
psiDiagnosticMap.put(factory.psiDiagnosticFactory, message, rendererA, rendererB, rendererC)
putToFirMap(factory)
put(factory, FirDiagnosticWithParameters3Renderer(message, rendererA, rendererB, rendererC))
}
private fun putToFirMap(factory: AbstractFirDiagnosticFactory<*, *>) {
psiDiagnosticMap[factory.psiDiagnosticFactory]?.let {
diagnosticsMap[factory] = it
}
private fun put(factory: AbstractFirDiagnosticFactory<*, *>, renderer: FirDiagnosticRenderer<*>) {
val classicRenderer = renderer.toClassicDiagnosticRenderer()
renderersMap[factory] = renderer
classicRenderersMap[factory] = classicRenderer
psiDiagnosticMap.put(factory.psiDiagnosticFactory, classicRenderer)
}
}
@@ -0,0 +1,89 @@
/*
* Copyright 2010-2020 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.*
import java.text.MessageFormat
sealed class FirDiagnosticRenderer<D : FirDiagnostic<*>> {
abstract fun render(diagnostic: D): String
abstract fun toClassicDiagnosticRenderer(): DiagnosticRenderer<*>
}
class SimpleFirDiagnosticRenderer(private val message: String) : FirDiagnosticRenderer<FirSimpleDiagnostic<*>>() {
override fun render(diagnostic: FirSimpleDiagnostic<*>): String {
return message
}
override fun toClassicDiagnosticRenderer(): DiagnosticRenderer<*> {
return SimpleDiagnosticRenderer(message)
}
}
sealed class AbstractFirDiagnosticWithParametersRenderer<D : FirDiagnostic<*>>(
protected val message: String
) : FirDiagnosticRenderer<D>() {
private val messageFormat = MessageFormat(message)
override fun render(diagnostic: D): String {
return messageFormat.format(renderParameters(diagnostic))
}
abstract fun renderParameters(diagnostic: D): Array<out Any>
}
class FirDiagnosticWithParameters1Renderer<A : Any>(
message: String,
private val rendererForA: DiagnosticParameterRenderer<A>?,
) : AbstractFirDiagnosticWithParametersRenderer<FirDiagnosticWithParameters1<*, A>>(message) {
override fun renderParameters(diagnostic: FirDiagnosticWithParameters1<*, A>): Array<out Any> {
val context = RenderingContext.of(diagnostic.a)
return arrayOf(renderParameter(diagnostic.a, rendererForA, context),)
}
override fun toClassicDiagnosticRenderer(): DiagnosticRenderer<*> {
return DiagnosticWithParameters1Renderer(message, rendererForA)
}
}
class FirDiagnosticWithParameters2Renderer<A : Any, B : Any>(
message: String,
private val rendererForA: DiagnosticParameterRenderer<A>?,
private val rendererForB: DiagnosticParameterRenderer<B>?,
) : AbstractFirDiagnosticWithParametersRenderer<FirDiagnosticWithParameters2<*, A, B>>(message) {
override fun renderParameters(diagnostic: FirDiagnosticWithParameters2<*, A, B>): Array<out Any> {
val context = RenderingContext.of(diagnostic.a, diagnostic.b)
return arrayOf(
renderParameter(diagnostic.a, rendererForA, context),
renderParameter(diagnostic.b, rendererForB, context),
)
}
override fun toClassicDiagnosticRenderer(): DiagnosticRenderer<*> {
return DiagnosticWithParameters2Renderer(message, rendererForA, rendererForB)
}
}
class FirDiagnosticWithParameters3Renderer<A : Any, B : Any, C : Any>(
message: String,
private val rendererForA: DiagnosticParameterRenderer<A>?,
private val rendererForB: DiagnosticParameterRenderer<B>?,
private val rendererForC: DiagnosticParameterRenderer<C>?,
) : AbstractFirDiagnosticWithParametersRenderer<FirDiagnosticWithParameters3<*, A, B, C>>(message) {
override fun renderParameters(diagnostic: FirDiagnosticWithParameters3<*, A, B, C>): Array<out Any> {
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),
)
}
override fun toClassicDiagnosticRenderer(): DiagnosticRenderer<*> {
return DiagnosticWithParameters3Renderer(message, rendererForA, rendererForB, rendererForC)
}
}
@@ -79,6 +79,11 @@ public final class DiagnosticFactoryToRendererMap {
map.put(factory, new DiagnosticWithParameters3Renderer<A, B, C>(message, rendererA, rendererB, rendererC));
}
public void put(@NotNull DiagnosticFactory<?> factory, @NotNull DiagnosticRenderer<?> renderer) {
checkMutability();
map.put(factory, renderer);
}
@Nullable
public DiagnosticRenderer<?> get(@NotNull DiagnosticFactory<?> factory) {
return map.get(factory);