[AA] Improve coding conventions of KtAnalysisSession

- This commit rewords the coding conventions around `KtAnalysisSession`
  and forbids usage of class context receivers. As explained in the
  KDoc, classes opaquely capture their context receivers as properties,
  which is a high-risk source of leakage.
This commit is contained in:
Marco Pennekamp
2023-11-20 14:58:05 +01:00
committed by Space Team
parent cec9260b45
commit dd23415793
@@ -17,18 +17,43 @@ import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.psi.KtFile
/**
* [KtAnalysisSession] is the entry point into all frontend-related work. It has the following contracts:
* [KtAnalysisSession] is the entry point to all frontend-related work. It has the following contracts:
*
* - It should not be accessed from event dispatch thread.
* - It should not be accessed outside a read action.
* - It should not be leaked outside the read action it was created in.
* - To be sure that an analysis session is not leaked, it is forbidden to store it in a variable. Consider working with it only inside
* [analyze] blocks, and pass it to functions via context receivers (e.g. `context(KtAnalysisSession)`).
* - It should not be accessed from the event dispatch thread or outside a read action.
* - It should not be leaked outside the read action it was created in. To ensure that an analysis session isn't leaked, there are
* additional conventions, explained further below.
* - All entities retrieved from an analysis session should not be leaked outside the read action the analysis session was created in.
*
* To pass a symbol from one read action to another use [KtSymbolPointer], which can be created from a symbol by [KtSymbol.createPointer].
* To pass a symbol from one read action to another, use [KtSymbolPointer], which can be created from a symbol by [KtSymbol.createPointer].
*
* To create a [KtAnalysisSession], please use [analyze] or one of its siblings.
*
* ### Conventions to avoid leakage
*
* It is crucial to avoid leaking the analysis session outside the read action it was created in, as the analysis session itself and all
* entities retrieved from it will become invalid. An analysis session also shouldn't be leaked from the [analyze] call it was created in.
*
* It is forbidden to store an analysis session in a variable, parameter, or property. From the [analyze] block which provides the analysis
* session, the analysis session should be passed to functions via context receivers. For example:
*
* ```kotlin
* context(KtAnalysisSession)
* fun foo() { ... }
* ```
*
* **Class context receivers** should not be used to pass analysis sessions. While a context receiver on a class will make the analysis
* session available in the constructor, it will also be captured by the class as a property. This behavior is easy to miss and a high risk
* for unintentional leakage. For example:
*
* ```kotlin
* // DO NOT DO THIS
* context(KtAnalysisSession)
* class Usage {
* fun foo() {
* // The `KtAnalysisSession` is available here.
* }
* }
* ```
*/
@OptIn(KtAnalysisApiInternals::class, KtAnalysisNonPublicApi::class)
@Suppress("AnalysisApiMissingLifetimeCheck")