Rearrange fir diagnostic for further reuse

This commit is contained in:
Ilya Chernikov
2021-09-17 22:13:23 +02:00
parent a5bf8f5f91
commit 31c58767cf
61 changed files with 1972 additions and 1944 deletions
@@ -16,8 +16,8 @@ import org.jetbrains.kotlin.analysis.api.fir.types.KtFirType
import org.jetbrains.kotlin.analysis.api.types.KtSubstitutor
import org.jetbrains.kotlin.analysis.api.types.KtType
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnostic
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirPsiDiagnostic
import org.jetbrains.kotlin.fir.analysis.diagnostics.KtDiagnostic
import org.jetbrains.kotlin.fir.analysis.diagnostics.KtPsiDiagnostic
import org.jetbrains.kotlin.fir.analysis.diagnostics.toFirDiagnostics
import org.jetbrains.kotlin.fir.diagnostics.ConeDiagnostic
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
@@ -41,17 +41,17 @@ internal interface KtFirAnalysisSessionComponent {
fun ConeKotlinType.asKtType() = analysisSession.firSymbolBuilder.typeBuilder.buildKtType(this)
fun FirPsiDiagnostic.asKtDiagnostic(): KtDiagnosticWithPsi<*> =
KT_DIAGNOSTIC_CONVERTER.convert(analysisSession, this as FirDiagnostic)
fun KtPsiDiagnostic.asKtDiagnostic(): KtDiagnosticWithPsi<*> =
KT_DIAGNOSTIC_CONVERTER.convert(analysisSession, this as KtDiagnostic)
fun ConeDiagnostic.asKtDiagnostic(
source: KtSourceElement,
qualifiedAccessSource: KtSourceElement?,
diagnosticCache: MutableList<FirDiagnostic>
diagnosticCache: MutableList<KtDiagnostic>
): KtDiagnosticWithPsi<*>? {
val firDiagnostic = toFirDiagnostics(analysisSession.rootModuleSession, source, qualifiedAccessSource).firstOrNull() ?: return null
diagnosticCache += firDiagnostic
check(firDiagnostic is FirPsiDiagnostic)
check(firDiagnostic is KtPsiDiagnostic)
return firDiagnostic.asKtDiagnostic()
}
@@ -24,7 +24,7 @@ import org.jetbrains.kotlin.analysis.api.tokens.ValidityToken
import org.jetbrains.kotlin.analysis.api.types.KtSubstitutor
import org.jetbrains.kotlin.analysis.api.withValidityAssertion
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.getOrBuildFir
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnostic
import org.jetbrains.kotlin.fir.analysis.diagnostics.KtDiagnostic
import org.jetbrains.kotlin.fir.declarations.FirConstructor
import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.realPsi
@@ -49,7 +49,7 @@ internal class KtFirCallResolver(
override val analysisSession: KtFirAnalysisSession,
override val token: ValidityToken,
) : AbstractKtCallResolver(), KtFirAnalysisSessionComponent {
private val diagnosticCache = mutableListOf<FirDiagnostic>()
private val diagnosticCache = mutableListOf<KtDiagnostic>()
private val cache: ConcurrentHashMap<KtElement, KtCall?> = ConcurrentHashMap()
override fun resolveAccessorCall(call: KtSimpleNameExpression): KtCall? = withValidityAssertion {
@@ -5,16 +5,15 @@
package org.jetbrains.kotlin.analysis.api.fir.components
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnostic
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.DiagnosticCheckerFilter
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.collectDiagnosticsForFile
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.getDiagnostics
import org.jetbrains.kotlin.analysis.api.tokens.ValidityToken
import org.jetbrains.kotlin.analysis.api.components.KtDiagnosticCheckerFilter
import org.jetbrains.kotlin.analysis.api.components.KtDiagnosticProvider
import org.jetbrains.kotlin.analysis.api.diagnostics.KtDiagnosticWithPsi
import org.jetbrains.kotlin.analysis.api.fir.KtFirAnalysisSession
import org.jetbrains.kotlin.analysis.api.tokens.ValidityToken
import org.jetbrains.kotlin.analysis.api.withValidityAssertion
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.DiagnosticCheckerFilter
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.collectDiagnosticsForFile
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.getDiagnostics
import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.psi.KtFile
@@ -8,22 +8,22 @@ package org.jetbrains.kotlin.analysis.api.fir.diagnostics
import com.intellij.openapi.util.TextRange
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.analysis.api.ValidityTokenOwner
import org.jetbrains.kotlin.diagnostics.Severity
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDefaultErrorMessages
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnostic
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirPsiDiagnostic
import org.jetbrains.kotlin.analysis.api.diagnostics.KtDiagnosticWithPsi
import org.jetbrains.kotlin.analysis.api.withValidityAssertion
import org.jetbrains.kotlin.diagnostics.Severity
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDefaultErrorMessages
import org.jetbrains.kotlin.fir.analysis.diagnostics.KtDiagnostic
import org.jetbrains.kotlin.fir.analysis.diagnostics.KtPsiDiagnostic
internal interface KtAbstractFirDiagnostic<PSI : PsiElement> : KtDiagnosticWithPsi<PSI>, ValidityTokenOwner {
val firDiagnostic: FirPsiDiagnostic
val firDiagnostic: KtPsiDiagnostic
override val factoryName: String
get() = withValidityAssertion { firDiagnostic.factory.name }
override val defaultMessage: String
get() = withValidityAssertion {
val diagnostic = firDiagnostic as FirDiagnostic
val diagnostic = firDiagnostic as KtDiagnostic
val firDiagnosticRenderer = FirDefaultErrorMessages.getRendererForDiagnostic(diagnostic)
return firDiagnosticRenderer.render(diagnostic)
@@ -5,33 +5,33 @@
package org.jetbrains.kotlin.analysis.api.fir.diagnostics
import org.jetbrains.kotlin.fir.analysis.diagnostics.*
import org.jetbrains.kotlin.analysis.api.fir.KtFirAnalysisSession
import org.jetbrains.kotlin.fir.analysis.diagnostics.*
internal interface KtFirDiagnosticCreator
internal fun interface KtFirDiagnostic0Creator : KtFirDiagnosticCreator {
fun KtFirAnalysisSession.create(diagnostic: FirSimpleDiagnostic): KtFirDiagnostic<*>
fun KtFirAnalysisSession.create(diagnostic: KtSimpleDiagnostic): KtFirDiagnostic<*>
}
internal fun interface KtFirDiagnostic1Creator<A> : KtFirDiagnosticCreator {
fun KtFirAnalysisSession.create(diagnostic: FirDiagnosticWithParameters1<A>): KtFirDiagnostic<*>
fun KtFirAnalysisSession.create(diagnostic: KtDiagnosticWithParameters1<A>): KtFirDiagnostic<*>
}
internal fun interface KtFirDiagnostic2Creator<A, B> : KtFirDiagnosticCreator {
fun KtFirAnalysisSession.create(diagnostic: FirDiagnosticWithParameters2<A, B>): KtFirDiagnostic<*>
fun KtFirAnalysisSession.create(diagnostic: KtDiagnosticWithParameters2<A, B>): KtFirDiagnostic<*>
}
internal fun interface KtFirDiagnostic3Creator<A, B, C> : KtFirDiagnosticCreator {
fun KtFirAnalysisSession.create(diagnostic: FirDiagnosticWithParameters3<A, B, C>): KtFirDiagnostic<*>
fun KtFirAnalysisSession.create(diagnostic: KtDiagnosticWithParameters3<A, B, C>): KtFirDiagnostic<*>
}
internal fun interface KtFirDiagnostic4Creator<A, B, C, D> : KtFirDiagnosticCreator {
fun KtFirAnalysisSession.create(diagnostic: FirDiagnosticWithParameters4<A, B, C, D>): KtFirDiagnostic<*>
fun KtFirAnalysisSession.create(diagnostic: KtDiagnosticWithParameters4<A, B, C, D>): KtFirDiagnostic<*>
}
internal class KtDiagnosticConverter(private val conversions: Map<AbstractFirDiagnosticFactory, KtFirDiagnosticCreator>) {
fun convert(analysisSession: KtFirAnalysisSession, diagnostic: FirDiagnostic): KtFirDiagnostic<*> {
internal class KtDiagnosticConverter(private val conversions: Map<AbstractKtDiagnosticFactory, KtFirDiagnosticCreator>) {
fun convert(analysisSession: KtFirAnalysisSession, diagnostic: KtDiagnostic): KtFirDiagnostic<*> {
val creator = conversions[diagnostic.factory]
?: error("No conversion was found for ${diagnostic.factory}")
@@ -39,19 +39,19 @@ internal class KtDiagnosticConverter(private val conversions: Map<AbstractFirDia
return with(analysisSession) {
when (creator) {
is KtFirDiagnostic0Creator -> with(creator) {
create(diagnostic as FirSimpleDiagnostic)
create(diagnostic as KtSimpleDiagnostic)
}
is KtFirDiagnostic1Creator<*> -> with(creator as KtFirDiagnostic1Creator<Any?>) {
create(diagnostic as FirDiagnosticWithParameters1<Any?>)
create(diagnostic as KtDiagnosticWithParameters1<Any?>)
}
is KtFirDiagnostic2Creator<*, *> -> with(creator as KtFirDiagnostic2Creator<Any?, Any?>) {
create(diagnostic as FirDiagnosticWithParameters2<Any?, Any?>)
create(diagnostic as KtDiagnosticWithParameters2<Any?, Any?>)
}
is KtFirDiagnostic3Creator<*, *, *> -> with(creator as KtFirDiagnostic3Creator<Any?, Any?, Any?>) {
create(diagnostic as FirDiagnosticWithParameters3<Any?, Any?, Any?>)
create(diagnostic as KtDiagnosticWithParameters3<Any?, Any?, Any?>)
}
is KtFirDiagnostic4Creator<*, *, *, *> -> with(creator as KtFirDiagnostic4Creator<Any?, Any?, Any?, Any?>) {
create(diagnostic as FirDiagnosticWithParameters4<Any?, Any?, Any?, Any?>)
create(diagnostic as KtDiagnosticWithParameters4<Any?, Any?, Any?, Any?>)
}
else -> error("Invalid KtFirDiagnosticCreator ${creator::class.simpleName}")
}
@@ -60,25 +60,25 @@ internal class KtDiagnosticConverter(private val conversions: Map<AbstractFirDia
}
internal class KtDiagnosticConverterBuilder private constructor() {
private val conversions = mutableMapOf<AbstractFirDiagnosticFactory, KtFirDiagnosticCreator>()
private val conversions = mutableMapOf<AbstractKtDiagnosticFactory, KtFirDiagnosticCreator>()
fun add(diagnostic: FirDiagnosticFactory0, creator: KtFirDiagnostic0Creator) {
fun add(diagnostic: KtDiagnosticFactory0, creator: KtFirDiagnostic0Creator) {
conversions[diagnostic] = creator
}
fun <A> add(diagnostic: FirDiagnosticFactory1<A>, creator: KtFirDiagnostic1Creator<A>) {
fun <A> add(diagnostic: KtDiagnosticFactory1<A>, creator: KtFirDiagnostic1Creator<A>) {
conversions[diagnostic] = creator
}
fun <A, B> add(diagnostic: FirDiagnosticFactory2<A, B>, creator: KtFirDiagnostic2Creator<A, B>) {
fun <A, B> add(diagnostic: KtDiagnosticFactory2<A, B>, creator: KtFirDiagnostic2Creator<A, B>) {
conversions[diagnostic] = creator
}
fun <A, B, C> add(diagnostic: FirDiagnosticFactory3<A, B, C>, creator: KtFirDiagnostic3Creator<A, B, C>) {
fun <A, B, C> add(diagnostic: KtDiagnosticFactory3<A, B, C>, creator: KtFirDiagnostic3Creator<A, B, C>) {
conversions[diagnostic] = creator
}
fun <A, B, C, D> add(diagnostic: FirDiagnosticFactory4<A, B, C, D>, creator: KtFirDiagnostic4Creator<A, B, C, D>) {
fun <A, B, C, D> add(diagnostic: KtDiagnosticFactory4<A, B, C, D>, creator: KtFirDiagnostic4Creator<A, B, C, D>) {
conversions[diagnostic] = creator
}
@@ -18,6 +18,7 @@ dependencies {
api(project(":compiler:backend.common.jvm"))
api(project(":analysis:analysis-api-impl-barebone"))
testApi(project(":analysis:analysis-api-fir"))
implementation(project(":compiler:frontend.common"))
implementation(project(":compiler:ir.psi2ir"))
implementation(project(":compiler:fir:entrypoint"))
implementation(project(":analysis:analysis-api-providers"))
@@ -18,7 +18,7 @@ import org.jetbrains.kotlin.analysis.low.level.api.fir.util.originalKtFile
import org.jetbrains.kotlin.analysis.project.structure.KtModule
import org.jetbrains.kotlin.fir.FirElement
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirPsiDiagnostic
import org.jetbrains.kotlin.fir.analysis.diagnostics.KtPsiDiagnostic
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
import org.jetbrains.kotlin.fir.declarations.FirFile
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
@@ -75,10 +75,10 @@ internal class FirModuleResolveStateDepended(
return null
}
override fun getDiagnostics(element: KtElement, filter: DiagnosticCheckerFilter): List<FirPsiDiagnostic> =
override fun getDiagnostics(element: KtElement, filter: DiagnosticCheckerFilter): List<KtPsiDiagnostic> =
TODO("Diagnostics are not implemented for depended state")
override fun collectDiagnosticsForFile(ktFile: KtFile, filter: DiagnosticCheckerFilter): Collection<FirPsiDiagnostic> =
override fun collectDiagnosticsForFile(ktFile: KtFile, filter: DiagnosticCheckerFilter): Collection<KtPsiDiagnostic> =
TODO("Diagnostics are not implemented for depended state")
@OptIn(InternalForInline::class)
@@ -7,15 +7,6 @@ package org.jetbrains.kotlin.analysis.low.level.api.fir
import com.intellij.openapi.project.Project
import org.jetbrains.kotlin.analysis.api.impl.barebone.annotations.InternalForInline
import org.jetbrains.kotlin.fir.FirElement
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirPsiDiagnostic
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
import org.jetbrains.kotlin.fir.declarations.FirFile
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
import org.jetbrains.kotlin.fir.expressions.FirAnonymousFunctionExpression
import org.jetbrains.kotlin.fir.expressions.FirAnonymousObjectExpression
import org.jetbrains.kotlin.fir.resolve.ScopeSession
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.DiagnosticCheckerFilter
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.FirModuleResolveState
import org.jetbrains.kotlin.analysis.low.level.api.fir.diagnostics.DiagnosticsCollector
@@ -37,6 +28,15 @@ import org.jetbrains.kotlin.analysis.low.level.api.fir.util.originalDeclaration
import org.jetbrains.kotlin.analysis.project.structure.KtModule
import org.jetbrains.kotlin.analysis.project.structure.KtSourceModule
import org.jetbrains.kotlin.analysis.project.structure.getKtModule
import org.jetbrains.kotlin.fir.FirElement
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.analysis.diagnostics.KtPsiDiagnostic
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
import org.jetbrains.kotlin.fir.declarations.FirFile
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
import org.jetbrains.kotlin.fir.expressions.FirAnonymousFunctionExpression
import org.jetbrains.kotlin.fir.expressions.FirAnonymousObjectExpression
import org.jetbrains.kotlin.fir.resolve.ScopeSession
import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider
import org.jetbrains.kotlin.psi.*
@@ -78,10 +78,10 @@ internal class FirModuleResolveStateImpl(
override fun tryGetCachedFirFile(declaration: FirDeclaration, cache: ModuleFileCache): FirFile? =
cache.getContainerFirFile(declaration)
override fun getDiagnostics(element: KtElement, filter: DiagnosticCheckerFilter): List<FirPsiDiagnostic> =
override fun getDiagnostics(element: KtElement, filter: DiagnosticCheckerFilter): List<KtPsiDiagnostic> =
diagnosticsCollector.getDiagnosticsFor(element, filter)
override fun collectDiagnosticsForFile(ktFile: KtFile, filter: DiagnosticCheckerFilter): Collection<FirPsiDiagnostic> =
override fun collectDiagnosticsForFile(ktFile: KtFile, filter: DiagnosticCheckerFilter): Collection<KtPsiDiagnostic> =
diagnosticsCollector.collectDiagnosticsForFile(ktFile, filter)
@OptIn(InternalForInline::class)
@@ -13,6 +13,9 @@ import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.ModuleFileCache
import org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve.ResolveType
import org.jetbrains.kotlin.analysis.project.structure.KtModule
import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.fir.analysis.diagnostics.KtPsiDiagnostic
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.psi.KtFile
@@ -44,9 +47,9 @@ abstract class FirModuleResolveState {
*/
internal abstract fun tryGetCachedFirFile(declaration: FirDeclaration, cache: ModuleFileCache): FirFile?
internal abstract fun getDiagnostics(element: KtElement, filter: DiagnosticCheckerFilter): List<FirPsiDiagnostic>
internal abstract fun getDiagnostics(element: KtElement, filter: DiagnosticCheckerFilter): List<KtPsiDiagnostic>
internal abstract fun collectDiagnosticsForFile(ktFile: KtFile, filter: DiagnosticCheckerFilter): Collection<FirPsiDiagnostic>
internal abstract fun collectDiagnosticsForFile(ktFile: KtFile, filter: DiagnosticCheckerFilter): Collection<KtPsiDiagnostic>
@InternalForInline
abstract fun findSourceFirDeclaration(
@@ -13,7 +13,7 @@ import org.jetbrains.kotlin.analysis.project.structure.KtModule
import org.jetbrains.kotlin.analysis.project.structure.KtSourceModule
import org.jetbrains.kotlin.analysis.project.structure.getKtModule
import org.jetbrains.kotlin.fir.FirElement
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirPsiDiagnostic
import org.jetbrains.kotlin.fir.analysis.diagnostics.KtPsiDiagnostic
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.psi.KtElement
@@ -148,7 +148,7 @@ fun <D : FirDeclaration, R> D.withFirDeclaration(
* Returns a list of Diagnostics compiler finds for given [KtElement]
* This operation could be performance affective because it create FIleStructureElement and resolve non-local declaration into BODY phase
*/
fun KtElement.getDiagnostics(resolveState: FirModuleResolveState, filter: DiagnosticCheckerFilter): Collection<FirPsiDiagnostic> =
fun KtElement.getDiagnostics(resolveState: FirModuleResolveState, filter: DiagnosticCheckerFilter): Collection<KtPsiDiagnostic> =
resolveState.getDiagnostics(this, filter)
/**
@@ -158,7 +158,7 @@ fun KtElement.getDiagnostics(resolveState: FirModuleResolveState, filter: Diagno
fun KtFile.collectDiagnosticsForFile(
resolveState: FirModuleResolveState,
filter: DiagnosticCheckerFilter
): Collection<FirPsiDiagnostic> =
): Collection<KtPsiDiagnostic> =
resolveState.collectDiagnosticsForFile(this, filter)
/**
@@ -5,10 +5,10 @@
package org.jetbrains.kotlin.analysis.low.level.api.fir.diagnostics
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirPsiDiagnostic
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.DiagnosticCheckerFilter
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.ModuleFileCache
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.structure.FileStructureCache
import org.jetbrains.kotlin.fir.analysis.diagnostics.KtPsiDiagnostic
import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.psi.KtFile
@@ -16,14 +16,14 @@ internal class DiagnosticsCollector(
private val fileStructureCache: FileStructureCache,
private val cache: ModuleFileCache,
) {
fun getDiagnosticsFor(element: KtElement, filter: DiagnosticCheckerFilter): List<FirPsiDiagnostic> {
fun getDiagnosticsFor(element: KtElement, filter: DiagnosticCheckerFilter): List<KtPsiDiagnostic> {
val fileStructure = fileStructureCache.getFileStructure(element.containingKtFile, cache)
val structureElement = fileStructure.getStructureElementFor(element)
val diagnostics = structureElement.diagnostics
return diagnostics.diagnosticsFor(filter, element)
}
fun collectDiagnosticsForFile(ktFile: KtFile, filter: DiagnosticCheckerFilter): Collection<FirPsiDiagnostic> {
fun collectDiagnosticsForFile(ktFile: KtFile, filter: DiagnosticCheckerFilter): Collection<KtPsiDiagnostic> {
val fileStructure = fileStructureCache.getFileStructure(ktFile, cache)
return fileStructure.getAllDiagnosticsForFile(filter)
}
@@ -6,12 +6,12 @@
package org.jetbrains.kotlin.analysis.low.level.api.fir.diagnostics
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirPsiDiagnostic
import org.jetbrains.kotlin.fir.analysis.diagnostics.KtPsiDiagnostic
internal class FileStructureElementDiagnosticList(
private val map: Map<PsiElement, List<FirPsiDiagnostic>>
private val map: Map<PsiElement, List<KtPsiDiagnostic>>
) {
fun diagnosticsFor(element: PsiElement): List<FirPsiDiagnostic> = map[element] ?: emptyList()
fun diagnosticsFor(element: PsiElement): List<KtPsiDiagnostic> = map[element] ?: emptyList()
inline fun forEach(action: (List<FirPsiDiagnostic>) -> Unit) = map.values.forEach(action)
inline fun forEach(action: (List<KtPsiDiagnostic>) -> Unit) = map.values.forEach(action)
}
@@ -7,10 +7,10 @@ package org.jetbrains.kotlin.analysis.low.level.api.fir.diagnostics
import com.intellij.psi.PsiElement
import com.intellij.util.SmartList
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirPsiDiagnostic
import org.jetbrains.kotlin.fir.declarations.FirFile
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.DiagnosticCheckerFilter
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.LockProvider
import org.jetbrains.kotlin.fir.analysis.diagnostics.KtPsiDiagnostic
import org.jetbrains.kotlin.fir.declarations.FirFile
internal class FileStructureElementDiagnostics(
private val firFile: FirFile,
@@ -25,8 +25,8 @@ internal class FileStructureElementDiagnostics(
retriever.retrieve(firFile, FileStructureElementDiagnosticsCollector.EXTENDED_COLLECTOR, lockProvider)
}
fun diagnosticsFor(filter: DiagnosticCheckerFilter, element: PsiElement): List<FirPsiDiagnostic> =
SmartList<FirPsiDiagnostic>().apply {
fun diagnosticsFor(filter: DiagnosticCheckerFilter, element: PsiElement): List<KtPsiDiagnostic> =
SmartList<KtPsiDiagnostic>().apply {
if (filter.runCommonCheckers) {
addAll(diagnosticByCommonCheckers.diagnosticsFor(element))
}
@@ -36,7 +36,7 @@ internal class FileStructureElementDiagnostics(
}
inline fun forEach(filter: DiagnosticCheckerFilter, action: (List<FirPsiDiagnostic>) -> Unit) {
inline fun forEach(filter: DiagnosticCheckerFilter, action: (List<KtPsiDiagnostic>) -> Unit) {
if (filter.runCommonCheckers) {
diagnosticByCommonCheckers.forEach(action)
}
@@ -6,67 +6,66 @@
package org.jetbrains.kotlin.analysis.low.level.api.fir.diagnostics
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.diagnostics.*
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.addValueFor
import org.jetbrains.kotlin.fir.analysis.diagnostics.*
internal class FirIdeDiagnosticReporter : DiagnosticReporter() {
val diagnostics = mutableMapOf<PsiElement, MutableList<FirPsiDiagnostic>>()
val diagnostics = mutableMapOf<PsiElement, MutableList<KtPsiDiagnostic>>()
override fun report(diagnostic: FirDiagnostic?, context: CheckerContext) {
override fun report(diagnostic: KtDiagnostic?, context: DiagnosticContext) {
if (diagnostic == null) return
if (context.isDiagnosticSuppressed(diagnostic)) return
val psiDiagnostic = when (diagnostic) {
is FirPsiDiagnostic -> diagnostic
is FirLightDiagnostic -> diagnostic.toPsiDiagnostic()
is KtPsiDiagnostic -> diagnostic
is KtLightDiagnostic -> diagnostic.toPsiDiagnostic()
else -> error("Unknown diagnostic type ${diagnostic::class.simpleName}")
}
diagnostics.addValueFor(psiDiagnostic.psiElement, psiDiagnostic)
}
}
private fun FirLightDiagnostic.toPsiDiagnostic(): FirPsiDiagnostic {
private fun KtLightDiagnostic.toPsiDiagnostic(): KtPsiDiagnostic {
val psiSourceElement = element.unwrapToKtPsiSourceElement()
?: error("Diagnostic should be created from PSI in IDE")
@Suppress("UNCHECKED_CAST")
return when (this) {
is FirLightSimpleDiagnostic -> FirPsiSimpleDiagnostic(
is KtLightSimpleDiagnostic -> KtPsiSimpleDiagnostic(
psiSourceElement,
severity,
factory,
positioningStrategy
)
is FirLightDiagnosticWithParameters1<*> -> FirPsiDiagnosticWithParameters1(
is KtLightDiagnosticWithParameters1<*> -> KtPsiDiagnosticWithParameters1(
psiSourceElement,
a,
severity,
factory as FirDiagnosticFactory1<Any?>,
factory as KtDiagnosticFactory1<Any?>,
positioningStrategy
)
is FirLightDiagnosticWithParameters2<*, *> -> FirPsiDiagnosticWithParameters2(
is KtLightDiagnosticWithParameters2<*, *> -> KtPsiDiagnosticWithParameters2(
psiSourceElement,
a, b,
severity,
factory as FirDiagnosticFactory2<Any?, Any?>,
factory as KtDiagnosticFactory2<Any?, Any?>,
positioningStrategy
)
is FirLightDiagnosticWithParameters3<*, *, *> -> FirPsiDiagnosticWithParameters3(
is KtLightDiagnosticWithParameters3<*, *, *> -> KtPsiDiagnosticWithParameters3(
psiSourceElement,
a, b, c,
severity,
factory as FirDiagnosticFactory3<Any?, Any?, Any?>,
factory as KtDiagnosticFactory3<Any?, Any?, Any?>,
positioningStrategy
)
is FirLightDiagnosticWithParameters4<*, *, *, *> -> FirPsiDiagnosticWithParameters4(
is KtLightDiagnosticWithParameters4<*, *, *, *> -> KtPsiDiagnosticWithParameters4(
psiSourceElement,
a, b, c, d,
severity,
factory as FirDiagnosticFactory4<Any?, Any?, Any?, Any?>,
factory as KtDiagnosticFactory4<Any?, Any?, Any?, Any?>,
positioningStrategy
)
else -> error("Unknown diagnostic type ${this::class.simpleName}")
@@ -6,10 +6,6 @@
package org.jetbrains.kotlin.analysis.low.level.api.fir.file.structure
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirPsiDiagnostic
import org.jetbrains.kotlin.fir.declarations.FirFile
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
import org.jetbrains.kotlin.fir.resolve.ScopeSession
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.DiagnosticCheckerFilter
import org.jetbrains.kotlin.analysis.low.level.api.fir.element.builder.getNonLocalContainingOrThisDeclaration
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.FirFileBuilder
@@ -18,6 +14,10 @@ import org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve.FirLazyDecla
import org.jetbrains.kotlin.analysis.low.level.api.fir.providers.firIdeProvider
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.findSourceNonLocalFirDeclaration
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.getElementTextInContext
import org.jetbrains.kotlin.fir.analysis.diagnostics.KtPsiDiagnostic
import org.jetbrains.kotlin.fir.declarations.FirFile
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
import org.jetbrains.kotlin.fir.resolve.ScopeSession
import org.jetbrains.kotlin.psi.*
import java.util.concurrent.ConcurrentHashMap
@@ -70,7 +70,7 @@ internal class FileStructure private constructor(
}
@OptIn(ExperimentalStdlibApi::class)
fun getAllDiagnosticsForFile(diagnosticCheckerFilter: DiagnosticCheckerFilter): Collection<FirPsiDiagnostic> {
fun getAllDiagnosticsForFile(diagnosticCheckerFilter: DiagnosticCheckerFilter): Collection<KtPsiDiagnostic> {
val structureElements = getAllStructureElements()
return buildList {
@@ -78,7 +78,7 @@ internal class FileStructure private constructor(
}
}
private fun MutableCollection<FirPsiDiagnostic>.collectDiagnosticsFromStructureElements(
private fun MutableCollection<KtPsiDiagnostic>.collectDiagnosticsFromStructureElements(
structureElements: Collection<FileStructureElement>,
diagnosticCheckerFilter: DiagnosticCheckerFilter
) {
@@ -10,13 +10,12 @@ import org.jetbrains.kotlin.analysis.low.level.api.fir.api.FirModuleResolveState
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.collectDiagnosticsForFile
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.resolvedFirToPhase
import org.jetbrains.kotlin.fir.analysis.AbstractFirAnalyzerFacade
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnostic
import org.jetbrains.kotlin.fir.analysis.diagnostics.KtDiagnostic
import org.jetbrains.kotlin.fir.backend.Fir2IrResult
import org.jetbrains.kotlin.fir.declarations.FirFile
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
import org.jetbrains.kotlin.fir.resolve.ScopeSession
import org.jetbrains.kotlin.fir.resolve.transformers.FirSealedClassInheritorsProcessor
import org.jetbrains.kotlin.psi
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.psi2ir.generators.GeneratorExtensions
import org.jetbrains.kotlin.test.model.TestFile
@@ -28,13 +27,13 @@ class LowLevelFirAnalyzerFacade(
) : AbstractFirAnalyzerFacade() {
override val scopeSession: ScopeSession get() = shouldNotBeCalled()
override fun runCheckers(): Map<FirFile, List<FirDiagnostic>> {
override fun runCheckers(): Map<FirFile, List<KtDiagnostic>> {
findSealedInheritors()
return allFirFiles.values.associateWith { firFile ->
val ktFile = firFile.psi as KtFile
val diagnostics = ktFile.collectDiagnosticsForFile(resolveState, diagnosticCheckerFilter)
@Suppress("UNCHECKED_CAST")
diagnostics.toList() as List<FirDiagnostic>
diagnostics.toList() as List<KtDiagnostic>
}
}