Beispiel #1
0
  @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;
  }
Beispiel #2
0
  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;
  }
Beispiel #3
0
  /**
   * @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;
  }
Beispiel #4
0
  @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);
  }
Beispiel #5
0
  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;
  }