FIR: Decouple AbstractDiagnosticCollectorComponent and AbstractDiagnosticCollector

This commit is contained in:
Ilya Kirillov
2021-04-26 17:44:18 +02:00
parent e43835c9f5
commit 81a7271009
18 changed files with 221 additions and 189 deletions
@@ -9,6 +9,7 @@ import org.jetbrains.kotlin.fir.FirElement
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollector
import org.jetbrains.kotlin.fir.analysis.collectors.FirDiagnosticsCollector
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporterFactory
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
import org.jetbrains.kotlin.fir.declarations.FirFile
import org.jetbrains.kotlin.fir.resolve.ScopeSession
@@ -19,7 +20,7 @@ class FirCheckersResolveProcessor(
session: FirSession,
scopeSession: ScopeSession
) : FirTransformerBasedResolveProcessor(session, scopeSession) {
val diagnosticCollector = FirDiagnosticsCollector.create(session, scopeSession)
val diagnosticCollector: AbstractDiagnosticCollector = FirDiagnosticsCollector.create(session, scopeSession)
override val transformer: FirTransformer<Nothing?> = FirCheckersRunnerTransformer(diagnosticCollector)
}
@@ -30,7 +31,8 @@ class FirCheckersRunnerTransformer(private val diagnosticCollector: AbstractDiag
}
override fun transformFile(file: FirFile, data: Nothing?): FirDeclaration {
diagnosticCollector.collectDiagnostics(file)
val reporter = DiagnosticReporterFactory.createReporter()
diagnosticCollector.collectDiagnostics(file, reporter)
return file
}
}
@@ -19,33 +19,15 @@ import org.jetbrains.kotlin.fir.types.*
abstract class AbstractDiagnosticCollector(
override val session: FirSession,
override val scopeSession: ScopeSession = ScopeSession(),
protected val createComponents: (DiagnosticReporter) -> List<AbstractDiagnosticCollectorComponent>,
) : SessionHolder {
fun collectDiagnostics(firDeclaration: FirDeclaration): List<FirDiagnostic<*>> {
if (!componentsInitialized) {
throw IllegalStateException("Components are not initialized")
}
initializeCollector()
fun collectDiagnostics(firDeclaration: FirDeclaration, reporter: DiagnosticReporter) {
val components = createComponents(reporter)
val visitor = createVisitor(components)
firDeclaration.accept(visitor, null)
return getCollectedDiagnostics()
}
protected abstract fun initializeCollector()
protected abstract fun getCollectedDiagnostics(): List<FirDiagnostic<*>>
abstract val reporter: DiagnosticReporter
protected val components: MutableList<AbstractDiagnosticCollectorComponent> = mutableListOf()
private var componentsInitialized = false
protected abstract val visitor: CheckerRunningDiagnosticCollectorVisitor
fun initializeComponents(vararg components: AbstractDiagnosticCollectorComponent) {
if (componentsInitialized) {
throw IllegalStateException()
}
this.components += components
componentsInitialized = true
}
protected abstract fun createVisitor(components: List<AbstractDiagnosticCollectorComponent>): CheckerRunningDiagnosticCollectorVisitor
companion object {
const val SUPPRESS_ALL_INFOS = "infos"
@@ -66,14 +48,3 @@ abstract class AbstractDiagnosticCollector(
}
}
}
fun AbstractDiagnosticCollector.registerAllComponents() {
initializeComponents(
DeclarationCheckersDiagnosticComponent(this),
ExpressionCheckersDiagnosticComponent(this),
TypeCheckersDiagnosticComponent(this),
ErrorNodeDiagnosticCollectorComponent(this),
ControlFlowAnalysisDiagnosticComponent(this),
)
}
@@ -6,12 +6,20 @@
package org.jetbrains.kotlin.fir.analysis.collectors
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.analysis.collectors.components.DiagnosticComponentsFactory
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnostic
import org.jetbrains.kotlin.fir.analysis.diagnostics.impl.DiagnosticReporterWithSuppress
import org.jetbrains.kotlin.fir.analysis.diagnostics.impl.SimpleDiagnosticReporter
import org.jetbrains.kotlin.fir.declarations.FirFile
import org.jetbrains.kotlin.fir.resolve.ScopeSession
object FirDiagnosticsCollector {
fun create(session: FirSession, scopeSession: ScopeSession): SimpleDiagnosticsCollector {
val collector = SimpleDiagnosticsCollector(session, scopeSession)
collector.registerAllComponents()
return collector
fun create(
session: FirSession,
scopeSession: ScopeSession,
): SimpleDiagnosticsCollector {
return SimpleDiagnosticsCollector(session, scopeSession) { reporter ->
DiagnosticComponentsFactory.createAllDiagnosticComponents(session, reporter)
}
}
}
@@ -7,42 +7,29 @@ package org.jetbrains.kotlin.fir.analysis.collectors
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.analysis.checkers.context.PersistentCheckerContext
import org.jetbrains.kotlin.fir.analysis.collectors.components.AbstractDiagnosticCollectorComponent
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnostic
import org.jetbrains.kotlin.fir.analysis.diagnostics.impl.BaseDiagnosticReporter
import org.jetbrains.kotlin.fir.analysis.diagnostics.impl.DiagnosticReporterWithSuppress
import org.jetbrains.kotlin.fir.analysis.diagnostics.impl.SimpleDiagnosticReporter
import org.jetbrains.kotlin.fir.resolve.ScopeSession
import org.jetbrains.kotlin.fir.resolve.SessionHolder
import org.jetbrains.kotlin.fir.resolve.transformers.ReturnTypeCalculatorForFullBodyResolve
class SimpleDiagnosticsCollector(
session: FirSession,
scopeSession: ScopeSession,
private val disableSuppress: Boolean = false
) : AbstractDiagnosticCollector(session, scopeSession) {
override val visitor: CheckerRunningDiagnosticCollectorVisitor = CheckerRunningDiagnosticCollectorVisitor(
PersistentCheckerContext(
this,
ReturnTypeCalculatorForFullBodyResolve()
),
components
)
override var reporter = createDiagnosticReporter()
private set
private fun createDiagnosticReporter(): BaseDiagnosticReporter {
return if (disableSuppress) {
SimpleDiagnosticReporter()
} else {
DiagnosticReporterWithSuppress()
}
}
override fun initializeCollector() {
reporter = createDiagnosticReporter()
}
override fun getCollectedDiagnostics(): List<FirDiagnostic<*>> {
return reporter.diagnostics
createComponents: (DiagnosticReporter) -> List<AbstractDiagnosticCollectorComponent>,
) : AbstractDiagnosticCollector(session, scopeSession, createComponents) {
override fun createVisitor(components: List<AbstractDiagnosticCollectorComponent>): CheckerRunningDiagnosticCollectorVisitor {
return CheckerRunningDiagnosticCollectorVisitor(
PersistentCheckerContext(
this,
ReturnTypeCalculatorForFullBodyResolve()
),
components
)
}
}
@@ -12,11 +12,9 @@ import org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollector
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.visitors.FirVisitor
abstract class AbstractDiagnosticCollectorComponent(private val collector: AbstractDiagnosticCollector) : FirVisitor<Unit, CheckerContext>() {
protected val session: FirSession = collector.session
abstract class AbstractDiagnosticCollectorComponent(
protected val session: FirSession,
protected val reporter: DiagnosticReporter,
) : FirVisitor<Unit, CheckerContext>() {
override fun visitElement(element: FirElement, data: CheckerContext) {}
protected val reporter: DiagnosticReporter
get() = collector.reporter
}
@@ -5,19 +5,22 @@
package org.jetbrains.kotlin.fir.analysis.collectors.components
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.analysis.cfa.FirControlFlowAnalyzer
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.DeclarationCheckers
import org.jetbrains.kotlin.fir.analysis.checkersComponent
import org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollector
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.references.FirControlFlowGraphReference
import org.jetbrains.kotlin.fir.resolve.dfa.controlFlowGraph
class ControlFlowAnalysisDiagnosticComponent(
collector: AbstractDiagnosticCollector,
declarationCheckers: DeclarationCheckers = collector.session.checkersComponent.declarationCheckers,
) : AbstractDiagnosticCollectorComponent(collector) {
session: FirSession,
reporter: DiagnosticReporter,
declarationCheckers: DeclarationCheckers = session.checkersComponent.declarationCheckers,
) : AbstractDiagnosticCollectorComponent(session, reporter) {
private val controlFlowAnalyzer = FirControlFlowAnalyzer(session, declarationCheckers)
// ------------------------------- Class initializer -------------------------------
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.fir.analysis.collectors.components
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.analysis.CheckersComponentInternal
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.DeclarationCheckers
@@ -16,9 +17,10 @@ import org.jetbrains.kotlin.fir.declarations.*
@OptIn(CheckersComponentInternal::class)
class DeclarationCheckersDiagnosticComponent(
collector: AbstractDiagnosticCollector,
private val checkers: DeclarationCheckers = collector.session.checkersComponent.declarationCheckers,
) : AbstractDiagnosticCollectorComponent(collector) {
session: FirSession,
reporter: DiagnosticReporter,
private val checkers: DeclarationCheckers = session.checkersComponent.declarationCheckers,
) : AbstractDiagnosticCollectorComponent(session, reporter) {
override fun visitFile(file: FirFile, data: CheckerContext) {
checkers.allFileCheckers.check(file, data, reporter)
@@ -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.fir.analysis.collectors.components
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
object DiagnosticComponentsFactory {
fun createAllDiagnosticComponents(session: FirSession, reporter: DiagnosticReporter): List<AbstractDiagnosticCollectorComponent> {
return listOf(
DeclarationCheckersDiagnosticComponent(session, reporter),
ExpressionCheckersDiagnosticComponent(session, reporter),
TypeCheckersDiagnosticComponent(session, reporter),
ErrorNodeDiagnosticCollectorComponent(session, reporter),
ControlFlowAnalysisDiagnosticComponent(session, reporter),
)
}
}
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.fir.analysis.collectors.components
import org.jetbrains.kotlin.KtNodeTypes
import org.jetbrains.kotlin.fir.FirFakeSourceElementKind
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.FirSourceElement
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollector
@@ -23,7 +24,10 @@ import org.jetbrains.kotlin.fir.types.ConeClassErrorType
import org.jetbrains.kotlin.fir.types.FirErrorTypeRef
import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef
class ErrorNodeDiagnosticCollectorComponent(collector: AbstractDiagnosticCollector) : AbstractDiagnosticCollectorComponent(collector) {
class ErrorNodeDiagnosticCollectorComponent(
session: FirSession,
reporter: DiagnosticReporter,
) : AbstractDiagnosticCollectorComponent(session, reporter) {
override fun visitErrorLoop(errorLoop: FirErrorLoop, data: CheckerContext) {
val source = errorLoop.source ?: return
reportFirDiagnostic(errorLoop.diagnostic, source, reporter, data)
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.fir.analysis.collectors.components
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.analysis.CheckersComponentInternal
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.expression.ExpressionCheckers
@@ -17,9 +18,10 @@ import org.jetbrains.kotlin.fir.expressions.*
@OptIn(CheckersComponentInternal::class)
class ExpressionCheckersDiagnosticComponent(
collector: AbstractDiagnosticCollector,
private val checkers: ExpressionCheckers = collector.session.checkersComponent.expressionCheckers,
) : AbstractDiagnosticCollectorComponent(collector) {
session: FirSession,
reporter: DiagnosticReporter,
private val checkers: ExpressionCheckers = session.checkersComponent.expressionCheckers,
) : AbstractDiagnosticCollectorComponent(session, reporter) {
override fun visitAnonymousFunction(anonymousFunction: FirAnonymousFunction, data: CheckerContext) {
checkers.allAnonymousFunctionAsExpressionCheckers.check(anonymousFunction, data, reporter)
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.fir.analysis.collectors.components
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.analysis.CheckersComponentInternal
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.type.FirTypeChecker
@@ -16,9 +17,10 @@ import org.jetbrains.kotlin.fir.types.*
@OptIn(CheckersComponentInternal::class)
class TypeCheckersDiagnosticComponent(
collector: AbstractDiagnosticCollector,
private val checkers: TypeCheckers = collector.session.checkersComponent.typeCheckers,
) : AbstractDiagnosticCollectorComponent(collector) {
session: FirSession,
reporter: DiagnosticReporter,
private val checkers: TypeCheckers = session.checkersComponent.typeCheckers,
) : AbstractDiagnosticCollectorComponent(session, reporter) {
override fun visitDynamicTypeRef(dynamicTypeRef: FirDynamicTypeRef, data: CheckerContext) {
checkers.allTypeRefCheckers.check(dynamicTypeRef, data, reporter)
@@ -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.fir.analysis.diagnostics
import org.jetbrains.kotlin.fir.analysis.diagnostics.impl.BaseDiagnosticReporter
import org.jetbrains.kotlin.fir.analysis.diagnostics.impl.DiagnosticReporterWithSuppress
import org.jetbrains.kotlin.fir.analysis.diagnostics.impl.SimpleDiagnosticReporter
object DiagnosticReporterFactory {
fun createReporter(disableSuppress: Boolean = false): BaseDiagnosticReporter {
return if (disableSuppress) {
SimpleDiagnosticReporter()
} else {
DiagnosticReporterWithSuppress()
}
}
}
@@ -9,6 +9,7 @@ import org.jetbrains.kotlin.backend.jvm.serialization.JvmIdSignatureDescriptor
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.analysis.collectors.FirDiagnosticsCollector
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporterFactory
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnostic
import org.jetbrains.kotlin.fir.backend.Fir2IrConverter
import org.jetbrains.kotlin.fir.backend.Fir2IrResult
@@ -78,7 +79,9 @@ class FirAnalyzerFacade(
val collector = FirDiagnosticsCollector.create(session, scopeSession)
collectedDiagnostics = buildMap {
for (file in firFiles!!) {
put(file, collector.collectDiagnostics(file))
val reporter = DiagnosticReporterFactory.createReporter()
collector.collectDiagnostics(file, reporter)
put(file, reporter.diagnostics)
}
}
return collectedDiagnostics!!