Do not force overridden descriptors computation

Currently 'overriddenDescriptors' of substituted function is lazy
and in most cases it's unnecessary to compute it
(it's enough to use the same field from 'original')
This commit is contained in:
Denis Zharkov
2016-02-03 12:05:53 +03:00
parent 9e3d381eb3
commit 18e7272a1e
7 changed files with 17 additions and 9 deletions
@@ -77,7 +77,7 @@ fun getEffectiveVariance(parameterVariance: Variance, projectionKind: Variance):
val CallableDescriptor?.isMethodWithDeclarationSiteWildcards: Boolean val CallableDescriptor?.isMethodWithDeclarationSiteWildcards: Boolean
get() { get() {
if (this !is CallableMemberDescriptor) return false if (this !is CallableMemberDescriptor) return false
return firstOverridden { return original.firstOverridden(useOriginal = true) {
METHODS_WITH_DECLARATION_SITE_WILDCARDS.contains(it.propertyIfAccessor.fqNameOrNull()) METHODS_WITH_DECLARATION_SITE_WILDCARDS.contains(it.propertyIfAccessor.fqNameOrNull())
} != null } != null
} }
@@ -117,7 +117,7 @@ public class SamAdapterOverridabilityCondition implements ExternalOverridability
return new SamAdapterInfo(samAdapter, ownerType); return new SamAdapterInfo(samAdapter, ownerType);
} }
for (CallableMemberDescriptor overridden : samAdapter.getOverriddenDescriptors()) { for (CallableMemberDescriptor overridden : samAdapter.getOriginal().getOverriddenDescriptors()) {
ClassDescriptor containingClass = (ClassDescriptor) overridden.getContainingDeclaration(); ClassDescriptor containingClass = (ClassDescriptor) overridden.getContainingDeclaration();
for (KotlinType immediateSupertype : TypeUtils.getImmediateSupertypes(ownerType)) { for (KotlinType immediateSupertype : TypeUtils.getImmediateSupertypes(ownerType)) {
@@ -99,7 +99,7 @@ private fun deprecationByOverridden(root: CallableMemberDescriptor): Deprecation
visited.add(node) visited.add(node)
val deprecatedAnnotation = node.getDeprecationByAnnotation() val deprecatedAnnotation = node.getDeprecationByAnnotation()
val overriddenDescriptors = node.overriddenDescriptors val overriddenDescriptors = node.original.overriddenDescriptors
when { when {
deprecatedAnnotation != null -> { deprecatedAnnotation != null -> {
deprecations.add(deprecatedAnnotation) deprecations.add(deprecatedAnnotation)
@@ -142,6 +142,8 @@ object BuiltinMethodsWithSpecialGenericSignature {
@JvmStatic @JvmStatic
fun CallableMemberDescriptor.getSpecialSignatureInfo(): SpecialSignatureInfo? { fun CallableMemberDescriptor.getSpecialSignatureInfo(): SpecialSignatureInfo? {
if (name !in ERASED_VALUE_PARAMETERS_SHORT_NAMES) return null
val builtinFqName = firstOverridden { it is FunctionDescriptor && it.hasErasedValueParametersInJava }?.fqNameOrNull() val builtinFqName = firstOverridden { it is FunctionDescriptor && it.hasErasedValueParametersInJava }?.fqNameOrNull()
?: return null ?: return null
@@ -35,6 +35,12 @@ public interface FunctionDescriptor extends CallableMemberDescriptor {
@Override @Override
FunctionDescriptor substitute(@NotNull TypeSubstitutor substitutor); FunctionDescriptor substitute(@NotNull TypeSubstitutor substitutor);
/**
* This method should be used with q Wgreat care, because if descriptor is substituted one, calling 'getOverriddenDescriptors'
* may force lazy computation, that's unnecessary in most cases.
* So, if 'getOriginal().getOverriddenDescriptors()' is enough for you, please use it instead.
* @return
*/
@Override @Override
@NotNull @NotNull
Collection<? extends FunctionDescriptor> getOverriddenDescriptors(); Collection<? extends FunctionDescriptor> getOverriddenDescriptors();
@@ -196,7 +196,7 @@ public abstract class FunctionDescriptorImpl extends DeclarationDescriptorNonRoo
public boolean isOperator() { public boolean isOperator() {
if (isOperator) return true; if (isOperator) return true;
for (FunctionDescriptor descriptor : getOverriddenDescriptors()) { for (FunctionDescriptor descriptor : getOriginal().getOverriddenDescriptors()) {
if (descriptor.isOperator()) return true; if (descriptor.isOperator()) return true;
} }
@@ -207,7 +207,7 @@ public abstract class FunctionDescriptorImpl extends DeclarationDescriptorNonRoo
public boolean isInfix() { public boolean isInfix() {
if (isInfix) return true; if (isInfix) return true;
for (FunctionDescriptor descriptor : getOverriddenDescriptors()) { for (FunctionDescriptor descriptor : getOriginal().getOverriddenDescriptors()) {
if (descriptor.isInfix()) return true; if (descriptor.isInfix()) return true;
} }
@@ -210,14 +210,14 @@ val CallableMemberDescriptor.propertyIfAccessor: CallableMemberDescriptor
fun CallableDescriptor.fqNameOrNull(): FqName? = fqNameUnsafe.check { it.isSafe }?.toSafe() fun CallableDescriptor.fqNameOrNull(): FqName? = fqNameUnsafe.check { it.isSafe }?.toSafe()
fun CallableMemberDescriptor.firstOverridden( fun CallableMemberDescriptor.firstOverridden(
useOriginal: Boolean = false,
predicate: (CallableMemberDescriptor) -> Boolean predicate: (CallableMemberDescriptor) -> Boolean
): CallableMemberDescriptor? { ): CallableMemberDescriptor? {
var result: CallableMemberDescriptor? = null var result: CallableMemberDescriptor? = null
return DFS.dfs(listOf(this), return DFS.dfs(listOf(this),
object : DFS.Neighbors<CallableMemberDescriptor> { { current ->
override fun getNeighbors(current: CallableMemberDescriptor?): Iterable<CallableMemberDescriptor> { val descriptor = if (useOriginal) current?.original else current
return current?.overriddenDescriptors ?: emptyList() descriptor?.overriddenDescriptors ?: emptyList()
}
}, },
object : DFS.AbstractNodeHandler<CallableMemberDescriptor, CallableMemberDescriptor?>() { object : DFS.AbstractNodeHandler<CallableMemberDescriptor, CallableMemberDescriptor?>() {
override fun beforeChildren(current: CallableMemberDescriptor) = result == null override fun beforeChildren(current: CallableMemberDescriptor) = result == null