@NotNull private static Collection<CallableMemberDescriptor> extractMembersOverridableInBothWays( @NotNull CallableMemberDescriptor overrider, @NotNull Queue<CallableMemberDescriptor> extractFrom, @NotNull DescriptorSink sink) { Collection<CallableMemberDescriptor> overridable = new ArrayList<CallableMemberDescriptor>(); overridable.add(overrider); for (Iterator<CallableMemberDescriptor> iterator = extractFrom.iterator(); iterator.hasNext(); ) { CallableMemberDescriptor candidate = iterator.next(); if (overrider == candidate) { iterator.remove(); continue; } OverrideCompatibilityInfo.Result result1 = DEFAULT.isOverridableBy(candidate, overrider).getResult(); OverrideCompatibilityInfo.Result result2 = DEFAULT.isOverridableBy(overrider, candidate).getResult(); if (result1 == OVERRIDABLE && result2 == OVERRIDABLE) { overridable.add(candidate); iterator.remove(); } else if (result1 == CONFLICT || result2 == CONFLICT) { sink.conflict(overrider, candidate); iterator.remove(); } } return overridable; }
@Nullable public static OverrideCompatibilityInfo.Result getBothWaysOverridability( CallableDescriptor overriderDescriptor, CallableDescriptor candidateDescriptor) { OverrideCompatibilityInfo.Result result1 = DEFAULT.isOverridableBy(candidateDescriptor, overriderDescriptor, null).getResult(); OverrideCompatibilityInfo.Result result2 = DEFAULT.isOverridableBy(overriderDescriptor, candidateDescriptor, null).getResult(); return result1 == OVERRIDABLE && result2 == OVERRIDABLE ? OVERRIDABLE : ((result1 == CONFLICT || result2 == CONFLICT) ? CONFLICT : INCOMPATIBLE); }
private static Collection<CallableMemberDescriptor> extractAndBindOverridesForMember( @NotNull CallableMemberDescriptor fromCurrent, @NotNull Collection<? extends CallableMemberDescriptor> descriptorsFromSuper, @NotNull ClassDescriptor current, @NotNull DescriptorSink sink) { Collection<CallableMemberDescriptor> bound = new ArrayList<CallableMemberDescriptor>(descriptorsFromSuper.size()); for (CallableMemberDescriptor fromSupertype : descriptorsFromSuper) { OverrideCompatibilityInfo.Result result = DEFAULT.isOverridableBy(fromSupertype, fromCurrent).getResult(); boolean isVisible = Visibilities.isVisible(ReceiverValue.IRRELEVANT_RECEIVER, fromSupertype, current); switch (result) { case OVERRIDABLE: if (isVisible) { fromCurrent.addOverriddenDescriptor(fromSupertype); } bound.add(fromSupertype); break; case CONFLICT: if (isVisible) { sink.conflict(fromSupertype, fromCurrent); } bound.add(fromSupertype); break; case INCOMPATIBLE: break; } } return bound; }
public static boolean isMoreSpecific( @NotNull CallableDescriptor a, @NotNull CallableDescriptor b) { KotlinType aReturnType = a.getReturnType(); KotlinType bReturnType = b.getReturnType(); assert aReturnType != null : "Return type of " + a + " is null"; assert bReturnType != null : "Return type of " + b + " is null"; if (!isVisibilityMoreSpecific(a, b)) return false; if (a instanceof SimpleFunctionDescriptor) { assert b instanceof SimpleFunctionDescriptor : "b is " + b.getClass(); return isReturnTypeMoreSpecific(a, aReturnType, b, bReturnType); } if (a instanceof PropertyDescriptor) { assert b instanceof PropertyDescriptor : "b is " + b.getClass(); PropertyDescriptor pa = (PropertyDescriptor) a; PropertyDescriptor pb = (PropertyDescriptor) b; if (!isAccessorMoreSpecific(pa.getSetter(), pb.getSetter())) return false; if (pa.isVar() && pb.isVar()) { return DEFAULT .createTypeChecker(a.getTypeParameters(), b.getTypeParameters()) .equalTypes(aReturnType, bReturnType); } else { // both vals or var vs val: val can't be more specific then var return !(!pa.isVar() && pb.isVar()) && isReturnTypeMoreSpecific(a, aReturnType, b, bReturnType); } } throw new IllegalArgumentException("Unexpected callable: " + a.getClass()); }
private static boolean isReturnTypeMoreSpecific( @NotNull CallableDescriptor a, @NotNull KotlinType aReturnType, @NotNull CallableDescriptor b, @NotNull KotlinType bReturnType) { KotlinTypeChecker typeChecker = DEFAULT.createTypeChecker(a.getTypeParameters(), b.getTypeParameters()); return typeChecker.isSubtypeOf(aReturnType, bReturnType); }
@NotNull public static <D extends CallableMemberDescriptor> Collection<D> resolveOverrides( @NotNull Name name, @NotNull Collection<D> membersFromSupertypes, @NotNull Collection<D> membersFromCurrent, @NotNull ClassDescriptor classDescriptor, @NotNull final ErrorReporter errorReporter) { final Set<D> result = new HashSet<D>(); OverridingUtil.generateOverridesInFunctionGroup( name, membersFromSupertypes, membersFromCurrent, classDescriptor, new OverridingUtil.DescriptorSink() { @Override @SuppressWarnings("unchecked") public void addToScope(@NotNull CallableMemberDescriptor fakeOverride) { OverridingUtil.resolveUnknownVisibilityForMember( fakeOverride, new Function1<CallableMemberDescriptor, Unit>() { @Override public Unit invoke(@NotNull CallableMemberDescriptor descriptor) { errorReporter.reportCannotInferVisibility(descriptor); return Unit.INSTANCE$; } }); result.add((D) fakeOverride); } @Override public void conflict( @NotNull CallableMemberDescriptor fromSuper, @NotNull CallableMemberDescriptor fromCurrent) { // nop } }); return result; }
private static Collection<CallableMemberDescriptor> extractAndBindOverridesForMember( @NotNull CallableMemberDescriptor fromCurrent, @NotNull Collection<? extends CallableMemberDescriptor> descriptorsFromSuper, @NotNull ClassDescriptor current, @NotNull OverridingStrategy strategy) { Collection<CallableMemberDescriptor> bound = new ArrayList<CallableMemberDescriptor>(descriptorsFromSuper.size()); Collection<CallableMemberDescriptor> overridden = SmartSet.create(); for (CallableMemberDescriptor fromSupertype : descriptorsFromSuper) { OverrideCompatibilityInfo.Result result = DEFAULT.isOverridableBy(fromSupertype, fromCurrent, current).getResult(); boolean isVisibleForOverride = isVisibleForOverride(fromCurrent, fromSupertype); switch (result) { case OVERRIDABLE: if (isVisibleForOverride) { overridden.add(fromSupertype); } bound.add(fromSupertype); break; case CONFLICT: if (isVisibleForOverride) { strategy.overrideConflict(fromSupertype, fromCurrent); } bound.add(fromSupertype); break; case INCOMPATIBLE: break; } } strategy.setOverriddenDescriptors(fromCurrent, overridden); return bound; }