[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(":compiler:backend.common.jvm"))
|
||||||
api(project(":analysis:analysis-api-impl-barebone"))
|
api(project(":analysis:analysis-api-impl-barebone"))
|
||||||
api(project(":js:js.config"))
|
api(project(":js:js.config"))
|
||||||
|
api(project(":compiler:cli-common"))
|
||||||
testApi(project(":analysis:analysis-api-fir"))
|
testApi(project(":analysis:analysis-api-fir"))
|
||||||
implementation(project(":compiler:frontend.common"))
|
implementation(project(":compiler:frontend.common"))
|
||||||
implementation(project(":compiler:fir:entrypoint"))
|
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.JvmDeclarationCheckers
|
||||||
import org.jetbrains.kotlin.fir.analysis.jvm.checkers.JvmExpressionCheckers
|
import org.jetbrains.kotlin.fir.analysis.jvm.checkers.JvmExpressionCheckers
|
||||||
import org.jetbrains.kotlin.fir.analysis.jvm.checkers.JvmTypeCheckers
|
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.fir.extensions.extensionService
|
||||||
import org.jetbrains.kotlin.platform.SimplePlatform
|
import org.jetbrains.kotlin.platform.SimplePlatform
|
||||||
import org.jetbrains.kotlin.platform.jvm.JvmPlatform
|
import org.jetbrains.kotlin.platform.jvm.JvmPlatform
|
||||||
import org.jetbrains.kotlin.platform.JsPlatform
|
import org.jetbrains.kotlin.platform.JsPlatform
|
||||||
|
import org.jetbrains.kotlin.platform.konan.NativePlatform
|
||||||
|
|
||||||
internal abstract class AbstractLLFirDiagnosticsCollector(
|
internal abstract class AbstractLLFirDiagnosticsCollector(
|
||||||
session: FirSession,
|
session: FirSession,
|
||||||
@@ -81,6 +83,7 @@ private object CheckersFactory {
|
|||||||
when (platform) {
|
when (platform) {
|
||||||
is JvmPlatform -> add(JvmDeclarationCheckers)
|
is JvmPlatform -> add(JvmDeclarationCheckers)
|
||||||
is JsPlatform -> add(JsDeclarationCheckers)
|
is JsPlatform -> add(JsDeclarationCheckers)
|
||||||
|
is NativePlatform -> add(NativeDeclarationCheckers)
|
||||||
else -> {}
|
else -> {}
|
||||||
}
|
}
|
||||||
addAll(extensionCheckers.map { it.declarationCheckers })
|
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
|
package org.jetbrains.kotlin.analysis.low.level.api.fir.sessions
|
||||||
|
|
||||||
import com.intellij.openapi.project.Project
|
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.CachedValue
|
||||||
import com.intellij.psi.util.CachedValueProvider
|
import com.intellij.psi.util.CachedValueProvider
|
||||||
import com.intellij.psi.util.CachedValuesManager
|
import com.intellij.psi.util.CachedValuesManager
|
||||||
import com.intellij.util.containers.CollectionFactory
|
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.project.structure.*
|
||||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.providers.*
|
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.low.level.api.fir.util.checkCanceled
|
||||||
import org.jetbrains.kotlin.analysis.project.structure.*
|
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.FirModuleDataImpl
|
||||||
import org.jetbrains.kotlin.fir.FirSession
|
import org.jetbrains.kotlin.fir.FirSession
|
||||||
import org.jetbrains.kotlin.fir.PrivateSessionConstructor
|
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.extensions.*
|
||||||
import org.jetbrains.kotlin.fir.java.JavaSymbolProvider
|
|
||||||
import org.jetbrains.kotlin.fir.resolve.providers.*
|
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.session.*
|
||||||
import org.jetbrains.kotlin.fir.symbols.FirLazyDeclarationResolver
|
|
||||||
import org.jetbrains.kotlin.name.Name
|
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.platform.jvm.JvmPlatforms
|
||||||
import org.jetbrains.kotlin.psi.KtFile
|
import org.jetbrains.kotlin.platform.konan.NativePlatform
|
||||||
import org.jetbrains.kotlin.resolve.jvm.modules.JavaModuleResolver
|
|
||||||
import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatformAnalyzerServices
|
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
|
import java.util.concurrent.ConcurrentMap
|
||||||
|
|
||||||
@OptIn(PrivateSessionConstructor::class, SessionConfiguration::class)
|
|
||||||
internal class LLFirSessionCache(private val project: Project) {
|
internal class LLFirSessionCache(private val project: Project) {
|
||||||
companion object {
|
companion object {
|
||||||
fun getInstance(project: Project): LLFirSessionCache {
|
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 sourceCache: ConcurrentMap<KtModule, CachedValue<LLFirSession>> = CollectionFactory.createConcurrentSoftValueMap()
|
||||||
private val binaryCache: 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 {
|
fun getSession(module: KtModule, preferBinary: Boolean = false): LLFirSession {
|
||||||
if (module is KtBinaryModule && (preferBinary || module is KtSdkModule)) {
|
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)
|
return getCachedSession(module, sourceCache, ::createSession)
|
||||||
@@ -104,464 +76,24 @@ internal class LLFirSessionCache(private val project: Project) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun createSession(module: KtModule): LLFirSession {
|
private fun createSession(module: KtModule): LLFirSession {
|
||||||
|
val sessionFactory = createPlatformAwareSessionFactory(module)
|
||||||
return when (module) {
|
return when (module) {
|
||||||
is KtSourceModule -> createSourcesSession(module)
|
is KtSourceModule -> sessionFactory.createSourcesSession(module)
|
||||||
is KtLibraryModule, is KtLibrarySourceModule -> createLibrarySession(module)
|
is KtLibraryModule, is KtLibrarySourceModule -> sessionFactory.createLibrarySession(module)
|
||||||
is KtSdkModule -> createBinaryLibrarySession(module)
|
is KtSdkModule -> sessionFactory.createBinaryLibrarySession(module)
|
||||||
is KtScriptModule -> createScriptSession(module)
|
is KtScriptModule -> sessionFactory.createScriptSession(module)
|
||||||
is KtNotUnderContentRootModule -> createNotUnderContentRootResolvableSession(module)
|
is KtNotUnderContentRootModule -> sessionFactory.createNotUnderContentRootResolvableSession(module)
|
||||||
else -> error("Unexpected module kind: ${module::class.simpleName}")
|
else -> error("Unexpected module kind: ${module::class.simpleName}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createSourcesSession(module: KtSourceModule): LLFirSourcesSession {
|
private fun createPlatformAwareSessionFactory(module: KtModule): LLFirAbstractSessionFactory {
|
||||||
val platform = module.platform
|
val targetPlatform = module.platform
|
||||||
val builtinsSession = LLFirBuiltinsSessionFactory.getInstance(project).getBuiltinsSession(platform)
|
return when {
|
||||||
val languageVersionSettings = wrapLanguageVersionSettings(module.languageVersionSettings)
|
targetPlatform.all { it is JvmPlatform } -> LLFirJvmSessionFactory(project)
|
||||||
|
targetPlatform.all { it is JsPlatform } -> LLFirJsSessionFactory(project)
|
||||||
val scopeProvider = FirKotlinScopeProvider(::wrapScopeWithJvmMapped)
|
targetPlatform.all { it is NativePlatform } -> LLFirNativeSessionFactory(project)
|
||||||
val components = LLFirModuleResolveComponents(module, globalResolveComponents, scopeProvider)
|
else -> LLFirCommonSessionFactory(project)
|
||||||
|
|
||||||
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()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-2
@@ -50,9 +50,10 @@ object FirNativeSessionFactory : FirAbstractSessionFactory() {
|
|||||||
).apply {
|
).apply {
|
||||||
bindSession(session)
|
bindSession(session)
|
||||||
}
|
}
|
||||||
|
val kotlinLibraries = resolvedLibraries.map { it.library }
|
||||||
listOfNotNull(
|
listOfNotNull(
|
||||||
KlibBasedSymbolProvider(session, moduleDataProvider, kotlinScopeProvider, resolvedLibraries.map { it.library }),
|
KlibBasedSymbolProvider(session, moduleDataProvider, kotlinScopeProvider, kotlinLibraries),
|
||||||
NativeForwardDeclarationsSymbolProvider(session, forwardDeclarationsModuleData, kotlinScopeProvider, resolvedLibraries),
|
NativeForwardDeclarationsSymbolProvider(session, forwardDeclarationsModuleData, kotlinScopeProvider, kotlinLibraries),
|
||||||
FirBuiltinSymbolProvider(session, builtinsModuleData, kotlinScopeProvider),
|
FirBuiltinSymbolProvider(session, builtinsModuleData, kotlinScopeProvider),
|
||||||
FirExtensionSyntheticFunctionInterfaceProvider.createIfNeeded(session, builtinsModuleData, kotlinScopeProvider),
|
FirExtensionSyntheticFunctionInterfaceProvider.createIfNeeded(session, builtinsModuleData, kotlinScopeProvider),
|
||||||
FirCloneableSymbolProvider(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.symbols.impl.*
|
||||||
import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef
|
import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef
|
||||||
import org.jetbrains.kotlin.fir.types.constructClassType
|
import org.jetbrains.kotlin.fir.types.constructClassType
|
||||||
|
import org.jetbrains.kotlin.library.KotlinLibrary
|
||||||
import org.jetbrains.kotlin.library.includedForwardDeclarations
|
import org.jetbrains.kotlin.library.includedForwardDeclarations
|
||||||
import org.jetbrains.kotlin.library.isInterop
|
import org.jetbrains.kotlin.library.isInterop
|
||||||
import org.jetbrains.kotlin.library.metadata.impl.ForwardDeclarationKind
|
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.ClassId
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
@@ -36,7 +36,7 @@ class NativeForwardDeclarationsSymbolProvider(
|
|||||||
session: FirSession,
|
session: FirSession,
|
||||||
private val forwardDeclarationsModuleData: FirModuleData,
|
private val forwardDeclarationsModuleData: FirModuleData,
|
||||||
private val kotlinScopeProvider: FirKotlinScopeProvider,
|
private val kotlinScopeProvider: FirKotlinScopeProvider,
|
||||||
private val resolvedLibraries: Collection<KotlinResolvedLibrary>,
|
private val kotlinLibraries: Collection<KotlinLibrary>,
|
||||||
) : FirSymbolProvider(session) {
|
) : FirSymbolProvider(session) {
|
||||||
private companion object {
|
private companion object {
|
||||||
private val validPackages = ForwardDeclarationKind.packageFqNameToKind.keys
|
private val validPackages = ForwardDeclarationKind.packageFqNameToKind.keys
|
||||||
@@ -44,8 +44,7 @@ class NativeForwardDeclarationsSymbolProvider(
|
|||||||
|
|
||||||
private val includedForwardDeclarations: Set<ClassId> by lazy {
|
private val includedForwardDeclarations: Set<ClassId> by lazy {
|
||||||
buildSet {
|
buildSet {
|
||||||
for (resolvedLibrary in resolvedLibraries) {
|
for (library in kotlinLibraries) {
|
||||||
val library = resolvedLibrary.library
|
|
||||||
if (!library.isInterop) continue
|
if (!library.isInterop) continue
|
||||||
|
|
||||||
for (fqName in library.includedForwardDeclarations) {
|
for (fqName in library.includedForwardDeclarations) {
|
||||||
|
|||||||
Reference in New Issue
Block a user