All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jetbrains.kotlin.analysis.api.session.KaSessionProvider.kt Maven / Gradle / Ivy

/*
 * Copyright 2010-2020 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.analysis.api.session

import com.intellij.openapi.Disposable
import com.intellij.openapi.project.Project
import org.jetbrains.annotations.TestOnly
import org.jetbrains.kotlin.analysis.api.KaSession
import org.jetbrains.kotlin.analysis.api.KaImplementationDetail
import org.jetbrains.kotlin.analysis.api.projectStructure.KaModule
import org.jetbrains.kotlin.psi.KtElement

/**
 * Provides [KaSession]s by use-site [KtElement]s or [KaModule]s.
 *
 * This provider should not be used directly.
 * Please use [analyze][org.jetbrains.kotlin.analysis.api.analyze] or [analyzeCopy][org.jetbrains.kotlin.analysis.api.analyzeCopy] instead.
 */
@OptIn(KaImplementationDetail::class)
public abstract class KaSessionProvider(public val project: Project) : Disposable {
    public abstract fun getAnalysisSession(useSiteElement: KtElement): KaSession

    public abstract fun getAnalysisSession(useSiteModule: KaModule): KaSession

    // The `analyse` functions affect binary compatibility as they are inlined with every `analyze` call. To avoid breaking binary
    // compatibility, their implementations should not be changed unless absolutely necessary. It should be possible to put most
    // functionality into `beforeEnteringAnalysis` and/or `afterLeavingAnalysis`.

    public inline fun  analyze(
        useSiteElement: KtElement,
        action: KaSession.() -> R,
    ): R {
        val analysisSession = getAnalysisSession(useSiteElement)

        beforeEnteringAnalysis(analysisSession, useSiteElement)
        return try {
            val lock = Any()
            synchronized(lock) {
                // A 'synchronized' block here prevents non-local suspend calls from being inlined.
                // There will be a compilation error if a suspend function is called from the inside.
                analysisSession.action()
            }
        } finally {
            afterLeavingAnalysis(analysisSession, useSiteElement)
        }
    }

    public inline fun  analyze(
        useSiteModule: KaModule,
        action: KaSession.() -> R,
    ): R {
        val analysisSession = getAnalysisSession(useSiteModule)

        beforeEnteringAnalysis(analysisSession, useSiteModule)
        return try {
            val lock = Any()
            synchronized(lock) {
                // A 'synchronized' block here prevents non-local suspend calls from being inlined.
                // There will be a compilation error if a suspend function is called from the inside.
                analysisSession.action()
            }
        } finally {
            afterLeavingAnalysis(analysisSession, useSiteModule)
        }
    }

    /**
     * [beforeEnteringAnalysis] hooks into analysis *before* [analyze]'s action is executed.
     *
     * The signature of [beforeEnteringAnalysis] should be kept stable to avoid breaking binary compatibility, since [analyze] is inlined.
     */
    @KaImplementationDetail
    public abstract fun beforeEnteringAnalysis(session: KaSession, useSiteElement: KtElement)

    /**
     * [beforeEnteringAnalysis] hooks into analysis *before* [analyze]'s action is executed.
     *
     * The signature of [beforeEnteringAnalysis] should be kept stable to avoid breaking binary compatibility, since [analyze] is inlined.
     */
    @KaImplementationDetail
    public abstract fun beforeEnteringAnalysis(session: KaSession, useSiteModule: KaModule)

    /**
     * [afterLeavingAnalysis] hooks into analysis *after* [analyze]'s action has been executed.
     *
     * The signature of [afterLeavingAnalysis] should be kept stable to avoid breaking binary compatibility, since [analyze] is inlined.
     */
    @KaImplementationDetail
    public abstract fun afterLeavingAnalysis(session: KaSession, useSiteElement: KtElement)

    /**
     * [afterLeavingAnalysis] hooks into analysis *after* [analyze]'s action has been executed.
     *
     * The signature of [afterLeavingAnalysis] should be kept stable to avoid breaking binary compatibility, since [analyze] is inlined.
     */
    @KaImplementationDetail
    public abstract fun afterLeavingAnalysis(session: KaSession, useSiteModule: KaModule)

    @KaImplementationDetail
    public abstract fun clearCaches()

    override fun dispose() {}

    public companion object {
        @KaImplementationDetail
        public fun getInstance(project: Project): KaSessionProvider =
            project.getService(KaSessionProvider::class.java)
    }
}

@Deprecated("Use 'KaSessionProvider' instead", ReplaceWith("KaSessionProvider"))
public typealias KtAnalysisSessionProvider = KaSessionProvider




© 2015 - 2025 Weber Informatics LLC | Privacy Policy