[Analysis API] forbid providing custom KtLifetimeToken for every analyze call
^KT-60488 fixed
This commit is contained in:
committed by
Space Team
parent
b617b24d48
commit
4b523825be
+3
-3
@@ -17,11 +17,11 @@ import java.lang.UnsupportedOperationException
|
||||
|
||||
@OptIn(KtAnalysisApiInternals::class)
|
||||
class KtFe10AnalysisSessionProvider(project: Project) : KtAnalysisSessionProvider(project) {
|
||||
override fun getAnalysisSession(useSiteKtElement: KtElement, factory: KtLifetimeTokenFactory): KtAnalysisSession {
|
||||
return KtFe10AnalysisSession(project, useSiteKtElement, factory.create(project))
|
||||
override fun getAnalysisSession(useSiteKtElement: KtElement): KtAnalysisSession {
|
||||
return KtFe10AnalysisSession(project, useSiteKtElement, tokenFactory.create(project))
|
||||
}
|
||||
|
||||
override fun getAnalysisSessionByUseSiteKtModule(useSiteKtModule: KtModule, factory: KtLifetimeTokenFactory): KtAnalysisSession {
|
||||
override fun getAnalysisSessionByUseSiteKtModule(useSiteKtModule: KtModule): KtAnalysisSession {
|
||||
throw UnsupportedOperationException("getAnalysisSessionByModule() should not be used on KtFe10AnalysisSession")
|
||||
}
|
||||
|
||||
|
||||
+5
-5
@@ -35,17 +35,17 @@ class KtFirAnalysisSessionProvider(project: Project) : KtAnalysisSessionProvider
|
||||
LowMemoryWatcher.register(::clearCaches, project)
|
||||
}
|
||||
|
||||
override fun getAnalysisSession(useSiteKtElement: KtElement, factory: KtLifetimeTokenFactory): KtAnalysisSession {
|
||||
override fun getAnalysisSession(useSiteKtElement: KtElement): KtAnalysisSession {
|
||||
val module = ProjectStructureProvider.getModule(project, useSiteKtElement, contextualModule = null)
|
||||
return getAnalysisSessionByUseSiteKtModule(module, factory)
|
||||
return getAnalysisSessionByUseSiteKtModule(module)
|
||||
}
|
||||
|
||||
override fun getAnalysisSessionByUseSiteKtModule(useSiteKtModule: KtModule, factory: KtLifetimeTokenFactory): KtAnalysisSession {
|
||||
val key = Pair(useSiteKtModule, factory.identifier)
|
||||
override fun getAnalysisSessionByUseSiteKtModule(useSiteKtModule: KtModule): KtAnalysisSession {
|
||||
val key = Pair(useSiteKtModule, tokenFactory.identifier)
|
||||
return cache.computeIfAbsent(key) {
|
||||
CachedValuesManager.getManager(project).createCachedValue {
|
||||
val firResolveSession = useSiteKtModule.getFirResolveSession(project)
|
||||
val validityToken = factory.create(project)
|
||||
val validityToken = tokenFactory.create(project)
|
||||
|
||||
CachedValueProvider.Result(
|
||||
KtFirAnalysisSession.createAnalysisSessionByFirResolveSession(firResolveSession, validityToken),
|
||||
|
||||
+3
-3
@@ -10,8 +10,8 @@ import com.intellij.mock.MockProject
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.psi.PsiClass
|
||||
import org.jetbrains.kotlin.analysis.api.KtAnalysisApiInternals
|
||||
import org.jetbrains.kotlin.analysis.api.lifetime.KtDefaultLifetimeTokenProvider
|
||||
import org.jetbrains.kotlin.analysis.api.lifetime.KtReadActionConfinementDefaultLifetimeTokenProvider
|
||||
import org.jetbrains.kotlin.analysis.api.lifetime.KtLifetimeTokenProvider
|
||||
import org.jetbrains.kotlin.analysis.api.lifetime.KtReadActionConfinementLifetimeTokenProvider
|
||||
import org.jetbrains.kotlin.analysis.api.standalone.base.project.structure.StandaloneProjectFactory
|
||||
import org.jetbrains.kotlin.analysis.decompiled.light.classes.ClsJavaStubByVirtualFileCache
|
||||
import org.jetbrains.kotlin.analysis.decompiled.light.classes.DecompiledLightClassesFactory
|
||||
@@ -38,7 +38,7 @@ object AnalysisApiBaseTestServiceRegistrar: AnalysisApiTestServiceRegistrar() {
|
||||
override fun registerProjectServices(project: MockProject, testServices: TestServices) {
|
||||
project.apply {
|
||||
registerService(KotlinModificationTrackerFactory::class.java, KotlinStaticModificationTrackerFactory::class.java)
|
||||
registerService(KtDefaultLifetimeTokenProvider::class.java, KtReadActionConfinementDefaultLifetimeTokenProvider::class.java)
|
||||
registerService(KtLifetimeTokenProvider::class.java, KtReadActionConfinementLifetimeTokenProvider::class.java)
|
||||
|
||||
//KotlinClassFileDecompiler is registered as application service so it's available for the tests run in parallel as well
|
||||
//when the decompiler is registered, for compiled class KtClsFile is created instead of ClsFileImpl
|
||||
|
||||
+3
-3
@@ -16,8 +16,8 @@ import kotlin.contracts.ExperimentalContracts
|
||||
import kotlin.contracts.InvocationKind
|
||||
import kotlin.contracts.contract
|
||||
import org.jetbrains.kotlin.analysis.api.KtAnalysisApiInternals
|
||||
import org.jetbrains.kotlin.analysis.api.lifetime.KtDefaultLifetimeTokenProvider
|
||||
import org.jetbrains.kotlin.analysis.api.lifetime.KtReadActionConfinementDefaultLifetimeTokenProvider
|
||||
import org.jetbrains.kotlin.analysis.api.lifetime.KtLifetimeTokenProvider
|
||||
import org.jetbrains.kotlin.analysis.api.lifetime.KtReadActionConfinementLifetimeTokenProvider
|
||||
import org.jetbrains.kotlin.analysis.api.standalone.base.project.structure.FirStandaloneServiceRegistrar
|
||||
import org.jetbrains.kotlin.analysis.api.standalone.base.project.structure.StandaloneProjectFactory
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.services.FirSealedClassInheritorsProcessorFactory
|
||||
@@ -121,7 +121,7 @@ public class StandaloneAnalysisAPISessionBuilder(
|
||||
FirStandaloneServiceRegistrar.registerProjectModelServices(project, kotlinCoreProjectEnvironment.parentDisposable)
|
||||
|
||||
registerService(KotlinModificationTrackerFactory::class.java, KotlinStaticModificationTrackerFactory::class.java)
|
||||
registerService(KtDefaultLifetimeTokenProvider::class.java, KtReadActionConfinementDefaultLifetimeTokenProvider::class.java)
|
||||
registerService(KtLifetimeTokenProvider::class.java, KtReadActionConfinementLifetimeTokenProvider::class.java)
|
||||
|
||||
registerService(KtModuleScopeProvider::class.java, KtModuleScopeProviderImpl())
|
||||
registerService(KotlinAnnotationsResolverFactory::class.java, KotlinStaticAnnotationsResolverFactory(ktFiles))
|
||||
|
||||
@@ -22,50 +22,40 @@ import org.jetbrains.kotlin.psi.KtFile
|
||||
* Uses [useSiteKtElement] as an [KtElement] which containing module is a use-site module,
|
||||
* i.e, the module from which perspective the project will be analyzed.
|
||||
*
|
||||
* [nonDefaultLifetimeTokenFactory] represents lifetime and accessibility guaranties
|
||||
* which will be applied to the [org.jetbrains.kotlin.analysis.api.lifetime.KtLifetimeOwner] instances created during code analysis.
|
||||
*
|
||||
* @see KtAnalysisSession
|
||||
* @see KtLifetimeTokenFactory
|
||||
* @see analyzeWithReadAction
|
||||
*/
|
||||
public inline fun <R> analyze(
|
||||
useSiteKtElement: KtElement,
|
||||
nonDefaultLifetimeTokenFactory: KtLifetimeTokenFactory? = null,
|
||||
action: KtAnalysisSession.() -> R
|
||||
): R =
|
||||
KtAnalysisSessionProvider.getInstance(useSiteKtElement.project)
|
||||
.analyse(useSiteKtElement, nonDefaultLifetimeTokenFactory, action)
|
||||
.analyse(useSiteKtElement, action)
|
||||
|
||||
|
||||
/**
|
||||
* Execute given [action] in [KtAnalysisSession] context
|
||||
* Uses [useSiteKtModule] as use-site module, i.e, the module from which perspective the project will be analyzed.
|
||||
*
|
||||
* [nonDefaultLifetimeTokenFactory] represents lifetime and accessibility guaranties
|
||||
* which will be applied to the [org.jetbrains.kotlin.analysis.api.lifetime.KtLifetimeOwner] instances created during code analysis.
|
||||
*
|
||||
* @see KtAnalysisSession
|
||||
* @see KtLifetimeTokenFactory
|
||||
*/
|
||||
public inline fun <R> analyze(
|
||||
useSiteKtModule: KtModule,
|
||||
nonDefaultLifetimeTokenFactory: KtLifetimeTokenFactory? = null,
|
||||
crossinline action: KtAnalysisSession.() -> R
|
||||
): R {
|
||||
val sessionProvider = KtAnalysisSessionProvider.getInstance(useSiteKtModule.project)
|
||||
return sessionProvider.analyze(useSiteKtModule, nonDefaultLifetimeTokenFactory, action)
|
||||
return sessionProvider.analyze(useSiteKtModule, action)
|
||||
}
|
||||
|
||||
|
||||
public inline fun <R> analyzeInDependedAnalysisSession(
|
||||
originalFile: KtFile,
|
||||
elementToReanalyze: KtElement,
|
||||
nonDefaultLifetimeTokenFactory: KtLifetimeTokenFactory? = null,
|
||||
action: KtAnalysisSession.() -> R
|
||||
): R =
|
||||
KtAnalysisSessionProvider.getInstance(originalFile.project)
|
||||
.analyseInDependedAnalysisSession(originalFile, elementToReanalyze, nonDefaultLifetimeTokenFactory, action)
|
||||
.analyseInDependedAnalysisSession(originalFile, elementToReanalyze, action)
|
||||
|
||||
/**
|
||||
* Execute given [action] in [KtAnalysisSession] context like [analyze] does but execute it in read action
|
||||
@@ -81,10 +71,9 @@ public inline fun <R> analyzeInDependedAnalysisSession(
|
||||
*/
|
||||
public inline fun <R> analyzeWithReadAction(
|
||||
contextElement: KtElement,
|
||||
nonDefaultLifetimeTokenFactory: KtLifetimeTokenFactory? = null,
|
||||
crossinline action: KtAnalysisSession.() -> R
|
||||
): R = ApplicationManager.getApplication().runReadAction(Computable {
|
||||
analyze(contextElement, nonDefaultLifetimeTokenFactory, action)
|
||||
analyze(contextElement, action)
|
||||
})
|
||||
|
||||
/**
|
||||
@@ -97,13 +86,12 @@ public inline fun <R> analyzeWithReadAction(
|
||||
public inline fun <R> analyzeInModalWindow(
|
||||
contextElement: KtElement,
|
||||
windowTitle: String,
|
||||
nonDefaultLifetimeTokenFactory: KtLifetimeTokenFactory? = null,
|
||||
crossinline action: KtAnalysisSession.() -> R
|
||||
): R {
|
||||
ApplicationManager.getApplication().assertIsDispatchThread()
|
||||
val task = object : Task.WithResult<R, Exception>(contextElement.project, windowTitle, /*canBeCancelled*/ true) {
|
||||
override fun compute(indicator: ProgressIndicator): R =
|
||||
analyzeWithReadAction(contextElement, nonDefaultLifetimeTokenFactory) { action() }
|
||||
analyzeWithReadAction(contextElement) { action() }
|
||||
}
|
||||
task.queue()
|
||||
return task.result
|
||||
|
||||
+6
-6
@@ -9,19 +9,19 @@ import com.intellij.openapi.project.Project
|
||||
import org.jetbrains.kotlin.analysis.api.KtAnalysisApiInternals
|
||||
|
||||
@KtAnalysisApiInternals
|
||||
public abstract class KtDefaultLifetimeTokenProvider {
|
||||
public abstract fun getDefaultLifetimeTokenFactory(): KtLifetimeTokenFactory
|
||||
public abstract class KtLifetimeTokenProvider {
|
||||
public abstract fun getLifetimeTokenFactory(): KtLifetimeTokenFactory
|
||||
|
||||
public companion object {
|
||||
@KtAnalysisApiInternals
|
||||
public fun getService(project: Project): KtDefaultLifetimeTokenProvider =
|
||||
project.getService(KtDefaultLifetimeTokenProvider::class.java)
|
||||
public fun getService(project: Project): KtLifetimeTokenProvider =
|
||||
project.getService(KtLifetimeTokenProvider::class.java)
|
||||
}
|
||||
}
|
||||
|
||||
@KtAnalysisApiInternals
|
||||
public class KtReadActionConfinementDefaultLifetimeTokenProvider: KtDefaultLifetimeTokenProvider() {
|
||||
override fun getDefaultLifetimeTokenFactory(): KtLifetimeTokenFactory {
|
||||
public class KtReadActionConfinementLifetimeTokenProvider : KtLifetimeTokenProvider() {
|
||||
override fun getLifetimeTokenFactory(): KtLifetimeTokenFactory {
|
||||
return KtReadActionConfinementLifetimeTokenFactory
|
||||
}
|
||||
}
|
||||
+16
-26
@@ -11,7 +11,7 @@ import org.jetbrains.annotations.TestOnly
|
||||
import org.jetbrains.kotlin.analysis.api.KtAnalysisSession
|
||||
import org.jetbrains.kotlin.analysis.api.KtAnalysisApiInternals
|
||||
import org.jetbrains.kotlin.analysis.api.lifetime.impl.NoWriteActionInAnalyseCallChecker
|
||||
import org.jetbrains.kotlin.analysis.api.lifetime.KtDefaultLifetimeTokenProvider
|
||||
import org.jetbrains.kotlin.analysis.api.lifetime.KtLifetimeTokenProvider
|
||||
import org.jetbrains.kotlin.analysis.api.lifetime.KtLifetimeTokenFactory
|
||||
import org.jetbrains.kotlin.analysis.project.structure.KtModule
|
||||
import org.jetbrains.kotlin.psi.KtElement
|
||||
@@ -21,63 +21,53 @@ import org.jetbrains.kotlin.psi.KtFile
|
||||
* Provides [KtAnalysisSession] by [contextElement]
|
||||
* Should not be used directly, consider using [analyse]/[analyzeWithReadAction]/[analyzeInModalWindow] instead
|
||||
*/
|
||||
@KtAnalysisApiInternals
|
||||
@OptIn(KtAnalysisApiInternals::class)
|
||||
public abstract class KtAnalysisSessionProvider(public val project: Project) : Disposable {
|
||||
@KtAnalysisApiInternals
|
||||
public val tokenFactory: KtLifetimeTokenFactory = KtLifetimeTokenProvider.getService(project).getLifetimeTokenFactory()
|
||||
|
||||
@Suppress("LeakingThis")
|
||||
public val noWriteActionInAnalyseCallChecker: NoWriteActionInAnalyseCallChecker = NoWriteActionInAnalyseCallChecker(this)
|
||||
|
||||
public abstract fun getAnalysisSession(useSiteKtElement: KtElement, factory: KtLifetimeTokenFactory): KtAnalysisSession
|
||||
public abstract fun getAnalysisSession(useSiteKtElement: KtElement): KtAnalysisSession
|
||||
|
||||
public abstract fun getAnalysisSessionByUseSiteKtModule(useSiteKtModule: KtModule, factory: KtLifetimeTokenFactory): KtAnalysisSession
|
||||
public abstract fun getAnalysisSessionByUseSiteKtModule(useSiteKtModule: KtModule): KtAnalysisSession
|
||||
|
||||
public inline fun <R> analyseInDependedAnalysisSession(
|
||||
originalFile: KtFile,
|
||||
elementToReanalyze: KtElement,
|
||||
nonDefaultLifetimeTokenFactory: KtLifetimeTokenFactory?,
|
||||
action: KtAnalysisSession.() -> R
|
||||
action: KtAnalysisSession.() -> R,
|
||||
): R {
|
||||
val factory =
|
||||
nonDefaultLifetimeTokenFactory ?: KtDefaultLifetimeTokenProvider.getService(project).getDefaultLifetimeTokenFactory()
|
||||
|
||||
val originalAnalysisSession = getAnalysisSession(originalFile, factory)
|
||||
val originalAnalysisSession = getAnalysisSession(originalFile)
|
||||
val dependedAnalysisSession = originalAnalysisSession
|
||||
.createContextDependentCopy(originalFile, elementToReanalyze)
|
||||
return analyse(dependedAnalysisSession, factory, action)
|
||||
return analyse(dependedAnalysisSession, action)
|
||||
}
|
||||
|
||||
public inline fun <R> analyse(
|
||||
useSiteKtElement: KtElement,
|
||||
nonDefaultLifetimeTokenFactory: KtLifetimeTokenFactory?,
|
||||
action: KtAnalysisSession.() -> R
|
||||
action: KtAnalysisSession.() -> R,
|
||||
): R {
|
||||
val factory =
|
||||
nonDefaultLifetimeTokenFactory ?: KtDefaultLifetimeTokenProvider.getService(project).getDefaultLifetimeTokenFactory()
|
||||
return analyse(getAnalysisSession(useSiteKtElement, factory), factory, action)
|
||||
return analyse(getAnalysisSession(useSiteKtElement), action)
|
||||
}
|
||||
|
||||
public inline fun <R> analyze(
|
||||
useSiteKtModule: KtModule,
|
||||
nonDefaultLifetimeTokenFactory: KtLifetimeTokenFactory?,
|
||||
action: KtAnalysisSession.() -> R
|
||||
action: KtAnalysisSession.() -> R,
|
||||
): R {
|
||||
val factory =
|
||||
nonDefaultLifetimeTokenFactory ?: KtDefaultLifetimeTokenProvider.getService(project).getDefaultLifetimeTokenFactory()
|
||||
|
||||
return analyse(getAnalysisSessionByUseSiteKtModule(useSiteKtModule, factory), factory, action)
|
||||
return analyse(getAnalysisSessionByUseSiteKtModule(useSiteKtModule), action)
|
||||
}
|
||||
|
||||
public inline fun <R> analyse(
|
||||
analysisSession: KtAnalysisSession,
|
||||
factory: KtLifetimeTokenFactory,
|
||||
action: KtAnalysisSession.() -> R
|
||||
action: KtAnalysisSession.() -> R,
|
||||
): R {
|
||||
noWriteActionInAnalyseCallChecker.beforeEnteringAnalysisContext()
|
||||
factory.beforeEnteringAnalysisContext(analysisSession.token)
|
||||
tokenFactory.beforeEnteringAnalysisContext(analysisSession.token)
|
||||
return try {
|
||||
analysisSession.action()
|
||||
} finally {
|
||||
factory.afterLeavingAnalysisContext(analysisSession.token)
|
||||
tokenFactory.afterLeavingAnalysisContext(analysisSession.token)
|
||||
noWriteActionInAnalyseCallChecker.afterLeavingAnalysisContext()
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user