From 71f9c101a177a42eae4c1a037b3af831f54a8ebc Mon Sep 17 00:00:00 2001 From: Dmitrii Gridin Date: Fri, 16 Feb 2024 18:37:03 +0100 Subject: [PATCH] [LL FIR] KDoc here and there --- .../level/api/fir/api/LLFirResolveSession.kt | 28 ++++++-- .../level/api/fir/api/LowLevelFirApiFacade.kt | 22 ++++-- ...FileStructureElementDiagnosticRetriever.kt | 6 ++ .../FileStructureElementDiagnostics.kt | 5 +- .../fir/element/builder/FirElementBuilder.kt | 56 ++++++++++++--- .../api/fir/file/builder/LLFirLockProvider.kt | 9 ++- .../api/fir/file/structure/FileStructure.kt | 23 ++++++ .../file/structure/FileStructureElement.kt | 8 +++ .../LLFirDeclarationModificationService.kt | 4 +- .../LLFirLazyResolveContractChecker.kt | 8 ++- .../LLFirModuleLazyDeclarationResolver.kt | 9 +++ .../LLFirResolveDesignationCollector.kt | 11 +++ .../LLFirAnnotationArgumentsLazyResolver.kt | 15 ++++ .../fir/transformers/LLFirBodyLazyResolver.kt | 22 ++++++ .../LLFirCompilerAnnotationsLazyResolver.kt | 10 +++ .../LLFirContractsLazyResolver.kt | 14 ++++ .../LLFirExpectActualMatcherLazyResolver.kt | 13 ++++ ...FirGeneratedCompanionObjectLazyResolver.kt | 9 +++ .../LLFirImplicitTypesLazyResolver.kt | 14 ++++ .../LLFirLazyPhaseResolverByPhase.kt | 9 ++- .../transformers/LLFirLazyResolverRunner.kt | 17 +++-- .../LLFirSealedClassInheritorsLazyResolver.kt | 11 +++ .../transformers/LLFirStatusLazyResolver.kt | 28 ++++---- .../LLFirSupertypeLazyResolver.kt | 17 +++++ .../fir/transformers/LLFirTargetResolver.kt | 71 +++++++++++++++++++ .../fir/transformers/LLFirTypeLazyResolver.kt | 12 ++++ 26 files changed, 404 insertions(+), 47 deletions(-) diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/api/LLFirResolveSession.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/api/LLFirResolveSession.kt index d8af27223fd..4406517f066 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/api/LLFirResolveSession.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/api/LLFirResolveSession.kt @@ -1,5 +1,5 @@ /* - * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Copyright 2010-2024 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. */ @@ -9,8 +9,8 @@ import com.intellij.openapi.project.Project import com.intellij.psi.PsiElement import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.LLFirSession import org.jetbrains.kotlin.analysis.low.level.api.fir.state.LLDiagnosticProvider -import org.jetbrains.kotlin.analysis.low.level.api.fir.state.LLModuleResolutionStrategyProvider import org.jetbrains.kotlin.analysis.low.level.api.fir.state.LLModuleProvider +import org.jetbrains.kotlin.analysis.low.level.api.fir.state.LLModuleResolutionStrategyProvider import org.jetbrains.kotlin.analysis.low.level.api.fir.state.LLScopeSessionProvider import org.jetbrains.kotlin.analysis.low.level.api.fir.state.LLSessionProvider import org.jetbrains.kotlin.analysis.project.structure.KtModule @@ -57,11 +57,21 @@ abstract class LLFirResolveSession( } /** - * Build fully resolved FIR node for a requested element. - * This operation could be time-consuming because it creates FileStructureElement - * and resolves non-local declaration into BODY phase. - * Please use [getOrBuildFirFile] to get [FirFile] in undefined phase + * Build [FirElement] node in its final resolved state for a requested element. + * + * Note: that it isn't always [BODY_RESOLVE][FirResolvePhase.BODY_RESOLVE] + * as not all declarations have types/bodies/etc. to resolve. + * + * This operation could be time-consuming because it creates + * [FileStructureElement][org.jetbrains.kotlin.analysis.low.level.api.fir.file.structure.FileStructureElement] + * and may resolve non-local declarations into [BODY_RESOLVE][FirResolvePhase.BODY_RESOLVE] phase. + * + * Please use [getOrBuildFirFile] to get [FirFile] in undefined phase. + * + * @return associated [FirElement] in final resolved state if it exists. + * * @see getOrBuildFirFile + * @see org.jetbrains.kotlin.analysis.low.level.api.fir.element.builder.FirElementBuilder.getOrBuildFirFor */ internal abstract fun getOrBuildFirFor(element: KtElement): FirElement? @@ -70,10 +80,16 @@ abstract class LLFirResolveSession( */ internal abstract fun getOrBuildFirFile(ktFile: KtFile): FirFile + /** + * @see LLDiagnosticProvider.getDiagnostics + */ internal fun getDiagnostics(element: KtElement, filter: DiagnosticCheckerFilter): List { return diagnosticProvider.getDiagnostics(element, filter) } + /** + * @see LLDiagnosticProvider.collectDiagnostics + */ internal fun collectDiagnosticsForFile(ktFile: KtFile, filter: DiagnosticCheckerFilter): Collection { return diagnosticProvider.collectDiagnostics(ktFile, filter) } diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/api/LowLevelFirApiFacade.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/api/LowLevelFirApiFacade.kt index 6a62108b32f..0dbf4f6dd9c 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/api/LowLevelFirApiFacade.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/api/LowLevelFirApiFacade.kt @@ -1,5 +1,5 @@ /* - * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Copyright 2010-2024 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. */ @@ -8,10 +8,8 @@ package org.jetbrains.kotlin.analysis.low.level.api.fir.api import com.intellij.openapi.project.Project import org.jetbrains.kotlin.analysis.low.level.api.fir.LLFirResolveSessionService import org.jetbrains.kotlin.analysis.project.structure.KtModule -import org.jetbrains.kotlin.analysis.project.structure.ProjectStructureProvider import org.jetbrains.kotlin.diagnostics.KtPsiDiagnostic import org.jetbrains.kotlin.fir.FirElement -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.symbols.FirBasedSymbol @@ -89,11 +87,21 @@ fun KtFile.collectDiagnosticsForFile( firResolveSession.collectDiagnosticsForFile(this, filter) /** - * Get a [FirElement] which was created by [KtElement] - * Returned [FirElement] is guaranteed to be resolved to [FirResolvePhase.BODY_RESOLVE] phase - * This operation could be performance affective because it create FIleStructureElement and resolve non-local declaration into BODY phase. + * Build [FirElement] node in its final resolved state for a requested element. * - * The `null` value is returned iff FIR tree does not have corresponding element + * Note: that it isn't always [BODY_RESOLVE][FirResolvePhase.BODY_RESOLVE] + * as not all declarations have types/bodies/etc. to resolve. + * + * This operation could be time-consuming because it creates + * [FileStructureElement][org.jetbrains.kotlin.analysis.low.level.api.fir.file.structure.FileStructureElement] + * and may resolve non-local declarations into [BODY_RESOLVE][FirResolvePhase.BODY_RESOLVE] phase. + * + * Please use [getOrBuildFirFile] to get [FirFile] in undefined phase. + * + * @return associated [FirElement] in final resolved state if it exists. + * + * @see getOrBuildFirFile + * @see LLFirResolveSession.getOrBuildFirFor */ fun KtElement.getOrBuildFir( firResolveSession: LLFirResolveSession, diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostics/FileStructureElementDiagnosticRetriever.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostics/FileStructureElementDiagnosticRetriever.kt index 19c28d159ff..4ac9433e669 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostics/FileStructureElementDiagnosticRetriever.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostics/FileStructureElementDiagnosticRetriever.kt @@ -22,6 +22,12 @@ import org.jetbrains.kotlin.fir.declarations.impl.FirPrimaryConstructor import org.jetbrains.kotlin.fir.resolve.SessionHolderImpl import org.jetbrains.kotlin.util.withSourceCodeAnalysisExceptionUnwrapping +/** + * Collects [FileStructureElementDiagnosticList] for specific [declaration]. + * + * @see FileStructureElementDiagnostics + * @see org.jetbrains.kotlin.analysis.low.level.api.fir.file.structure.FileStructureElement + */ internal sealed class FileStructureElementDiagnosticRetriever( val declaration: FirDeclaration, private val file: FirFile, diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostics/FileStructureElementDiagnostics.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostics/FileStructureElementDiagnostics.kt index 967ded2e81f..9b87b9ea7e9 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostics/FileStructureElementDiagnostics.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostics/FileStructureElementDiagnostics.kt @@ -1,5 +1,5 @@ /* - * Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Copyright 2010-2024 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. */ @@ -10,6 +10,9 @@ import com.intellij.util.SmartList import org.jetbrains.kotlin.analysis.low.level.api.fir.api.DiagnosticCheckerFilter import org.jetbrains.kotlin.diagnostics.KtPsiDiagnostic +/** + * @see FileStructureElementDiagnosticsCollector + */ internal class FileStructureElementDiagnostics(private val retriever: FileStructureElementDiagnosticRetriever) { private val diagnosticByCommonCheckers: FileStructureElementDiagnosticList by lazy { retriever.retrieve(FileStructureElementDiagnosticsCollector.USUAL_COLLECTOR) diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/element/builder/FirElementBuilder.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/element/builder/FirElementBuilder.kt index 411362676a7..bf099ab2b36 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/element/builder/FirElementBuilder.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/element/builder/FirElementBuilder.kt @@ -40,12 +40,18 @@ import org.jetbrains.kotlin.psi.psiUtil.parentsWithSelf import org.jetbrains.kotlin.utils.exceptions.errorWithAttachment import org.jetbrains.kotlin.utils.exceptions.withPsiEntry +/** + * This class is responsible for mapping from [KtElement] to [FirElement] + * using [FileStructure][org.jetbrains.kotlin.analysis.low.level.api.fir.file.structure.FileStructure]. + * + * @see getOrBuildFirFor + * @see org.jetbrains.kotlin.analysis.low.level.api.fir.file.structure.FileStructure + * @see getNonLocalContainingDeclaration + */ @ThreadSafe -internal class FirElementBuilder( - private val moduleComponents: LLFirModuleResolveComponents, -) { +internal class FirElementBuilder(private val moduleComponents: LLFirModuleResolveComponents) { companion object { - fun getPsiAsFirElementSource(element: KtElement): KtElement? { + private fun getPsiAsFirElementSource(element: KtElement): KtElement? { val deparenthesized = if (element is KtExpression) KtPsiUtil.safeDeparenthesize(element) else element return when { deparenthesized is KtPropertyDelegate -> deparenthesized.expression ?: element @@ -67,13 +73,29 @@ internal class FirElementBuilder( else -> deparenthesized } } + + private fun doKtElementHasCorrespondingFirElement(ktElement: KtElement): Boolean = when (ktElement) { + is KtImportList -> false + else -> true + } } - fun doKtElementHasCorrespondingFirElement(ktElement: KtElement): Boolean = when (ktElement) { - is KtImportList -> false - else -> true - } - + /** + * Returns a [FirElement] in its final resolved state. + * + * Note: that it isn't always [BODY_RESOLVE][FirResolvePhase.BODY_RESOLVE] + * as not all declarations have types/bodies/etc. to resolve. + * + * For instance, [KtPackageDirective] has nothing to resolve, + * so it will be returned as is ([FirPackageDirective][org.jetbrains.kotlin.fir.FirPackageDirective]), + * with the [RAW_FIR][FirResolvePhase.RAW_FIR] phase. + * + * @return associated [FirElement] in final resolved state if it exists. + * + * @see getFirForElementInsideAnnotations + * @see getFirForElementInsideTypes + * @see getFirForElementInsideFileHeader + */ fun getOrBuildFirFor(element: KtElement): FirElement? { return if (element is KtFile && element !is KtCodeFragment) { getOrBuildFirForKtFile(element) @@ -306,6 +328,12 @@ private fun KtDeclaration.isPartOf(callableDeclaration: KtCallableDeclaration): internal val KtTypeParameter.containingDeclaration: KtDeclaration? get() = (parent as? KtTypeParameterList)?.parent as? KtDeclaration +/** + * Returns **true** if [this] declaration is a unit of resolution and can be treated as non-local. + * The property is supposed to be used only in the pair with [getNonLocalContainingDeclaration] or [getNonLocalContainingOrThisDeclaration] + * + * @see getNonLocalContainingDeclaration + */ internal val KtDeclaration.isAutonomousDeclaration: Boolean get() = when (this) { is KtPropertyAccessor, is KtParameter, is KtTypeParameter -> false @@ -316,6 +344,14 @@ internal fun PsiElement.getNonLocalContainingOrThisDeclaration(predicate: (KtDec return getNonLocalContainingDeclaration(parentsWithSelf, predicate) } +/** + * Returns the first non-local declaration from [elementsToCheck] that contains the given elements, + * based on the specified predicate. + * + * The resulting declaration can be considered reachable at [RAW_FIR][FirResolvePhase.RAW_FIR] phase. + * + * @see org.jetbrains.kotlin.analysis.low.level.api.fir.file.structure.FileStructure + */ internal fun getNonLocalContainingDeclaration( elementsToCheck: Sequence, predicate: (KtDeclaration) -> Boolean = { true }, @@ -339,7 +375,7 @@ internal fun getNonLocalContainingDeclaration( parent is KtCodeFragment || parent is PsiErrorElement ) { - // Candidate turned out to be local. Let's find another one. + // The candidate turned out to be local. Let's find another one. candidate = null } } diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/file/builder/LLFirLockProvider.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/file/builder/LLFirLockProvider.kt index b1ae6863809..81f15e64f38 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/file/builder/LLFirLockProvider.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/file/builder/LLFirLockProvider.kt @@ -18,7 +18,14 @@ import java.util.concurrent.atomic.AtomicReferenceFieldUpdater import java.util.concurrent.locks.ReentrantLock /** - * Keyed locks provider. + * This class is responsible for the locking strategy in the lazy resolution mode. + * Each [FirElementWithResolveState] have [FirResolveState] which is used by this provider + * to build the lock system. + * + * @see LLFirLazyResolveContractChecker + * @see withWriteLock + * @see withReadLock + * @see withJumpingLock */ internal class LLFirLockProvider(private val checker: LLFirLazyResolveContractChecker) { private val globalLock = ReentrantLock() diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/file/structure/FileStructure.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/file/structure/FileStructure.kt index fd499e5b1e0..daa762d3691 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/file/structure/FileStructure.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/file/structure/FileStructure.kt @@ -31,6 +31,25 @@ import org.jetbrains.kotlin.utils.exceptions.errorWithAttachment import org.jetbrains.kotlin.utils.exceptions.withPsiEntry import java.util.concurrent.ConcurrentHashMap +/** + * Aggregates [KT][KtElement] -> [FIR][org.jetbrains.kotlin.fir.FirElement] mappings and diagnostics for associated [KtFile]. + * + * For every [KtFile] we need mapping for, we have [FileStructure] which contains a tree like-structure of [FileStructureElement]. + * + * When we want to get `KT -> FIR` mapping, + * we [getOrPut][getStructureElementFor] [FileStructureElement] for the closest non-local declaration + * which contains the requested [KtElement]. + * + * Some of [FileStructureElement] can be invalidated in the case on in-block PSI modification. + * See [invalidateElement] and [LLFirDeclarationModificationService] for details. + * + * The mapping is an optimization to avoid searching for the associated [FirElement][org.jetbrains.kotlin.fir.FirElement] + * by [KtElement] as it requires deep traverse through the main element of [FileStructureElement]. + * + * @see org.jetbrains.kotlin.analysis.low.level.api.fir.element.builder.FirElementBuilder + * @see FileStructureElement + * @see LLFirDeclarationModificationService + */ internal class FileStructure private constructor( private val ktFile: KtFile, private val firFile: FirFile, @@ -56,12 +75,16 @@ internal class FileStructure private constructor( * This method is responsible for "invalidation" of re-analyzable declarations. * * @see LLFirDeclarationModificationService + * @see getNonLocalReanalyzableContainingDeclaration */ fun invalidateElement(element: KtElement) { val container = getContainerKtElement(element) structureElements.remove(container) } + /** + * @return [FileStructureElement] for the closest non-local declaration which contains this [element]. + */ fun getStructureElementFor(element: KtElement): FileStructureElement { val container = getContainerKtElement(element) return structureElements.getOrPut(container) { createStructureElement(container) } diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/file/structure/FileStructureElement.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/file/structure/FileStructureElement.kt index 5654ac175b6..10780c0c0d2 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/file/structure/FileStructureElement.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/file/structure/FileStructureElement.kt @@ -24,6 +24,14 @@ import org.jetbrains.kotlin.fir.visitors.FirVisitor import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.utils.exceptions.requireWithAttachment +/** + * Collects [KT -> FIR][KtToFirMapping] mapping and [diagnostics][FileStructureElementDiagnostics] for [declaration]. + * + * @param declaration is a fully resolved declaration + * + * @see FileStructure + * @see org.jetbrains.kotlin.analysis.low.level.api.fir.diagnostics.FileStructureElementDiagnosticsCollector + */ internal sealed class FileStructureElement( val declaration: FirDeclaration, val diagnostics: FileStructureElementDiagnostics, diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/file/structure/LLFirDeclarationModificationService.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/file/structure/LLFirDeclarationModificationService.kt index 8fc163d6186..9319495e061 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/file/structure/LLFirDeclarationModificationService.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/file/structure/LLFirDeclarationModificationService.kt @@ -54,6 +54,7 @@ import org.jetbrains.kotlin.psi.psiUtil.isContractDescriptionCallPsiCheck * * In case of non-local changes (out-of-block modification), this service will publish event to [MODULE_OUT_OF_BLOCK_MODIFICATION]. * + * @see getNonLocalReanalyzableContainingDeclaration * @see MODULE_OUT_OF_BLOCK_MODIFICATION * @see org.jetbrains.kotlin.analysis.providers.topics.KotlinModuleOutOfBlockModificationListener */ @@ -113,7 +114,8 @@ class LLFirDeclarationModificationService(val project: Project) : Disposable { } /** - * Force the service to publish delayed modifications. This action is required to fix inconsistencies in FirFile tree. + * Force the service to publish delayed modifications. + * This action is required to fix inconsistencies in [FirFile][org.jetbrains.kotlin.fir.declarations.FirFile] tree. */ fun flushModifications() { ApplicationManager.getApplication().assertIsWriteThread() diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/lazy/resolve/LLFirLazyResolveContractChecker.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/lazy/resolve/LLFirLazyResolveContractChecker.kt index 90b4140d082..e6ccd571c7d 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/lazy/resolve/LLFirLazyResolveContractChecker.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/lazy/resolve/LLFirLazyResolveContractChecker.kt @@ -1,5 +1,5 @@ /* - * Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Copyright 2010-2024 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. */ @@ -9,6 +9,12 @@ import com.intellij.openapi.diagnostic.Logger import org.jetbrains.kotlin.fir.declarations.FirResolvePhase import org.jetbrains.kotlin.fir.symbols.FirLazyResolveContractViolationException +/** + * Checks a lazy resolve call's compliance with [FirResolvePhase] contracts. + * + * @see FirResolvePhase + * @see FirLazyResolveContractViolationException + */ internal class LLFirLazyResolveContractChecker { private val currentTransformerPhase = ThreadLocal.withInitial { null } diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/lazy/resolve/LLFirModuleLazyDeclarationResolver.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/lazy/resolve/LLFirModuleLazyDeclarationResolver.kt index dbb3e76809e..46a965e30d3 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/lazy/resolve/LLFirModuleLazyDeclarationResolver.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/lazy/resolve/LLFirModuleLazyDeclarationResolver.kt @@ -19,6 +19,15 @@ import org.jetbrains.kotlin.fir.utils.exceptions.withFirEntry import org.jetbrains.kotlin.fir.visitors.transformSingle import org.jetbrains.kotlin.utils.exceptions.rethrowExceptionWithDetails +/** + * This is the entry point for lazy resolution. + * + * The class is responsible to [collect][LLFirResolveDesignationCollector] required [LLFirResolveTarget] + * and resolve it for the requested phase. + * + * @see org.jetbrains.kotlin.fir.symbols.lazyResolveToPhase + * @see LLFirLazyResolverRunner + */ internal class LLFirModuleLazyDeclarationResolver(val moduleComponents: LLFirModuleResolveComponents) { /** * Lazily resolves the [target] to a given [toPhase]. diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/lazy/resolve/LLFirResolveDesignationCollector.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/lazy/resolve/LLFirResolveDesignationCollector.kt index 0a574f5dbb3..1585da54fba 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/lazy/resolve/LLFirResolveDesignationCollector.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/lazy/resolve/LLFirResolveDesignationCollector.kt @@ -19,6 +19,14 @@ import org.jetbrains.kotlin.fir.declarations.synthetic.FirSyntheticProperty import org.jetbrains.kotlin.fir.declarations.synthetic.FirSyntheticPropertyAccessor import org.jetbrains.kotlin.fir.isCopyCreatedInScope +/** + * Collects [LLFirResolveTarget] for requested [FirElementWithResolveState]. + * + * Effectively, this class is responsible for which elements can be lazily resolved and which cannot. + * + * @see LLFirResolveTarget + * @see shouldBeResolved + */ internal object LLFirResolveDesignationCollector { fun getDesignationToResolve(target: FirElementWithResolveState): LLFirResolveTarget? { return getDesignationToResolve(target, FirDesignation::asResolveTarget) @@ -54,6 +62,9 @@ internal object LLFirResolveDesignationCollector { } } + /** + * @see isLazyResolvable + */ private fun FirElementWithResolveState.shouldBeResolved() = when (this) { is FirDeclaration -> shouldBeResolved() is FirFileAnnotationsContainer -> annotations.isNotEmpty() diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirAnnotationArgumentsLazyResolver.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirAnnotationArgumentsLazyResolver.kt index bb803810641..35944c37494 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirAnnotationArgumentsLazyResolver.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirAnnotationArgumentsLazyResolver.kt @@ -67,6 +67,21 @@ internal object LLFirAnnotationArgumentsLazyResolver : LLFirLazyResolver(FirReso } } +/** + * This resolver is responsible for [ANNOTATION_ARGUMENTS][FirResolvePhase.ANNOTATION_ARGUMENTS] phase. + * + * This resolver: + * - Transforms unresolved annotation arguments into resolved ones. + * It includes both regular and type annotations. + * + * Before the transformation, the resolver [recreates][AnnotationArgumentsStateKeepers] all unresolved argument lists + * to prevent corrupted states due to [PCE][com.intellij.openapi.progress.ProcessCanceledException]. + * + * @see postponedSymbolsForAnnotationResolution + * @see AnnotationArgumentsStateKeepers + * @see FirAnnotationArgumentsTransformer + * @see FirResolvePhase.ANNOTATION_ARGUMENTS + */ private class LLFirAnnotationArgumentsTargetResolver(resolveTarget: LLFirResolveTarget) : LLFirAbstractBodyTargetResolver( resolveTarget, FirResolvePhase.ANNOTATION_ARGUMENTS, diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirBodyLazyResolver.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirBodyLazyResolver.kt index 8c492ca6846..5a684ba64b8 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirBodyLazyResolver.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirBodyLazyResolver.kt @@ -65,6 +65,28 @@ internal object LLFirBodyLazyResolver : LLFirLazyResolver(FirResolvePhase.BODY_R } } +/** + * This resolver is responsible for [BODY_RESOLVE][FirResolvePhase.BODY_RESOLVE] phase. + * + * This resolver: + * - Transforms bodies of declarations. + * - Builds [control flow graph][org.jetbrains.kotlin.fir.resolve.dfa.cfg.ControlFlowGraph]. + * + * Before the transformation, the resolver [recreates][BodyStateKeepers] all bodies + * to prevent corrupted states due to [PCE][com.intellij.openapi.progress.ProcessCanceledException]. + * + * Special rules: + * - [FirFile] – All members which [isUsedInControlFlowGraphBuilderForFile] have + * to be resolved before the file to build correct [CFG][org.jetbrains.kotlin.fir.resolve.dfa.cfg.ControlFlowGraph]. + * - [FirScript] – All members which [isUsedInControlFlowGraphBuilderForScript] have + * to be resolved before the script to build correct [CFG][org.jetbrains.kotlin.fir.resolve.dfa.cfg.ControlFlowGraph]. + * - [FirRegularClass] – All members which [isUsedInControlFlowGraphBuilderForClass] have + * to be resolved before the class to build correct [CFG][org.jetbrains.kotlin.fir.resolve.dfa.cfg.ControlFlowGraph]. + * + * @see BodyStateKeepers + * @see FirBodyResolveTransformer + * @see FirResolvePhase.BODY_RESOLVE + */ private class LLFirBodyTargetResolver(target: LLFirResolveTarget) : LLFirAbstractBodyTargetResolver( target, FirResolvePhase.BODY_RESOLVE, diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirCompilerAnnotationsLazyResolver.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirCompilerAnnotationsLazyResolver.kt index dc7eb07035b..57e13af6da8 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirCompilerAnnotationsLazyResolver.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirCompilerAnnotationsLazyResolver.kt @@ -43,6 +43,16 @@ internal object LLFirCompilerAnnotationsLazyResolver : LLFirLazyResolver(FirReso } } +/** + * This resolver is responsible for [COMPILER_REQUIRED_ANNOTATIONS][FirResolvePhase.COMPILER_REQUIRED_ANNOTATIONS] phase. + * + * This resolver: + * - Transforms compiler required annotations of declarations. + * - Calculates [DeprecationsProvider]. + * + * @see FirCompilerRequiredAnnotationsResolveTransformer + * @see FirResolvePhase.COMPILER_REQUIRED_ANNOTATIONS + */ private class LLFirCompilerRequiredAnnotationsTargetResolver( target: LLFirResolveTarget, computationSession: LLFirCompilerRequiredAnnotationsComputationSession? = null, diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirContractsLazyResolver.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirContractsLazyResolver.kt index 007d3b39972..1e251970d17 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirContractsLazyResolver.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirContractsLazyResolver.kt @@ -29,6 +29,20 @@ internal object LLFirContractsLazyResolver : LLFirLazyResolver(FirResolvePhase.C } } +/** + * This resolver is responsible for [CONTRACTS][FirResolvePhase.CONTRACTS] phase. + * + * This resolver: + * - Transforms a [contract][org.jetbrains.kotlin.fir.contracts.FirContractDescription] + * definition in [contract owners][FirContractDescriptionOwner]. + * + * Before the transformation, the resolver [recreates][ContractStateKeepers] bodies + * to prevent corrupted states due to [PCE][com.intellij.openapi.progress.ProcessCanceledException]. + * + * @see ContractStateKeepers + * @see FirContractResolveTransformer + * @see FirResolvePhase.CONTRACTS + */ private class LLFirContractsTargetResolver(target: LLFirResolveTarget) : LLFirAbstractBodyTargetResolver( target, FirResolvePhase.CONTRACTS, diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirExpectActualMatcherLazyResolver.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirExpectActualMatcherLazyResolver.kt index 324115a4737..4757a1fe9c8 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirExpectActualMatcherLazyResolver.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirExpectActualMatcherLazyResolver.kt @@ -29,6 +29,19 @@ internal object LLFirExpectActualMatcherLazyResolver : LLFirLazyResolver(FirReso } } +/** + * This resolver is responsible for [EXPECT_ACTUAL_MATCHING][FirResolvePhase.EXPECT_ACTUAL_MATCHING] phase. + * + * This resolver: + * - Searches and set [expectForActual][org.jetbrains.kotlin.fir.declarations.expectForActual] + * property for declarations. + * + * Special rules: + * - First resolves outer classes to this phase in multiplatform projects. + * + * @see FirExpectActualMatcherTransformer + * @see FirResolvePhase.EXPECT_ACTUAL_MATCHING + */ private class LLFirExpectActualMatchingTargetResolver(target: LLFirResolveTarget) : LLFirTargetResolver( target, FirResolvePhase.EXPECT_ACTUAL_MATCHING diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirGeneratedCompanionObjectLazyResolver.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirGeneratedCompanionObjectLazyResolver.kt index bc59a12f123..6fb16bc00c1 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirGeneratedCompanionObjectLazyResolver.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirGeneratedCompanionObjectLazyResolver.kt @@ -17,6 +17,15 @@ internal object LLFirGeneratedCompanionObjectLazyResolver : LLFirLazyResolver(Fi override fun phaseSpecificCheckIsResolved(target: FirElementWithResolveState) {} } +/** + * This resolver is responsible for [COMPANION_GENERATION][FirResolvePhase.COMPANION_GENERATION] phase. + * + * This resolver: + * - Generates companion objects which were provided by compiler plugins. + * + * @see FirCompanionGenerationTransformer + * @see FirResolvePhase.COMPANION_GENERATION + */ private class LLFirCompanionGenerationTargetResolver(target: LLFirResolveTarget) : LLFirTargetResolver( target, FirResolvePhase.COMPANION_GENERATION, diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirImplicitTypesLazyResolver.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirImplicitTypesLazyResolver.kt index f0d5f07ef7b..ec689ce2ff1 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirImplicitTypesLazyResolver.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirImplicitTypesLazyResolver.kt @@ -117,6 +117,20 @@ internal class LLImplicitBodyResolveComputationSession : ImplicitBodyResolveComp fun popCycledSymbolIfExists(): FirCallableSymbol<*>? = cycledSymbol?.also { cycledSymbol = null } } +/** + * This resolver is responsible for [IMPLICIT_TYPES_BODY_RESOLVE][FirResolvePhase.IMPLICIT_TYPES_BODY_RESOLVE] phase. + * + * This resolver: + * - Transforms [FirImplicitTypeRef] into [FirResolvedTypeRef][org.jetbrains.kotlin.fir.types.FirResolvedTypeRef]. + * + * Before the transformation, the resolver [recreates][BodyStateKeepers] all bodies + * to prevent corrupted states due to [PCE][com.intellij.openapi.progress.ProcessCanceledException]. + * + * @see postponedSymbolsForAnnotationResolution + * @see BodyStateKeepers + * @see FirImplicitAwareBodyResolveTransformer + * @see FirResolvePhase.IMPLICIT_TYPES_BODY_RESOLVE + */ internal class LLFirImplicitBodyTargetResolver( target: LLFirResolveTarget, llImplicitBodyResolveComputationSessionParameter: LLImplicitBodyResolveComputationSession? = null, diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirLazyPhaseResolverByPhase.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirLazyPhaseResolverByPhase.kt index 7e7207ace83..d2c2ca39109 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirLazyPhaseResolverByPhase.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirLazyPhaseResolverByPhase.kt @@ -8,19 +8,22 @@ package org.jetbrains.kotlin.analysis.low.level.api.fir.transformers import org.jetbrains.kotlin.fir.declarations.FirResolvePhase import java.util.* +/** + * Maps [FirResolvePhase] to the associated [LLFirTargetResolver]. + */ internal object LLFirLazyPhaseResolverByPhase { private val byPhase = EnumMap(FirResolvePhase::class.java).apply { + this[FirResolvePhase.COMPILER_REQUIRED_ANNOTATIONS] = LLFirCompilerAnnotationsLazyResolver this[FirResolvePhase.COMPANION_GENERATION] = LLFirGeneratedCompanionObjectLazyResolver this[FirResolvePhase.SUPER_TYPES] = LLFirSupertypeLazyResolver + this[FirResolvePhase.SEALED_CLASS_INHERITORS] = LLFirSealedClassInheritorsLazyResolver this[FirResolvePhase.TYPES] = LLFirTypeLazyResolver this[FirResolvePhase.STATUS] = LLFirStatusLazyResolver - this[FirResolvePhase.COMPILER_REQUIRED_ANNOTATIONS] = LLFirCompilerAnnotationsLazyResolver + this[FirResolvePhase.EXPECT_ACTUAL_MATCHING] = LLFirExpectActualMatcherLazyResolver this[FirResolvePhase.CONTRACTS] = LLFirContractsLazyResolver this[FirResolvePhase.IMPLICIT_TYPES_BODY_RESOLVE] = LLFirImplicitTypesLazyResolver this[FirResolvePhase.ANNOTATION_ARGUMENTS] = LLFirAnnotationArgumentsLazyResolver this[FirResolvePhase.BODY_RESOLVE] = LLFirBodyLazyResolver - this[FirResolvePhase.EXPECT_ACTUAL_MATCHING] = LLFirExpectActualMatcherLazyResolver - this[FirResolvePhase.SEALED_CLASS_INHERITORS] = LLFirSealedClassInheritorsLazyResolver } fun getByPhase(phase: FirResolvePhase): LLFirLazyResolver = byPhase.getValue(phase) diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirLazyResolverRunner.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirLazyResolverRunner.kt index 588cb292bea..1d5b6a718ab 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirLazyResolverRunner.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirLazyResolverRunner.kt @@ -10,11 +10,20 @@ import org.jetbrains.kotlin.analysis.low.level.api.fir.api.targets.LLFirResolveT import org.jetbrains.kotlin.analysis.low.level.api.fir.api.targets.session import org.jetbrains.kotlin.fir.declarations.FirResolvePhase +/** + * Runs required [LLFirLazyResolver] on [LLFirResolveTarget] based on [FirResolvePhase]. + * + * @see runLazyResolverByPhase + * @see LLFirLazyResolver + * @see org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.LLFirLockProvider + */ internal object LLFirLazyResolverRunner { - fun runLazyResolverByPhase( - phase: FirResolvePhase, - target: LLFirResolveTarget, - ) { + /** + * Runs [resolver][LLFirLazyResolver] associated with [phase] for [target] and checks if it finished correctly. + * + * @see LLFirLazyPhaseResolverByPhase + */ + fun runLazyResolverByPhase(phase: FirResolvePhase, target: LLFirResolveTarget) { val lazyResolver = LLFirLazyPhaseResolverByPhase.getByPhase(phase) val lockProvider = LLFirGlobalResolveComponents.getInstance(target.session).lockProvider lockProvider.withGlobalLock { diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirSealedClassInheritorsLazyResolver.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirSealedClassInheritorsLazyResolver.kt index 1180f74a0c8..168ffe765f1 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirSealedClassInheritorsLazyResolver.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirSealedClassInheritorsLazyResolver.kt @@ -18,6 +18,17 @@ internal object LLFirSealedClassInheritorsLazyResolver : LLFirLazyResolver(FirRe } +/** + * This resolver is responsible for [SEALED_CLASS_INHERITORS][FirResolvePhase.SEALED_CLASS_INHERITORS] phase. + * + * LL FIR use [LLSealedInheritorsProviderByAnalysisApiProvider][org.jetbrains.kotlin.analysis.low.level.api.fir.api.services.LLSealedInheritorsProviderByAnalysisApiProvider] + * instead of the compiler [SealedClassInheritorsProviderImpl][org.jetbrains.kotlin.fir.declarations.SealedClassInheritorsProviderImpl], + * so it does nothing during this phase as sealed class hierarchy will be provided later on demand. + * + * @see org.jetbrains.kotlin.analysis.low.level.api.fir.api.services.LLSealedInheritorsProviderFactory + * @see org.jetbrains.kotlin.fir.declarations.SealedClassInheritorsProvider + * @see FirResolvePhase.SEALED_CLASS_INHERITORS + */ private class LLFirSealedClassInheritorsDesignatedResolver(target: LLFirResolveTarget) : LLFirTargetResolver( target, FirResolvePhase.SEALED_CLASS_INHERITORS, diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirStatusLazyResolver.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirStatusLazyResolver.kt index eb7059919e2..fb6a01a39f3 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirStatusLazyResolver.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirStatusLazyResolver.kt @@ -25,7 +25,6 @@ import org.jetbrains.kotlin.fir.types.FirTypeRef import org.jetbrains.kotlin.fir.types.coneType import org.jetbrains.kotlin.fir.types.toSymbol import org.jetbrains.kotlin.fir.visitors.transformSingle -import org.jetbrains.kotlin.name.Name internal object LLFirStatusLazyResolver : LLFirLazyResolver(FirResolvePhase.STATUS) { override fun createTargetResolver(target: LLFirResolveTarget): LLFirTargetResolver = LLFirStatusTargetResolver( @@ -49,18 +48,6 @@ private sealed class StatusResolveMode(val resolveSupertypes: Boolean) { object AllCallables : StatusResolveMode(resolveSupertypes = true) { override fun shouldBeResolved(callableDeclaration: FirCallableDeclaration): Boolean = true } - - class FunctionWithSpecificName(val name: Name) : StatusResolveMode(resolveSupertypes = true) { - override fun shouldBeResolved(callableDeclaration: FirCallableDeclaration): Boolean { - return callableDeclaration is FirSimpleFunction && callableDeclaration.name == name - } - } - - class PropertyWithSpecificName(val name: Name) : StatusResolveMode(resolveSupertypes = true) { - override fun shouldBeResolved(callableDeclaration: FirCallableDeclaration): Boolean { - return callableDeclaration is FirProperty && callableDeclaration.name == name - } - } } private fun LLFirResolveTarget.resolveMode(): StatusResolveMode = when (this) { @@ -91,6 +78,21 @@ private class LLStatusComputationSession(val useSiteSession: FirSession) : Statu val canHaveActualization: Boolean get() = shouldCheckForActualization } +/** + * This resolver is responsible for [STATUS][FirResolvePhase.STATUS] phase. + * + * This resolver: + * - Transforms modality, visibility, and modifiers for [member declarations][FirMemberDeclaration]. + * + * Special rules: + * - First resolves outer classes to this phase. + * - First resolves all members of super types for non-[FirClassLikeDeclaration] declarations. + * - [Searches][org.jetbrains.kotlin.analysis.low.level.api.fir.transformers.LLFirStatusTargetResolver.Transformer.superTypeToSymbols] + * super types not only in the declaration site session, but also in the call site session to resolve `expect` declaration first. + * + * @see FirStatusResolveTransformer + * @see FirResolvePhase.STATUS + */ private class LLFirStatusTargetResolver( target: LLFirResolveTarget, private val statusComputationSession: LLStatusComputationSession = LLStatusComputationSession(target.session), diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirSupertypeLazyResolver.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirSupertypeLazyResolver.kt index c8d7c6ecbb3..a14822363bc 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirSupertypeLazyResolver.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirSupertypeLazyResolver.kt @@ -48,6 +48,23 @@ internal object LLFirSupertypeLazyResolver : LLFirLazyResolver(FirResolvePhase.S } } +/** + * This resolver is responsible for [SUPER_TYPES][FirResolvePhase.SUPER_TYPES] phase. + * + * This resolver: + * - Transforms all supertypes of classes. + * - Performs type aliases expansion. + * - Breaks loops in the type hierarchy if needed. + * + * Special rules: + * - First resolves outer classes to this phase. + * - Resolves all super types recursively. + * - [Searches][org.jetbrains.kotlin.analysis.low.level.api.fir.transformers.LLFirSuperTypeTargetResolver.crawlSupertype] + * super types not only in the declaration site session, but also in the call site session to resolve `expect` declaration first. + * + * @see FirSupertypeResolverVisitor + * @see FirResolvePhase.SUPER_TYPES + */ private class LLFirSuperTypeTargetResolver( target: LLFirResolveTarget, private val supertypeComputationSession: LLFirSupertypeComputationSession = LLFirSupertypeComputationSession(target.session), diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirTargetResolver.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirTargetResolver.kt index 3dff39d9e66..a66bfedca4e 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirTargetResolver.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirTargetResolver.kt @@ -38,6 +38,40 @@ import org.jetbrains.kotlin.utils.exceptions.checkWithAttachment import org.jetbrains.kotlin.utils.exceptions.errorWithAttachment import org.jetbrains.kotlin.utils.exceptions.requireWithAttachment +/** + * This class represents the resolver for each [FirResolvePhase]. + * + * Usually such the resolver extends the corresponding compiler phase transformer or delegates to it. + * + * The main difference with original compiler transformers is that we can transform declarations + * only under the lock of the declaration (see [LLFirLockProvider] for locks implementation). + * E.g., to avoid [contract violations][org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve.LLFirLazyResolveContractChecker] + * we cannot transform class member declaration under the class lock – we have to take the corresponding declaration lock + * to avoid concurrent issues. + * + * So, at least we have a different implementation for transformations of such declarations as [FirFile], [FirScript] and [FirRegularClass]. + * + * Due to lazy resolution, we have to maintain the resolution order explicitly in some cases as we are not guaranteed by default that all + * dependencies or outer declarations are resolved before the target one. + * We have [resolveDependencies] method which describes common dependencies between declarations. + * Also, each [LLFirResolveTarget] can define phase-specific rules. + * + * Implementations: + * - [COMPILER_REQUIRED_ANNOTATIONS][FirResolvePhase.COMPILER_REQUIRED_ANNOTATIONS] – [LLFirCompilerRequiredAnnotationsTargetResolver] + * - [COMPANION_GENERATION][FirResolvePhase.COMPANION_GENERATION] – [LLFirCompanionGenerationTargetResolver] + * - [SUPER_TYPES][FirResolvePhase.SUPER_TYPES] – [LLFirSuperTypeTargetResolver] + * - [SEALED_CLASS_INHERITORS][FirResolvePhase.SEALED_CLASS_INHERITORS] – [LLFirSealedClassInheritorsLazyResolver] + * - [TYPES][FirResolvePhase.TYPES] – [LLFirTypeTargetResolver] + * - [STATUS][FirResolvePhase.STATUS] – [LLFirStatusTargetResolver] + * - [EXPECT_ACTUAL_MATCHING][FirResolvePhase.EXPECT_ACTUAL_MATCHING] – [LLFirExpectActualMatchingTargetResolver] + * - [CONTRACTS][FirResolvePhase.CONTRACTS] – [LLFirContractsTargetResolver] + * - [IMPLICIT_TYPES_BODY_RESOLVE][FirResolvePhase.IMPLICIT_TYPES_BODY_RESOLVE] – [LLFirImplicitBodyTargetResolver] + * - [ANNOTATION_ARGUMENTS][FirResolvePhase.ANNOTATION_ARGUMENTS] – [LLFirAnnotationArgumentsTargetResolver] + * - [BODY_RESOLVE][FirResolvePhase.BODY_RESOLVE] – [LLFirBodyTargetResolver] + * + * @see LLFirLockProvider + * @see FirResolvePhase + */ internal abstract class LLFirTargetResolver( protected val resolveTarget: LLFirResolveTarget, val resolverPhase: FirResolvePhase, @@ -83,6 +117,12 @@ internal abstract class LLFirTargetResolver( } /** + * Dependency target resolution can be skipped to optimize the resolution if this phase does not require any dependencies. + * + * For instance, [LLFirBodyTargetResolver] skips it as no one should depend on body resolution of another declaration. + * + * @return **true** if [resolveDependencies] step should be skipped + * * @see resolveDependencies */ open val skipDependencyTargetResolutionStep: Boolean get() = false @@ -91,6 +131,7 @@ internal abstract class LLFirTargetResolver( * Requests the resolution for dependencies to avoid race in the case of FIR instance sharing. * Will be executed before resolution without a lock. * + * @see resolveDataClassMemberDependencies * @see skipDependencyTargetResolutionStep */ private fun resolveDependencies(target: FirElementWithResolveState) { @@ -190,10 +231,32 @@ internal abstract class LLFirTargetResolver( protected open fun checkResolveConsistency() {} + /** + * This method executes **not under the lock** of [target]. + * Any unsafe reads from [target] declaration have to be done under [withReadLock]. + * [performCustomResolveUnderLock] have to be used for modifications. + * + * This method can be useful to resolve some dependencies (like [resolveDependencies] in general), + * but with some phase-specific rules. + * + * For instance, to pre-resolve [FirRegularClass] members before the class itself as it is required + * to build the [CFG][org.jetbrains.kotlin.fir.resolve.dfa.cfg.ControlFlowGraph]. + * + * @return **true** if [performCustomResolveUnderLock] has been called + * + * @see withReadLock + * @see performCustomResolveUnderLock + */ protected open fun doResolveWithoutLock(target: FirElementWithResolveState): Boolean = false + /** + * This method executes **under the lock** of [target]. + */ protected abstract fun doLazyResolveUnderLock(target: FirElementWithResolveState) + /** + * Executes the resolution. + */ fun resolveDesignation() { checkResolveConsistency() resolveTarget.visit(this) @@ -203,6 +266,14 @@ internal abstract class LLFirTargetResolver( performResolve(element) } + /** + * Performs the resolution of [target]. + * The [target] element have to be at least in [resolverPhase].[previous][FirResolvePhase.previous] phase. + * + * @see resolveDependencies + * @see doResolveWithoutLock + * @see doLazyResolveUnderLock + */ protected fun performResolve(target: FirElementWithResolveState) { resolveDependencies(target) diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirTypeLazyResolver.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirTypeLazyResolver.kt index d94d106327f..c138965d574 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirTypeLazyResolver.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirTypeLazyResolver.kt @@ -56,6 +56,18 @@ internal object LLFirTypeLazyResolver : LLFirLazyResolver(FirResolvePhase.TYPES) } } +/** + * This resolver is responsible for [TYPES][FirResolvePhase.TYPES] phase. + * + * This resolver: + * - Transform explicitly written types in declaration headers. + * + * Special rules: + * - First resolves outer classes to this phase. + * + * @see FirTypeResolveTransformer + * @see FirResolvePhase.TYPES + */ private class LLFirTypeTargetResolver(target: LLFirResolveTarget) : LLFirTargetResolver(target, FirResolvePhase.TYPES) { private val transformer = object : FirTypeResolveTransformer(resolveTargetSession, resolveTargetScopeSession) { override fun transformTypeRef(typeRef: FirTypeRef, data: Any?): FirResolvedTypeRef {