[FIR] Use diagnostic markers in FIR diagnostics

This commit is contained in:
Dmitriy Novozhilov
2021-09-08 18:13:28 +03:00
committed by TeamCityServer
parent 850ca1916f
commit 00069b1d2f
2 changed files with 34 additions and 37 deletions
@@ -8,14 +8,14 @@ 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 com.intellij.psi.PsiFile import com.intellij.psi.PsiFile
import org.jetbrains.kotlin.diagnostics.Severity import org.jetbrains.kotlin.diagnostics.*
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
// ------------------------------ diagnostics ------------------------------ // ------------------------------ diagnostics ------------------------------
sealed class FirDiagnostic { sealed class FirDiagnostic : DiagnosticMarker {
abstract val element: FirSourceElement abstract val element: FirSourceElement
abstract val severity: Severity abstract val severity: Severity
abstract val factory: AbstractFirDiagnosticFactory abstract val factory: AbstractFirDiagnosticFactory
@@ -26,47 +26,50 @@ sealed class FirDiagnostic {
val isValid: Boolean val isValid: Boolean
get() = positioningStrategy.isValid(element) get() = positioningStrategy.isValid(element)
override val factoryName: String
get() = factory.name
} }
sealed class FirSimpleDiagnostic : FirDiagnostic() { sealed class FirSimpleDiagnostic : FirDiagnostic() {
abstract override val factory: FirDiagnosticFactory0 abstract override val factory: FirDiagnosticFactory0
} }
sealed class FirDiagnosticWithParameters1<A> : FirDiagnostic() { sealed class FirDiagnosticWithParameters1<A> : FirDiagnostic(), DiagnosticWithParameters1Marker<A> {
abstract val a: A abstract override val a: A
abstract override val factory: FirDiagnosticFactory1<A> abstract override val factory: FirDiagnosticFactory1<A>
} }
sealed class FirDiagnosticWithParameters2<A, B> : FirDiagnostic() { sealed class FirDiagnosticWithParameters2<A, B> : FirDiagnostic(), DiagnosticWithParameters2Marker<A, B> {
abstract val a: A abstract override val a: A
abstract val b: B abstract override val b: B
abstract override val factory: FirDiagnosticFactory2<A, B> abstract override val factory: FirDiagnosticFactory2<A, B>
} }
sealed class FirDiagnosticWithParameters3<A, B, C> : FirDiagnostic() { sealed class FirDiagnosticWithParameters3<A, B, C> : FirDiagnostic(), DiagnosticWithParameters3Marker<A, B, C> {
abstract val a: A abstract override val a: A
abstract val b: B abstract override val b: B
abstract val c: C abstract override val c: C
abstract override val factory: FirDiagnosticFactory3<A, B, C> abstract override val factory: FirDiagnosticFactory3<A, B, C>
} }
sealed class FirDiagnosticWithParameters4<A, B, C, D> : FirDiagnostic() { sealed class FirDiagnosticWithParameters4<A, B, C, D> : FirDiagnostic(), DiagnosticWithParameters4Marker<A, B, C, D> {
abstract val a: A abstract override val a: A
abstract val b: B abstract override val b: B
abstract val c: C abstract override val c: C
abstract val d: D abstract override val d: D
abstract override val factory: FirDiagnosticFactory4<A, B, C, D> abstract override val factory: FirDiagnosticFactory4<A, B, C, D>
} }
// ------------------------------ psi diagnostics ------------------------------ // ------------------------------ psi diagnostics ------------------------------
interface FirPsiDiagnostic { interface FirPsiDiagnostic : DiagnosticMarker {
val factory: AbstractFirDiagnosticFactory val factory: AbstractFirDiagnosticFactory
val element: FirPsiSourceElement val element: FirPsiSourceElement
val textRanges: List<TextRange> val textRanges: List<TextRange>
val severity: Severity val severity: Severity
val psiElement: PsiElement override val psiElement: PsiElement
get() = element.psi get() = element.psi
val psiFile: PsiFile val psiFile: PsiFile
@@ -151,8 +154,12 @@ data class FirPsiDiagnosticWithParameters4<A, B, C, D>(
// ------------------------------ light tree diagnostics ------------------------------ // ------------------------------ light tree diagnostics ------------------------------
interface FirLightDiagnostic { interface FirLightDiagnostic : DiagnosticMarker {
val element: FirLightSourceElement val element: FirLightSourceElement
@Deprecated("Should not be called", level = DeprecationLevel.HIDDEN)
override val psiElement: PsiElement
get() = error("psiElement should not be called on FirLightDiagnostic")
} }
data class FirLightSimpleDiagnostic( data class FirLightSimpleDiagnostic(
@@ -8,37 +8,27 @@ 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.PositioningStrategy import org.jetbrains.kotlin.diagnostics.PositioningStrategy
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
import org.jetbrains.kotlin.fir.psi
class SourceElementPositioningStrategy( class SourceElementPositioningStrategy(
private val lightTreeStrategy: LightTreePositioningStrategy, private val lightTreeStrategy: LightTreePositioningStrategy,
private val psiStrategy: PositioningStrategy<*> private val psiStrategy: PositioningStrategy<*>
) { ) {
fun markDiagnostic(diagnostic: FirDiagnostic): List<TextRange> { fun markDiagnostic(diagnostic: FirDiagnostic): List<TextRange> {
val element = diagnostic.element return when (val element = diagnostic.element) {
if (element is FirPsiSourceElement) { is FirPsiSourceElement -> psiStrategy.markDiagnostic(diagnostic)
return if (psiStrategy is FirPsiPositioningStrategy<*>) { is FirLightSourceElement -> lightTreeStrategy.markFirDiagnostic(element, diagnostic)
psiStrategy.markFirDiagnostic(element, diagnostic)
} else {
@Suppress("UNCHECKED_CAST")
psiStrategy.hackyMark(element.psi)
}
} }
return lightTreeStrategy.markFirDiagnostic(element, diagnostic)
} }
fun isValid(element: FirSourceElement): Boolean { fun isValid(element: FirSourceElement): Boolean {
if (element is FirPsiSourceElement) { return when (element) {
@Suppress("UNCHECKED_CAST") is FirPsiSourceElement -> psiStrategy.hackyIsValid(element.psi)
return psiStrategy.hackyIsValid(element.psi) is FirLightSourceElement -> lightTreeStrategy.isValid(element.lighterASTNode, element.treeStructure)
} }
return lightTreeStrategy.isValid(element.lighterASTNode, element.treeStructure)
}
private fun PositioningStrategy<*>.hackyMark(psi: PsiElement): List<TextRange> {
@Suppress("UNCHECKED_CAST")
return (this as PositioningStrategy<PsiElement>).mark(psi)
} }
private fun PositioningStrategy<*>.hackyIsValid(psi: PsiElement): Boolean { private fun PositioningStrategy<*>.hackyIsValid(psi: PsiElement): Boolean {