[LL API] Refactor session caches
Use 'CachedValue' and dependency handling with 'ModificationTracker' for dependent session invalidation.
This commit is contained in:
+10
-10
@@ -6,21 +6,21 @@
|
||||
package org.jetbrains.kotlin.analysis.api.standalone;
|
||||
|
||||
import com.intellij.mock.MockProject;
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.LLFirGlobalResolveComponents;
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.LLFirResolveSessionService;
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.project.structure.LLFirLibrarySessionFactory;
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.LLFirSessionCache;
|
||||
|
||||
@SuppressWarnings("KotlinInternalInJava")
|
||||
class RegisterComponentService {
|
||||
static void registerLLFirLibrarySessionFactory(MockProject project) {
|
||||
project.registerService(
|
||||
LLFirLibrarySessionFactory.class,
|
||||
new LLFirLibrarySessionFactory(project)
|
||||
);
|
||||
static void registerLLFirSessionCache(MockProject project) {
|
||||
project.registerService(LLFirSessionCache.class, new LLFirSessionCache(project));
|
||||
}
|
||||
|
||||
static void registerLLFirGlobalResolveComponents(MockProject project) {
|
||||
project.registerService(LLFirGlobalResolveComponents.class, new LLFirGlobalResolveComponents(project));
|
||||
}
|
||||
|
||||
static void registerLLFirResolveSessionService(MockProject project) {
|
||||
project.registerService(
|
||||
LLFirResolveSessionService.class,
|
||||
new LLFirResolveSessionService(project)
|
||||
);
|
||||
project.registerService(LLFirResolveSessionService.class, new LLFirResolveSessionService(project));
|
||||
}
|
||||
}
|
||||
|
||||
+2
-1
@@ -142,7 +142,8 @@ public class StandaloneAnalysisAPISessionBuilder(
|
||||
}
|
||||
)
|
||||
registerService(LLFirBuiltinsSessionFactory::class.java, LLFirBuiltinsSessionFactory(this))
|
||||
RegisterComponentService.registerLLFirLibrarySessionFactory(this)
|
||||
RegisterComponentService.registerLLFirSessionCache(this)
|
||||
RegisterComponentService.registerLLFirGlobalResolveComponents(this)
|
||||
|
||||
registerService(KotlinReferenceProvidersService::class.java, HLApiReferenceProviderService::class.java)
|
||||
registerService(KotlinReferenceProviderContributor::class.java, KotlinFirReferenceContributor::class.java)
|
||||
|
||||
+28
-4
@@ -6,15 +6,39 @@
|
||||
package org.jetbrains.kotlin.analysis.utils.trackers
|
||||
|
||||
import com.intellij.openapi.util.ModificationTracker
|
||||
import java.util.*
|
||||
import kotlin.collections.ArrayList
|
||||
|
||||
public class CompositeModificationTracker private constructor(private val trackers: List<ModificationTracker>) : ModificationTracker {
|
||||
override fun getModificationCount(): Long = trackers.sumOf { it.modificationCount }
|
||||
|
||||
public companion object {
|
||||
public fun create(trackers: List<ModificationTracker>): ModificationTracker = when (trackers.size) {
|
||||
0 -> ModificationTracker.NEVER_CHANGED
|
||||
1 -> trackers.single()
|
||||
else -> CompositeModificationTracker(trackers)
|
||||
public fun create(trackers: List<ModificationTracker>): ModificationTracker {
|
||||
return when (trackers.size) {
|
||||
0 -> ModificationTracker.NEVER_CHANGED
|
||||
1 -> trackers.single()
|
||||
else -> CompositeModificationTracker(trackers)
|
||||
}
|
||||
}
|
||||
|
||||
public fun createFlattened(trackers: List<ModificationTracker>): ModificationTracker {
|
||||
val map = IdentityHashMap<ModificationTracker, Boolean>()
|
||||
val flattened = ArrayList<ModificationTracker>()
|
||||
|
||||
fun flatten(tracker: ModificationTracker) {
|
||||
when (tracker) {
|
||||
is CompositeModificationTracker -> tracker.trackers.forEach(::flatten)
|
||||
ModificationTracker.NEVER_CHANGED -> {}
|
||||
else -> {
|
||||
if (map.put(tracker, true) == null) {
|
||||
flattened += tracker
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
trackers.forEach(::flatten)
|
||||
return create(flattened)
|
||||
}
|
||||
}
|
||||
}
|
||||
+7
-4
@@ -7,11 +7,14 @@ package org.jetbrains.kotlin.analysis.low.level.api.fir
|
||||
|
||||
import com.intellij.openapi.project.Project
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.LLFirLockProvider
|
||||
import org.jetbrains.kotlin.analysis.project.structure.KtModule
|
||||
|
||||
internal class LLFirGlobalResolveComponents(
|
||||
val project: Project,
|
||||
) {
|
||||
internal class LLFirGlobalResolveComponents(val project: Project) {
|
||||
companion object {
|
||||
fun getInstance(project: Project): LLFirGlobalResolveComponents {
|
||||
return project.getService(LLFirGlobalResolveComponents::class.java)
|
||||
}
|
||||
}
|
||||
|
||||
val phaseRunner: LLFirPhaseRunner = LLFirPhaseRunner()
|
||||
val lockProvider: LLFirLockProvider = LLFirLockProvider()
|
||||
}
|
||||
-1
@@ -30,7 +30,6 @@ import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
|
||||
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||
import org.jetbrains.kotlin.psi.KtElement
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
|
||||
internal class LLFirResolveSessionDepended(
|
||||
val originalFirResolveSession: LLFirResolvableResolveSession,
|
||||
|
||||
+25
-81
@@ -7,10 +7,9 @@ package org.jetbrains.kotlin.analysis.low.level.api.fir
|
||||
|
||||
import com.intellij.openapi.components.ServiceManager
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.roots.ProjectRootModificationTracker
|
||||
import org.jetbrains.annotations.TestOnly
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.LLFirResolveSession
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.LLFirSessionProviderStorage
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.LLFirSession
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.LLFirSessionCache
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.state.LLFirLibraryOrLibrarySourceResolvableResolveSession
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.state.LLFirNotUnderContentRootResolveSession
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.state.LLFirResolvableResolveSession
|
||||
@@ -18,91 +17,36 @@ import org.jetbrains.kotlin.analysis.low.level.api.fir.state.LLFirScriptResolveS
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.state.LLFirSourceResolveSession
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.errorWithFirSpecificEntries
|
||||
import org.jetbrains.kotlin.analysis.project.structure.*
|
||||
import org.jetbrains.kotlin.analysis.providers.createProjectWideOutOfBlockModificationTracker
|
||||
import org.jetbrains.kotlin.analysis.utils.caches.SoftCachedMap
|
||||
|
||||
internal class LLFirResolveSessionService(project: Project) {
|
||||
private val sessionProviderStorage = LLFirSessionProviderStorage(project)
|
||||
class LLFirResolveSessionService(project: Project) {
|
||||
private val cache = LLFirSessionCache.getInstance(project)
|
||||
|
||||
private val cache = SoftCachedMap.create<KtModule, LLFirResolvableResolveSession>(
|
||||
project,
|
||||
SoftCachedMap.Kind.STRONG_KEYS_SOFT_VALUES,
|
||||
listOf(
|
||||
ProjectRootModificationTracker.getInstance(project),
|
||||
project.createProjectWideOutOfBlockModificationTracker(),
|
||||
)
|
||||
)
|
||||
fun getFirResolveSession(module: KtModule): LLFirResolveSession {
|
||||
return create(module, cache::getSession)
|
||||
}
|
||||
|
||||
fun getFirResolveSession(module: KtModule): LLFirResolvableResolveSession {
|
||||
return cache.getOrPut(module) {
|
||||
createFirResolveSessionFor(module, sessionProviderStorage)
|
||||
fun getFirResolveSessionNoCaching(module: KtModule): LLFirResolveSession {
|
||||
return create(module, cache::getSessionNoCaching)
|
||||
}
|
||||
|
||||
private fun create(module: KtModule, factory: (KtModule) -> LLFirSession): LLFirResolvableResolveSession {
|
||||
val session = factory(module)
|
||||
|
||||
return when (module) {
|
||||
is KtSourceModule -> LLFirSourceResolveSession(session)
|
||||
is KtLibraryModule, is KtLibrarySourceModule -> LLFirLibraryOrLibrarySourceResolvableResolveSession(session)
|
||||
is KtScriptModule -> LLFirScriptResolveSession(session)
|
||||
is KtNotUnderContentRootModule -> LLFirNotUnderContentRootResolveSession(session)
|
||||
else -> {
|
||||
errorWithFirSpecificEntries("Unexpected ${module::class.java}") {
|
||||
withEntry("module", module) { it.moduleDescription }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun getInstance(project: Project): LLFirResolveSessionService =
|
||||
ServiceManager.getService(project, LLFirResolveSessionService::class.java)
|
||||
|
||||
internal fun createFirResolveSessionFor(
|
||||
useSiteKtModule: KtModule,
|
||||
sessionProviderStorage: LLFirSessionProviderStorage
|
||||
): LLFirResolvableResolveSession {
|
||||
val sessionProvider = sessionProviderStorage.getSessionProvider(useSiteKtModule)
|
||||
val useSiteSession = sessionProvider.rootModuleSession
|
||||
return when (useSiteKtModule) {
|
||||
is KtSourceModule -> {
|
||||
LLFirSourceResolveSession(
|
||||
useSiteSession.moduleComponents.globalResolveComponents,
|
||||
sessionProviderStorage.project,
|
||||
useSiteKtModule,
|
||||
sessionProvider,
|
||||
)
|
||||
}
|
||||
|
||||
is KtLibraryModule, is KtLibrarySourceModule -> {
|
||||
LLFirLibraryOrLibrarySourceResolvableResolveSession(
|
||||
useSiteSession.moduleComponents.globalResolveComponents,
|
||||
sessionProviderStorage.project,
|
||||
useSiteKtModule,
|
||||
sessionProvider,
|
||||
)
|
||||
}
|
||||
|
||||
is KtScriptModule -> {
|
||||
LLFirScriptResolveSession(
|
||||
useSiteSession.moduleComponents.globalResolveComponents,
|
||||
sessionProviderStorage.project,
|
||||
useSiteKtModule,
|
||||
sessionProvider
|
||||
)
|
||||
}
|
||||
|
||||
is KtNotUnderContentRootModule -> {
|
||||
LLFirNotUnderContentRootResolveSession(
|
||||
useSiteSession.moduleComponents.globalResolveComponents,
|
||||
sessionProviderStorage.project,
|
||||
useSiteKtModule,
|
||||
sessionProvider,
|
||||
)
|
||||
}
|
||||
|
||||
else -> {
|
||||
errorWithFirSpecificEntries("Unexpected ${useSiteKtModule::class.java}") {
|
||||
withEntry("module", useSiteKtModule) { it.moduleDescription }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@TestOnly
|
||||
fun createFirResolveSessionForNoCaching(useSiteKtModule: KtModule, project: Project): LLFirResolveSession {
|
||||
return LLFirResolveSessionService.createFirResolveSessionFor(
|
||||
useSiteKtModule = useSiteKtModule,
|
||||
sessionProviderStorage = LLFirSessionProviderStorage(project)
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
+4
-1
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.analysis.low.level.api.fir.api
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.util.PsiTreeUtil
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.DeclarationCopyBuilder.withBodyFrom
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.LLFirGlobalResolveComponents
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.LLFirResolveSessionDepended
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.element.builder.FileTowerProvider
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.element.builder.FirTowerContextProvider
|
||||
@@ -259,7 +260,9 @@ object LowLevelFirApiFacadeForResolveOnAir {
|
||||
|
||||
val isInBodyReplacement = isInBodyReplacement(nonLocalDeclaration, replacement)
|
||||
|
||||
return firResolveSession.globalComponents.lockProvider.withLock(originalFirFile) {
|
||||
val globalResolveComponents = LLFirGlobalResolveComponents.getInstance(firResolveSession.project)
|
||||
|
||||
return globalResolveComponents.lockProvider.withLock(originalFirFile) {
|
||||
val copiedFirDeclaration = if (isInBodyReplacement) {
|
||||
when (originalDeclaration) {
|
||||
is FirSimpleFunction ->
|
||||
|
||||
+11
-10
@@ -6,6 +6,7 @@
|
||||
package org.jetbrains.kotlin.analysis.low.level.api.fir.project.structure
|
||||
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.util.ModificationTracker
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.providers.LLFirBuiltinSymbolProvider
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.providers.LLFirBuiltinsAndCloneableSessionProvider
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.LLFirBuiltinsAndCloneableSession
|
||||
@@ -37,9 +38,7 @@ import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatformAnalyzerServices
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
|
||||
@OptIn(PrivateSessionConstructor::class, SessionConfiguration::class)
|
||||
class LLFirBuiltinsSessionFactory(
|
||||
private val project: Project,
|
||||
) {
|
||||
class LLFirBuiltinsSessionFactory(private val project: Project) {
|
||||
private val builtInTypes = BuiltinTypes() // TODO should be platform-specific
|
||||
private val builtinsAndCloneableSession = ConcurrentHashMap<TargetPlatform, LLFirBuiltinsAndCloneableSession>()
|
||||
|
||||
@@ -49,10 +48,11 @@ class LLFirBuiltinsSessionFactory(
|
||||
|
||||
private fun createBuiltinsAndCloneableSession(platform: TargetPlatform): LLFirBuiltinsAndCloneableSession {
|
||||
val builtinsModule = KtBuiltinsModule(platform, platform.getAnalyzerServices(), project)
|
||||
return LLFirBuiltinsAndCloneableSession(builtinsModule, builtInTypes).apply session@{
|
||||
val moduleData = LLFirModuleData(builtinsModule).apply {
|
||||
bindSession(this@session)
|
||||
}
|
||||
|
||||
val session = LLFirBuiltinsAndCloneableSession(builtinsModule, ModificationTracker.NEVER_CHANGED, builtInTypes)
|
||||
val moduleData = LLFirModuleData(builtinsModule).apply { bindSession(session) }
|
||||
|
||||
return session.apply {
|
||||
registerIdeComponents(project)
|
||||
register(FirLazyDeclarationResolver::class, FirDummyCompilerLazyDeclarationResolver)
|
||||
registerCommonComponents(LanguageVersionSettingsImpl.DEFAULT/*TODO*/)
|
||||
@@ -62,10 +62,11 @@ class LLFirBuiltinsSessionFactory(
|
||||
|
||||
val kotlinScopeProvider = FirKotlinScopeProvider(::wrapScopeWithJvmMapped)
|
||||
register(FirKotlinScopeProvider::class, kotlinScopeProvider)
|
||||
|
||||
val symbolProvider = createCompositeSymbolProvider(this) {
|
||||
add(LLFirBuiltinSymbolProvider(this@session, moduleData, kotlinScopeProvider))
|
||||
add(FirExtensionSyntheticFunctionInterfaceProvider(this@session, moduleData, kotlinScopeProvider))
|
||||
add(FirCloneableSymbolProvider(this@session, moduleData, kotlinScopeProvider))
|
||||
add(LLFirBuiltinSymbolProvider(session, moduleData, kotlinScopeProvider))
|
||||
add(FirExtensionSyntheticFunctionInterfaceProvider(session, moduleData, kotlinScopeProvider))
|
||||
add(FirCloneableSymbolProvider(session, moduleData, kotlinScopeProvider))
|
||||
}
|
||||
|
||||
register(FirSymbolProvider::class, symbolProvider)
|
||||
|
||||
-81
@@ -1,81 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2022 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.low.level.api.fir.project.structure
|
||||
|
||||
import com.intellij.openapi.project.Project
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.providers.LLFirFirClassByPsiClassProvider
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.providers.LLFirLibrarySessionProvider
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.LLFirLibrarySession
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.LLFirSession
|
||||
import org.jetbrains.kotlin.analysis.project.structure.KtBinaryModule
|
||||
import org.jetbrains.kotlin.analysis.project.structure.KtModule
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl
|
||||
import org.jetbrains.kotlin.fir.PrivateSessionConstructor
|
||||
import org.jetbrains.kotlin.fir.SessionConfiguration
|
||||
import org.jetbrains.kotlin.fir.backend.jvm.FirJvmTypeMapper
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.FirProvider
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider
|
||||
import org.jetbrains.kotlin.fir.resolve.scopes.wrapScopeWithJvmMapped
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.FirDummyCompilerLazyDeclarationResolver
|
||||
import org.jetbrains.kotlin.fir.scopes.FirKotlinScopeProvider
|
||||
import org.jetbrains.kotlin.fir.session.*
|
||||
import org.jetbrains.kotlin.fir.symbols.FirLazyDeclarationResolver
|
||||
import org.jetbrains.kotlin.resolve.jvm.modules.JavaModuleResolver
|
||||
|
||||
@OptIn(PrivateSessionConstructor::class, SessionConfiguration::class)
|
||||
class LLFirLibrarySessionFactory(
|
||||
private val project: Project,
|
||||
) {
|
||||
|
||||
internal fun getLibrarySession(ktBinaryModule: KtBinaryModule, sessionsCache: MutableMap<KtModule, LLFirSession>): LLFirLibrarySession {
|
||||
return sessionsCache.getOrPut(ktBinaryModule) {
|
||||
createModuleLibrariesSession(ktBinaryModule, sessionsCache)
|
||||
} as LLFirLibrarySession
|
||||
}
|
||||
|
||||
private fun createModuleLibrariesSession(
|
||||
ktLibraryModule: KtBinaryModule,
|
||||
sessionsCache: MutableMap<KtModule, LLFirSession>,
|
||||
): LLFirLibrarySession {
|
||||
val platform = ktLibraryModule.platform
|
||||
val builtinsSession = LLFirBuiltinsSessionFactory.getInstance(project).getBuiltinsSession(platform)
|
||||
sessionsCache.putIfAbsent(builtinsSession.ktModule, builtinsSession)
|
||||
return LLFirLibrarySession(ktLibraryModule, builtinsSession.builtinTypes).apply session@{
|
||||
val moduleData = LLFirModuleData(ktLibraryModule).apply { bindSession(this@session) }
|
||||
registerModuleData(moduleData)
|
||||
registerIdeComponents(project)
|
||||
register(FirLazyDeclarationResolver::class, FirDummyCompilerLazyDeclarationResolver)
|
||||
registerCommonComponents(LanguageVersionSettingsImpl.DEFAULT/*TODO*/)
|
||||
registerCommonComponentsAfterExtensionsAreConfigured()
|
||||
registerCommonJavaComponents(JavaModuleResolver.getInstance(project))
|
||||
registerJavaSpecificResolveComponents()
|
||||
|
||||
val kotlinScopeProvider = FirKotlinScopeProvider(::wrapScopeWithJvmMapped)
|
||||
register(FirKotlinScopeProvider::class, kotlinScopeProvider)
|
||||
|
||||
val symbolProvider = LLFirLibraryProviderFactory.createLibraryProvidersForScope(
|
||||
this,
|
||||
moduleData,
|
||||
kotlinScopeProvider,
|
||||
project,
|
||||
builtinTypes,
|
||||
ktLibraryModule.contentScope,
|
||||
builtinsSession.symbolProvider
|
||||
)
|
||||
|
||||
register(LLFirFirClassByPsiClassProvider::class, LLFirFirClassByPsiClassProvider(this))
|
||||
register(FirProvider::class, LLFirLibrarySessionProvider(symbolProvider))
|
||||
register(FirSymbolProvider::class, symbolProvider)
|
||||
register(FirJvmTypeMapper::class, FirJvmTypeMapper(this))
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun getInstance(project: Project): LLFirLibrarySessionFactory =
|
||||
project.getService(LLFirLibrarySessionFactory::class.java)
|
||||
}
|
||||
}
|
||||
+3
-1
@@ -5,11 +5,13 @@
|
||||
|
||||
package org.jetbrains.kotlin.analysis.low.level.api.fir.sessions
|
||||
|
||||
import com.intellij.openapi.util.ModificationTracker
|
||||
import org.jetbrains.kotlin.analysis.project.structure.KtModule
|
||||
import org.jetbrains.kotlin.fir.BuiltinTypes
|
||||
import org.jetbrains.kotlin.fir.PrivateSessionConstructor
|
||||
|
||||
class LLFirBuiltinsAndCloneableSession @PrivateSessionConstructor constructor(
|
||||
ktModule: KtModule,
|
||||
dependencyTracker: ModificationTracker,
|
||||
builtinTypes: BuiltinTypes,
|
||||
) : LLFirLibraryLikeSession(ktModule, builtinTypes)
|
||||
) : LLFirLibraryLikeSession(ktModule, dependencyTracker, builtinTypes)
|
||||
+3
-1
@@ -5,6 +5,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.analysis.low.level.api.fir.sessions
|
||||
|
||||
import com.intellij.openapi.util.ModificationTracker
|
||||
import org.jetbrains.kotlin.analysis.project.structure.KtModule
|
||||
import org.jetbrains.kotlin.fir.BuiltinTypes
|
||||
import org.jetbrains.kotlin.fir.PrivateSessionConstructor
|
||||
@@ -14,5 +15,6 @@ import org.jetbrains.kotlin.fir.PrivateSessionConstructor
|
||||
*/
|
||||
internal class LLFirLibrarySession @PrivateSessionConstructor constructor(
|
||||
ktModule: KtModule,
|
||||
dependencyTracker: ModificationTracker,
|
||||
builtinTypes: BuiltinTypes,
|
||||
) : LLFirLibraryLikeSession(ktModule, builtinTypes)
|
||||
) : LLFirLibraryLikeSession(ktModule, dependencyTracker, builtinTypes)
|
||||
|
||||
+3
-1
@@ -5,6 +5,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.analysis.low.level.api.fir.sessions
|
||||
|
||||
import com.intellij.openapi.util.ModificationTracker
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.LLFirScopeSessionProvider
|
||||
import org.jetbrains.kotlin.analysis.project.structure.KtModule
|
||||
import org.jetbrains.kotlin.fir.BuiltinTypes
|
||||
@@ -12,8 +13,9 @@ import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
||||
|
||||
abstract class LLFirLibraryLikeSession(
|
||||
ktModule: KtModule,
|
||||
dependencyTracker: ModificationTracker,
|
||||
builtinTypes: BuiltinTypes,
|
||||
) : LLFirSession(ktModule, builtinTypes, Kind.Library) {
|
||||
) : LLFirSession(ktModule, dependencyTracker, builtinTypes, Kind.Library) {
|
||||
private val scopeSessionProvider = LLFirScopeSessionProvider.create(project, invalidationTrackers = emptyList())
|
||||
|
||||
override fun getScopeSession(): ScopeSession {
|
||||
|
||||
+3
-1
@@ -5,6 +5,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.analysis.low.level.api.fir.sessions
|
||||
|
||||
import com.intellij.openapi.util.ModificationTracker
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.LLFirModuleResolveComponents
|
||||
import org.jetbrains.kotlin.analysis.project.structure.KtLibraryModule
|
||||
import org.jetbrains.kotlin.analysis.project.structure.KtLibrarySourceModule
|
||||
@@ -13,9 +14,10 @@ import org.jetbrains.kotlin.fir.BuiltinTypes
|
||||
|
||||
internal class LLFirLibraryOrLibrarySourceResolvableModuleSession(
|
||||
ktModule: KtModule,
|
||||
dependencyTracker: ModificationTracker,
|
||||
override val moduleComponents: LLFirModuleResolveComponents,
|
||||
builtinTypes: BuiltinTypes,
|
||||
) : LLFirResolvableModuleSession(ktModule, builtinTypes) {
|
||||
) : LLFirResolvableModuleSession(ktModule, dependencyTracker, builtinTypes) {
|
||||
init {
|
||||
checkIsValidKtModule(ktModule)
|
||||
}
|
||||
|
||||
+3
-1
@@ -5,6 +5,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.analysis.low.level.api.fir.sessions
|
||||
|
||||
import com.intellij.openapi.util.ModificationTracker
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.LLFirModuleResolveComponents
|
||||
import org.jetbrains.kotlin.analysis.project.structure.KtNotUnderContentRootModule
|
||||
import org.jetbrains.kotlin.fir.BuiltinTypes
|
||||
@@ -12,6 +13,7 @@ import org.jetbrains.kotlin.fir.PrivateSessionConstructor
|
||||
|
||||
internal class LLFirNonUnderContentRootResolvableModuleSession @PrivateSessionConstructor constructor(
|
||||
ktModule: KtNotUnderContentRootModule,
|
||||
dependencyTracker: ModificationTracker,
|
||||
override val moduleComponents: LLFirModuleResolveComponents,
|
||||
builtinTypes: BuiltinTypes,
|
||||
) : LLFirResolvableModuleSession(ktModule, builtinTypes)
|
||||
) : LLFirResolvableModuleSession(ktModule, dependencyTracker, builtinTypes)
|
||||
|
||||
+3
-1
@@ -5,6 +5,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.analysis.low.level.api.fir.sessions
|
||||
|
||||
import com.intellij.openapi.util.ModificationTracker
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.LLFirModuleResolveComponents
|
||||
import org.jetbrains.kotlin.analysis.project.structure.KtModule
|
||||
import org.jetbrains.kotlin.fir.BuiltinTypes
|
||||
@@ -14,8 +15,9 @@ import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
|
||||
|
||||
abstract class LLFirResolvableModuleSession(
|
||||
ktModule: KtModule,
|
||||
dependencyTracker: ModificationTracker,
|
||||
builtinTypes: BuiltinTypes
|
||||
) : LLFirModuleSession(ktModule, builtinTypes, Kind.Source) {
|
||||
) : LLFirModuleSession(ktModule, dependencyTracker, builtinTypes, Kind.Source) {
|
||||
internal abstract val moduleComponents: LLFirModuleResolveComponents
|
||||
|
||||
final override fun getScopeSession(): ScopeSession {
|
||||
|
||||
+3
-1
@@ -5,6 +5,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.analysis.low.level.api.fir.sessions
|
||||
|
||||
import com.intellij.openapi.util.ModificationTracker
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.LLFirModuleResolveComponents
|
||||
import org.jetbrains.kotlin.analysis.project.structure.KtScriptModule
|
||||
import org.jetbrains.kotlin.fir.BuiltinTypes
|
||||
@@ -12,6 +13,7 @@ import org.jetbrains.kotlin.fir.PrivateSessionConstructor
|
||||
|
||||
internal class LLFirScriptSession @PrivateSessionConstructor constructor(
|
||||
ktModule: KtScriptModule,
|
||||
dependencyTracker: ModificationTracker,
|
||||
override val moduleComponents: LLFirModuleResolveComponents,
|
||||
builtinTypes: BuiltinTypes
|
||||
) : LLFirResolvableModuleSession(ktModule, builtinTypes)
|
||||
) : LLFirResolvableModuleSession(ktModule, dependencyTracker, builtinTypes)
|
||||
+42
-13
@@ -7,9 +7,11 @@ package org.jetbrains.kotlin.analysis.low.level.api.fir.sessions
|
||||
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.util.ModificationTracker
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.BooleanModificationTracker
|
||||
import com.intellij.psi.PsiFile
|
||||
import com.intellij.psi.SmartPointerManager
|
||||
import org.jetbrains.kotlin.analysis.project.structure.*
|
||||
import org.jetbrains.kotlin.analysis.providers.KotlinModificationTrackerFactory
|
||||
import org.jetbrains.kotlin.analysis.providers.KtModuleStateTracker
|
||||
import org.jetbrains.kotlin.analysis.utils.trackers.CompositeModificationTracker
|
||||
import org.jetbrains.kotlin.fir.BuiltinTypes
|
||||
import org.jetbrains.kotlin.fir.FirElementWithResolvePhase
|
||||
@@ -22,16 +24,17 @@ import java.util.concurrent.atomic.AtomicBoolean
|
||||
@OptIn(PrivateSessionConstructor::class)
|
||||
abstract class LLFirSession(
|
||||
val ktModule: KtModule,
|
||||
dependencyTracker: ModificationTracker,
|
||||
override val builtinTypes: BuiltinTypes,
|
||||
kind: Kind
|
||||
) : FirSession(sessionProvider = null, kind) {
|
||||
abstract fun getScopeSession(): ScopeSession
|
||||
|
||||
val modificationTracker: ModificationTracker
|
||||
|
||||
private val initialModificationCount: Long
|
||||
private val isExplicitlyInvalidated = AtomicBoolean(false)
|
||||
|
||||
val modificationTracker: ModificationTracker
|
||||
|
||||
val project: Project
|
||||
get() = ktModule.project
|
||||
|
||||
@@ -41,24 +44,49 @@ abstract class LLFirSession(
|
||||
|
||||
val outOfBlockTracker = when (ktModule) {
|
||||
is KtSourceModule -> trackerFactory.createModuleWithoutDependenciesOutOfBlockModificationTracker(ktModule)
|
||||
is KtNotUnderContentRootModule -> ModificationTracker { ktModule.file?.modificationStamp ?: 0 }
|
||||
is KtScriptModule -> ModificationTracker { ktModule.file.modificationStamp }
|
||||
is KtScriptDependencyModule -> ModificationTracker { ktModule.file?.modificationStamp ?: 0 }
|
||||
else -> ModificationTracker.NEVER_CHANGED
|
||||
is KtNotUnderContentRootModule -> ktModule.file?.let(::FileModificationTracker)
|
||||
is KtScriptModule -> FileModificationTracker(ktModule.file)
|
||||
is KtScriptDependencyModule -> ktModule.file?.let(::FileModificationTracker)
|
||||
else -> null
|
||||
}
|
||||
|
||||
modificationTracker = CompositeModificationTracker.create(
|
||||
listOf(
|
||||
modificationTracker = CompositeModificationTracker.createFlattened(
|
||||
listOfNotNull(
|
||||
ExplicitInvalidationTracker(ktModule, isExplicitlyInvalidated),
|
||||
ModuleStateModificationTracker(ktModule, validityTracker),
|
||||
outOfBlockTracker,
|
||||
ModificationTracker { validityTracker.rootModificationCount },
|
||||
BooleanModificationTracker { validityTracker.isValid },
|
||||
BooleanModificationTracker { !isExplicitlyInvalidated.get() }
|
||||
dependencyTracker
|
||||
)
|
||||
)
|
||||
|
||||
initialModificationCount = modificationTracker.modificationCount
|
||||
}
|
||||
|
||||
private class ModuleStateModificationTracker(val module: KtModule, val tracker: KtModuleStateTracker) : ModificationTracker {
|
||||
override fun getModificationCount(): Long = tracker.rootModificationCount
|
||||
override fun toString(): String = "Module state tracker for module " + module.moduleDescription + "'"
|
||||
}
|
||||
|
||||
private class ExplicitInvalidationTracker(val module: KtModule, val isExplicitlyInvalidated: AtomicBoolean) : ModificationTracker {
|
||||
override fun getModificationCount(): Long = if (isExplicitlyInvalidated.get()) 1 else 0
|
||||
override fun toString(): String = "Explicit invalidation tracker for module '" + module.moduleDescription + "'"
|
||||
}
|
||||
|
||||
private class FileModificationTracker(file: PsiFile) : ModificationTracker {
|
||||
private val pointer = SmartPointerManager.getInstance(file.project).createSmartPsiElementPointer(file)
|
||||
|
||||
override fun getModificationCount(): Long {
|
||||
val file = pointer.element ?: return Long.MAX_VALUE
|
||||
return file.modificationStamp
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
val file = pointer.element ?: return "File tracker for a collected file"
|
||||
val virtualFile = file.virtualFile ?: return "File tracker for a non-physical file '" + file.name + "'"
|
||||
return "File tracker for path '" + virtualFile.path + "'"
|
||||
}
|
||||
}
|
||||
|
||||
fun invalidate() {
|
||||
isExplicitlyInvalidated.set(true)
|
||||
}
|
||||
@@ -69,9 +97,10 @@ abstract class LLFirSession(
|
||||
|
||||
abstract class LLFirModuleSession(
|
||||
ktModule: KtModule,
|
||||
dependencyTracker: ModificationTracker,
|
||||
builtinTypes: BuiltinTypes,
|
||||
kind: Kind
|
||||
) : LLFirSession(ktModule, builtinTypes, kind)
|
||||
) : LLFirSession(ktModule, dependencyTracker, builtinTypes, kind)
|
||||
|
||||
val FirElementWithResolvePhase.llFirSession: LLFirSession
|
||||
get() = moduleData.session as LLFirSession
|
||||
|
||||
+170
-99
@@ -6,8 +6,13 @@
|
||||
package org.jetbrains.kotlin.analysis.low.level.api.fir.sessions
|
||||
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.util.ModificationTracker
|
||||
import com.intellij.psi.search.GlobalSearchScope
|
||||
import com.intellij.psi.search.ProjectScope
|
||||
import com.intellij.psi.util.CachedValue
|
||||
import com.intellij.psi.util.CachedValueProvider
|
||||
import com.intellij.psi.util.CachedValuesManager
|
||||
import com.intellij.util.containers.CollectionFactory
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.LLFirGlobalResolveComponents
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.LLFirLazyDeclarationResolver
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.LLFirModuleResolveComponents
|
||||
@@ -18,6 +23,7 @@ import org.jetbrains.kotlin.analysis.project.structure.*
|
||||
import org.jetbrains.kotlin.analysis.providers.createAnnotationResolver
|
||||
import org.jetbrains.kotlin.analysis.providers.createDeclarationProvider
|
||||
import org.jetbrains.kotlin.analysis.providers.createPackageProvider
|
||||
import org.jetbrains.kotlin.analysis.utils.trackers.CompositeModificationTracker
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl
|
||||
@@ -33,6 +39,7 @@ import org.jetbrains.kotlin.fir.java.JavaSymbolProvider
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.*
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.impl.FirExtensionSyntheticFunctionInterfaceProvider
|
||||
import org.jetbrains.kotlin.fir.resolve.scopes.wrapScopeWithJvmMapped
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.FirDummyCompilerLazyDeclarationResolver
|
||||
import org.jetbrains.kotlin.fir.scopes.FirKotlinScopeProvider
|
||||
import org.jetbrains.kotlin.fir.session.*
|
||||
import org.jetbrains.kotlin.fir.symbols.FirLazyDeclarationResolver
|
||||
@@ -41,37 +48,84 @@ import org.jetbrains.kotlin.platform.jvm.JvmPlatforms
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.resolve.jvm.modules.JavaModuleResolver
|
||||
import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatformAnalyzerServices
|
||||
import java.util.concurrent.ConcurrentMap
|
||||
|
||||
@OptIn(PrivateSessionConstructor::class, SessionConfiguration::class)
|
||||
internal object LLFirSessionFactory {
|
||||
fun createSourcesSession(
|
||||
module: KtSourceModule,
|
||||
globalResolveComponents: LLFirGlobalResolveComponents,
|
||||
sessionsCache: MutableMap<KtModule, LLFirSession>
|
||||
): LLFirSourcesSession {
|
||||
sessionsCache[module]?.let { return it as LLFirSourcesSession }
|
||||
internal class LLFirSessionCache(private val project: Project) {
|
||||
companion object {
|
||||
fun getInstance(project: Project): LLFirSessionCache {
|
||||
return project.getService(LLFirSessionCache::class.java)
|
||||
}
|
||||
}
|
||||
|
||||
private val globalResolveComponents: LLFirGlobalResolveComponents
|
||||
get() = LLFirGlobalResolveComponents.getInstance(project)
|
||||
|
||||
private val sourceCache: ConcurrentMap<KtModule, CachedValue<LLFirSession>> = CollectionFactory.createConcurrentSoftValueMap()
|
||||
private val binaryCache: ConcurrentMap<KtModule, CachedValue<LLFirSession>> = CollectionFactory.createConcurrentSoftValueMap()
|
||||
|
||||
/**
|
||||
* Returns the existing session if found, or creates a new session and caches it.
|
||||
* Analyzable session will be returned for a library module.
|
||||
*/
|
||||
fun getSession(module: KtModule, preferBinary: Boolean = false): LLFirSession {
|
||||
if (module is KtBinaryModule && (preferBinary || module is KtSdkModule)) {
|
||||
return getCachedSession(module, binaryCache, ::createBinaryLibrarySession)
|
||||
}
|
||||
|
||||
return getCachedSession(module, sourceCache, ::createSession)
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a session without caching it.
|
||||
* Note that session dependencies are still cached.
|
||||
*/
|
||||
internal fun getSessionNoCaching(module: KtModule): LLFirSession {
|
||||
return createSession(module)
|
||||
}
|
||||
|
||||
private fun <T : KtModule> getCachedSession(
|
||||
module: T,
|
||||
storage: ConcurrentMap<KtModule, CachedValue<LLFirSession>>,
|
||||
factory: (T) -> LLFirSession
|
||||
): LLFirSession {
|
||||
checkCanceled()
|
||||
|
||||
val project = module.project
|
||||
return storage.computeIfAbsent(module) {
|
||||
CachedValuesManager.getManager(project).createCachedValue {
|
||||
val session = factory(module)
|
||||
CachedValueProvider.Result(session, session.modificationTracker)
|
||||
}
|
||||
}.value
|
||||
}
|
||||
|
||||
private fun createSession(module: KtModule): LLFirSession {
|
||||
return when (module) {
|
||||
is KtSourceModule -> createSourcesSession(module)
|
||||
is KtLibraryModule, is KtLibrarySourceModule -> createLibrarySession(module)
|
||||
is KtSdkModule -> createBinaryLibrarySession(module)
|
||||
is KtScriptModule -> createScriptSession(module)
|
||||
is KtNotUnderContentRootModule -> createNotUnderContentRootResolvableSession(module)
|
||||
else -> error("Unexpected module kind: ${module::class.simpleName}")
|
||||
}
|
||||
}
|
||||
|
||||
private fun createSourcesSession(module: KtSourceModule): LLFirSourcesSession {
|
||||
val platform = module.platform
|
||||
val builtinsSession = LLFirBuiltinsSessionFactory.getInstance(project).getBuiltinsSession(platform)
|
||||
val languageVersionSettings = wrapLanguageVersionSettings(module.languageVersionSettings)
|
||||
|
||||
val scopeProvider = FirKotlinScopeProvider(::wrapScopeWithJvmMapped)
|
||||
|
||||
val components = LLFirModuleResolveComponents(module, globalResolveComponents, scopeProvider)
|
||||
|
||||
val contentScope = module.contentScope
|
||||
val session = LLFirSourcesSession(
|
||||
module,
|
||||
components,
|
||||
builtinsSession.builtinTypes
|
||||
)
|
||||
sessionsCache[module] = session
|
||||
val dependencies = collectSourceModuleDependencies(module)
|
||||
val dependencyTracker = createSourceModuleDependencyTracker(module, dependencies)
|
||||
val session = LLFirSourcesSession(module, dependencyTracker, components, builtinsSession.builtinTypes)
|
||||
components.session = session
|
||||
|
||||
return session.apply session@{
|
||||
val moduleData = LLFirModuleData(module).apply { bindSession(this@session) }
|
||||
val moduleData = createModuleData(session)
|
||||
|
||||
return session.apply {
|
||||
registerModuleData(moduleData)
|
||||
register(FirKotlinScopeProvider::class, scopeProvider)
|
||||
|
||||
@@ -81,6 +135,8 @@ internal object LLFirSessionFactory {
|
||||
registerResolveComponents()
|
||||
registerJavaSpecificResolveComponents()
|
||||
|
||||
val contentScope = module.contentScope
|
||||
|
||||
val provider = LLFirProvider(
|
||||
this,
|
||||
components,
|
||||
@@ -102,8 +158,7 @@ internal object LLFirSessionFactory {
|
||||
}
|
||||
|
||||
val dependencyProvider = LLFirDependentModuleProvidersBySessions(this) {
|
||||
processSourceDependencies(module, sessionsCache, globalResolveComponents)
|
||||
|
||||
addAll(dependencies)
|
||||
add(builtinsSession)
|
||||
}
|
||||
|
||||
@@ -134,36 +189,27 @@ internal object LLFirSessionFactory {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fun createLibraryOrLibrarySourceResolvableSession(
|
||||
module: KtModule,
|
||||
globalComponents: LLFirGlobalResolveComponents,
|
||||
builtinSession: LLFirBuiltinsAndCloneableSession,
|
||||
sessionsCache: MutableMap<KtModule, LLFirSession>,
|
||||
languageVersionSettings: LanguageVersionSettings = LanguageVersionSettingsImpl.DEFAULT
|
||||
): LLFirLibraryOrLibrarySourceResolvableModuleSession {
|
||||
LLFirLibraryOrLibrarySourceResolvableModuleSession.checkIsValidKtModule(module)
|
||||
sessionsCache[module]?.let { return it as LLFirLibraryOrLibrarySourceResolvableModuleSession }
|
||||
checkCanceled()
|
||||
|
||||
val project = module.project
|
||||
|
||||
private fun createLibrarySession(module: KtModule): LLFirLibraryOrLibrarySourceResolvableModuleSession {
|
||||
val libraryModule = when (module) {
|
||||
is KtLibraryModule -> module
|
||||
is KtLibrarySourceModule -> module.binaryLibrary
|
||||
else -> error("Unexpected module ${module::class.simpleName}")
|
||||
}
|
||||
|
||||
val scopeProvider = FirKotlinScopeProvider()
|
||||
val components = LLFirModuleResolveComponents(module, globalComponents, scopeProvider)
|
||||
val platform = module.platform
|
||||
val builtinsSession = LLFirBuiltinsSessionFactory.getInstance(project).getBuiltinsSession(platform)
|
||||
val languageVersionSettings = LanguageVersionSettingsImpl.DEFAULT
|
||||
|
||||
val contentScope = module.contentScope
|
||||
val session = LLFirLibraryOrLibrarySourceResolvableModuleSession(module, components, builtinSession.builtinTypes)
|
||||
sessionsCache[module] = session
|
||||
val scopeProvider = FirKotlinScopeProvider()
|
||||
val components = LLFirModuleResolveComponents(module, globalResolveComponents, scopeProvider)
|
||||
|
||||
val dependencyTracker = builtinsSession.modificationTracker
|
||||
val session = LLFirLibraryOrLibrarySourceResolvableModuleSession(module, dependencyTracker, components, builtinsSession.builtinTypes)
|
||||
components.session = session
|
||||
|
||||
return session.apply session@{
|
||||
val moduleData = LLFirModuleData(module).apply { bindSession(this@session) }
|
||||
val moduleData = createModuleData(session)
|
||||
|
||||
return session.apply {
|
||||
registerModuleData(moduleData)
|
||||
register(FirKotlinScopeProvider::class, scopeProvider)
|
||||
|
||||
@@ -174,6 +220,8 @@ internal object LLFirSessionFactory {
|
||||
registerResolveComponents()
|
||||
registerJavaSpecificResolveComponents()
|
||||
|
||||
val contentScope = module.contentScope
|
||||
|
||||
val provider = LLFirProvider(
|
||||
this,
|
||||
components,
|
||||
@@ -188,11 +236,11 @@ internal object LLFirSessionFactory {
|
||||
|
||||
// We need FirRegisteredPluginAnnotations during extensions' registration process
|
||||
val annotationsResolver = project.createAnnotationResolver(contentScope)
|
||||
register(FirRegisteredPluginAnnotations::class, LLFirIdeRegisteredPluginAnnotations(this@session, annotationsResolver))
|
||||
register(FirRegisteredPluginAnnotations::class, LLFirIdeRegisteredPluginAnnotations(this, annotationsResolver))
|
||||
register(FirPredicateBasedProvider::class, FirEmptyPredicateBasedProvider)
|
||||
|
||||
val dependencyProvider = LLFirDependentModuleProvidersByProviders(this) {
|
||||
add(builtinSession.symbolProvider)
|
||||
add(builtinsSession.symbolProvider)
|
||||
|
||||
// Script dependencies are self-contained and should not depend on other libraries
|
||||
if (module !is KtScriptDependencyModule) {
|
||||
@@ -231,29 +279,64 @@ internal object LLFirSessionFactory {
|
||||
}
|
||||
}
|
||||
|
||||
fun createScriptSession(
|
||||
module: KtScriptModule,
|
||||
sessionsCache: MutableMap<KtModule, LLFirSession>
|
||||
): LLFirScriptSession {
|
||||
sessionsCache[module]?.let { return it as LLFirScriptSession }
|
||||
checkCanceled()
|
||||
private fun createBinaryLibrarySession(module: KtBinaryModule): LLFirLibrarySession {
|
||||
val platform = module.platform
|
||||
val builtinsSession = LLFirBuiltinsSessionFactory.getInstance(project).getBuiltinsSession(platform)
|
||||
|
||||
val project = module.project
|
||||
val dependencyTracker = ModificationTracker.NEVER_CHANGED
|
||||
val session = LLFirLibrarySession(module, dependencyTracker, builtinsSession.builtinTypes)
|
||||
|
||||
val moduleData = createModuleData(session)
|
||||
|
||||
return session.apply {
|
||||
registerModuleData(moduleData)
|
||||
registerIdeComponents(project)
|
||||
register(FirLazyDeclarationResolver::class, FirDummyCompilerLazyDeclarationResolver)
|
||||
registerCommonComponents(LanguageVersionSettingsImpl.DEFAULT/*TODO*/)
|
||||
registerCommonComponentsAfterExtensionsAreConfigured()
|
||||
registerCommonJavaComponents(JavaModuleResolver.getInstance(project))
|
||||
registerJavaSpecificResolveComponents()
|
||||
|
||||
val kotlinScopeProvider = FirKotlinScopeProvider(::wrapScopeWithJvmMapped)
|
||||
register(FirKotlinScopeProvider::class, kotlinScopeProvider)
|
||||
|
||||
val symbolProvider = LLFirLibraryProviderFactory.createLibraryProvidersForScope(
|
||||
this,
|
||||
moduleData,
|
||||
kotlinScopeProvider,
|
||||
project,
|
||||
builtinTypes,
|
||||
module.contentScope,
|
||||
builtinsSession.symbolProvider
|
||||
)
|
||||
|
||||
register(LLFirFirClassByPsiClassProvider::class, LLFirFirClassByPsiClassProvider(this))
|
||||
register(FirProvider::class, LLFirLibrarySessionProvider(symbolProvider))
|
||||
register(FirSymbolProvider::class, symbolProvider)
|
||||
register(FirJvmTypeMapper::class, FirJvmTypeMapper(this))
|
||||
|
||||
LLFirSessionConfigurator.configure(this)
|
||||
}
|
||||
}
|
||||
|
||||
private fun createScriptSession(module: KtScriptModule): LLFirScriptSession {
|
||||
val platform = module.platform
|
||||
val builtinsSession = LLFirBuiltinsSessionFactory.getInstance(project).getBuiltinsSession(platform)
|
||||
val languageVersionSettings = wrapLanguageVersionSettings(module.languageVersionSettings)
|
||||
val scopeProvider = FirKotlinScopeProvider(::wrapScopeWithJvmMapped)
|
||||
val globalResolveComponents = LLFirGlobalResolveComponents(project)
|
||||
|
||||
val components = LLFirModuleResolveComponents(module, globalResolveComponents, scopeProvider)
|
||||
val contentScope = module.contentScope
|
||||
|
||||
val session = LLFirScriptSession(module, components, builtinsSession.builtinTypes)
|
||||
sessionsCache[module] = session
|
||||
val dependencies = collectSourceModuleDependencies(module)
|
||||
val dependencyTracker = createSourceModuleDependencyTracker(module, dependencies)
|
||||
|
||||
val session = LLFirScriptSession(module, dependencyTracker, components, builtinsSession.builtinTypes)
|
||||
components.session = session
|
||||
|
||||
return session.apply session@{
|
||||
val moduleData = LLFirModuleData(module).apply { bindSession(this@session) }
|
||||
val moduleData = createModuleData(session)
|
||||
|
||||
return session.apply {
|
||||
registerModuleData(moduleData)
|
||||
register(FirKotlinScopeProvider::class, scopeProvider)
|
||||
|
||||
@@ -276,12 +359,7 @@ internal object LLFirSessionFactory {
|
||||
register(FirLazyDeclarationResolver::class, LLFirLazyDeclarationResolver())
|
||||
|
||||
val dependencyProvider = LLFirDependentModuleProvidersBySessions(this) {
|
||||
processSourceDependencies(
|
||||
module,
|
||||
sessionsCache,
|
||||
globalResolveComponents
|
||||
)
|
||||
|
||||
addAll(dependencies)
|
||||
add(builtinsSession)
|
||||
}
|
||||
|
||||
@@ -309,27 +387,19 @@ internal object LLFirSessionFactory {
|
||||
}
|
||||
}
|
||||
|
||||
fun createNotUnderContentRootResolvableSession(
|
||||
module: KtNotUnderContentRootModule,
|
||||
sessionsCache: MutableMap<KtModule, LLFirSession>
|
||||
): LLFirNonUnderContentRootResolvableModuleSession {
|
||||
sessionsCache[module]?.let { return it as LLFirNonUnderContentRootResolvableModuleSession }
|
||||
checkCanceled()
|
||||
|
||||
val project = module.project
|
||||
private fun createNotUnderContentRootResolvableSession(module: KtNotUnderContentRootModule): LLFirNonUnderContentRootResolvableModuleSession {
|
||||
val builtinsSession = LLFirBuiltinsSessionFactory.getInstance(project).getBuiltinsSession(JvmPlatforms.unspecifiedJvmPlatform)
|
||||
val languageVersionSettings = LanguageVersionSettingsImpl.DEFAULT
|
||||
val scopeProvider = FirKotlinScopeProvider(::wrapScopeWithJvmMapped)
|
||||
val globalResolveComponents = LLFirGlobalResolveComponents(project)
|
||||
val components = LLFirModuleResolveComponents(module, globalResolveComponents, scopeProvider)
|
||||
val contentScope = module.contentScope
|
||||
|
||||
val session = LLFirNonUnderContentRootResolvableModuleSession(module, components, builtinsSession.builtinTypes)
|
||||
sessionsCache[module] = session
|
||||
val dependencyTracker = builtinsSession.modificationTracker
|
||||
val session = LLFirNonUnderContentRootResolvableModuleSession(module, dependencyTracker, components, builtinsSession.builtinTypes)
|
||||
components.session = session
|
||||
|
||||
return session.apply session@{
|
||||
val moduleData = LLFirModuleData(module).apply { bindSession(this@session) }
|
||||
val moduleData = createModuleData(session)
|
||||
|
||||
return session.apply {
|
||||
registerModuleData(moduleData)
|
||||
register(FirKotlinScopeProvider::class, scopeProvider)
|
||||
|
||||
@@ -346,7 +416,7 @@ internal object LLFirSessionFactory {
|
||||
this,
|
||||
components,
|
||||
if (ktFile != null) FileBasedKotlinDeclarationProvider(ktFile) else EmptyKotlinDeclarationProvider,
|
||||
project.createPackageProvider(contentScope),
|
||||
project.createPackageProvider(module.contentScope),
|
||||
canContainKotlinPackage = true,
|
||||
)
|
||||
|
||||
@@ -395,45 +465,46 @@ internal object LLFirSessionFactory {
|
||||
}
|
||||
}
|
||||
|
||||
private fun MutableList<LLFirSession>.processSourceDependencies(
|
||||
module: KtModule,
|
||||
sessionsCache: MutableMap<KtModule, LLFirSession>,
|
||||
globalResolveComponents: LLFirGlobalResolveComponents
|
||||
) {
|
||||
val project = module.project
|
||||
private fun collectSourceModuleDependencies(module: KtModule): List<LLFirSession> {
|
||||
val dependencies = mutableListOf<LLFirSession>()
|
||||
|
||||
fun getOrCreateSessionForDependency(dependency: KtModule): LLFirSession? = when (dependency) {
|
||||
is KtBuiltinsModule -> {
|
||||
// Built-ins are already added
|
||||
null
|
||||
}
|
||||
|
||||
is KtBinaryModule -> {
|
||||
LLFirLibrarySessionFactory.getInstance(project).getLibrarySession(dependency, sessionsCache)
|
||||
}
|
||||
|
||||
is KtSourceModule -> {
|
||||
createSourcesSession(dependency, globalResolveComponents, sessionsCache)
|
||||
}
|
||||
is KtBuiltinsModule -> null // Built-ins are already added
|
||||
is KtBinaryModule -> getSession(dependency, preferBinary = true)
|
||||
is KtSourceModule -> getSession(dependency)
|
||||
|
||||
is KtScriptModule,
|
||||
is KtScriptDependencyModule,
|
||||
is KtNotUnderContentRootModule,
|
||||
is KtLibrarySourceModule -> {
|
||||
error("Module $module cannot depend on ${dependency::class}: $dependency")
|
||||
}
|
||||
is KtLibrarySourceModule -> error("Module $module cannot depend on ${dependency::class}: $dependency")
|
||||
}
|
||||
|
||||
module.directRegularDependencies.mapNotNullTo(this@processSourceDependencies, ::getOrCreateSessionForDependency)
|
||||
module.directRegularDependencies.mapNotNullTo(dependencies, ::getOrCreateSessionForDependency)
|
||||
|
||||
// The dependency provider needs to have access to all direct and indirect `dependsOn` dependencies, as `dependsOn`
|
||||
// dependencies are transitive.
|
||||
val directRegularDependenciesSet = module.directRegularDependencies.toSet()
|
||||
module.transitiveDependsOnDependencies.forEach { dependency ->
|
||||
if (dependency !in directRegularDependenciesSet) {
|
||||
getOrCreateSessionForDependency(dependency)?.let(this::add)
|
||||
getOrCreateSessionForDependency(dependency)?.let(dependencies::add)
|
||||
}
|
||||
}
|
||||
|
||||
return dependencies
|
||||
}
|
||||
|
||||
private fun createSourceModuleDependencyTracker(module: KtModule, exposedDependencies: List<LLFirSession>): ModificationTracker {
|
||||
val friendDependencies = module.directFriendDependencies
|
||||
val trackers = ArrayList<ModificationTracker>(exposedDependencies.size + friendDependencies.size)
|
||||
|
||||
exposedDependencies.forEach { trackers += it.modificationTracker }
|
||||
friendDependencies.forEach { trackers += getSession(it).modificationTracker }
|
||||
|
||||
return CompositeModificationTracker.createFlattened(trackers)
|
||||
}
|
||||
|
||||
private fun createModuleData(session: LLFirSession): LLFirModuleData {
|
||||
return LLFirModuleData(session.ktModule).apply { bindSession(session) }
|
||||
}
|
||||
}
|
||||
|
||||
-70
@@ -1,70 +0,0 @@
|
||||
/*
|
||||
* 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.low.level.api.fir.sessions
|
||||
|
||||
import com.intellij.openapi.project.Project
|
||||
import org.jetbrains.annotations.TestOnly
|
||||
import org.jetbrains.kotlin.analysis.api.impl.barebone.annotations.Immutable
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.project.structure.LLFirModuleData
|
||||
import org.jetbrains.kotlin.analysis.project.structure.KtModule
|
||||
import org.jetbrains.kotlin.analysis.utils.errors.requireIsInstance
|
||||
import org.jetbrains.kotlin.fir.FirModuleData
|
||||
import org.jetbrains.kotlin.fir.FirSessionProvider
|
||||
import java.lang.ref.WeakReference
|
||||
|
||||
@Immutable
|
||||
class LLFirSessionProvider internal constructor(
|
||||
val project: Project,
|
||||
internal val rootModuleSession: LLFirResolvableModuleSession,
|
||||
private val ktModuleToSession: KtModuleToSessionMapping
|
||||
) : FirSessionProvider() {
|
||||
override fun getSession(moduleData: FirModuleData): LLFirSession {
|
||||
requireIsInstance<LLFirModuleData>(moduleData)
|
||||
return getResolvableSession(moduleData.ktModule)
|
||||
}
|
||||
|
||||
fun getSession(module: KtModule): LLFirSession =
|
||||
ktModuleToSession.getSession(module)
|
||||
|
||||
fun getResolvableSession(module: KtModule): LLFirResolvableModuleSession =
|
||||
ktModuleToSession.getSession(module) as LLFirResolvableModuleSession
|
||||
|
||||
@get:TestOnly
|
||||
val allSessions: Collection<LLFirSession>
|
||||
get() = ktModuleToSession.getAllSessions()
|
||||
}
|
||||
|
||||
internal abstract class KtModuleToSessionMapping {
|
||||
abstract fun getSession(module: KtModule): LLFirSession
|
||||
|
||||
@TestOnly
|
||||
abstract fun getAllSessions(): Collection<LLFirSession>
|
||||
}
|
||||
|
||||
internal class KtModuleToSessionMappingByMapImpl(
|
||||
private val map: Map<KtModule, LLFirSession>
|
||||
) : KtModuleToSessionMapping() {
|
||||
override fun getSession(module: KtModule): LLFirSession =
|
||||
map.getValue(module)
|
||||
|
||||
override fun getAllSessions(): Collection<LLFirSession> =
|
||||
map.values
|
||||
}
|
||||
|
||||
internal class KtModuleToSessionMappingByWeakValueMapImpl(
|
||||
initialMap: Map<KtModule, LLFirSession>
|
||||
) : KtModuleToSessionMapping() {
|
||||
private val softValuesMap = initialMap.entries.associate { (key, value) -> key to WeakReference(value) }
|
||||
|
||||
override fun getSession(module: KtModule): LLFirSession {
|
||||
val softReference = softValuesMap.getValue(module)
|
||||
return softReference.get()
|
||||
?: error("soft reference for $module was invalidated")
|
||||
}
|
||||
|
||||
override fun getAllSessions(): Collection<LLFirSession> =
|
||||
softValuesMap.keys.map { getSession(it) }
|
||||
}
|
||||
-144
@@ -1,144 +0,0 @@
|
||||
/*
|
||||
* 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.low.level.api.fir.sessions
|
||||
|
||||
import com.intellij.openapi.project.Project
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.LLFirGlobalResolveComponents
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.project.structure.LLFirBuiltinsSessionFactory
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.addValueFor
|
||||
import org.jetbrains.kotlin.analysis.project.structure.*
|
||||
import java.lang.ref.SoftReference
|
||||
|
||||
class LLFirSessionProviderStorage(val project: Project) {
|
||||
private val sourceAsUseSiteSessionCache = LLFirSessionsCache()
|
||||
private val libraryAsUseSiteSessionCache = LLFirSessionsCache()
|
||||
private val notUnderContentRootSessionCache = LLFirSessionsCache()
|
||||
|
||||
private val builtInsSessionFactory = LLFirBuiltinsSessionFactory.getInstance(project)
|
||||
|
||||
private val globalComponents = LLFirGlobalResolveComponents(project)
|
||||
|
||||
fun getSessionProvider(useSiteKtModule: KtModule): LLFirSessionProvider = when (useSiteKtModule) {
|
||||
is KtSourceModule -> {
|
||||
createSessionProviderForSourceSession(useSiteKtModule)
|
||||
}
|
||||
|
||||
is KtLibraryModule, is KtLibrarySourceModule -> {
|
||||
createSessionProviderForLibraryOrLibrarySource(useSiteKtModule)
|
||||
}
|
||||
|
||||
is KtScriptModule -> {
|
||||
createSessionProviderForScriptSession(useSiteKtModule)
|
||||
}
|
||||
|
||||
is KtNotUnderContentRootModule -> {
|
||||
createSessionProviderForNotUnderContentRootSession(useSiteKtModule)
|
||||
}
|
||||
|
||||
else -> error("Unexpected ${useSiteKtModule::class.simpleName}")
|
||||
}
|
||||
|
||||
private fun createSessionProviderForSourceSession(useSiteKtModule: KtSourceModule): LLFirSessionProvider {
|
||||
val (sessions, session) = sourceAsUseSiteSessionCache.withMappings { mappings ->
|
||||
val sessions = mutableMapOf<KtModule, LLFirSession>().apply { putAll(mappings) }
|
||||
val session = LLFirSessionFactory.createSourcesSession(useSiteKtModule, globalComponents, sessions)
|
||||
sessions to session
|
||||
}
|
||||
return LLFirSessionProvider(project, session, KtModuleToSessionMappingByWeakValueMapImpl(sessions))
|
||||
}
|
||||
|
||||
|
||||
private fun createSessionProviderForLibraryOrLibrarySource(useSiteKtModule: KtModule): LLFirSessionProvider {
|
||||
val (sessions, session) = libraryAsUseSiteSessionCache.withMappings { mappings ->
|
||||
val sessions = mutableMapOf<KtModule, LLFirSession>().apply { putAll(mappings) }
|
||||
val session = LLFirSessionFactory.createLibraryOrLibrarySourceResolvableSession(
|
||||
useSiteKtModule,
|
||||
globalComponents,
|
||||
builtInsSessionFactory.getBuiltinsSession(useSiteKtModule.platform),
|
||||
sessions
|
||||
)
|
||||
sessions to session
|
||||
}
|
||||
return LLFirSessionProvider(project, session, KtModuleToSessionMappingByWeakValueMapImpl(sessions))
|
||||
}
|
||||
|
||||
private fun createSessionProviderForScriptSession(useSiteKtModule: KtScriptModule): LLFirSessionProvider {
|
||||
val (sessions, session) = sourceAsUseSiteSessionCache.withMappings { mappings ->
|
||||
val sessions = mutableMapOf<KtModule, LLFirSession>().apply { putAll(mappings) }
|
||||
val session = LLFirSessionFactory.createScriptSession(
|
||||
useSiteKtModule,
|
||||
sessions
|
||||
)
|
||||
sessions to session
|
||||
}
|
||||
return LLFirSessionProvider(project, session, KtModuleToSessionMappingByWeakValueMapImpl(sessions))
|
||||
}
|
||||
|
||||
private fun createSessionProviderForNotUnderContentRootSession(useSiteKtModule: KtNotUnderContentRootModule): LLFirSessionProvider {
|
||||
val (sessions, session) = notUnderContentRootSessionCache.withMappings { mappings ->
|
||||
val sessions = mutableMapOf<KtModule, LLFirSession>().apply { putAll(mappings) }
|
||||
val session = LLFirSessionFactory.createNotUnderContentRootResolvableSession(useSiteKtModule, sessions)
|
||||
sessions to session
|
||||
}
|
||||
return LLFirSessionProvider(project, session, KtModuleToSessionMappingByWeakValueMapImpl(sessions))
|
||||
}
|
||||
}
|
||||
|
||||
private class LLFirSessionsCache {
|
||||
@Volatile
|
||||
private var mappings: Map<KtModule, SoftReference<LLFirSession>> = emptyMap()
|
||||
|
||||
inline fun <R> withMappings(
|
||||
action: (Map<KtModule, LLFirSession>) -> Pair<Map<KtModule, LLFirSession>, R>
|
||||
): Pair<Map<KtModule, LLFirSession>, R> {
|
||||
val (newMappings, result) = action(getSessions().mapValues { it.value })
|
||||
mappings = newMappings.mapValues { SoftReference(it.value) }
|
||||
return newMappings to result
|
||||
}
|
||||
|
||||
private fun getSessions(): Map<KtModule, LLFirSession> = buildMap {
|
||||
// Initially, all sessions are considered to be valid ('true').
|
||||
val sessions = LinkedHashMap<LLFirSession, Boolean>().apply {
|
||||
for (sessionRef in mappings.values) {
|
||||
val session = sessionRef.get() ?: continue
|
||||
put(session, true)
|
||||
}
|
||||
}
|
||||
|
||||
val reversedDependencies = buildMap {
|
||||
for (session in sessions.keys) {
|
||||
if (session.isValid) {
|
||||
val module = session.ktModule
|
||||
for (dependency in module.directRegularDependencies) {
|
||||
addValueFor(dependency, module)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun invalidateRecursively(session: LLFirSession) {
|
||||
// Invalidate all dependent sessions only if we didn't that before
|
||||
if (sessions.put(session, false) == true) {
|
||||
for (dependentModule in reversedDependencies[session.ktModule].orEmpty()) {
|
||||
val dependentSession = mappings[dependentModule]?.get() ?: continue
|
||||
invalidateRecursively(dependentSession)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (session in sessions.keys) {
|
||||
if (session.isValid) continue
|
||||
invalidateRecursively(session)
|
||||
}
|
||||
|
||||
return buildMap {
|
||||
for ((session, isValid) in sessions) {
|
||||
if (!isValid) continue
|
||||
put(session.ktModule, session)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+3
-1
@@ -5,6 +5,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.analysis.low.level.api.fir.sessions
|
||||
|
||||
import com.intellij.openapi.util.ModificationTracker
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.LLFirModuleResolveComponents
|
||||
import org.jetbrains.kotlin.analysis.project.structure.KtSourceModule
|
||||
import org.jetbrains.kotlin.fir.BuiltinTypes
|
||||
@@ -12,6 +13,7 @@ import org.jetbrains.kotlin.fir.PrivateSessionConstructor
|
||||
|
||||
internal class LLFirSourcesSession @PrivateSessionConstructor constructor(
|
||||
ktModule: KtSourceModule,
|
||||
dependencyTracker: ModificationTracker,
|
||||
override val moduleComponents: LLFirModuleResolveComponents,
|
||||
builtinTypes: BuiltinTypes,
|
||||
) : LLFirResolvableModuleSession(ktModule, builtinTypes)
|
||||
) : LLFirResolvableModuleSession(ktModule, dependencyTracker, builtinTypes)
|
||||
|
||||
+4
-13
@@ -5,23 +5,17 @@
|
||||
|
||||
package org.jetbrains.kotlin.analysis.low.level.api.fir.state
|
||||
|
||||
import com.intellij.openapi.project.Project
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.LLFirGlobalResolveComponents
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.DiagnosticCheckerFilter
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.LLFirSessionProvider
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.LLFirLibraryOrLibrarySourceResolvableModuleSession
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.LLFirSession
|
||||
import org.jetbrains.kotlin.analysis.project.structure.KtModule
|
||||
import org.jetbrains.kotlin.diagnostics.KtPsiDiagnostic
|
||||
import org.jetbrains.kotlin.psi.KtElement
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
|
||||
|
||||
internal class LLFirLibraryOrLibrarySourceResolvableResolveSession(
|
||||
override val globalComponents: LLFirGlobalResolveComponents,
|
||||
override val project: Project,
|
||||
override val useSiteKtModule: KtModule,
|
||||
sessionProvider: LLFirSessionProvider,
|
||||
) : LLFirResolvableResolveSession(sessionProvider) {
|
||||
useSiteFirSession: LLFirSession
|
||||
) : LLFirResolvableResolveSession(useSiteFirSession) {
|
||||
override fun getDiagnostics(element: KtElement, filter: DiagnosticCheckerFilter): List<KtPsiDiagnostic> =
|
||||
emptyList()
|
||||
|
||||
@@ -30,10 +24,7 @@ internal class LLFirLibraryOrLibrarySourceResolvableResolveSession(
|
||||
|
||||
override fun getModuleKind(module: KtModule): ModuleKind {
|
||||
LLFirLibraryOrLibrarySourceResolvableModuleSession.checkIsValidKtModule(module)
|
||||
return when {
|
||||
module == this.useSiteKtModule -> ModuleKind.RESOLVABLE_MODULE
|
||||
else -> ModuleKind.BINARY_MODULE
|
||||
}
|
||||
return if (module == useSiteKtModule) ModuleKind.RESOLVABLE_MODULE else ModuleKind.BINARY_MODULE
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+3
-8
@@ -5,21 +5,16 @@
|
||||
|
||||
package org.jetbrains.kotlin.analysis.low.level.api.fir.state
|
||||
|
||||
import com.intellij.openapi.project.Project
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.LLFirGlobalResolveComponents
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.DiagnosticCheckerFilter
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.LLFirSessionProvider
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.LLFirSession
|
||||
import org.jetbrains.kotlin.analysis.project.structure.KtModule
|
||||
import org.jetbrains.kotlin.diagnostics.KtPsiDiagnostic
|
||||
import org.jetbrains.kotlin.psi.KtElement
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
|
||||
internal class LLFirNotUnderContentRootResolveSession(
|
||||
override val globalComponents: LLFirGlobalResolveComponents,
|
||||
override val project: Project,
|
||||
override val useSiteKtModule: KtModule,
|
||||
sessionProvider: LLFirSessionProvider,
|
||||
) : LLFirResolvableResolveSession(sessionProvider) {
|
||||
useSiteFirSession: LLFirSession
|
||||
) : LLFirResolvableResolveSession(useSiteFirSession) {
|
||||
override fun getDiagnostics(element: KtElement, filter: DiagnosticCheckerFilter): List<KtPsiDiagnostic> =
|
||||
emptyList()
|
||||
|
||||
|
||||
+24
-9
@@ -5,14 +5,15 @@
|
||||
|
||||
package org.jetbrains.kotlin.analysis.low.level.api.fir.state
|
||||
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.LLFirGlobalResolveComponents
|
||||
import com.intellij.openapi.diagnostic.Logger
|
||||
import com.intellij.openapi.project.Project
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.LLFirModuleResolveComponents
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.LLFirResolveSession
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.element.builder.FirTowerContextProvider
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.element.builder.getNonLocalContainingOrThisDeclaration
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.LLFirResolvableModuleSession
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.LLFirSession
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.LLFirSessionProvider
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.LLFirSessionCache
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.FirDeclarationForCompiledElementSearcher
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.errorWithFirSpecificEntries
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.findSourceNonLocalFirDeclaration
|
||||
@@ -40,18 +41,32 @@ import org.jetbrains.kotlin.psi.KtElement
|
||||
import org.jetbrains.kotlin.psi.KtExpression
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
|
||||
@Suppress("PrivatePropertyName")
|
||||
private val LOG = Logger.getInstance(LLFirResolvableResolveSession::class.java)
|
||||
|
||||
internal abstract class LLFirResolvableResolveSession(
|
||||
private val sessionProvider: LLFirSessionProvider,
|
||||
final override val useSiteFirSession: LLFirSession
|
||||
) : LLFirResolveSession() {
|
||||
abstract val globalComponents: LLFirGlobalResolveComponents
|
||||
final override val useSiteKtModule: KtModule
|
||||
get() = useSiteFirSession.ktModule
|
||||
|
||||
final override val useSiteFirSession = sessionProvider.rootModuleSession
|
||||
final override val project: Project
|
||||
get() = useSiteKtModule.project
|
||||
|
||||
override fun getSessionFor(module: KtModule): LLFirSession =
|
||||
sessionProvider.getSession(module)
|
||||
override fun getSessionFor(module: KtModule): LLFirSession {
|
||||
LOG.assertTrue(useSiteFirSession.isValid, "Use-site session is invalid")
|
||||
|
||||
protected open fun getResolvableSessionFor(module: KtModule): LLFirResolvableModuleSession =
|
||||
sessionProvider.getResolvableSession(module)
|
||||
if (module == useSiteFirSession.ktModule) {
|
||||
return useSiteFirSession
|
||||
}
|
||||
|
||||
val cache = LLFirSessionCache.getInstance(module.project)
|
||||
return cache.getSession(module, preferBinary = true)
|
||||
}
|
||||
|
||||
protected open fun getResolvableSessionFor(module: KtModule): LLFirResolvableModuleSession {
|
||||
return getSessionFor(module) as LLFirResolvableModuleSession
|
||||
}
|
||||
|
||||
override fun getScopeSessionFor(firSession: FirSession): ScopeSession {
|
||||
requireIsInstance<LLFirSession>(firSession)
|
||||
|
||||
+2
-40
@@ -5,12 +5,6 @@
|
||||
|
||||
package org.jetbrains.kotlin.analysis.low.level.api.fir.state
|
||||
|
||||
import com.intellij.openapi.components.ServiceManager
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.util.containers.CollectionFactory
|
||||
import com.intellij.util.containers.FactoryMap
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.LLFirGlobalResolveComponents
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.LLFirResolveSessionService
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.DiagnosticCheckerFilter
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.*
|
||||
import org.jetbrains.kotlin.analysis.project.structure.*
|
||||
@@ -20,40 +14,8 @@ import org.jetbrains.kotlin.psi.KtElement
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
|
||||
internal class LLFirScriptResolveSession(
|
||||
override val globalComponents: LLFirGlobalResolveComponents,
|
||||
override val project: Project,
|
||||
override val useSiteKtModule: KtModule,
|
||||
sessionProvider: LLFirSessionProvider
|
||||
) : LLFirResolvableResolveSession(sessionProvider) {
|
||||
private val dependencyCache: Map<KtModule, LLFirSession> =
|
||||
FactoryMap.createMap(::createDependencySession, CollectionFactory::createConcurrentSoftValueMap)
|
||||
|
||||
private fun createDependencySession(module: KtModule): LLFirSession {
|
||||
when (module) {
|
||||
is KtScriptDependencyModule -> {
|
||||
val resolveSessionService = ServiceManager.getService(project, LLFirResolveSessionService::class.java)
|
||||
return resolveSessionService.getFirResolveSession(module).useSiteFirSession
|
||||
}
|
||||
else -> error("Unsupported script dependency session type: ${module.javaClass.name}")
|
||||
}
|
||||
}
|
||||
|
||||
override fun getSessionFor(module: KtModule): LLFirSession {
|
||||
if (module is KtScriptDependencyModule) {
|
||||
return dependencyCache.getValue(module)
|
||||
}
|
||||
|
||||
return super.getSessionFor(module)
|
||||
}
|
||||
|
||||
override fun getResolvableSessionFor(module: KtModule): LLFirResolvableModuleSession {
|
||||
if (module is KtScriptDependencyModule && module is KtLibrarySourceModule) {
|
||||
return dependencyCache[module] as LLFirResolvableModuleSession
|
||||
}
|
||||
|
||||
return super.getResolvableSessionFor(module)
|
||||
}
|
||||
|
||||
useSiteFirSession: LLFirSession
|
||||
) : LLFirResolvableResolveSession(useSiteFirSession) {
|
||||
override fun getDiagnostics(element: KtElement, filter: DiagnosticCheckerFilter): List<KtPsiDiagnostic> {
|
||||
val moduleComponents = getModuleComponentsForElement(element)
|
||||
return moduleComponents.diagnosticsCollector.getDiagnosticsFor(element, filter)
|
||||
|
||||
+3
-8
@@ -5,10 +5,8 @@
|
||||
|
||||
package org.jetbrains.kotlin.analysis.low.level.api.fir.state
|
||||
|
||||
import com.intellij.openapi.project.Project
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.LLFirGlobalResolveComponents
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.DiagnosticCheckerFilter
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.LLFirSessionProvider
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.LLFirSession
|
||||
import org.jetbrains.kotlin.analysis.project.structure.KtBuiltinsModule
|
||||
import org.jetbrains.kotlin.analysis.project.structure.KtLibraryModule
|
||||
import org.jetbrains.kotlin.analysis.project.structure.KtModule
|
||||
@@ -19,11 +17,8 @@ import org.jetbrains.kotlin.psi.KtElement
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
|
||||
internal class LLFirSourceResolveSession(
|
||||
override val globalComponents: LLFirGlobalResolveComponents,
|
||||
override val project: Project,
|
||||
override val useSiteKtModule: KtModule,
|
||||
sessionProvider: LLFirSessionProvider,
|
||||
) : LLFirResolvableResolveSession(sessionProvider) {
|
||||
useSiteFirSession: LLFirSession
|
||||
) : LLFirResolvableResolveSession(useSiteFirSession) {
|
||||
override fun getDiagnostics(element: KtElement, filter: DiagnosticCheckerFilter): List<KtPsiDiagnostic> {
|
||||
val moduleComponents = getModuleComponentsForElement(element)
|
||||
return moduleComponents.diagnosticsCollector.getDiagnosticsFor(element, filter)
|
||||
|
||||
+1
-7
@@ -6,7 +6,6 @@
|
||||
package org.jetbrains.kotlin.analysis.low.level.api.fir.util
|
||||
|
||||
import com.intellij.openapi.progress.ProgressManager
|
||||
import com.intellij.openapi.util.ModificationTracker
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.LLFirResolvableModuleSession
|
||||
import org.jetbrains.kotlin.fir.FirElement
|
||||
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
|
||||
@@ -73,9 +72,4 @@ internal val FirDeclaration.containingKtFileIfAny: KtFile?
|
||||
|
||||
internal fun KtDeclaration.isNonAnonymousClassOrObject() =
|
||||
this is KtClassOrObject
|
||||
&& !this.isObjectLiteral()
|
||||
|
||||
|
||||
internal fun BooleanModificationTracker(provider: () -> Boolean): ModificationTracker {
|
||||
return ModificationTracker { if (provider()) 0 else 1 }
|
||||
}
|
||||
&& !this.isObjectLiteral()
|
||||
+3
-4
@@ -6,9 +6,9 @@
|
||||
package org.jetbrains.kotlin.analysis.low.level.api.fir.compiler.based
|
||||
|
||||
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.LLFirResolveSessionService
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.DiagnosticCheckerFilter
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.getOrBuildFirFile
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.createFirResolveSessionForNoCaching
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.test.base.FirLowLevelCompilerBasedTestConfigurator
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.transformers.LLFirLazyTransformer
|
||||
import org.jetbrains.kotlin.analysis.test.framework.AbstractCompilerBasedTest
|
||||
@@ -19,7 +19,6 @@ import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.platform.jvm.JvmPlatforms
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.test.FirParser
|
||||
import org.jetbrains.kotlin.test.TestInfrastructureInternals
|
||||
import org.jetbrains.kotlin.test.builders.TestConfigurationBuilder
|
||||
import org.jetbrains.kotlin.test.builders.firHandlersStep
|
||||
import org.jetbrains.kotlin.test.builders.testConfiguration
|
||||
@@ -86,8 +85,8 @@ abstract class AbstractCompilerBasedTestForFir : AbstractCompilerBasedTest() {
|
||||
val moduleInfoProvider = testServices.ktModuleProvider
|
||||
val ktModule = moduleInfoProvider.getModule(module.name) as KtSourceModuleByCompilerConfiguration
|
||||
|
||||
val project = testServices.compilerConfigurationProvider.getProject(module)
|
||||
val firResolveSession = createFirResolveSessionForNoCaching(ktModule, project)
|
||||
val project = ktModule.project
|
||||
val firResolveSession = LLFirResolveSessionService.getInstance(project).getFirResolveSessionNoCaching(ktModule)
|
||||
|
||||
val allFirFiles =
|
||||
module.files.filter { it.isKtFile }.zip(
|
||||
|
||||
+2
-2
@@ -5,10 +5,10 @@
|
||||
|
||||
package org.jetbrains.kotlin.analysis.low.level.api.fir.compiler.based
|
||||
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.LLFirResolveSessionService
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.LLFirResolveSession
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.getOrBuildFirFile
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.services.FirSealedClassInheritorsProcessorFactory
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.createFirResolveSessionForNoCaching
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.services.LLFirSealedClassInheritorsProcessorFactoryForTests
|
||||
import org.jetbrains.kotlin.analysis.project.structure.ProjectStructureProvider
|
||||
import org.jetbrains.kotlin.analysis.test.framework.project.structure.ktModuleProvider
|
||||
@@ -51,7 +51,7 @@ class SealedClassesInheritorsCaclulatorPreAnalysisHandler(
|
||||
val ktModuleProvider = project.getService(ProjectStructureProvider::class.java)
|
||||
val ktModule = ktFiles.map(ktModuleProvider::getKtModuleForKtElement).distinct().single()
|
||||
|
||||
val tmpFirResolveSession = createFirResolveSessionForNoCaching(ktModule, project)
|
||||
val tmpFirResolveSession = LLFirResolveSessionService.getInstance(project).getFirResolveSessionNoCaching(ktModule)
|
||||
val firFiles = ktFiles.map { it.getOrBuildFirFile(tmpFirResolveSession) }
|
||||
val sealedInheritors = collectSealedClassInheritors(firFiles, tmpFirResolveSession)
|
||||
val provider =
|
||||
|
||||
+3
-2
@@ -42,8 +42,9 @@ internal fun FirDeclaration.name(): String = symbol.name()
|
||||
|
||||
internal inline fun <R> resolveWithClearCaches(context: KtElement, action: (LLFirResolveSession) -> R): R {
|
||||
val project = context.project
|
||||
val firResolveSession = createFirResolveSessionForNoCaching(context.getKtModule(project), project)
|
||||
return action(firResolveSession)
|
||||
val module = context.getKtModule(project)
|
||||
val resolveSession = LLFirResolveSessionService.getInstance(project).getFirResolveSessionNoCaching(module)
|
||||
return action(resolveSession)
|
||||
}
|
||||
|
||||
internal val LLFirResolveSession.isSourceSession: Boolean
|
||||
|
||||
+4
-2
@@ -13,13 +13,14 @@ import org.jetbrains.kotlin.analysis.api.KtAnalysisApiInternals
|
||||
import org.jetbrains.kotlin.analysis.api.fir.KtFirAnalysisSessionProvider
|
||||
import org.jetbrains.kotlin.analysis.api.fir.references.ReadWriteAccessCheckerFirImpl
|
||||
import org.jetbrains.kotlin.analysis.api.session.KtAnalysisSessionProvider
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.LLFirGlobalResolveComponents
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.LLFirResolveSessionService
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.services.FirSealedClassInheritorsProcessorFactory
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.project.structure.LLFirBuiltinsSessionFactory
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.project.structure.LLFirLibrarySessionFactory
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.services.KtCompilerPluginsProviderForTests
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.services.LLFirSealedClassInheritorsProcessorFactoryForTests
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.services.PackagePartProviderTestImpl
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.LLFirSessionCache
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.LLFirSessionConfigurator
|
||||
import org.jetbrains.kotlin.analysis.project.structure.KtCompilerPluginsProvider
|
||||
import org.jetbrains.kotlin.analysis.providers.PackagePartProviderFactory
|
||||
@@ -49,7 +50,8 @@ object AnalysisApiFirTestServiceRegistrar : AnalysisApiTestServiceRegistrar() {
|
||||
registerService(KtAnalysisSessionProvider::class.java, KtFirAnalysisSessionProvider(this))
|
||||
registerService(FirSealedClassInheritorsProcessorFactory::class.java, LLFirSealedClassInheritorsProcessorFactoryForTests())
|
||||
registerService(LLFirResolveSessionService::class.java)
|
||||
registerService(LLFirLibrarySessionFactory::class.java)
|
||||
registerService(LLFirSessionCache::class.java)
|
||||
registerService(LLFirGlobalResolveComponents::class.java)
|
||||
registerService(LLFirBuiltinsSessionFactory::class.java)
|
||||
registerService(PackagePartProviderFactory::class.java, PackagePartProviderTestImpl(testServices))
|
||||
|
||||
|
||||
Reference in New Issue
Block a user