Implement common Diagnostic(Factory/Renderer) in related FIR classes

This commit is contained in:
Mikhail Glukhikh
2020-11-17 12:22:13 +03:00
parent d47e16331c
commit 1795c4f3e5
36 changed files with 232 additions and 350 deletions
@@ -128,7 +128,7 @@ class AnalyzerWithCompilerReport(
psiElement: E, factory: DiagnosticFactory0<E>, val message: String psiElement: E, factory: DiagnosticFactory0<E>, val message: String
) : SimpleDiagnostic<E>(psiElement, factory, Severity.ERROR) { ) : SimpleDiagnostic<E>(psiElement, factory, Severity.ERROR) {
override fun isValid(): Boolean = true override val isValid: Boolean = true
} }
companion object { companion object {
@@ -28,9 +28,9 @@ class DefaultDiagnosticReporter(override val messageCollector: MessageCollector)
interface MessageCollectorBasedReporter : DiagnosticMessageReporter { interface MessageCollectorBasedReporter : DiagnosticMessageReporter {
val messageCollector: MessageCollector val messageCollector: MessageCollector
override fun report(diagnostic: Diagnostic, file: PsiFile, render: String) = messageCollector.report( override fun report(diagnostic: Diagnostic, file: PsiFile?, render: String) = messageCollector.report(
AnalyzerWithCompilerReport.convertSeverity(diagnostic.severity), AnalyzerWithCompilerReport.convertSeverity(diagnostic.severity),
render, render,
MessageUtil.psiFileToMessageLocation(file, file.name, DiagnosticUtils.getLineAndColumnRange(diagnostic)) MessageUtil.psiFileToMessageLocation(file!!, file.name, DiagnosticUtils.getLineAndColumnRange(diagnostic))
) )
} }
@@ -28,9 +28,9 @@ class DefaultDiagnosticReporter(override val messageCollector: MessageCollector)
interface MessageCollectorBasedReporter : DiagnosticMessageReporter { interface MessageCollectorBasedReporter : DiagnosticMessageReporter {
val messageCollector: MessageCollector val messageCollector: MessageCollector
override fun report(diagnostic: Diagnostic, file: PsiFile, render: String) = messageCollector.report( override fun report(diagnostic: Diagnostic, file: PsiFile?, render: String) = messageCollector.report(
AnalyzerWithCompilerReport.convertSeverity(diagnostic.severity), AnalyzerWithCompilerReport.convertSeverity(diagnostic.severity),
render, render,
MessageUtil.psiFileToMessageLocation(file, file.name, DiagnosticUtils.getLineAndColumn(diagnostic)) MessageUtil.psiFileToMessageLocation(file!!, file.name, DiagnosticUtils.getLineAndColumn(diagnostic))
) )
} }
@@ -20,5 +20,5 @@ import com.intellij.psi.PsiFile
import org.jetbrains.kotlin.diagnostics.Diagnostic import org.jetbrains.kotlin.diagnostics.Diagnostic
interface DiagnosticMessageReporter { interface DiagnosticMessageReporter {
fun report(diagnostic: Diagnostic, file: PsiFile, render: String) fun report(diagnostic: Diagnostic, file: PsiFile?, render: String)
} }
@@ -343,9 +343,7 @@ object KotlinToJVMBytecodeCompiler {
firAnalyzerFacade.runResolution() firAnalyzerFacade.runResolution()
val firDiagnostics = firAnalyzerFacade.runCheckers().values.flatten() val firDiagnostics = firAnalyzerFacade.runCheckers().values.flatten()
AnalyzerWithCompilerReport.reportDiagnostics( AnalyzerWithCompilerReport.reportDiagnostics(
SimpleDiagnostics( SimpleDiagnostics(firDiagnostics),
firDiagnostics.map { it.toRegularDiagnostic() }
),
environment.messageCollector environment.messageCollector
) )
performanceManager?.notifyAnalysisFinished() performanceManager?.notifyAnalysisFinished()
@@ -429,30 +427,6 @@ object KotlinToJVMBytecodeCompiler {
return writeOutputs(environment, projectConfiguration, chunk, outputs, mainClassFqName) return writeOutputs(environment, projectConfiguration, chunk, outputs, mainClassFqName)
} }
private fun FirDiagnostic<*>.toRegularDiagnostic(): Diagnostic {
val psiSource = element as FirPsiSourceElement<*>
@Suppress("UNCHECKED_CAST")
when (this) {
is FirSimpleDiagnostic ->
return SimpleDiagnostic(
psiSource.psi, factory.psiDiagnosticFactory as DiagnosticFactory0<PsiElement>, severity
)
is FirDiagnosticWithParameters1<*, *> ->
return DiagnosticWithParameters1(
psiSource.psi, this.a, factory.psiDiagnosticFactory as DiagnosticFactory1<PsiElement, Any>, severity
)
is FirDiagnosticWithParameters2<*, *, *> ->
return DiagnosticWithParameters2(
psiSource.psi, this.a, this.b, factory.psiDiagnosticFactory as DiagnosticFactory2<PsiElement, Any, Any>, severity
)
is FirDiagnosticWithParameters3<*, *, *, *> ->
return DiagnosticWithParameters3(
psiSource.psi, this.a, this.b, this.c,
factory.psiDiagnosticFactory as DiagnosticFactory3<PsiElement, Any, Any, Any>, severity
)
}
}
private fun getBuildFilePaths(buildFile: File?, sourceFilePaths: List<String>): List<String> = private fun getBuildFilePaths(buildFile: File?, sourceFilePaths: List<String>): List<String> =
if (buildFile == null) sourceFilePaths if (buildFile == null) sourceFilePaths
else sourceFilePaths.map { path -> else sourceFilePaths.map { path ->
@@ -129,7 +129,7 @@ class FirDefaultErrorMessages : DefaultErrorMessages.Extension {
companion object { companion object {
fun getRendererForDiagnostic(diagnostic: FirDiagnostic<*>): FirDiagnosticRenderer<*> { fun getRendererForDiagnostic(diagnostic: FirDiagnostic<*>): FirDiagnosticRenderer<*> {
val factory = diagnostic.factory val factory = diagnostic.factory
return MAP[factory] ?: factory.defaultRenderer return MAP[factory] ?: factory.firRenderer
} }
// * - The old FE reports these diagnostics with additional parameters // * - The old FE reports these diagnostics with additional parameters
@@ -5,7 +5,9 @@
package org.jetbrains.kotlin.fir.analysis.diagnostics package org.jetbrains.kotlin.fir.analysis.diagnostics
import com.intellij.openapi.util.TextRange
import com.intellij.psi.PsiElement import com.intellij.psi.PsiElement
import com.intellij.psi.PsiFile
import org.jetbrains.kotlin.diagnostics.Diagnostic import org.jetbrains.kotlin.diagnostics.Diagnostic
import org.jetbrains.kotlin.diagnostics.Severity import org.jetbrains.kotlin.diagnostics.Severity
import org.jetbrains.kotlin.fir.FirLightSourceElement import org.jetbrains.kotlin.fir.FirLightSourceElement
@@ -14,10 +16,16 @@ import org.jetbrains.kotlin.fir.FirSourceElement
// ------------------------------ diagnostics ------------------------------ // ------------------------------ diagnostics ------------------------------
sealed class FirDiagnostic<out E : FirSourceElement> { sealed class FirDiagnostic<out E : FirSourceElement> : Diagnostic {
abstract val element: E abstract val element: E
abstract val severity: Severity abstract override val severity: Severity
abstract val factory: AbstractFirDiagnosticFactory<*, *> abstract override val factory: AbstractFirDiagnosticFactory<*, *>
override val textRanges: List<TextRange>
get() = factory.getTextRanges(this)
override val isValid: Boolean
get() = true
} }
sealed class FirSimpleDiagnostic<out E : FirSourceElement> : FirDiagnostic<E>() { sealed class FirSimpleDiagnostic<out E : FirSourceElement> : FirDiagnostic<E>() {
@@ -44,31 +52,28 @@ sealed class FirDiagnosticWithParameters3<out E : FirSourceElement, A : Any, B :
// ------------------------------ psi diagnostics ------------------------------ // ------------------------------ psi diagnostics ------------------------------
interface FirPsiDiagnostic<P : PsiElement> { interface FirPsiDiagnostic<P : PsiElement> : Diagnostic {
fun asPsiBasedDiagnostic(): Diagnostic
val element: FirPsiSourceElement<P> val element: FirPsiSourceElement<P>
override val psiElement: PsiElement
get() = element.psi
override val psiFile: PsiFile
get() = psiElement.containingFile
} }
data class FirPsiSimpleDiagnostic<P : PsiElement>( data class FirPsiSimpleDiagnostic<P : PsiElement>(
override val element: FirPsiSourceElement<P>, override val element: FirPsiSourceElement<P>,
override val severity: Severity, override val severity: Severity,
override val factory: FirDiagnosticFactory0<FirPsiSourceElement<P>, P> override val factory: FirDiagnosticFactory0<FirPsiSourceElement<P>, P>
) : FirSimpleDiagnostic<FirPsiSourceElement<P>>(), FirPsiDiagnostic<P> { ) : FirSimpleDiagnostic<FirPsiSourceElement<P>>(), FirPsiDiagnostic<P>
override fun asPsiBasedDiagnostic(): Diagnostic {
return factory.psiDiagnosticFactory.on(element.psi)
}
}
data class FirPsiDiagnosticWithParameters1<P : PsiElement, A : Any>( data class FirPsiDiagnosticWithParameters1<P : PsiElement, A : Any>(
override val element: FirPsiSourceElement<P>, override val element: FirPsiSourceElement<P>,
override val a: A, override val a: A,
override val severity: Severity, override val severity: Severity,
override val factory: FirDiagnosticFactory1<FirPsiSourceElement<P>, P, A> override val factory: FirDiagnosticFactory1<FirPsiSourceElement<P>, P, A>
) : FirDiagnosticWithParameters1<FirPsiSourceElement<P>, A>(), FirPsiDiagnostic<P> { ) : FirDiagnosticWithParameters1<FirPsiSourceElement<P>, A>(), FirPsiDiagnostic<P>
override fun asPsiBasedDiagnostic(): Diagnostic {
return factory.psiDiagnosticFactory.on(element.psi, a)
}
}
data class FirPsiDiagnosticWithParameters2<P : PsiElement, A : Any, B : Any>( data class FirPsiDiagnosticWithParameters2<P : PsiElement, A : Any, B : Any>(
override val element: FirPsiSourceElement<P>, override val element: FirPsiSourceElement<P>,
@@ -76,11 +81,7 @@ data class FirPsiDiagnosticWithParameters2<P : PsiElement, A : Any, B : Any>(
override val b: B, override val b: B,
override val severity: Severity, override val severity: Severity,
override val factory: FirDiagnosticFactory2<FirPsiSourceElement<P>, P, A, B> override val factory: FirDiagnosticFactory2<FirPsiSourceElement<P>, P, A, B>
) : FirDiagnosticWithParameters2<FirPsiSourceElement<P>, A, B>(), FirPsiDiagnostic<P> { ) : FirDiagnosticWithParameters2<FirPsiSourceElement<P>, A, B>(), FirPsiDiagnostic<P>
override fun asPsiBasedDiagnostic(): Diagnostic {
return factory.psiDiagnosticFactory.on(element.psi, a, b)
}
}
data class FirPsiDiagnosticWithParameters3<P : PsiElement, A : Any, B : Any, C : Any>( data class FirPsiDiagnosticWithParameters3<P : PsiElement, A : Any, B : Any, C : Any>(
override val element: FirPsiSourceElement<P>, override val element: FirPsiSourceElement<P>,
@@ -89,16 +90,20 @@ data class FirPsiDiagnosticWithParameters3<P : PsiElement, A : Any, B : Any, C :
override val c: C, override val c: C,
override val severity: Severity, override val severity: Severity,
override val factory: FirDiagnosticFactory3<FirPsiSourceElement<P>, P, A, B, C> override val factory: FirDiagnosticFactory3<FirPsiSourceElement<P>, P, A, B, C>
) : FirDiagnosticWithParameters3<FirPsiSourceElement<P>, A, B, C>(), FirPsiDiagnostic<P> { ) : FirDiagnosticWithParameters3<FirPsiSourceElement<P>, A, B, C>(), FirPsiDiagnostic<P>
override fun asPsiBasedDiagnostic(): Diagnostic {
return factory.psiDiagnosticFactory.on(element.psi, a, b, c)
}
}
// ------------------------------ light tree diagnostics ------------------------------ // ------------------------------ light tree diagnostics ------------------------------
interface FirLightDiagnostic { interface FirLightDiagnostic : Diagnostic {
val element: FirLightSourceElement val element: FirLightSourceElement
override val psiElement: PsiElement
get() {
throw UnsupportedOperationException("Light diagnostic does not hold PSI element")
}
override val psiFile: PsiFile?
get() = null
} }
data class FirLightSimpleDiagnostic( data class FirLightSimpleDiagnostic(
@@ -10,39 +10,33 @@ package org.jetbrains.kotlin.fir.analysis.diagnostics
import com.intellij.openapi.util.TextRange import com.intellij.openapi.util.TextRange
import com.intellij.psi.PsiElement import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.diagnostics.* import org.jetbrains.kotlin.diagnostics.*
import org.jetbrains.kotlin.diagnostics.rendering.DiagnosticRenderer
import org.jetbrains.kotlin.fir.FirLightSourceElement import org.jetbrains.kotlin.fir.FirLightSourceElement
import org.jetbrains.kotlin.fir.FirPsiSourceElement import org.jetbrains.kotlin.fir.FirPsiSourceElement
import org.jetbrains.kotlin.fir.FirSourceElement import org.jetbrains.kotlin.fir.FirSourceElement
sealed class AbstractFirDiagnosticFactory<out E : FirSourceElement, D : FirDiagnostic<E>>( sealed class AbstractFirDiagnosticFactory<out E : FirSourceElement, D : FirDiagnostic<E>>(
val name: String, override var name: String?,
val severity: Severity, override val severity: Severity,
val positioningStrategy: LightTreePositioningStrategy, val positioningStrategy: LightTreePositioningStrategy,
) { ) : DiagnosticFactory<D>(name, severity) {
abstract val psiDiagnosticFactory: DiagnosticFactoryWithPsiElement<*, *> abstract val firRenderer: FirDiagnosticRenderer<D>
abstract val defaultRenderer: FirDiagnosticRenderer<*> override var defaultRenderer: DiagnosticRenderer<D>?
get() = firRenderer
set(_) {
}
fun getTextRanges(diagnostic: FirDiagnostic<*>): List<TextRange> = fun getTextRanges(diagnostic: FirDiagnostic<*>): List<TextRange> =
positioningStrategy.markDiagnostic(diagnostic) positioningStrategy.markDiagnostic(diagnostic)
override fun toString(): String {
return name
}
} }
class FirDiagnosticFactory0<E : FirSourceElement, P : PsiElement>( class FirDiagnosticFactory0<E : FirSourceElement, P : PsiElement>(
name: String, name: String,
severity: Severity, severity: Severity,
override val psiDiagnosticFactory: DiagnosticFactory0<P>,
positioningStrategy: LightTreePositioningStrategy = LightTreePositioningStrategy.DEFAULT, positioningStrategy: LightTreePositioningStrategy = LightTreePositioningStrategy.DEFAULT,
) : AbstractFirDiagnosticFactory<E, FirSimpleDiagnostic<E>>(name, severity, positioningStrategy) { ) : AbstractFirDiagnosticFactory<E, FirSimpleDiagnostic<E>>(name, severity, positioningStrategy) {
companion object { override val firRenderer: FirDiagnosticRenderer<FirSimpleDiagnostic<E>> = SimpleFirDiagnosticRenderer("")
private val DefaultRenderer = SimpleFirDiagnosticRenderer("")
}
override val defaultRenderer: FirDiagnosticRenderer<*>
get() = DefaultRenderer
fun on(element: E): FirSimpleDiagnostic<E> { fun on(element: E): FirSimpleDiagnostic<E> {
return when (element) { return when (element) {
@@ -58,18 +52,12 @@ class FirDiagnosticFactory0<E : FirSourceElement, P : PsiElement>(
class FirDiagnosticFactory1<E : FirSourceElement, P : PsiElement, A : Any>( class FirDiagnosticFactory1<E : FirSourceElement, P : PsiElement, A : Any>(
name: String, name: String,
severity: Severity, severity: Severity,
override val psiDiagnosticFactory: DiagnosticFactory1<P, A>,
positioningStrategy: LightTreePositioningStrategy = LightTreePositioningStrategy.DEFAULT, positioningStrategy: LightTreePositioningStrategy = LightTreePositioningStrategy.DEFAULT,
) : AbstractFirDiagnosticFactory<E, FirDiagnosticWithParameters1<E, A>>(name, severity, positioningStrategy) { ) : AbstractFirDiagnosticFactory<E, FirDiagnosticWithParameters1<E, A>>(name, severity, positioningStrategy) {
companion object { override val firRenderer: FirDiagnosticRenderer<FirDiagnosticWithParameters1<E, A>> = FirDiagnosticWithParameters1Renderer(
private val DefaultRenderer = FirDiagnosticWithParameters1Renderer( "{0}",
"{0}", FirDiagnosticRenderers.TO_STRING
FirDiagnosticRenderers.TO_STRING )
)
}
override val defaultRenderer: FirDiagnosticRenderer<*>
get() = DefaultRenderer
fun on(element: E, a: A): FirDiagnosticWithParameters1<E, A> { fun on(element: E, a: A): FirDiagnosticWithParameters1<E, A> {
return when (element) { return when (element) {
@@ -85,19 +73,13 @@ class FirDiagnosticFactory1<E : FirSourceElement, P : PsiElement, A : Any>(
class FirDiagnosticFactory2<E : FirSourceElement, P : PsiElement, A : Any, B : Any>( class FirDiagnosticFactory2<E : FirSourceElement, P : PsiElement, A : Any, B : Any>(
name: String, name: String,
severity: Severity, severity: Severity,
override val psiDiagnosticFactory: DiagnosticFactory2<P, A, B>,
positioningStrategy: LightTreePositioningStrategy = LightTreePositioningStrategy.DEFAULT, positioningStrategy: LightTreePositioningStrategy = LightTreePositioningStrategy.DEFAULT,
) : AbstractFirDiagnosticFactory<E, FirDiagnosticWithParameters2<E, A, B>>(name, severity, positioningStrategy) { ) : AbstractFirDiagnosticFactory<E, FirDiagnosticWithParameters2<E, A, B>>(name, severity, positioningStrategy) {
companion object { override val firRenderer: FirDiagnosticRenderer<FirDiagnosticWithParameters2<E, A, B>> = FirDiagnosticWithParameters2Renderer(
private val DefaultRenderer = FirDiagnosticWithParameters2Renderer( "{0}, {1}",
"{0}, {1}", FirDiagnosticRenderers.TO_STRING,
FirDiagnosticRenderers.TO_STRING, FirDiagnosticRenderers.TO_STRING
FirDiagnosticRenderers.TO_STRING )
)
}
override val defaultRenderer: FirDiagnosticRenderer<*>
get() = DefaultRenderer
fun on(element: E, a: A, b: B): FirDiagnosticWithParameters2<E, A, B> { fun on(element: E, a: A, b: B): FirDiagnosticWithParameters2<E, A, B> {
return when (element) { return when (element) {
@@ -113,20 +95,14 @@ class FirDiagnosticFactory2<E : FirSourceElement, P : PsiElement, A : Any, B : A
class FirDiagnosticFactory3<E : FirSourceElement, P : PsiElement, A : Any, B : Any, C : Any>( class FirDiagnosticFactory3<E : FirSourceElement, P : PsiElement, A : Any, B : Any, C : Any>(
name: String, name: String,
severity: Severity, severity: Severity,
override val psiDiagnosticFactory: DiagnosticFactory3<P, A, B, C>,
positioningStrategy: LightTreePositioningStrategy = LightTreePositioningStrategy.DEFAULT, positioningStrategy: LightTreePositioningStrategy = LightTreePositioningStrategy.DEFAULT,
) : AbstractFirDiagnosticFactory<E, FirDiagnosticWithParameters3<E, A, B, C>>(name, severity, positioningStrategy) { ) : AbstractFirDiagnosticFactory<E, FirDiagnosticWithParameters3<E, A, B, C>>(name, severity, positioningStrategy) {
companion object { override val firRenderer: FirDiagnosticRenderer<FirDiagnosticWithParameters3<E, A, B, C>> = FirDiagnosticWithParameters3Renderer(
private val DefaultRenderer = FirDiagnosticWithParameters3Renderer( "{0}, {1}, {2}",
"{0}, {1}, {2}", FirDiagnosticRenderers.TO_STRING,
FirDiagnosticRenderers.TO_STRING, FirDiagnosticRenderers.TO_STRING,
FirDiagnosticRenderers.TO_STRING, FirDiagnosticRenderers.TO_STRING
FirDiagnosticRenderers.TO_STRING )
)
}
override val defaultRenderer: FirDiagnosticRenderer<*>
get() = DefaultRenderer
fun on(element: E, a: A, b: B, c: C): FirDiagnosticWithParameters3<E, A, B, C> { fun on(element: E, a: A, b: B, c: C): FirDiagnosticWithParameters3<E, A, B, C> {
return when (element) { return when (element) {
@@ -147,7 +123,9 @@ fun <E : FirSourceElement, P : PsiElement> FirDiagnosticFactory0<E, P>.on(elemen
return element?.let { on(it) } return element?.let { on(it) }
} }
fun <E : FirSourceElement, P : PsiElement, A : Any> FirDiagnosticFactory1<E, P, A>.on(element: E?, a: A): FirDiagnosticWithParameters1<E, A>? { fun <E : FirSourceElement, P : PsiElement, A : Any> FirDiagnosticFactory1<E, P, A>.on(
element: E?, a: A
): FirDiagnosticWithParameters1<E, A>? {
return element?.let { on(it, a) } return element?.let { on(it, a) }
} }
@@ -12,112 +12,88 @@ import kotlin.properties.ReadOnlyProperty
import kotlin.reflect.KProperty import kotlin.reflect.KProperty
fun <E : FirSourceElement, P : PsiElement> warning0(): DiagnosticFactory0DelegateProvider<E, P> { fun <E : FirSourceElement, P : PsiElement> warning0(): DiagnosticFactory0DelegateProvider<E, P> {
return DiagnosticFactory0DelegateProvider(Severity.WARNING, null) return DiagnosticFactory0DelegateProvider(Severity.WARNING)
} }
fun <E : FirSourceElement, P : PsiElement, A : Any> warning1(): DiagnosticFactory1DelegateProvider<E, P, A> { fun <E : FirSourceElement, P : PsiElement, A : Any> warning1(): DiagnosticFactory1DelegateProvider<E, P, A> {
return DiagnosticFactory1DelegateProvider(Severity.WARNING, null) return DiagnosticFactory1DelegateProvider(Severity.WARNING)
} }
fun <E : FirSourceElement, P : PsiElement, A : Any, B : Any> warning2(): DiagnosticFactory2DelegateProvider<E, P, A, B> { fun <E : FirSourceElement, P : PsiElement, A : Any, B : Any> warning2(): DiagnosticFactory2DelegateProvider<E, P, A, B> {
return DiagnosticFactory2DelegateProvider(Severity.WARNING, null) return DiagnosticFactory2DelegateProvider(Severity.WARNING)
} }
fun <E : FirSourceElement, P : PsiElement, A : Any, B : Any, C : Any> warning3(): DiagnosticFactory3DelegateProvider<E, P, A, B, C> { fun <E : FirSourceElement, P : PsiElement, A : Any, B : Any, C : Any> warning3(): DiagnosticFactory3DelegateProvider<E, P, A, B, C> {
return DiagnosticFactory3DelegateProvider(Severity.WARNING, null) return DiagnosticFactory3DelegateProvider(Severity.WARNING)
} }
fun <E : FirSourceElement, P : PsiElement> error0(): DiagnosticFactory0DelegateProvider<E, P> { fun <E : FirSourceElement, P : PsiElement> error0(): DiagnosticFactory0DelegateProvider<E, P> {
return DiagnosticFactory0DelegateProvider(Severity.ERROR, null) return DiagnosticFactory0DelegateProvider(Severity.ERROR)
} }
fun <E : FirSourceElement, P : PsiElement, A : Any> error1(): DiagnosticFactory1DelegateProvider<E, P, A> { fun <E : FirSourceElement, P : PsiElement, A : Any> error1(): DiagnosticFactory1DelegateProvider<E, P, A> {
return DiagnosticFactory1DelegateProvider(Severity.ERROR, null) return DiagnosticFactory1DelegateProvider(Severity.ERROR)
} }
fun <E : FirSourceElement, P : PsiElement, A : Any, B : Any> error2(): DiagnosticFactory2DelegateProvider<E, P, A, B> { fun <E : FirSourceElement, P : PsiElement, A : Any, B : Any> error2(): DiagnosticFactory2DelegateProvider<E, P, A, B> {
return DiagnosticFactory2DelegateProvider(Severity.ERROR, null) return DiagnosticFactory2DelegateProvider(Severity.ERROR)
} }
fun <E : FirSourceElement, P : PsiElement, A : Any, B : Any, C : Any> error3(): DiagnosticFactory3DelegateProvider<E, P, A, B, C> { fun <E : FirSourceElement, P : PsiElement, A : Any, B : Any, C : Any> error3(): DiagnosticFactory3DelegateProvider<E, P, A, B, C> {
return DiagnosticFactory3DelegateProvider(Severity.ERROR, null) return DiagnosticFactory3DelegateProvider(Severity.ERROR)
} }
/** /**
* Note that those functions can be applicable only for factories * Note that those functions can be applicable only for factories
* that takes `PsiElement` as first type parameter * that takes `PsiElement` as first type parameter
*/ */
fun <E : FirSourceElement, P : PsiElement> existing( fun <E : FirSourceElement, P : PsiElement> existing0(): DiagnosticFactory0DelegateProvider<E, P> {
psiDiagnosticFactory: DiagnosticFactory0<P> return DiagnosticFactory0DelegateProvider(Severity.ERROR)
): DiagnosticFactory0DelegateProvider<E, P> {
return DiagnosticFactory0DelegateProvider(Severity.ERROR, psiDiagnosticFactory)
} }
fun <E : FirSourceElement, P : PsiElement, A : Any> existing( fun <E : FirSourceElement, P : PsiElement, A : Any> existing1(): DiagnosticFactory1DelegateProvider<E, P, A> {
psiDiagnosticFactory: DiagnosticFactory1<P, A> return DiagnosticFactory1DelegateProvider(Severity.ERROR)
): DiagnosticFactory1DelegateProvider<E, P, A> {
return DiagnosticFactory1DelegateProvider(Severity.ERROR, psiDiagnosticFactory)
} }
fun <E : FirSourceElement, P : PsiElement, A : Any, B : Any> existing( fun <E : FirSourceElement, P : PsiElement, A : Any, B : Any> existing2(): DiagnosticFactory2DelegateProvider<E, P, A, B> {
psiDiagnosticFactory: DiagnosticFactory2<P, A, B> return DiagnosticFactory2DelegateProvider(Severity.ERROR)
): DiagnosticFactory2DelegateProvider<E, P, A, B> {
return DiagnosticFactory2DelegateProvider(Severity.ERROR, psiDiagnosticFactory)
} }
fun <E : FirSourceElement, P : PsiElement, A : Any, B : Any, C : Any> existing( fun <E : FirSourceElement, P : PsiElement, A : Any, B : Any, C : Any> existing3(): DiagnosticFactory3DelegateProvider<E, P, A, B, C> {
psiDiagnosticFactory: DiagnosticFactory3<P, A, B, C> return DiagnosticFactory3DelegateProvider(Severity.ERROR)
): DiagnosticFactory3DelegateProvider<E, P, A, B, C> {
return DiagnosticFactory3DelegateProvider(Severity.ERROR, psiDiagnosticFactory)
} }
// ------------------------------ Providers ------------------------------ // ------------------------------ Providers ------------------------------
class DiagnosticFactory0DelegateProvider<E : FirSourceElement, P : PsiElement>( class DiagnosticFactory0DelegateProvider<E : FirSourceElement, P : PsiElement>(
private val severity: Severity, private val severity: Severity
private val psiDiagnosticFactory: DiagnosticFactory0<P>?
) { ) {
operator fun provideDelegate(thisRef: Any?, prop: KProperty<*>): ReadOnlyProperty<Any?, FirDiagnosticFactory0<E, P>> { operator fun provideDelegate(thisRef: Any?, prop: KProperty<*>): ReadOnlyProperty<Any?, FirDiagnosticFactory0<E, P>> {
val psiFactory = psiDiagnosticFactory ?: DiagnosticFactory0.create<P>(severity).apply { return DummyDelegate(FirDiagnosticFactory0(prop.name, severity))
initializeName(prop.name)
}
return DummyDelegate(FirDiagnosticFactory0(prop.name, severity, psiFactory))
} }
} }
class DiagnosticFactory1DelegateProvider<E : FirSourceElement, P : PsiElement, A : Any>( class DiagnosticFactory1DelegateProvider<E : FirSourceElement, P : PsiElement, A : Any>(
private val severity: Severity, private val severity: Severity
private val psiDiagnosticFactory: DiagnosticFactory1<P, A>?
) { ) {
operator fun provideDelegate(thisRef: Any?, prop: KProperty<*>): ReadOnlyProperty<Any?, FirDiagnosticFactory1<E, P, A>> { operator fun provideDelegate(thisRef: Any?, prop: KProperty<*>): ReadOnlyProperty<Any?, FirDiagnosticFactory1<E, P, A>> {
val psiFactory = psiDiagnosticFactory ?: DiagnosticFactory1.create<P, A>(severity).apply { return DummyDelegate(FirDiagnosticFactory1(prop.name, severity))
initializeName(prop.name)
}
return DummyDelegate(FirDiagnosticFactory1(prop.name, severity, psiFactory))
} }
} }
class DiagnosticFactory2DelegateProvider<E : FirSourceElement, P : PsiElement, A : Any, B : Any>( class DiagnosticFactory2DelegateProvider<E : FirSourceElement, P : PsiElement, A : Any, B : Any>(
private val severity: Severity, private val severity: Severity
private val psiDiagnosticFactory: DiagnosticFactory2<P, A, B>?
) { ) {
operator fun provideDelegate(thisRef: Any?, prop: KProperty<*>): ReadOnlyProperty<Any?, FirDiagnosticFactory2<E, P, A, B>> { operator fun provideDelegate(thisRef: Any?, prop: KProperty<*>): ReadOnlyProperty<Any?, FirDiagnosticFactory2<E, P, A, B>> {
val psiFactory = psiDiagnosticFactory ?: DiagnosticFactory2.create<P, A, B>(severity).apply { return DummyDelegate(FirDiagnosticFactory2(prop.name, severity))
initializeName(prop.name)
}
return DummyDelegate(FirDiagnosticFactory2(prop.name, severity, psiFactory))
} }
} }
class DiagnosticFactory3DelegateProvider<E : FirSourceElement, P : PsiElement, A : Any, B : Any, C : Any>( class DiagnosticFactory3DelegateProvider<E : FirSourceElement, P : PsiElement, A : Any, B : Any, C : Any>(
private val severity: Severity, private val severity: Severity
private val psiDiagnosticFactory: DiagnosticFactory3<P, A, B, C>?
) { ) {
operator fun provideDelegate(thisRef: Any?, prop: KProperty<*>): ReadOnlyProperty<Any?, FirDiagnosticFactory3<E, P, A, B, C>> { operator fun provideDelegate(thisRef: Any?, prop: KProperty<*>): ReadOnlyProperty<Any?, FirDiagnosticFactory3<E, P, A, B, C>> {
val psiFactory = psiDiagnosticFactory ?: DiagnosticFactory3.create<P, A, B, C>(severity).apply { return DummyDelegate(FirDiagnosticFactory3(prop.name, severity))
initializeName(prop.name)
}
return DummyDelegate(FirDiagnosticFactory3(prop.name, severity, psiFactory))
} }
} }
@@ -7,51 +7,47 @@ package org.jetbrains.kotlin.fir.analysis.diagnostics
import org.jetbrains.kotlin.diagnostics.rendering.DiagnosticFactoryToRendererMap import org.jetbrains.kotlin.diagnostics.rendering.DiagnosticFactoryToRendererMap
import org.jetbrains.kotlin.diagnostics.rendering.DiagnosticParameterRenderer import org.jetbrains.kotlin.diagnostics.rendering.DiagnosticParameterRenderer
import org.jetbrains.kotlin.diagnostics.rendering.DiagnosticRenderer import org.jetbrains.kotlin.fir.FirSourceElement
class FirDiagnosticFactoryToRendererMap(val name: String) { class FirDiagnosticFactoryToRendererMap(val name: String) {
private val classicRenderersMap: MutableMap<AbstractFirDiagnosticFactory<*, *>, DiagnosticRenderer<*>> = mutableMapOf()
private val renderersMap: MutableMap<AbstractFirDiagnosticFactory<*, *>, FirDiagnosticRenderer<*>> = mutableMapOf() private val renderersMap: MutableMap<AbstractFirDiagnosticFactory<*, *>, FirDiagnosticRenderer<*>> = mutableMapOf()
val psiDiagnosticMap: DiagnosticFactoryToRendererMap = DiagnosticFactoryToRendererMap() val psiDiagnosticMap: DiagnosticFactoryToRendererMap = DiagnosticFactoryToRendererMap()
operator fun get(factory: AbstractFirDiagnosticFactory<*, *>): FirDiagnosticRenderer<*>? = renderersMap[factory] operator fun get(factory: AbstractFirDiagnosticFactory<*, *>): FirDiagnosticRenderer<*>? = renderersMap[factory]
fun getClassicRenderer(factory: AbstractFirDiagnosticFactory<*, *>): DiagnosticRenderer<*>? = classicRenderersMap[factory]
fun put(factory: FirDiagnosticFactory0<*, *>, message: String) { fun <E : FirSourceElement> put(factory: FirDiagnosticFactory0<E, *>, message: String) {
put(factory, SimpleFirDiagnosticRenderer(message)) put(factory, SimpleFirDiagnosticRenderer<E>(message))
} }
fun <A : Any> put( fun <E : FirSourceElement, A : Any> put(
factory: FirDiagnosticFactory1<*, *, A>, factory: FirDiagnosticFactory1<E, *, A>,
message: String, message: String,
rendererA: DiagnosticParameterRenderer<A>? rendererA: DiagnosticParameterRenderer<A>?
) { ) {
put(factory, FirDiagnosticWithParameters1Renderer(message, rendererA)) put(factory, FirDiagnosticWithParameters1Renderer<E, A>(message, rendererA))
} }
fun <A : Any, B : Any> put( fun <E : FirSourceElement, A : Any, B : Any> put(
factory: FirDiagnosticFactory2<*, *, A, B>, factory: FirDiagnosticFactory2<E, *, A, B>,
message: String, message: String,
rendererA: DiagnosticParameterRenderer<A>?, rendererA: DiagnosticParameterRenderer<A>?,
rendererB: DiagnosticParameterRenderer<B>? rendererB: DiagnosticParameterRenderer<B>?
) { ) {
put(factory, FirDiagnosticWithParameters2Renderer(message, rendererA, rendererB)) put(factory, FirDiagnosticWithParameters2Renderer<E, A, B>(message, rendererA, rendererB))
} }
fun <A : Any, B : Any, C : Any> put( fun <E : FirSourceElement, A : Any, B : Any, C : Any> put(
factory: FirDiagnosticFactory3<*, *, A, B, C>, factory: FirDiagnosticFactory3<E, *, A, B, C>,
message: String, message: String,
rendererA: DiagnosticParameterRenderer<A>?, rendererA: DiagnosticParameterRenderer<A>?,
rendererB: DiagnosticParameterRenderer<B>?, rendererB: DiagnosticParameterRenderer<B>?,
rendererC: DiagnosticParameterRenderer<C>? rendererC: DiagnosticParameterRenderer<C>?
) { ) {
put(factory, FirDiagnosticWithParameters3Renderer(message, rendererA, rendererB, rendererC)) put(factory, FirDiagnosticWithParameters3Renderer<E, A, B, C>(message, rendererA, rendererB, rendererC))
} }
private fun put(factory: AbstractFirDiagnosticFactory<*, *>, renderer: FirDiagnosticRenderer<*>) { private fun put(factory: AbstractFirDiagnosticFactory<*, *>, renderer: FirDiagnosticRenderer<*>) {
val classicRenderer = renderer.toClassicDiagnosticRenderer()
renderersMap[factory] = renderer renderersMap[factory] = renderer
classicRenderersMap[factory] = classicRenderer psiDiagnosticMap.put(factory, renderer)
psiDiagnosticMap.put(factory.psiDiagnosticFactory, classicRenderer)
} }
} }
@@ -6,22 +6,17 @@
package org.jetbrains.kotlin.fir.analysis.diagnostics package org.jetbrains.kotlin.fir.analysis.diagnostics
import org.jetbrains.kotlin.diagnostics.rendering.* import org.jetbrains.kotlin.diagnostics.rendering.*
import org.jetbrains.kotlin.fir.FirSourceElement
import java.text.MessageFormat import java.text.MessageFormat
sealed class FirDiagnosticRenderer<D : FirDiagnostic<*>> { sealed class FirDiagnosticRenderer<D : FirDiagnostic<*>> : DiagnosticRenderer<D> {
abstract fun render(diagnostic: D): String abstract override fun render(diagnostic: D): String
abstract fun toClassicDiagnosticRenderer(): DiagnosticRenderer<*>
} }
class SimpleFirDiagnosticRenderer(private val message: String) : FirDiagnosticRenderer<FirSimpleDiagnostic<*>>() { class SimpleFirDiagnosticRenderer<E : FirSourceElement>(private val message: String) : FirDiagnosticRenderer<FirSimpleDiagnostic<E>>() {
override fun render(diagnostic: FirSimpleDiagnostic<*>): String { override fun render(diagnostic: FirSimpleDiagnostic<E>): String {
return message return message
} }
override fun toClassicDiagnosticRenderer(): DiagnosticRenderer<*> {
return SimpleDiagnosticRenderer(message)
}
} }
sealed class AbstractFirDiagnosticWithParametersRenderer<D : FirDiagnostic<*>>( sealed class AbstractFirDiagnosticWithParametersRenderer<D : FirDiagnostic<*>>(
@@ -36,45 +31,37 @@ sealed class AbstractFirDiagnosticWithParametersRenderer<D : FirDiagnostic<*>>(
abstract fun renderParameters(diagnostic: D): Array<out Any> abstract fun renderParameters(diagnostic: D): Array<out Any>
} }
class FirDiagnosticWithParameters1Renderer<A : Any>( class FirDiagnosticWithParameters1Renderer<E : FirSourceElement, A : Any>(
message: String, message: String,
private val rendererForA: DiagnosticParameterRenderer<A>?, private val rendererForA: DiagnosticParameterRenderer<A>?,
) : AbstractFirDiagnosticWithParametersRenderer<FirDiagnosticWithParameters1<*, A>>(message) { ) : AbstractFirDiagnosticWithParametersRenderer<FirDiagnosticWithParameters1<E, A>>(message) {
override fun renderParameters(diagnostic: FirDiagnosticWithParameters1<*, A>): Array<out Any> { override fun renderParameters(diagnostic: FirDiagnosticWithParameters1<E, A>): Array<out Any> {
val context = RenderingContext.of(diagnostic.a) val context = RenderingContext.of(diagnostic.a)
return arrayOf(renderParameter(diagnostic.a, rendererForA, context),) return arrayOf(renderParameter(diagnostic.a, rendererForA, context))
}
override fun toClassicDiagnosticRenderer(): DiagnosticRenderer<*> {
return DiagnosticWithParameters1Renderer(message, rendererForA)
} }
} }
class FirDiagnosticWithParameters2Renderer<A : Any, B : Any>( class FirDiagnosticWithParameters2Renderer<E : FirSourceElement, A : Any, B : Any>(
message: String, message: String,
private val rendererForA: DiagnosticParameterRenderer<A>?, private val rendererForA: DiagnosticParameterRenderer<A>?,
private val rendererForB: DiagnosticParameterRenderer<B>?, private val rendererForB: DiagnosticParameterRenderer<B>?,
) : AbstractFirDiagnosticWithParametersRenderer<FirDiagnosticWithParameters2<*, A, B>>(message) { ) : AbstractFirDiagnosticWithParametersRenderer<FirDiagnosticWithParameters2<E, A, B>>(message) {
override fun renderParameters(diagnostic: FirDiagnosticWithParameters2<*, A, B>): Array<out Any> { override fun renderParameters(diagnostic: FirDiagnosticWithParameters2<E, A, B>): Array<out Any> {
val context = RenderingContext.of(diagnostic.a, diagnostic.b) val context = RenderingContext.of(diagnostic.a, diagnostic.b)
return arrayOf( return arrayOf(
renderParameter(diagnostic.a, rendererForA, context), renderParameter(diagnostic.a, rendererForA, context),
renderParameter(diagnostic.b, rendererForB, context), renderParameter(diagnostic.b, rendererForB, context),
) )
} }
override fun toClassicDiagnosticRenderer(): DiagnosticRenderer<*> {
return DiagnosticWithParameters2Renderer(message, rendererForA, rendererForB)
}
} }
class FirDiagnosticWithParameters3Renderer<A : Any, B : Any, C : Any>( class FirDiagnosticWithParameters3Renderer<E : FirSourceElement, A : Any, B : Any, C : Any>(
message: String, message: String,
private val rendererForA: DiagnosticParameterRenderer<A>?, private val rendererForA: DiagnosticParameterRenderer<A>?,
private val rendererForB: DiagnosticParameterRenderer<B>?, private val rendererForB: DiagnosticParameterRenderer<B>?,
private val rendererForC: DiagnosticParameterRenderer<C>?, private val rendererForC: DiagnosticParameterRenderer<C>?,
) : AbstractFirDiagnosticWithParametersRenderer<FirDiagnosticWithParameters3<*, A, B, C>>(message) { ) : AbstractFirDiagnosticWithParametersRenderer<FirDiagnosticWithParameters3<E, A, B, C>>(message) {
override fun renderParameters(diagnostic: FirDiagnosticWithParameters3<*, A, B, C>): Array<out Any> { override fun renderParameters(diagnostic: FirDiagnosticWithParameters3<E, A, B, C>): Array<out Any> {
val context = RenderingContext.of(diagnostic.a, diagnostic.b, diagnostic.c) val context = RenderingContext.of(diagnostic.a, diagnostic.b, diagnostic.c)
return arrayOf( return arrayOf(
renderParameter(diagnostic.a, rendererForA, context), renderParameter(diagnostic.a, rendererForA, context),
@@ -82,8 +69,4 @@ class FirDiagnosticWithParameters3Renderer<A : Any, B : Any, C : Any>(
renderParameter(diagnostic.c, rendererForC, context), renderParameter(diagnostic.c, rendererForC, context),
) )
} }
override fun toClassicDiagnosticRenderer(): DiagnosticRenderer<*> {
return DiagnosticWithParameters3Renderer(message, rendererForA, rendererForB, rendererForC)
}
} }
@@ -8,7 +8,6 @@ package org.jetbrains.kotlin.fir.analysis.diagnostics
import com.intellij.psi.PsiElement import com.intellij.psi.PsiElement
import com.intellij.psi.PsiTypeElement import com.intellij.psi.PsiTypeElement
import org.jetbrains.kotlin.contracts.description.EventOccurrencesRange import org.jetbrains.kotlin.contracts.description.EventOccurrencesRange
import org.jetbrains.kotlin.diagnostics.Errors
import org.jetbrains.kotlin.fir.FirEffectiveVisibility import org.jetbrains.kotlin.fir.FirEffectiveVisibility
import org.jetbrains.kotlin.fir.FirSourceElement import org.jetbrains.kotlin.fir.FirSourceElement
import org.jetbrains.kotlin.fir.declarations.FirClass import org.jetbrains.kotlin.fir.declarations.FirClass
@@ -67,10 +66,10 @@ object FirErrors {
val SEALED_SUPERTYPE_IN_LOCAL_CLASS by error0<FirSourceElement, PsiElement>() val SEALED_SUPERTYPE_IN_LOCAL_CLASS by error0<FirSourceElement, PsiElement>()
// Constructor problems // Constructor problems
val CONSTRUCTOR_IN_OBJECT by existing<FirSourceElement, KtDeclaration>(Errors.CONSTRUCTOR_IN_OBJECT) val CONSTRUCTOR_IN_OBJECT by existing0<FirSourceElement, KtDeclaration>()
val CONSTRUCTOR_IN_INTERFACE by existing<FirSourceElement, KtDeclaration>(Errors.CONSTRUCTOR_IN_INTERFACE) val CONSTRUCTOR_IN_INTERFACE by existing0<FirSourceElement, KtDeclaration>()
val NON_PRIVATE_CONSTRUCTOR_IN_ENUM by existing<FirSourceElement, PsiElement>(Errors.NON_PRIVATE_CONSTRUCTOR_IN_ENUM) val NON_PRIVATE_CONSTRUCTOR_IN_ENUM by existing0<FirSourceElement, PsiElement>()
val NON_PRIVATE_CONSTRUCTOR_IN_SEALED by existing<FirSourceElement, PsiElement>(Errors.NON_PRIVATE_CONSTRUCTOR_IN_SEALED) val NON_PRIVATE_CONSTRUCTOR_IN_SEALED by existing0<FirSourceElement, PsiElement>()
val CYCLIC_CONSTRUCTOR_DELEGATION_CALL by warning0<FirSourceElement, PsiElement>() val CYCLIC_CONSTRUCTOR_DELEGATION_CALL by warning0<FirSourceElement, PsiElement>()
val PRIMARY_CONSTRUCTOR_DELEGATION_CALL_EXPECTED by warning0<FirSourceElement, PsiElement>() val PRIMARY_CONSTRUCTOR_DELEGATION_CALL_EXPECTED by warning0<FirSourceElement, PsiElement>()
val SUPERTYPE_INITIALIZED_WITHOUT_PRIMARY_CONSTRUCTOR by warning0<FirSourceElement, PsiElement>() val SUPERTYPE_INITIALIZED_WITHOUT_PRIMARY_CONSTRUCTOR by warning0<FirSourceElement, PsiElement>()
@@ -80,19 +79,19 @@ object FirErrors {
val SEALED_CLASS_CONSTRUCTOR_CALL by error0<FirSourceElement, PsiElement>() val SEALED_CLASS_CONSTRUCTOR_CALL by error0<FirSourceElement, PsiElement>()
// Annotations // Annotations
val ANNOTATION_ARGUMENT_KCLASS_LITERAL_OF_TYPE_PARAMETER_ERROR by existing<FirSourceElement, KtExpression>(Errors.ANNOTATION_ARGUMENT_KCLASS_LITERAL_OF_TYPE_PARAMETER_ERROR) val ANNOTATION_ARGUMENT_KCLASS_LITERAL_OF_TYPE_PARAMETER_ERROR by existing0<FirSourceElement, KtExpression>()
val ANNOTATION_ARGUMENT_MUST_BE_CONST by existing<FirSourceElement, KtExpression>(Errors.ANNOTATION_ARGUMENT_MUST_BE_CONST) val ANNOTATION_ARGUMENT_MUST_BE_CONST by existing0<FirSourceElement, KtExpression>()
val ANNOTATION_ARGUMENT_MUST_BE_ENUM_CONST by existing<FirSourceElement, KtExpression>(Errors.ANNOTATION_ARGUMENT_MUST_BE_ENUM_CONST) val ANNOTATION_ARGUMENT_MUST_BE_ENUM_CONST by existing0<FirSourceElement, KtExpression>()
val ANNOTATION_ARGUMENT_MUST_BE_KCLASS_LITERAL by existing<FirSourceElement, KtExpression>(Errors.ANNOTATION_ARGUMENT_MUST_BE_KCLASS_LITERAL) val ANNOTATION_ARGUMENT_MUST_BE_KCLASS_LITERAL by existing0<FirSourceElement, KtExpression>()
val ANNOTATION_CLASS_MEMBER by existing<FirSourceElement, PsiElement>(Errors.ANNOTATION_CLASS_MEMBER) val ANNOTATION_CLASS_MEMBER by existing0<FirSourceElement, PsiElement>()
val ANNOTATION_PARAMETER_DEFAULT_VALUE_MUST_BE_CONSTANT by existing<FirSourceElement, KtExpression>(Errors.ANNOTATION_PARAMETER_DEFAULT_VALUE_MUST_BE_CONSTANT) val ANNOTATION_PARAMETER_DEFAULT_VALUE_MUST_BE_CONSTANT by existing0<FirSourceElement, KtExpression>()
val INVALID_TYPE_OF_ANNOTATION_MEMBER by existing<FirSourceElement, KtTypeReference>(Errors.INVALID_TYPE_OF_ANNOTATION_MEMBER) val INVALID_TYPE_OF_ANNOTATION_MEMBER by existing0<FirSourceElement, KtTypeReference>()
val LOCAL_ANNOTATION_CLASS_ERROR by existing<FirSourceElement, KtClassOrObject>(Errors.LOCAL_ANNOTATION_CLASS_ERROR) val LOCAL_ANNOTATION_CLASS_ERROR by existing0<FirSourceElement, KtClassOrObject>()
val MISSING_VAL_ON_ANNOTATION_PARAMETER by existing<FirSourceElement, KtParameter>(Errors.MISSING_VAL_ON_ANNOTATION_PARAMETER) val MISSING_VAL_ON_ANNOTATION_PARAMETER by existing0<FirSourceElement, KtParameter>()
val NON_CONST_VAL_USED_IN_CONSTANT_EXPRESSION by existing<FirSourceElement, KtExpression>(Errors.NON_CONST_VAL_USED_IN_CONSTANT_EXPRESSION) val NON_CONST_VAL_USED_IN_CONSTANT_EXPRESSION by existing0<FirSourceElement, KtExpression>()
val NOT_AN_ANNOTATION_CLASS by error1<FirSourceElement, PsiElement, String>() val NOT_AN_ANNOTATION_CLASS by error1<FirSourceElement, PsiElement, String>()
val NULLABLE_TYPE_OF_ANNOTATION_MEMBER by existing<FirSourceElement, KtTypeReference>(Errors.NULLABLE_TYPE_OF_ANNOTATION_MEMBER) val NULLABLE_TYPE_OF_ANNOTATION_MEMBER by existing0<FirSourceElement, KtTypeReference>()
val VAR_ANNOTATION_PARAMETER by existing<FirSourceElement, KtParameter>(Errors.VAR_ANNOTATION_PARAMETER) val VAR_ANNOTATION_PARAMETER by existing0<FirSourceElement, KtParameter>()
// Exposed visibility group // Exposed visibility group
val EXPOSED_TYPEALIAS_EXPANDED_TYPE by error3<FirSourceElement, PsiElement, FirEffectiveVisibility, FirMemberDeclaration, FirEffectiveVisibility>() val EXPOSED_TYPEALIAS_EXPANDED_TYPE by error3<FirSourceElement, PsiElement, FirEffectiveVisibility, FirMemberDeclaration, FirEffectiveVisibility>()
@@ -105,7 +104,7 @@ object FirErrors {
val EXPOSED_TYPE_PARAMETER_BOUND by error3<FirSourceElement, KtTypeParameter, FirEffectiveVisibility, FirMemberDeclaration, FirEffectiveVisibility>() val EXPOSED_TYPE_PARAMETER_BOUND by error3<FirSourceElement, KtTypeParameter, FirEffectiveVisibility, FirMemberDeclaration, FirEffectiveVisibility>()
// Modifiers // Modifiers
val INAPPLICABLE_INFIX_MODIFIER by existing<FirSourceElement, PsiElement, String>(Errors.INAPPLICABLE_INFIX_MODIFIER) val INAPPLICABLE_INFIX_MODIFIER by existing1<FirSourceElement, PsiElement, String>()
val REPEATED_MODIFIER by error1<FirSourceElement, PsiElement, KtModifierKeywordToken>() val REPEATED_MODIFIER by error1<FirSourceElement, PsiElement, KtModifierKeywordToken>()
val REDUNDANT_MODIFIER by error2<FirSourceElement, PsiElement, KtModifierKeywordToken, KtModifierKeywordToken>() val REDUNDANT_MODIFIER by error2<FirSourceElement, PsiElement, KtModifierKeywordToken, KtModifierKeywordToken>()
val DEPRECATED_MODIFIER_PAIR by error2<FirSourceElement, PsiElement, KtModifierKeywordToken, KtModifierKeywordToken>() val DEPRECATED_MODIFIER_PAIR by error2<FirSourceElement, PsiElement, KtModifierKeywordToken, KtModifierKeywordToken>()
@@ -184,7 +184,8 @@ sealed class FirPsiSourceElement<out P : PsiElement>(val psi: P) : FirSourceElem
override fun getRoot(): LighterASTNode = lighterAST.root override fun getRoot(): LighterASTNode = lighterAST.root
override fun getParent(node: LighterASTNode): LighterASTNode? = node.unwrap().psi.parent?.node?.let { TreeBackedLighterAST.wrap(it) } override fun getParent(node: LighterASTNode): LighterASTNode? =
node.unwrap().psi.parent?.node?.let { TreeBackedLighterAST.wrap(it) }
override fun getChildren(node: LighterASTNode, nodesRef: Ref<Array<LighterASTNode>>): Int { override fun getChildren(node: LighterASTNode, nodesRef: Ref<Array<LighterASTNode>>): Int {
val children = node.unwrap().psi.children val children = node.unwrap().psi.children
@@ -201,7 +202,7 @@ sealed class FirPsiSourceElement<out P : PsiElement>(val psi: P) : FirSourceElem
override fun getStartOffset(node: LighterASTNode): Int = node.unwrap().startOffset override fun getStartOffset(node: LighterASTNode): Int = node.unwrap().startOffset
override fun getEndOffset(node: LighterASTNode): Int = node.unwrap().let { it.startOffset + it.textLength - 1 } override fun getEndOffset(node: LighterASTNode): Int = node.unwrap().let { it.startOffset + it.textLength }
} }
} }
@@ -17,10 +17,10 @@ class ActualDiagnostic constructor(val diagnostic: Diagnostic, override val plat
TextDiagnostic.InferenceCompatibility.OLD TextDiagnostic.InferenceCompatibility.OLD
override val name: String override val name: String
get() = diagnostic.factory.name get() = diagnostic.factory.name!!
val file: PsiFile val file: PsiFile
get() = diagnostic.psiFile get() = diagnostic.psiFile!!
override fun compareTo(other: AbstractTestDiagnostic): Int { override fun compareTo(other: AbstractTestDiagnostic): Int {
return if (this.diagnostic is DiagnosticWithParameters1<*, *> && other is ActualDiagnostic && other.diagnostic is DiagnosticWithParameters1<*, *>) { return if (this.diagnostic is DiagnosticWithParameters1<*, *> && other is ActualDiagnostic && other.diagnostic is DiagnosticWithParameters1<*, *>) {
@@ -21,28 +21,16 @@ class SyntaxErrorDiagnostic(errorElement: PsiErrorElement) : AbstractDiagnosticF
SyntaxErrorDiagnosticFactory.INSTANCE SyntaxErrorDiagnosticFactory.INSTANCE
) )
open class AbstractDiagnosticForTests(private val element: PsiElement, private val factory: DiagnosticFactory<*>) : Diagnostic { open class AbstractDiagnosticForTests(override val psiElement: PsiElement, override val factory: DiagnosticFactory<*>) : Diagnostic {
override fun getFactory(): DiagnosticFactory<*> { override val severity: Severity
return factory get() = Severity.ERROR
}
override fun getSeverity(): Severity { override val textRanges: List<TextRange>
return Severity.ERROR get() = listOf(psiElement.textRange)
}
override fun getPsiElement(): PsiElement { override val psiFile: PsiFile
return element get() = psiElement.containingFile
}
override fun getTextRanges(): List<TextRange> { override val isValid: Boolean
return listOf(element.textRange) get() = true
}
override fun getPsiFile(): PsiFile {
return element.containingFile
}
override fun isValid(): Boolean {
return true
}
} }
@@ -17,10 +17,12 @@ import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory
class DebugInfoDiagnosticFactory0 : DiagnosticFactory0<PsiElement>, class DebugInfoDiagnosticFactory0 private constructor(
private val privateName: String,
severity: Severity = Severity.ERROR
) : DiagnosticFactory0<PsiElement>(severity, PositioningStrategies.DEFAULT),
DebugInfoDiagnosticFactory { DebugInfoDiagnosticFactory {
private val name: String override val withExplicitDefinitionOnly: Boolean = false
override val withExplicitDefinitionOnly: Boolean
override fun createDiagnostic( override fun createDiagnostic(
expression: KtExpression, expression: KtExpression,
@@ -32,22 +34,9 @@ class DebugInfoDiagnosticFactory0 : DiagnosticFactory0<PsiElement>,
return DebugInfoDiagnostic(expression, this) return DebugInfoDiagnostic(expression, this)
} }
private constructor(name: String, severity: Severity = Severity.ERROR) : super(severity, PositioningStrategies.DEFAULT) { override var name: String?
this.name = name get() = "DEBUG_INFO_$privateName"
this.withExplicitDefinitionOnly = false set(_) {}
}
private constructor(name: String, severity: Severity, withExplicitDefinitionOnly: Boolean) : super(
severity,
PositioningStrategies.DEFAULT
) {
this.name = name
this.withExplicitDefinitionOnly = withExplicitDefinitionOnly
}
override fun getName(): String {
return "DEBUG_INFO_$name"
}
companion object { companion object {
val SMARTCAST = DebugInfoDiagnosticFactory0("SMARTCAST", Severity.INFO) val SMARTCAST = DebugInfoDiagnosticFactory0("SMARTCAST", Severity.INFO)
@@ -19,11 +19,11 @@ import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory
class DebugInfoDiagnosticFactory1 : DiagnosticFactory1<PsiElement, String>, class DebugInfoDiagnosticFactory1 : DiagnosticFactory1<PsiElement, String>,
DebugInfoDiagnosticFactory { DebugInfoDiagnosticFactory {
private val name: String private val privateName: String
override fun getName(): String { override var name: String?
return "DEBUG_INFO_$name" get() = "DEBUG_INFO_$privateName"
} set(_) {}
override val withExplicitDefinitionOnly: Boolean override val withExplicitDefinitionOnly: Boolean
@@ -33,8 +33,8 @@ class DebugInfoDiagnosticFactory1 : DiagnosticFactory1<PsiElement, String>,
dataFlowValueFactory: DataFlowValueFactory?, dataFlowValueFactory: DataFlowValueFactory?,
languageVersionSettings: LanguageVersionSettings?, languageVersionSettings: LanguageVersionSettings?,
moduleDescriptor: ModuleDescriptorImpl? moduleDescriptor: ModuleDescriptorImpl?
) = when (name) { ) = when (privateName) {
EXPRESSION_TYPE.name -> { EXPRESSION_TYPE.privateName -> {
val (type, dataFlowTypes) = CheckerTestUtil.getTypeInfo( val (type, dataFlowTypes) = CheckerTestUtil.getTypeInfo(
expression, expression,
bindingContext, bindingContext,
@@ -45,23 +45,23 @@ class DebugInfoDiagnosticFactory1 : DiagnosticFactory1<PsiElement, String>,
this.on(expression, Renderers.renderExpressionType(type, dataFlowTypes)) this.on(expression, Renderers.renderExpressionType(type, dataFlowTypes))
} }
CALL.name -> { CALL.privateName -> {
val (fqName, typeCall) = CheckerTestUtil.getCallDebugInfo(expression, bindingContext) val (fqName, typeCall) = CheckerTestUtil.getCallDebugInfo(expression, bindingContext)
this.on(expression, Renderers.renderCallInfo(fqName, typeCall)) this.on(expression, Renderers.renderCallInfo(fqName, typeCall))
} }
else -> throw NotImplementedError("Creation diagnostic '$name' isn't supported.") else -> throw NotImplementedError("Creation diagnostic '$name' isn't supported.")
} }
protected constructor(name: String, severity: Severity) : super(severity, PositioningStrategies.DEFAULT) { private constructor(name: String, severity: Severity) : super(severity, PositioningStrategies.DEFAULT) {
this.name = name this.privateName = name
this.withExplicitDefinitionOnly = false this.withExplicitDefinitionOnly = false
} }
protected constructor(name: String, severity: Severity, withExplicitDefinitionOnly: Boolean) : super( private constructor(name: String, severity: Severity, withExplicitDefinitionOnly: Boolean) : super(
severity, severity,
PositioningStrategies.DEFAULT PositioningStrategies.DEFAULT
) { ) {
this.name = name this.privateName = name
this.withExplicitDefinitionOnly = withExplicitDefinitionOnly this.withExplicitDefinitionOnly = withExplicitDefinitionOnly
} }
@@ -10,9 +10,9 @@ import org.jetbrains.kotlin.diagnostics.DiagnosticFactory
import org.jetbrains.kotlin.diagnostics.Severity import org.jetbrains.kotlin.diagnostics.Severity
class SyntaxErrorDiagnosticFactory private constructor() : DiagnosticFactory<SyntaxErrorDiagnostic>(Severity.ERROR) { class SyntaxErrorDiagnosticFactory private constructor() : DiagnosticFactory<SyntaxErrorDiagnostic>(Severity.ERROR) {
override fun getName(): String { override var name: String?
return "SYNTAX" get() = "SYNTAX"
} set(_) {}
companion object { companion object {
val INSTANCE = SyntaxErrorDiagnosticFactory() val INSTANCE = SyntaxErrorDiagnosticFactory()
@@ -24,6 +24,6 @@ interface Diagnostic {
val severity: Severity val severity: Severity
val psiElement: PsiElement val psiElement: PsiElement
val textRanges: List<TextRange> val textRanges: List<TextRange>
val psiFile: PsiFile val psiFile: PsiFile?
val isValid: Boolean val isValid: Boolean
} }
@@ -24,7 +24,6 @@ import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile; import com.intellij.psi.PsiFile;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor; import org.jetbrains.kotlin.descriptors.DeclarationDescriptor;
import org.jetbrains.kotlin.psi.psiUtil.PsiUtilsKt; import org.jetbrains.kotlin.psi.psiUtil.PsiUtilsKt;
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils; import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils;
@@ -75,6 +74,9 @@ public class DiagnosticUtils {
List<TextRange> textRanges = diagnostic.getTextRanges(); List<TextRange> textRanges = diagnostic.getTextRanges();
if (textRanges.isEmpty()) return PsiDiagnosticUtils.LineAndColumn.NONE; if (textRanges.isEmpty()) return PsiDiagnosticUtils.LineAndColumn.NONE;
TextRange firstRange = firstRange(textRanges); TextRange firstRange = firstRange(textRanges);
if (file == null) {
return PsiDiagnosticUtils.LineAndColumn.NONE;
}
return getLineAndColumnInPsiFile(file, firstRange); return getLineAndColumnInPsiFile(file, firstRange);
} }
@@ -90,6 +92,9 @@ public class DiagnosticUtils {
List<TextRange> textRanges = diagnostic.getTextRanges(); List<TextRange> textRanges = diagnostic.getTextRanges();
if (textRanges.isEmpty()) return PsiDiagnosticUtils.LineAndColumnRange.NONE; if (textRanges.isEmpty()) return PsiDiagnosticUtils.LineAndColumnRange.NONE;
TextRange firstRange = firstRange(textRanges); TextRange firstRange = firstRange(textRanges);
if (file == null) {
return PsiDiagnosticUtils.LineAndColumnRange.NONE;
}
return getLineAndColumnRangeInPsiFile(file, firstRange); return getLineAndColumnRangeInPsiFile(file, firstRange);
} }
@@ -124,9 +129,13 @@ public class DiagnosticUtils {
public static List<Diagnostic> sortedDiagnostics(@NotNull Collection<Diagnostic> diagnostics) { public static List<Diagnostic> sortedDiagnostics(@NotNull Collection<Diagnostic> diagnostics) {
List<Diagnostic> result = Lists.newArrayList(diagnostics); List<Diagnostic> result = Lists.newArrayList(diagnostics);
result.sort((d1, d2) -> { result.sort((d1, d2) -> {
String path1 = d1.getPsiFile().getViewProvider().getVirtualFile().getPath(); PsiFile file1 = d1.getPsiFile();
String path2 = d2.getPsiFile().getViewProvider().getVirtualFile().getPath(); PsiFile file2 = d2.getPsiFile();
if (!path1.equals(path2)) return path1.compareTo(path2); if (file1 != null && file2 != null) {
String path1 = file1.getViewProvider().getVirtualFile().getPath();
String path2 = file2.getViewProvider().getVirtualFile().getPath();
if (!path1.equals(path2)) return path1.compareTo(path2);
}
TextRange range1 = firstRange(d1.getTextRanges()); TextRange range1 = firstRange(d1.getTextRanges());
TextRange range2 = firstRange(d2.getTextRanges()); TextRange range2 = firstRange(d2.getTextRanges());
@@ -164,7 +164,7 @@ abstract class KotlinSuppressCache {
companion object { companion object {
private fun getDiagnosticSuppressKey(diagnostic: Diagnostic): String = private fun getDiagnosticSuppressKey(diagnostic: Diagnostic): String =
diagnostic.factory.name.toLowerCase() diagnostic.factory.name!!.toLowerCase()
private fun isSuppressedByStrings(key: String, strings: Set<String>, severity: Severity): Boolean = private fun isSuppressedByStrings(key: String, strings: Set<String>, severity: Severity): Boolean =
severity == Severity.WARNING && "warnings" in strings || key in strings severity == Severity.WARNING && "warnings" in strings || key in strings
@@ -24,13 +24,12 @@ import org.jetbrains.kotlin.asJava.classes.KtLightClassForSourceDeclaration
import org.jetbrains.kotlin.asJava.classes.getOutermostClassOrObject import org.jetbrains.kotlin.asJava.classes.getOutermostClassOrObject
import org.jetbrains.kotlin.asJava.classes.safeIsScript import org.jetbrains.kotlin.asJava.classes.safeIsScript
import org.jetbrains.kotlin.diagnostics.Diagnostic import org.jetbrains.kotlin.diagnostics.Diagnostic
import org.jetbrains.kotlin.diagnostics.DiagnosticFactory.cast import org.jetbrains.kotlin.diagnostics.DiagnosticFactory
import org.jetbrains.kotlin.diagnostics.Errors.* import org.jetbrains.kotlin.diagnostics.Errors.*
import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil
import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.resolve.diagnostics.Diagnostics import org.jetbrains.kotlin.resolve.diagnostics.Diagnostics
import org.jetbrains.kotlin.resolve.jvm.diagnostics.ConflictingJvmDeclarationsData import org.jetbrains.kotlin.resolve.jvm.diagnostics.ConflictingJvmDeclarationsData
import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm
import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm.* import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm.*
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKind.* import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKind.*
@@ -90,8 +89,7 @@ fun getJvmSignatureDiagnostics(element: PsiElement, otherDiagnostics: Diagnostic
return null return null
} }
val result = doGetDiagnostics() val result = doGetDiagnostics() ?: return null
if (result == null) return null
return FilteredJvmDiagnostics(result, otherDiagnostics) return FilteredJvmDiagnostics(result, otherDiagnostics)
} }
@@ -111,7 +109,7 @@ class FilteredJvmDiagnostics(val jvmDiagnostics: Diagnostics, val otherDiagnosti
} }
override fun forElement(psiElement: PsiElement): Collection<Diagnostic> { override fun forElement(psiElement: PsiElement): Collection<Diagnostic> {
fun Diagnostic.data() = cast(this, jvmDiagnosticFactories).a fun Diagnostic.data() = DiagnosticFactory.cast(this, jvmDiagnosticFactories).a
val (conflicting, other) = jvmDiagnostics.forElement(psiElement).partition { it.factory in jvmDiagnosticFactories } val (conflicting, other) = jvmDiagnostics.forElement(psiElement).partition { it.factory in jvmDiagnosticFactories }
if (alreadyReported(psiElement)) { if (alreadyReported(psiElement)) {
// CONFLICTING_OVERLOADS already reported, no need to duplicate it // CONFLICTING_OVERLOADS already reported, no need to duplicate it
@@ -125,22 +123,19 @@ class FilteredJvmDiagnostics(val jvmDiagnostics: Diagnostics, val otherDiagnosti
val diagnostics = it.value val diagnostics = it.value
if (diagnostics.size <= 1) { if (diagnostics.size <= 1) {
filtered.addAll(diagnostics) filtered.addAll(diagnostics)
} } else {
else {
filtered.addAll( filtered.addAll(
diagnostics.filter { diagnostics.filter { me ->
me -> diagnostics.none { other ->
diagnostics.none { me != other && (
other -> // in case of implementation copied from a super trait there will be both diagnostics on the same signature
me != other && ( other.factory == CONFLICTING_JVM_DECLARATIONS && (me.factory == ACCIDENTAL_OVERRIDE ||
// in case of implementation copied from a super trait there will be both diagnostics on the same signature me.factory == CONFLICTING_INHERITED_JVM_DECLARATIONS)
other.factory == ErrorsJvm.CONFLICTING_JVM_DECLARATIONS && (me.factory == ACCIDENTAL_OVERRIDE || // there are paris of corresponding signatures that frequently clash simultaneously: multifile class & part, trait and trait-impl
me.factory == CONFLICTING_INHERITED_JVM_DECLARATIONS) || other.data().higherThan(me.data())
// there are paris of corresponding signatures that frequently clash simultaneously: multifile class & part, trait and trait-impl )
|| other.data().higherThan(me.data())
)
}
} }
}
) )
} }
} }
@@ -22,7 +22,6 @@ import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
import org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM import org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM
import org.jetbrains.kotlin.diagnostics.PsiDiagnosticUtils import org.jetbrains.kotlin.diagnostics.PsiDiagnosticUtils
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnostic import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnostic
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirPsiDiagnostic
import org.jetbrains.kotlin.fir.builder.RawFirBuilder import org.jetbrains.kotlin.fir.builder.RawFirBuilder
import org.jetbrains.kotlin.fir.builder.RawFirBuilderMode import org.jetbrains.kotlin.fir.builder.RawFirBuilderMode
import org.jetbrains.kotlin.fir.declarations.FirFile import org.jetbrains.kotlin.fir.declarations.FirFile
@@ -326,8 +325,7 @@ abstract class AbstractFirBaseDiagnosticsTest : BaseDiagnosticsTest() {
private fun Iterable<FirDiagnostic<*>>.toActualDiagnostic(root: PsiElement): List<ActualDiagnostic> { private fun Iterable<FirDiagnostic<*>>.toActualDiagnostic(root: PsiElement): List<ActualDiagnostic> {
val result = mutableListOf<ActualDiagnostic>() val result = mutableListOf<ActualDiagnostic>()
mapTo(result) { mapTo(result) {
val oldDiagnostic = (it as FirPsiDiagnostic<*>).asPsiBasedDiagnostic() ActualDiagnostic(it, null, true)
ActualDiagnostic(oldDiagnostic, null, true)
} }
for (errorElement in AnalyzingUtils.getSyntaxErrorRanges(root)) { for (errorElement in AnalyzingUtils.getSyntaxErrorRanges(root)) {
result.add(ActualDiagnostic(SyntaxErrorDiagnostic(errorElement), null, true)) result.add(ActualDiagnostic(SyntaxErrorDiagnostic(errorElement), null, true))
@@ -40,7 +40,6 @@ import org.jetbrains.kotlin.fir.visitors.FirDefaultVisitorVoid
import org.jetbrains.kotlin.fir.visitors.FirVisitorVoid import org.jetbrains.kotlin.fir.visitors.FirVisitorVoid
import org.jetbrains.kotlin.name.FqNameUnsafe import org.jetbrains.kotlin.name.FqNameUnsafe
import org.jetbrains.kotlin.test.KotlinTestUtils import org.jetbrains.kotlin.test.KotlinTestUtils
import org.jetbrains.kotlin.test.testFramework.KtUsefulTestCase
import org.jetbrains.kotlin.util.OperatorNameConventions import org.jetbrains.kotlin.util.OperatorNameConventions
import org.jetbrains.kotlin.utils.addIfNotNull import org.jetbrains.kotlin.utils.addIfNotNull
import java.io.File import java.io.File
@@ -63,8 +62,8 @@ import java.io.File
*/ */
abstract class AbstractFirDiagnosticsTest : AbstractFirBaseDiagnosticsTest() { abstract class AbstractFirDiagnosticsTest : AbstractFirBaseDiagnosticsTest() {
companion object { companion object {
val DUMP_CFG_DIRECTIVE = "DUMP_CFG" const val DUMP_CFG_DIRECTIVE = "DUMP_CFG"
val COMMON_COROUTINES_DIRECTIVE ="COMMON_COROUTINES_TEST" const val COMMON_COROUTINES_DIRECTIVE = "COMMON_COROUTINES_TEST"
val TestFile.withDumpCfgDirective: Boolean val TestFile.withDumpCfgDirective: Boolean
get() = DUMP_CFG_DIRECTIVE in directives get() = DUMP_CFG_DIRECTIVE in directives
@@ -204,7 +203,8 @@ abstract class AbstractFirDiagnosticsTest : AbstractFirBaseDiagnosticsTest() {
argument: () -> String, argument: () -> String,
): FirDiagnosticWithParameters1<FirSourceElement, String>? { ): FirDiagnosticWithParameters1<FirSourceElement, String>? {
val sourceElement = element.source ?: return null val sourceElement = element.source ?: return null
if (diagnosedRangesToDiagnosticNames[sourceElement.startOffset..sourceElement.endOffset]?.contains(this.name) != true) return null val name = name ?: return null
if (diagnosedRangesToDiagnosticNames[sourceElement.startOffset..sourceElement.endOffset]?.contains(name) != true) return null
val argumentText = argument() val argumentText = argument()
return when (sourceElement) { return when (sourceElement) {
@@ -212,21 +212,13 @@ abstract class AbstractFirDiagnosticsTest : AbstractFirBaseDiagnosticsTest() {
sourceElement, sourceElement,
argumentText, argumentText,
severity, severity,
FirDiagnosticFactory1( FirDiagnosticFactory1(name, severity)
name,
severity,
this
)
) )
is FirLightSourceElement -> FirLightDiagnosticWithParameters1( is FirLightSourceElement -> FirLightDiagnosticWithParameters1(
sourceElement, sourceElement,
argumentText, argumentText,
severity, severity,
FirDiagnosticFactory1<FirSourceElement, PsiElement, String>( FirDiagnosticFactory1<FirSourceElement, PsiElement, String>(name, severity)
name,
severity,
this
)
) )
} }
} }
@@ -324,13 +316,13 @@ abstract class AbstractFirDiagnosticsTest : AbstractFirBaseDiagnosticsTest() {
private val cfgKinds = listOf(EdgeKind.DeadForward, EdgeKind.CfgForward, EdgeKind.DeadBackward, EdgeKind.CfgBackward) private val cfgKinds = listOf(EdgeKind.DeadForward, EdgeKind.CfgForward, EdgeKind.DeadBackward, EdgeKind.CfgBackward)
private fun checkEdge(from: CFGNode<*>, to: CFGNode<*>) { private fun checkEdge(from: CFGNode<*>, to: CFGNode<*>) {
KtUsefulTestCase.assertContainsElements(from.followingNodes, to) assertContainsElements(from.followingNodes, to)
KtUsefulTestCase.assertContainsElements(to.previousNodes, from) assertContainsElements(to.previousNodes, from)
val fromKind = from.outgoingEdges.getValue(to).kind val fromKind = from.outgoingEdges.getValue(to).kind
val toKind = to.incomingEdges.getValue(from).kind val toKind = to.incomingEdges.getValue(from).kind
TestCase.assertEquals(fromKind, toKind) TestCase.assertEquals(fromKind, toKind)
if (from.isDead && to.isDead) { if (from.isDead && to.isDead) {
KtUsefulTestCase.assertContainsElements(cfgKinds, toKind) assertContainsElements(cfgKinds, toKind)
} }
} }
@@ -57,7 +57,7 @@ abstract class AbstractFirDiagnosticsWithLightTreeTest : AbstractFirDiagnosticsT
val expected = existingDiagnostics[startOffset] ?: emptyMap() val expected = existingDiagnostics[startOffset] ?: emptyMap()
val actual = actualDiagnostics[startOffset] ?: emptyMap() val actual = actualDiagnostics[startOffset] ?: emptyMap()
for (name in expected.keys + actual.keys) { for (name in expected.keys + actual.keys) {
if (name == "SYNTAX") continue if (name == null || name == "SYNTAX") continue
val expectedCount = expected[name] ?: 0 val expectedCount = expected[name] ?: 0
val actualCount = actual[name] ?: 0 val actualCount = actual[name] ?: 0
if (expectedCount != actualCount) { if (expectedCount != actualCount) {
@@ -28,7 +28,7 @@ class DiagnosticTestTypeValidator(
private fun findTestCases(diagnostic: Diagnostic): TestCasesByNumbers { private fun findTestCases(diagnostic: Diagnostic): TestCasesByNumbers {
val ranges = diagnostic.textRanges val ranges = diagnostic.textRanges
val filename = diagnostic.psiFile.name val filename = diagnostic.psiFile!!.name
val foundTestCases = testInfo.cases.byRanges[filename]!!.floorEntry(ranges[0].startOffset) val foundTestCases = testInfo.cases.byRanges[filename]!!.floorEntry(ranges[0].startOffset)
if (foundTestCases != null) if (foundTestCases != null)
@@ -52,7 +52,7 @@ class DiagnosticTestTypeValidator(
private fun collectDiagnostics(files: List<BaseDiagnosticsTest.TestFile>) { private fun collectDiagnostics(files: List<BaseDiagnosticsTest.TestFile>) {
files.forEach { file -> files.forEach { file ->
file.actualDiagnostics.forEach { file.actualDiagnostics.forEach {
val diagnosticName = it.diagnostic.factory.name val diagnosticName = it.diagnostic.factory.name!!
diagnosticStats.run { put(diagnosticName, getOrDefault(diagnosticName, 0) + 1) } diagnosticStats.run { put(diagnosticName, getOrDefault(diagnosticName, 0) + 1) }
diagnostics.add(it.diagnostic) diagnostics.add(it.diagnostic)
} }
@@ -30,9 +30,9 @@ import org.jetbrains.kotlin.test.KotlinTestWithEnvironment
import org.junit.Assert import org.junit.Assert
class MutableDiagnosticsTest : KotlinTestWithEnvironment() { class MutableDiagnosticsTest : KotlinTestWithEnvironment() {
override fun createEnvironment(): KotlinCoreEnvironment? { override fun createEnvironment(): KotlinCoreEnvironment {
return KotlinCoreEnvironment.createForTests( return KotlinCoreEnvironment.createForTests(
testRootDisposable, KotlinTestUtils.newConfiguration(), EnvironmentConfigFiles.JVM_CONFIG_FILES testRootDisposable, KotlinTestUtils.newConfiguration(), EnvironmentConfigFiles.JVM_CONFIG_FILES
) )
} }
@@ -137,19 +137,18 @@ class MutableDiagnosticsTest : KotlinTestWithEnvironment() {
private class DummyDiagnosticFactory : DiagnosticFactory<DummyDiagnostic>("DUMMY", Severity.ERROR) private class DummyDiagnosticFactory : DiagnosticFactory<DummyDiagnostic>("DUMMY", Severity.ERROR)
private inner class DummyDiagnostic : Diagnostic { private inner class DummyDiagnostic : Diagnostic {
private val factory = DummyDiagnosticFactory() override val factory = DummyDiagnosticFactory()
private val dummyElement = KtPsiFactory(environment.project).createType("Int") private val dummyElement = KtPsiFactory(environment.project).createType("Int")
init { init {
dummyElement.getContainingKtFile().doNotAnalyze = null dummyElement.containingKtFile.doNotAnalyze = null
} }
override fun getFactory() = factory override val severity get() = factory.severity
override fun getSeverity() = factory.severity override val psiElement get() = dummyElement
override fun getPsiElement() = dummyElement override val textRanges get() = unimplemented()
override fun getTextRanges() = unimplemented() override val psiFile get() = unimplemented()
override fun getPsiFile() = unimplemented() override val isValid get() = unimplemented()
override fun isValid() = unimplemented()
private fun unimplemented(): Nothing = throw UnsupportedOperationException() private fun unimplemented(): Nothing = throw UnsupportedOperationException()
} }
@@ -45,7 +45,7 @@ class AnnotationPresentationInfo(
if (fixes.isEmpty()) { if (fixes.isEmpty()) {
// if there are no quick fixes we need to register an EmptyIntentionAction to enable 'suppress' actions // if there are no quick fixes we need to register an EmptyIntentionAction to enable 'suppress' actions
annotation.newFix(EmptyIntentionAction(diagnostic.factory.name)).registerFix() annotation.newFix(EmptyIntentionAction(diagnostic.factory.name!!)).registerFix()
} }
} }
} }
@@ -37,7 +37,7 @@ class KotlinSuppressableWarningProblemGroup(
} }
fun createSuppressWarningActions(element: PsiElement, diagnosticFactory: DiagnosticFactory<*>): List<SuppressIntentionAction> = fun createSuppressWarningActions(element: PsiElement, diagnosticFactory: DiagnosticFactory<*>): List<SuppressIntentionAction> =
createSuppressWarningActions(element, diagnosticFactory.severity, diagnosticFactory.name) createSuppressWarningActions(element, diagnosticFactory.severity, diagnosticFactory.name!!)
fun createSuppressWarningActions(element: PsiElement, severity: Severity, suppressionKey: String): List<SuppressIntentionAction> { fun createSuppressWarningActions(element: PsiElement, severity: Severity, suppressionKey: String): List<SuppressIntentionAction> {
@@ -42,7 +42,7 @@ internal abstract class AbstractFirIdeDiagnosticsCollector(
override fun report(diagnostic: FirDiagnostic<*>?) { override fun report(diagnostic: FirDiagnostic<*>?) {
if (diagnostic !is FirPsiDiagnostic<*>) return if (diagnostic !is FirPsiDiagnostic<*>) return
if (diagnostic.element.psi !is KtElement) return if (diagnostic.element.psi !is KtElement) return
onDiagnostic(diagnostic.asPsiBasedDiagnostic()) onDiagnostic(diagnostic)
} }
} }
@@ -261,7 +261,7 @@ class KotlinBytecodeToolWindow(private val myProject: Project, private val toolW
answer.append("// ================\n") answer.append("// ================\n")
for (diagnostic in diagnostics) { for (diagnostic in diagnostics) {
answer.append("// Error at ") answer.append("// Error at ")
.append(diagnostic.psiFile.name) .append(diagnostic.psiFile?.name)
.append(join(diagnostic.textRanges, ",")) .append(join(diagnostic.textRanges, ","))
.append(": ") .append(": ")
.append(DefaultErrorMessages.render(diagnostic)) .append(DefaultErrorMessages.render(diagnostic))
@@ -46,7 +46,7 @@ class MigrateDiagnosticSuppressionInspection : AbstractKotlinInspection(), Clean
} }
class ReplaceDiagnosticNameFix(private val diagnosticFactory: DiagnosticFactory<*>) : LocalQuickFix { class ReplaceDiagnosticNameFix(private val diagnosticFactory: DiagnosticFactory<*>) : LocalQuickFix {
override fun getName() = KotlinBundle.message("replace.diagnostic.name.fix.text", familyName, diagnosticFactory.name) override fun getName() = KotlinBundle.message("replace.diagnostic.name.fix.text", familyName, diagnosticFactory.name!!)
override fun getFamilyName() = KotlinBundle.message("replace.diagnostic.name.fix.family.name") override fun getFamilyName() = KotlinBundle.message("replace.diagnostic.name.fix.family.name")
@@ -128,7 +128,7 @@ class AddFunctionToSupertypeFix private constructor(
val descriptors = generateFunctionsToAdd(function) val descriptors = generateFunctionsToAdd(function)
if (descriptors.isEmpty()) return null if (descriptors.isEmpty()) return null
val project = diagnostic.psiFile.project val project = diagnostic.psiFile!!.project
val functionData = descriptors.mapNotNull { createFunctionData(it, project) } val functionData = descriptors.mapNotNull { createFunctionData(it, project) }
if (functionData.isEmpty()) return null if (functionData.isEmpty()) return null
@@ -102,7 +102,7 @@ class AddPropertyToSupertypeFix private constructor(
val descriptors = generatePropertiesToAdd(property) val descriptors = generatePropertiesToAdd(property)
if (descriptors.isEmpty()) return null if (descriptors.isEmpty()) return null
val project = diagnostic.psiFile.project val project = diagnostic.psiFile!!.project
val propertyData = descriptors.mapNotNull { createPropertyData(it, property.initializer, project) } val propertyData = descriptors.mapNotNull { createPropertyData(it, property.initializer, project) }
if (propertyData.isEmpty()) return null if (propertyData.isEmpty()) return null
@@ -82,7 +82,7 @@ open class DiagnosticCodeMetaInfoRenderConfiguration(
} }
fun getTag(codeMetaInfo: DiagnosticCodeMetaInfo): String { fun getTag(codeMetaInfo: DiagnosticCodeMetaInfo): String {
return codeMetaInfo.diagnostic.factory.name return codeMetaInfo.diagnostic.factory.name!!
} }
} }
@@ -15,7 +15,7 @@ import javax.xml.parsers.DocumentBuilderFactory
class IdeDiagnosticMessageHolder : DiagnosticMessageHolder { class IdeDiagnosticMessageHolder : DiagnosticMessageHolder {
private val diagnostics = arrayListOf<Pair<Diagnostic, String>>() private val diagnostics = arrayListOf<Pair<Diagnostic, String>>()
override fun report(diagnostic: Diagnostic, file: PsiFile, render: String) { override fun report(diagnostic: Diagnostic, file: PsiFile?, render: String) {
diagnostics.add(Pair(diagnostic, render)) diagnostics.add(Pair(diagnostic, render))
} }