Got rid of a global map for invisible overridden descriptors

This commit is contained in:
Andrey Breslav
2012-05-31 13:50:15 +04:00
parent 9e1c218af2
commit 83eaa4deb7
@@ -16,7 +16,6 @@
package org.jetbrains.jet.lang.resolve; package org.jetbrains.jet.lang.resolve;
import com.google.common.collect.LinkedHashMultimap;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.google.common.collect.Multimap; import com.google.common.collect.Multimap;
import com.google.common.collect.Sets; import com.google.common.collect.Sets;
@@ -31,7 +30,6 @@ import org.jetbrains.jet.lang.diagnostics.Errors;
import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.name.Name; import org.jetbrains.jet.lang.resolve.name.Name;
import org.jetbrains.jet.lang.resolve.scopes.JetScope; import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import org.jetbrains.jet.lang.types.ErrorUtils;
import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.checker.JetTypeChecker; import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
import org.jetbrains.jet.lexer.JetTokens; import org.jetbrains.jet.lexer.JetTokens;
@@ -42,6 +40,7 @@ import java.util.*;
import static org.jetbrains.jet.lang.diagnostics.Errors.*; import static org.jetbrains.jet.lang.diagnostics.Errors.*;
import static org.jetbrains.jet.lang.resolve.BindingContext.DELEGATED; import static org.jetbrains.jet.lang.resolve.BindingContext.DELEGATED;
import static org.jetbrains.jet.lang.resolve.OverridingUtil.OverrideCompatibilityInfo.Result.OVERRIDABLE;
/** /**
* @author abreslav * @author abreslav
@@ -72,18 +71,17 @@ public class OverrideResolver {
public void process() { public void process() {
//all created fake descriptors are stored to resolve visibility on them later //all created fake descriptors are stored to resolve visibility on them later
Multimap<CallableDescriptor, CallableDescriptor> invisibleOverriddenDescriptors = LinkedHashMultimap.create(); generateOverrides();
generateOverrides(invisibleOverriddenDescriptors);
checkVisibility(); checkVisibility();
checkOverrides(invisibleOverriddenDescriptors); checkOverrides();
checkParameterOverridesForAllClasses(); checkParameterOverridesForAllClasses();
} }
/** /**
* Generate fake overrides and add overridden descriptors to existing descriptors. * Generate fake overrides and add overridden descriptors to existing descriptors.
*/ */
private void generateOverrides(@NotNull Multimap<CallableDescriptor, CallableDescriptor> invisibleOverriddenDescriptors) { private void generateOverrides() {
Set<MutableClassDescriptor> ourClasses = new HashSet<MutableClassDescriptor>(); Set<MutableClassDescriptor> ourClasses = new HashSet<MutableClassDescriptor>();
ourClasses.addAll(context.getClasses().values()); ourClasses.addAll(context.getClasses().values());
ourClasses.addAll(context.getObjects().values()); ourClasses.addAll(context.getObjects().values());
@@ -91,12 +89,13 @@ public class OverrideResolver {
Set<ClassifierDescriptor> processed = new HashSet<ClassifierDescriptor>(); Set<ClassifierDescriptor> processed = new HashSet<ClassifierDescriptor>();
for (MutableClassDescriptor clazz : ourClasses) { for (MutableClassDescriptor clazz : ourClasses) {
generateOverridesInAClass(clazz, processed, ourClasses, invisibleOverriddenDescriptors); generateOverridesInAClass(clazz, processed, ourClasses);
} }
} }
private void generateOverridesInAClass(@NotNull final MutableClassDescriptor classDescriptor, @NotNull Set<ClassifierDescriptor> processed, public void generateOverridesInAClass(@NotNull final MutableClassDescriptor classDescriptor,
@NotNull Set<MutableClassDescriptor> ourClasses, @NotNull Multimap<CallableDescriptor, CallableDescriptor> invisibleOverriddenDescriptors) { @NotNull Set<ClassifierDescriptor> processed,
@NotNull Set<MutableClassDescriptor> ourClasses) {
if (!processed.add(classDescriptor)) { if (!processed.add(classDescriptor)) {
return; return;
} }
@@ -109,7 +108,7 @@ public class OverrideResolver {
for (JetType supertype : classDescriptor.getTypeConstructor().getSupertypes()) { for (JetType supertype : classDescriptor.getTypeConstructor().getSupertypes()) {
ClassDescriptor superclass = (ClassDescriptor) supertype.getConstructor().getDeclarationDescriptor(); ClassDescriptor superclass = (ClassDescriptor) supertype.getConstructor().getDeclarationDescriptor();
if (superclass instanceof MutableClassDescriptor) { if (superclass instanceof MutableClassDescriptor) {
generateOverridesInAClass((MutableClassDescriptor) superclass, processed, ourClasses, invisibleOverriddenDescriptors); generateOverridesInAClass((MutableClassDescriptor) superclass, processed, ourClasses);
} }
} }
@@ -129,7 +128,6 @@ public class OverrideResolver {
functionsFromSupertypesByName.get(functionName), functionsFromSupertypesByName.get(functionName),
functionsFromCurrentByName.get(functionName), functionsFromCurrentByName.get(functionName),
classDescriptor, classDescriptor,
invisibleOverriddenDescriptors,
new DescriptorSink() { new DescriptorSink() {
@Override @Override
public void addToScope(@NotNull CallableMemberDescriptor fakeOverride) { public void addToScope(@NotNull CallableMemberDescriptor fakeOverride) {
@@ -175,7 +173,6 @@ public class OverrideResolver {
@NotNull Collection<? extends CallableMemberDescriptor> functionsFromSupertypes, @NotNull Collection<? extends CallableMemberDescriptor> functionsFromSupertypes,
@NotNull Collection<? extends CallableMemberDescriptor> functionsFromCurrent, @NotNull Collection<? extends CallableMemberDescriptor> functionsFromCurrent,
@NotNull ClassDescriptor current, @NotNull ClassDescriptor current,
@Nullable Multimap<CallableDescriptor, CallableDescriptor> invisibleOverriddenDescriptors,
@NotNull DescriptorSink sink) { @NotNull DescriptorSink sink) {
List<CallableMemberDescriptor> fakeOverrideList = Lists.newArrayList(); List<CallableMemberDescriptor> fakeOverrideList = Lists.newArrayList();
@@ -187,14 +184,9 @@ public class OverrideResolver {
for (CallableMemberDescriptor functionFromCurrent : functionsFromCurrent) { for (CallableMemberDescriptor functionFromCurrent : functionsFromCurrent) {
OverridingUtil.OverrideCompatibilityInfo.Result result = OverridingUtil.isOverridableBy(functionFromSupertype, functionFromCurrent).getResult(); OverridingUtil.OverrideCompatibilityInfo.Result result = OverridingUtil.isOverridableBy(functionFromSupertype, functionFromCurrent).getResult();
if (result == OverridingUtil.OverrideCompatibilityInfo.Result.OVERRIDABLE) { if (result == OVERRIDABLE) {
if (!isVisible) { if (isVisible) {
if (invisibleOverriddenDescriptors != null) {
invisibleOverriddenDescriptors.put(functionFromCurrent, functionFromSupertype);
}
}
else {
OverridingUtil.bindOverride(functionFromCurrent, functionFromSupertype); OverridingUtil.bindOverride(functionFromCurrent, functionFromSupertype);
} }
overrides = true; overrides = true;
@@ -205,7 +197,7 @@ public class OverrideResolver {
} }
for (CallableMemberDescriptor fakeOverride : fakeOverrideList) { for (CallableMemberDescriptor fakeOverride : fakeOverrideList) {
if (OverridingUtil.isOverridableBy(functionFromSupertype, fakeOverride).getResult() == OverridingUtil.OverrideCompatibilityInfo.Result.OVERRIDABLE) { if (OverridingUtil.isOverridableBy(functionFromSupertype, fakeOverride).getResult() == OVERRIDABLE) {
OverridingUtil.bindOverride(fakeOverride, functionFromSupertype); OverridingUtil.bindOverride(fakeOverride, functionFromSupertype);
overrides = true; overrides = true;
} }
@@ -251,22 +243,21 @@ public class OverrideResolver {
return r; return r;
} }
private void checkOverrides(@NotNull Multimap<CallableDescriptor, CallableDescriptor> invisibleOverriddenDescriptors) { private void checkOverrides() {
for (Map.Entry<JetClass, MutableClassDescriptor> entry : context.getClasses().entrySet()) { for (Map.Entry<JetClass, MutableClassDescriptor> entry : context.getClasses().entrySet()) {
checkOverridesInAClass(entry.getValue(), entry.getKey(), invisibleOverriddenDescriptors); checkOverridesInAClass(entry.getValue(), entry.getKey());
} }
for (Map.Entry<JetObjectDeclaration, MutableClassDescriptor> entry : context.getObjects().entrySet()) { for (Map.Entry<JetObjectDeclaration, MutableClassDescriptor> entry : context.getObjects().entrySet()) {
checkOverridesInAClass(entry.getValue(), entry.getKey(), invisibleOverriddenDescriptors); checkOverridesInAClass(entry.getValue(), entry.getKey());
} }
} }
protected void checkOverridesInAClass(@NotNull MutableClassDescriptor classDescriptor, @NotNull JetClassOrObject klass, protected void checkOverridesInAClass(@NotNull MutableClassDescriptor classDescriptor, @NotNull JetClassOrObject klass) {
@NotNull Multimap<CallableDescriptor, CallableDescriptor> invisibleOverriddenDescriptors) {
if (topDownAnalysisParameters.isAnalyzingBootstrapLibrary()) return; if (topDownAnalysisParameters.isAnalyzingBootstrapLibrary()) return;
// Check overrides for internal consistency // Check overrides for internal consistency
for (CallableMemberDescriptor member : classDescriptor.getDeclaredCallableMembers()) { for (CallableMemberDescriptor member : classDescriptor.getDeclaredCallableMembers()) {
checkOverrideForMember(member, invisibleOverriddenDescriptors); checkOverrideForMember(member);
} }
// Check if everything that must be overridden, actually is // Check if everything that must be overridden, actually is
@@ -356,8 +347,8 @@ public class OverrideResolver {
for (CallableMemberDescriptor another : filteredMembers) { for (CallableMemberDescriptor another : filteredMembers) {
// if (one == another) continue; // if (one == another) continue;
factoredMembers.put(one, one); factoredMembers.put(one, one);
if (OverridingUtil.isOverridableBy(one, another).getResult() == OverridingUtil.OverrideCompatibilityInfo.Result.OVERRIDABLE if (OverridingUtil.isOverridableBy(one, another).getResult() == OVERRIDABLE
|| OverridingUtil.isOverridableBy(another, one).getResult() == OverridingUtil.OverrideCompatibilityInfo.Result.OVERRIDABLE) { || OverridingUtil.isOverridableBy(another, one).getResult() == OVERRIDABLE) {
factoredMembers.put(one, another); factoredMembers.put(one, another);
} }
} }
@@ -365,8 +356,7 @@ public class OverrideResolver {
return factoredMembers; return factoredMembers;
} }
private void checkOverrideForMember(@NotNull CallableMemberDescriptor declared, private void checkOverrideForMember(@NotNull CallableMemberDescriptor declared) {
@NotNull Multimap<CallableDescriptor, CallableDescriptor> invisibleOverriddenDescriptors) {
JetNamedDeclaration member = (JetNamedDeclaration) BindingContextUtils.descriptorToDeclaration(trace.getBindingContext(), declared); JetNamedDeclaration member = (JetNamedDeclaration) BindingContextUtils.descriptorToDeclaration(trace.getBindingContext(), declared);
if (member == null) { if (member == null) {
Boolean delegated = trace.get(DELEGATED, declared); Boolean delegated = trace.get(DELEGATED, declared);
@@ -410,9 +400,14 @@ public class OverrideResolver {
} }
if (hasOverrideModifier && declared.getOverriddenDescriptors().size() == 0) { if (hasOverrideModifier && declared.getOverriddenDescriptors().size() == 0) {
if (!invisibleOverriddenDescriptors.get(declared).isEmpty()) { DeclarationDescriptor containingDeclaration = declared.getContainingDeclaration();
CallableDescriptor descriptor = invisibleOverriddenDescriptors.values().iterator().next(); assert containingDeclaration instanceof ClassDescriptor : "Overrides may only be resolved in a class, but " + declared + " comes from " + containingDeclaration;
trace.report(CANNOT_OVERRIDE_INVISIBLE_MEMBER.on(member, declared, descriptor, descriptor.getContainingDeclaration())); ClassDescriptor declaringClass = (ClassDescriptor) containingDeclaration;
CallableMemberDescriptor invisibleOverriddenDescriptor = findInvisibleOverriddenDescriptor(declared, declaringClass);
if (invisibleOverriddenDescriptor != null) {
trace.report(CANNOT_OVERRIDE_INVISIBLE_MEMBER.on(member, declared, invisibleOverriddenDescriptor,
invisibleOverriddenDescriptor.getContainingDeclaration()));
} }
else { else {
trace.report(NOTHING_TO_OVERRIDE.on(member, declared)); trace.report(NOTHING_TO_OVERRIDE.on(member, declared));
@@ -425,6 +420,26 @@ public class OverrideResolver {
} }
} }
private CallableMemberDescriptor findInvisibleOverriddenDescriptor(CallableMemberDescriptor declared, ClassDescriptor declaringClass) {
CallableMemberDescriptor invisibleOverride = null;
outer:
for (JetType supertype : declaringClass.getTypeConstructor().getSupertypes()) {
Set<CallableMemberDescriptor> all = Sets.newLinkedHashSet();
all.addAll(supertype.getMemberScope().getFunctions(declared.getName()));
all.addAll((Set) supertype.getMemberScope().getProperties(declared.getName()));
for (CallableMemberDescriptor fromSuper : all) {
if (OverridingUtil.isOverridableBy(fromSuper, declared).getResult() == OVERRIDABLE) {
invisibleOverride = fromSuper;
if (Visibilities.isVisible(fromSuper, declared)) {
throw new IllegalStateException("Descriptor " + fromSuper + "is overridable by " + declared + " and visible but does not appear in its getOverriddenDescriptors()");
}
break outer;
}
}
}
return invisibleOverride;
}
private void checkParameterOverridesForAllClasses() { private void checkParameterOverridesForAllClasses() {
List<MutableClassDescriptor> allClasses = Lists.newArrayList(context.getClasses().values()); List<MutableClassDescriptor> allClasses = Lists.newArrayList(context.getClasses().values());
allClasses.addAll(context.getObjects().values()); allClasses.addAll(context.getObjects().values());