[FIR] Add ability to generate special diagnostic factories for deprecation warnings
This kind of diagnostic factory has two different factories with warning and error severity and language feature with turns on reporting of error
This commit is contained in:
+31
-5
@@ -6,6 +6,7 @@
|
||||
package org.jetbrains.kotlin.fir.checkers.generator.diagnostics.model
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.diagnostics.Severity
|
||||
import org.jetbrains.kotlin.fir.PrivateForInline
|
||||
import kotlin.properties.PropertyDelegateProvider
|
||||
@@ -24,24 +25,31 @@ abstract class AbstractDiagnosticGroup @PrivateForInline constructor(val name: S
|
||||
@OptIn(PrivateForInline::class)
|
||||
internal inline fun <reified P : PsiElement> error(
|
||||
positioningStrategy: PositioningStrategy = PositioningStrategy.DEFAULT,
|
||||
crossinline init: DiagnosticBuilder.() -> Unit = {}
|
||||
crossinline init: DiagnosticBuilder.Regular.() -> Unit = {}
|
||||
) = diagnosticDelegateProvider<P>(Severity.ERROR, positioningStrategy, init)
|
||||
|
||||
|
||||
@OptIn(PrivateForInline::class)
|
||||
internal inline fun <reified P : PsiElement> warning(
|
||||
positioningStrategy: PositioningStrategy = PositioningStrategy.DEFAULT,
|
||||
crossinline init: DiagnosticBuilder.() -> Unit = {}
|
||||
crossinline init: DiagnosticBuilder.Regular.() -> Unit = {}
|
||||
) = diagnosticDelegateProvider<P>(Severity.WARNING, positioningStrategy, init)
|
||||
|
||||
@OptIn(PrivateForInline::class)
|
||||
internal inline fun <reified P : PsiElement> deprecationError(
|
||||
featureForError: LanguageFeature,
|
||||
positioningStrategy: PositioningStrategy = PositioningStrategy.DEFAULT,
|
||||
crossinline init: DiagnosticBuilder.Deprecation.() -> Unit = {}
|
||||
) = deprecationDiagnosticDelegateProvider<P>(featureForError, positioningStrategy, init)
|
||||
|
||||
@PrivateForInline
|
||||
@OptIn(ExperimentalStdlibApi::class)
|
||||
internal inline fun <reified P : PsiElement> diagnosticDelegateProvider(
|
||||
severity: Severity,
|
||||
positioningStrategy: PositioningStrategy,
|
||||
crossinline init: DiagnosticBuilder.() -> Unit = {}
|
||||
) = PropertyDelegateProvider<Any?, ReadOnlyProperty<AbstractDiagnosticGroup, DiagnosticData>> { _, property ->
|
||||
val diagnostic = DiagnosticBuilder(
|
||||
crossinline init: DiagnosticBuilder.Regular.() -> Unit = {}
|
||||
) = PropertyDelegateProvider<Any?, ReadOnlyProperty<AbstractDiagnosticGroup, RegularDiagnosticData>> { _, property ->
|
||||
val diagnostic = DiagnosticBuilder.Regular(
|
||||
containingObjectName,
|
||||
severity,
|
||||
name = property.name,
|
||||
@@ -52,6 +60,24 @@ abstract class AbstractDiagnosticGroup @PrivateForInline constructor(val name: S
|
||||
ReadOnlyProperty { _, _ -> diagnostic }
|
||||
}
|
||||
|
||||
@PrivateForInline
|
||||
@OptIn(ExperimentalStdlibApi::class)
|
||||
internal inline fun <reified P : PsiElement> deprecationDiagnosticDelegateProvider(
|
||||
featureForError: LanguageFeature,
|
||||
positioningStrategy: PositioningStrategy,
|
||||
crossinline init: DiagnosticBuilder.Deprecation.() -> Unit = {}
|
||||
) = PropertyDelegateProvider<Any?, ReadOnlyProperty<AbstractDiagnosticGroup, DeprecationDiagnosticData>> { _, property ->
|
||||
val diagnostic = DiagnosticBuilder.Deprecation(
|
||||
containingObjectName,
|
||||
featureForError,
|
||||
name = property.name,
|
||||
psiType = typeOf<P>(),
|
||||
positioningStrategy,
|
||||
).apply(init).build()
|
||||
_diagnostics += diagnostic
|
||||
ReadOnlyProperty { _, _ -> diagnostic }
|
||||
}
|
||||
|
||||
@OptIn(PrivateForInline::class)
|
||||
operator fun plus(other: AbstractDiagnosticGroup): AbstractDiagnosticGroup {
|
||||
require(name == other.name)
|
||||
|
||||
+47
-15
@@ -5,6 +5,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.fir.checkers.generator.diagnostics.model
|
||||
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.diagnostics.Severity
|
||||
import org.jetbrains.kotlin.fir.PrivateForInline
|
||||
import kotlin.properties.ReadOnlyProperty
|
||||
@@ -65,13 +66,52 @@ abstract class DiagnosticList(internal val objectName: String) {
|
||||
abstract inner class DiagnosticGroup(name: String) : AbstractDiagnosticGroup(name, objectName)
|
||||
}
|
||||
|
||||
class DiagnosticBuilder(
|
||||
private val containingObjectName: String,
|
||||
private val severity: Severity,
|
||||
private val name: String,
|
||||
private val psiType: KType,
|
||||
private val positioningStrategy: PositioningStrategy,
|
||||
sealed class DiagnosticBuilder(
|
||||
protected val containingObjectName: String,
|
||||
protected val name: String,
|
||||
protected val psiType: KType,
|
||||
protected val positioningStrategy: PositioningStrategy,
|
||||
) {
|
||||
class Regular(
|
||||
containingObjectName: String,
|
||||
private val severity: Severity,
|
||||
name: String,
|
||||
psiType: KType,
|
||||
positioningStrategy: PositioningStrategy,
|
||||
) : DiagnosticBuilder(containingObjectName, name, psiType, positioningStrategy) {
|
||||
@OptIn(PrivateForInline::class)
|
||||
override fun build(): RegularDiagnosticData {
|
||||
return RegularDiagnosticData(
|
||||
containingObjectName,
|
||||
severity,
|
||||
name,
|
||||
psiType,
|
||||
parameters,
|
||||
positioningStrategy,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
class Deprecation(
|
||||
containingObjectName: String,
|
||||
private val featureForError: LanguageFeature,
|
||||
name: String,
|
||||
psiType: KType,
|
||||
positioningStrategy: PositioningStrategy,
|
||||
) : DiagnosticBuilder(containingObjectName, name, psiType, positioningStrategy) {
|
||||
@OptIn(PrivateForInline::class)
|
||||
override fun build(): DeprecationDiagnosticData {
|
||||
return DeprecationDiagnosticData(
|
||||
containingObjectName,
|
||||
featureForError,
|
||||
name,
|
||||
psiType,
|
||||
parameters,
|
||||
positioningStrategy,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@PrivateForInline
|
||||
val parameters = mutableListOf<DiagnosticParameter>()
|
||||
|
||||
@@ -86,15 +126,7 @@ class DiagnosticBuilder(
|
||||
)
|
||||
}
|
||||
|
||||
@OptIn(PrivateForInline::class)
|
||||
fun build() = DiagnosticData(
|
||||
containingObjectName,
|
||||
severity,
|
||||
name,
|
||||
psiType,
|
||||
parameters,
|
||||
positioningStrategy,
|
||||
)
|
||||
abstract fun build(): DiagnosticData
|
||||
|
||||
companion object {
|
||||
const val MAX_DIAGNOSTIC_PARAMETER_COUNT = 4
|
||||
|
||||
+18
-8
@@ -55,16 +55,21 @@ object ErrorListDiagnosticListRenderer : DiagnosticListRenderer() {
|
||||
private fun SmartPrinter.printDiagnostic(diagnostic: DiagnosticData) {
|
||||
print("val ${diagnostic.name} by ${diagnostic.getFactoryFunction()}")
|
||||
printTypeArguments(diagnostic.getAllTypeArguments())
|
||||
printPositioningStrategy(diagnostic)
|
||||
printPositioningStrategyAndLanguageFeature(diagnostic)
|
||||
println()
|
||||
}
|
||||
|
||||
private fun SmartPrinter.printPositioningStrategy(diagnostic: DiagnosticData) {
|
||||
print("(")
|
||||
if (!diagnostic.hasDefaultPositioningStrategy()) {
|
||||
print(diagnostic.positioningStrategy.expressionToCreate)
|
||||
@OptIn(ExperimentalStdlibApi::class)
|
||||
private fun SmartPrinter.printPositioningStrategyAndLanguageFeature(diagnostic: DiagnosticData) {
|
||||
val argumentsList = buildList {
|
||||
if (diagnostic is DeprecationDiagnosticData) {
|
||||
add(diagnostic.featureForError.name)
|
||||
}
|
||||
if (!diagnostic.hasDefaultPositioningStrategy()) {
|
||||
add(diagnostic.positioningStrategy.expressionToCreate)
|
||||
}
|
||||
}
|
||||
print(")")
|
||||
print(argumentsList.joinToString(", ", prefix = "(", postfix = ")"))
|
||||
}
|
||||
|
||||
|
||||
@@ -124,14 +129,19 @@ object ErrorListDiagnosticListRenderer : DiagnosticListRenderer() {
|
||||
add(PositioningStrategy.importToAdd)
|
||||
}
|
||||
}
|
||||
for (deprecationDiagnostic in diagnosticList.allDiagnostics.filterIsInstance<DeprecationDiagnosticData>()) {
|
||||
add("org.jetbrains.kotlin.config.LanguageFeature.${deprecationDiagnostic.featureForError.name}")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private val KType.kClass: KClass<*>
|
||||
get() = classifier as KClass<*>
|
||||
|
||||
private fun DiagnosticData.getFactoryFunction(): String =
|
||||
severity.name.lowercase() + parameters.size
|
||||
private fun DiagnosticData.getFactoryFunction(): String = when (this) {
|
||||
is RegularDiagnosticData -> severity.name.lowercase()
|
||||
is DeprecationDiagnosticData -> "deprecationError"
|
||||
} + parameters.size
|
||||
}
|
||||
|
||||
private inline fun <T> SmartPrinter.printSeparatedWithComma(list: List<T>, printItem: (T) -> Unit) {
|
||||
|
||||
+25
-7
@@ -5,17 +5,35 @@
|
||||
|
||||
package org.jetbrains.kotlin.fir.checkers.generator.diagnostics.model
|
||||
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.diagnostics.Severity
|
||||
import kotlin.reflect.KType
|
||||
|
||||
data class DiagnosticData(
|
||||
val containingObjectName: String,
|
||||
sealed class DiagnosticData {
|
||||
abstract val containingObjectName: String
|
||||
abstract val name: String
|
||||
abstract val psiType: KType
|
||||
abstract val parameters: List<DiagnosticParameter>
|
||||
abstract val positioningStrategy: PositioningStrategy
|
||||
}
|
||||
|
||||
data class RegularDiagnosticData(
|
||||
override val containingObjectName: String,
|
||||
val severity: Severity,
|
||||
val name: String,
|
||||
val psiType: KType,
|
||||
val parameters: List<DiagnosticParameter>,
|
||||
val positioningStrategy: PositioningStrategy,
|
||||
)
|
||||
override val name: String,
|
||||
override val psiType: KType,
|
||||
override val parameters: List<DiagnosticParameter>,
|
||||
override val positioningStrategy: PositioningStrategy,
|
||||
) : DiagnosticData()
|
||||
|
||||
data class DeprecationDiagnosticData(
|
||||
override val containingObjectName: String,
|
||||
val featureForError: LanguageFeature,
|
||||
override val name: String,
|
||||
override val psiType: KType,
|
||||
override val parameters: List<DiagnosticParameter>,
|
||||
override val positioningStrategy: PositioningStrategy,
|
||||
) : DiagnosticData()
|
||||
|
||||
data class DiagnosticParameter(
|
||||
val name: String,
|
||||
+69
@@ -10,6 +10,7 @@ import org.jetbrains.kotlin.fir.FirElement
|
||||
import org.jetbrains.kotlin.fir.FirSourceElement
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollector
|
||||
import org.jetbrains.kotlin.fir.languageVersionSettings
|
||||
|
||||
abstract class DiagnosticReporter {
|
||||
abstract fun report(diagnostic: FirDiagnostic?, context: CheckerContext)
|
||||
@@ -75,6 +76,74 @@ fun <A : Any, B : Any, C : Any, D : Any> DiagnosticReporter.reportOn(
|
||||
source?.let { report(factory.on(it, a, b, c, d, positioningStrategy), context) }
|
||||
}
|
||||
|
||||
@OptIn(InternalDiagnosticFactoryMethod::class)
|
||||
fun DiagnosticReporter.reportOn(
|
||||
source: FirSourceElement?,
|
||||
factory: FirDiagnosticFactoryForDeprecation0,
|
||||
context: CheckerContext,
|
||||
positioningStrategy: SourceElementPositioningStrategy? = null
|
||||
) {
|
||||
reportOn(source, factory.chooseFactory(context), context, positioningStrategy)
|
||||
}
|
||||
|
||||
@OptIn(InternalDiagnosticFactoryMethod::class)
|
||||
fun <A : Any> DiagnosticReporter.reportOn(
|
||||
source: FirSourceElement?,
|
||||
factory: FirDiagnosticFactoryForDeprecation1<A>,
|
||||
a: A,
|
||||
context: CheckerContext,
|
||||
positioningStrategy: SourceElementPositioningStrategy? = null
|
||||
) {
|
||||
reportOn(source, factory.chooseFactory(context), a, context, positioningStrategy)
|
||||
}
|
||||
|
||||
@OptIn(InternalDiagnosticFactoryMethod::class)
|
||||
fun <A : Any, B : Any> DiagnosticReporter.reportOn(
|
||||
source: FirSourceElement?,
|
||||
factory: FirDiagnosticFactoryForDeprecation2<A, B>,
|
||||
a: A,
|
||||
b: B,
|
||||
context: CheckerContext,
|
||||
positioningStrategy: SourceElementPositioningStrategy? = null
|
||||
) {
|
||||
reportOn(source, factory.chooseFactory(context), a, b, context, positioningStrategy)
|
||||
}
|
||||
|
||||
@OptIn(InternalDiagnosticFactoryMethod::class)
|
||||
fun <A : Any, B : Any, C : Any> DiagnosticReporter.reportOn(
|
||||
source: FirSourceElement?,
|
||||
factory: FirDiagnosticFactoryForDeprecation3<A, B, C>,
|
||||
a: A,
|
||||
b: B,
|
||||
c: C,
|
||||
context: CheckerContext,
|
||||
positioningStrategy: SourceElementPositioningStrategy? = null
|
||||
) {
|
||||
reportOn(source, factory.chooseFactory(context), a, b, c, context, positioningStrategy)
|
||||
}
|
||||
|
||||
@OptIn(InternalDiagnosticFactoryMethod::class)
|
||||
fun <A : Any, B : Any, C : Any, D : Any> DiagnosticReporter.reportOn(
|
||||
source: FirSourceElement?,
|
||||
factory: FirDiagnosticFactoryForDeprecation4<A, B, C, D>,
|
||||
a: A,
|
||||
b: B,
|
||||
c: C,
|
||||
d: D,
|
||||
context: CheckerContext,
|
||||
positioningStrategy: SourceElementPositioningStrategy? = null
|
||||
) {
|
||||
reportOn(source, factory.chooseFactory(context), a, b, c, d, context, positioningStrategy)
|
||||
}
|
||||
|
||||
fun <F : AbstractFirDiagnosticFactory> FirDiagnosticFactoryForDeprecation<F>.chooseFactory(context: CheckerContext): F {
|
||||
return if (context.session.languageVersionSettings.supportsFeature(deprecatingFeature)) {
|
||||
errorFactory
|
||||
} else {
|
||||
warningFactory
|
||||
}
|
||||
}
|
||||
|
||||
inline fun withSuppressedDiagnostics(
|
||||
element: FirElement,
|
||||
context: CheckerContext,
|
||||
|
||||
+39
@@ -2,6 +2,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.fir.analysis.diagnostics
|
||||
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.diagnostics.Severity
|
||||
import org.jetbrains.kotlin.fir.FirLightSourceElement
|
||||
import org.jetbrains.kotlin.fir.FirPsiSourceElement
|
||||
@@ -200,3 +201,41 @@ class FirDiagnosticFactory4<A, B, C, D>(
|
||||
private fun incorrectElement(element: FirSourceElement): Nothing {
|
||||
throw IllegalArgumentException("Unknown element type: ${element::class}")
|
||||
}
|
||||
|
||||
// ------------------------------ factories for deprecation ------------------------------
|
||||
|
||||
sealed class FirDiagnosticFactoryForDeprecation<F : AbstractFirDiagnosticFactory>(
|
||||
val deprecatingFeature: LanguageFeature,
|
||||
val warningFactory: F,
|
||||
val errorFactory: F
|
||||
)
|
||||
|
||||
class FirDiagnosticFactoryForDeprecation0(
|
||||
featureForError: LanguageFeature,
|
||||
warningFactory: FirDiagnosticFactory0,
|
||||
errorFactory: FirDiagnosticFactory0
|
||||
) : FirDiagnosticFactoryForDeprecation<FirDiagnosticFactory0>(featureForError, warningFactory, errorFactory)
|
||||
|
||||
class FirDiagnosticFactoryForDeprecation1<A>(
|
||||
featureForError: LanguageFeature,
|
||||
warningFactory: FirDiagnosticFactory1<A>,
|
||||
errorFactory: FirDiagnosticFactory1<A>
|
||||
) : FirDiagnosticFactoryForDeprecation<FirDiagnosticFactory1<A>>(featureForError, warningFactory, errorFactory)
|
||||
|
||||
class FirDiagnosticFactoryForDeprecation2<A, B>(
|
||||
featureForError: LanguageFeature,
|
||||
warningFactory: FirDiagnosticFactory2<A, B>,
|
||||
errorFactory: FirDiagnosticFactory2<A, B>
|
||||
) : FirDiagnosticFactoryForDeprecation<FirDiagnosticFactory2<A, B>>(featureForError, warningFactory, errorFactory)
|
||||
|
||||
class FirDiagnosticFactoryForDeprecation3<A, B, C>(
|
||||
featureForError: LanguageFeature,
|
||||
warningFactory: FirDiagnosticFactory3<A, B, C>,
|
||||
errorFactory: FirDiagnosticFactory3<A, B, C>
|
||||
) : FirDiagnosticFactoryForDeprecation<FirDiagnosticFactory3<A, B, C>>(featureForError, warningFactory, errorFactory)
|
||||
|
||||
class FirDiagnosticFactoryForDeprecation4<A, B, C, D>(
|
||||
featureForError: LanguageFeature,
|
||||
warningFactory: FirDiagnosticFactory4<A, B, C, D>,
|
||||
errorFactory: FirDiagnosticFactory4<A, B, C, D>
|
||||
) : FirDiagnosticFactoryForDeprecation<FirDiagnosticFactory4<A, B, C, D>>(featureForError, warningFactory, errorFactory)
|
||||
|
||||
+99
@@ -6,6 +6,7 @@
|
||||
package org.jetbrains.kotlin.fir.analysis.diagnostics
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.diagnostics.Severity
|
||||
import kotlin.properties.ReadOnlyProperty
|
||||
import kotlin.reflect.KClass
|
||||
@@ -65,6 +66,41 @@ inline fun <reified P : PsiElement, A, B, C, D> error4(
|
||||
return DiagnosticFactory4DelegateProvider(Severity.ERROR, positioningStrategy, P::class)
|
||||
}
|
||||
|
||||
inline fun <reified P : PsiElement> deprecationError0(
|
||||
featureForError: LanguageFeature,
|
||||
positioningStrategy: SourceElementPositioningStrategy = SourceElementPositioningStrategy.DEFAULT
|
||||
): DeprecationDiagnosticFactory0DelegateProvider {
|
||||
return DeprecationDiagnosticFactory0DelegateProvider(featureForError, positioningStrategy, P::class)
|
||||
}
|
||||
|
||||
inline fun <reified P : PsiElement, A> deprecationError1(
|
||||
featureForError: LanguageFeature,
|
||||
positioningStrategy: SourceElementPositioningStrategy = SourceElementPositioningStrategy.DEFAULT
|
||||
): DeprecationDiagnosticFactory1DelegateProvider<A> {
|
||||
return DeprecationDiagnosticFactory1DelegateProvider(featureForError, positioningStrategy, P::class)
|
||||
}
|
||||
|
||||
inline fun <reified P : PsiElement, A, B> deprecationError2(
|
||||
featureForError: LanguageFeature,
|
||||
positioningStrategy: SourceElementPositioningStrategy = SourceElementPositioningStrategy.DEFAULT
|
||||
): DeprecationDiagnosticFactory2DelegateProvider<A, B> {
|
||||
return DeprecationDiagnosticFactory2DelegateProvider(featureForError, positioningStrategy, P::class)
|
||||
}
|
||||
|
||||
inline fun <reified P : PsiElement, A, B, C> deprecationError3(
|
||||
featureForError: LanguageFeature,
|
||||
positioningStrategy: SourceElementPositioningStrategy = SourceElementPositioningStrategy.DEFAULT
|
||||
): DeprecationDiagnosticFactory3DelegateProvider<A, B, C> {
|
||||
return DeprecationDiagnosticFactory3DelegateProvider(featureForError, positioningStrategy, P::class)
|
||||
}
|
||||
|
||||
inline fun <reified P : PsiElement, A, B, C, D> deprecationError4(
|
||||
featureForError: LanguageFeature,
|
||||
positioningStrategy: SourceElementPositioningStrategy = SourceElementPositioningStrategy.DEFAULT
|
||||
): DeprecationDiagnosticFactory4DelegateProvider<A, B, C, D> {
|
||||
return DeprecationDiagnosticFactory4DelegateProvider(featureForError, positioningStrategy, P::class)
|
||||
}
|
||||
|
||||
// ------------------------------ Providers ------------------------------
|
||||
|
||||
class DiagnosticFactory0DelegateProvider(
|
||||
@@ -117,6 +153,69 @@ class DiagnosticFactory4DelegateProvider<A, B, C, D>(
|
||||
}
|
||||
}
|
||||
|
||||
private const val WARNING = "_WARNING"
|
||||
private const val ERROR = "_ERROR"
|
||||
|
||||
class DeprecationDiagnosticFactory0DelegateProvider(
|
||||
private val featureForError: LanguageFeature,
|
||||
private val positioningStrategy: SourceElementPositioningStrategy,
|
||||
private val psiType: KClass<*>
|
||||
) {
|
||||
operator fun provideDelegate(thisRef: Any?, prop: KProperty<*>): ReadOnlyProperty<Any?, FirDiagnosticFactoryForDeprecation0> {
|
||||
val errorFactory = FirDiagnosticFactory0("${prop.name}$ERROR", Severity.ERROR, positioningStrategy, psiType)
|
||||
val warningFactory = FirDiagnosticFactory0("${prop.name}$WARNING", Severity.WARNING, positioningStrategy, psiType)
|
||||
return DummyDelegate(FirDiagnosticFactoryForDeprecation0(featureForError, warningFactory, errorFactory))
|
||||
}
|
||||
}
|
||||
|
||||
class DeprecationDiagnosticFactory1DelegateProvider<A>(
|
||||
private val featureForError: LanguageFeature,
|
||||
private val positioningStrategy: SourceElementPositioningStrategy,
|
||||
private val psiType: KClass<*>
|
||||
) {
|
||||
operator fun provideDelegate(thisRef: Any?, prop: KProperty<*>): ReadOnlyProperty<Any?, FirDiagnosticFactoryForDeprecation1<A>> {
|
||||
val errorFactory = FirDiagnosticFactory1<A>("${prop.name}$ERROR", Severity.ERROR, positioningStrategy, psiType)
|
||||
val warningFactory = FirDiagnosticFactory1<A>("${prop.name}$WARNING", Severity.WARNING, positioningStrategy, psiType)
|
||||
return DummyDelegate(FirDiagnosticFactoryForDeprecation1(featureForError, warningFactory, errorFactory))
|
||||
}
|
||||
}
|
||||
|
||||
class DeprecationDiagnosticFactory2DelegateProvider<A, B>(
|
||||
private val featureForError: LanguageFeature,
|
||||
private val positioningStrategy: SourceElementPositioningStrategy,
|
||||
private val psiType: KClass<*>
|
||||
) {
|
||||
operator fun provideDelegate(thisRef: Any?, prop: KProperty<*>): ReadOnlyProperty<Any?, FirDiagnosticFactoryForDeprecation2<A, B>> {
|
||||
val errorFactory = FirDiagnosticFactory2<A, B>("${prop.name}$ERROR", Severity.ERROR, positioningStrategy, psiType)
|
||||
val warningFactory = FirDiagnosticFactory2<A, B>("${prop.name}$WARNING", Severity.WARNING, positioningStrategy, psiType)
|
||||
return DummyDelegate(FirDiagnosticFactoryForDeprecation2(featureForError, warningFactory, errorFactory))
|
||||
}
|
||||
}
|
||||
|
||||
class DeprecationDiagnosticFactory3DelegateProvider<A, B, C>(
|
||||
private val featureForError: LanguageFeature,
|
||||
private val positioningStrategy: SourceElementPositioningStrategy,
|
||||
private val psiType: KClass<*>
|
||||
) {
|
||||
operator fun provideDelegate(thisRef: Any?, prop: KProperty<*>): ReadOnlyProperty<Any?, FirDiagnosticFactoryForDeprecation3<A, B, C>> {
|
||||
val errorFactory = FirDiagnosticFactory3<A, B, C>("${prop.name}$ERROR", Severity.ERROR, positioningStrategy, psiType)
|
||||
val warningFactory = FirDiagnosticFactory3<A, B, C>("${prop.name}$WARNING", Severity.WARNING, positioningStrategy, psiType)
|
||||
return DummyDelegate(FirDiagnosticFactoryForDeprecation3(featureForError, warningFactory, errorFactory))
|
||||
}
|
||||
}
|
||||
|
||||
class DeprecationDiagnosticFactory4DelegateProvider<A, B, C, D>(
|
||||
private val featureForError: LanguageFeature,
|
||||
private val positioningStrategy: SourceElementPositioningStrategy,
|
||||
private val psiType: KClass<*>
|
||||
) {
|
||||
operator fun provideDelegate(thisRef: Any?, prop: KProperty<*>): ReadOnlyProperty<Any?, FirDiagnosticFactoryForDeprecation4<A, B, C, D>> {
|
||||
val errorFactory = FirDiagnosticFactory4<A, B, C, D>("${prop.name}$ERROR", Severity.ERROR, positioningStrategy, psiType)
|
||||
val warningFactory = FirDiagnosticFactory4<A, B, C, D>("${prop.name}$WARNING", Severity.WARNING, positioningStrategy, psiType)
|
||||
return DummyDelegate(FirDiagnosticFactoryForDeprecation4(featureForError, warningFactory, errorFactory))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private class DummyDelegate<T>(val value: T) : ReadOnlyProperty<Any?, T> {
|
||||
override fun getValue(thisRef: Any?, property: KProperty<*>): T {
|
||||
|
||||
+61
@@ -54,7 +54,68 @@ class FirDiagnosticFactoryToRendererMap(val name: String) {
|
||||
put(factory, FirDiagnosticWithParameters4Renderer(message, rendererA, rendererB, rendererC, rendererD))
|
||||
}
|
||||
|
||||
fun put(factory: FirDiagnosticFactoryForDeprecation0, message: String) {
|
||||
put(factory.errorFactory, SimpleFirDiagnosticRenderer(message))
|
||||
put(factory.warningFactory, SimpleFirDiagnosticRenderer(factory.warningMessage(message)))
|
||||
}
|
||||
|
||||
fun <A> put(
|
||||
factory: FirDiagnosticFactoryForDeprecation1<A>,
|
||||
message: String,
|
||||
rendererA: DiagnosticParameterRenderer<A>?
|
||||
) {
|
||||
put(factory.errorFactory, FirDiagnosticWithParameters1Renderer(message, rendererA))
|
||||
put(factory.warningFactory, FirDiagnosticWithParameters1Renderer(factory.warningMessage(message), rendererA))
|
||||
}
|
||||
|
||||
fun <A, B> put(
|
||||
factory: FirDiagnosticFactoryForDeprecation2<A, B>,
|
||||
message: String,
|
||||
rendererA: DiagnosticParameterRenderer<A>?,
|
||||
rendererB: DiagnosticParameterRenderer<B>?
|
||||
) {
|
||||
put(factory.errorFactory, FirDiagnosticWithParameters2Renderer(message, rendererA, rendererB))
|
||||
put(factory.warningFactory, FirDiagnosticWithParameters2Renderer(factory.warningMessage(message), rendererA, rendererB))
|
||||
}
|
||||
|
||||
fun <A, B, C> put(
|
||||
factory: FirDiagnosticFactoryForDeprecation3<A, B, C>,
|
||||
message: String,
|
||||
rendererA: DiagnosticParameterRenderer<A>?,
|
||||
rendererB: DiagnosticParameterRenderer<B>?,
|
||||
rendererC: DiagnosticParameterRenderer<C>?
|
||||
) {
|
||||
put(factory.errorFactory, FirDiagnosticWithParameters3Renderer(message, rendererA, rendererB, rendererC))
|
||||
put(factory.warningFactory, FirDiagnosticWithParameters3Renderer(factory.warningMessage(message), rendererA, rendererB, rendererC))
|
||||
}
|
||||
|
||||
fun <A, B, C, D> put(
|
||||
factory: FirDiagnosticFactoryForDeprecation4<A, B, C, D>,
|
||||
message: String,
|
||||
rendererA: DiagnosticParameterRenderer<A>?,
|
||||
rendererB: DiagnosticParameterRenderer<B>?,
|
||||
rendererC: DiagnosticParameterRenderer<C>?,
|
||||
rendererD: DiagnosticParameterRenderer<D>?
|
||||
) {
|
||||
put(factory.errorFactory, FirDiagnosticWithParameters4Renderer(message, rendererA, rendererB, rendererC, rendererD))
|
||||
put(factory.warningFactory, FirDiagnosticWithParameters4Renderer(factory.warningMessage(message), rendererA, rendererB, rendererC, rendererD))
|
||||
}
|
||||
|
||||
private fun put(factory: AbstractFirDiagnosticFactory, renderer: FirDiagnosticRenderer) {
|
||||
renderersMap[factory] = renderer
|
||||
}
|
||||
|
||||
private fun FirDiagnosticFactoryForDeprecation<*>.warningMessage(errorMessage: String): String {
|
||||
return buildString {
|
||||
append(errorMessage)
|
||||
append(". This will become an error")
|
||||
val sinceVersion = deprecatingFeature.sinceVersion
|
||||
if (sinceVersion != null) {
|
||||
append(" in Kotlin ")
|
||||
append(sinceVersion.versionString)
|
||||
} else {
|
||||
append(" in a future release")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
@@ -5,12 +5,14 @@
|
||||
|
||||
package org.jetbrains.kotlin.idea.frontend.api.fir.generator
|
||||
|
||||
import org.jetbrains.kotlin.diagnostics.Severity
|
||||
import org.jetbrains.kotlin.fir.checkers.generator.diagnostics.model.DiagnosticData
|
||||
import org.jetbrains.kotlin.fir.checkers.generator.diagnostics.model.DiagnosticParameter
|
||||
import kotlin.reflect.KType
|
||||
|
||||
data class HLDiagnostic(
|
||||
val original: DiagnosticData,
|
||||
val severity: Severity?,
|
||||
val className: String,
|
||||
val implClassName: String,
|
||||
val parameters: List<HLDiagnosticParameter>,
|
||||
|
||||
+44
-17
@@ -11,11 +11,10 @@ import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||
import org.jetbrains.kotlin.contracts.description.EventOccurrencesRange
|
||||
import org.jetbrains.kotlin.descriptors.EffectiveVisibility
|
||||
import org.jetbrains.kotlin.descriptors.Visibility
|
||||
import org.jetbrains.kotlin.diagnostics.Severity
|
||||
import org.jetbrains.kotlin.diagnostics.WhenMissingCase
|
||||
import org.jetbrains.kotlin.fir.FirModuleData
|
||||
import org.jetbrains.kotlin.fir.checkers.generator.diagnostics.model.DiagnosticData
|
||||
import org.jetbrains.kotlin.fir.checkers.generator.diagnostics.model.DiagnosticList
|
||||
import org.jetbrains.kotlin.fir.checkers.generator.diagnostics.model.DiagnosticParameter
|
||||
import org.jetbrains.kotlin.fir.checkers.generator.diagnostics.model.*
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccess
|
||||
@@ -39,16 +38,33 @@ import kotlin.reflect.full.createType
|
||||
import kotlin.reflect.full.isSubclassOf
|
||||
|
||||
object HLDiagnosticConverter {
|
||||
fun convert(diagnosticList: DiagnosticList): HLDiagnosticList =
|
||||
HLDiagnosticList(diagnosticList.allDiagnostics.map(::convertDiagnostic))
|
||||
@OptIn(ExperimentalStdlibApi::class)
|
||||
fun convert(diagnosticList: DiagnosticList): HLDiagnosticList {
|
||||
return HLDiagnosticList(diagnosticList.allDiagnostics.flatMap(::convertDiagnostic))
|
||||
}
|
||||
|
||||
private fun convertDiagnostic(diagnostic: DiagnosticData): HLDiagnostic =
|
||||
HLDiagnostic(
|
||||
original = diagnostic,
|
||||
className = diagnostic.getHLDiagnosticClassName(),
|
||||
implClassName = diagnostic.getHLDiagnosticImplClassName(),
|
||||
parameters = diagnostic.parameters.mapIndexed(::convertParameter)
|
||||
)
|
||||
private fun convertDiagnostic(diagnostic: DiagnosticData): List<HLDiagnostic> {
|
||||
return when (diagnostic){
|
||||
is RegularDiagnosticData -> listOf(
|
||||
HLDiagnostic(
|
||||
original = diagnostic,
|
||||
severity = null,
|
||||
className = diagnostic.getHLDiagnosticClassName(),
|
||||
implClassName = diagnostic.getHLDiagnosticImplClassName(),
|
||||
parameters = diagnostic.parameters.mapIndexed(::convertParameter)
|
||||
)
|
||||
)
|
||||
is DeprecationDiagnosticData -> listOf(Severity.ERROR, Severity.WARNING).map {
|
||||
HLDiagnostic(
|
||||
original = diagnostic,
|
||||
severity = it,
|
||||
className = diagnostic.getHLDiagnosticClassName(it),
|
||||
implClassName = diagnostic.getHLDiagnosticImplClassName(it),
|
||||
parameters = diagnostic.parameters.mapIndexed(::convertParameter)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun convertParameter(index: Int, diagnosticParameter: DiagnosticParameter): HLDiagnosticParameter {
|
||||
val conversion = FirToKtConversionCreator.createConversion(diagnosticParameter.type)
|
||||
@@ -63,16 +79,27 @@ object HLDiagnosticConverter {
|
||||
)
|
||||
}
|
||||
|
||||
private fun DiagnosticData.getHLDiagnosticClassName() =
|
||||
name.lowercase()
|
||||
private fun RegularDiagnosticData.getHLDiagnosticClassName(): String = name.sanitizeName()
|
||||
|
||||
private fun RegularDiagnosticData.getHLDiagnosticImplClassName(): String =
|
||||
"${getHLDiagnosticClassName()}Impl"
|
||||
|
||||
private fun DeprecationDiagnosticData.getHLDiagnosticClassName(severity: Severity): String {
|
||||
val diagnosticName = "${name}_${severity.name}"
|
||||
return diagnosticName.sanitizeName()
|
||||
}
|
||||
|
||||
private fun DeprecationDiagnosticData.getHLDiagnosticImplClassName(severity: Severity): String {
|
||||
return "${getHLDiagnosticClassName(severity)}Impl"
|
||||
}
|
||||
|
||||
private fun String.sanitizeName(): String =
|
||||
lowercase()
|
||||
.split('_')
|
||||
.joinToString(separator = "") {
|
||||
it.replaceFirstChar(Char::uppercaseChar)
|
||||
}
|
||||
|
||||
private fun DiagnosticData.getHLDiagnosticImplClassName() =
|
||||
"${getHLDiagnosticClassName()}Impl"
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
+5
-1
@@ -28,7 +28,11 @@ object FirDiagnosticToKtDiagnosticConverterRenderer : AbstractDiagnosticsDataCla
|
||||
}
|
||||
|
||||
private fun SmartPrinter.printConverter(diagnostic: HLDiagnostic) {
|
||||
println("add(${diagnostic.original.containingObjectName}.${diagnostic.original.name}) { firDiagnostic ->")
|
||||
print("add(${diagnostic.original.containingObjectName}.${diagnostic.original.name}")
|
||||
if (diagnostic.severity != null) {
|
||||
print(".${diagnostic.severity.name.lowercase()}Factory")
|
||||
}
|
||||
println(") { firDiagnostic ->")
|
||||
withIndent {
|
||||
println("${diagnostic.implClassName}(")
|
||||
withIndent {
|
||||
|
||||
Reference in New Issue
Block a user