diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/FirCheckersResolveProcessor.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/FirCheckersResolveProcessor.kt index 94d441b9f26..431ffc4df6f 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/FirCheckersResolveProcessor.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/FirCheckersResolveProcessor.kt @@ -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 = 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 } } \ No newline at end of file diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/AbstractDiagnosticCollector.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/AbstractDiagnosticCollector.kt index 76d5f4831d3..3903aff1893 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/AbstractDiagnosticCollector.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/AbstractDiagnosticCollector.kt @@ -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, ) : SessionHolder { - fun collectDiagnostics(firDeclaration: FirDeclaration): List> { - 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> - abstract val reporter: DiagnosticReporter - - protected val components: MutableList = 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): 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), - ) -} diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/FirDiagnosticsCollector.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/FirDiagnosticsCollector.kt index 331af0b92d2..e1431d2d2da 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/FirDiagnosticsCollector.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/FirDiagnosticsCollector.kt @@ -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) + } } } diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/SimpleDiagnosticsCollector.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/SimpleDiagnosticsCollector.kt index 070b62a0fc6..6797bbad093 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/SimpleDiagnosticsCollector.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/SimpleDiagnosticsCollector.kt @@ -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> { - return reporter.diagnostics + createComponents: (DiagnosticReporter) -> List, +) : AbstractDiagnosticCollector(session, scopeSession, createComponents) { + override fun createVisitor(components: List): CheckerRunningDiagnosticCollectorVisitor { + return CheckerRunningDiagnosticCollectorVisitor( + PersistentCheckerContext( + this, + ReturnTypeCalculatorForFullBodyResolve() + ), + components + ) } } diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/components/AbstractDiagnosticCollectorComponent.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/components/AbstractDiagnosticCollectorComponent.kt index ac982ba3e26..f1c68d3cbd4 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/components/AbstractDiagnosticCollectorComponent.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/components/AbstractDiagnosticCollectorComponent.kt @@ -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() { - protected val session: FirSession = collector.session - +abstract class AbstractDiagnosticCollectorComponent( + protected val session: FirSession, + protected val reporter: DiagnosticReporter, +) : FirVisitor() { override fun visitElement(element: FirElement, data: CheckerContext) {} - - protected val reporter: DiagnosticReporter - get() = collector.reporter } diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/components/ControlFlowAnalysisDiagnosticComponent.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/components/ControlFlowAnalysisDiagnosticComponent.kt index 9cbe152f45b..2bcd76e3162 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/components/ControlFlowAnalysisDiagnosticComponent.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/components/ControlFlowAnalysisDiagnosticComponent.kt @@ -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 ------------------------------- diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/components/DeclarationCheckersDiagnosticComponent.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/components/DeclarationCheckersDiagnosticComponent.kt index e39b01910de..f79b1ea5891 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/components/DeclarationCheckersDiagnosticComponent.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/components/DeclarationCheckersDiagnosticComponent.kt @@ -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) diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/components/DiagnosticComponentsFactory.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/components/DiagnosticComponentsFactory.kt new file mode 100644 index 00000000000..d568e1399bd --- /dev/null +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/components/DiagnosticComponentsFactory.kt @@ -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 { + return listOf( + DeclarationCheckersDiagnosticComponent(session, reporter), + ExpressionCheckersDiagnosticComponent(session, reporter), + TypeCheckersDiagnosticComponent(session, reporter), + ErrorNodeDiagnosticCollectorComponent(session, reporter), + ControlFlowAnalysisDiagnosticComponent(session, reporter), + ) + } + +} \ No newline at end of file diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/components/ErrorNodeDiagnosticCollectorComponent.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/components/ErrorNodeDiagnosticCollectorComponent.kt index 29d2e3fc84a..f5dacf54bd3 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/components/ErrorNodeDiagnosticCollectorComponent.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/components/ErrorNodeDiagnosticCollectorComponent.kt @@ -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) diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/components/ExpressionCheckersDiagnosticComponent.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/components/ExpressionCheckersDiagnosticComponent.kt index f9766b0f4a5..123d62c5a21 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/components/ExpressionCheckersDiagnosticComponent.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/components/ExpressionCheckersDiagnosticComponent.kt @@ -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) diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/components/TypeCheckersDiagnosticComponent.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/components/TypeCheckersDiagnosticComponent.kt index bf0fb65cdc4..03ad0730e93 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/components/TypeCheckersDiagnosticComponent.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/components/TypeCheckersDiagnosticComponent.kt @@ -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) diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/DiagnosticReporterFactory.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/DiagnosticReporterFactory.kt new file mode 100644 index 00000000000..7f5020446e1 --- /dev/null +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/DiagnosticReporterFactory.kt @@ -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() + } + } +} \ No newline at end of file diff --git a/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/analysis/FirAnalyzerFacade.kt b/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/analysis/FirAnalyzerFacade.kt index ec44f315ab1..df9178af079 100644 --- a/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/analysis/FirAnalyzerFacade.kt +++ b/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/analysis/FirAnalyzerFacade.kt @@ -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!! diff --git a/compiler/tests-common/tests/org/jetbrains/kotlin/fir/AbstractFirDiagnosticTest.kt b/compiler/tests-common/tests/org/jetbrains/kotlin/fir/AbstractFirDiagnosticTest.kt index 2d4cfb27b8d..a9a43801870 100644 --- a/compiler/tests-common/tests/org/jetbrains/kotlin/fir/AbstractFirDiagnosticTest.kt +++ b/compiler/tests-common/tests/org/jetbrains/kotlin/fir/AbstractFirDiagnosticTest.kt @@ -268,7 +268,9 @@ abstract class AbstractFirDiagnosticsTest : AbstractFirBaseDiagnosticsTest() { for (firFile in firFiles) { val session = firFile.declarationSiteSession val collector = collectors.computeIfAbsent(session) { createCollector(session) } - result[firFile] = collector.collectDiagnostics(firFile).toList() + val reporter = DiagnosticReporterFactory.createReporter() + collector.collectDiagnostics(firFile, reporter) + result[firFile] = reporter.diagnostics } return result } diff --git a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/diagnostics/AbstractFirIdeDiagnosticsCollector.kt b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/diagnostics/AbstractFirIdeDiagnosticsCollector.kt index 75f57806a63..76057f27fe1 100644 --- a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/diagnostics/AbstractFirIdeDiagnosticsCollector.kt +++ b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/diagnostics/AbstractFirIdeDiagnosticsCollector.kt @@ -5,122 +5,72 @@ package org.jetbrains.kotlin.idea.fir.low.level.api.diagnostics -import com.intellij.psi.PsiElement import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.SessionConfiguration import org.jetbrains.kotlin.fir.analysis.CheckersComponent -import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext import org.jetbrains.kotlin.fir.analysis.checkers.declaration.DeclarationCheckers import org.jetbrains.kotlin.fir.analysis.checkers.expression.ExpressionCheckers import org.jetbrains.kotlin.fir.analysis.checkers.type.TypeCheckers import org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollector import org.jetbrains.kotlin.fir.analysis.collectors.components.* -import org.jetbrains.kotlin.fir.analysis.diagnostics.* +import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter import org.jetbrains.kotlin.fir.checkers.* internal abstract class AbstractFirIdeDiagnosticsCollector( session: FirSession, useExtendedCheckers: Boolean, ) : AbstractDiagnosticCollector( - session -) { - init { - val declarationCheckers = CheckersFactory.createDeclarationCheckers(useExtendedCheckers) - val expressionCheckers = CheckersFactory.createExpressionCheckers(useExtendedCheckers) - val typeCheckers = CheckersFactory.createTypeCheckers(useExtendedCheckers) - - @Suppress("LeakingThis") - initializeComponents( - DeclarationCheckersDiagnosticComponent(this, declarationCheckers), - ExpressionCheckersDiagnosticComponent(this, expressionCheckers), - TypeCheckersDiagnosticComponent(this, typeCheckers), - ErrorNodeDiagnosticCollectorComponent(this), - ControlFlowAnalysisDiagnosticComponent(this, declarationCheckers), - ) + session, + createComponents = { reporter -> + CheckersFactory.createComponents(session, reporter, useExtendedCheckers) } - - protected abstract fun onDiagnostic(diagnostic: FirPsiDiagnostic<*>) +) - private inner class Reporter : DiagnosticReporter() { - override fun report(diagnostic: FirDiagnostic<*>?, context: CheckerContext) { - if (diagnostic == null) return - if (context.isDiagnosticSuppressed(diagnostic)) return +private object CheckersFactory { + fun createComponents( + session: FirSession, + reporter: DiagnosticReporter, + useExtendedCheckers: Boolean + ): List { + val declarationCheckers = createDeclarationCheckers(useExtendedCheckers) + val expressionCheckers = createExpressionCheckers(useExtendedCheckers) + val typeCheckers = createTypeCheckers(useExtendedCheckers) - val psiDiagnostic = when (diagnostic) { - is FirPsiDiagnostic<*> -> diagnostic - is FirLightDiagnostic -> diagnostic.toPsiDiagnostic() - else -> error("Unknown diagnostic type ${diagnostic::class.simpleName}") - } - - onDiagnostic(psiDiagnostic) + return if (useExtendedCheckers) { + listOf( + DeclarationCheckersDiagnosticComponent(session, reporter, declarationCheckers), + ExpressionCheckersDiagnosticComponent(session, reporter, expressionCheckers), + TypeCheckersDiagnosticComponent(session, reporter, typeCheckers), + ControlFlowAnalysisDiagnosticComponent(session, reporter, declarationCheckers), + ) + } else { + listOf( + DeclarationCheckersDiagnosticComponent(session, reporter, declarationCheckers), + ExpressionCheckersDiagnosticComponent(session, reporter, expressionCheckers), + TypeCheckersDiagnosticComponent(session, reporter, typeCheckers), + ErrorNodeDiagnosticCollectorComponent(session, reporter), + ControlFlowAnalysisDiagnosticComponent(session, reporter, declarationCheckers), + ) } } - override var reporter: DiagnosticReporter = Reporter() - - override fun initializeCollector() { - reporter = Reporter() - } - - - override fun getCollectedDiagnostics(): List> { - // Not necessary in IDE - return emptyList() - } -} - -private fun FirLightDiagnostic.toPsiDiagnostic(): FirPsiDiagnostic<*> { - val psiSourceElement = element.unwrapToFirPsiSourceElement() - ?: error("Diagnostic should be created from PSI in IDE") - @Suppress("UNCHECKED_CAST") - return when (this) { - is FirLightSimpleDiagnostic -> FirPsiSimpleDiagnostic( - psiSourceElement, - severity, - factory as FirDiagnosticFactory0 - ) - - is FirLightDiagnosticWithParameters1<*> -> FirPsiDiagnosticWithParameters1( - psiSourceElement, - a, - severity, - factory as FirDiagnosticFactory1 - ) - - is FirLightDiagnosticWithParameters2<*, *> -> FirPsiDiagnosticWithParameters2( - psiSourceElement, - a, b, - severity, - factory as FirDiagnosticFactory2 - ) - - is FirLightDiagnosticWithParameters3<*, *, *> -> FirPsiDiagnosticWithParameters3( - psiSourceElement, - a, b, c, - severity, - factory as FirDiagnosticFactory3 - ) - else -> error("Unknown diagnostic type ${this::class.simpleName}") - } -} - -private object CheckersFactory { private val extendedDeclarationCheckers = createDeclarationCheckers(ExtendedDeclarationCheckers) - private val commonDeclarationCheckers = createDeclarationCheckers(CommonDeclarationCheckers) - fun createDeclarationCheckers(useExtendedCheckers: Boolean): DeclarationCheckers = + private val commonDeclarationCheckers = createDeclarationCheckers(CommonDeclarationCheckers,) + + private fun createDeclarationCheckers(useExtendedCheckers: Boolean): DeclarationCheckers = if (useExtendedCheckers) extendedDeclarationCheckers else commonDeclarationCheckers - fun createExpressionCheckers(useExtendedCheckers: Boolean): ExpressionCheckers = + private fun createExpressionCheckers(useExtendedCheckers: Boolean): ExpressionCheckers = if (useExtendedCheckers) ExtendedExpressionCheckers else CommonExpressionCheckers - fun createTypeCheckers(useExtendedCheckers: Boolean): TypeCheckers = CommonTypeCheckers + private fun createTypeCheckers(useExtendedCheckers: Boolean): TypeCheckers = CommonTypeCheckers // TODO hack to have all checkers present in DeclarationCheckers.memberDeclarationCheckers and similar // If use ExtendedDeclarationCheckers directly when DeclarationCheckers.memberDeclarationCheckers will not contain basicDeclarationCheckers @OptIn(SessionConfiguration::class) - private fun createDeclarationCheckers(declarationCheckers: DeclarationCheckers): DeclarationCheckers = - CheckersComponent().apply { register(declarationCheckers) }.declarationCheckers + private fun createDeclarationCheckers(vararg declarationCheckers: DeclarationCheckers): DeclarationCheckers = + CheckersComponent().apply { declarationCheckers.forEach(::register) }.declarationCheckers } diff --git a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/diagnostics/FileStructureElementDiagnosticsCollector.kt b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/diagnostics/FileStructureElementDiagnosticsCollector.kt index dbafbd857e2..6b75cec7914 100644 --- a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/diagnostics/FileStructureElementDiagnosticsCollector.kt +++ b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/diagnostics/FileStructureElementDiagnosticsCollector.kt @@ -19,13 +19,14 @@ internal class FileStructureElementDiagnosticsCollector private constructor(priv fun collectForStructureElement( firDeclaration: FirDeclaration, createVisitor: (components: List) -> CheckerRunningDiagnosticCollectorVisitor, - ): FileStructureElementDiagnosticList = - FirIdeStructureElementDiagnosticsCollector( + ): FileStructureElementDiagnosticList { + val reporter = FirIdeDiagnosticReporter() + val collector = FirIdeStructureElementDiagnosticsCollector( firDeclaration.declarationSiteSession, createVisitor, useExtendedCheckers, - ).let { collector -> - collector.collectDiagnostics(firDeclaration) - FileStructureElementDiagnosticList(collector.result) - } + ) + collector.collectDiagnostics(firDeclaration, reporter) + return FileStructureElementDiagnosticList(reporter.diagnostics) + } } diff --git a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/diagnostics/FirIdeDiagnosticReporter.kt b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/diagnostics/FirIdeDiagnosticReporter.kt new file mode 100644 index 00000000000..43d2cd8a5c9 --- /dev/null +++ b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/diagnostics/FirIdeDiagnosticReporter.kt @@ -0,0 +1,62 @@ +/* + * 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.idea.fir.low.level.api.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.idea.fir.low.level.api.util.addValueFor + +internal class FirIdeDiagnosticReporter : DiagnosticReporter() { + val diagnostics = mutableMapOf>>() + + override fun report(diagnostic: FirDiagnostic<*>?, context: CheckerContext) { + if (diagnostic == null) return + if (context.isDiagnosticSuppressed(diagnostic)) return + + val psiDiagnostic = when (diagnostic) { + is FirPsiDiagnostic<*> -> diagnostic + is FirLightDiagnostic -> diagnostic.toPsiDiagnostic() + else -> error("Unknown diagnostic type ${diagnostic::class.simpleName}") + } + diagnostics.addValueFor(psiDiagnostic.psiElement, psiDiagnostic) + } +} + +private fun FirLightDiagnostic.toPsiDiagnostic(): FirPsiDiagnostic<*> { + val psiSourceElement = element.unwrapToFirPsiSourceElement() + ?: error("Diagnostic should be created from PSI in IDE") + @Suppress("UNCHECKED_CAST") + return when (this) { + is FirLightSimpleDiagnostic -> FirPsiSimpleDiagnostic( + psiSourceElement, + severity, + factory as FirDiagnosticFactory0 + ) + + is FirLightDiagnosticWithParameters1<*> -> FirPsiDiagnosticWithParameters1( + psiSourceElement, + a, + severity, + factory as FirDiagnosticFactory1 + ) + + is FirLightDiagnosticWithParameters2<*, *> -> FirPsiDiagnosticWithParameters2( + psiSourceElement, + a, b, + severity, + factory as FirDiagnosticFactory2 + ) + + is FirLightDiagnosticWithParameters3<*, *, *> -> FirPsiDiagnosticWithParameters3( + psiSourceElement, + a, b, c, + severity, + factory as FirDiagnosticFactory3 + ) + else -> error("Unknown diagnostic type ${this::class.simpleName}") + } +} \ No newline at end of file diff --git a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/diagnostics/fir/FirIdeStructureElementDiagnosticsCollector.kt b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/diagnostics/fir/FirIdeStructureElementDiagnosticsCollector.kt index a711a7ffb74..dbde762fdb6 100644 --- a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/diagnostics/fir/FirIdeStructureElementDiagnosticsCollector.kt +++ b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/diagnostics/fir/FirIdeStructureElementDiagnosticsCollector.kt @@ -5,27 +5,20 @@ package org.jetbrains.kotlin.idea.fir.low.level.api.diagnostics.fir -import com.intellij.psi.PsiElement import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.analysis.collectors.CheckerRunningDiagnosticCollectorVisitor import org.jetbrains.kotlin.fir.analysis.collectors.components.AbstractDiagnosticCollectorComponent -import org.jetbrains.kotlin.fir.analysis.diagnostics.FirPsiDiagnostic import org.jetbrains.kotlin.idea.fir.low.level.api.diagnostics.AbstractFirIdeDiagnosticsCollector -import org.jetbrains.kotlin.idea.fir.low.level.api.util.addValueFor internal class FirIdeStructureElementDiagnosticsCollector( session: FirSession, - createVisitor: (components: List) -> CheckerRunningDiagnosticCollectorVisitor, + private val doCreateVisitor: (components: List) -> CheckerRunningDiagnosticCollectorVisitor, useExtendedCheckers: Boolean, ) : AbstractFirIdeDiagnosticsCollector( session, useExtendedCheckers, ) { - override val visitor: CheckerRunningDiagnosticCollectorVisitor = createVisitor(components) - - val result = mutableMapOf>>() - - override fun onDiagnostic(diagnostic: FirPsiDiagnostic<*>) { - result.addValueFor(diagnostic.psiElement, diagnostic) + override fun createVisitor(components: List): CheckerRunningDiagnosticCollectorVisitor { + return doCreateVisitor(components) } } \ No newline at end of file