Delegation by expression is accounted for in OverrideResolver

Delegated descriptors are generated and stored under DELEGATED trace slice
This commit is contained in:
Andrey Breslav
2011-09-27 15:32:29 +04:00
parent cc68fcabc6
commit c8c740c52f
21 changed files with 229 additions and 57 deletions
@@ -11,4 +11,7 @@ public interface CallableMemberDescriptor extends CallableDescriptor, MemberDesc
@NotNull
@Override
Set<? extends CallableMemberDescriptor> getOverriddenDescriptors();
@NotNull
CallableMemberDescriptor copy(DeclarationDescriptor newOwner, boolean makeNonAbstract);
}
@@ -28,7 +28,7 @@ public class ConstructorDescriptorImpl extends FunctionDescriptorImpl implements
@Override
@Deprecated
public FunctionDescriptorImpl initialize(@Nullable JetType receiverType, @NotNull List<TypeParameterDescriptor> typeParameters, @NotNull List<ValueParameterDescriptor> unsubstitutedValueParameters, @Nullable JetType unsubstitutedReturnType, Modality modality, Visibility visibility) {
public FunctionDescriptorImpl initialize(@Nullable JetType receiverType, @NotNull List<TypeParameterDescriptor> typeParameters, @NotNull List<ValueParameterDescriptor> unsubstitutedValueParameters, @Nullable JetType unsubstitutedReturnType, Modality modality, @NotNull Visibility visibility) {
assert receiverType == null;
return super.initialize(null, typeParameters, unsubstitutedValueParameters, unsubstitutedReturnType, modality, visibility);
}
@@ -78,4 +78,10 @@ public class ConstructorDescriptorImpl extends FunctionDescriptorImpl implements
Collections.<AnnotationDescriptor>emptyList(), // TODO
isPrimary);
}
@NotNull
@Override
public ConstructorDescriptor copy(DeclarationDescriptor newOwner, boolean makeNonAbstract) {
throw new UnsupportedOperationException("Constructors should not be copied for overriding");
}
}
@@ -23,4 +23,8 @@ public interface FunctionDescriptor extends CallableMemberDescriptor {
@Override
@NotNull
Set<? extends FunctionDescriptor> getOverriddenDescriptors();
@NotNull
@Override
FunctionDescriptor copy(DeclarationDescriptor newOwner, boolean makeNonAbstract);
}
@@ -5,6 +5,7 @@ import com.google.common.collect.Sets;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ExtensionReceiver;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
import org.jetbrains.jet.lang.types.DescriptorSubstitutor;
@@ -175,24 +176,18 @@ public class FunctionDescriptorImpl extends DeclarationDescriptorImpl implements
return visitor.visitFunctionDescriptor(this, data);
}
// @Override
// public boolean equals(Object obj) {
// if (obj == null) return false;
// if (obj.getClass() != FunctionDescriptorImpl.class) return false;
// FunctionDescriptorImpl other = (FunctionDescriptorImpl) obj;
// if (!eq(this.getName(), other.getName())) return false;
// if (!eq(this.getContainingDeclaration(), other.getContainingDeclaration())) return false;
//
// }
//
// private static boolean eq(Object a, Object b) {
// if (a == null) return b == null;
// if (b == null) return false;
// return a.equals(b);
// }
//
// @Override
// public int hashCode() {
// return super.hashCode(); // TODO
// }
@NotNull
@Override
public FunctionDescriptor copy(DeclarationDescriptor newOwner, boolean makeNonAbstract) {
FunctionDescriptorImpl copy = new FunctionDescriptorImpl(newOwner, Lists.newArrayList(getAnnotations()), getName());
copy.initialize(
getReceiver().exists() ? getReceiver().getType() : null,
DescriptorUtils.copyTypeParameters(copy, typeParameters),
DescriptorUtils.copyValueParameters(copy, unsubstitutedValueParameters),
unsubstitutedReturnType,
DescriptorUtils.convertModality(modality, makeNonAbstract),
visibility
);
return copy;
}
}
@@ -8,14 +8,14 @@ public enum Modality {
OPEN(true),
ABSTRACT(true);
private final boolean open;
private final boolean overridable;
private Modality(boolean open) {
this.open = open;
private Modality(boolean overridable) {
this.overridable = overridable;
}
public boolean isOpen() {
return open;
public boolean isOverridable() {
return overridable;
}
public static Modality convertFromFlags(boolean _abstract, boolean open) {
@@ -172,7 +172,7 @@ public class MutableClassDescriptor extends MutableDeclarationDescriptor impleme
this.typeConstructor = new TypeConstructorImpl(
this,
Collections.<AnnotationDescriptor>emptyList(), // TODO : pass annotations from the class?
!modality.isOpen(),
!modality.isOverridable(),
getName(),
typeParameters,
supertypes);
@@ -76,4 +76,10 @@ public abstract class PropertyAccessorDescriptor extends DeclarationDescriptorIm
public PropertyDescriptor getCorrespondingProperty() {
return correspondingProperty;
}
@NotNull
@Override
public PropertyAccessorDescriptor copy(DeclarationDescriptor newOwner, boolean makeNonAbstract) {
throw new UnsupportedOperationException("Accessors must be copied by the corresponding property");
}
}
@@ -5,6 +5,7 @@ import com.google.common.collect.Sets;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ExtensionReceiver;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
import org.jetbrains.jet.lang.types.JetType;
@@ -168,5 +169,27 @@ public class PropertyDescriptor extends VariableDescriptorImpl implements Callab
@Override
public Set<? extends PropertyDescriptor> getOverriddenDescriptors() {
return overriddenProperties;
}
@NotNull
@Override
public PropertyDescriptor copy(DeclarationDescriptor newOwner, boolean makeNonAbstract) {
PropertyDescriptor propertyDescriptor = new PropertyDescriptor(
newOwner,
Lists.newArrayList(getAnnotations()),
DescriptorUtils.convertModality(modality, makeNonAbstract), visibility, isVar,
receiver.exists() ? receiver.getType() : null, getName(), getInType(), getOutType());
PropertyGetterDescriptor newGetter = getter == null ? null : new PropertyGetterDescriptor(
propertyDescriptor, Lists.newArrayList(getter.getAnnotations()),
DescriptorUtils.convertModality(getter.getModality(), makeNonAbstract), getter.getVisibility(),
getter.getReturnType(),
getter.hasBody(), getter.isDefault());
PropertySetterDescriptor newSetter = setter == null ? null : new PropertySetterDescriptor(
DescriptorUtils.convertModality(setter.getModality(), makeNonAbstract), setter.getVisibility(),
propertyDescriptor,
Lists.newArrayList(setter.getAnnotations()),
setter.hasBody(), setter.isDefault());;
propertyDescriptor.initialize(DescriptorUtils.copyTypeParameters(propertyDescriptor, getTypeParameters()), newGetter, newSetter);
return propertyDescriptor;
}
}
@@ -18,7 +18,7 @@ public class PropertyGetterDescriptor extends PropertyAccessorDescriptor {
private final Set<PropertyGetterDescriptor> overriddenGetters = Sets.newHashSet();
private JetType returnType;
public PropertyGetterDescriptor(@NotNull Modality modality, @NotNull Visibility visibility, @NotNull PropertyDescriptor correspondingProperty, @NotNull List<AnnotationDescriptor> annotations, @Nullable JetType returnType, boolean hasBody, boolean isDefault) {
public PropertyGetterDescriptor(@NotNull PropertyDescriptor correspondingProperty, @NotNull List<AnnotationDescriptor> annotations, @NotNull Modality modality, @NotNull Visibility visibility, @Nullable JetType returnType, boolean hasBody, boolean isDefault) {
super(modality, visibility, correspondingProperty, annotations, "get-" + correspondingProperty.getName(), hasBody, isDefault);
this.returnType = returnType == null ? correspondingProperty.getOutType() : returnType;
}
@@ -64,5 +64,4 @@ public class PropertySetterDescriptor extends PropertyAccessorDescriptor {
public <R, D> R accept(DeclarationDescriptorVisitor<R, D> visitor, D data) {
return visitor.visitPropertySetterDescriptor(this, data);
}
}
@@ -1,5 +1,6 @@
package org.jetbrains.jet.lang.descriptors;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
@@ -157,4 +158,9 @@ public class TypeParameterDescriptor extends DeclarationDescriptorImpl implement
public int getIndex() {
return index;
}
@NotNull
public TypeParameterDescriptor copy(@NotNull DeclarationDescriptor newOwner) {
return new TypeParameterDescriptor(newOwner, Lists.newArrayList(getAnnotations()), variance, getName(), index);
}
}
@@ -23,4 +23,7 @@ public interface ValueParameterDescriptor extends VariableDescriptor {
@Override
ValueParameterDescriptor getOriginal();
@NotNull
ValueParameterDescriptor copy(DeclarationDescriptor newOwner);
}
@@ -1,5 +1,6 @@
package org.jetbrains.jet.lang.descriptors;
import com.google.common.collect.Lists;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
@@ -96,9 +97,15 @@ public class ValueParameterDescriptorImpl extends VariableDescriptorImpl impleme
public <R, D> R accept(DeclarationDescriptorVisitor<R, D> visitor, D data) {
return visitor.visitValueParameterDescriptor(this, data);
}
@Override
public boolean isVar() {
return isVar;
}
@NotNull
@Override
public ValueParameterDescriptor copy(@NotNull DeclarationDescriptor newOwner) {
return new ValueParameterDescriptorImpl(newOwner, index, Lists.newArrayList(getAnnotations()), getName(), getInType(), getOutType(), hasDefaultValue, isVararg);
}
}
@@ -31,4 +31,10 @@ public class VariableAsFunctionDescriptor extends FunctionDescriptorImpl {
public VariableDescriptor getVariableDescriptor() {
return variableDescriptor;
}
}
@NotNull
@Override
public VariableAsFunctionDescriptor copy(DeclarationDescriptor newOwner, boolean makeNonAbstract) {
throw new UnsupportedOperationException("Should not be copied for overriding");
}
}
@@ -40,6 +40,7 @@ public interface BindingContext {
WritableSlice<JetExpression, DeclarationDescriptor> VARIABLE_ASSIGNMENT = Slices.createSimpleSlice("VARIABLE_ASSIGNMENT");
WritableSlice<JetExpression, Boolean> PROCESSED = Slices.createSimpleSetSlice("PROCESSED");
WritableSlice<JetElement, Boolean> STATEMENT = Slices.createRemovableSetSlice("STATEMENT");
WritableSlice<CallableMemberDescriptor, Boolean> DELEGATED = Slices.createRemovableSetSlice("DELEGATED");
WritableSlice<PropertyDescriptor, Boolean> BACKING_FIELD_REQUIRED = new Slices.SetSlice<PropertyDescriptor>("BACKING_FIELD_REQUIRED", RewritePolicy.DO_NOTHING) {
@Override
@@ -708,16 +708,16 @@ public class ClassDescriptorResolver {
}
getterDescriptor = new PropertyGetterDescriptor(
resolveModalityFromModifiers(trace, getter.getModifierList(), propertyDescriptor.getModality()),
propertyDescriptor, annotations, resolveModalityFromModifiers(trace, getter.getModifierList(), propertyDescriptor.getModality()),
resolveVisibilityFromModifiers(trace, getter.getModifierList(), propertyDescriptor.getVisibility()),
propertyDescriptor, annotations, returnType, getter.getBodyExpression() != null, false);
returnType, getter.getBodyExpression() != null, false);
trace.record(BindingContext.PROPERTY_ACCESSOR, getter, getterDescriptor);
}
else {
getterDescriptor = new PropertyGetterDescriptor(
propertyDescriptor.getModality(),
propertyDescriptor, Collections.<AnnotationDescriptor>emptyList(), propertyDescriptor.getModality(),
propertyDescriptor.getVisibility(),
propertyDescriptor, Collections.<AnnotationDescriptor>emptyList(), propertyDescriptor.getOutType(), false, true);
propertyDescriptor.getOutType(), false, true);
}
return getterDescriptor;
}
@@ -0,0 +1,66 @@
package org.jetbrains.jet.lang.resolve;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
import org.jetbrains.jet.lang.descriptors.MutableClassDescriptor;
import org.jetbrains.jet.lang.descriptors.PropertyDescriptor;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.types.JetType;
import java.util.Map;
import static org.jetbrains.jet.lang.resolve.BindingContext.DELEGATED;
/**
* @author abreslav
*/
public class DelegationResolver {
private final TopDownAnalysisContext context;
public DelegationResolver(TopDownAnalysisContext context) {
this.context = context;
}
public void process() {
addDelegatedMembers();
}
private void addDelegatedMembers() {
for (Map.Entry<JetClass, MutableClassDescriptor> entry : context.getClasses().entrySet()) {
addDelegatedMembers(entry.getKey(), entry.getValue());
}
for (Map.Entry<JetObjectDeclaration, MutableClassDescriptor> entry : context.getObjects().entrySet()) {
addDelegatedMembers(entry.getKey(), entry.getValue());
}
}
private void addDelegatedMembers(JetClassOrObject jetClass, MutableClassDescriptor classDescriptor) {
for (JetDelegationSpecifier delegationSpecifier : jetClass.getDelegationSpecifiers()) {
if (delegationSpecifier instanceof JetDelegatorByExpressionSpecifier) {
JetDelegatorByExpressionSpecifier specifier = (JetDelegatorByExpressionSpecifier) delegationSpecifier;
JetType type = context.getTrace().get(BindingContext.TYPE, specifier.getTypeReference());
if (type != null) {
for (DeclarationDescriptor declarationDescriptor : type.getMemberScope().getAllDescriptors()) {
if (declarationDescriptor instanceof PropertyDescriptor) {
PropertyDescriptor propertyDescriptor = (PropertyDescriptor) declarationDescriptor;
if (propertyDescriptor.getModality().isOverridable()) {
PropertyDescriptor copy = propertyDescriptor.copy(classDescriptor, true);
classDescriptor.addPropertyDescriptor(copy);
context.getTrace().record(DELEGATED, copy);
}
}
else if (declarationDescriptor instanceof FunctionDescriptor) {
FunctionDescriptor functionDescriptor = (FunctionDescriptor) declarationDescriptor;
if (functionDescriptor.getModality().isOverridable()) {
FunctionDescriptor copy = functionDescriptor.copy(classDescriptor, true);
classDescriptor.addFunctionDescriptor(copy);
context.getTrace().record(DELEGATED, copy);
}
}
}
}
}
}
}
}
@@ -1,5 +1,6 @@
package org.jetbrains.jet.lang.resolve;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.*;
@@ -89,4 +90,25 @@ public class DescriptorUtils {
}
});
}
public static List<ValueParameterDescriptor> copyValueParameters(DeclarationDescriptor newOwner, List<ValueParameterDescriptor> parameters) {
List<ValueParameterDescriptor> result = Lists.newArrayList();
for (ValueParameterDescriptor parameter : parameters) {
result.add(parameter.copy(newOwner));
}
return result;
}
public static List<TypeParameterDescriptor> copyTypeParameters(DeclarationDescriptor newOwner, List<TypeParameterDescriptor> parameters) {
List<TypeParameterDescriptor> result = Lists.newArrayList();
for (TypeParameterDescriptor parameter : parameters) {
result.add(parameter.copy(newOwner));
}
return result;
}
public static Modality convertModality(Modality modality, boolean makeNonAbstract) {
if (makeNonAbstract && modality == Modality.ABSTRACT) return Modality.OPEN;
return modality;
}
}
@@ -17,6 +17,7 @@ import java.util.Map;
import java.util.Set;
import static org.jetbrains.jet.lang.diagnostics.Errors.*;
import static org.jetbrains.jet.lang.resolve.BindingContext.DELEGATED;
/**
* @author abreslav
@@ -104,28 +105,13 @@ public class OverrideResolver {
// Check if everything that must be overridden, actually is
// Everything from supertypes
Set<JetType> delegatedByExpression = Sets.newHashSet();
for (JetDelegationSpecifier delegationSpecifier : klass.getDelegationSpecifiers()) {
if (delegationSpecifier instanceof JetDelegatorByExpressionSpecifier) {
JetDelegatorByExpressionSpecifier specifier = (JetDelegatorByExpressionSpecifier) delegationSpecifier;
JetType type = context.getTrace().get(BindingContext.TYPE, specifier.getTypeReference());
if (type != null) {
delegatedByExpression.add(type);
}
}
}
Map<CallableMemberDescriptor, CallableMemberDescriptor> implementedWithDelegationBy = Maps.newHashMap();
Set<CallableMemberDescriptor> inheritedFunctions = Sets.newLinkedHashSet();
for (JetType supertype : classDescriptor.getSupertypes()) {
boolean delegatedBy = delegatedByExpression.contains(supertype);
for (DeclarationDescriptor descriptor : supertype.getMemberScope().getAllDescriptors()) {
if (descriptor instanceof CallableMemberDescriptor) {
CallableMemberDescriptor memberDescriptor = (CallableMemberDescriptor) descriptor;
inheritedFunctions.add(memberDescriptor);
if (delegatedBy && memberDescriptor.getModality().isOpen()) {
implementedWithDelegationBy.put(memberDescriptor, createOverridingDescriptor(classDescriptor, memberDescriptor));
}
}
}
}
@@ -230,14 +216,13 @@ public class OverrideResolver {
// }
}
@Nullable
private CallableMemberDescriptor createOverridingDescriptor(@NotNull MutableClassDescriptor subClass, @NotNull CallableMemberDescriptor superDescriptor) {
return null;
}
private void checkOverride(CallableMemberDescriptor declared) {
JetNamedDeclaration member = (JetNamedDeclaration) context.getTrace().get(BindingContext.DESCRIPTOR_TO_DECLARATION, declared);
assert member != null;
if (member == null) {
assert context.getTrace().get(DELEGATED, declared);
return;
}
JetModifierList modifierList = member.getModifierList();
ASTNode overrideNode = modifierList != null ? modifierList.getModifierNode(JetTokens.OVERRIDE_KEYWORD) : null;
boolean hasOverrideModifier = overrideNode != null;
@@ -248,7 +233,7 @@ public class OverrideResolver {
for (CallableMemberDescriptor overridden : declared.getOverriddenDescriptors()) {
if (overridden != null) {
if (hasOverrideModifier) {
if (!overridden.getModality().isOpen() && !finalOverriddenError) {
if (!overridden.getModality().isOverridable() && !finalOverriddenError) {
// context.getTrace().getErrorHandler().genericError(overrideNode, "Method " + overridden.getName() + " in " + overridden.getContainingDeclaration().getName() + " is final and cannot be overridden");
context.getTrace().report(OVERRIDING_FINAL_MEMBER.on(overrideNode, overridden, overridden.getContainingDeclaration()));
finalOverriddenError = true;
@@ -65,6 +65,7 @@ public class TopDownAnalyzer {
TopDownAnalysisContext context = new TopDownAnalysisContext(semanticServices, trace);
new TypeHierarchyResolver(context).process(outerScope, owner, declarations);
new DeclarationResolver(context).process();
new DelegationResolver(context).process();
new OverrideResolver(context).process();
new BodyResolver(context).resolveBehaviorDeclarationBodies();
}
@@ -78,6 +79,7 @@ public class TopDownAnalyzer {
context.getNamespaceDescriptors().put(namespace, standardLibraryNamespace);
new TypeHierarchyResolver(context).process(outerScope, standardLibraryNamespace, namespace.getDeclarations());
new DeclarationResolver(context).process();
new DelegationResolver(context).process();
OverrideResolver overrideResolver = new OverrideResolver(context) {
@Override
protected void checkOverridesInAClass(MutableClassDescriptor classDescriptor, JetClassOrObject klass) {
@@ -0,0 +1,38 @@
//namespace override
trait T {
fun foo()
val v : Int
}
open class <!ABSTRACT_MEMBER_NOT_IMPLEMENTED!>Br<!>(t : T) : T {
}
class <!ABSTRACT_MEMBER_NOT_IMPLEMENTED!>Br3<!>(t : T) : Br(t) {
}
open class Br1(t : T) : T by t {
}
class Br2(t : T) : Br1(t) {
}
trait G<T> {
fun foo(t : T) : T
}
class <!ABSTRACT_MEMBER_NOT_IMPLEMENTED!>GC<!>() : G<Int> {
}
open class GC1(g : G<Int>) : G<Int> by g {
}
open class GC2(g : G<Int>) : GC1(g) {
}