[LL FIR] update low-level-api-fir.md doc

This commit is contained in:
Dmitrii Gridin
2024-02-16 18:36:44 +01:00
committed by Space Team
parent 71f9c101a1
commit 3ce3c50b92
@@ -1,71 +1,66 @@
# Low Level API # Low-Level API FIR
Low-level API (LL API for short) is an interlayer between Analysis API FIR Implementation and FIR compiler. Low-level API is responsible for: Low-level API FIR (LL API or LL FIR for short) is an interlayer between Analysis API FIR Implementation and FIR compiler.
Low-level API FIR is responsible but not limited for:
* Finding corresponding `FirElement` by `KtElement` - Finding corresponding [FirElement](../../../compiler/fir/tree/gen/org/jetbrains/kotlin/fir/FirElement.kt) by `KtElement`
* Lazy resolving of `FirDeclaration` - Lazy resolution of declarations ([FirElementWithResolveState](../../../compiler/fir/tree/gen/org/jetbrains/kotlin/fir/FirElementWithResolveState.kt))
* Collecting diagnostics for `FirDeclaration` - Collecting diagnostics for [FirDeclaration](../../../compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/FirDeclaration.kt)
* Incremental code analysis - Incremental code analysis
* Implementing FIR providers using IntelliJ indexes - Implementing FIR providers using the Analysis API implementor's declaration/package/etc. providers (e.g., IntelliJ indexes in the IDE)
You can read about how FIR compiler works [here](../../fir/fir-basics.md). You can read about how FIR compiler works [here](../../fir/fir-basics.md).
The entry point for LL API is `FirModuleResolveState`.` FirModuleResolveState` is a view of project modules visible from the current module. The entry point for LL API is [LLFirResolveSession](../../../analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/api/LLFirResolveSession.kt).
The lifetime of `LLFirResolveSession` represents a project view from a use-site [KtModule](../../../analysis/project-structure/src/org/jetbrains/kotlin/analysis/project/structure/KtModule.kt).
`FirModuleResolveState` is limited by Kotlin Out of Block Modification. The lifetime of `LLFirResolveSession` is limited by modification events.
## Mapping KtElement to FirElement (KT -> FIR) & Incremental Analysis [LowLevelFirApiFacade](../../../analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/api/LowLevelFirApiFacade.kt)
file contains a useful API surface to interact with Low Level API FIR from Analysis API FIR.
To implement some stuff in Analysis API, we need to get resolved `FirElement` by the given `KtElement`. Also, this functionality is ## Documentation
considered to be used not very often (mostly, for the files opened in the editor) as it resolves declarations to the `BODY_RESOLVE` and
collects `KT -> FIR` mappings for it.
Finding `KT -> FIR` mappings works like the following: There are a bunch of different areas.
Docs for each area are sorted by context depth from the basic overview to the deepest implementation details.
* For every `KtFile` we need mapping for, we have `FileStructure` which contains a tree like-structure of `FileStructureElement` - Mapping from `KtElement` to `FirElement` (*KT -> FIR*) & Incremental Analysis & Collecting diagnostics
* `FileStructureElement` can be one of the following: 1. [FirElementBuilder](../../../analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/element/builder/FirElementBuilder.kt)
* `ReanalyzableStructureElement` represents a non-local declaration that can be incrementally reanalyzed after non-out of block change is responsible for mapping from `KtElement` to `FirElement`.
inside it. 2. [FileStructure](../../../analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/file/structure/FileStructure.kt)
* `NonReanalyzableDeclarationStructureElement` represents non-local declaration which can not be incrementally reanalyzed is a tree like-structure of `FileStructureElement` which is associated with some `KtFile`.
* `RootFileStructureElement` represents file except all declarations inside Aggregates information about *KT -> FIR* mapping and diagnostics for associated file.
* `FileStructureElement` form a nested tree-like structure 3. [FileStructureElement](../../../analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/file/structure/FileStructureElement.kt)
* Then we want to get `KT -> FIR` mapping we find containing `FileStructureElement`. If is not up-to-date we rebuild it and then take from is a representation of specific `KtElement`.
it. Is responsible for *KT -> FIR* mapping and diagnostics for the specific `KtElement`.
4. [FileStructureElementDiagnosticRetriever](../../../analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostics/FileStructureElementDiagnosticRetriever.kt)
The following declarations can be reanalyzed (in other words, can be represented as ReanalyzableStructureElement): is responsible to collect diagnostics for `FileStructureElement`.
5. [LLFirDeclarationModificationService](../../../analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/file/structure/LLFirDeclarationModificationService.kt)
* Functions with explicit return type is a service which is responsible for `FileStructure` invalidation in the case of associated PSI modification.
* Properties with explicit type - Lazy resolution
* Secondary constructors 1. [FirResolvePhase](../../../compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/FirResolvePhase.kt)
* Getters/setters of the property with explicit type to understand what the compiler phases are and what is the basic difference between the CLI and the Analysis API modes.
2. [LLFirModuleLazyDeclarationResolver](../../../analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/lazy/resolve/LLFirModuleLazyDeclarationResolver.kt)
# Lazy Declaration resolving is the entry point for lazy resolution.
Receives some `FirElementWithResolveState` element and a desired phase and resolve this element to this phase.
FIR in compiler mode works by sequentially running every resolve phase on all files at once like shown in pseudo-code: 3. [LLFirResolveDesignationCollector](../../../analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/lazy/resolve/LLFirResolveDesignationCollector.kt)
is a designation collector.
```kotlin Collects `LLFirResolveTarget` for the specific `FirElementWithResolveState`.
for (phase in allResolvePhases) { Decides which element can be resolved lazily and which cannot.
for (file in allFirFiles) { 4. [LLFirResolveTarget](../../../analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/api/targets/LLFirResolveTarget.kt)
runPhaseOnFile(file, phase) is an instruction on how to resolve specific `FirElementWithResolveState`.
} 5. [LLFirLazyResolverRunner](../../../analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirLazyResolverRunner.kt)
} is responsible
``` for running [LLFirLazyResolver](../../../analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirLazyResolver.kt)
for the specific phase and making sure that it worked correctly.
Such behavior does not work for the Analysis API. Analysis API needs to resolve one specific declaration to the minimum possible phase. To 6. [LLFirTargetResolver](../../../analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirTargetResolver.kt)
solve that problem, there are *lazy phases*. Lazy phases can be run only on a single declaration, not on the whole `FirFile`. is the core part of lazy resolution.
We have a separate implementation of `LLFirTargetResolver` for each compiler phase,
Suppose we need to resolve some `FirDeclaration` to phase number `N`: each of which is responsible for all the resolution logic for the associated phase.
7. [LLFirLockProvider](../../../analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/file/builder/LLFirLockProvider.kt)
* First, we resolve containing `FirFile` to the `IMPORTS` phase, is responsible for locking logic which is widely used by `LLFirTargetResolver` during resolution.
* Then we resolve file annotations, - [ContextCollector](../../../analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/util/ContextCollector.kt)
* When we find a non-local container for our declaration as only non-local declarations can be lazily resolved for now, represents resolution context of a specific place in code (a context)
* Finally, resolve *only* that container from phase number `1` to phase `N`
All resolve happens under containing file-based *write lock*.
## Project Module Structure ## Project Module Structure
The `FirModuleResolveState` represents a view from a specific module (**root module**) to the dependent modules. A module is represented by: The `LLFirResolveSession` represents a view from a specific module (**root module**) to the dependent modules. A module is represented by:
* `LLFirSession` the implementation of `FirSession` (FIR compiler representation of a module)
* `FirIdeSourcesSession` the implementation of `FirSession` (FIR compiler representation of a module) * `ModuleFileCache` the `KtFile -> FirFile` cache & also caches for FIR providers
* `ModuleFileCache` the `KtFile -> FirFile` cache & also caches for FIR providers