Move common diagnostics infrastructure to frontend.common

This commit is contained in:
Ilya Chernikov
2021-09-20 19:21:31 +02:00
parent f1d0ead652
commit e9f59e8d1d
253 changed files with 404 additions and 341 deletions
@@ -0,0 +1,32 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.diagnostics
import com.intellij.openapi.util.TextRange
import org.jetbrains.kotlin.KtSourceElement
abstract class AbstractSourceElementPositioningStrategy {
abstract fun markDiagnostic(diagnostic: KtDiagnostic): List<TextRange>
abstract fun isValid(element: KtSourceElement): Boolean
companion object {
private val defaultProxy = object : AbstractSourceElementPositioningStrategy() {
lateinit var currentDefault: AbstractSourceElementPositioningStrategy
override fun markDiagnostic(diagnostic: KtDiagnostic): List<TextRange> = currentDefault.markDiagnostic(diagnostic)
override fun isValid(element: KtSourceElement): Boolean = currentDefault.isValid(element)
}
@JvmStatic
fun setDefault(default: AbstractSourceElementPositioningStrategy) {
defaultProxy.currentDefault = default
}
val DEFAULT: AbstractSourceElementPositioningStrategy = defaultProxy
}
}
@@ -0,0 +1,35 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.diagnostics
import com.intellij.psi.PsiElement
interface DiagnosticMarker {
val psiElement: PsiElement
val factoryName: String
}
interface DiagnosticWithParameters1Marker<A> : DiagnosticMarker {
val a: A
}
interface DiagnosticWithParameters2Marker<A, B> : DiagnosticMarker {
val a: A
val b: B
}
interface DiagnosticWithParameters3Marker<A, B, C> : DiagnosticMarker {
val a: A
val b: B
val c: C
}
interface DiagnosticWithParameters4Marker<A, B, C, D> : DiagnosticMarker {
val a: A
val b: B
val c: C
val d: D
}
@@ -0,0 +1,25 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.diagnostics
import org.jetbrains.kotlin.config.LanguageVersionSettings
interface DiagnosticContext {
fun isDiagnosticSuppressed(diagnostic: KtDiagnostic): Boolean
fun addSuppressedDiagnostics(
diagnosticNames: Collection<String>,
allInfosSuppressed: Boolean,
allWarningsSuppressed: Boolean,
allErrorsSuppressed: Boolean
): DiagnosticContext
val languageVersionSettings: LanguageVersionSettings
}
abstract class DiagnosticReporter {
abstract fun report(diagnostic: KtDiagnostic?, context: DiagnosticContext)
}
@@ -0,0 +1,20 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.diagnostics
import org.jetbrains.kotlin.diagnostics.impl.BaseDiagnosticReporter
import org.jetbrains.kotlin.diagnostics.impl.DiagnosticReporterWithSuppress
import org.jetbrains.kotlin.diagnostics.impl.SimpleDiagnosticReporter
object DiagnosticReporterFactory {
fun createReporter(disableSuppress: Boolean = false): BaseDiagnosticReporter {
return if (disableSuppress) {
SimpleDiagnosticReporter()
} else {
DiagnosticReporterWithSuppress()
}
}
}
@@ -0,0 +1,208 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.diagnostics
import com.intellij.openapi.util.TextRange
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiFile
import org.jetbrains.kotlin.KtLightSourceElement
import org.jetbrains.kotlin.KtPsiSourceElement
import org.jetbrains.kotlin.KtSourceElement
import org.jetbrains.kotlin.diagnostics.*
// ------------------------------ diagnostics ------------------------------
sealed class KtDiagnostic : DiagnosticMarker {
abstract val element: KtSourceElement
abstract val severity: Severity
abstract val factory: AbstractKtDiagnosticFactory
abstract val positioningStrategy: AbstractSourceElementPositioningStrategy
val textRanges: List<TextRange>
get() = positioningStrategy.markDiagnostic(this)
val isValid: Boolean
get() = positioningStrategy.isValid(element)
override val factoryName: String
get() = factory.name
}
sealed class KtSimpleDiagnostic : KtDiagnostic() {
abstract override val factory: KtDiagnosticFactory0
}
sealed class KtDiagnosticWithParameters1<A> : KtDiagnostic(), DiagnosticWithParameters1Marker<A> {
abstract override val a: A
abstract override val factory: KtDiagnosticFactory1<A>
}
sealed class KtDiagnosticWithParameters2<A, B> : KtDiagnostic(), DiagnosticWithParameters2Marker<A, B> {
abstract override val a: A
abstract override val b: B
abstract override val factory: KtDiagnosticFactory2<A, B>
}
sealed class KtDiagnosticWithParameters3<A, B, C> : KtDiagnostic(), DiagnosticWithParameters3Marker<A, B, C> {
abstract override val a: A
abstract override val b: B
abstract override val c: C
abstract override val factory: KtDiagnosticFactory3<A, B, C>
}
sealed class KtDiagnosticWithParameters4<A, B, C, D> : KtDiagnostic(), DiagnosticWithParameters4Marker<A, B, C, D> {
abstract override val a: A
abstract override val b: B
abstract override val c: C
abstract override val d: D
abstract override val factory: KtDiagnosticFactory4<A, B, C, D>
}
// ------------------------------ psi diagnostics ------------------------------
interface KtPsiDiagnostic : DiagnosticMarker {
val factory: AbstractKtDiagnosticFactory
val element: KtPsiSourceElement
val textRanges: List<TextRange>
val severity: Severity
override val psiElement: PsiElement
get() = element.psi
val psiFile: PsiFile
get() = psiElement.containingFile
}
private const val CHECK_PSI_CONSISTENCY_IN_DIAGNOSTICS = true
private fun KtPsiDiagnostic.checkPsiTypeConsistency() {
if (CHECK_PSI_CONSISTENCY_IN_DIAGNOSTICS) {
require(factory.psiType.isInstance(element.psi)) {
"${element.psi::class} is not a subtype of ${factory.psiType} for factory $factory"
}
}
}
data class KtPsiSimpleDiagnostic(
override val element: KtPsiSourceElement,
override val severity: Severity,
override val factory: KtDiagnosticFactory0,
override val positioningStrategy: AbstractSourceElementPositioningStrategy
) : KtSimpleDiagnostic(), KtPsiDiagnostic {
init {
checkPsiTypeConsistency()
}
}
data class KtPsiDiagnosticWithParameters1<A>(
override val element: KtPsiSourceElement,
override val a: A,
override val severity: Severity,
override val factory: KtDiagnosticFactory1<A>,
override val positioningStrategy: AbstractSourceElementPositioningStrategy
) : KtDiagnosticWithParameters1<A>(), KtPsiDiagnostic {
init {
checkPsiTypeConsistency()
}
}
data class KtPsiDiagnosticWithParameters2<A, B>(
override val element: KtPsiSourceElement,
override val a: A,
override val b: B,
override val severity: Severity,
override val factory: KtDiagnosticFactory2<A, B>,
override val positioningStrategy: AbstractSourceElementPositioningStrategy
) : KtDiagnosticWithParameters2<A, B>(), KtPsiDiagnostic {
init {
checkPsiTypeConsistency()
}
}
data class KtPsiDiagnosticWithParameters3<A, B, C>(
override val element: KtPsiSourceElement,
override val a: A,
override val b: B,
override val c: C,
override val severity: Severity,
override val factory: KtDiagnosticFactory3<A, B, C>,
override val positioningStrategy: AbstractSourceElementPositioningStrategy
) : KtDiagnosticWithParameters3<A, B, C>(), KtPsiDiagnostic {
init {
checkPsiTypeConsistency()
}
}
data class KtPsiDiagnosticWithParameters4<A, B, C, D>(
override val element: KtPsiSourceElement,
override val a: A,
override val b: B,
override val c: C,
override val d: D,
override val severity: Severity,
override val factory: KtDiagnosticFactory4<A, B, C, D>,
override val positioningStrategy: AbstractSourceElementPositioningStrategy
) : KtDiagnosticWithParameters4<A, B, C, D>(), KtPsiDiagnostic {
init {
checkPsiTypeConsistency()
}
}
// ------------------------------ light tree diagnostics ------------------------------
interface KtLightDiagnostic : DiagnosticMarker {
val element: KtLightSourceElement
@Deprecated("Should not be called", level = DeprecationLevel.HIDDEN)
override val psiElement: PsiElement
get() = error("psiElement should not be called on KtLightDiagnostic")
}
data class KtLightSimpleDiagnostic(
override val element: KtLightSourceElement,
override val severity: Severity,
override val factory: KtDiagnosticFactory0,
override val positioningStrategy: AbstractSourceElementPositioningStrategy
) : KtSimpleDiagnostic(), KtLightDiagnostic
data class KtLightDiagnosticWithParameters1<A>(
override val element: KtLightSourceElement,
override val a: A,
override val severity: Severity,
override val factory: KtDiagnosticFactory1<A>,
override val positioningStrategy: AbstractSourceElementPositioningStrategy
) : KtDiagnosticWithParameters1<A>(), KtLightDiagnostic
data class KtLightDiagnosticWithParameters2<A, B>(
override val element: KtLightSourceElement,
override val a: A,
override val b: B,
override val severity: Severity,
override val factory: KtDiagnosticFactory2<A, B>,
override val positioningStrategy: AbstractSourceElementPositioningStrategy
) : KtDiagnosticWithParameters2<A, B>(), KtLightDiagnostic
data class KtLightDiagnosticWithParameters3<A, B, C>(
override val element: KtLightSourceElement,
override val a: A,
override val b: B,
override val c: C,
override val severity: Severity,
override val factory: KtDiagnosticFactory3<A, B, C>,
override val positioningStrategy: AbstractSourceElementPositioningStrategy
) : KtDiagnosticWithParameters3<A, B, C>(), KtLightDiagnostic
data class KtLightDiagnosticWithParameters4<A, B, C, D>(
override val element: KtLightSourceElement,
override val a: A,
override val b: B,
override val c: C,
override val d: D,
override val severity: Severity,
override val factory: KtDiagnosticFactory4<A, B, C, D>,
override val positioningStrategy: AbstractSourceElementPositioningStrategy
) : KtDiagnosticWithParameters4<A, B, C, D>(), KtLightDiagnostic
@@ -0,0 +1,240 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
@file:Suppress("UNCHECKED_CAST")
package org.jetbrains.kotlin.diagnostics
import org.jetbrains.kotlin.KtLightSourceElement
import org.jetbrains.kotlin.KtPsiSourceElement
import org.jetbrains.kotlin.KtSourceElement
import org.jetbrains.kotlin.config.LanguageFeature
import kotlin.reflect.KClass
@RequiresOptIn("Please use DiagnosticReporter.reportOn method if possible")
annotation class InternalDiagnosticFactoryMethod
sealed class AbstractKtDiagnosticFactory(
val name: String,
val severity: Severity,
val defaultPositioningStrategy: AbstractSourceElementPositioningStrategy,
val psiType: KClass<*>
) {
abstract val ktRenderer: KtDiagnosticRenderer
override fun toString(): String {
return name
}
}
class KtDiagnosticFactory0(
name: String,
severity: Severity,
defaultPositioningStrategy: AbstractSourceElementPositioningStrategy,
psiType: KClass<*>
) : AbstractKtDiagnosticFactory(name, severity, defaultPositioningStrategy, psiType) {
override val ktRenderer: KtDiagnosticRenderer = SimpleKtDiagnosticRenderer("")
@InternalDiagnosticFactoryMethod
fun on(
element: KtSourceElement,
positioningStrategy: AbstractSourceElementPositioningStrategy?
): KtSimpleDiagnostic {
return when (element) {
is KtPsiSourceElement -> KtPsiSimpleDiagnostic(
element, severity, this, positioningStrategy ?: defaultPositioningStrategy
)
is KtLightSourceElement -> KtLightSimpleDiagnostic(element, severity, this, positioningStrategy ?: defaultPositioningStrategy)
}
}
}
class KtDiagnosticFactory1<A>(
name: String,
severity: Severity,
defaultPositioningStrategy: AbstractSourceElementPositioningStrategy,
psiType: KClass<*>
) : AbstractKtDiagnosticFactory(name, severity, defaultPositioningStrategy, psiType) {
override val ktRenderer: KtDiagnosticRenderer = KtDiagnosticWithParameters1Renderer(
"{0}",
KtDiagnosticRenderers.TO_STRING
)
@InternalDiagnosticFactoryMethod
fun on(
element: KtSourceElement,
a: A,
positioningStrategy: AbstractSourceElementPositioningStrategy?
): KtDiagnosticWithParameters1<A> {
return when (element) {
is KtPsiSourceElement -> KtPsiDiagnosticWithParameters1(
element, a, severity, this, positioningStrategy ?: defaultPositioningStrategy
)
is KtLightSourceElement -> KtLightDiagnosticWithParameters1(
element,
a,
severity,
this,
positioningStrategy ?: defaultPositioningStrategy
)
}
}
}
class KtDiagnosticFactory2<A, B>(
name: String,
severity: Severity,
defaultPositioningStrategy: AbstractSourceElementPositioningStrategy,
psiType: KClass<*>
) : AbstractKtDiagnosticFactory(name, severity, defaultPositioningStrategy, psiType) {
override val ktRenderer: KtDiagnosticRenderer = KtDiagnosticWithParameters2Renderer(
"{0}, {1}",
KtDiagnosticRenderers.TO_STRING,
KtDiagnosticRenderers.TO_STRING
)
@InternalDiagnosticFactoryMethod
fun on(
element: KtSourceElement,
a: A,
b: B,
positioningStrategy: AbstractSourceElementPositioningStrategy?
): KtDiagnosticWithParameters2<A, B> {
return when (element) {
is KtPsiSourceElement -> KtPsiDiagnosticWithParameters2(
element, a, b, severity, this, positioningStrategy ?: defaultPositioningStrategy
)
is KtLightSourceElement -> KtLightDiagnosticWithParameters2(
element,
a,
b,
severity,
this,
positioningStrategy ?: defaultPositioningStrategy
)
}
}
}
class KtDiagnosticFactory3<A, B, C>(
name: String,
severity: Severity,
defaultPositioningStrategy: AbstractSourceElementPositioningStrategy,
psiType: KClass<*>
) : AbstractKtDiagnosticFactory(name, severity, defaultPositioningStrategy, psiType) {
override val ktRenderer: KtDiagnosticRenderer = KtDiagnosticWithParameters3Renderer(
"{0}, {1}, {2}",
KtDiagnosticRenderers.TO_STRING,
KtDiagnosticRenderers.TO_STRING,
KtDiagnosticRenderers.TO_STRING
)
@InternalDiagnosticFactoryMethod
fun on(
element: KtSourceElement,
a: A,
b: B,
c: C,
positioningStrategy: AbstractSourceElementPositioningStrategy?
): KtDiagnosticWithParameters3<A, B, C> {
return when (element) {
is KtPsiSourceElement -> KtPsiDiagnosticWithParameters3(
element, a, b, c, severity, this, positioningStrategy ?: defaultPositioningStrategy
)
is KtLightSourceElement -> KtLightDiagnosticWithParameters3(
element,
a,
b,
c,
severity,
this,
positioningStrategy ?: defaultPositioningStrategy
)
}
}
}
class KtDiagnosticFactory4<A, B, C, D>(
name: String,
severity: Severity,
defaultPositioningStrategy: AbstractSourceElementPositioningStrategy,
psiType: KClass<*>
) : AbstractKtDiagnosticFactory(name, severity, defaultPositioningStrategy, psiType) {
override val ktRenderer: KtDiagnosticRenderer = KtDiagnosticWithParameters4Renderer(
"{0}, {1}, {2}, {3}",
KtDiagnosticRenderers.TO_STRING,
KtDiagnosticRenderers.TO_STRING,
KtDiagnosticRenderers.TO_STRING,
KtDiagnosticRenderers.TO_STRING
)
@InternalDiagnosticFactoryMethod
fun on(
element: KtSourceElement,
a: A,
b: B,
c: C,
d: D,
positioningStrategy: AbstractSourceElementPositioningStrategy?
): KtDiagnosticWithParameters4<A, B, C, D> {
return when (element) {
is KtPsiSourceElement -> KtPsiDiagnosticWithParameters4(
element, a, b, c, d, severity, this, positioningStrategy ?: defaultPositioningStrategy
)
is KtLightSourceElement -> KtLightDiagnosticWithParameters4(
element,
a,
b,
c,
d,
severity,
this,
positioningStrategy ?: defaultPositioningStrategy
)
}
}
}
private fun incorrectElement(element: KtSourceElement): Nothing {
throw IllegalArgumentException("Unknown element type: ${element::class}")
}
// ------------------------------ factories for deprecation ------------------------------
sealed class KtDiagnosticFactoryForDeprecation<F : AbstractKtDiagnosticFactory>(
val deprecatingFeature: LanguageFeature,
val warningFactory: F,
val errorFactory: F
)
class KtDiagnosticFactoryForDeprecation0(
featureForError: LanguageFeature,
warningFactory: KtDiagnosticFactory0,
errorFactory: KtDiagnosticFactory0
) : KtDiagnosticFactoryForDeprecation<KtDiagnosticFactory0>(featureForError, warningFactory, errorFactory)
class KtDiagnosticFactoryForDeprecation1<A>(
featureForError: LanguageFeature,
warningFactory: KtDiagnosticFactory1<A>,
errorFactory: KtDiagnosticFactory1<A>
) : KtDiagnosticFactoryForDeprecation<KtDiagnosticFactory1<A>>(featureForError, warningFactory, errorFactory)
class KtDiagnosticFactoryForDeprecation2<A, B>(
featureForError: LanguageFeature,
warningFactory: KtDiagnosticFactory2<A, B>,
errorFactory: KtDiagnosticFactory2<A, B>
) : KtDiagnosticFactoryForDeprecation<KtDiagnosticFactory2<A, B>>(featureForError, warningFactory, errorFactory)
class KtDiagnosticFactoryForDeprecation3<A, B, C>(
featureForError: LanguageFeature,
warningFactory: KtDiagnosticFactory3<A, B, C>,
errorFactory: KtDiagnosticFactory3<A, B, C>
) : KtDiagnosticFactoryForDeprecation<KtDiagnosticFactory3<A, B, C>>(featureForError, warningFactory, errorFactory)
class KtDiagnosticFactoryForDeprecation4<A, B, C, D>(
featureForError: LanguageFeature,
warningFactory: KtDiagnosticFactory4<A, B, C, D>,
errorFactory: KtDiagnosticFactory4<A, B, C, D>
) : KtDiagnosticFactoryForDeprecation<KtDiagnosticFactory4<A, B, C, D>>(featureForError, warningFactory, errorFactory)
@@ -0,0 +1,229 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.diagnostics
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.config.LanguageFeature
import kotlin.properties.ReadOnlyProperty
import kotlin.reflect.KClass
import kotlin.reflect.KProperty
inline fun <reified P : PsiElement> warning0(
positioningStrategy: AbstractSourceElementPositioningStrategy = AbstractSourceElementPositioningStrategy.DEFAULT
): DiagnosticFactory0DelegateProvider {
return DiagnosticFactory0DelegateProvider(Severity.WARNING, positioningStrategy, P::class)
}
inline fun <reified P : PsiElement, A> warning1(
positioningStrategy: AbstractSourceElementPositioningStrategy = AbstractSourceElementPositioningStrategy.DEFAULT
): DiagnosticFactory1DelegateProvider<A> {
return DiagnosticFactory1DelegateProvider(Severity.WARNING, positioningStrategy, P::class)
}
inline fun <reified P : PsiElement, A, B> warning2(
positioningStrategy: AbstractSourceElementPositioningStrategy = AbstractSourceElementPositioningStrategy.DEFAULT
): DiagnosticFactory2DelegateProvider<A, B> {
return DiagnosticFactory2DelegateProvider(Severity.WARNING, positioningStrategy, P::class)
}
inline fun <reified P : PsiElement, A, B, C> warning3(
positioningStrategy: AbstractSourceElementPositioningStrategy = AbstractSourceElementPositioningStrategy.DEFAULT
): DiagnosticFactory3DelegateProvider<A, B, C> {
return DiagnosticFactory3DelegateProvider(Severity.WARNING, positioningStrategy, P::class)
}
inline fun <reified P : PsiElement, A, B, C, D> warning4(
positioningStrategy: AbstractSourceElementPositioningStrategy = AbstractSourceElementPositioningStrategy.DEFAULT
): DiagnosticFactory4DelegateProvider<A, B, C, D> {
return DiagnosticFactory4DelegateProvider(Severity.WARNING, positioningStrategy, P::class)
}
inline fun <reified P : PsiElement> error0(
positioningStrategy: AbstractSourceElementPositioningStrategy = AbstractSourceElementPositioningStrategy.DEFAULT
): DiagnosticFactory0DelegateProvider {
return DiagnosticFactory0DelegateProvider(Severity.ERROR, positioningStrategy, P::class)
}
inline fun <reified P : PsiElement, A> error1(
positioningStrategy: AbstractSourceElementPositioningStrategy = AbstractSourceElementPositioningStrategy.DEFAULT
): DiagnosticFactory1DelegateProvider<A> {
return DiagnosticFactory1DelegateProvider(Severity.ERROR, positioningStrategy, P::class)
}
inline fun <reified P : PsiElement, A, B> error2(
positioningStrategy: AbstractSourceElementPositioningStrategy = AbstractSourceElementPositioningStrategy.DEFAULT
): DiagnosticFactory2DelegateProvider<A, B> {
return DiagnosticFactory2DelegateProvider(Severity.ERROR, positioningStrategy, P::class)
}
inline fun <reified P : PsiElement, A, B, C> error3(
positioningStrategy: AbstractSourceElementPositioningStrategy = AbstractSourceElementPositioningStrategy.DEFAULT
): DiagnosticFactory3DelegateProvider<A, B, C> {
return DiagnosticFactory3DelegateProvider(Severity.ERROR, positioningStrategy, P::class)
}
inline fun <reified P : PsiElement, A, B, C, D> error4(
positioningStrategy: AbstractSourceElementPositioningStrategy = AbstractSourceElementPositioningStrategy.DEFAULT
): DiagnosticFactory4DelegateProvider<A, B, C, D> {
return DiagnosticFactory4DelegateProvider(Severity.ERROR, positioningStrategy, P::class)
}
inline fun <reified P : PsiElement> deprecationError0(
featureForError: LanguageFeature,
positioningStrategy: AbstractSourceElementPositioningStrategy = AbstractSourceElementPositioningStrategy.DEFAULT
): DeprecationDiagnosticFactory0DelegateProvider {
return DeprecationDiagnosticFactory0DelegateProvider(featureForError, positioningStrategy, P::class)
}
inline fun <reified P : PsiElement, A> deprecationError1(
featureForError: LanguageFeature,
positioningStrategy: AbstractSourceElementPositioningStrategy = AbstractSourceElementPositioningStrategy.DEFAULT
): DeprecationDiagnosticFactory1DelegateProvider<A> {
return DeprecationDiagnosticFactory1DelegateProvider(featureForError, positioningStrategy, P::class)
}
inline fun <reified P : PsiElement, A, B> deprecationError2(
featureForError: LanguageFeature,
positioningStrategy: AbstractSourceElementPositioningStrategy = AbstractSourceElementPositioningStrategy.DEFAULT
): DeprecationDiagnosticFactory2DelegateProvider<A, B> {
return DeprecationDiagnosticFactory2DelegateProvider(featureForError, positioningStrategy, P::class)
}
inline fun <reified P : PsiElement, A, B, C> deprecationError3(
featureForError: LanguageFeature,
positioningStrategy: AbstractSourceElementPositioningStrategy = AbstractSourceElementPositioningStrategy.DEFAULT
): DeprecationDiagnosticFactory3DelegateProvider<A, B, C> {
return DeprecationDiagnosticFactory3DelegateProvider(featureForError, positioningStrategy, P::class)
}
inline fun <reified P : PsiElement, A, B, C, D> deprecationError4(
featureForError: LanguageFeature,
positioningStrategy: AbstractSourceElementPositioningStrategy = AbstractSourceElementPositioningStrategy.DEFAULT
): DeprecationDiagnosticFactory4DelegateProvider<A, B, C, D> {
return DeprecationDiagnosticFactory4DelegateProvider(featureForError, positioningStrategy, P::class)
}
// ------------------------------ Providers ------------------------------
class DiagnosticFactory0DelegateProvider(
private val severity: Severity,
private val positioningStrategy: AbstractSourceElementPositioningStrategy,
private val psiType: KClass<*>
) {
operator fun provideDelegate(thisRef: Any?, prop: KProperty<*>): ReadOnlyProperty<Any?, KtDiagnosticFactory0> {
return DummyDelegate(KtDiagnosticFactory0(prop.name, severity, positioningStrategy, psiType))
}
}
class DiagnosticFactory1DelegateProvider<A>(
private val severity: Severity,
private val positioningStrategy: AbstractSourceElementPositioningStrategy,
private val psiType: KClass<*>
) {
operator fun provideDelegate(thisRef: Any?, prop: KProperty<*>): ReadOnlyProperty<Any?, KtDiagnosticFactory1<A>> {
return DummyDelegate(KtDiagnosticFactory1(prop.name, severity, positioningStrategy, psiType))
}
}
class DiagnosticFactory2DelegateProvider<A, B>(
private val severity: Severity,
private val positioningStrategy: AbstractSourceElementPositioningStrategy,
private val psiType: KClass<*>
) {
operator fun provideDelegate(thisRef: Any?, prop: KProperty<*>): ReadOnlyProperty<Any?, KtDiagnosticFactory2<A, B>> {
return DummyDelegate(KtDiagnosticFactory2(prop.name, severity, positioningStrategy, psiType))
}
}
class DiagnosticFactory3DelegateProvider<A, B, C>(
private val severity: Severity,
private val positioningStrategy: AbstractSourceElementPositioningStrategy,
private val psiType: KClass<*>
) {
operator fun provideDelegate(thisRef: Any?, prop: KProperty<*>): ReadOnlyProperty<Any?, KtDiagnosticFactory3<A, B, C>> {
return DummyDelegate(KtDiagnosticFactory3(prop.name, severity, positioningStrategy, psiType))
}
}
class DiagnosticFactory4DelegateProvider<A, B, C, D>(
private val severity: Severity,
private val positioningStrategy: AbstractSourceElementPositioningStrategy,
private val psiType: KClass<*>
) {
operator fun provideDelegate(thisRef: Any?, prop: KProperty<*>): ReadOnlyProperty<Any?, KtDiagnosticFactory4<A, B, C, D>> {
return DummyDelegate(KtDiagnosticFactory4(prop.name, severity, positioningStrategy, psiType))
}
}
private const val WARNING = "_WARNING"
private const val ERROR = "_ERROR"
class DeprecationDiagnosticFactory0DelegateProvider(
private val featureForError: LanguageFeature,
private val positioningStrategy: AbstractSourceElementPositioningStrategy,
private val psiType: KClass<*>
) {
operator fun provideDelegate(thisRef: Any?, prop: KProperty<*>): ReadOnlyProperty<Any?, KtDiagnosticFactoryForDeprecation0> {
val errorFactory = KtDiagnosticFactory0("${prop.name}$ERROR", Severity.ERROR, positioningStrategy, psiType)
val warningFactory = KtDiagnosticFactory0("${prop.name}$WARNING", Severity.WARNING, positioningStrategy, psiType)
return DummyDelegate(KtDiagnosticFactoryForDeprecation0(featureForError, warningFactory, errorFactory))
}
}
class DeprecationDiagnosticFactory1DelegateProvider<A>(
private val featureForError: LanguageFeature,
private val positioningStrategy: AbstractSourceElementPositioningStrategy,
private val psiType: KClass<*>
) {
operator fun provideDelegate(thisRef: Any?, prop: KProperty<*>): ReadOnlyProperty<Any?, KtDiagnosticFactoryForDeprecation1<A>> {
val errorFactory = KtDiagnosticFactory1<A>("${prop.name}$ERROR", Severity.ERROR, positioningStrategy, psiType)
val warningFactory = KtDiagnosticFactory1<A>("${prop.name}$WARNING", Severity.WARNING, positioningStrategy, psiType)
return DummyDelegate(KtDiagnosticFactoryForDeprecation1(featureForError, warningFactory, errorFactory))
}
}
class DeprecationDiagnosticFactory2DelegateProvider<A, B>(
private val featureForError: LanguageFeature,
private val positioningStrategy: AbstractSourceElementPositioningStrategy,
private val psiType: KClass<*>
) {
operator fun provideDelegate(thisRef: Any?, prop: KProperty<*>): ReadOnlyProperty<Any?, KtDiagnosticFactoryForDeprecation2<A, B>> {
val errorFactory = KtDiagnosticFactory2<A, B>("${prop.name}$ERROR", Severity.ERROR, positioningStrategy, psiType)
val warningFactory = KtDiagnosticFactory2<A, B>("${prop.name}$WARNING", Severity.WARNING, positioningStrategy, psiType)
return DummyDelegate(KtDiagnosticFactoryForDeprecation2(featureForError, warningFactory, errorFactory))
}
}
class DeprecationDiagnosticFactory3DelegateProvider<A, B, C>(
private val featureForError: LanguageFeature,
private val positioningStrategy: AbstractSourceElementPositioningStrategy,
private val psiType: KClass<*>
) {
operator fun provideDelegate(thisRef: Any?, prop: KProperty<*>): ReadOnlyProperty<Any?, KtDiagnosticFactoryForDeprecation3<A, B, C>> {
val errorFactory = KtDiagnosticFactory3<A, B, C>("${prop.name}$ERROR", Severity.ERROR, positioningStrategy, psiType)
val warningFactory = KtDiagnosticFactory3<A, B, C>("${prop.name}$WARNING", Severity.WARNING, positioningStrategy, psiType)
return DummyDelegate(KtDiagnosticFactoryForDeprecation3(featureForError, warningFactory, errorFactory))
}
}
class DeprecationDiagnosticFactory4DelegateProvider<A, B, C, D>(
private val featureForError: LanguageFeature,
private val positioningStrategy: AbstractSourceElementPositioningStrategy,
private val psiType: KClass<*>
) {
operator fun provideDelegate(thisRef: Any?, prop: KProperty<*>): ReadOnlyProperty<Any?, KtDiagnosticFactoryForDeprecation4<A, B, C, D>> {
val errorFactory = KtDiagnosticFactory4<A, B, C, D>("${prop.name}$ERROR", Severity.ERROR, positioningStrategy, psiType)
val warningFactory = KtDiagnosticFactory4<A, B, C, D>("${prop.name}$WARNING", Severity.WARNING, positioningStrategy, psiType)
return DummyDelegate(KtDiagnosticFactoryForDeprecation4(featureForError, warningFactory, errorFactory))
}
}
private class DummyDelegate<T>(val value: T) : ReadOnlyProperty<Any?, T> {
override fun getValue(thisRef: Any?, property: KProperty<*>): T {
return value
}
}
@@ -0,0 +1,121 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.diagnostics
import org.jetbrains.kotlin.diagnostics.rendering.DiagnosticParameterRenderer
class KtDiagnosticFactoryToRendererMap(val name: String) {
private val renderersMap: MutableMap<AbstractKtDiagnosticFactory, KtDiagnosticRenderer> = mutableMapOf()
operator fun get(factory: AbstractKtDiagnosticFactory): KtDiagnosticRenderer? = renderersMap[factory]
fun put(factory: KtDiagnosticFactory0, message: String) {
put(factory, SimpleKtDiagnosticRenderer(message))
}
fun <A> put(
factory: KtDiagnosticFactory1<A>,
message: String,
rendererA: DiagnosticParameterRenderer<A>?
) {
put(factory, KtDiagnosticWithParameters1Renderer(message, rendererA))
}
fun <A, B> put(
factory: KtDiagnosticFactory2<A, B>,
message: String,
rendererA: DiagnosticParameterRenderer<A>?,
rendererB: DiagnosticParameterRenderer<B>?
) {
put(factory, KtDiagnosticWithParameters2Renderer(message, rendererA, rendererB))
}
fun <A, B, C> put(
factory: KtDiagnosticFactory3<A, B, C>,
message: String,
rendererA: DiagnosticParameterRenderer<A>?,
rendererB: DiagnosticParameterRenderer<B>?,
rendererC: DiagnosticParameterRenderer<C>?
) {
put(factory, KtDiagnosticWithParameters3Renderer(message, rendererA, rendererB, rendererC))
}
fun <A, B, C, D> put(
factory: KtDiagnosticFactory4<A, B, C, D>,
message: String,
rendererA: DiagnosticParameterRenderer<A>?,
rendererB: DiagnosticParameterRenderer<B>?,
rendererC: DiagnosticParameterRenderer<C>?,
rendererD: DiagnosticParameterRenderer<D>?
) {
put(factory, KtDiagnosticWithParameters4Renderer(message, rendererA, rendererB, rendererC, rendererD))
}
fun put(factory: KtDiagnosticFactoryForDeprecation0, message: String) {
put(factory.errorFactory, SimpleKtDiagnosticRenderer(message))
put(factory.warningFactory, SimpleKtDiagnosticRenderer(factory.warningMessage(message)))
}
fun <A> put(
factory: KtDiagnosticFactoryForDeprecation1<A>,
message: String,
rendererA: DiagnosticParameterRenderer<A>?
) {
put(factory.errorFactory, KtDiagnosticWithParameters1Renderer(message, rendererA))
put(factory.warningFactory, KtDiagnosticWithParameters1Renderer(factory.warningMessage(message), rendererA))
}
fun <A, B> put(
factory: KtDiagnosticFactoryForDeprecation2<A, B>,
message: String,
rendererA: DiagnosticParameterRenderer<A>?,
rendererB: DiagnosticParameterRenderer<B>?
) {
put(factory.errorFactory, KtDiagnosticWithParameters2Renderer(message, rendererA, rendererB))
put(factory.warningFactory, KtDiagnosticWithParameters2Renderer(factory.warningMessage(message), rendererA, rendererB))
}
fun <A, B, C> put(
factory: KtDiagnosticFactoryForDeprecation3<A, B, C>,
message: String,
rendererA: DiagnosticParameterRenderer<A>?,
rendererB: DiagnosticParameterRenderer<B>?,
rendererC: DiagnosticParameterRenderer<C>?
) {
put(factory.errorFactory, KtDiagnosticWithParameters3Renderer(message, rendererA, rendererB, rendererC))
put(factory.warningFactory, KtDiagnosticWithParameters3Renderer(factory.warningMessage(message), rendererA, rendererB, rendererC))
}
fun <A, B, C, D> put(
factory: KtDiagnosticFactoryForDeprecation4<A, B, C, D>,
message: String,
rendererA: DiagnosticParameterRenderer<A>?,
rendererB: DiagnosticParameterRenderer<B>?,
rendererC: DiagnosticParameterRenderer<C>?,
rendererD: DiagnosticParameterRenderer<D>?
) {
put(factory.errorFactory, KtDiagnosticWithParameters4Renderer(message, rendererA, rendererB, rendererC, rendererD))
put(factory.warningFactory, KtDiagnosticWithParameters4Renderer(factory.warningMessage(message), rendererA, rendererB, rendererC, rendererD))
}
private fun put(factory: AbstractKtDiagnosticFactory, renderer: KtDiagnosticRenderer) {
renderersMap[factory] = renderer
}
private fun KtDiagnosticFactoryForDeprecation<*>.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")
}
}
}
}
@@ -0,0 +1,104 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.diagnostics
import org.jetbrains.kotlin.diagnostics.rendering.DiagnosticParameterRenderer
import org.jetbrains.kotlin.diagnostics.rendering.RenderingContext
import org.jetbrains.kotlin.diagnostics.rendering.renderParameter
import java.text.MessageFormat
sealed interface KtDiagnosticRenderer {
fun render(diagnostic: KtDiagnostic): String
fun renderParameters(diagnostic: KtDiagnostic): Array<out Any?>
}
class SimpleKtDiagnosticRenderer(private val message: String) : KtDiagnosticRenderer {
override fun render(diagnostic: KtDiagnostic): String {
require(diagnostic is KtSimpleDiagnostic)
return message
}
override fun renderParameters(diagnostic: KtDiagnostic): Array<out Any?> {
require(diagnostic is KtSimpleDiagnostic)
return emptyArray()
}
}
sealed class AbstractKtDiagnosticWithParametersRenderer(
protected val message: String
) : KtDiagnosticRenderer {
private val messageFormat = MessageFormat(message)
final override fun render(diagnostic: KtDiagnostic): String {
return messageFormat.format(renderParameters(diagnostic))
}
}
class KtDiagnosticWithParameters1Renderer<A>(
message: String,
private val rendererForA: DiagnosticParameterRenderer<A>?,
) : AbstractKtDiagnosticWithParametersRenderer(message) {
override fun renderParameters(diagnostic: KtDiagnostic): Array<out Any?> {
require(diagnostic is KtDiagnosticWithParameters1<*>)
val context = RenderingContext.of(diagnostic.a)
@Suppress("UNCHECKED_CAST")
return arrayOf(renderParameter(diagnostic.a as A, rendererForA, context))
}
}
class KtDiagnosticWithParameters2Renderer<A, B>(
message: String,
private val rendererForA: DiagnosticParameterRenderer<A>?,
private val rendererForB: DiagnosticParameterRenderer<B>?,
) : AbstractKtDiagnosticWithParametersRenderer(message) {
override fun renderParameters(diagnostic: KtDiagnostic): Array<out Any?> {
require(diagnostic is KtDiagnosticWithParameters2<*, *>)
val context = RenderingContext.of(diagnostic.a, diagnostic.b)
@Suppress("UNCHECKED_CAST")
return arrayOf(
renderParameter(diagnostic.a as A, rendererForA, context),
renderParameter(diagnostic.b as B, rendererForB, context),
)
}
}
class KtDiagnosticWithParameters3Renderer<A, B, C>(
message: String,
private val rendererForA: DiagnosticParameterRenderer<A>?,
private val rendererForB: DiagnosticParameterRenderer<B>?,
private val rendererForC: DiagnosticParameterRenderer<C>?,
) : AbstractKtDiagnosticWithParametersRenderer(message) {
override fun renderParameters(diagnostic: KtDiagnostic): Array<out Any?> {
require(diagnostic is KtDiagnosticWithParameters3<*, *, *>)
val context = RenderingContext.of(diagnostic.a, diagnostic.b, diagnostic.c)
@Suppress("UNCHECKED_CAST")
return arrayOf(
renderParameter(diagnostic.a as A, rendererForA, context),
renderParameter(diagnostic.b as B, rendererForB, context),
renderParameter(diagnostic.c as C, rendererForC, context),
)
}
}
class KtDiagnosticWithParameters4Renderer<A, B, C, D>(
message: String,
private val rendererForA: DiagnosticParameterRenderer<A>?,
private val rendererForB: DiagnosticParameterRenderer<B>?,
private val rendererForC: DiagnosticParameterRenderer<C>?,
private val rendererForD: DiagnosticParameterRenderer<D>?,
) : AbstractKtDiagnosticWithParametersRenderer(message) {
override fun renderParameters(diagnostic: KtDiagnostic): Array<out Any?> {
require(diagnostic is KtDiagnosticWithParameters4<*, *, *, *>)
val context = RenderingContext.of(diagnostic.a, diagnostic.b, diagnostic.c, diagnostic.d)
@Suppress("UNCHECKED_CAST")
return arrayOf(
renderParameter(diagnostic.a as A, rendererForA, context),
renderParameter(diagnostic.b as B, rendererForB, context),
renderParameter(diagnostic.c as C, rendererForC, context),
renderParameter(diagnostic.d as D, rendererForD, context),
)
}
}
@@ -0,0 +1,39 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.diagnostics
import org.jetbrains.kotlin.descriptors.Visibility
import org.jetbrains.kotlin.diagnostics.rendering.ContextIndependentParameterRenderer
import org.jetbrains.kotlin.diagnostics.rendering.Renderer
object KtDiagnosticRenderers {
val NULLABLE_STRING = Renderer<String?> { it ?: "null" }
val TO_STRING = Renderer { element: Any? ->
element.toString()
}
val EMPTY = Renderer { _: Any? -> "" }
val VISIBILITY = Renderer { visibility: Visibility ->
visibility.externalDisplayName
}
val NOT_RENDERED = Renderer<Any?> {
""
}
val FUNCTION_PARAMETERS = Renderer { hasValueParameters: Boolean -> if (hasValueParameters) "..." else "" }
@Suppress("FunctionName")
fun <T> COLLECTION(renderer: ContextIndependentParameterRenderer<T>): ContextIndependentParameterRenderer<Collection<T>> {
return Renderer { list ->
list.joinToString(prefix = "[", postfix = "]", separator = ", ", limit = 3, truncated = "...") {
renderer.render(it)
}
}
}
}
@@ -0,0 +1,13 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.diagnostics.impl
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.diagnostics.KtDiagnostic
abstract class BaseDiagnosticReporter : DiagnosticReporter() {
abstract val diagnostics: List<KtDiagnostic>
}
@@ -0,0 +1,25 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.diagnostics.impl
import org.jetbrains.kotlin.KtSourceElement
import org.jetbrains.kotlin.diagnostics.AbstractKtDiagnosticFactory
import org.jetbrains.kotlin.diagnostics.DiagnosticContext
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.diagnostics.KtDiagnostic
class DeduplicatingDiagnosticReporter(private val inner: DiagnosticReporter) : DiagnosticReporter() {
private val reported = mutableSetOf<Pair<KtSourceElement, AbstractKtDiagnosticFactory>>()
override fun report(diagnostic: KtDiagnostic?, context: DiagnosticContext) {
if (diagnostic != null && reported.add(Pair(diagnostic.element, diagnostic.factory))) {
inner.report(diagnostic, context)
}
}
}
fun DiagnosticReporter.deduplicating(): DeduplicatingDiagnosticReporter = DeduplicatingDiagnosticReporter(this)
@@ -0,0 +1,22 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.diagnostics.impl
import org.jetbrains.kotlin.diagnostics.DiagnosticContext
import org.jetbrains.kotlin.diagnostics.KtDiagnostic
class DiagnosticReporterWithSuppress : BaseDiagnosticReporter() {
private val _diagnostics: MutableList<KtDiagnostic> = mutableListOf()
override val diagnostics: List<KtDiagnostic>
get() = _diagnostics
override fun report(diagnostic: KtDiagnostic?, context: DiagnosticContext) {
if (diagnostic == null) return
if (!context.isDiagnosticSuppressed(diagnostic)) {
_diagnostics += diagnostic
}
}
}
@@ -0,0 +1,20 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.diagnostics.impl
import org.jetbrains.kotlin.diagnostics.DiagnosticContext
import org.jetbrains.kotlin.diagnostics.KtDiagnostic
class SimpleDiagnosticReporter : BaseDiagnosticReporter() {
private val _diagnostics: MutableList<KtDiagnostic> = mutableListOf()
override val diagnostics: List<KtDiagnostic>
get() = _diagnostics
override fun report(diagnostic: KtDiagnostic?, context: DiagnosticContext) {
if (diagnostic == null) return
_diagnostics += diagnostic
}
}