From 5ceec858aa0a5e30ab7fe4cc2c40e5843a5b77f1 Mon Sep 17 00:00:00 2001 From: Ilya Kirillov Date: Thu, 1 Apr 2021 17:55:24 +0200 Subject: [PATCH] FIR IDE: do not search for sealed class inheritors on every class resolve --- .../fir/session/ComponentsContainers.kt | 8 ++ .../kotlin/fir/session/FirSessionFactory.kt | 2 + .../deserialization/ClassDeserialization.kt | 3 +- .../fir/serialization/FirElementSerializer.kt | 3 +- .../kotlin/fir/java/JavaSymbolProvider.kt | 3 +- .../FirSealedClassInheritorsProcessor.kt | 2 +- .../FirWhenExhaustivenessTransformer.kt | 2 +- .../fir/declarations/SealedClassInheritors.kt | 37 ++++++- .../api/FirIdeSealedHierarchyProcessor.kt | 104 ------------------ .../idea/fir/low/level/api/FirPhaseRunner.kt | 2 +- .../SealedClassInheritorsProviderIdeImpl.kt | 70 ++++++++++++ .../api/sessions/FirIdeSessionFactory.kt | 6 +- .../api/AbstractFirSealedInheritorsTest.kt | 8 +- 13 files changed, 133 insertions(+), 117 deletions(-) delete mode 100644 idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/FirIdeSealedHierarchyProcessor.kt create mode 100644 idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/SealedClassInheritorsProviderIdeImpl.kt diff --git a/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/session/ComponentsContainers.kt b/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/session/ComponentsContainers.kt index e606c8ec1b7..4476adbe080 100644 --- a/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/session/ComponentsContainers.kt +++ b/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/session/ComponentsContainers.kt @@ -12,6 +12,8 @@ import org.jetbrains.kotlin.fir.analysis.CheckersComponent import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirNameConflictsTracker import org.jetbrains.kotlin.fir.caches.FirCachesFactory import org.jetbrains.kotlin.fir.caches.FirThreadUnsafeCachesFactory +import org.jetbrains.kotlin.fir.declarations.SealedClassInheritorsProvider +import org.jetbrains.kotlin.fir.declarations.SealedClassInheritorsProviderImpl import org.jetbrains.kotlin.fir.extensions.FirExtensionService import org.jetbrains.kotlin.fir.extensions.FirPredicateBasedProvider import org.jetbrains.kotlin.fir.extensions.FirRegisteredPluginAnnotations @@ -51,6 +53,12 @@ fun FirSession.registerThreadUnsafeCaches() { register(FirCachesFactory::class, FirThreadUnsafeCachesFactory) } +@OptIn(SessionConfiguration::class) +fun FirSession.registerSealedClassInheritorsProvider() { + register(SealedClassInheritorsProvider::class, SealedClassInheritorsProviderImpl) +} + + // -------------------------- Resolve components -------------------------- diff --git a/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/session/FirSessionFactory.kt b/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/session/FirSessionFactory.kt index 19624e17e29..f8383fac11a 100644 --- a/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/session/FirSessionFactory.kt +++ b/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/session/FirSessionFactory.kt @@ -77,6 +77,7 @@ object FirSessionFactory { registerCommonComponents(languageVersionSettings) registerResolveComponents(lookupTracker) registerJavaSpecificResolveComponents() + registerSealedClassInheritorsProvider() val kotlinScopeProvider = KotlinScopeProvider(::wrapScopeWithJvmMapped) @@ -127,6 +128,7 @@ object FirSessionFactory { return FirLibrarySession(moduleInfo, sessionProvider).apply { registerThreadUnsafeCaches() registerCommonComponents(languageVersionSettings) + registerSealedClassInheritorsProvider() val javaSymbolProvider = JavaSymbolProvider(this, project, scope) diff --git a/compiler/fir/fir-deserialization/src/org/jetbrains/kotlin/fir/deserialization/ClassDeserialization.kt b/compiler/fir/fir-deserialization/src/org/jetbrains/kotlin/fir/deserialization/ClassDeserialization.kt index dd0d8d5e29f..c451ff05f27 100644 --- a/compiler/fir/fir-deserialization/src/org/jetbrains/kotlin/fir/deserialization/ClassDeserialization.kt +++ b/compiler/fir/fir-deserialization/src/org/jetbrains/kotlin/fir/deserialization/ClassDeserialization.kt @@ -195,9 +195,10 @@ fun deserializeClassToSymbol( }) }.also { if (isSealed) { - it.sealedInheritors = classProto.sealedSubclassFqNameList.map { nameIndex -> + val inheritors = classProto.sealedSubclassFqNameList.map { nameIndex -> ClassId.fromString(nameResolver.getQualifiedClassName(nameIndex)) } + it.setSealedClassInheritors(inheritors) } (it.annotations as MutableList) += context.annotationDeserializer.loadClassAnnotations(classProto, context.nameResolver) diff --git a/compiler/fir/fir-serialization/src/org/jetbrains/kotlin/fir/serialization/FirElementSerializer.kt b/compiler/fir/fir-serialization/src/org/jetbrains/kotlin/fir/serialization/FirElementSerializer.kt index 347724bee6e..849398b9798 100644 --- a/compiler/fir/fir-serialization/src/org/jetbrains/kotlin/fir/serialization/FirElementSerializer.kt +++ b/compiler/fir/fir-serialization/src/org/jetbrains/kotlin/fir/serialization/FirElementSerializer.kt @@ -166,8 +166,7 @@ class FirElementSerializer private constructor( } if (klass is FirRegularClass && klass.modality == Modality.SEALED) { - val inheritors = klass.sealedInheritors - requireNotNull(inheritors) + val inheritors = klass.getSealedClassInheritors(session) for (inheritorId in inheritors) { builder.addSealedSubclassFqName(stringTable.getQualifiedClassNameIndex(inheritorId)) } diff --git a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/JavaSymbolProvider.kt b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/JavaSymbolProvider.kt index fe7357052ed..84c7f160d32 100644 --- a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/JavaSymbolProvider.kt +++ b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/JavaSymbolProvider.kt @@ -332,10 +332,11 @@ class JavaSymbolProvider( } }.apply { if (modality == Modality.SEALED) { - sealedInheritors = javaClass.permittedTypes.mapNotNull { classifierType -> + val inheritors = javaClass.permittedTypes.mapNotNull { classifierType -> val classifier = classifierType.classifier as? JavaClass classifier?.let { JavaToKotlinClassMap.mapJavaToKotlin(it.fqName!!) } } + setSealedClassInheritors(inheritors) } if (classIsAnnotation) { diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirSealedClassInheritorsProcessor.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirSealedClassInheritorsProcessor.kt index 2254c96a831..b2339c685bc 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirSealedClassInheritorsProcessor.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirSealedClassInheritorsProcessor.kt @@ -86,7 +86,7 @@ class FirSealedClassInheritorsProcessor( if (regularClass.modality == Modality.SEALED) { val inheritors = inheritorsMap.remove(regularClass) if (inheritors != null) { - regularClass.sealedInheritors = inheritors + regularClass.setSealedClassInheritors(inheritors) } } if (inheritorsMap.isEmpty()) return regularClass.compose() diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirWhenExhaustivenessTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirWhenExhaustivenessTransformer.kt index 97b96c8c9ff..e2c0d4d9024 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirWhenExhaustivenessTransformer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirWhenExhaustivenessTransformer.kt @@ -313,7 +313,7 @@ private object WhenOnSealedClassExhaustivenessChecker : WhenExhaustivenessChecke return } when { - fir.modality == Modality.SEALED -> fir.sealedInheritors?.forEach { + fir.modality == Modality.SEALED -> fir.getSealedClassInheritors(session).forEach { val symbol = session.symbolProvider.getClassLikeSymbolByFqName(it) as? FirRegularClassSymbol symbol?.collectAllSubclassesTo(destination, session) } diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/SealedClassInheritors.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/SealedClassInheritors.kt index e16a6ad3498..2a5c4030df0 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/SealedClassInheritors.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/SealedClassInheritors.kt @@ -5,8 +5,41 @@ package org.jetbrains.kotlin.fir.declarations +import org.jetbrains.kotlin.fir.FirSession +import org.jetbrains.kotlin.fir.FirSessionComponent import org.jetbrains.kotlin.name.ClassId -object SealedClassInheritorsKey : FirDeclarationDataKey() -var FirRegularClass.sealedInheritors: List? by FirDeclarationDataRegistry.data(SealedClassInheritorsKey) +@RequiresOptIn("For getting/setting sealed class inheritors, consider using getSealedClassInheritors/setSealedClassInheritors") +annotation class SealedClassInheritorsProviderInternals + +abstract class SealedClassInheritorsProvider : FirSessionComponent { + abstract fun getSealedClassInheritors(firClass: FirRegularClass): List +} + +private val FirSession.sealedClassInheritorsProvider: SealedClassInheritorsProvider by FirSession.sessionComponentAccessor() + +object SealedClassInheritorsProviderImpl : SealedClassInheritorsProvider() { + @OptIn(SealedClassInheritorsProviderInternals::class) + override fun getSealedClassInheritors(firClass: FirRegularClass): List { + return firClass.sealedInheritorsAttr ?: emptyList() + } +} + + +fun FirRegularClass.getSealedClassInheritors(session: FirSession): List { + require(this.isSealed) + return session.sealedClassInheritorsProvider.getSealedClassInheritors(this) +} + +@OptIn(SealedClassInheritorsProviderInternals::class) +fun FirRegularClass.setSealedClassInheritors(inheritors: List) { + require(this.isSealed) + sealedInheritorsAttr = inheritors +} + +private object SealedClassInheritorsKey : FirDeclarationDataKey() + +@SealedClassInheritorsProviderInternals +var FirRegularClass.sealedInheritorsAttr: List? by FirDeclarationDataRegistry.data(SealedClassInheritorsKey) + private set diff --git a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/FirIdeSealedHierarchyProcessor.kt b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/FirIdeSealedHierarchyProcessor.kt deleted file mode 100644 index 1a0c8eb0028..00000000000 --- a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/FirIdeSealedHierarchyProcessor.kt +++ /dev/null @@ -1,104 +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.idea.fir.low.level.api - -import com.intellij.openapi.module.Module -import com.intellij.psi.JavaDirectoryService -import com.intellij.psi.PsiPackage -import com.intellij.psi.search.GlobalSearchScope -import com.intellij.psi.search.PackageScope -import com.intellij.psi.search.SearchScope -import com.intellij.psi.search.searches.ClassInheritorsSearch -import org.jetbrains.kotlin.asJava.KotlinAsJavaSupport -import org.jetbrains.kotlin.asJava.toLightClass -import org.jetbrains.kotlin.fir.FirElement -import org.jetbrains.kotlin.fir.FirSession -import org.jetbrains.kotlin.fir.declarations.* -import org.jetbrains.kotlin.fir.psi -import org.jetbrains.kotlin.fir.resolve.ScopeSession -import org.jetbrains.kotlin.fir.resolve.transformers.FirSealedClassInheritorsProcessor -import org.jetbrains.kotlin.fir.resolve.transformers.FirTransformerBasedResolveProcessor -import org.jetbrains.kotlin.fir.visitors.CompositeTransformResult -import org.jetbrains.kotlin.fir.visitors.FirDefaultVisitor -import org.jetbrains.kotlin.fir.visitors.FirTransformer -import org.jetbrains.kotlin.fir.visitors.compose -import org.jetbrains.kotlin.idea.util.classIdIfNonLocal -import org.jetbrains.kotlin.idea.util.module -import org.jetbrains.kotlin.name.ClassId -import org.jetbrains.kotlin.psi.KtClass -import org.jetbrains.kotlin.resolve.jvm.KotlinJavaPsiFacade - - -class FirIdeSealedHierarchyProcessor(session: FirSession, scopeSession: ScopeSession) : - FirTransformerBasedResolveProcessor(session, scopeSession) { - - override val transformer: FirTransformer = SealedClassInheritorsTransformer - - - private object SealedClassInheritorsTransformer : FirTransformer() { - override fun transformElement(element: E, data: Nothing?): CompositeTransformResult { - throw IllegalStateException("Should not be there") - } - - override fun transformFile(file: FirFile, data: Nothing?): CompositeTransformResult { - val sealedClassInheritorsMap = mutableMapOf>() - file.accept(SealedInheritorsCollector, sealedClassInheritorsMap) - - if (sealedClassInheritorsMap.isEmpty()) return file.compose() - return file.transform(FirSealedClassInheritorsProcessor.InheritorsTransformer(sealedClassInheritorsMap), null) - } - } - - private object SealedInheritorsCollector : FirDefaultVisitor>>() { - - override fun visitElement(element: FirElement, data: MutableMap>) {} - - override fun visitFile(file: FirFile, data: MutableMap>) { - file.declarations.forEach { it.accept(this, data) } - } - - override fun visitRegularClass(regularClass: FirRegularClass, data: MutableMap>) { - if (!regularClass.isSealed) { - regularClass.acceptChildren(this, data) - return - } - - val sealedKtClass = regularClass.psi as? KtClass ?: return - val module = sealedKtClass.module ?: return - val containingPackage = regularClass.classId.packageFqName - - val psiPackage = KotlinJavaPsiFacade.getInstance(sealedKtClass.project) - .findPackage(containingPackage.asString(), GlobalSearchScope.moduleScope(module)) - ?: getPackageViaDirectoryService(sealedKtClass) - ?: return - - val kotlinAsJavaSupport = KotlinAsJavaSupport.getInstance(sealedKtClass.project) - val lightClass = sealedKtClass.toLightClass() ?: kotlinAsJavaSupport.getFakeLightClass(sealedKtClass) - - val searchScope: SearchScope = getSearchScope(module, psiPackage) - val searchParameters = ClassInheritorsSearch.SearchParameters(lightClass, searchScope, false, true, false) - val subclasses = ClassInheritorsSearch.search(searchParameters) - .mapNotNull { it.classIdIfNonLocal() } - .toMutableList() - - // Enforce a deterministic order on the result. - subclasses.sortBy { it.toString() } - - data[regularClass] = subclasses - } - - private fun getSearchScope(module: Module, psiPackage: PsiPackage): GlobalSearchScope { - val packageScope = PackageScope(psiPackage, false, false) - // MPP multiple common modules are not supported!! - return module.moduleScope.intersectWith(packageScope) - } - } -} - -private fun getPackageViaDirectoryService(ktClass: KtClass): PsiPackage? { - val directory = ktClass.containingFile.containingDirectory ?: return null - return JavaDirectoryService.getInstance().getPackage(directory) -} diff --git a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/FirPhaseRunner.kt b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/FirPhaseRunner.kt index 31d66909665..d034ac0dbd9 100644 --- a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/FirPhaseRunner.kt +++ b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/FirPhaseRunner.kt @@ -81,7 +81,7 @@ internal fun FirResolvePhase.createTransformerBasedProcessorByPhase( FirResolvePhase.CLASS_GENERATION -> FirDummyTransformerBasedProcessor(session, scopeSession) // TODO: remove FirResolvePhase.IMPORTS -> FirImportResolveProcessor(session, scopeSession) FirResolvePhase.SUPER_TYPES -> FirSupertypeResolverProcessor(session, scopeSession) - FirResolvePhase.SEALED_CLASS_INHERITORS -> FirIdeSealedHierarchyProcessor(session, scopeSession) + FirResolvePhase.SEALED_CLASS_INHERITORS -> FirDummyTransformerBasedProcessor(session, scopeSession) FirResolvePhase.TYPES -> FirTypeResolveProcessor(session, scopeSession) FirResolvePhase.ARGUMENTS_OF_PLUGIN_ANNOTATIONS -> FirAnnotationArgumentsResolveProcessor(session, scopeSession) FirResolvePhase.EXTENSION_STATUS_UPDATE -> FirTransformerBasedExtensionStatusProcessor(session, scopeSession) diff --git a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/SealedClassInheritorsProviderIdeImpl.kt b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/SealedClassInheritorsProviderIdeImpl.kt new file mode 100644 index 00000000000..c3645615e47 --- /dev/null +++ b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/SealedClassInheritorsProviderIdeImpl.kt @@ -0,0 +1,70 @@ +/* + * 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.idea.fir.low.level.api + +import com.intellij.openapi.module.Module +import com.intellij.psi.JavaDirectoryService +import com.intellij.psi.PsiPackage +import com.intellij.psi.search.GlobalSearchScope +import com.intellij.psi.search.PackageScope +import com.intellij.psi.search.SearchScope +import com.intellij.psi.search.searches.ClassInheritorsSearch +import org.jetbrains.kotlin.asJava.KotlinAsJavaSupport +import org.jetbrains.kotlin.asJava.toLightClass +import org.jetbrains.kotlin.fir.declarations.* +import org.jetbrains.kotlin.fir.psi +import org.jetbrains.kotlin.idea.util.classIdIfNonLocal +import org.jetbrains.kotlin.idea.util.module +import org.jetbrains.kotlin.name.ClassId +import org.jetbrains.kotlin.psi.KtClass +import org.jetbrains.kotlin.resolve.jvm.KotlinJavaPsiFacade +import java.util.concurrent.ConcurrentHashMap + +class SealedClassInheritorsProviderIdeImpl : SealedClassInheritorsProvider() { + val cache = ConcurrentHashMap>() + + @OptIn(SealedClassInheritorsProviderInternals::class) + override fun getSealedClassInheritors(firClass: FirRegularClass): List { + require(firClass.isSealed) + firClass.sealedInheritorsAttr?.let { return it } + return cache.computeIfAbsent(firClass.classId) { getInheritors(firClass) } + } + + private fun getInheritors(firClass: FirRegularClass): List { + val sealedKtClass = firClass.psi as? KtClass ?: return emptyList() + val module = sealedKtClass.module ?: return emptyList() + val containingPackage = firClass.classId.packageFqName + + val psiPackage = KotlinJavaPsiFacade.getInstance(sealedKtClass.project) + .findPackage(containingPackage.asString(), GlobalSearchScope.moduleScope(module)) + ?: getPackageViaDirectoryService(sealedKtClass) + ?: return emptyList() + + val kotlinAsJavaSupport = KotlinAsJavaSupport.getInstance(sealedKtClass.project) + val lightClass = sealedKtClass.toLightClass() ?: kotlinAsJavaSupport.getFakeLightClass(sealedKtClass) + + val searchScope: SearchScope = getSearchScope(module, psiPackage) + val searchParameters = ClassInheritorsSearch.SearchParameters(lightClass, searchScope, false, true, false) + val subclasses = ClassInheritorsSearch.search(searchParameters) + .mapNotNull { it.classIdIfNonLocal() } + .toMutableList() + + // Enforce a deterministic order on the result. + subclasses.sortBy { it.toString() } + return subclasses + } + + private fun getSearchScope(module: Module, psiPackage: PsiPackage): GlobalSearchScope { + val packageScope = PackageScope(psiPackage, false, false) + // MPP multiple common modules are not supported!! + return module.moduleScope.intersectWith(packageScope) + } + + private fun getPackageViaDirectoryService(ktClass: KtClass): PsiPackage? { + val directory = ktClass.containingFile.containingDirectory ?: return null + return JavaDirectoryService.getInstance().getPackage(directory) + } +} \ No newline at end of file diff --git a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/sessions/FirIdeSessionFactory.kt b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/sessions/FirIdeSessionFactory.kt index 2169f3b7c60..a3985164469 100644 --- a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/sessions/FirIdeSessionFactory.kt +++ b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/sessions/FirIdeSessionFactory.kt @@ -13,15 +13,14 @@ import org.jetbrains.kotlin.fir.PrivateSessionConstructor import org.jetbrains.kotlin.fir.SessionConfiguration import org.jetbrains.kotlin.fir.backend.jvm.FirJvmTypeMapper import org.jetbrains.kotlin.fir.caches.FirCachesFactory -import org.jetbrains.kotlin.fir.checkers.registerCommonCheckers import org.jetbrains.kotlin.fir.checkers.registerExtendedCommonCheckers +import org.jetbrains.kotlin.fir.declarations.SealedClassInheritorsProvider import org.jetbrains.kotlin.fir.dependenciesWithoutSelf import org.jetbrains.kotlin.fir.java.JavaSymbolProvider import org.jetbrains.kotlin.fir.java.deserialization.KotlinDeserializedJvmSymbolsProvider import org.jetbrains.kotlin.fir.resolve.symbolProvider import org.jetbrains.kotlin.fir.resolve.providers.FirProvider import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider -import org.jetbrains.kotlin.fir.resolve.providers.impl.FirBuiltinSymbolProvider import org.jetbrains.kotlin.fir.resolve.providers.impl.FirCloneableSymbolProvider import org.jetbrains.kotlin.fir.resolve.providers.impl.FirCompositeSymbolProvider import org.jetbrains.kotlin.fir.resolve.scopes.wrapScopeWithJvmMapped @@ -33,6 +32,7 @@ import org.jetbrains.kotlin.idea.caches.resolve.IDEPackagePartProvider import org.jetbrains.kotlin.idea.fir.low.level.api.FirPhaseRunner import org.jetbrains.kotlin.idea.fir.low.level.api.IdeFirPhaseManager import org.jetbrains.kotlin.idea.fir.low.level.api.IdeSessionComponents +import org.jetbrains.kotlin.idea.fir.low.level.api.SealedClassInheritorsProviderIdeImpl import org.jetbrains.kotlin.idea.fir.low.level.api.file.builder.FirFileBuilder import org.jetbrains.kotlin.idea.fir.low.level.api.file.builder.ModuleFileCacheImpl import org.jetbrains.kotlin.idea.fir.low.level.api.fir.caches.FirThreadSafeCachesFactory @@ -43,7 +43,6 @@ import org.jetbrains.kotlin.idea.fir.low.level.api.providers.FirIdeLibrariesSess import org.jetbrains.kotlin.idea.fir.low.level.api.providers.FirIdeProvider import org.jetbrains.kotlin.idea.fir.low.level.api.providers.FirModuleWithDependenciesSymbolProvider import org.jetbrains.kotlin.idea.fir.low.level.api.providers.FirThreadSafeSymbolProviderWrapper -import org.jetbrains.kotlin.idea.fir.low.level.api.sessions.FirIdeSessionFactory.registerIdeComponents import org.jetbrains.kotlin.idea.fir.low.level.api.util.ModuleLibrariesSearchScope import org.jetbrains.kotlin.idea.fir.low.level.api.util.checkCanceled import org.jetbrains.kotlin.load.java.JavaClassFinderImpl @@ -232,5 +231,6 @@ internal object FirIdeSessionFactory { private fun FirIdeSession.registerIdeComponents() { register(IdeSessionComponents::class, IdeSessionComponents.create(this)) register(FirCachesFactory::class, FirThreadSafeCachesFactory) + register(SealedClassInheritorsProvider::class, SealedClassInheritorsProviderIdeImpl()) } } diff --git a/idea/idea-frontend-fir/idea-fir-low-level-api/tests/org/jetbrains/kotlin/idea/fir/low/level/api/AbstractFirSealedInheritorsTest.kt b/idea/idea-frontend-fir/idea-fir-low-level-api/tests/org/jetbrains/kotlin/idea/fir/low/level/api/AbstractFirSealedInheritorsTest.kt index f0bc36f5037..09e14d0cc66 100644 --- a/idea/idea-frontend-fir/idea-fir-low-level-api/tests/org/jetbrains/kotlin/idea/fir/low/level/api/AbstractFirSealedInheritorsTest.kt +++ b/idea/idea-frontend-fir/idea-fir-low-level-api/tests/org/jetbrains/kotlin/idea/fir/low/level/api/AbstractFirSealedInheritorsTest.kt @@ -25,7 +25,13 @@ abstract class AbstractFirSealedInheritorsTest : AbstractFirMultiModuleLazyResol override fun checkFirFile(firFile: FirFile, path: String) { val allClasses = firFile.listNestedClasses().closure { it.listNestedClasses() } - val inheritorNames = allClasses.flatMap { it.sealedInheritors ?: emptyList() }.map { it.asString() }.sorted() + val inheritorNames = allClasses.flatMap { firClass -> + if (firClass.isSealed) { + firClass.getSealedClassInheritors(firFile.session) + } else { + emptyList() + } + }.map { it.asString() }.sorted() KotlinTestUtils.assertEqualsToFile(File("$path/expected.txt"), inheritorNames.joinToString("\n")) } }