@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; }
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; }
/** * @param <H> is something that handles CallableDescriptor inside * @return */ @NotNull public static <H> Collection<H> extractMembersOverridableInBothWays( @NotNull H overrider, @NotNull @Mutable Collection<H> extractFrom, @NotNull Function1<H, CallableDescriptor> descriptorByHandle, @NotNull Function1<H, Unit> onConflict) { Collection<H> overridable = new ArrayList<H>(); overridable.add(overrider); CallableDescriptor overriderDescriptor = descriptorByHandle.invoke(overrider); for (Iterator<H> iterator = extractFrom.iterator(); iterator.hasNext(); ) { H candidate = iterator.next(); CallableDescriptor candidateDescriptor = descriptorByHandle.invoke(candidate); if (overrider == candidate) { iterator.remove(); continue; } OverrideCompatibilityInfo.Result finalResult = getBothWaysOverridability(overriderDescriptor, candidateDescriptor); if (finalResult == OVERRIDABLE) { overridable.add(candidate); iterator.remove(); } else if (finalResult == CONFLICT) { onConflict.invoke(candidate); iterator.remove(); } } return overridable; }
/** * Given a fake override, finds any declaration of it in the overridden descriptors. Keep in mind * that there may be many declarations of the fake override in the supertypes, this method finds * just the only one. TODO: probably all call-sites of this method are wrong, they should handle * all super-declarations */ @NotNull @SuppressWarnings("unchecked") public static <D extends CallableMemberDescriptor> D unwrapFakeOverride(@NotNull D descriptor) { while (descriptor.getKind() == CallableMemberDescriptor.Kind.FAKE_OVERRIDE) { Collection<? extends CallableMemberDescriptor> overridden = descriptor.getOverriddenDescriptors(); if (overridden.isEmpty()) { throw new IllegalStateException( "Fake override should have at least one overridden descriptor: " + descriptor); } descriptor = (D) overridden.iterator().next(); } return descriptor; }
private static boolean allHasSameContainingDeclaration( @NotNull Collection<CallableMemberDescriptor> notOverridden) { if (notOverridden.size() < 2) return true; final DeclarationDescriptor containingDeclaration = notOverridden.iterator().next().getContainingDeclaration(); return CollectionsKt.all( notOverridden, new Function1<CallableMemberDescriptor, Boolean>() { @Override public Boolean invoke(CallableMemberDescriptor descriptor) { return descriptor.getContainingDeclaration() == containingDeclaration; } }); }
@Nullable public static Visibility findMaxVisibility( @NotNull Collection<? extends CallableMemberDescriptor> descriptors) { if (descriptors.isEmpty()) { return Visibilities.DEFAULT_VISIBILITY; } Visibility maxVisibility = null; for (CallableMemberDescriptor descriptor : descriptors) { Visibility visibility = descriptor.getVisibility(); assert visibility != Visibilities.INHERITED : "Visibility should have been computed for " + descriptor; if (maxVisibility == null) { maxVisibility = visibility; continue; } Integer compareResult = Visibilities.compare(visibility, maxVisibility); if (compareResult == null) { maxVisibility = null; } else if (compareResult > 0) { maxVisibility = visibility; } } if (maxVisibility == null) { return null; } for (CallableMemberDescriptor descriptor : descriptors) { Integer compareResult = Visibilities.compare(maxVisibility, descriptor.getVisibility()); if (compareResult == null || compareResult < 0) { return null; } } return maxVisibility; }
@Nullable private static Visibility findMaxVisibility( @NotNull Collection<? extends CallableMemberDescriptor> descriptors) { if (descriptors.isEmpty()) { return Visibilities.INTERNAL; } Visibility maxVisibility = null; for (CallableMemberDescriptor descriptor : descriptors) { Visibility visibility = descriptor.getVisibility(); assert visibility != Visibilities.INHERITED : "Visibility should have been computed for " + descriptor; if (maxVisibility == null) { maxVisibility = visibility; continue; } Integer compareResult = Visibilities.compare(visibility, maxVisibility); if (compareResult == null) { maxVisibility = null; } else if (compareResult > 0) { maxVisibility = visibility; } } // TODO: IDEA seems to issue an incorrect warning here //noinspection ConstantConditions if (maxVisibility == null) { return null; } for (CallableMemberDescriptor descriptor : descriptors) { Integer compareResult = Visibilities.compare(maxVisibility, descriptor.getVisibility()); if (compareResult == null || compareResult < 0) { return null; } } return maxVisibility; }
private void checkSupertypesForConsistency(@NotNull ClassDescriptor classDescriptor) { Multimap<TypeConstructor, TypeProjection> multimap = SubstitutionUtils.buildDeepSubstitutionMultimap(classDescriptor.getDefaultType()); for (Map.Entry<TypeConstructor, Collection<TypeProjection>> entry : multimap.asMap().entrySet()) { Collection<TypeProjection> projections = entry.getValue(); if (projections.size() > 1) { TypeConstructor typeConstructor = entry.getKey(); DeclarationDescriptor declarationDescriptor = typeConstructor.getDeclarationDescriptor(); assert declarationDescriptor instanceof TypeParameterDescriptor : declarationDescriptor; TypeParameterDescriptor typeParameterDescriptor = (TypeParameterDescriptor) declarationDescriptor; // Immediate arguments of supertypes cannot be projected Set<JetType> conflictingTypes = Sets.newLinkedHashSet(); for (TypeProjection projection : projections) { conflictingTypes.add(projection.getType()); } removeDuplicateTypes(conflictingTypes); if (conflictingTypes.size() > 1) { DeclarationDescriptor containingDeclaration = typeParameterDescriptor.getContainingDeclaration(); assert containingDeclaration instanceof ClassDescriptor : containingDeclaration; JetClassOrObject psiElement = (JetClassOrObject) DescriptorToSourceUtils.getSourceFromDescriptor(classDescriptor); assert psiElement != null; JetDelegationSpecifierList delegationSpecifierList = psiElement.getDelegationSpecifierList(); assert delegationSpecifierList != null; // // trace.getErrorHandler().genericError(delegationSpecifierList.getNode(), "Type parameter // " + typeParameterDescriptor.getName() + " of " + containingDeclaration.getName() + " // has inconsistent values: " + conflictingTypes); trace.report( INCONSISTENT_TYPE_PARAMETER_VALUES.on( delegationSpecifierList, typeParameterDescriptor, (ClassDescriptor) containingDeclaration, conflictingTypes)); } } } }
public static void generateOverridesInFunctionGroup( @SuppressWarnings("UnusedParameters") @NotNull Name name, // DO NOT DELETE THIS PARAMETER: needed to make sure all descriptors have the // same name @NotNull Collection<? extends CallableMemberDescriptor> membersFromSupertypes, @NotNull Collection<? extends CallableMemberDescriptor> membersFromCurrent, @NotNull ClassDescriptor current, @NotNull DescriptorSink sink) { Collection<CallableMemberDescriptor> notOverridden = new LinkedHashSet<CallableMemberDescriptor>(membersFromSupertypes); for (CallableMemberDescriptor fromCurrent : membersFromCurrent) { Collection<CallableMemberDescriptor> bound = extractAndBindOverridesForMember(fromCurrent, membersFromSupertypes, current, sink); notOverridden.removeAll(bound); } createAndBindFakeOverrides(current, notOverridden, sink); }
private static void createAndBindFakeOverride( @NotNull Collection<CallableMemberDescriptor> overridables, @NotNull ClassDescriptor current, @NotNull DescriptorSink sink) { Collection<CallableMemberDescriptor> visibleOverridables = filterVisibleFakeOverrides(current, overridables); boolean allInvisible = visibleOverridables.isEmpty(); Collection<CallableMemberDescriptor> effectiveOverridden = allInvisible ? overridables : visibleOverridables; Modality modality = getMinimalModality(effectiveOverridden); Visibility visibility = allInvisible ? Visibilities.INVISIBLE_FAKE : Visibilities.INHERITED; CallableMemberDescriptor mostSpecific = selectMostSpecificMemberFromSuper(effectiveOverridden); CallableMemberDescriptor fakeOverride = mostSpecific.copy( current, modality, visibility, CallableMemberDescriptor.Kind.FAKE_OVERRIDE, false); for (CallableMemberDescriptor descriptor : effectiveOverridden) { fakeOverride.addOverriddenDescriptor(descriptor); } sink.addFakeOverride(fakeOverride); }
private static void createAndBindFakeOverride( @NotNull Collection<CallableMemberDescriptor> overridables, @NotNull ClassDescriptor current, @NotNull OverridingStrategy strategy) { Collection<CallableMemberDescriptor> visibleOverridables = filterVisibleFakeOverrides(current, overridables); boolean allInvisible = visibleOverridables.isEmpty(); Collection<CallableMemberDescriptor> effectiveOverridden = allInvisible ? overridables : visibleOverridables; Modality modality = determineModality(effectiveOverridden); Visibility visibility = allInvisible ? Visibilities.INVISIBLE_FAKE : Visibilities.INHERITED; // FIXME doesn't work as expected for flexible types: should create a refined signature. // Current algorithm produces bad results in presence of annotated Java signatures such as: // J: foo(s: String!): String -- @NotNull String foo(String s); // K: foo(s: String): String? // --> 'foo(s: String!): String' as an inherited signature with most specific return type. // This is bad because it can be overridden by 'foo(s: String?): String', which is not // override-equivalent with K::foo above. // Should be 'foo(s: String): String'. CallableMemberDescriptor mostSpecific = selectMostSpecificMember( effectiveOverridden, new Function1<CallableMemberDescriptor, CallableDescriptor>() { @Override public CallableMemberDescriptor invoke(CallableMemberDescriptor descriptor) { return descriptor; } }); CallableMemberDescriptor fakeOverride = mostSpecific.copy( current, modality, visibility, CallableMemberDescriptor.Kind.FAKE_OVERRIDE, false); strategy.setOverriddenDescriptors(fakeOverride, effectiveOverridden); assert !fakeOverride.getOverriddenDescriptors().isEmpty() : "Overridden descriptors should be set for " + CallableMemberDescriptor.Kind.FAKE_OVERRIDE; strategy.addFakeOverride(fakeOverride); }
@NotNull public static <H> H selectMostSpecificMember( @NotNull Collection<H> overridables, @NotNull Function1<H, CallableDescriptor> descriptorByHandle) { assert !overridables.isEmpty() : "Should have at least one overridable descriptor"; if (overridables.size() == 1) { return CollectionsKt.first(overridables); } Collection<H> candidates = new ArrayList<H>(2); List<CallableDescriptor> callableMemberDescriptors = CollectionsKt.map(overridables, descriptorByHandle); H transitivelyMostSpecific = CollectionsKt.first(overridables); CallableDescriptor transitivelyMostSpecificDescriptor = descriptorByHandle.invoke(transitivelyMostSpecific); for (H overridable : overridables) { CallableDescriptor descriptor = descriptorByHandle.invoke(overridable); if (isMoreSpecificThenAllOf(descriptor, callableMemberDescriptors)) { candidates.add(overridable); } if (isMoreSpecific(descriptor, transitivelyMostSpecificDescriptor) && !isMoreSpecific(transitivelyMostSpecificDescriptor, descriptor)) { transitivelyMostSpecific = overridable; } } if (candidates.isEmpty()) { return transitivelyMostSpecific; } else if (candidates.size() == 1) { return CollectionsKt.first(candidates); } H firstNonFlexible = null; for (H candidate : candidates) { //noinspection ConstantConditions if (!FlexibleTypesKt.isFlexible(descriptorByHandle.invoke(candidate).getReturnType())) { firstNonFlexible = candidate; break; } } if (firstNonFlexible != null) { return firstNonFlexible; } return CollectionsKt.first(candidates); }
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; }