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 b01a3302514..e507e5e6e40 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 @@ -67,12 +67,6 @@ abstract class AbstractDiagnosticCollector( } } -enum class DiagnosticCollectorDeclarationAction(val checkInCurrentDeclaration: Boolean, val lookupForNestedDeclaration: Boolean) { - CHECK_IN_CURRENT_DECLARATION_AND_LOOKUP_FOR_NESTED(checkInCurrentDeclaration = true, lookupForNestedDeclaration = true), - CHECK_IN_CURRENT_DECLARATION_AND_DO_NOT_LOOKUP_FOR_NESTED(checkInCurrentDeclaration = true, lookupForNestedDeclaration = false), - DO_NOT_CHECK_IN_CURRENT_DECLARATION_AND_LOOKUP_FOR_NESTED(checkInCurrentDeclaration = false, lookupForNestedDeclaration = true), - SKIP(checkInCurrentDeclaration = false, lookupForNestedDeclaration = false), -} fun AbstractDiagnosticCollector.registerAllComponents() { initializeComponents( diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/AbstractDiagnosticCollectorVisitor.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/AbstractDiagnosticCollectorVisitor.kt index 61d04dfe614..3b30ba1634e 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/AbstractDiagnosticCollectorVisitor.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/AbstractDiagnosticCollectorVisitor.kt @@ -28,7 +28,6 @@ abstract class AbstractDiagnosticCollectorVisitor( @set:PrivateForInline var context: PersistentCheckerContext, protected val components: List, ) : FirDefaultVisitor() { - protected var currentAction = DiagnosticCollectorDeclarationAction.CHECK_IN_CURRENT_DECLARATION_AND_LOOKUP_FOR_NESTED protected open fun beforeRunningAllComponentsOnElement(element: FirElement) {} protected open fun beforeRunningSingleComponentOnElement(element: FirElement) {} @@ -182,16 +181,10 @@ abstract class AbstractDiagnosticCollectorVisitor( declaration: FirDeclaration, block: () -> Unit = { declaration.acceptChildren(this, null) } ) { - if (!currentAction.lookupForNestedDeclaration) return - - val action = getDeclarationActionOnDeclarationEnter(declaration) - withDiagnosticsAction(action) { - runComponents(declaration) - withDeclaration(declaration) { - block() - } + runComponents(declaration) + withDeclaration(declaration) { + block() } - onDeclarationExit(declaration) } private fun visitWithDeclarationAndReceiver(declaration: FirDeclaration, labelName: Name?, receiverTypeRef: FirTypeRef?) { @@ -220,21 +213,6 @@ abstract class AbstractDiagnosticCollectorVisitor( } } - protected open fun getDeclarationActionOnDeclarationEnter(declaration: FirDeclaration): DiagnosticCollectorDeclarationAction = - DiagnosticCollectorDeclarationAction.CHECK_IN_CURRENT_DECLARATION_AND_LOOKUP_FOR_NESTED - - protected open fun onDeclarationExit(declaration: FirDeclaration) {} - - private inline fun withDiagnosticsAction(action: DiagnosticCollectorDeclarationAction, block: () -> R): R { - val oldAction = currentAction - currentAction = action - return try { - block() - } finally { - currentAction = oldAction - } - } - @OptIn(PrivateForInline::class) inline fun withQualifiedAccess(qualifiedAccess: FirQualifiedAccess, block: () -> R): R { val existingContext = context diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/CheckerRunningDiagnosticCollectorVisitor.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/CheckerRunningDiagnosticCollectorVisitor.kt index 2de527191cf..17db55b4bf4 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/CheckerRunningDiagnosticCollectorVisitor.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/CheckerRunningDiagnosticCollectorVisitor.kt @@ -20,12 +20,10 @@ open class CheckerRunningDiagnosticCollectorVisitor( } override fun runComponents(element: FirElement) { - if (currentAction.checkInCurrentDeclaration) { - beforeRunningAllComponentsOnElement(element) - components.forEach { - beforeRunningSingleComponentOnElement(element) - element.accept(it, context) - } + beforeRunningAllComponentsOnElement(element) + components.forEach { + beforeRunningSingleComponentOnElement(element) + element.accept(it, context) } } } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/BodyResolveComponents.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/BodyResolveComponents.kt index d4574529bf8..c9829eafbc3 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/BodyResolveComponents.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/BodyResolveComponents.kt @@ -36,7 +36,11 @@ interface SessionHolder { val scopeSession: ScopeSession } -data class SessionHolderImpl(override val session: FirSession, override val scopeSession: ScopeSession): SessionHolder +data class SessionHolderImpl(override val session: FirSession, override val scopeSession: ScopeSession) : SessionHolder { + companion object { + fun createWithEmptyScopeSession(session: FirSession): SessionHolderImpl = SessionHolderImpl(session, ScopeSession()) + } +} abstract class BodyResolveComponents : SessionHolder { abstract val returnTypeCalculator: ReturnTypeCalculator diff --git a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/diagnostics/FileStructureElementDiagnosticRetriever.kt b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/diagnostics/FileStructureElementDiagnosticRetriever.kt index 42c3ac0b5ad..5972e9d876d 100644 --- a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/diagnostics/FileStructureElementDiagnosticRetriever.kt +++ b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/diagnostics/FileStructureElementDiagnosticRetriever.kt @@ -5,11 +5,13 @@ package org.jetbrains.kotlin.idea.fir.low.level.api.diagnostics +import org.jetbrains.kotlin.fir.FirElement +import org.jetbrains.kotlin.fir.analysis.collectors.components.AbstractDiagnosticCollectorComponent import org.jetbrains.kotlin.fir.declarations.FirDeclaration import org.jetbrains.kotlin.fir.declarations.FirFile -import org.jetbrains.kotlin.fir.resolve.ScopeSession import org.jetbrains.kotlin.fir.resolve.SessionHolderImpl import org.jetbrains.kotlin.idea.fir.low.level.api.diagnostics.fir.PersistenceContextCollector +import org.jetbrains.kotlin.idea.fir.low.level.api.diagnostics.fir.PersistentCheckerContextFactory internal abstract class FileStructureElementDiagnosticRetriever { abstract fun retrieve(firFile: FirFile, collector: FileStructureElementDiagnosticsCollector): FileStructureElementDiagnosticList @@ -19,8 +21,36 @@ internal class SingleNonLocalDeclarationDiagnosticRetriever( private val declaration: FirDeclaration ) : FileStructureElementDiagnosticRetriever() { override fun retrieve(firFile: FirFile, collector: FileStructureElementDiagnosticsCollector): FileStructureElementDiagnosticList { - val sessionHolder = SessionHolderImpl(firFile.session, ScopeSession()) + val sessionHolder = SessionHolderImpl.createWithEmptyScopeSession(firFile.session) val context = PersistenceContextCollector.collectContext(sessionHolder, firFile, declaration) - return collector.collectForStructureElement(declaration, context) + return collector.collectForStructureElement(declaration) { components -> + FirIdeDiagnosticVisitor(context, components) + } + } +} + +internal object FileDiagnosticRetriever : FileStructureElementDiagnosticRetriever() { + override fun retrieve(firFile: FirFile, collector: FileStructureElementDiagnosticsCollector): FileStructureElementDiagnosticList = + collector.collectForStructureElement(firFile) { components -> + Visitor(firFile, components) + } + + private class Visitor( + firFile: FirFile, + components: List + ) : FirIdeDiagnosticVisitor( + PersistentCheckerContextFactory.createEmptyPersistenceCheckerContext(SessionHolderImpl.createWithEmptyScopeSession(firFile.session)), + components + ) { + override fun goToNestedDeclarations(element: FirElement) { + val goNested = when (element) { + is FirFile -> true + is FirDeclaration -> false + else -> true + } + if (goNested) { + super.goToNestedDeclarations(element) + } + } } } \ 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/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 c50750faf32..fe3f38e6ffd 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 @@ -5,15 +5,10 @@ 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.analysis.checkers.context.PersistentCheckerContext -import org.jetbrains.kotlin.fir.analysis.collectors.DiagnosticCollectorDeclarationAction -import org.jetbrains.kotlin.fir.analysis.diagnostics.FirPsiDiagnostic +import org.jetbrains.kotlin.fir.analysis.collectors.CheckerRunningDiagnosticCollectorVisitor +import org.jetbrains.kotlin.fir.analysis.collectors.components.AbstractDiagnosticCollectorComponent import org.jetbrains.kotlin.fir.declarations.FirDeclaration -import org.jetbrains.kotlin.fir.declarations.FirFile -import org.jetbrains.kotlin.idea.fir.low.level.api.diagnostics.fir.PersistentCheckerContextFactory -import org.jetbrains.kotlin.idea.fir.low.level.api.util.addValueFor +import org.jetbrains.kotlin.idea.fir.low.level.api.diagnostics.fir.FirIdeStructureElementDiagnosticsCollector internal class FileStructureElementDiagnosticsCollector private constructor(private val useExtendedCheckers: Boolean) { companion object { @@ -23,51 +18,14 @@ internal class FileStructureElementDiagnosticsCollector private constructor(priv fun collectForStructureElement( firDeclaration: FirDeclaration, - initialContext: PersistentCheckerContext?, - onDeclarationExit: (FirDeclaration) -> Unit = {}, - onDeclarationEnter: (FirDeclaration) -> DiagnosticCollectorDeclarationAction = { - DiagnosticCollectorDeclarationAction.CHECK_IN_CURRENT_DECLARATION_AND_LOOKUP_FOR_NESTED - }, + createVisitor: (components: List) -> CheckerRunningDiagnosticCollectorVisitor, ): FileStructureElementDiagnosticList = FirIdeStructureElementDiagnosticsCollector( firDeclaration.session, - initialContext, + createVisitor, useExtendedCheckers, - onDeclarationEnter, - onDeclarationExit ).let { collector -> collector.collectDiagnostics(firDeclaration) FileStructureElementDiagnosticList(collector.result) } - - private class FirIdeStructureElementDiagnosticsCollector( - session: FirSession, - initialContext: PersistentCheckerContext?, - useExtendedCheckers: Boolean, - private val onDeclarationEnter: (FirDeclaration) -> DiagnosticCollectorDeclarationAction, - private val onDeclarationExit: (FirDeclaration) -> Unit - ) : AbstractFirIdeDiagnosticsCollector( - session, - useExtendedCheckers, - ) { - val result = mutableMapOf>>() - - override fun onDiagnostic(diagnostic: FirPsiDiagnostic<*>) { - result.addValueFor(diagnostic.psiElement, diagnostic) - } - - override val visitor = object : FirIdeDiagnosticVisitor( - initialContext ?: PersistentCheckerContextFactory.createEmptyPersistenceCheckerContext(this), - components - ) { - override fun getDeclarationActionOnDeclarationEnter( - declaration: FirDeclaration, - ): DiagnosticCollectorDeclarationAction = - onDeclarationEnter.invoke(declaration) - - override fun onDeclarationExit(declaration: FirDeclaration) { - onDeclarationExit.invoke(declaration) - } - } - } } \ 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/FirIdeDiagnosticVisitor.kt b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/diagnostics/FirIdeDiagnosticVisitor.kt index fba43240e08..f8209871591 100644 --- a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/diagnostics/FirIdeDiagnosticVisitor.kt +++ b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/diagnostics/FirIdeDiagnosticVisitor.kt @@ -13,7 +13,7 @@ import org.jetbrains.kotlin.fir.resolve.SessionHolder import org.jetbrains.kotlin.idea.fir.low.level.api.diagnostics.fir.PersistentCheckerContextFactory import org.jetbrains.kotlin.idea.fir.low.level.api.util.checkCanceled -open class FirIdeDiagnosticVisitor( +internal open class FirIdeDiagnosticVisitor( context: PersistentCheckerContext, components: List ) : CheckerRunningDiagnosticCollectorVisitor(context, components) { 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 new file mode 100644 index 00000000000..a711a7ffb74 --- /dev/null +++ b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/diagnostics/fir/FirIdeStructureElementDiagnosticsCollector.kt @@ -0,0 +1,31 @@ +/* + * 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.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, + useExtendedCheckers: Boolean, +) : AbstractFirIdeDiagnosticsCollector( + session, + useExtendedCheckers, +) { + override val visitor: CheckerRunningDiagnosticCollectorVisitor = createVisitor(components) + + val result = mutableMapOf>>() + + override fun onDiagnostic(diagnostic: FirPsiDiagnostic<*>) { + result.addValueFor(diagnostic.psiElement, diagnostic) + } +} \ 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/file/structure/FileStructureElement.kt b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/file/structure/FileStructureElement.kt index f4a5e6d6dff..c5b74fd1247 100644 --- a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/file/structure/FileStructureElement.kt +++ b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/file/structure/FileStructureElement.kt @@ -6,25 +6,19 @@ package org.jetbrains.kotlin.idea.fir.low.level.api.file.structure import org.jetbrains.kotlin.fir.FirElement -import org.jetbrains.kotlin.fir.analysis.collectors.DiagnosticCollectorDeclarationAction import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.psi import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol -import org.jetbrains.kotlin.idea.fir.low.level.api.diagnostics.* -import org.jetbrains.kotlin.idea.fir.low.level.api.diagnostics.FileStructureElementDiagnosticList -import org.jetbrains.kotlin.idea.fir.low.level.api.diagnostics.FileStructureElementDiagnosticRetriever +import org.jetbrains.kotlin.idea.fir.low.level.api.diagnostics.FileDiagnosticRetriever import org.jetbrains.kotlin.idea.fir.low.level.api.diagnostics.FileStructureElementDiagnostics -import org.jetbrains.kotlin.idea.fir.low.level.api.diagnostics.FileStructureElementDiagnosticsCollector import org.jetbrains.kotlin.idea.fir.low.level.api.diagnostics.SingleNonLocalDeclarationDiagnosticRetriever import org.jetbrains.kotlin.idea.fir.low.level.api.element.builder.FirTowerDataContextCollector import org.jetbrains.kotlin.idea.fir.low.level.api.file.builder.ModuleFileCache import org.jetbrains.kotlin.idea.fir.low.level.api.lazy.resolve.FirLazyDeclarationResolver import org.jetbrains.kotlin.idea.fir.low.level.api.providers.FirIdeProvider import org.jetbrains.kotlin.idea.fir.low.level.api.util.hasFqName -import org.jetbrains.kotlin.idea.fir.low.level.api.util.isGeneratedDeclaration -import org.jetbrains.kotlin.idea.fir.low.level.api.util.ktDeclaration import org.jetbrains.kotlin.psi.* internal sealed class FileStructureElement(val firFile: FirFile) { @@ -179,16 +173,7 @@ internal class RootStructureElement( override val mappings: Map = FirElementsRecorder.recordElementsFrom(firFile, recorder) - override val diagnostics = FileStructureElementDiagnostics(firFile, DiagnosticRetriever) - - private object DiagnosticRetriever : FileStructureElementDiagnosticRetriever() { - override fun retrieve(firFile: FirFile, collector: FileStructureElementDiagnosticsCollector): FileStructureElementDiagnosticList { - return collector.collectForStructureElement(firFile, initialContext = null) { firDeclaration -> - if (firDeclaration is FirFile) DiagnosticCollectorDeclarationAction.CHECK_IN_CURRENT_DECLARATION_AND_DO_NOT_LOOKUP_FOR_NESTED - else DiagnosticCollectorDeclarationAction.SKIP - } - } - } + override val diagnostics = FileStructureElementDiagnostics(firFile, FileDiagnosticRetriever) companion object { private val recorder = object : FirElementsRecorder() {