diff --git a/analysis/analysis-api-providers/src/org/jetbrains/kotlin/analysis/providers/KotlinSealedInheritorsProvider.kt b/analysis/analysis-api-providers/src/org/jetbrains/kotlin/analysis/providers/KotlinSealedInheritorsProvider.kt new file mode 100644 index 00000000000..39a101b2baf --- /dev/null +++ b/analysis/analysis-api-providers/src/org/jetbrains/kotlin/analysis/providers/KotlinSealedInheritorsProvider.kt @@ -0,0 +1,36 @@ +/* + * Copyright 2010-2024 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.providers + +import com.intellij.openapi.project.Project +import org.jetbrains.kotlin.name.ClassId +import org.jetbrains.kotlin.psi.KtClass + +/** + * [KotlinSealedInheritorsProvider] provides a list of direct inheritors for sealed [KtClass]es (which may be a class or an interface). It + * may be created with [KotlinSealedInheritorsProviderFactory]. + * + * Implementations of this service should consider caching the results. The [KotlinSealedInheritorsProvider] is tied to the lifetime of its + * owning session, so it will be invalidated automatically with the session. + */ +public interface KotlinSealedInheritorsProvider { + /** + * Returns the sealed inheritors of [ktClass], which may be a class or an interface. [ktClass] is guaranteed to be sealed. + */ + public fun getSealedInheritors(ktClass: KtClass): List +} + +public interface KotlinSealedInheritorsProviderFactory { + /** + * Creates a [KotlinSealedInheritorsProvider] for a session. + */ + public fun createSealedInheritorsProvider(): KotlinSealedInheritorsProvider + + public companion object { + public fun getInstance(project: Project): KotlinSealedInheritorsProviderFactory? = + project.getService(KotlinSealedInheritorsProviderFactory::class.java) + } +} diff --git a/analysis/analysis-api-standalone/src/org/jetbrains/kotlin/analysis/api/standalone/StandaloneAnalysisAPISessionBuilder.kt b/analysis/analysis-api-standalone/src/org/jetbrains/kotlin/analysis/api/standalone/StandaloneAnalysisAPISessionBuilder.kt index be4c20fbd3d..512bbbced2e 100644 --- a/analysis/analysis-api-standalone/src/org/jetbrains/kotlin/analysis/api/standalone/StandaloneAnalysisAPISessionBuilder.kt +++ b/analysis/analysis-api-standalone/src/org/jetbrains/kotlin/analysis/api/standalone/StandaloneAnalysisAPISessionBuilder.kt @@ -17,7 +17,7 @@ import org.jetbrains.kotlin.analysis.api.standalone.base.project.structure.FirSt import org.jetbrains.kotlin.analysis.api.standalone.base.project.structure.KtStaticProjectStructureProvider import org.jetbrains.kotlin.analysis.api.standalone.base.project.structure.LLFirStandaloneLibrarySymbolProviderFactory import org.jetbrains.kotlin.analysis.api.standalone.base.project.structure.StandaloneProjectFactory -import org.jetbrains.kotlin.analysis.low.level.api.fir.api.services.FirSealedClassInheritorsProcessorFactory +import org.jetbrains.kotlin.analysis.low.level.api.fir.api.services.LLSealedInheritorsProviderFactory import org.jetbrains.kotlin.analysis.low.level.api.fir.project.structure.LLFirLibrarySymbolProviderFactory import org.jetbrains.kotlin.analysis.project.structure.KtSourceModule import org.jetbrains.kotlin.analysis.project.structure.builder.KtModuleProviderBuilder @@ -140,9 +140,9 @@ public class StandaloneAnalysisAPISessionBuilder( registerService(KotlinPackageProviderMerger::class.java, KotlinStaticPackageProviderMerger(this)) registerService( - FirSealedClassInheritorsProcessorFactory::class.java, - object : FirSealedClassInheritorsProcessorFactory() { - override fun createSealedClassInheritorsProvider(): SealedClassInheritorsProvider { + LLSealedInheritorsProviderFactory::class.java, + object : LLSealedInheritorsProviderFactory { + override fun createSealedInheritorsProvider(): SealedClassInheritorsProvider { return SealedClassInheritorsProviderImpl } } diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/api/services/LLSealedInheritorsProviderFactory.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/api/services/LLSealedInheritorsProviderFactory.kt new file mode 100644 index 00000000000..8b79abe4451 --- /dev/null +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/api/services/LLSealedInheritorsProviderFactory.kt @@ -0,0 +1,56 @@ +/* + * Copyright 2010-2021 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.api.services + +import com.intellij.openapi.project.Project +import org.jetbrains.kotlin.analysis.providers.KotlinSealedInheritorsProvider +import org.jetbrains.kotlin.analysis.providers.KotlinSealedInheritorsProviderFactory +import org.jetbrains.kotlin.fir.declarations.FirRegularClass +import org.jetbrains.kotlin.fir.declarations.SealedClassInheritorsProvider +import org.jetbrains.kotlin.fir.psi +import org.jetbrains.kotlin.name.ClassId +import org.jetbrains.kotlin.psi.KtClass + +interface LLSealedInheritorsProviderFactory { + /** + * Creates a [SealedClassInheritorsProvider] for a session. A new [SealedClassInheritorsProvider] instance should be created on every + * call. + */ + fun createSealedInheritorsProvider(): SealedClassInheritorsProvider +} + +/** + * Creates a [SealedClassInheritorsProvider] for a session. + * + * Requires either [LLSealedInheritorsProviderFactory] or [KotlinSealedInheritorsProviderFactory] to be registered as a project service. + */ +internal fun createSealedInheritorsProvider(project: Project): SealedClassInheritorsProvider = + createFromLLProvider(project) + ?: createFromAnalysisApiProvider(project) + ?: error( + """ + Expected one of the following services to be registered with $project: + - ${LLSealedInheritorsProviderFactory::class.simpleName} + - ${KotlinSealedInheritorsProviderFactory::class.simpleName} + """.trimIndent() + ) + +private fun createFromLLProvider(project: Project): SealedClassInheritorsProvider? = + project.getService(LLSealedInheritorsProviderFactory::class.java)?.createSealedInheritorsProvider() + +private fun createFromAnalysisApiProvider(project: Project): SealedClassInheritorsProvider? = + KotlinSealedInheritorsProviderFactory.getInstance(project) + ?.createSealedInheritorsProvider() + ?.let(::LLSealedInheritorsProviderByAnalysisApiProvider) + +private class LLSealedInheritorsProviderByAnalysisApiProvider( + private val provider: KotlinSealedInheritorsProvider, +) : SealedClassInheritorsProvider() { + override fun getSealedClassInheritors(firClass: FirRegularClass): List { + val ktClass = firClass.psi as? KtClass ?: return emptyList() + return provider.getSealedInheritors(ktClass) + } +} diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/api/services/SealedInheritorsProviderFactory.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/api/services/SealedInheritorsProviderFactory.kt deleted file mode 100644 index 6a04af1f50f..00000000000 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/api/services/SealedInheritorsProviderFactory.kt +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright 2010-2021 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.api.services - -import com.intellij.openapi.project.Project -import com.intellij.psi.search.GlobalSearchScope -import org.jetbrains.kotlin.fir.declarations.SealedClassInheritorsProvider -import org.jetbrains.kotlin.fir.resolve.transformers.FirSealedClassInheritorsProcessor -import org.jetbrains.kotlin.load.kotlin.PackagePartProvider - -abstract class FirSealedClassInheritorsProcessorFactory { - /** - * Creates [SealedClassInheritorsProvider] for a module. - * This function should crate a new [SealedClassInheritorsProvider] instance on every call. - */ - abstract fun createSealedClassInheritorsProvider(): SealedClassInheritorsProvider -} - -/** - * Creates [SealedClassInheritorsProvider] for a module. - * This function should crate a new [SealedClassInheritorsProvider] instance on every call. - */ -internal fun Project.createSealedInheritorsProvider(): SealedClassInheritorsProvider = - getService(FirSealedClassInheritorsProcessorFactory::class.java).createSealedClassInheritorsProvider() \ No newline at end of file diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/project/structure/sessionFactoryHelpers.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/project/structure/sessionFactoryHelpers.kt index f2321240f0c..0f6eb3575ad 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/project/structure/sessionFactoryHelpers.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/project/structure/sessionFactoryHelpers.kt @@ -6,7 +6,6 @@ package org.jetbrains.kotlin.analysis.low.level.api.fir.project.structure import com.intellij.openapi.project.Project -import com.intellij.psi.search.GlobalSearchScope import org.jetbrains.kotlin.analysis.api.resolve.extensions.KtResolveExtensionProvider import org.jetbrains.kotlin.analysis.low.level.api.fir.IdeSessionComponents import org.jetbrains.kotlin.analysis.low.level.api.fir.api.services.createSealedInheritorsProvider @@ -39,7 +38,7 @@ import org.jetbrains.kotlin.fir.session.FirSessionConfigurator internal fun LLFirSession.registerIdeComponents(project: Project) { register(IdeSessionComponents::class, IdeSessionComponents.create()) register(FirCachesFactory::class, FirThreadSafeCachesFactory) - register(SealedClassInheritorsProvider::class, project.createSealedInheritorsProvider()) + register(SealedClassInheritorsProvider::class, createSealedInheritorsProvider(project)) register(FirExceptionHandler::class, LLFirExceptionHandler) register(CodeFragmentScopeProvider::class, CodeFragmentScopeProvider(this)) createResolveExtensionTool()?.let { diff --git a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/compiler/based/SealedClassesInheritorsCaclulatorPreAnalysisHandler.kt b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/compiler/based/SealedClassesInheritorsCaclulatorPreAnalysisHandler.kt index b645bd452e7..84a9bce03f1 100644 --- a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/compiler/based/SealedClassesInheritorsCaclulatorPreAnalysisHandler.kt +++ b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/compiler/based/SealedClassesInheritorsCaclulatorPreAnalysisHandler.kt @@ -8,8 +8,8 @@ package org.jetbrains.kotlin.analysis.low.level.api.fir.compiler.based import org.jetbrains.kotlin.analysis.low.level.api.fir.LLFirResolveSessionService import org.jetbrains.kotlin.analysis.low.level.api.fir.api.LLFirResolveSession import org.jetbrains.kotlin.analysis.low.level.api.fir.api.getOrBuildFirFile -import org.jetbrains.kotlin.analysis.low.level.api.fir.api.services.FirSealedClassInheritorsProcessorFactory -import org.jetbrains.kotlin.analysis.low.level.api.fir.services.LLFirSealedClassInheritorsProcessorFactoryForTests +import org.jetbrains.kotlin.analysis.low.level.api.fir.api.services.LLSealedInheritorsProviderFactory +import org.jetbrains.kotlin.analysis.low.level.api.fir.services.LLSealedInheritorsProviderFactoryForTests import org.jetbrains.kotlin.analysis.project.structure.ProjectStructureProvider import org.jetbrains.kotlin.analysis.test.framework.project.structure.getKtFiles import org.jetbrains.kotlin.analysis.test.framework.project.structure.ktModuleProvider @@ -19,7 +19,6 @@ import org.jetbrains.kotlin.fir.declarations.FirResolvePhase import org.jetbrains.kotlin.fir.resolve.transformers.FirSealedClassInheritorsProcessor import org.jetbrains.kotlin.fir.symbols.lazyResolveToPhaseRecursively import org.jetbrains.kotlin.name.ClassId -import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.test.directives.model.DirectiveApplicability import org.jetbrains.kotlin.test.directives.model.SimpleDirectivesContainer import org.jetbrains.kotlin.test.services.PreAnalysisHandler @@ -55,8 +54,7 @@ class SealedClassesInheritorsCaclulatorPreAnalysisHandler( val tmpFirResolveSession = LLFirResolveSessionService.getInstance(project).getFirResolveSessionNoCaching(ktModule) val firFiles = ktFiles.map { it.getOrBuildFirFile(tmpFirResolveSession) } val sealedInheritors = collectSealedClassInheritors(firFiles, tmpFirResolveSession) - val provider = - project.getService(FirSealedClassInheritorsProcessorFactory::class.java) as LLFirSealedClassInheritorsProcessorFactoryForTests + val provider = project.getService(LLSealedInheritorsProviderFactory::class.java) as LLSealedInheritorsProviderFactoryForTests provider.registerInheritors(ktModule, sealedInheritors) } } diff --git a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/services/LLFirSealedClassInheritorsProcessorFactoryForTests.kt b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/services/LLSealedInheritorsProviderFactoryForTests.kt similarity index 89% rename from analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/services/LLFirSealedClassInheritorsProcessorFactoryForTests.kt rename to analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/services/LLSealedInheritorsProviderFactoryForTests.kt index 31a135a74f9..68b355f2e5a 100644 --- a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/services/LLFirSealedClassInheritorsProcessorFactoryForTests.kt +++ b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/services/LLSealedInheritorsProviderFactoryForTests.kt @@ -5,7 +5,7 @@ package org.jetbrains.kotlin.analysis.low.level.api.fir.services -import org.jetbrains.kotlin.analysis.low.level.api.fir.api.services.FirSealedClassInheritorsProcessorFactory +import org.jetbrains.kotlin.analysis.low.level.api.fir.api.services.LLSealedInheritorsProviderFactory import org.jetbrains.kotlin.analysis.low.level.api.fir.project.structure.llFirModuleData import org.jetbrains.kotlin.analysis.project.structure.KtDanglingFileModule import org.jetbrains.kotlin.analysis.project.structure.KtModule @@ -16,14 +16,14 @@ import org.jetbrains.kotlin.fir.declarations.sealedInheritorsAttr import org.jetbrains.kotlin.fir.declarations.utils.classId import org.jetbrains.kotlin.name.ClassId -internal class LLFirSealedClassInheritorsProcessorFactoryForTests : FirSealedClassInheritorsProcessorFactory() { +internal class LLSealedInheritorsProviderFactoryForTests : LLSealedInheritorsProviderFactory { private val inheritorsByModule = mutableMapOf>>() fun registerInheritors(ktModule: KtModule, inheritors: Map>) { inheritorsByModule[ktModule] = inheritors } - override fun createSealedClassInheritorsProvider(): SealedClassInheritorsProvider { + override fun createSealedInheritorsProvider(): SealedClassInheritorsProvider { return SealedClassInheritorsProviderForTests(inheritorsByModule) } } diff --git a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/test/base/AnalysisApiFirTestServiceRegistrar.kt b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/test/base/AnalysisApiFirTestServiceRegistrar.kt index 69d9a4ae932..adb15572d6d 100644 --- a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/test/base/AnalysisApiFirTestServiceRegistrar.kt +++ b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/test/base/AnalysisApiFirTestServiceRegistrar.kt @@ -8,8 +8,8 @@ package org.jetbrains.kotlin.analysis.low.level.api.fir.test.base import com.intellij.mock.MockApplication import com.intellij.mock.MockProject import org.jetbrains.kotlin.analysis.api.standalone.base.project.structure.FirStandaloneServiceRegistrar -import org.jetbrains.kotlin.analysis.low.level.api.fir.api.services.FirSealedClassInheritorsProcessorFactory -import org.jetbrains.kotlin.analysis.low.level.api.fir.services.LLFirSealedClassInheritorsProcessorFactoryForTests +import org.jetbrains.kotlin.analysis.low.level.api.fir.api.services.LLSealedInheritorsProviderFactory +import org.jetbrains.kotlin.analysis.low.level.api.fir.services.LLSealedInheritorsProviderFactoryForTests import org.jetbrains.kotlin.analysis.low.level.api.fir.services.NoOpKtCompilerPluginsProvider import org.jetbrains.kotlin.analysis.low.level.api.fir.services.PackagePartProviderTestImpl import org.jetbrains.kotlin.analysis.project.structure.KtCompilerPluginsProvider @@ -28,7 +28,7 @@ object AnalysisApiFirTestServiceRegistrar : AnalysisApiTestServiceRegistrar() { project.apply { FirStandaloneServiceRegistrar.registerProjectServices(project) - registerService(FirSealedClassInheritorsProcessorFactory::class.java, LLFirSealedClassInheritorsProcessorFactoryForTests()) + registerService(LLSealedInheritorsProviderFactory::class.java, LLSealedInheritorsProviderFactoryForTests()) registerService(PackagePartProviderFactory::class.java, PackagePartProviderTestImpl(testServices)) registerService(KtCompilerPluginsProvider::class.java, NoOpKtCompilerPluginsProvider) }