[LL FIR] introduce platform-aware LL FIR session factories
KT-58769
This commit is contained in:
committed by
Space Team
parent
e11f7daae4
commit
2a79643dcf
@@ -20,6 +20,7 @@ dependencies {
|
||||
api(project(":compiler:backend.common.jvm"))
|
||||
api(project(":analysis:analysis-api-impl-barebone"))
|
||||
api(project(":js:js.config"))
|
||||
api(project(":compiler:cli-common"))
|
||||
testApi(project(":analysis:analysis-api-fir"))
|
||||
implementation(project(":compiler:frontend.common"))
|
||||
implementation(project(":compiler:fir:entrypoint"))
|
||||
|
||||
+3
@@ -26,10 +26,12 @@ import org.jetbrains.kotlin.fir.analysis.js.checkers.JsExpressionCheckers
|
||||
import org.jetbrains.kotlin.fir.analysis.jvm.checkers.JvmDeclarationCheckers
|
||||
import org.jetbrains.kotlin.fir.analysis.jvm.checkers.JvmExpressionCheckers
|
||||
import org.jetbrains.kotlin.fir.analysis.jvm.checkers.JvmTypeCheckers
|
||||
import org.jetbrains.kotlin.fir.analysis.native.checkers.NativeDeclarationCheckers
|
||||
import org.jetbrains.kotlin.fir.extensions.extensionService
|
||||
import org.jetbrains.kotlin.platform.SimplePlatform
|
||||
import org.jetbrains.kotlin.platform.jvm.JvmPlatform
|
||||
import org.jetbrains.kotlin.platform.JsPlatform
|
||||
import org.jetbrains.kotlin.platform.konan.NativePlatform
|
||||
|
||||
internal abstract class AbstractLLFirDiagnosticsCollector(
|
||||
session: FirSession,
|
||||
@@ -81,6 +83,7 @@ private object CheckersFactory {
|
||||
when (platform) {
|
||||
is JvmPlatform -> add(JvmDeclarationCheckers)
|
||||
is JsPlatform -> add(JsDeclarationCheckers)
|
||||
is NativePlatform -> add(NativeDeclarationCheckers)
|
||||
else -> {}
|
||||
}
|
||||
addAll(extensionCheckers.map { it.declarationCheckers })
|
||||
|
||||
+511
@@ -0,0 +1,511 @@
|
||||
/*
|
||||
* Copyright 2010-2023 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 com.intellij.openapi.util.ModificationTracker
|
||||
import com.intellij.psi.search.GlobalSearchScope
|
||||
import com.intellij.psi.search.ProjectScope
|
||||
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
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.project.structure.*
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.providers.*
|
||||
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.providers.impl.EmptyKotlinDeclarationProvider
|
||||
import org.jetbrains.kotlin.analysis.providers.impl.FileBasedKotlinDeclarationProvider
|
||||
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
|
||||
import org.jetbrains.kotlin.fir.PrivateSessionConstructor
|
||||
import org.jetbrains.kotlin.fir.SessionConfiguration
|
||||
import org.jetbrains.kotlin.fir.analysis.checkersComponent
|
||||
import org.jetbrains.kotlin.fir.analysis.extensions.additionalCheckers
|
||||
import org.jetbrains.kotlin.fir.backend.jvm.FirJvmTypeMapper
|
||||
import org.jetbrains.kotlin.fir.extensions.*
|
||||
import org.jetbrains.kotlin.fir.java.JavaSymbolProvider
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.DEPENDENCIES_SYMBOL_PROVIDER_QUALIFIED_KEY
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.FirProvider
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.impl.FirExtensionSyntheticFunctionInterfaceProvider
|
||||
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.platform.jvm.JvmPlatforms
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.resolve.jvm.modules.JavaModuleResolver
|
||||
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.partitionIsInstance
|
||||
|
||||
@OptIn(PrivateSessionConstructor::class, SessionConfiguration::class)
|
||||
internal abstract class LLFirAbstractSessionFactory(protected val project: Project) {
|
||||
private val globalResolveComponents: LLFirGlobalResolveComponents
|
||||
get() = LLFirGlobalResolveComponents.getInstance(project)
|
||||
|
||||
abstract fun createSourcesSession(module: KtSourceModule): LLFirSourcesSession
|
||||
abstract fun createLibrarySession(module: KtModule): LLFirLibraryOrLibrarySourceResolvableModuleSession
|
||||
abstract fun createBinaryLibrarySession(module: KtBinaryModule): LLFirLibrarySession
|
||||
|
||||
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 components = LLFirModuleResolveComponents(module, globalResolveComponents, scopeProvider)
|
||||
val contentScope = module.contentScope
|
||||
|
||||
val dependencies = collectSourceModuleDependencies(module)
|
||||
val dependencyTracker = createSourceModuleDependencyTracker(module, dependencies)
|
||||
|
||||
val session = LLFirScriptSession(module, dependencyTracker, components, builtinsSession.builtinTypes)
|
||||
components.session = session
|
||||
|
||||
val moduleData = createModuleData(session)
|
||||
|
||||
return session.apply {
|
||||
registerModuleData(moduleData)
|
||||
register(FirKotlinScopeProvider::class, scopeProvider)
|
||||
|
||||
registerIdeComponents(project)
|
||||
registerCommonComponents(languageVersionSettings)
|
||||
registerCommonComponentsAfterExtensionsAreConfigured()
|
||||
registerCommonJavaComponents(JavaModuleResolver.getInstance(project))
|
||||
registerResolveComponents()
|
||||
registerJavaSpecificResolveComponents()
|
||||
|
||||
val provider = LLFirProvider(
|
||||
this,
|
||||
components,
|
||||
FileBasedKotlinDeclarationProvider(module.file),
|
||||
project.createPackageProvider(contentScope),
|
||||
canContainKotlinPackage = true,
|
||||
)
|
||||
|
||||
register(FirProvider::class, provider)
|
||||
register(FirLazyDeclarationResolver::class, LLFirLazyDeclarationResolver())
|
||||
|
||||
val dependencyProvider = LLFirDependenciesSymbolProvider(this, buildList {
|
||||
addDependencySymbolProvidersTo(session, dependencies, this)
|
||||
add(builtinsSession.symbolProvider)
|
||||
})
|
||||
|
||||
val javaSymbolProvider = createJavaSymbolProvider(this, moduleData, project, contentScope)
|
||||
register(JavaSymbolProvider::class, javaSymbolProvider)
|
||||
|
||||
register(
|
||||
FirSymbolProvider::class,
|
||||
LLFirModuleWithDependenciesSymbolProvider(
|
||||
this,
|
||||
providers = listOfNotNull(
|
||||
javaSymbolProvider,
|
||||
provider.symbolProvider,
|
||||
),
|
||||
dependencyProvider,
|
||||
)
|
||||
)
|
||||
|
||||
register(FirPredicateBasedProvider::class, FirEmptyPredicateBasedProvider)
|
||||
register(DEPENDENCIES_SYMBOL_PROVIDER_QUALIFIED_KEY, dependencyProvider)
|
||||
register(FirRegisteredPluginAnnotations::class, FirRegisteredPluginAnnotations.Empty)
|
||||
|
||||
LLFirSessionConfigurator.configure(this)
|
||||
}
|
||||
}
|
||||
|
||||
fun createNotUnderContentRootResolvableSession(module: KtNotUnderContentRootModule): LLFirNonUnderContentRootResolvableModuleSession {
|
||||
val builtinsSession = LLFirBuiltinsSessionFactory.getInstance(project).getBuiltinsSession(JvmPlatforms.unspecifiedJvmPlatform)
|
||||
val languageVersionSettings = LanguageVersionSettingsImpl.DEFAULT
|
||||
val scopeProvider = FirKotlinScopeProvider(::wrapScopeWithJvmMapped)
|
||||
val components = LLFirModuleResolveComponents(module, globalResolveComponents, scopeProvider)
|
||||
|
||||
val dependencyTracker = builtinsSession.modificationTracker
|
||||
val session = LLFirNonUnderContentRootResolvableModuleSession(module, dependencyTracker, components, builtinsSession.builtinTypes)
|
||||
components.session = session
|
||||
|
||||
val moduleData = createModuleData(session)
|
||||
|
||||
return session.apply {
|
||||
registerModuleData(moduleData)
|
||||
register(FirKotlinScopeProvider::class, scopeProvider)
|
||||
|
||||
registerIdeComponents(project)
|
||||
registerCommonComponents(languageVersionSettings)
|
||||
registerCommonComponentsAfterExtensionsAreConfigured()
|
||||
registerCommonJavaComponents(JavaModuleResolver.getInstance(project))
|
||||
registerResolveComponents()
|
||||
registerJavaSpecificResolveComponents()
|
||||
|
||||
val ktFile = module.file as? KtFile
|
||||
|
||||
val provider = LLFirProvider(
|
||||
this,
|
||||
components,
|
||||
if (ktFile != null) FileBasedKotlinDeclarationProvider(ktFile) else EmptyKotlinDeclarationProvider,
|
||||
project.createPackageProvider(module.contentScope),
|
||||
canContainKotlinPackage = true,
|
||||
)
|
||||
|
||||
register(FirProvider::class, provider)
|
||||
register(FirLazyDeclarationResolver::class, LLFirLazyDeclarationResolver())
|
||||
|
||||
val dependencyProvider = LLFirDependenciesSymbolProvider(this, listOf(builtinsSession.symbolProvider))
|
||||
|
||||
register(
|
||||
FirSymbolProvider::class,
|
||||
LLFirModuleWithDependenciesSymbolProvider(
|
||||
this,
|
||||
providers = listOf(
|
||||
provider.symbolProvider,
|
||||
),
|
||||
dependencyProvider,
|
||||
)
|
||||
)
|
||||
|
||||
register(FirPredicateBasedProvider::class, FirEmptyPredicateBasedProvider)
|
||||
register(DEPENDENCIES_SYMBOL_PROVIDER_QUALIFIED_KEY, dependencyProvider)
|
||||
register(FirJvmTypeMapper::class, FirJvmTypeMapper(this))
|
||||
register(FirRegisteredPluginAnnotations::class, FirRegisteredPluginAnnotations.Empty)
|
||||
|
||||
LLFirSessionConfigurator.configure(this)
|
||||
}
|
||||
}
|
||||
|
||||
protected class SourceSessionCreationContext(
|
||||
val moduleData: LLFirModuleData,
|
||||
val contentScope: GlobalSearchScope,
|
||||
val firProvider: LLFirProvider,
|
||||
val dependencyProvider: LLFirDependenciesSymbolProvider,
|
||||
val syntheticFunctionInterfaceProvider: FirExtensionSyntheticFunctionInterfaceProvider?,
|
||||
val switchableExtensionDeclarationsSymbolProvider: FirSwitchableExtensionDeclarationsSymbolProvider?,
|
||||
)
|
||||
|
||||
protected fun doCreateSourcesSession(
|
||||
module: KtSourceModule,
|
||||
scopeProvider: FirKotlinScopeProvider = FirKotlinScopeProvider(),
|
||||
additionalSessionConfiguration: LLFirSourcesSession.(context: SourceSessionCreationContext) -> Unit,
|
||||
): LLFirSourcesSession {
|
||||
val platform = module.platform
|
||||
val builtinsSession = LLFirBuiltinsSessionFactory.getInstance(project).getBuiltinsSession(platform)
|
||||
val languageVersionSettings = wrapLanguageVersionSettings(module.languageVersionSettings)
|
||||
|
||||
val components = LLFirModuleResolveComponents(module, globalResolveComponents, scopeProvider)
|
||||
|
||||
val dependencies = collectSourceModuleDependencies(module)
|
||||
val dependencyTracker = createSourceModuleDependencyTracker(module, dependencies)
|
||||
val session = LLFirSourcesSession(module, dependencyTracker, components, builtinsSession.builtinTypes)
|
||||
components.session = session
|
||||
|
||||
val moduleData = createModuleData(session)
|
||||
val contentScope = module.contentScope
|
||||
|
||||
|
||||
return session.apply {
|
||||
registerModuleData(moduleData)
|
||||
register(FirKotlinScopeProvider::class, scopeProvider)
|
||||
|
||||
registerIdeComponents(project)
|
||||
registerCommonComponents(languageVersionSettings)
|
||||
registerResolveComponents()
|
||||
|
||||
val firProvider = LLFirProvider(
|
||||
this,
|
||||
components,
|
||||
project.createDeclarationProvider(contentScope, module),
|
||||
project.createPackageProvider(contentScope),
|
||||
/* Source modules can contain `kotlin` package only if `-Xallow-kotlin-package` is specified, this is handled in LLFirProvider */
|
||||
canContainKotlinPackage = false,
|
||||
)
|
||||
|
||||
register(FirProvider::class, firProvider)
|
||||
register(FirLazyDeclarationResolver::class, LLFirLazyDeclarationResolver())
|
||||
|
||||
registerCompilerPluginServices(contentScope, project, module)
|
||||
registerCompilerPluginExtensions(project, module)
|
||||
registerCommonComponentsAfterExtensionsAreConfigured()
|
||||
|
||||
val dependencyProvider = LLFirDependenciesSymbolProvider(this, buildList {
|
||||
addDependencySymbolProvidersTo(session, dependencies, this)
|
||||
add(builtinsSession.symbolProvider)
|
||||
})
|
||||
|
||||
register(DEPENDENCIES_SYMBOL_PROVIDER_QUALIFIED_KEY, dependencyProvider)
|
||||
register(LLFirFirClassByPsiClassProvider::class, LLFirFirClassByPsiClassProvider(this))
|
||||
|
||||
LLFirSessionConfigurator.configure(this)
|
||||
|
||||
extensionService.additionalCheckers.forEach(session.checkersComponent::register)
|
||||
|
||||
val syntheticFunctionInterfaceProvider =
|
||||
FirExtensionSyntheticFunctionInterfaceProvider.createIfNeeded(this, moduleData, scopeProvider)
|
||||
val switchableExtensionDeclarationsSymbolProvider =
|
||||
FirSwitchableExtensionDeclarationsSymbolProvider.createIfNeeded(this)?.also {
|
||||
register(FirSwitchableExtensionDeclarationsSymbolProvider::class, it)
|
||||
}
|
||||
|
||||
val context = SourceSessionCreationContext(
|
||||
moduleData, contentScope, firProvider, dependencyProvider, syntheticFunctionInterfaceProvider,
|
||||
switchableExtensionDeclarationsSymbolProvider,
|
||||
)
|
||||
additionalSessionConfiguration(context)
|
||||
}
|
||||
}
|
||||
|
||||
protected class LibrarySessionCreationContext(
|
||||
val moduleData: LLFirModuleData,
|
||||
val contentScope: GlobalSearchScope,
|
||||
val firProvider: LLFirProvider,
|
||||
val dependencyProvider: LLFirDependenciesSymbolProvider
|
||||
)
|
||||
|
||||
protected fun doCreateLibrarySession(
|
||||
module: KtModule,
|
||||
additionalSessionConfiguration: LLFirLibraryOrLibrarySourceResolvableModuleSession.(context: LibrarySessionCreationContext) -> Unit
|
||||
): LLFirLibraryOrLibrarySourceResolvableModuleSession {
|
||||
val libraryModule = when (module) {
|
||||
is KtLibraryModule -> module
|
||||
is KtLibrarySourceModule -> module.binaryLibrary
|
||||
else -> error("Unexpected module ${module::class.simpleName}")
|
||||
}
|
||||
|
||||
val platform = module.platform
|
||||
val builtinsSession = LLFirBuiltinsSessionFactory.getInstance(project).getBuiltinsSession(platform)
|
||||
val languageVersionSettings = LanguageVersionSettingsImpl.DEFAULT
|
||||
|
||||
val scopeProvider = FirKotlinScopeProvider()
|
||||
val components = LLFirModuleResolveComponents(module, globalResolveComponents, scopeProvider)
|
||||
|
||||
val dependencyTracker = builtinsSession.modificationTracker
|
||||
val session =
|
||||
LLFirLibraryOrLibrarySourceResolvableModuleSession(module, dependencyTracker, components, builtinsSession.builtinTypes)
|
||||
components.session = session
|
||||
|
||||
val moduleData = createModuleData(session)
|
||||
|
||||
return session.apply {
|
||||
registerModuleData(moduleData)
|
||||
register(FirKotlinScopeProvider::class, scopeProvider)
|
||||
|
||||
registerIdeComponents(project)
|
||||
registerCommonComponents(languageVersionSettings)
|
||||
registerCommonComponentsAfterExtensionsAreConfigured()
|
||||
registerResolveComponents()
|
||||
|
||||
val contentScope = module.contentScope
|
||||
|
||||
val firProvider = LLFirProvider(
|
||||
this,
|
||||
components,
|
||||
project.createDeclarationProvider(contentScope, module),
|
||||
project.createPackageProvider(contentScope),
|
||||
canContainKotlinPackage = true,
|
||||
)
|
||||
|
||||
register(FirProvider::class, firProvider)
|
||||
|
||||
register(FirLazyDeclarationResolver::class, LLFirLazyDeclarationResolver())
|
||||
|
||||
// We need FirRegisteredPluginAnnotations during extensions' registration process
|
||||
val annotationsResolver = project.createAnnotationResolver(contentScope)
|
||||
register(FirRegisteredPluginAnnotations::class, LLFirIdeRegisteredPluginAnnotations(this, annotationsResolver))
|
||||
register(FirPredicateBasedProvider::class, FirEmptyPredicateBasedProvider)
|
||||
|
||||
val dependencyProvider = LLFirDependenciesSymbolProvider(this, buildList {
|
||||
add(builtinsSession.symbolProvider)
|
||||
|
||||
// Script dependencies are self-contained and should not depend on other libraries
|
||||
if (module !is KtScriptDependencyModule) {
|
||||
// Add all libraries excluding the current one
|
||||
val librariesSearchScope = ProjectScope.getLibrariesScope(project)
|
||||
.intersectWith(GlobalSearchScope.notScope(libraryModule.contentScope))
|
||||
|
||||
val restLibrariesProvider = LLFirLibraryProviderFactory.createLibraryProvidersForAllProjectLibraries(
|
||||
session, moduleData, scopeProvider,
|
||||
project, builtinTypes, librariesSearchScope
|
||||
)
|
||||
|
||||
addAll(restLibrariesProvider)
|
||||
}
|
||||
})
|
||||
|
||||
register(DEPENDENCIES_SYMBOL_PROVIDER_QUALIFIED_KEY, dependencyProvider)
|
||||
register(LLFirFirClassByPsiClassProvider::class, LLFirFirClassByPsiClassProvider(this))
|
||||
|
||||
val context = LibrarySessionCreationContext(moduleData, contentScope, firProvider, dependencyProvider)
|
||||
additionalSessionConfiguration(context)
|
||||
|
||||
LLFirSessionConfigurator.configure(this)
|
||||
}
|
||||
}
|
||||
|
||||
protected class BinaryLibrarySessionCreationContext
|
||||
|
||||
protected fun doCreateBinaryLibrarySession(
|
||||
module: KtBinaryModule,
|
||||
additionalSessionConfiguration: LLFirLibrarySession.(context: BinaryLibrarySessionCreationContext) -> Unit,
|
||||
): LLFirLibrarySession {
|
||||
val platform = module.platform
|
||||
val builtinsSession = LLFirBuiltinsSessionFactory.getInstance(project).getBuiltinsSession(platform)
|
||||
|
||||
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()
|
||||
|
||||
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)
|
||||
|
||||
val context = BinaryLibrarySessionCreationContext()
|
||||
additionalSessionConfiguration(context)
|
||||
LLFirSessionConfigurator.configure(this)
|
||||
}
|
||||
}
|
||||
|
||||
private fun wrapLanguageVersionSettings(original: LanguageVersionSettings): LanguageVersionSettings {
|
||||
return object : LanguageVersionSettings by original {
|
||||
override fun getFeatureSupport(feature: LanguageFeature): LanguageFeature.State {
|
||||
return when (feature) {
|
||||
LanguageFeature.EnableDfaWarningsInK2 -> LanguageFeature.State.ENABLED
|
||||
else -> original.getFeatureSupport(feature)
|
||||
}
|
||||
}
|
||||
|
||||
override fun supportsFeature(feature: LanguageFeature): Boolean {
|
||||
return when (getFeatureSupport(feature)) {
|
||||
LanguageFeature.State.ENABLED, LanguageFeature.State.ENABLED_WITH_WARNING -> true
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun collectSourceModuleDependencies(module: KtModule): List<LLFirSession> {
|
||||
val llFirSessionCache = LLFirSessionCache.getInstance(project)
|
||||
|
||||
fun getOrCreateSessionForDependency(dependency: KtModule): LLFirSession? = when (dependency) {
|
||||
is KtBuiltinsModule -> null // Built-ins are already added
|
||||
is KtBinaryModule -> llFirSessionCache.getSession(dependency, preferBinary = true)
|
||||
is KtSourceModule -> llFirSessionCache.getSession(dependency)
|
||||
|
||||
is KtScriptModule,
|
||||
is KtScriptDependencyModule,
|
||||
is KtNotUnderContentRootModule,
|
||||
is KtLibrarySourceModule -> error("Module $module cannot depend on ${dependency::class}: $dependency")
|
||||
}
|
||||
|
||||
val dependencyModules = buildSet {
|
||||
addAll(module.directRegularDependencies)
|
||||
|
||||
// The dependency provider needs to have access to all direct and indirect `dependsOn` dependencies, as `dependsOn`
|
||||
// dependencies are transitive.
|
||||
addAll(module.transitiveDependsOnDependencies)
|
||||
}
|
||||
|
||||
return dependencyModules.mapNotNull(::getOrCreateSessionForDependency)
|
||||
}
|
||||
|
||||
private fun createSourceModuleDependencyTracker(module: KtModule, exposedDependencies: List<LLFirSession>): ModificationTracker {
|
||||
val llFirSessionCache = LLFirSessionCache.getInstance(project)
|
||||
val friendDependencies = module.directFriendDependencies
|
||||
val trackers = ArrayList<ModificationTracker>(exposedDependencies.size + friendDependencies.size)
|
||||
|
||||
exposedDependencies.forEach { trackers += it.modificationTracker }
|
||||
friendDependencies.forEach { trackers += llFirSessionCache.getSession(it).modificationTracker }
|
||||
|
||||
return CompositeModificationTracker.createFlattened(trackers)
|
||||
}
|
||||
|
||||
private fun createModuleData(session: LLFirSession): LLFirModuleData {
|
||||
return LLFirModuleData(session.ktModule).apply { bindSession(session) }
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds dependency symbol providers from [dependencies] to [destination]. The function might combine, reorder, or exclude specific
|
||||
* symbol providers for optimization.
|
||||
*/
|
||||
private fun addDependencySymbolProvidersTo(
|
||||
session: LLFirSession,
|
||||
dependencies: List<LLFirSession>,
|
||||
destination: MutableList<FirSymbolProvider>,
|
||||
) {
|
||||
val dependencyProviders = buildList {
|
||||
dependencies.forEach { session ->
|
||||
when (val dependencyProvider = session.symbolProvider) {
|
||||
is LLFirModuleWithDependenciesSymbolProvider -> addAll(dependencyProvider.providers)
|
||||
else -> add(dependencyProvider)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dependencyProviders.mergeDependencySymbolProvidersInto(session, destination)
|
||||
}
|
||||
|
||||
/**
|
||||
* Merges dependency symbol providers of the same kind if possible. The merged symbol provider usually delegates to its subordinate
|
||||
* symbol providers to preserve session semantics, but it will have some form of advantage over individual symbol providers (such as
|
||||
* querying an index once instead of N times).
|
||||
*
|
||||
* [session] should be the session of the dependent module. Because all symbol providers are tied to a session, we need a session to
|
||||
* create a combined symbol provider.
|
||||
*/
|
||||
private fun List<FirSymbolProvider>.mergeDependencySymbolProvidersInto(
|
||||
session: LLFirSession,
|
||||
destination: MutableList<FirSymbolProvider>,
|
||||
) {
|
||||
SymbolProviderMerger(this, destination).apply {
|
||||
merge<LLFirProvider.SymbolProvider> { LLFirCombinedKotlinSymbolProvider.merge(session, project, it) }
|
||||
merge<JavaSymbolProvider> { LLFirCombinedJavaSymbolProvider.merge(session, project, it) }
|
||||
merge<FirExtensionSyntheticFunctionInterfaceProvider> { LLFirCombinedSyntheticFunctionSymbolProvider.merge(session, it) }
|
||||
finish()
|
||||
}
|
||||
}
|
||||
|
||||
private class SymbolProviderMerger(
|
||||
symbolProviders: List<FirSymbolProvider>,
|
||||
private val destination: MutableList<FirSymbolProvider>
|
||||
) {
|
||||
private var remainingSymbolProviders = symbolProviders
|
||||
|
||||
inline fun <reified A : FirSymbolProvider> merge(create: (List<A>) -> FirSymbolProvider?) {
|
||||
val (specificSymbolProviders, remainingSymbolProviders) = remainingSymbolProviders.partitionIsInstance<_, A>()
|
||||
destination.addIfNotNull(create(specificSymbolProviders))
|
||||
this.remainingSymbolProviders = remainingSymbolProviders
|
||||
}
|
||||
|
||||
fun finish() {
|
||||
destination.addAll(remainingSymbolProviders)
|
||||
remainingSymbolProviders = emptyList()
|
||||
}
|
||||
}
|
||||
}
|
||||
+70
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Copyright 2010-2023 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.providers.LLFirModuleWithDependenciesSymbolProvider
|
||||
import org.jetbrains.kotlin.analysis.project.structure.KtBinaryModule
|
||||
import org.jetbrains.kotlin.analysis.project.structure.KtModule
|
||||
import org.jetbrains.kotlin.analysis.project.structure.KtSourceModule
|
||||
import org.jetbrains.kotlin.fir.FirVisibilityChecker
|
||||
import org.jetbrains.kotlin.fir.SessionConfiguration
|
||||
import org.jetbrains.kotlin.fir.analysis.FirOverridesBackwardCompatibilityHelper
|
||||
import org.jetbrains.kotlin.fir.analysis.jvm.FirJvmOverridesBackwardCompatibilityHelper
|
||||
import org.jetbrains.kotlin.fir.resolve.calls.ConeCallConflictResolverFactory
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider
|
||||
import org.jetbrains.kotlin.fir.scopes.FirPlatformClassMapper
|
||||
import org.jetbrains.kotlin.fir.session.DefaultCallConflictResolverFactory
|
||||
|
||||
@OptIn(SessionConfiguration::class)
|
||||
internal class LLFirCommonSessionFactory(project: Project) : LLFirAbstractSessionFactory(project) {
|
||||
override fun createSourcesSession(module: KtSourceModule): LLFirSourcesSession {
|
||||
return doCreateSourcesSession(module) { context ->
|
||||
registerModuleIndependentCommonComponents()
|
||||
|
||||
register(
|
||||
FirSymbolProvider::class,
|
||||
LLFirModuleWithDependenciesSymbolProvider(
|
||||
this,
|
||||
providers = listOf(
|
||||
context.firProvider.symbolProvider,
|
||||
),
|
||||
context.dependencyProvider,
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override fun createLibrarySession(module: KtModule): LLFirLibraryOrLibrarySourceResolvableModuleSession {
|
||||
return doCreateLibrarySession(module) { context ->
|
||||
registerModuleIndependentCommonComponents()
|
||||
|
||||
register(
|
||||
FirSymbolProvider::class,
|
||||
LLFirModuleWithDependenciesSymbolProvider(
|
||||
this,
|
||||
providers = listOf(
|
||||
context.firProvider.symbolProvider,
|
||||
),
|
||||
context.dependencyProvider,
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override fun createBinaryLibrarySession(module: KtBinaryModule): LLFirLibrarySession {
|
||||
return doCreateBinaryLibrarySession(module) {
|
||||
registerModuleIndependentCommonComponents()
|
||||
}
|
||||
}
|
||||
|
||||
private fun LLFirSession.registerModuleIndependentCommonComponents() {
|
||||
register(FirVisibilityChecker::class, FirVisibilityChecker.Default)
|
||||
register(ConeCallConflictResolverFactory::class, DefaultCallConflictResolverFactory)
|
||||
register(FirPlatformClassMapper::class, FirPlatformClassMapper.Default)
|
||||
register(FirOverridesBackwardCompatibilityHelper::class, FirJvmOverridesBackwardCompatibilityHelper)
|
||||
}
|
||||
}
|
||||
+75
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright 2010-2023 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.providers.LLFirModuleWithDependenciesSymbolProvider
|
||||
import org.jetbrains.kotlin.analysis.project.structure.KtBinaryModule
|
||||
import org.jetbrains.kotlin.analysis.project.structure.KtModule
|
||||
import org.jetbrains.kotlin.analysis.project.structure.KtSourceModule
|
||||
import org.jetbrains.kotlin.fir.FirVisibilityChecker
|
||||
import org.jetbrains.kotlin.fir.SessionConfiguration
|
||||
import org.jetbrains.kotlin.fir.analysis.FirOverridesBackwardCompatibilityHelper
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.FirPlatformDiagnosticSuppressor
|
||||
import org.jetbrains.kotlin.fir.analysis.js.checkers.FirJsPlatformDiagnosticSuppressor
|
||||
import org.jetbrains.kotlin.fir.analysis.jvm.FirJvmOverridesBackwardCompatibilityHelper
|
||||
import org.jetbrains.kotlin.fir.resolve.calls.ConeCallConflictResolverFactory
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider
|
||||
import org.jetbrains.kotlin.fir.scopes.FirPlatformClassMapper
|
||||
import org.jetbrains.kotlin.fir.session.JsCallConflictResolverFactory
|
||||
|
||||
@OptIn(SessionConfiguration::class)
|
||||
internal class LLFirJsSessionFactory(project: Project) : LLFirAbstractSessionFactory(project) {
|
||||
override fun createSourcesSession(module: KtSourceModule): LLFirSourcesSession {
|
||||
return doCreateSourcesSession(module) { context ->
|
||||
registerModuleIndependentJsComponents()
|
||||
|
||||
register(
|
||||
FirSymbolProvider::class,
|
||||
LLFirModuleWithDependenciesSymbolProvider(
|
||||
this,
|
||||
providers = listOfNotNull(
|
||||
context.firProvider.symbolProvider,
|
||||
context.switchableExtensionDeclarationsSymbolProvider,
|
||||
context.syntheticFunctionInterfaceProvider,
|
||||
),
|
||||
context.dependencyProvider,
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override fun createLibrarySession(module: KtModule): LLFirLibraryOrLibrarySourceResolvableModuleSession {
|
||||
return doCreateLibrarySession(module) { context ->
|
||||
registerModuleIndependentJsComponents()
|
||||
|
||||
register(
|
||||
FirSymbolProvider::class,
|
||||
LLFirModuleWithDependenciesSymbolProvider(
|
||||
this,
|
||||
providers = listOf(
|
||||
context.firProvider.symbolProvider,
|
||||
),
|
||||
context.dependencyProvider,
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override fun createBinaryLibrarySession(module: KtBinaryModule): LLFirLibrarySession {
|
||||
return doCreateBinaryLibrarySession(module) {
|
||||
registerModuleIndependentJsComponents()
|
||||
}
|
||||
}
|
||||
|
||||
private fun LLFirSession.registerModuleIndependentJsComponents() {
|
||||
register(FirVisibilityChecker::class, FirVisibilityChecker.Default)
|
||||
register(ConeCallConflictResolverFactory::class, JsCallConflictResolverFactory)
|
||||
register(FirPlatformClassMapper::class, FirPlatformClassMapper.Default)
|
||||
register(FirOverridesBackwardCompatibilityHelper::class, FirJvmOverridesBackwardCompatibilityHelper)
|
||||
register(FirPlatformDiagnosticSuppressor::class, FirJsPlatformDiagnosticSuppressor())
|
||||
}
|
||||
}
|
||||
+77
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright 2010-2023 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.project.structure.*
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.providers.*
|
||||
import org.jetbrains.kotlin.analysis.project.structure.*
|
||||
import org.jetbrains.kotlin.fir.SessionConfiguration
|
||||
import org.jetbrains.kotlin.fir.backend.jvm.FirJvmTypeMapper
|
||||
import org.jetbrains.kotlin.fir.java.JavaSymbolProvider
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider
|
||||
import org.jetbrains.kotlin.fir.resolve.scopes.wrapScopeWithJvmMapped
|
||||
import org.jetbrains.kotlin.fir.scopes.FirKotlinScopeProvider
|
||||
import org.jetbrains.kotlin.fir.session.*
|
||||
import org.jetbrains.kotlin.resolve.jvm.modules.JavaModuleResolver
|
||||
|
||||
@OptIn(SessionConfiguration::class)
|
||||
internal class LLFirJvmSessionFactory(project: Project) : LLFirAbstractSessionFactory(project) {
|
||||
|
||||
override fun createSourcesSession(module: KtSourceModule): LLFirSourcesSession {
|
||||
return doCreateSourcesSession(module, FirKotlinScopeProvider(::wrapScopeWithJvmMapped)) { context ->
|
||||
registerCommonJavaComponents(JavaModuleResolver.getInstance(project))
|
||||
registerJavaSpecificResolveComponents()
|
||||
val javaSymbolProvider = createJavaSymbolProvider(this, context.moduleData, project, context.contentScope)
|
||||
register(JavaSymbolProvider::class, javaSymbolProvider)
|
||||
|
||||
register(
|
||||
FirSymbolProvider::class,
|
||||
LLFirModuleWithDependenciesSymbolProvider(
|
||||
this,
|
||||
providers = listOfNotNull(
|
||||
context.firProvider.symbolProvider,
|
||||
context.switchableExtensionDeclarationsSymbolProvider,
|
||||
javaSymbolProvider,
|
||||
context.syntheticFunctionInterfaceProvider,
|
||||
),
|
||||
context.dependencyProvider,
|
||||
)
|
||||
)
|
||||
|
||||
register(FirJvmTypeMapper::class, FirJvmTypeMapper(this))
|
||||
}
|
||||
}
|
||||
|
||||
override fun createLibrarySession(module: KtModule): LLFirLibraryOrLibrarySourceResolvableModuleSession {
|
||||
return doCreateLibrarySession(module) { context ->
|
||||
registerCommonJavaComponents(JavaModuleResolver.getInstance(project))
|
||||
registerJavaSpecificResolveComponents()
|
||||
val javaSymbolProvider = createJavaSymbolProvider(this, context.moduleData, project, context.contentScope)
|
||||
register(
|
||||
FirSymbolProvider::class,
|
||||
LLFirModuleWithDependenciesSymbolProvider(
|
||||
this,
|
||||
providers = listOf(
|
||||
context.firProvider.symbolProvider,
|
||||
javaSymbolProvider,
|
||||
),
|
||||
context.dependencyProvider,
|
||||
)
|
||||
)
|
||||
register(JavaSymbolProvider::class, javaSymbolProvider)
|
||||
register(FirJvmTypeMapper::class, FirJvmTypeMapper(this))
|
||||
}
|
||||
}
|
||||
|
||||
override fun createBinaryLibrarySession(module: KtBinaryModule): LLFirLibrarySession {
|
||||
return doCreateBinaryLibrarySession(module) {
|
||||
registerCommonJavaComponents(JavaModuleResolver.getInstance(project))
|
||||
registerJavaSpecificResolveComponents()
|
||||
register(FirJvmTypeMapper::class, FirJvmTypeMapper(this))
|
||||
}
|
||||
}
|
||||
}
|
||||
+71
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright 2010-2023 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.providers.LLFirModuleWithDependenciesSymbolProvider
|
||||
import org.jetbrains.kotlin.analysis.project.structure.KtBinaryModule
|
||||
import org.jetbrains.kotlin.analysis.project.structure.KtModule
|
||||
import org.jetbrains.kotlin.analysis.project.structure.KtSourceModule
|
||||
import org.jetbrains.kotlin.fir.FirVisibilityChecker
|
||||
import org.jetbrains.kotlin.fir.SessionConfiguration
|
||||
import org.jetbrains.kotlin.fir.analysis.FirDefaultOverridesBackwardCompatibilityHelper
|
||||
import org.jetbrains.kotlin.fir.analysis.FirOverridesBackwardCompatibilityHelper
|
||||
import org.jetbrains.kotlin.fir.resolve.calls.ConeCallConflictResolverFactory
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider
|
||||
import org.jetbrains.kotlin.fir.scopes.FirPlatformClassMapper
|
||||
import org.jetbrains.kotlin.fir.session.DefaultCallConflictResolverFactory
|
||||
|
||||
@OptIn(SessionConfiguration::class)
|
||||
internal class LLFirNativeSessionFactory(project: Project) : LLFirAbstractSessionFactory(project) {
|
||||
override fun createSourcesSession(module: KtSourceModule): LLFirSourcesSession {
|
||||
return doCreateSourcesSession(module) { context ->
|
||||
registerModuleIndependentNativeComponents()
|
||||
|
||||
register(
|
||||
FirSymbolProvider::class,
|
||||
LLFirModuleWithDependenciesSymbolProvider(
|
||||
this,
|
||||
providers = listOfNotNull(
|
||||
context.firProvider.symbolProvider,
|
||||
context.switchableExtensionDeclarationsSymbolProvider,
|
||||
context.syntheticFunctionInterfaceProvider,
|
||||
),
|
||||
context.dependencyProvider,
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override fun createLibrarySession(module: KtModule): LLFirLibraryOrLibrarySourceResolvableModuleSession {
|
||||
return doCreateLibrarySession(module) { context ->
|
||||
registerModuleIndependentNativeComponents()
|
||||
register(
|
||||
FirSymbolProvider::class,
|
||||
LLFirModuleWithDependenciesSymbolProvider(
|
||||
this,
|
||||
providers = listOf(
|
||||
context.firProvider.symbolProvider,
|
||||
),
|
||||
context.dependencyProvider,
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override fun createBinaryLibrarySession(module: KtBinaryModule): LLFirLibrarySession {
|
||||
return doCreateBinaryLibrarySession(module) {
|
||||
registerModuleIndependentNativeComponents()
|
||||
}
|
||||
}
|
||||
|
||||
private fun LLFirSession.registerModuleIndependentNativeComponents() {
|
||||
register(FirVisibilityChecker::class, FirVisibilityChecker.Default)
|
||||
register(ConeCallConflictResolverFactory::class, DefaultCallConflictResolverFactory)
|
||||
register(FirPlatformClassMapper::class, FirPlatformClassMapper.Default)
|
||||
register(FirOverridesBackwardCompatibilityHelper::class, FirDefaultOverridesBackwardCompatibilityHelper)
|
||||
}
|
||||
}
|
||||
+19
-487
@@ -6,55 +6,28 @@
|
||||
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
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.project.structure.*
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.providers.*
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.checkCanceled
|
||||
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.providers.impl.EmptyKotlinDeclarationProvider
|
||||
import org.jetbrains.kotlin.analysis.providers.impl.FileBasedKotlinDeclarationProvider
|
||||
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
|
||||
import org.jetbrains.kotlin.fir.FirModuleDataImpl
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.PrivateSessionConstructor
|
||||
import org.jetbrains.kotlin.fir.SessionConfiguration
|
||||
import org.jetbrains.kotlin.fir.analysis.checkersComponent
|
||||
import org.jetbrains.kotlin.fir.analysis.extensions.additionalCheckers
|
||||
import org.jetbrains.kotlin.fir.backend.jvm.FirJvmTypeMapper
|
||||
import org.jetbrains.kotlin.fir.extensions.*
|
||||
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
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.platform.JsPlatform
|
||||
import org.jetbrains.kotlin.platform.jvm.JvmPlatform
|
||||
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.platform.konan.NativePlatform
|
||||
import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatformAnalyzerServices
|
||||
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.partitionIsInstance
|
||||
import java.util.concurrent.ConcurrentMap
|
||||
|
||||
@OptIn(PrivateSessionConstructor::class, SessionConfiguration::class)
|
||||
internal class LLFirSessionCache(private val project: Project) {
|
||||
companion object {
|
||||
fun getInstance(project: Project): LLFirSessionCache {
|
||||
@@ -62,9 +35,6 @@ internal class LLFirSessionCache(private val project: Project) {
|
||||
}
|
||||
}
|
||||
|
||||
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()
|
||||
|
||||
@@ -74,7 +44,9 @@ internal class LLFirSessionCache(private val project: Project) {
|
||||
*/
|
||||
fun getSession(module: KtModule, preferBinary: Boolean = false): LLFirSession {
|
||||
if (module is KtBinaryModule && (preferBinary || module is KtSdkModule)) {
|
||||
return getCachedSession(module, binaryCache, ::createBinaryLibrarySession)
|
||||
return getCachedSession(module, binaryCache) {
|
||||
createPlatformAwareSessionFactory(module).createBinaryLibrarySession(module)
|
||||
}
|
||||
}
|
||||
|
||||
return getCachedSession(module, sourceCache, ::createSession)
|
||||
@@ -104,464 +76,24 @@ internal class LLFirSessionCache(private val project: Project) {
|
||||
}
|
||||
|
||||
private fun createSession(module: KtModule): LLFirSession {
|
||||
val sessionFactory = createPlatformAwareSessionFactory(module)
|
||||
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)
|
||||
is KtSourceModule -> sessionFactory.createSourcesSession(module)
|
||||
is KtLibraryModule, is KtLibrarySourceModule -> sessionFactory.createLibrarySession(module)
|
||||
is KtSdkModule -> sessionFactory.createBinaryLibrarySession(module)
|
||||
is KtScriptModule -> sessionFactory.createScriptSession(module)
|
||||
is KtNotUnderContentRootModule -> sessionFactory.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 dependencies = collectSourceModuleDependencies(module)
|
||||
val dependencyTracker = createSourceModuleDependencyTracker(module, dependencies)
|
||||
val session = LLFirSourcesSession(module, dependencyTracker, components, builtinsSession.builtinTypes)
|
||||
components.session = session
|
||||
|
||||
val moduleData = createModuleData(session)
|
||||
|
||||
return session.apply {
|
||||
registerModuleData(moduleData)
|
||||
register(FirKotlinScopeProvider::class, scopeProvider)
|
||||
|
||||
registerIdeComponents(project)
|
||||
registerCommonComponents(languageVersionSettings)
|
||||
registerCommonJavaComponents(JavaModuleResolver.getInstance(project))
|
||||
registerResolveComponents()
|
||||
registerJavaSpecificResolveComponents()
|
||||
|
||||
val contentScope = module.contentScope
|
||||
|
||||
val provider = LLFirProvider(
|
||||
this,
|
||||
components,
|
||||
project.createDeclarationProvider(contentScope, module),
|
||||
project.createPackageProvider(contentScope),
|
||||
/* Source modules can contain `kotlin` package only if `-Xallow-kotlin-package` is specified, this is handled in LLFirProvider */
|
||||
canContainKotlinPackage = false,
|
||||
)
|
||||
|
||||
register(FirProvider::class, provider)
|
||||
register(FirLazyDeclarationResolver::class, LLFirLazyDeclarationResolver())
|
||||
|
||||
registerCompilerPluginServices(contentScope, project, module)
|
||||
registerCompilerPluginExtensions(project, module)
|
||||
registerCommonComponentsAfterExtensionsAreConfigured()
|
||||
|
||||
val switchableExtensionDeclarationsSymbolProvider =
|
||||
FirSwitchableExtensionDeclarationsSymbolProvider.createIfNeeded(session)?.also {
|
||||
register(FirSwitchableExtensionDeclarationsSymbolProvider::class, it)
|
||||
}
|
||||
|
||||
val dependencyProvider = LLFirDependenciesSymbolProvider(this, buildList {
|
||||
addDependencySymbolProvidersTo(session, dependencies, this)
|
||||
add(builtinsSession.symbolProvider)
|
||||
})
|
||||
|
||||
val javaSymbolProvider = createJavaSymbolProvider(this, moduleData, project, contentScope)
|
||||
val syntheticFunctionInterfaceProvider =
|
||||
FirExtensionSyntheticFunctionInterfaceProvider.createIfNeeded(this, moduleData, scopeProvider)
|
||||
register(
|
||||
FirSymbolProvider::class,
|
||||
LLFirModuleWithDependenciesSymbolProvider(
|
||||
this,
|
||||
providers = listOfNotNull(
|
||||
provider.symbolProvider,
|
||||
switchableExtensionDeclarationsSymbolProvider,
|
||||
javaSymbolProvider,
|
||||
syntheticFunctionInterfaceProvider,
|
||||
),
|
||||
dependencyProvider,
|
||||
)
|
||||
)
|
||||
register(JavaSymbolProvider::class, javaSymbolProvider)
|
||||
|
||||
register(DEPENDENCIES_SYMBOL_PROVIDER_QUALIFIED_KEY, dependencyProvider)
|
||||
register(FirJvmTypeMapper::class, FirJvmTypeMapper(this))
|
||||
register(LLFirFirClassByPsiClassProvider::class, LLFirFirClassByPsiClassProvider(this))
|
||||
|
||||
LLFirSessionConfigurator.configure(this)
|
||||
|
||||
extensionService.additionalCheckers.forEach(session.checkersComponent::register)
|
||||
}
|
||||
}
|
||||
|
||||
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 platform = module.platform
|
||||
val builtinsSession = LLFirBuiltinsSessionFactory.getInstance(project).getBuiltinsSession(platform)
|
||||
val languageVersionSettings = LanguageVersionSettingsImpl.DEFAULT
|
||||
|
||||
val scopeProvider = FirKotlinScopeProvider()
|
||||
val components = LLFirModuleResolveComponents(module, globalResolveComponents, scopeProvider)
|
||||
|
||||
val dependencyTracker = builtinsSession.modificationTracker
|
||||
val session = LLFirLibraryOrLibrarySourceResolvableModuleSession(module, dependencyTracker, components, builtinsSession.builtinTypes)
|
||||
components.session = session
|
||||
|
||||
val moduleData = createModuleData(session)
|
||||
|
||||
return session.apply {
|
||||
registerModuleData(moduleData)
|
||||
register(FirKotlinScopeProvider::class, scopeProvider)
|
||||
|
||||
registerIdeComponents(project)
|
||||
registerCommonComponents(languageVersionSettings)
|
||||
registerCommonComponentsAfterExtensionsAreConfigured()
|
||||
registerCommonJavaComponents(JavaModuleResolver.getInstance(project))
|
||||
registerResolveComponents()
|
||||
registerJavaSpecificResolveComponents()
|
||||
|
||||
val contentScope = module.contentScope
|
||||
|
||||
val provider = LLFirProvider(
|
||||
this,
|
||||
components,
|
||||
project.createDeclarationProvider(contentScope, module),
|
||||
project.createPackageProvider(contentScope),
|
||||
canContainKotlinPackage = true,
|
||||
)
|
||||
|
||||
register(FirProvider::class, provider)
|
||||
|
||||
register(FirLazyDeclarationResolver::class, LLFirLazyDeclarationResolver())
|
||||
|
||||
// We need FirRegisteredPluginAnnotations during extensions' registration process
|
||||
val annotationsResolver = project.createAnnotationResolver(contentScope)
|
||||
register(FirRegisteredPluginAnnotations::class, LLFirIdeRegisteredPluginAnnotations(this, annotationsResolver))
|
||||
register(FirPredicateBasedProvider::class, FirEmptyPredicateBasedProvider)
|
||||
|
||||
val dependencyProvider = LLFirDependenciesSymbolProvider(this, buildList {
|
||||
add(builtinsSession.symbolProvider)
|
||||
|
||||
// Script dependencies are self-contained and should not depend on other libraries
|
||||
if (module !is KtScriptDependencyModule) {
|
||||
// Add all libraries excluding the current one
|
||||
val librariesSearchScope = ProjectScope.getLibrariesScope(project)
|
||||
.intersectWith(GlobalSearchScope.notScope(libraryModule.contentScope))
|
||||
|
||||
val restLibrariesProvider = LLFirLibraryProviderFactory.createLibraryProvidersForAllProjectLibraries(
|
||||
session, moduleData, scopeProvider,
|
||||
project, builtinTypes, librariesSearchScope
|
||||
)
|
||||
|
||||
addAll(restLibrariesProvider)
|
||||
}
|
||||
})
|
||||
|
||||
val javaSymbolProvider = createJavaSymbolProvider(this, moduleData, project, contentScope)
|
||||
register(
|
||||
FirSymbolProvider::class,
|
||||
LLFirModuleWithDependenciesSymbolProvider(
|
||||
this,
|
||||
providers = listOf(
|
||||
provider.symbolProvider,
|
||||
javaSymbolProvider,
|
||||
),
|
||||
dependencyProvider,
|
||||
)
|
||||
)
|
||||
register(JavaSymbolProvider::class, javaSymbolProvider)
|
||||
|
||||
register(DEPENDENCIES_SYMBOL_PROVIDER_QUALIFIED_KEY, dependencyProvider)
|
||||
register(FirJvmTypeMapper::class, FirJvmTypeMapper(this))
|
||||
register(LLFirFirClassByPsiClassProvider::class, LLFirFirClassByPsiClassProvider(this))
|
||||
|
||||
LLFirSessionConfigurator.configure(this)
|
||||
}
|
||||
}
|
||||
|
||||
private fun createBinaryLibrarySession(module: KtBinaryModule): LLFirLibrarySession {
|
||||
val platform = module.platform
|
||||
val builtinsSession = LLFirBuiltinsSessionFactory.getInstance(project).getBuiltinsSession(platform)
|
||||
|
||||
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 components = LLFirModuleResolveComponents(module, globalResolveComponents, scopeProvider)
|
||||
val contentScope = module.contentScope
|
||||
|
||||
val dependencies = collectSourceModuleDependencies(module)
|
||||
val dependencyTracker = createSourceModuleDependencyTracker(module, dependencies)
|
||||
|
||||
val session = LLFirScriptSession(module, dependencyTracker, components, builtinsSession.builtinTypes)
|
||||
components.session = session
|
||||
|
||||
val moduleData = createModuleData(session)
|
||||
|
||||
return session.apply {
|
||||
registerModuleData(moduleData)
|
||||
register(FirKotlinScopeProvider::class, scopeProvider)
|
||||
|
||||
registerIdeComponents(project)
|
||||
registerCommonComponents(languageVersionSettings)
|
||||
registerCommonComponentsAfterExtensionsAreConfigured()
|
||||
registerCommonJavaComponents(JavaModuleResolver.getInstance(project))
|
||||
registerResolveComponents()
|
||||
registerJavaSpecificResolveComponents()
|
||||
|
||||
val provider = LLFirProvider(
|
||||
this,
|
||||
components,
|
||||
FileBasedKotlinDeclarationProvider(module.file),
|
||||
project.createPackageProvider(contentScope),
|
||||
canContainKotlinPackage = true,
|
||||
)
|
||||
|
||||
register(FirProvider::class, provider)
|
||||
register(FirLazyDeclarationResolver::class, LLFirLazyDeclarationResolver())
|
||||
|
||||
val dependencyProvider = LLFirDependenciesSymbolProvider(this, buildList {
|
||||
addDependencySymbolProvidersTo(session, dependencies, this)
|
||||
add(builtinsSession.symbolProvider)
|
||||
})
|
||||
|
||||
val javaSymbolProvider = createJavaSymbolProvider(this, moduleData, project, contentScope)
|
||||
register(JavaSymbolProvider::class, javaSymbolProvider)
|
||||
|
||||
register(
|
||||
FirSymbolProvider::class,
|
||||
LLFirModuleWithDependenciesSymbolProvider(
|
||||
this,
|
||||
providers = listOfNotNull(
|
||||
javaSymbolProvider,
|
||||
provider.symbolProvider,
|
||||
),
|
||||
dependencyProvider,
|
||||
)
|
||||
)
|
||||
|
||||
register(FirPredicateBasedProvider::class, FirEmptyPredicateBasedProvider)
|
||||
register(DEPENDENCIES_SYMBOL_PROVIDER_QUALIFIED_KEY, dependencyProvider)
|
||||
register(FirJvmTypeMapper::class, FirJvmTypeMapper(this))
|
||||
register(FirRegisteredPluginAnnotations::class, FirRegisteredPluginAnnotations.Empty)
|
||||
|
||||
LLFirSessionConfigurator.configure(this)
|
||||
}
|
||||
}
|
||||
|
||||
private fun createNotUnderContentRootResolvableSession(module: KtNotUnderContentRootModule): LLFirNonUnderContentRootResolvableModuleSession {
|
||||
val builtinsSession = LLFirBuiltinsSessionFactory.getInstance(project).getBuiltinsSession(JvmPlatforms.unspecifiedJvmPlatform)
|
||||
val languageVersionSettings = LanguageVersionSettingsImpl.DEFAULT
|
||||
val scopeProvider = FirKotlinScopeProvider(::wrapScopeWithJvmMapped)
|
||||
val components = LLFirModuleResolveComponents(module, globalResolveComponents, scopeProvider)
|
||||
|
||||
val dependencyTracker = builtinsSession.modificationTracker
|
||||
val session = LLFirNonUnderContentRootResolvableModuleSession(module, dependencyTracker, components, builtinsSession.builtinTypes)
|
||||
components.session = session
|
||||
|
||||
val moduleData = createModuleData(session)
|
||||
|
||||
return session.apply {
|
||||
registerModuleData(moduleData)
|
||||
register(FirKotlinScopeProvider::class, scopeProvider)
|
||||
|
||||
registerIdeComponents(project)
|
||||
registerCommonComponents(languageVersionSettings)
|
||||
registerCommonComponentsAfterExtensionsAreConfigured()
|
||||
registerCommonJavaComponents(JavaModuleResolver.getInstance(project))
|
||||
registerResolveComponents()
|
||||
registerJavaSpecificResolveComponents()
|
||||
|
||||
val ktFile = module.file as? KtFile
|
||||
|
||||
val provider = LLFirProvider(
|
||||
this,
|
||||
components,
|
||||
if (ktFile != null) FileBasedKotlinDeclarationProvider(ktFile) else EmptyKotlinDeclarationProvider,
|
||||
project.createPackageProvider(module.contentScope),
|
||||
canContainKotlinPackage = true,
|
||||
)
|
||||
|
||||
register(FirProvider::class, provider)
|
||||
register(FirLazyDeclarationResolver::class, LLFirLazyDeclarationResolver())
|
||||
|
||||
val dependencyProvider = LLFirDependenciesSymbolProvider(this, listOf(builtinsSession.symbolProvider))
|
||||
|
||||
register(
|
||||
FirSymbolProvider::class,
|
||||
LLFirModuleWithDependenciesSymbolProvider(
|
||||
this,
|
||||
providers = listOf(
|
||||
provider.symbolProvider,
|
||||
),
|
||||
dependencyProvider,
|
||||
)
|
||||
)
|
||||
|
||||
register(FirPredicateBasedProvider::class, FirEmptyPredicateBasedProvider)
|
||||
register(DEPENDENCIES_SYMBOL_PROVIDER_QUALIFIED_KEY, dependencyProvider)
|
||||
register(FirJvmTypeMapper::class, FirJvmTypeMapper(this))
|
||||
register(FirRegisteredPluginAnnotations::class, FirRegisteredPluginAnnotations.Empty)
|
||||
|
||||
LLFirSessionConfigurator.configure(this)
|
||||
}
|
||||
}
|
||||
|
||||
private fun wrapLanguageVersionSettings(original: LanguageVersionSettings): LanguageVersionSettings {
|
||||
return object : LanguageVersionSettings by original {
|
||||
override fun getFeatureSupport(feature: LanguageFeature): LanguageFeature.State {
|
||||
return when (feature) {
|
||||
LanguageFeature.EnableDfaWarningsInK2 -> LanguageFeature.State.ENABLED
|
||||
else -> original.getFeatureSupport(feature)
|
||||
}
|
||||
}
|
||||
|
||||
override fun supportsFeature(feature: LanguageFeature): Boolean {
|
||||
return when (getFeatureSupport(feature)) {
|
||||
LanguageFeature.State.ENABLED, LanguageFeature.State.ENABLED_WITH_WARNING -> true
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun collectSourceModuleDependencies(module: KtModule): List<LLFirSession> {
|
||||
fun getOrCreateSessionForDependency(dependency: KtModule): LLFirSession? = when (dependency) {
|
||||
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")
|
||||
}
|
||||
|
||||
val dependencyModules = buildSet {
|
||||
addAll(module.directRegularDependencies)
|
||||
|
||||
// The dependency provider needs to have access to all direct and indirect `dependsOn` dependencies, as `dependsOn`
|
||||
// dependencies are transitive.
|
||||
addAll(module.transitiveDependsOnDependencies)
|
||||
}
|
||||
|
||||
return dependencyModules.mapNotNull(::getOrCreateSessionForDependency)
|
||||
}
|
||||
|
||||
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) }
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds dependency symbol providers from [dependencies] to [destination]. The function might combine, reorder, or exclude specific
|
||||
* symbol providers for optimization.
|
||||
*/
|
||||
private fun addDependencySymbolProvidersTo(
|
||||
session: LLFirSession,
|
||||
dependencies: List<LLFirSession>,
|
||||
destination: MutableList<FirSymbolProvider>,
|
||||
) {
|
||||
val dependencyProviders = buildList {
|
||||
dependencies.forEach { session ->
|
||||
when (val dependencyProvider = session.symbolProvider) {
|
||||
is LLFirModuleWithDependenciesSymbolProvider -> addAll(dependencyProvider.providers)
|
||||
else -> add(dependencyProvider)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dependencyProviders.mergeDependencySymbolProvidersInto(session, destination)
|
||||
}
|
||||
|
||||
/**
|
||||
* Merges dependency symbol providers of the same kind if possible. The merged symbol provider usually delegates to its subordinate
|
||||
* symbol providers to preserve session semantics, but it will have some form of advantage over individual symbol providers (such as
|
||||
* querying an index once instead of N times).
|
||||
*
|
||||
* [session] should be the session of the dependent module. Because all symbol providers are tied to a session, we need a session to
|
||||
* create a combined symbol provider.
|
||||
*/
|
||||
private fun List<FirSymbolProvider>.mergeDependencySymbolProvidersInto(
|
||||
session: LLFirSession,
|
||||
destination: MutableList<FirSymbolProvider>,
|
||||
) {
|
||||
SymbolProviderMerger(this, destination).apply {
|
||||
merge<LLFirProvider.SymbolProvider> { LLFirCombinedKotlinSymbolProvider.merge(session, project, it) }
|
||||
merge<JavaSymbolProvider> { LLFirCombinedJavaSymbolProvider.merge(session, project, it) }
|
||||
merge<FirExtensionSyntheticFunctionInterfaceProvider> { LLFirCombinedSyntheticFunctionSymbolProvider.merge(session, it) }
|
||||
finish()
|
||||
}
|
||||
}
|
||||
|
||||
private class SymbolProviderMerger(
|
||||
symbolProviders: List<FirSymbolProvider>,
|
||||
private val destination: MutableList<FirSymbolProvider>
|
||||
) {
|
||||
private var remainingSymbolProviders = symbolProviders
|
||||
|
||||
inline fun <reified A : FirSymbolProvider> merge(create: (List<A>) -> FirSymbolProvider?) {
|
||||
val (specificSymbolProviders, remainingSymbolProviders) = remainingSymbolProviders.partitionIsInstance<_, A>()
|
||||
destination.addIfNotNull(create(specificSymbolProviders))
|
||||
this.remainingSymbolProviders = remainingSymbolProviders
|
||||
}
|
||||
|
||||
fun finish() {
|
||||
destination.addAll(remainingSymbolProviders)
|
||||
remainingSymbolProviders = emptyList()
|
||||
private fun createPlatformAwareSessionFactory(module: KtModule): LLFirAbstractSessionFactory {
|
||||
val targetPlatform = module.platform
|
||||
return when {
|
||||
targetPlatform.all { it is JvmPlatform } -> LLFirJvmSessionFactory(project)
|
||||
targetPlatform.all { it is JsPlatform } -> LLFirJsSessionFactory(project)
|
||||
targetPlatform.all { it is NativePlatform } -> LLFirNativeSessionFactory(project)
|
||||
else -> LLFirCommonSessionFactory(project)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+3
-2
@@ -50,9 +50,10 @@ object FirNativeSessionFactory : FirAbstractSessionFactory() {
|
||||
).apply {
|
||||
bindSession(session)
|
||||
}
|
||||
val kotlinLibraries = resolvedLibraries.map { it.library }
|
||||
listOfNotNull(
|
||||
KlibBasedSymbolProvider(session, moduleDataProvider, kotlinScopeProvider, resolvedLibraries.map { it.library }),
|
||||
NativeForwardDeclarationsSymbolProvider(session, forwardDeclarationsModuleData, kotlinScopeProvider, resolvedLibraries),
|
||||
KlibBasedSymbolProvider(session, moduleDataProvider, kotlinScopeProvider, kotlinLibraries),
|
||||
NativeForwardDeclarationsSymbolProvider(session, forwardDeclarationsModuleData, kotlinScopeProvider, kotlinLibraries),
|
||||
FirBuiltinSymbolProvider(session, builtinsModuleData, kotlinScopeProvider),
|
||||
FirExtensionSyntheticFunctionInterfaceProvider.createIfNeeded(session, builtinsModuleData, kotlinScopeProvider),
|
||||
FirCloneableSymbolProvider(session, builtinsModuleData, kotlinScopeProvider),
|
||||
|
||||
+3
-4
@@ -24,10 +24,10 @@ import org.jetbrains.kotlin.fir.scopes.FirKotlinScopeProvider
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.*
|
||||
import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef
|
||||
import org.jetbrains.kotlin.fir.types.constructClassType
|
||||
import org.jetbrains.kotlin.library.KotlinLibrary
|
||||
import org.jetbrains.kotlin.library.includedForwardDeclarations
|
||||
import org.jetbrains.kotlin.library.isInterop
|
||||
import org.jetbrains.kotlin.library.metadata.impl.ForwardDeclarationKind
|
||||
import org.jetbrains.kotlin.library.metadata.resolver.KotlinResolvedLibrary
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
@@ -36,7 +36,7 @@ class NativeForwardDeclarationsSymbolProvider(
|
||||
session: FirSession,
|
||||
private val forwardDeclarationsModuleData: FirModuleData,
|
||||
private val kotlinScopeProvider: FirKotlinScopeProvider,
|
||||
private val resolvedLibraries: Collection<KotlinResolvedLibrary>,
|
||||
private val kotlinLibraries: Collection<KotlinLibrary>,
|
||||
) : FirSymbolProvider(session) {
|
||||
private companion object {
|
||||
private val validPackages = ForwardDeclarationKind.packageFqNameToKind.keys
|
||||
@@ -44,8 +44,7 @@ class NativeForwardDeclarationsSymbolProvider(
|
||||
|
||||
private val includedForwardDeclarations: Set<ClassId> by lazy {
|
||||
buildSet {
|
||||
for (resolvedLibrary in resolvedLibraries) {
|
||||
val library = resolvedLibrary.library
|
||||
for (library in kotlinLibraries) {
|
||||
if (!library.isInterop) continue
|
||||
|
||||
for (fqName in library.includedForwardDeclarations) {
|
||||
|
||||
Reference in New Issue
Block a user