diff --git a/analysis/low-level-api-fir/build.gradle.kts b/analysis/low-level-api-fir/build.gradle.kts index e941c85cadd..14daf365b48 100644 --- a/analysis/low-level-api-fir/build.gradle.kts +++ b/analysis/low-level-api-fir/build.gradle.kts @@ -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")) diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostics/AbstractFirIdeDiagnosticsCollector.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostics/AbstractFirIdeDiagnosticsCollector.kt index 083d33ca1f1..e73ec30bb49 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostics/AbstractFirIdeDiagnosticsCollector.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostics/AbstractFirIdeDiagnosticsCollector.kt @@ -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 }) diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/sessions/LLFirAbstractSessionFactory.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/sessions/LLFirAbstractSessionFactory.kt new file mode 100644 index 00000000000..9f08ecbad45 --- /dev/null +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/sessions/LLFirAbstractSessionFactory.kt @@ -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 { + 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): ModificationTracker { + val llFirSessionCache = LLFirSessionCache.getInstance(project) + val friendDependencies = module.directFriendDependencies + val trackers = ArrayList(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, + destination: MutableList, + ) { + 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.mergeDependencySymbolProvidersInto( + session: LLFirSession, + destination: MutableList, + ) { + SymbolProviderMerger(this, destination).apply { + merge { LLFirCombinedKotlinSymbolProvider.merge(session, project, it) } + merge { LLFirCombinedJavaSymbolProvider.merge(session, project, it) } + merge { LLFirCombinedSyntheticFunctionSymbolProvider.merge(session, it) } + finish() + } + } + + private class SymbolProviderMerger( + symbolProviders: List, + private val destination: MutableList + ) { + private var remainingSymbolProviders = symbolProviders + + inline fun merge(create: (List) -> FirSymbolProvider?) { + val (specificSymbolProviders, remainingSymbolProviders) = remainingSymbolProviders.partitionIsInstance<_, A>() + destination.addIfNotNull(create(specificSymbolProviders)) + this.remainingSymbolProviders = remainingSymbolProviders + } + + fun finish() { + destination.addAll(remainingSymbolProviders) + remainingSymbolProviders = emptyList() + } + } +} diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/sessions/LLFirCommonSessionFactory.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/sessions/LLFirCommonSessionFactory.kt new file mode 100644 index 00000000000..5386ff89589 --- /dev/null +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/sessions/LLFirCommonSessionFactory.kt @@ -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) + } +} diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/sessions/LLFirJsSessionFactory.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/sessions/LLFirJsSessionFactory.kt new file mode 100644 index 00000000000..79b4b224de9 --- /dev/null +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/sessions/LLFirJsSessionFactory.kt @@ -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()) + } +} diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/sessions/LLFirJvmSessionFactory.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/sessions/LLFirJvmSessionFactory.kt new file mode 100644 index 00000000000..1c82bef1fef --- /dev/null +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/sessions/LLFirJvmSessionFactory.kt @@ -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)) + } + } +} diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/sessions/LLFirNativeSessionFactory.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/sessions/LLFirNativeSessionFactory.kt new file mode 100644 index 00000000000..579fceae24b --- /dev/null +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/sessions/LLFirNativeSessionFactory.kt @@ -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) + } +} diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/sessions/LLFirSessionCache.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/sessions/LLFirSessionCache.kt index e7db66d079c..dea1cd3a161 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/sessions/LLFirSessionCache.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/sessions/LLFirSessionCache.kt @@ -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> = CollectionFactory.createConcurrentSoftValueMap() private val binaryCache: ConcurrentMap> = 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 { - 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): ModificationTracker { - val friendDependencies = module.directFriendDependencies - val trackers = ArrayList(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, - destination: MutableList, - ) { - 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.mergeDependencySymbolProvidersInto( - session: LLFirSession, - destination: MutableList, - ) { - SymbolProviderMerger(this, destination).apply { - merge { LLFirCombinedKotlinSymbolProvider.merge(session, project, it) } - merge { LLFirCombinedJavaSymbolProvider.merge(session, project, it) } - merge { LLFirCombinedSyntheticFunctionSymbolProvider.merge(session, it) } - finish() - } - } - - private class SymbolProviderMerger( - symbolProviders: List, - private val destination: MutableList - ) { - private var remainingSymbolProviders = symbolProviders - - inline fun merge(create: (List) -> 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) } } } diff --git a/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/session/FirNativeSessionFactory.kt b/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/session/FirNativeSessionFactory.kt index d4df97620ed..d57e9c72a9c 100644 --- a/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/session/FirNativeSessionFactory.kt +++ b/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/session/FirNativeSessionFactory.kt @@ -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), diff --git a/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/session/NativeForwardDeclarationsSymbolProvider.kt b/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/session/NativeForwardDeclarationsSymbolProvider.kt index f056eb030ea..18f59eb1b47 100644 --- a/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/session/NativeForwardDeclarationsSymbolProvider.kt +++ b/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/session/NativeForwardDeclarationsSymbolProvider.kt @@ -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, + private val kotlinLibraries: Collection, ) : FirSymbolProvider(session) { private companion object { private val validPackages = ForwardDeclarationKind.packageFqNameToKind.keys @@ -44,8 +44,7 @@ class NativeForwardDeclarationsSymbolProvider( private val includedForwardDeclarations: Set by lazy { buildSet { - for (resolvedLibrary in resolvedLibraries) { - val library = resolvedLibrary.library + for (library in kotlinLibraries) { if (!library.isInterop) continue for (fqName in library.includedForwardDeclarations) {