Optimize completion for overridden descriptors
This commit is contained in:
@@ -233,3 +233,20 @@ fun CallableMemberDescriptor.overriddenTreeAsSequence(useOriginal: Boolean): Seq
|
|||||||
with(if (useOriginal) original else this) {
|
with(if (useOriginal) original else this) {
|
||||||
sequenceOf(this) + overriddenDescriptors.asSequence().flatMap { it.overriddenTreeAsSequence(useOriginal) }
|
sequenceOf(this) + overriddenDescriptors.asSequence().flatMap { it.overriddenTreeAsSequence(useOriginal) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun CallableDescriptor.overriddenTreeUniqueAsSequence(useOriginal: Boolean): Sequence<CallableDescriptor> {
|
||||||
|
val set = hashSetOf<CallableDescriptor>()
|
||||||
|
|
||||||
|
fun CallableDescriptor.doBuildOverriddenTreeAsSequence(): Sequence<CallableDescriptor> {
|
||||||
|
return with(if (useOriginal) original else this) {
|
||||||
|
if (original in set)
|
||||||
|
emptySequence()
|
||||||
|
else {
|
||||||
|
set += original
|
||||||
|
sequenceOf(this) + overriddenDescriptors.asSequence().flatMap { it.doBuildOverriddenTreeAsSequence() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return doBuildOverriddenTreeAsSequence()
|
||||||
|
}
|
||||||
|
|||||||
+39
-20
@@ -33,6 +33,7 @@ import org.jetbrains.kotlin.renderer.DescriptorRenderer
|
|||||||
import org.jetbrains.kotlin.renderer.render
|
import org.jetbrains.kotlin.renderer.render
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.hasDefaultValue
|
import org.jetbrains.kotlin.resolve.descriptorUtil.hasDefaultValue
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.isExtension
|
import org.jetbrains.kotlin.resolve.descriptorUtil.isExtension
|
||||||
|
import org.jetbrains.kotlin.resolve.descriptorUtil.overriddenTreeUniqueAsSequence
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.parentsWithSelf
|
import org.jetbrains.kotlin.resolve.descriptorUtil.parentsWithSelf
|
||||||
import org.jetbrains.kotlin.resolve.findOriginalTopMostOverriddenDescriptors
|
import org.jetbrains.kotlin.resolve.findOriginalTopMostOverriddenDescriptors
|
||||||
import org.jetbrains.kotlin.synthetic.SamAdapterExtensionFunctionDescriptor
|
import org.jetbrains.kotlin.synthetic.SamAdapterExtensionFunctionDescriptor
|
||||||
@@ -269,11 +270,6 @@ class LookupElementFactory(
|
|||||||
if (receiverTypes == null) return null
|
if (receiverTypes == null) return null
|
||||||
if (descriptor !is CallableDescriptor) return null
|
if (descriptor !is CallableDescriptor) return null
|
||||||
|
|
||||||
val overridden = descriptor.overriddenDescriptors
|
|
||||||
if (overridden.isNotEmpty()) {
|
|
||||||
return overridden.map { callableWeight(it)!! }.min()!!
|
|
||||||
}
|
|
||||||
|
|
||||||
// don't treat synthetic extensions as real extensions
|
// don't treat synthetic extensions as real extensions
|
||||||
if (descriptor is SyntheticJavaPropertyDescriptor) {
|
if (descriptor is SyntheticJavaPropertyDescriptor) {
|
||||||
return callableWeight(descriptor.getMethod)
|
return callableWeight(descriptor.getMethod)
|
||||||
@@ -282,29 +278,52 @@ class LookupElementFactory(
|
|||||||
return callableWeight(descriptor.sourceFunction)
|
return callableWeight(descriptor.sourceFunction)
|
||||||
}
|
}
|
||||||
|
|
||||||
val receiverParameter = descriptor.extensionReceiverParameter ?: descriptor.dispatchReceiverParameter
|
if (descriptor.overriddenDescriptors.isNotEmpty()) {
|
||||||
if (receiverParameter != null) {
|
// Optimization: when one of direct overridden fits, then nothing can fit better
|
||||||
return if (receiverTypes.any { TypeUtils.equalTypes(it, receiverParameter.type) }) {
|
descriptor.overriddenDescriptors.mapNotNull {
|
||||||
when {
|
it.callableWeightBasedOnReceiver(receiverTypes, onReceiverTypeMismatch = null)
|
||||||
descriptor.isExtensionForTypeParameter() -> CallableWeight.typeParameterExtension
|
}.min()?.let { return it }
|
||||||
descriptor.isExtension -> CallableWeight.thisTypeExtension
|
|
||||||
else -> CallableWeight.thisClassMember
|
val overridden = descriptor.overriddenTreeUniqueAsSequence(useOriginal = false)
|
||||||
}
|
return overridden.map { callableWeightBasic(it, receiverTypes)!! }.min()!!
|
||||||
}
|
|
||||||
else if (receiverTypes.any { it.isSubtypeOf(receiverParameter.type) }) {
|
|
||||||
if (descriptor.isExtension) CallableWeight.baseTypeExtension else CallableWeight.baseClassMember
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
CallableWeight.receiverCastRequired
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return callableWeightBasic(descriptor, receiverTypes)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun callableWeightBasic(descriptor: CallableDescriptor, receiverTypes: Collection<KotlinType>): CallableWeight? {
|
||||||
|
descriptor.callableWeightBasedOnReceiver(receiverTypes, CallableWeight.receiverCastRequired)?.let { return it }
|
||||||
|
|
||||||
return when (descriptor.containingDeclaration) {
|
return when (descriptor.containingDeclaration) {
|
||||||
is PackageFragmentDescriptor, is ClassifierDescriptor -> CallableWeight.globalOrStatic
|
is PackageFragmentDescriptor, is ClassifierDescriptor -> CallableWeight.globalOrStatic
|
||||||
else -> CallableWeight.local
|
else -> CallableWeight.local
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun CallableDescriptor.callableWeightBasedOnReceiver(
|
||||||
|
receiverTypes: Collection<KotlinType>,
|
||||||
|
onReceiverTypeMismatch: CallableWeight?
|
||||||
|
): CallableWeight? {
|
||||||
|
val receiverParameter = extensionReceiverParameter ?: dispatchReceiverParameter
|
||||||
|
if (receiverParameter != null) {
|
||||||
|
return if (receiverTypes.any { TypeUtils.equalTypes(it, receiverParameter.type) }) {
|
||||||
|
when {
|
||||||
|
isExtensionForTypeParameter() -> CallableWeight.typeParameterExtension
|
||||||
|
isExtension -> CallableWeight.thisTypeExtension
|
||||||
|
else -> CallableWeight.thisClassMember
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (receiverTypes.any { it.isSubtypeOf(receiverParameter.type) }) {
|
||||||
|
if (isExtension) CallableWeight.baseTypeExtension else CallableWeight.baseClassMember
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
onReceiverTypeMismatch
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
private fun CallableDescriptor.isExtensionForTypeParameter(): Boolean {
|
private fun CallableDescriptor.isExtensionForTypeParameter(): Boolean {
|
||||||
val receiverParameter = original.extensionReceiverParameter ?: return false
|
val receiverParameter = original.extensionReceiverParameter ?: return false
|
||||||
val typeParameter = receiverParameter.type.constructor.declarationDescriptor as? TypeParameterDescriptor ?: return false
|
val typeParameter = receiverParameter.type.constructor.declarationDescriptor as? TypeParameterDescriptor ?: return false
|
||||||
|
|||||||
Reference in New Issue
Block a user