FIR IDE: do not search for sealed class inheritors on every class resolve
This commit is contained in:
@@ -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.analysis.checkers.declaration.FirNameConflictsTracker
|
||||||
import org.jetbrains.kotlin.fir.caches.FirCachesFactory
|
import org.jetbrains.kotlin.fir.caches.FirCachesFactory
|
||||||
import org.jetbrains.kotlin.fir.caches.FirThreadUnsafeCachesFactory
|
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.FirExtensionService
|
||||||
import org.jetbrains.kotlin.fir.extensions.FirPredicateBasedProvider
|
import org.jetbrains.kotlin.fir.extensions.FirPredicateBasedProvider
|
||||||
import org.jetbrains.kotlin.fir.extensions.FirRegisteredPluginAnnotations
|
import org.jetbrains.kotlin.fir.extensions.FirRegisteredPluginAnnotations
|
||||||
@@ -51,6 +53,12 @@ fun FirSession.registerThreadUnsafeCaches() {
|
|||||||
register(FirCachesFactory::class, FirThreadUnsafeCachesFactory)
|
register(FirCachesFactory::class, FirThreadUnsafeCachesFactory)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@OptIn(SessionConfiguration::class)
|
||||||
|
fun FirSession.registerSealedClassInheritorsProvider() {
|
||||||
|
register(SealedClassInheritorsProvider::class, SealedClassInheritorsProviderImpl)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// -------------------------- Resolve components --------------------------
|
// -------------------------- Resolve components --------------------------
|
||||||
|
|
||||||
|
|||||||
@@ -77,6 +77,7 @@ object FirSessionFactory {
|
|||||||
registerCommonComponents(languageVersionSettings)
|
registerCommonComponents(languageVersionSettings)
|
||||||
registerResolveComponents(lookupTracker)
|
registerResolveComponents(lookupTracker)
|
||||||
registerJavaSpecificResolveComponents()
|
registerJavaSpecificResolveComponents()
|
||||||
|
registerSealedClassInheritorsProvider()
|
||||||
|
|
||||||
val kotlinScopeProvider = KotlinScopeProvider(::wrapScopeWithJvmMapped)
|
val kotlinScopeProvider = KotlinScopeProvider(::wrapScopeWithJvmMapped)
|
||||||
|
|
||||||
@@ -127,6 +128,7 @@ object FirSessionFactory {
|
|||||||
return FirLibrarySession(moduleInfo, sessionProvider).apply {
|
return FirLibrarySession(moduleInfo, sessionProvider).apply {
|
||||||
registerThreadUnsafeCaches()
|
registerThreadUnsafeCaches()
|
||||||
registerCommonComponents(languageVersionSettings)
|
registerCommonComponents(languageVersionSettings)
|
||||||
|
registerSealedClassInheritorsProvider()
|
||||||
|
|
||||||
val javaSymbolProvider = JavaSymbolProvider(this, project, scope)
|
val javaSymbolProvider = JavaSymbolProvider(this, project, scope)
|
||||||
|
|
||||||
|
|||||||
+2
-1
@@ -195,9 +195,10 @@ fun deserializeClassToSymbol(
|
|||||||
})
|
})
|
||||||
}.also {
|
}.also {
|
||||||
if (isSealed) {
|
if (isSealed) {
|
||||||
it.sealedInheritors = classProto.sealedSubclassFqNameList.map { nameIndex ->
|
val inheritors = classProto.sealedSubclassFqNameList.map { nameIndex ->
|
||||||
ClassId.fromString(nameResolver.getQualifiedClassName(nameIndex))
|
ClassId.fromString(nameResolver.getQualifiedClassName(nameIndex))
|
||||||
}
|
}
|
||||||
|
it.setSealedClassInheritors(inheritors)
|
||||||
}
|
}
|
||||||
(it.annotations as MutableList<FirAnnotationCall>) +=
|
(it.annotations as MutableList<FirAnnotationCall>) +=
|
||||||
context.annotationDeserializer.loadClassAnnotations(classProto, context.nameResolver)
|
context.annotationDeserializer.loadClassAnnotations(classProto, context.nameResolver)
|
||||||
|
|||||||
+1
-2
@@ -166,8 +166,7 @@ class FirElementSerializer private constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (klass is FirRegularClass && klass.modality == Modality.SEALED) {
|
if (klass is FirRegularClass && klass.modality == Modality.SEALED) {
|
||||||
val inheritors = klass.sealedInheritors
|
val inheritors = klass.getSealedClassInheritors(session)
|
||||||
requireNotNull(inheritors)
|
|
||||||
for (inheritorId in inheritors) {
|
for (inheritorId in inheritors) {
|
||||||
builder.addSealedSubclassFqName(stringTable.getQualifiedClassNameIndex(inheritorId))
|
builder.addSealedSubclassFqName(stringTable.getQualifiedClassNameIndex(inheritorId))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -332,10 +332,11 @@ class JavaSymbolProvider(
|
|||||||
}
|
}
|
||||||
}.apply {
|
}.apply {
|
||||||
if (modality == Modality.SEALED) {
|
if (modality == Modality.SEALED) {
|
||||||
sealedInheritors = javaClass.permittedTypes.mapNotNull { classifierType ->
|
val inheritors = javaClass.permittedTypes.mapNotNull { classifierType ->
|
||||||
val classifier = classifierType.classifier as? JavaClass
|
val classifier = classifierType.classifier as? JavaClass
|
||||||
classifier?.let { JavaToKotlinClassMap.mapJavaToKotlin(it.fqName!!) }
|
classifier?.let { JavaToKotlinClassMap.mapJavaToKotlin(it.fqName!!) }
|
||||||
}
|
}
|
||||||
|
setSealedClassInheritors(inheritors)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (classIsAnnotation) {
|
if (classIsAnnotation) {
|
||||||
|
|||||||
+1
-1
@@ -86,7 +86,7 @@ class FirSealedClassInheritorsProcessor(
|
|||||||
if (regularClass.modality == Modality.SEALED) {
|
if (regularClass.modality == Modality.SEALED) {
|
||||||
val inheritors = inheritorsMap.remove(regularClass)
|
val inheritors = inheritorsMap.remove(regularClass)
|
||||||
if (inheritors != null) {
|
if (inheritors != null) {
|
||||||
regularClass.sealedInheritors = inheritors
|
regularClass.setSealedClassInheritors(inheritors)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (inheritorsMap.isEmpty()) return regularClass.compose()
|
if (inheritorsMap.isEmpty()) return regularClass.compose()
|
||||||
|
|||||||
+1
-1
@@ -313,7 +313,7 @@ private object WhenOnSealedClassExhaustivenessChecker : WhenExhaustivenessChecke
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
when {
|
when {
|
||||||
fir.modality == Modality.SEALED -> fir.sealedInheritors?.forEach {
|
fir.modality == Modality.SEALED -> fir.getSealedClassInheritors(session).forEach {
|
||||||
val symbol = session.symbolProvider.getClassLikeSymbolByFqName(it) as? FirRegularClassSymbol
|
val symbol = session.symbolProvider.getClassLikeSymbolByFqName(it) as? FirRegularClassSymbol
|
||||||
symbol?.collectAllSubclassesTo(destination, session)
|
symbol?.collectAllSubclassesTo(destination, session)
|
||||||
}
|
}
|
||||||
|
|||||||
+35
-2
@@ -5,8 +5,41 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.fir.declarations
|
package org.jetbrains.kotlin.fir.declarations
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.fir.FirSession
|
||||||
|
import org.jetbrains.kotlin.fir.FirSessionComponent
|
||||||
import org.jetbrains.kotlin.name.ClassId
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
|
|
||||||
object SealedClassInheritorsKey : FirDeclarationDataKey()
|
|
||||||
|
|
||||||
var FirRegularClass.sealedInheritors: List<ClassId>? 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<ClassId>
|
||||||
|
}
|
||||||
|
|
||||||
|
private val FirSession.sealedClassInheritorsProvider: SealedClassInheritorsProvider by FirSession.sessionComponentAccessor()
|
||||||
|
|
||||||
|
object SealedClassInheritorsProviderImpl : SealedClassInheritorsProvider() {
|
||||||
|
@OptIn(SealedClassInheritorsProviderInternals::class)
|
||||||
|
override fun getSealedClassInheritors(firClass: FirRegularClass): List<ClassId> {
|
||||||
|
return firClass.sealedInheritorsAttr ?: emptyList()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun FirRegularClass.getSealedClassInheritors(session: FirSession): List<ClassId> {
|
||||||
|
require(this.isSealed)
|
||||||
|
return session.sealedClassInheritorsProvider.getSealedClassInheritors(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
@OptIn(SealedClassInheritorsProviderInternals::class)
|
||||||
|
fun FirRegularClass.setSealedClassInheritors(inheritors: List<ClassId>) {
|
||||||
|
require(this.isSealed)
|
||||||
|
sealedInheritorsAttr = inheritors
|
||||||
|
}
|
||||||
|
|
||||||
|
private object SealedClassInheritorsKey : FirDeclarationDataKey()
|
||||||
|
|
||||||
|
@SealedClassInheritorsProviderInternals
|
||||||
|
var FirRegularClass.sealedInheritorsAttr: List<ClassId>? by FirDeclarationDataRegistry.data(SealedClassInheritorsKey)
|
||||||
|
private set
|
||||||
|
|||||||
-104
@@ -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<Nothing?> = SealedClassInheritorsTransformer
|
|
||||||
|
|
||||||
|
|
||||||
private object SealedClassInheritorsTransformer : FirTransformer<Nothing?>() {
|
|
||||||
override fun <E : FirElement> transformElement(element: E, data: Nothing?): CompositeTransformResult<E> {
|
|
||||||
throw IllegalStateException("Should not be there")
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun transformFile(file: FirFile, data: Nothing?): CompositeTransformResult<FirDeclaration> {
|
|
||||||
val sealedClassInheritorsMap = mutableMapOf<FirRegularClass, MutableList<ClassId>>()
|
|
||||||
file.accept(SealedInheritorsCollector, sealedClassInheritorsMap)
|
|
||||||
|
|
||||||
if (sealedClassInheritorsMap.isEmpty()) return file.compose()
|
|
||||||
return file.transform(FirSealedClassInheritorsProcessor.InheritorsTransformer(sealedClassInheritorsMap), null)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private object SealedInheritorsCollector : FirDefaultVisitor<Unit, MutableMap<FirRegularClass, MutableList<ClassId>>>() {
|
|
||||||
|
|
||||||
override fun visitElement(element: FirElement, data: MutableMap<FirRegularClass, MutableList<ClassId>>) {}
|
|
||||||
|
|
||||||
override fun visitFile(file: FirFile, data: MutableMap<FirRegularClass, MutableList<ClassId>>) {
|
|
||||||
file.declarations.forEach { it.accept(this, data) }
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun visitRegularClass(regularClass: FirRegularClass, data: MutableMap<FirRegularClass, MutableList<ClassId>>) {
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
+1
-1
@@ -81,7 +81,7 @@ internal fun FirResolvePhase.createTransformerBasedProcessorByPhase(
|
|||||||
FirResolvePhase.CLASS_GENERATION -> FirDummyTransformerBasedProcessor(session, scopeSession) // TODO: remove
|
FirResolvePhase.CLASS_GENERATION -> FirDummyTransformerBasedProcessor(session, scopeSession) // TODO: remove
|
||||||
FirResolvePhase.IMPORTS -> FirImportResolveProcessor(session, scopeSession)
|
FirResolvePhase.IMPORTS -> FirImportResolveProcessor(session, scopeSession)
|
||||||
FirResolvePhase.SUPER_TYPES -> FirSupertypeResolverProcessor(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.TYPES -> FirTypeResolveProcessor(session, scopeSession)
|
||||||
FirResolvePhase.ARGUMENTS_OF_PLUGIN_ANNOTATIONS -> FirAnnotationArgumentsResolveProcessor(session, scopeSession)
|
FirResolvePhase.ARGUMENTS_OF_PLUGIN_ANNOTATIONS -> FirAnnotationArgumentsResolveProcessor(session, scopeSession)
|
||||||
FirResolvePhase.EXTENSION_STATUS_UPDATE -> FirTransformerBasedExtensionStatusProcessor(session, scopeSession)
|
FirResolvePhase.EXTENSION_STATUS_UPDATE -> FirTransformerBasedExtensionStatusProcessor(session, scopeSession)
|
||||||
|
|||||||
+70
@@ -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<ClassId, List<ClassId>>()
|
||||||
|
|
||||||
|
@OptIn(SealedClassInheritorsProviderInternals::class)
|
||||||
|
override fun getSealedClassInheritors(firClass: FirRegularClass): List<ClassId> {
|
||||||
|
require(firClass.isSealed)
|
||||||
|
firClass.sealedInheritorsAttr?.let { return it }
|
||||||
|
return cache.computeIfAbsent(firClass.classId) { getInheritors(firClass) }
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getInheritors(firClass: FirRegularClass): List<ClassId> {
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
+3
-3
@@ -13,15 +13,14 @@ import org.jetbrains.kotlin.fir.PrivateSessionConstructor
|
|||||||
import org.jetbrains.kotlin.fir.SessionConfiguration
|
import org.jetbrains.kotlin.fir.SessionConfiguration
|
||||||
import org.jetbrains.kotlin.fir.backend.jvm.FirJvmTypeMapper
|
import org.jetbrains.kotlin.fir.backend.jvm.FirJvmTypeMapper
|
||||||
import org.jetbrains.kotlin.fir.caches.FirCachesFactory
|
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.checkers.registerExtendedCommonCheckers
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.SealedClassInheritorsProvider
|
||||||
import org.jetbrains.kotlin.fir.dependenciesWithoutSelf
|
import org.jetbrains.kotlin.fir.dependenciesWithoutSelf
|
||||||
import org.jetbrains.kotlin.fir.java.JavaSymbolProvider
|
import org.jetbrains.kotlin.fir.java.JavaSymbolProvider
|
||||||
import org.jetbrains.kotlin.fir.java.deserialization.KotlinDeserializedJvmSymbolsProvider
|
import org.jetbrains.kotlin.fir.java.deserialization.KotlinDeserializedJvmSymbolsProvider
|
||||||
import org.jetbrains.kotlin.fir.resolve.symbolProvider
|
import org.jetbrains.kotlin.fir.resolve.symbolProvider
|
||||||
import org.jetbrains.kotlin.fir.resolve.providers.FirProvider
|
import org.jetbrains.kotlin.fir.resolve.providers.FirProvider
|
||||||
import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider
|
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.FirCloneableSymbolProvider
|
||||||
import org.jetbrains.kotlin.fir.resolve.providers.impl.FirCompositeSymbolProvider
|
import org.jetbrains.kotlin.fir.resolve.providers.impl.FirCompositeSymbolProvider
|
||||||
import org.jetbrains.kotlin.fir.resolve.scopes.wrapScopeWithJvmMapped
|
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.FirPhaseRunner
|
||||||
import org.jetbrains.kotlin.idea.fir.low.level.api.IdeFirPhaseManager
|
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.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.FirFileBuilder
|
||||||
import org.jetbrains.kotlin.idea.fir.low.level.api.file.builder.ModuleFileCacheImpl
|
import org.jetbrains.kotlin.idea.fir.low.level.api.file.builder.ModuleFileCacheImpl
|
||||||
import org.jetbrains.kotlin.idea.fir.low.level.api.fir.caches.FirThreadSafeCachesFactory
|
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.FirIdeProvider
|
||||||
import org.jetbrains.kotlin.idea.fir.low.level.api.providers.FirModuleWithDependenciesSymbolProvider
|
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.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.ModuleLibrariesSearchScope
|
||||||
import org.jetbrains.kotlin.idea.fir.low.level.api.util.checkCanceled
|
import org.jetbrains.kotlin.idea.fir.low.level.api.util.checkCanceled
|
||||||
import org.jetbrains.kotlin.load.java.JavaClassFinderImpl
|
import org.jetbrains.kotlin.load.java.JavaClassFinderImpl
|
||||||
@@ -232,5 +231,6 @@ internal object FirIdeSessionFactory {
|
|||||||
private fun FirIdeSession.registerIdeComponents() {
|
private fun FirIdeSession.registerIdeComponents() {
|
||||||
register(IdeSessionComponents::class, IdeSessionComponents.create(this))
|
register(IdeSessionComponents::class, IdeSessionComponents.create(this))
|
||||||
register(FirCachesFactory::class, FirThreadSafeCachesFactory)
|
register(FirCachesFactory::class, FirThreadSafeCachesFactory)
|
||||||
|
register(SealedClassInheritorsProvider::class, SealedClassInheritorsProviderIdeImpl())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+7
-1
@@ -25,7 +25,13 @@ abstract class AbstractFirSealedInheritorsTest : AbstractFirMultiModuleLazyResol
|
|||||||
|
|
||||||
override fun checkFirFile(firFile: FirFile, path: String) {
|
override fun checkFirFile(firFile: FirFile, path: String) {
|
||||||
val allClasses = firFile.listNestedClasses().closure { it.listNestedClasses() }
|
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"))
|
KotlinTestUtils.assertEqualsToFile(File("$path/expected.txt"), inheritorNames.joinToString("\n"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user