Refactor createAntBindFakeOverride.
Drop unneeded helper functions from overridingUtils.kt
This commit is contained in:
committed by
Denis Zharkov
parent
19a6cc74de
commit
02311538d6
@@ -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
|
||||
}
|
||||
Reference in New Issue
Block a user