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 deleted file mode 100644 index 39a101b2baf..00000000000 --- a/analysis/analysis-api-providers/src/org/jetbrains/kotlin/analysis/providers/KotlinSealedInheritorsProvider.kt +++ /dev/null @@ -1,36 +0,0 @@ -/* - * 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 06f8f6287b4..b285ab0e091 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 @@ -16,7 +16,6 @@ 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.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 @@ -32,8 +31,6 @@ import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreProjectEnvironment import org.jetbrains.kotlin.cli.jvm.compiler.setupIdeaStandaloneExecution import org.jetbrains.kotlin.config.CompilerConfiguration import org.jetbrains.kotlin.extensions.ProjectExtensionDescriptor -import org.jetbrains.kotlin.fir.declarations.SealedClassInheritorsProvider -import org.jetbrains.kotlin.fir.declarations.SealedClassInheritorsProviderImpl import org.jetbrains.kotlin.load.kotlin.PackagePartProvider import org.jetbrains.kotlin.psi.KtFile import kotlin.contracts.ExperimentalContracts @@ -137,15 +134,6 @@ public class StandaloneAnalysisAPISessionBuilder( ) registerService(KotlinPackageProviderMerger::class.java, KotlinStaticPackageProviderMerger(this)) - registerService( - LLSealedInheritorsProviderFactory::class.java, - object : LLSealedInheritorsProviderFactory { - override fun createSealedInheritorsProvider(): SealedClassInheritorsProvider { - return SealedClassInheritorsProviderImpl - } - } - ) - registerService( PackagePartProviderFactory::class.java, KotlinStaticPackagePartProviderFactory(packagePartProvider) diff --git a/analysis/analysis-api/testData/components/compilerFacility/compilation/classKinds.ir.txt b/analysis/analysis-api/testData/components/compilerFacility/compilation/classKinds.ir.txt index c9748571e64..5ff35b6d447 100644 --- a/analysis/analysis-api/testData/components/compilerFacility/compilation/classKinds.ir.txt +++ b/analysis/analysis-api/testData/components/compilerFacility/compilation/classKinds.ir.txt @@ -52,8 +52,8 @@ MODULE_FRAGMENT CLASS CLASS name:Operation modality:SEALED visibility:public superTypes:[kotlin.Any] sealedSubclasses: CLASS CLASS name:Add modality:FINAL visibility:public superTypes:[.Operation] - CLASS CLASS name:Subtract modality:FINAL visibility:public superTypes:[.Operation] CLASS CLASS name:Negate modality:FINAL visibility:public superTypes:[.Operation] + CLASS CLASS name:Subtract modality:FINAL visibility:public superTypes:[.Operation] $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:.Operation CLASS CLASS name:Add modality:FINAL visibility:public superTypes:[.Operation] $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:.Operation.Add diff --git a/analysis/analysis-api/testData/components/diagnosticsProvider/diagnostics/annotationWithEnumFromDuplicatedLibrary.descriptors.txt b/analysis/analysis-api/testData/components/diagnosticsProvider/diagnostics/annotationWithEnumFromDuplicatedLibrary.descriptors.txt index d73ecf0277b..37dc712bc5f 100644 --- a/analysis/analysis-api/testData/components/diagnosticsProvider/diagnostics/annotationWithEnumFromDuplicatedLibrary.descriptors.txt +++ b/analysis/analysis-api/testData/components/diagnosticsProvider/diagnostics/annotationWithEnumFromDuplicatedLibrary.descriptors.txt @@ -1,7 +1,7 @@ Diagnostics from elements: - for PSI element of type KtConstructorCalleeExpression at (34,2-12) - NO_VALUE_FOR_PARAMETER text ranges: [(115,125)] - PSI: KtConstructorCalleeExpression at (34,2-12) - for PSI element of type KtNameReferenceExpression at (32,8-10) - UNRESOLVED_REFERENCE text ranges: [(94,96)] - PSI: KtNameReferenceExpression at (32,8-10) + for PSI element of type KtConstructorCalleeExpression at (33,2-12) + NO_VALUE_FOR_PARAMETER text ranges: [(114,124)] + PSI: KtConstructorCalleeExpression at (33,2-12) + for PSI element of type KtNameReferenceExpression at (31,8-10) + UNRESOLVED_REFERENCE text ranges: [(93,95)] + PSI: KtNameReferenceExpression at (31,8-10) diff --git a/analysis/analysis-api/testData/components/diagnosticsProvider/diagnostics/annotationWithEnumFromDuplicatedLibrary.kt b/analysis/analysis-api/testData/components/diagnosticsProvider/diagnostics/annotationWithEnumFromDuplicatedLibrary.kt index ee48b0be638..b0fe8c0b191 100644 --- a/analysis/analysis-api/testData/components/diagnosticsProvider/diagnostics/annotationWithEnumFromDuplicatedLibrary.kt +++ b/analysis/analysis-api/testData/components/diagnosticsProvider/diagnostics/annotationWithEnumFromDuplicatedLibrary.kt @@ -1,5 +1,4 @@ // ALLOW_KOTLIN_PACKAGE -// DISABLE_SEALED_INHERITOR_CALCULATOR // MODULE: lib1 // FILE: anno.kt package kotlin.annotation diff --git a/analysis/analysis-api/testData/components/diagnosticsProvider/diagnostics/duplicatedCallableWithImplicitType.descriptors.txt b/analysis/analysis-api/testData/components/diagnosticsProvider/diagnostics/duplicatedCallableWithImplicitType.descriptors.txt index c383bbc5d4c..992c77bbce8 100644 --- a/analysis/analysis-api/testData/components/diagnosticsProvider/diagnostics/duplicatedCallableWithImplicitType.descriptors.txt +++ b/analysis/analysis-api/testData/components/diagnosticsProvider/diagnostics/duplicatedCallableWithImplicitType.descriptors.txt @@ -1,13 +1,13 @@ Diagnostics from elements: - for PSI element of type KtCallExpression at (24,20) - (27,2) - TYPE_MISMATCH text ranges: [(98,160)] - PSI: KtCallExpression at (24,20) - (27,2) - for PSI element of type KtLambdaExpression at (24,24) - (27,2) - TYPE_MISMATCH text ranges: [(102,160)] - PSI: KtLambdaExpression at (24,24) - (27,2) - for PSI element of type KtNameReferenceExpression at (25,5-17) - UNRESOLVED_REFERENCE text ranges: [(108,120)] - PSI: KtNameReferenceExpression at (25,5-17) - for PSI element of type KtNameReferenceExpression at (26,5-34) - UNRESOLVED_REFERENCE text ranges: [(127,156)] - PSI: KtNameReferenceExpression at (26,5-34) + for PSI element of type KtCallExpression at (23,20) - (26,2) + TYPE_MISMATCH text ranges: [(97,159)] + PSI: KtCallExpression at (23,20) - (26,2) + for PSI element of type KtLambdaExpression at (23,24) - (26,2) + TYPE_MISMATCH text ranges: [(101,159)] + PSI: KtLambdaExpression at (23,24) - (26,2) + for PSI element of type KtNameReferenceExpression at (24,5-17) + UNRESOLVED_REFERENCE text ranges: [(107,119)] + PSI: KtNameReferenceExpression at (24,5-17) + for PSI element of type KtNameReferenceExpression at (25,5-34) + UNRESOLVED_REFERENCE text ranges: [(126,155)] + PSI: KtNameReferenceExpression at (25,5-34) diff --git a/analysis/analysis-api/testData/components/diagnosticsProvider/diagnostics/duplicatedCallableWithImplicitType.kt b/analysis/analysis-api/testData/components/diagnosticsProvider/diagnostics/duplicatedCallableWithImplicitType.kt index f7ad7f26aa2..2e57792d55c 100644 --- a/analysis/analysis-api/testData/components/diagnosticsProvider/diagnostics/duplicatedCallableWithImplicitType.kt +++ b/analysis/analysis-api/testData/components/diagnosticsProvider/diagnostics/duplicatedCallableWithImplicitType.kt @@ -1,4 +1,3 @@ -// DISABLE_SEALED_INHERITOR_CALCULATOR // MODULE: lib1 // FILE: dependency.kt package usage 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 deleted file mode 100644 index 8b79abe4451..00000000000 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/api/services/LLSealedInheritorsProviderFactory.kt +++ /dev/null @@ -1,56 +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 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/project/structure/sessionFactoryHelpers.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/project/structure/sessionFactoryHelpers.kt index 0d6e284372a..e1816e79651 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 @@ -8,11 +8,11 @@ package org.jetbrains.kotlin.analysis.low.level.api.fir.project.structure import com.intellij.openapi.project.Project import com.intellij.openapi.util.Disposer import org.jetbrains.kotlin.analysis.api.resolve.extensions.KtResolveExtensionProvider -import org.jetbrains.kotlin.analysis.low.level.api.fir.api.services.createSealedInheritorsProvider import org.jetbrains.kotlin.analysis.low.level.api.fir.compile.CodeFragmentScopeProvider import org.jetbrains.kotlin.analysis.low.level.api.fir.fir.caches.FirThreadSafeCachesFactory import org.jetbrains.kotlin.analysis.low.level.api.fir.providers.LLFirIdePredicateBasedProvider import org.jetbrains.kotlin.analysis.low.level.api.fir.providers.LLFirIdeRegisteredPluginAnnotations +import org.jetbrains.kotlin.analysis.low.level.api.fir.providers.LLSealedInheritorsProvider import org.jetbrains.kotlin.analysis.low.level.api.fir.resolve.extensions.LLFirNonEmptyResolveExtensionTool import org.jetbrains.kotlin.analysis.low.level.api.fir.resolve.extensions.LLFirResolveExtensionTool import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.LLFirSession @@ -37,7 +37,7 @@ import org.jetbrains.kotlin.fir.session.FirSessionConfigurator @SessionConfiguration internal fun LLFirSession.registerIdeComponents(project: Project) { register(FirCachesFactory::class, FirThreadSafeCachesFactory) - register(SealedClassInheritorsProvider::class, createSealedInheritorsProvider(project)) + register(SealedClassInheritorsProvider::class, LLSealedInheritorsProvider(project)) register(FirExceptionHandler::class, LLFirExceptionHandler) register(CodeFragmentScopeProvider::class, CodeFragmentScopeProvider(this)) registerResolveExtensionTool() diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/providers/LLSealedInheritorsProvider.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/providers/LLSealedInheritorsProvider.kt new file mode 100644 index 00000000000..e42a884e466 --- /dev/null +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/providers/LLSealedInheritorsProvider.kt @@ -0,0 +1,99 @@ +/* + * 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.low.level.api.fir.providers + +import com.intellij.openapi.project.Project +import com.intellij.psi.search.GlobalSearchScope +import org.jetbrains.kotlin.analysis.low.level.api.fir.project.structure.llFirModuleData +import org.jetbrains.kotlin.analysis.project.structure.KotlinModuleDependentsProvider +import org.jetbrains.kotlin.analysis.project.structure.KtDanglingFileModule +import org.jetbrains.kotlin.analysis.providers.KotlinDirectInheritorsProvider +import org.jetbrains.kotlin.fir.declarations.FirClass +import org.jetbrains.kotlin.fir.declarations.FirRegularClass +import org.jetbrains.kotlin.fir.declarations.SealedClassInheritorsProvider +import org.jetbrains.kotlin.fir.declarations.SealedClassInheritorsProviderInternals +import org.jetbrains.kotlin.fir.declarations.sealedInheritorsAttr +import org.jetbrains.kotlin.fir.declarations.utils.classId +import org.jetbrains.kotlin.fir.declarations.utils.isExpect +import org.jetbrains.kotlin.fir.psi +import org.jetbrains.kotlin.name.ClassId +import org.jetbrains.kotlin.psi.KtClass +import java.util.concurrent.ConcurrentHashMap +import kotlin.collections.filter +import kotlin.collections.map +import kotlin.collections.mapNotNull +import kotlin.collections.plus +import kotlin.collections.sortedBy +import kotlin.let + +/** + * [LLSealedInheritorsProvider] is the LL FIR implementation of [SealedClassInheritorsProvider] for both the IDE and Standalone mode. + */ +@OptIn(SealedClassInheritorsProviderInternals::class) +internal class LLSealedInheritorsProvider(private val project: Project) : SealedClassInheritorsProvider() { + val cache = ConcurrentHashMap>() + + override fun getSealedClassInheritors(firClass: FirRegularClass): List { + // Classes from binary libraries which are deserialized from class files (but not stubs) will have their `sealedInheritorsAttr` set + // from metadata. + firClass.sealedInheritorsAttr?.let { return it.value } + + val classId = firClass.classId + + // Local classes cannot be sealed. + if (classId.isLocal) { + return emptyList() + } + + return cache.computeIfAbsent(classId) { searchInheritors(firClass) } + } + + /** + * Some notes about the search: + * + * - A Java class cannot legally extend a sealed Kotlin class (even in the same package), so we don't need to search for Java class + * inheritors. + * - Technically, we could use a package scope to narrow the search, but the search is already sufficiently narrow because it uses + * supertype indices and is confined to the current `KtModule` in most cases (except for 'expect' classes). Finding a `PsiPackage` + * for a `PackageScope` is not cheap, hence the decision to avoid it. If a `PackageScope` is needed in the future, it'd be best to + * extract a `PackageNameScope` which operates just with the qualified package name, to avoid `PsiPackage`. (At the time of writing, + * this is possible with the implementation of `PackageScope`.) + * - We ignore local classes to avoid lazy resolve contract violations. + * See KT-63795. + * - For `expect` declarations, the search scope includes all modules with a dependsOn dependency on the containing module. + * At the same time, `actual` declarations are restricted to the same module and require no special handling. + * See KT-45842. + * - KMP libraries are not yet supported. + * See KT-65591. + */ + private fun searchInheritors(firClass: FirClass): List { + val ktClass = firClass.psi as? KtClass ?: return emptyList() + + val ktModule = when (val classKtModule = firClass.llFirModuleData.ktModule) { + is KtDanglingFileModule -> classKtModule.contextModule + else -> classKtModule + } + + // `FirClass.isExpect` does not depend on the `STATUS` phase because it's already set during FIR building. + val scope = if (firClass.isExpect) { + val refinementDependents = KotlinModuleDependentsProvider.getInstance(project).getRefinementDependents(ktModule) + GlobalSearchScope.union(refinementDependents.map { it.contentScope } + ktModule.contentScope) + } else { + ktModule.contentScope + } + + return searchInScope(ktClass, firClass.classId, scope) + } + + private fun searchInScope(ktClass: KtClass, classId: ClassId, scope: GlobalSearchScope): List = + KotlinDirectInheritorsProvider.getInstance(project) + .getDirectKotlinInheritors(ktClass, scope, includeLocalInheritors = false) + .mapNotNull { it.getClassId() } + .filter { it.packageFqName == classId.packageFqName } + // Enforce a deterministic order on the result, e.g. for stable test output. + .sortedBy { it.toString() } + .ifEmpty { emptyList() } +} diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirSealedClassInheritorsLazyResolver.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirSealedClassInheritorsLazyResolver.kt index 168ffe765f1..43fdfc84d7d 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirSealedClassInheritorsLazyResolver.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/transformers/LLFirSealedClassInheritorsLazyResolver.kt @@ -21,11 +21,11 @@ internal object LLFirSealedClassInheritorsLazyResolver : LLFirLazyResolver(FirRe /** * This resolver is responsible for [SEALED_CLASS_INHERITORS][FirResolvePhase.SEALED_CLASS_INHERITORS] phase. * - * LL FIR use [LLSealedInheritorsProviderByAnalysisApiProvider][org.jetbrains.kotlin.analysis.low.level.api.fir.api.services.LLSealedInheritorsProviderByAnalysisApiProvider] + * LL FIR uses [LLSealedInheritorsProvider][org.jetbrains.kotlin.analysis.low.level.api.fir.providers.LLSealedInheritorsProvider] * instead of the compiler [SealedClassInheritorsProviderImpl][org.jetbrains.kotlin.fir.declarations.SealedClassInheritorsProviderImpl], - * so it does nothing during this phase as sealed class hierarchy will be provided later on demand. + * so it does nothing during this phase as sealed inheritors will be provided later on demand. * - * @see org.jetbrains.kotlin.analysis.low.level.api.fir.api.services.LLSealedInheritorsProviderFactory + * @see org.jetbrains.kotlin.analysis.low.level.api.fir.providers.LLSealedInheritorsProvider * @see org.jetbrains.kotlin.fir.declarations.SealedClassInheritorsProvider * @see FirResolvePhase.SEALED_CLASS_INHERITORS */ diff --git a/analysis/low-level-api-fir/testData/lazyResolve/annotationFromImplicitJavaType.kt b/analysis/low-level-api-fir/testData/lazyResolve/annotationFromImplicitJavaType.kt index 1ea17f598dd..54b19e22f4f 100644 --- a/analysis/low-level-api-fir/testData/lazyResolve/annotationFromImplicitJavaType.kt +++ b/analysis/low-level-api-fir/testData/lazyResolve/annotationFromImplicitJavaType.kt @@ -1,5 +1,4 @@ // SKIP_WHEN_OUT_OF_CONTENT_ROOT -// DISABLE_SEALED_INHERITOR_CALCULATOR // FILE: main.kt fun resolveMe(i: JavaInterface) = i.id diff --git a/analysis/low-level-api-fir/testData/lazyResolve/annotationFromImplicitJavaTypeWithJavaAnnotation.kt b/analysis/low-level-api-fir/testData/lazyResolve/annotationFromImplicitJavaTypeWithJavaAnnotation.kt index dfdcfdf7b4e..924cec1aa51 100644 --- a/analysis/low-level-api-fir/testData/lazyResolve/annotationFromImplicitJavaTypeWithJavaAnnotation.kt +++ b/analysis/low-level-api-fir/testData/lazyResolve/annotationFromImplicitJavaTypeWithJavaAnnotation.kt @@ -1,5 +1,4 @@ // SKIP_WHEN_OUT_OF_CONTENT_ROOT -// DISABLE_SEALED_INHERITOR_CALCULATOR // FILE: main.kt fun resolveMe(i: JavaInterface) = i.id diff --git a/analysis/low-level-api-fir/testData/lazyResolve/functions/implicitTypeFromFunctionWithDuplicatedName.kt b/analysis/low-level-api-fir/testData/lazyResolve/functions/implicitTypeFromFunctionWithDuplicatedName.kt index f4b17659c7f..4a67f8e4618 100644 --- a/analysis/low-level-api-fir/testData/lazyResolve/functions/implicitTypeFromFunctionWithDuplicatedName.kt +++ b/analysis/low-level-api-fir/testData/lazyResolve/functions/implicitTypeFromFunctionWithDuplicatedName.kt @@ -1,5 +1,4 @@ // SKIP_WHEN_OUT_OF_CONTENT_ROOT -// DISABLE_SEALED_INHERITOR_CALCULATOR // MODULE: lib1 // FILE: dependency.kt package usage diff --git a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/compiler/based/AbstractLowLevelCompilerBasedTest.kt b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/compiler/based/AbstractLowLevelCompilerBasedTest.kt index 2b78cc90afa..d3be7cb40d5 100644 --- a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/compiler/based/AbstractLowLevelCompilerBasedTest.kt +++ b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/compiler/based/AbstractLowLevelCompilerBasedTest.kt @@ -52,8 +52,6 @@ abstract class AbstractLowLevelCompilerBasedTest : AbstractCompilerBasedTest() { configureTest(this) defaultConfiguration(this) registerAnalysisApiBaseTestServices(disposable, FirLowLevelCompilerBasedTestConfigurator) - useDirectives(SealedClassesInheritorsCalculatorPreAnalysisHandler.Directives) - usePreAnalysisHandlers(::SealedClassesInheritorsCalculatorPreAnalysisHandler) useAdditionalServices(service(::AnalysisApiFirDiagnosticCollectorService)) firHandlersStep { diff --git a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/compiler/based/SealedClassesInheritorsCalculatorPreAnalysisHandler.kt b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/compiler/based/SealedClassesInheritorsCalculatorPreAnalysisHandler.kt deleted file mode 100644 index 05286085929..00000000000 --- a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/compiler/based/SealedClassesInheritorsCalculatorPreAnalysisHandler.kt +++ /dev/null @@ -1,105 +0,0 @@ -/* - * 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.low.level.api.fir.compiler.based - -import com.intellij.openapi.project.Project -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.sessions.LLFirSessionCache -import org.jetbrains.kotlin.analysis.project.structure.KtModule -import org.jetbrains.kotlin.analysis.project.structure.ProjectStructureProvider -import org.jetbrains.kotlin.analysis.providers.KotlinDeclarationProviderFactory -import org.jetbrains.kotlin.analysis.providers.impl.KotlinStaticDeclarationProviderFactory -import org.jetbrains.kotlin.analysis.test.framework.project.structure.ktModuleProvider -import org.jetbrains.kotlin.analysis.test.framework.project.structure.mainModules -import org.jetbrains.kotlin.fir.declarations.FirRegularClass -import org.jetbrains.kotlin.fir.declarations.FirResolvePhase -import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider -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.KtClassOrObject -import org.jetbrains.kotlin.test.directives.model.DirectiveApplicability -import org.jetbrains.kotlin.test.directives.model.SimpleDirectivesContainer -import org.jetbrains.kotlin.test.services.PreAnalysisHandler -import org.jetbrains.kotlin.test.services.TestModuleStructure -import org.jetbrains.kotlin.test.services.TestServices -import org.jetbrains.kotlin.test.services.compilerConfigurationProvider - -class SealedClassesInheritorsCalculatorPreAnalysisHandler( - testServices: TestServices, -) : PreAnalysisHandler(testServices) { - - override fun preprocessModuleStructure(moduleStructure: TestModuleStructure) { - } - - // Manually process all inheritors of sealed classes so that SealedClassInheritorsProviderTestImpl can work correctly for tests. - // In the actual IDE, SealedClassInheritorsProviderIdeImpl works by finding inheritors from the index instead of doing a - // preprocessing of all files. Therefore, the IDE does not rely on such a pre-analysis pass of all files in the module. - override fun prepareSealedClassInheritors(moduleStructure: TestModuleStructure) { - if (Directives.DISABLE_SEALED_INHERITOR_CALCULATOR in moduleStructure.allDirectives) { - return - } - - val project = testServices.compilerConfigurationProvider.getProject(moduleStructure.modules.first()) - - val sealedInheritorsProviderFactory = - project.getService(LLSealedInheritorsProviderFactory::class.java) as? LLSealedInheritorsProviderFactoryForTests - ?: return - - val declarationProviderFactory = KotlinDeclarationProviderFactory.getInstance(project) as KotlinStaticDeclarationProviderFactory - val projectStructureProvider = project.getService(ProjectStructureProvider::class.java) - - val allKtClasses = declarationProviderFactory.getAllKtClasses() - val ktClassesByKtModule = allKtClasses.groupBy { projectStructureProvider.getModule(it, contextualModule = null) } - - for (ktTestModule in testServices.ktModuleProvider.mainModules) { - val ktClasses = ktClassesByKtModule[ktTestModule.ktModule] ?: continue - val sealedInheritors = collectSealedInheritorClassIds(ktTestModule.ktModule, ktClasses, project) - - sealedInheritorsProviderFactory.registerInheritors(ktTestModule.ktModule, sealedInheritors) - } - - // We request and cache sessions while collecting sealed inheritors. To not interfere with the test, we should invalidate all - // sessions. Note that, while we could get uncached sessions from `LLFirSessionCache`, dependency sessions will still be cached, so - // that is not really an alternative to invalidating sessions. - LLFirSessionCache.getInstance(project).removeAllSessions(includeLibraryModules = true) - } - - private fun collectSealedInheritorClassIds( - ktModule: KtModule, - ktClasses: List, - project: Project, - ): Map> { - val sealedInheritorsByFirClass = mutableMapOf>() - - ktClasses.forEach { ktClass -> - val classId = ktClass.getClassId() ?: return@forEach - - // Using a resolve session/source-preferred session will cause class stubs from binary libraries to be decompiled (which - // results in an exception since we don't have a decompiler for them). - val firSession = LLFirSessionCache.getInstance(project).getSession(ktModule, preferBinary = true) - val firClassSymbol = firSession.symbolProvider.getClassLikeSymbolByClassId(classId) ?: return@forEach - firClassSymbol.lazyResolveToPhaseRecursively(FirResolvePhase.TYPES) - - val inheritorsCollector = FirSealedClassInheritorsProcessor.InheritorsCollector(firSession) - firClassSymbol.fir.accept(inheritorsCollector, sealedInheritorsByFirClass) - } - - return buildMap { - sealedInheritorsByFirClass.forEach { firClass, classIds -> - put(firClass.symbol.classId, classIds.distinct()) - } - } - } - - object Directives : SimpleDirectivesContainer() { - val DISABLE_SEALED_INHERITOR_CALCULATOR by directive( - description = "Disable mock sealed class inheritor calculation", - applicability = DirectiveApplicability.Global - ) - } -} diff --git a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/services/LLSealedInheritorsProviderFactoryForTests.kt b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/services/LLSealedInheritorsProviderFactoryForTests.kt deleted file mode 100644 index ad793422819..00000000000 --- a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/services/LLSealedInheritorsProviderFactoryForTests.kt +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package org.jetbrains.kotlin.analysis.low.level.api.fir.services - -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 -import org.jetbrains.kotlin.fir.declarations.FirRegularClass -import org.jetbrains.kotlin.fir.declarations.SealedClassInheritorsProvider -import org.jetbrains.kotlin.fir.declarations.SealedClassInheritorsProviderInternals -import org.jetbrains.kotlin.fir.declarations.sealedInheritorsAttr -import org.jetbrains.kotlin.fir.declarations.utils.classId -import org.jetbrains.kotlin.name.ClassId - -internal class LLSealedInheritorsProviderFactoryForTests : LLSealedInheritorsProviderFactory { - private val inheritorsByModule = mutableMapOf>>() - - fun registerInheritors(ktModule: KtModule, inheritors: Map>) { - inheritorsByModule[ktModule] = inheritors - } - - override fun createSealedInheritorsProvider(): SealedClassInheritorsProvider { - return SealedClassInheritorsProviderForTests(inheritorsByModule) - } -} - -private class SealedClassInheritorsProviderForTests( - private val inheritorsByModule: Map>> -) : SealedClassInheritorsProvider() { - @OptIn(SealedClassInheritorsProviderInternals::class) - override fun getSealedClassInheritors(firClass: FirRegularClass): List { - val ktModule = firClass.llFirModuleData.ktModule - val relevantModule = when (ktModule) { - is KtDanglingFileModule -> ktModule.contextModule - else -> ktModule - } - - // If the module is absent in the map, it's either a binary library that wasn't stub-indexed (e.g. in Standalone mode) or the module - // doesn't have any `.kt` files, in which case there cannot be sealed inheritors. `sealedInheritorsAttr` covers the binary library - // case, as class-based deserialization sets this attribute. - return inheritorsByModule[relevantModule]?.get(firClass.classId) ?: firClass.sealedInheritorsAttr?.value ?: emptyList() - } -} 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 5201393c648..16233a20b96 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,6 @@ 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.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 @@ -30,7 +28,6 @@ object AnalysisApiFirTestServiceRegistrar : AnalysisApiTestServiceRegistrar() { FirStandaloneServiceRegistrar.registerProjectServices(project) project.apply { - registerService(LLSealedInheritorsProviderFactory::class.java, LLSealedInheritorsProviderFactoryForTests()) registerService(PackagePartProviderFactory::class.java, PackagePartProviderTestImpl(testServices)) registerService(KtCompilerPluginsProvider::class.java, NoOpKtCompilerPluginsProvider) } diff --git a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/test/configurators/AnalysisApiFirLibrarySourceTestConfigurator.kt b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/test/configurators/AnalysisApiFirLibrarySourceTestConfigurator.kt index f50cda6d7d0..2138eeb26c3 100644 --- a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/test/configurators/AnalysisApiFirLibrarySourceTestConfigurator.kt +++ b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/test/configurators/AnalysisApiFirLibrarySourceTestConfigurator.kt @@ -10,7 +10,6 @@ import com.intellij.openapi.project.Project import org.jetbrains.kotlin.analysis.api.impl.base.test.configurators.AnalysisApiBaseTestServiceRegistrar import org.jetbrains.kotlin.analysis.api.impl.base.test.configurators.AnalysisApiDecompiledCodeTestServiceRegistrar import org.jetbrains.kotlin.analysis.api.impl.base.test.configurators.AnalysisApiLibraryBaseTestServiceRegistrar -import org.jetbrains.kotlin.analysis.low.level.api.fir.compiler.based.SealedClassesInheritorsCalculatorPreAnalysisHandler import org.jetbrains.kotlin.analysis.low.level.api.fir.test.base.AnalysisApiFirTestServiceRegistrar import org.jetbrains.kotlin.analysis.test.framework.project.structure.KtLibrarySourceTestModuleFactory import org.jetbrains.kotlin.analysis.test.framework.project.structure.KtTestModuleFactory @@ -40,8 +39,6 @@ object AnalysisApiFirLibrarySourceTestConfigurator : AnalysisApiTestConfigurator useAdditionalService { KtLibrarySourceTestModuleFactory } useAdditionalService { DispatchingTestModuleCompiler() } useAdditionalService { AnalysisApiIndexingConfiguration(AnalysisApiBinaryLibraryIndexingMode.INDEX_STUBS) } - useDirectives(SealedClassesInheritorsCalculatorPreAnalysisHandler.Directives) - usePreAnalysisHandlers(::SealedClassesInheritorsCalculatorPreAnalysisHandler) useConfigurators( ::AnalysisApiJvmEnvironmentConfigurator, ::JsEnvironmentConfigurator, diff --git a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/test/configurators/AnalysisApiFirSourceLikeTestConfigurator.kt b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/test/configurators/AnalysisApiFirSourceLikeTestConfigurator.kt index cc37ba8eace..88b925b871b 100644 --- a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/test/configurators/AnalysisApiFirSourceLikeTestConfigurator.kt +++ b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/test/configurators/AnalysisApiFirSourceLikeTestConfigurator.kt @@ -9,7 +9,6 @@ import com.intellij.openapi.Disposable import com.intellij.openapi.project.Project import org.jetbrains.kotlin.analysis.api.impl.base.test.configurators.AnalysisApiBaseTestServiceRegistrar import org.jetbrains.kotlin.analysis.api.impl.base.test.configurators.AnalysisApiDecompiledCodeTestServiceRegistrar -import org.jetbrains.kotlin.analysis.low.level.api.fir.compiler.based.SealedClassesInheritorsCalculatorPreAnalysisHandler import org.jetbrains.kotlin.analysis.low.level.api.fir.test.base.AnalysisApiFirTestServiceRegistrar import org.jetbrains.kotlin.analysis.low.level.api.fir.test.base.configureOptionalTestCompilerPlugin import org.jetbrains.kotlin.analysis.test.framework.project.structure.KtTestModuleProjectStructure @@ -34,8 +33,6 @@ abstract class AnalysisApiFirSourceLikeTestConfigurator(override val analyseInDe override fun configureTest(builder: TestConfigurationBuilder, disposable: Disposable) { builder.apply { useAdditionalService { AnalysisApiIndexingConfiguration(AnalysisApiBinaryLibraryIndexingMode.INDEX_STUBS) } - useDirectives(SealedClassesInheritorsCalculatorPreAnalysisHandler.Directives) - usePreAnalysisHandlers(::SealedClassesInheritorsCalculatorPreAnalysisHandler) configureOptionalTestCompilerPlugin() useConfigurators( ::CommonEnvironmentConfigurator,