Refactor createAntBindFakeOverride.

Drop unneeded helper functions from overridingUtils.kt
This commit is contained in:
Dmitry Petrov
2015-12-10 13:30:25 +03:00
committed by Denis Zharkov
parent 19a6cc74de
commit 02311538d6
2 changed files with 47 additions and 73 deletions
@@ -27,6 +27,7 @@ import org.jetbrains.kotlin.descriptors.impl.PropertyAccessorDescriptorImpl;
import org.jetbrains.kotlin.descriptors.impl.PropertyDescriptorImpl;
import org.jetbrains.kotlin.name.Name;
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue;
import org.jetbrains.kotlin.types.FlexibleTypesKt;
import org.jetbrains.kotlin.types.KotlinType;
import org.jetbrains.kotlin.types.TypeConstructor;
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker;
@@ -358,14 +359,53 @@ public class OverridingUtil {
throw new IllegalArgumentException("Unexpected callable: " + a.getClass());
}
private static CallableMemberDescriptor selectMostSpecificMemberFromSuper(@NotNull Collection<CallableMemberDescriptor> overridables) {
CallableMemberDescriptor result = null;
for (CallableMemberDescriptor overridable : overridables) {
if (result == null || isMoreSpecific(overridable, result)) {
result = overridable;
private static boolean isMoreSpecificThenAllOf(@NotNull CallableMemberDescriptor candidate, @NotNull Collection<CallableMemberDescriptor> descriptors) {
// NB subtyping relation in Kotlin is not transitive in presence of flexible types:
// String? <: String! <: String, but not String? <: String
for (CallableMemberDescriptor descriptor : descriptors) {
if (!isMoreSpecific(candidate, descriptor)) {
return false;
}
}
return result;
return true;
}
private static CallableMemberDescriptor selectMostSpecificMemberFromSuper(@NotNull Collection<CallableMemberDescriptor> overridables) {
assert !overridables.isEmpty() : "Should have at least one overridable descriptor";
if (overridables.size() == 1) {
return CollectionsKt.first(overridables);
}
Collection<CallableMemberDescriptor> candidates = new ArrayList<CallableMemberDescriptor>(2);
CallableMemberDescriptor transitivelyMostSpecific = null;
for (CallableMemberDescriptor overridable : overridables) {
if (isMoreSpecificThenAllOf(overridable, overridables)) {
candidates.add(overridable);
}
if (transitivelyMostSpecific == null || isMoreSpecific(overridable, transitivelyMostSpecific)) {
transitivelyMostSpecific = overridable;
}
}
if (candidates.isEmpty()) {
return transitivelyMostSpecific;
}
else if (candidates.size() == 1) {
return CollectionsKt.first(candidates);
}
CallableMemberDescriptor lastNonFlexible = null;
for (CallableMemberDescriptor candidate : candidates) {
if (!FlexibleTypesKt.isFlexible(candidate.getReturnType())) {
lastNonFlexible = candidate;
}
}
if (lastNonFlexible != null) {
return lastNonFlexible;
}
return CollectionsKt.last(candidates);
}
private static void createAndBindFakeOverride(
@@ -386,12 +426,7 @@ public class OverridingUtil {
// Should be 'foo(s: String): String'.
Modality modality = getMinimalModality(effectiveOverridden);
Visibility visibility = allInvisible ? Visibilities.INVISIBLE_FAKE : Visibilities.INHERITED;
CallableMemberDescriptor mostSpecific =
OverridingUtilsKt.getOverriddenWithMostSpecificReturnTypeOrNull(KotlinTypeChecker.DEFAULT, effectiveOverridden);
if (mostSpecific == null) {
// Use some (possibly erroneous) inherited signature. Will be reported as an error later.
mostSpecific = selectMostSpecificMemberFromSuper(effectiveOverridden);
}
CallableMemberDescriptor mostSpecific = selectMostSpecificMemberFromSuper(effectiveOverridden);
CallableMemberDescriptor fakeOverride =
mostSpecific.copy(current, modality, visibility, CallableMemberDescriptor.Kind.FAKE_OVERRIDE, false);
for (CallableMemberDescriptor descriptor : effectiveOverridden) {
@@ -46,64 +46,3 @@ fun <TDescriptor : CallableDescriptor> TDescriptor.findOriginalTopMostOverridden
(it.original as TDescriptor)
}
}
private fun CallableDescriptor.isVar(): Boolean =
this is PropertyDescriptor && isVar
private fun CallableDescriptor.isVal(): Boolean =
this is PropertyDescriptor && !isVar
private fun isMostSpecificByReturnTypeAndKind(
type: KotlinType,
returnTypeOwner: CallableDescriptor,
descriptors: Collection<CallableDescriptor>,
typeChecker: KotlinTypeChecker
): Boolean =
descriptors.all {
otherDescriptor ->
otherDescriptor == returnTypeOwner ||
(!(returnTypeOwner.isVal() && otherDescriptor.isVar()) &&
otherDescriptor.returnType?.let { typeChecker.isSubtypeOf(type, it) } ?: true)
}
fun <TDescriptor : CallableDescriptor> getOverriddenWithMostSpecificReturnTypeOrNull(
typeChecker: KotlinTypeChecker,
descriptors: Collection<TDescriptor>
): TDescriptor? {
val candidates = arrayListOf<TDescriptor>()
// Need this to avoid recursion on lazy types.
if (descriptors.isEmpty()) {
return null
} else if (descriptors.size == 1) {
return descriptors.first()
}
for (descriptor in descriptors) {
val returnType = descriptor.returnType ?: continue
if (isMostSpecificByReturnTypeAndKind(returnType, descriptor, descriptors, typeChecker)) {
candidates.add(descriptor)
}
else if (!TypeUtils.canHaveSubtypes(typeChecker, returnType)) {
return null
}
}
if (candidates.isEmpty()) {
return null
}
var withNonErrorReturnType: TDescriptor? = null
var withNonFlexibleReturnType: TDescriptor? = null
for (candidate in candidates) {
val returnType = candidate.returnType ?: continue
withNonErrorReturnType = candidate
if (!returnType.isFlexible()) {
withNonFlexibleReturnType = candidate
}
}
return withNonFlexibleReturnType ?: withNonErrorReturnType
}