Move some utilities from OverridingUtil to OverrideResolver

OverridingUtil will be present at runtime and we should strive to minimize the
size of our runtime classes

Also add a comment to getOverriddenDescriptors()
This commit is contained in:
Alexander Udalov
2014-03-28 15:09:04 +04:00
parent 3dffd428ad
commit 34e7584aec
18 changed files with 292 additions and 295 deletions
@@ -18,22 +18,20 @@ package org.jetbrains.jet.lang.resolve;
import com.google.common.base.Predicate;
import com.google.common.collect.*;
import com.intellij.util.Function;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.ReadOnly;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.descriptors.impl.FunctionDescriptorImpl;
import org.jetbrains.jet.lang.descriptors.impl.PropertyAccessorDescriptorImpl;
import org.jetbrains.jet.lang.descriptors.impl.PropertyDescriptorImpl;
import org.jetbrains.jet.lang.resolve.name.Name;
import org.jetbrains.jet.lang.types.*;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.TypeConstructor;
import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
import java.util.*;
import static org.jetbrains.jet.lang.descriptors.CallableMemberDescriptor.Kind.*;
import static org.jetbrains.jet.lang.resolve.OverridingUtil.OverrideCompatibilityInfo.Result.CONFLICT;
import static org.jetbrains.jet.lang.resolve.OverridingUtil.OverrideCompatibilityInfo.Result.OVERRIDABLE;
@@ -48,96 +46,6 @@ public class OverridingUtil {
private OverridingUtil() {
}
private static enum Filtering {
RETAIN_OVERRIDING,
RETAIN_OVERRIDDEN
}
@NotNull
public static <D extends CallableDescriptor> Set<D> filterOutOverridden(@NotNull Set<D> candidateSet) {
//noinspection unchecked
return filterOverrides(candidateSet, Function.ID, Filtering.RETAIN_OVERRIDING);
}
@NotNull
public static <D> Set<D> filterOutOverriding(@NotNull Set<D> candidateSet) {
//noinspection unchecked
return filterOverrides(candidateSet, Function.ID, Filtering.RETAIN_OVERRIDDEN);
}
@NotNull
public static <D> Set<D> filterOutOverridden(
@NotNull Set<D> candidateSet,
@NotNull Function<? super D, ? extends CallableDescriptor> transform
) {
return filterOverrides(candidateSet, transform, Filtering.RETAIN_OVERRIDING);
}
@NotNull
private static <D> Set<D> filterOverrides(
@NotNull Set<D> candidateSet,
@NotNull Function<? super D, ? extends CallableDescriptor> transform,
@NotNull Filtering filtering
) {
Set<D> candidates = Sets.newLinkedHashSet();
outerLoop:
for (D meD : candidateSet) {
CallableDescriptor me = transform.fun(meD);
for (D otherD : candidateSet) {
CallableDescriptor other = transform.fun(otherD);
if (me == other) continue;
if (filtering == Filtering.RETAIN_OVERRIDING) {
if (overrides(other, me)) {
continue outerLoop;
}
}
else if (filtering == Filtering.RETAIN_OVERRIDDEN) {
if (overrides(me, other)) {
continue outerLoop;
}
}
else {
throw new AssertionError("Unexpected Filtering object: " + filtering);
}
}
for (D otherD : candidates) {
CallableDescriptor other = transform.fun(otherD);
if (me.getOriginal() == other.getOriginal()
&& isOverridableBy(other, me).getResult() == OverrideCompatibilityInfo.Result.OVERRIDABLE
&& isOverridableBy(me, other).getResult() == OverrideCompatibilityInfo.Result.OVERRIDABLE) {
continue outerLoop;
}
}
candidates.add(meD);
}
return candidates;
}
public static <D extends CallableDescriptor> boolean overrides(@NotNull D f, @NotNull D g) {
CallableDescriptor originalG = g.getOriginal();
for (CallableDescriptor overriddenFunction : getAllOverriddenDescriptors(f)) {
if (originalG.equals(overriddenFunction.getOriginal())) return true;
}
return false;
}
public static Set<CallableDescriptor> getAllOverriddenDescriptors(CallableDescriptor f) {
Set<CallableDescriptor> overriddenDescriptors = Sets.newHashSet();
collectAllOverriddenDescriptors(f.getOriginal(), overriddenDescriptors);
return overriddenDescriptors;
}
private static void collectAllOverriddenDescriptors(
@NotNull CallableDescriptor current,
@NotNull Set<CallableDescriptor> result
) {
if (result.contains(current)) return;
for (CallableDescriptor descriptor : current.getOriginal().getOverriddenDescriptors()) {
collectAllOverriddenDescriptors(descriptor, result);
result.add(descriptor);
}
}
@NotNull
public static OverrideCompatibilityInfo isOverridableBy(@NotNull CallableDescriptor superDescriptor, @NotNull CallableDescriptor subDescriptor) {
if (superDescriptor instanceof FunctionDescriptor) {
@@ -271,77 +179,6 @@ public class OverridingUtil {
}
}
public static boolean isReturnTypeOkForOverride(@NotNull JetTypeChecker typeChecker, @NotNull CallableDescriptor superDescriptor, @NotNull CallableDescriptor subDescriptor) {
TypeSubstitutor typeSubstitutor = prepareTypeSubstitutor(superDescriptor, subDescriptor);
if (typeSubstitutor == null) return false;
JetType superReturnType = superDescriptor.getReturnType();
assert superReturnType != null;
JetType subReturnType = subDescriptor.getReturnType();
assert subReturnType != null;
JetType substitutedSuperReturnType = typeSubstitutor.substitute(superReturnType, Variance.OUT_VARIANCE);
assert substitutedSuperReturnType != null;
return typeChecker.isSubtypeOf(subReturnType, substitutedSuperReturnType);
}
@Nullable
private static TypeSubstitutor prepareTypeSubstitutor(@NotNull CallableDescriptor superDescriptor, @NotNull CallableDescriptor subDescriptor) {
List<TypeParameterDescriptor> superTypeParameters = superDescriptor.getTypeParameters();
List<TypeParameterDescriptor> subTypeParameters = subDescriptor.getTypeParameters();
if (subTypeParameters.size() != superTypeParameters.size()) return null;
Map<TypeConstructor, TypeProjection> substitutionContext = Maps.newHashMap();
for (int i = 0; i < superTypeParameters.size(); i++) {
substitutionContext.put(
superTypeParameters.get(i).getTypeConstructor(),
new TypeProjectionImpl(subTypeParameters.get(i).getDefaultType())
);
}
return TypeSubstitutor.create(substitutionContext);
}
public static boolean isPropertyTypeOkForOverride(
@NotNull JetTypeChecker typeChecker,
@NotNull PropertyDescriptor superDescriptor,
@NotNull PropertyDescriptor subDescriptor
) {
TypeSubstitutor typeSubstitutor = prepareTypeSubstitutor(superDescriptor, subDescriptor);
if (typeSubstitutor == null) return false;
JetType substitutedSuperReturnType = typeSubstitutor.substitute(superDescriptor.getType(), Variance.OUT_VARIANCE);
assert substitutedSuperReturnType != null;
return !superDescriptor.isVar() || typeChecker.equalTypes(subDescriptor.getType(), substitutedSuperReturnType);
}
/**
* Get overridden descriptors that are declarations, delegations or synthesized and are not dominated by any other such descriptor
*/
@NotNull
public static Set<CallableMemberDescriptor> getOverriddenDeclarations(@NotNull CallableMemberDescriptor descriptor) {
Set<CallableMemberDescriptor> result = new LinkedHashSet<CallableMemberDescriptor>();
getOverriddenDeclarations(descriptor, result);
return result;
}
private static void getOverriddenDeclarations(
@NotNull CallableMemberDescriptor descriptor,
@NotNull Set<CallableMemberDescriptor> result
) {
if (descriptor.getKind().isReal()) {
result.add(descriptor);
}
else {
if (descriptor.getOverriddenDescriptors().isEmpty()) {
throw new IllegalStateException("No overridden descriptors found for (fake override) " + descriptor);
}
for (CallableMemberDescriptor overridden : descriptor.getOverriddenDescriptors()) {
getOverriddenDeclarations(overridden, result);
}
}
}
public static void bindOverride(CallableMemberDescriptor fromCurrent, CallableMemberDescriptor fromSupertype) {
fromCurrent.addOverriddenDescriptor(fromSupertype);
@@ -593,6 +430,8 @@ public class OverridingUtil {
maxVisibility = visibility;
}
}
// TODO: IDEA seems to issue an incorrect warning here
//noinspection ConstantConditions
if (maxVisibility == null) {
return null;
}
@@ -698,70 +537,4 @@ public class OverridingUtil {
return message;
}
}
@NotNull
public static Set<CallableMemberDescriptor> getDirectlyOverriddenDeclarations(@NotNull CallableMemberDescriptor descriptor) {
Set<CallableMemberDescriptor> result = Sets.newHashSet();
Set<? extends CallableMemberDescriptor> overriddenDescriptors = descriptor.getOverriddenDescriptors();
for (CallableMemberDescriptor overriddenDescriptor : overriddenDescriptors) {
CallableMemberDescriptor.Kind kind = overriddenDescriptor.getKind();
if (kind == DECLARATION) {
result.add(overriddenDescriptor);
}
else if (kind == FAKE_OVERRIDE || kind == DELEGATION) {
result.addAll(getDirectlyOverriddenDeclarations(overriddenDescriptor));
}
else if (kind == SYNTHESIZED) {
//do nothing
}
else {
throw new AssertionError("Unexpected callable kind " + kind);
}
}
return filterOutOverridden(result);
}
@NotNull
public static Set<FunctionDescriptor> getDirectlyOverriddenDeclarations(@NotNull FunctionDescriptor descriptor) {
//noinspection unchecked
return (Set) getDirectlyOverriddenDeclarations((CallableMemberDescriptor) descriptor);
}
@NotNull
public static Set<PropertyDescriptor> getDirectlyOverriddenDeclarations(@NotNull PropertyDescriptor descriptor) {
//noinspection unchecked
return (Set) getDirectlyOverriddenDeclarations((CallableMemberDescriptor) descriptor);
}
@NotNull
public static <T extends CallableMemberDescriptor> Set<T> getAllOverriddenDeclarations(@NotNull T memberDescriptor) {
Set<T> result = Sets.newHashSet();
for (CallableMemberDescriptor overriddenDeclaration : memberDescriptor.getOverriddenDescriptors()) {
CallableMemberDescriptor.Kind kind = overriddenDeclaration.getKind();
if (kind == DECLARATION) {
//noinspection unchecked
result.add((T) overriddenDeclaration);
}
else if (kind == DELEGATION || kind == FAKE_OVERRIDE || kind == SYNTHESIZED) {
//do nothing
}
else {
throw new AssertionError("Unexpected callable kind " + kind);
}
//noinspection unchecked
result.addAll(getAllOverriddenDeclarations((T) overriddenDeclaration));
}
return result;
}
@NotNull
@ReadOnly
public static <T extends CallableMemberDescriptor> Set<T> getDeepestSuperDeclarations(T functionDescriptor) {
Set<T> overriddenDeclarations = getAllOverriddenDeclarations(functionDescriptor);
if (overriddenDeclarations.isEmpty()) {
return Collections.singleton(functionDescriptor);
}
return filterOutOverriding(overriddenDeclarations);
}
}