[FE] Extract computation of sealed class inheritors into separate component
This is needed to provide more optimal provider in IDE plugin
This commit is contained in:
committed by
TeamCityServer
parent
c0a1aecf9b
commit
6809adee9c
@@ -374,43 +374,6 @@ fun ClassifierDescriptor.getAllSuperClassifiers(): Sequence<ClassifierDescriptor
|
||||
return doGetAllSuperClassesAndInterfaces()
|
||||
}
|
||||
|
||||
// Note this is a generic and slow implementation which would work almost for any subclass of ClassDescriptor.
|
||||
// Please avoid using it in new code.
|
||||
// TODO: do something more clever instead at call sites of this function
|
||||
fun computeSealedSubclasses(sealedClass: ClassDescriptor, freedomForSealedInterfacesSupported: Boolean): Collection<ClassDescriptor> {
|
||||
if (sealedClass.modality != Modality.SEALED) return emptyList()
|
||||
|
||||
val result = linkedSetOf<ClassDescriptor>()
|
||||
|
||||
fun collectSubclasses(scope: MemberScope, collectNested: Boolean) {
|
||||
for (descriptor in scope.getContributedDescriptors(DescriptorKindFilter.CLASSIFIERS)) {
|
||||
if (descriptor !is ClassDescriptor) continue
|
||||
|
||||
if (DescriptorUtils.isDirectSubclass(descriptor, sealedClass)) {
|
||||
result.add(descriptor)
|
||||
}
|
||||
|
||||
if (collectNested) {
|
||||
collectSubclasses(descriptor.unsubstitutedInnerClassesScope, collectNested)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val container = if (!freedomForSealedInterfacesSupported) {
|
||||
sealedClass.containingDeclaration
|
||||
} else {
|
||||
sealedClass.parents.firstOrNull { it is PackageFragmentDescriptor }
|
||||
}
|
||||
if (container is PackageFragmentDescriptor) {
|
||||
collectSubclasses(
|
||||
container.getMemberScope(),
|
||||
collectNested = freedomForSealedInterfacesSupported
|
||||
)
|
||||
}
|
||||
collectSubclasses(sealedClass.unsubstitutedInnerClassesScope, collectNested = true)
|
||||
return result
|
||||
}
|
||||
|
||||
fun DeclarationDescriptor.isPublishedApi(): Boolean {
|
||||
val descriptor = if (this is CallableMemberDescriptor) DescriptorUtils.getDirectMember(this) else this
|
||||
return descriptor.annotations.hasAnnotation(StandardNames.FqNames.publishedApi)
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright 2010-2020 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.resolve
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.parents
|
||||
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
|
||||
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
||||
|
||||
abstract class SealedClassInheritorsProvider {
|
||||
abstract fun computeSealedSubclasses(
|
||||
sealedClass: ClassDescriptor,
|
||||
freedomForSealedInterfacesSupported: Boolean
|
||||
): Collection<ClassDescriptor>
|
||||
}
|
||||
|
||||
object SealedClassInheritorsProviderImpl : SealedClassInheritorsProvider() {
|
||||
// Note this is a generic and slow implementation which would work almost for any subclass of ClassDescriptor.
|
||||
// Please avoid using it in new code.
|
||||
// TODO: do something more clever instead at call sites of this function
|
||||
override fun computeSealedSubclasses(
|
||||
sealedClass: ClassDescriptor,
|
||||
freedomForSealedInterfacesSupported: Boolean
|
||||
): Collection<ClassDescriptor> {
|
||||
if (sealedClass.modality != Modality.SEALED) return emptyList()
|
||||
|
||||
val result = linkedSetOf<ClassDescriptor>()
|
||||
|
||||
fun collectSubclasses(scope: MemberScope, collectNested: Boolean) {
|
||||
for (descriptor in scope.getContributedDescriptors(DescriptorKindFilter.CLASSIFIERS)) {
|
||||
if (descriptor !is ClassDescriptor) continue
|
||||
|
||||
if (DescriptorUtils.isDirectSubclass(descriptor, sealedClass)) {
|
||||
result.add(descriptor)
|
||||
}
|
||||
|
||||
if (collectNested) {
|
||||
collectSubclasses(descriptor.unsubstitutedInnerClassesScope, collectNested)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val container = if (!freedomForSealedInterfacesSupported) {
|
||||
sealedClass.containingDeclaration
|
||||
} else {
|
||||
sealedClass.parents.firstOrNull { it is PackageFragmentDescriptor }
|
||||
}
|
||||
if (container is PackageFragmentDescriptor) {
|
||||
collectSubclasses(
|
||||
container.getMemberScope(),
|
||||
collectNested = freedomForSealedInterfacesSupported
|
||||
)
|
||||
}
|
||||
collectSubclasses(sealedClass.unsubstitutedInnerClassesScope, collectNested = true)
|
||||
return result
|
||||
}
|
||||
|
||||
}
|
||||
@@ -27,6 +27,7 @@ import org.jetbrains.kotlin.metadata.ProtoBuf
|
||||
import org.jetbrains.kotlin.metadata.deserialization.*
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.protobuf.ExtensionRegistryLite
|
||||
import org.jetbrains.kotlin.resolve.SealedClassInheritorsProvider
|
||||
import org.jetbrains.kotlin.resolve.constants.ConstantValue
|
||||
import org.jetbrains.kotlin.resolve.sam.SamConversionResolver
|
||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource
|
||||
|
||||
+2
-2
@@ -18,8 +18,8 @@ import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.DescriptorFactory
|
||||
import org.jetbrains.kotlin.resolve.NonReportingOverrideStrategy
|
||||
import org.jetbrains.kotlin.resolve.OverridingUtil
|
||||
import org.jetbrains.kotlin.resolve.SealedClassInheritorsProviderImpl
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.classId
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.computeSealedSubclasses
|
||||
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
|
||||
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
||||
import org.jetbrains.kotlin.resolve.scopes.StaticScopeForKotlinEnum
|
||||
@@ -165,7 +165,7 @@ class DeserializedClassDescriptor(
|
||||
}
|
||||
|
||||
// This is needed because classes compiled with Kotlin 1.0 did not contain the sealed_subclass_fq_name field
|
||||
return computeSealedSubclasses(this, freedomForSealedInterfacesSupported = false)
|
||||
return SealedClassInheritorsProviderImpl.computeSealedSubclasses(this, freedomForSealedInterfacesSupported = false)
|
||||
}
|
||||
|
||||
override fun getSealedSubclasses() = sealedSubclasses()
|
||||
|
||||
Reference in New Issue
Block a user