From fc243695f7bc6c48d1cdd69feeb2f437854b1f76 Mon Sep 17 00:00:00 2001 From: Andrey Breslav Date: Mon, 26 Sep 2011 21:09:10 +0400 Subject: [PATCH 1/6] Confusion between vals and funs fixed --- .../jet/lang/resolve/OverrideResolver.java | 70 +++++++++---------- .../jet/lang/resolve/OverridingUtil.java | 11 +++ .../ValAndFunOverrideCompatibilityClash.jet | 8 +++ 3 files changed, 54 insertions(+), 35 deletions(-) create mode 100644 idea/testData/checkerWithErrorTypes/full/ValAndFunOverrideCompatibilityClash.jet diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverrideResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverrideResolver.java index ecbc9cadbab..97af644f0b3 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverrideResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverrideResolver.java @@ -171,48 +171,48 @@ public class OverrideResolver { nameIdentifier = ((JetObjectDeclaration) klass).getNameIdentifier(); } -// for (CallableMemberDescriptor memberDescriptor : manyImpl) { -// context.getTrace().report(MANY_IMPL_MEMBER_NOT_IMPLEMENTED.on(nameIdentifier, klass, memberDescriptor)); -// break; -// } + for (CallableMemberDescriptor memberDescriptor : manyImpl) { + context.getTrace().report(MANY_IMPL_MEMBER_NOT_IMPLEMENTED.on(nameIdentifier, klass, memberDescriptor)); + break; + } if (classDescriptor.getModality() == Modality.ABSTRACT) { return; } -// for (CallableMemberDescriptor memberDescriptor : abstractNoImpl) { -// context.getTrace().report(ABSTRACT_MEMBER_NOT_IMPLEMENTED.on(nameIdentifier, klass, memberDescriptor)); -// break; -// } + for (CallableMemberDescriptor memberDescriptor : abstractNoImpl) { + context.getTrace().report(ABSTRACT_MEMBER_NOT_IMPLEMENTED.on(nameIdentifier, klass, memberDescriptor)); + break; + } - Set allOverriddenFunctions = Sets.newHashSet(); - Collection allDescriptors = classDescriptor.getDefaultType().getMemberScope().getAllDescriptors(); - for (DeclarationDescriptor descriptor : allDescriptors) { - if (descriptor instanceof FunctionDescriptor) { - FunctionDescriptor functionDescriptor = (FunctionDescriptor) descriptor; - if (functionDescriptor.getModality() != Modality.ABSTRACT) { - for (FunctionDescriptor overriddenDescriptor : functionDescriptor.getOverriddenDescriptors()) { - allOverriddenFunctions.add(overriddenDescriptor.getOriginal()); - } - } - } - } - boolean foundError = false; - for (DeclarationDescriptor descriptor : allDescriptors) { - if (descriptor instanceof FunctionDescriptor) { - FunctionDescriptor functionDescriptor = (FunctionDescriptor) descriptor; - if (functionDescriptor.getModality() == Modality.ABSTRACT && !allOverriddenFunctions.contains(functionDescriptor.getOriginal()) && !foundError && nameIdentifier != null) { - DeclarationDescriptor declarationDescriptor = functionDescriptor.getContainingDeclaration(); - if (declarationDescriptor != classDescriptor) { -// context.getTrace().getErrorHandler().genericError(nameIdentifier.getNode(), "Class '" + klass.getName() + "' must be declared abstract or implement abstract method '" + -// functionDescriptor.getName() + "' declared in " + declarationDescriptor.getName()); - context.getTrace().report(ABSTRACT_MEMBER_NOT_IMPLEMENTED.on(nameIdentifier, klass, functionDescriptor)); - foundError = true; - } - } - } - } +// Set allOverriddenFunctions = Sets.newHashSet(); +// Collection allDescriptors = classDescriptor.getDefaultType().getMemberScope().getAllDescriptors(); +// for (DeclarationDescriptor descriptor : allDescriptors) { +// if (descriptor instanceof FunctionDescriptor) { +// FunctionDescriptor functionDescriptor = (FunctionDescriptor) descriptor; +// if (functionDescriptor.getModality() != Modality.ABSTRACT) { +// for (FunctionDescriptor overriddenDescriptor : functionDescriptor.getOverriddenDescriptors()) { +// allOverriddenFunctions.add(overriddenDescriptor.getOriginal()); +// } +// } +// } +// } +// boolean foundError = false; +// for (DeclarationDescriptor descriptor : allDescriptors) { +// if (descriptor instanceof FunctionDescriptor) { +// FunctionDescriptor functionDescriptor = (FunctionDescriptor) descriptor; +// if (functionDescriptor.getModality() == Modality.ABSTRACT && !allOverriddenFunctions.contains(functionDescriptor.getOriginal()) && !foundError && nameIdentifier != null) { +// DeclarationDescriptor declarationDescriptor = functionDescriptor.getContainingDeclaration(); +// if (declarationDescriptor != classDescriptor) { +//// context.getTrace().getErrorHandler().genericError(nameIdentifier.getNode(), "Class '" + klass.getName() + "' must be declared abstract or implement abstract method '" + +//// functionDescriptor.getName() + "' declared in " + declarationDescriptor.getName()); +// context.getTrace().report(ABSTRACT_MEMBER_NOT_IMPLEMENTED.on(nameIdentifier, klass, functionDescriptor)); +// foundError = true; +// } +// } +// } +// } } private void checkOverride(CallableMemberDescriptor declared) { diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverridingUtil.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverridingUtil.java index 151461e145b..314f847b5ef 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverridingUtil.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverridingUtil.java @@ -85,6 +85,12 @@ public class OverridingUtil { @NotNull public static OverrideCompatibilityInfo isOverridableBy(@NotNull CallableDescriptor superDescriptor, @NotNull CallableDescriptor subDescriptor) { + if (superDescriptor instanceof FunctionDescriptor) { + if (subDescriptor instanceof PropertyDescriptor) return OverrideCompatibilityInfo.memberKindMismatch(); + } + if (superDescriptor instanceof PropertyDescriptor) { + if (subDescriptor instanceof FunctionDescriptor) return OverrideCompatibilityInfo.memberKindMismatch(); + } if (!superDescriptor.getName().equals(subDescriptor.getName())) { return OverrideCompatibilityInfo.nameMismatch(); } @@ -192,6 +198,11 @@ public class OverridingUtil { return new OverrideCompatibilityInfo(false, "valueParameterTypeMismatch"); // TODO } + @NotNull + public static OverrideCompatibilityInfo memberKindMismatch() { + return new OverrideCompatibilityInfo(false, "memberKindMismatch"); // TODO + } + @NotNull public static OverrideCompatibilityInfo returnTypeMismatch(JetType substitutedSuperReturnType, JetType unsubstitutedSubReturnType) { return new OverrideCompatibilityInfo(true, "returnTypeMismatch: " + unsubstitutedSubReturnType + " >< " + substitutedSuperReturnType); // TODO diff --git a/idea/testData/checkerWithErrorTypes/full/ValAndFunOverrideCompatibilityClash.jet b/idea/testData/checkerWithErrorTypes/full/ValAndFunOverrideCompatibilityClash.jet new file mode 100644 index 00000000000..f18974bb51f --- /dev/null +++ b/idea/testData/checkerWithErrorTypes/full/ValAndFunOverrideCompatibilityClash.jet @@ -0,0 +1,8 @@ +class Foo1() : java.util.ArrayList() + +open class Bar() { + fun v() : Int = 1 + val v : Int = 1 +} + +class Barr() : Bar() {} From c6c87ec3c8ff0276e0a1354186c9bc65dedf99cb Mon Sep 17 00:00:00 2001 From: Andrey Breslav Date: Mon, 26 Sep 2011 21:14:26 +0400 Subject: [PATCH 2/6] Static java fields not visible in non-static scopes any more --- .../jetbrains/jet/lang/resolve/java/JavaClassMembersScope.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaClassMembersScope.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaClassMembersScope.java index 8aed6d1ea3f..c5485602ba5 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaClassMembersScope.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaClassMembersScope.java @@ -85,6 +85,9 @@ public class JavaClassMembersScope implements JetScope { } for (PsiField field : psiClass.getAllFields()) { + if (field.hasModifierProperty(PsiModifier.STATIC) != staticMembers) { + continue; + } VariableDescriptor variableDescriptor = semanticServices.getDescriptorResolver().resolveFieldToVariableDescriptor(containingDeclaration, field); allDescriptors.add(variableDescriptor); } From 0cb2765ab0f356924a5967fdc51927c2efa1603d Mon Sep 17 00:00:00 2001 From: Andrey Breslav Date: Tue, 27 Sep 2011 10:25:24 +0400 Subject: [PATCH 3/6] Delegation is only allowed if the target type is a trait --- .../org/jetbrains/jet/lang/diagnostics/Errors.java | 1 + .../jetbrains/jet/lang/resolve/BodyResolver.java | 9 +++++++++ .../quick/DelegationNotTotrait.jet | 13 +++++++++++++ 3 files changed, 23 insertions(+) create mode 100644 idea/testData/checkerWithErrorTypes/quick/DelegationNotTotrait.jet diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Errors.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Errors.java index af17069d46f..a834d74feee 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Errors.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Errors.java @@ -141,6 +141,7 @@ public interface Errors { SimpleDiagnosticFactory MANY_CLASS_OBJECTS = SimpleDiagnosticFactory.create(ERROR, "Only one class object is allowed per class"); SimpleDiagnosticFactory CLASS_OBJECT_NOT_ALLOWED = SimpleDiagnosticFactory.create(ERROR, "A class object is not allowed here"); SimpleDiagnosticFactory DELEGATION_IN_TRAIT = SimpleDiagnosticFactory.create(ERROR, "Traits cannot use delegation"); + SimpleDiagnosticFactory DELEGATION_NOT_TO_TRAIT = SimpleDiagnosticFactory.create(ERROR, "Only traits can be delegated to"); SimpleDiagnosticFactory NO_CONSTRUCTOR = SimpleDiagnosticFactory.create(ERROR, "This class does not have a constructor"); SimpleDiagnosticFactory NOT_A_CLASS = SimpleDiagnosticFactory.create(ERROR, "Not a class"); SimpleDiagnosticFactory ILLEGAL_ESCAPE_SEQUENCE = SimpleDiagnosticFactory.create(ERROR, "Illegal escape sequence"); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BodyResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BodyResolver.java index 2beff92cbe7..1d7895f121d 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BodyResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BodyResolver.java @@ -136,6 +136,15 @@ public class BodyResolver { } JetType supertype = context.getTrace().getBindingContext().get(BindingContext.TYPE, specifier.getTypeReference()); recordSupertype(specifier.getTypeReference(), supertype); + if (supertype != null) { + DeclarationDescriptor declarationDescriptor = supertype.getConstructor().getDeclarationDescriptor(); + if (declarationDescriptor instanceof ClassDescriptor) { + ClassDescriptor classDescriptor = (ClassDescriptor) declarationDescriptor; + if (classDescriptor.getKind() != ClassKind.TRAIT) { + context.getTrace().report(DELEGATION_NOT_TO_TRAIT.on(specifier.getTypeReference())); + } + } + } JetExpression delegateExpression = specifier.getDelegateExpression(); if (delegateExpression != null) { JetScope scope = scopeForConstructor == null diff --git a/idea/testData/checkerWithErrorTypes/quick/DelegationNotTotrait.jet b/idea/testData/checkerWithErrorTypes/quick/DelegationNotTotrait.jet new file mode 100644 index 00000000000..646fba1f94d --- /dev/null +++ b/idea/testData/checkerWithErrorTypes/quick/DelegationNotTotrait.jet @@ -0,0 +1,13 @@ +open class Foo() { + +} + +class Barrr() : Foo by Foo() {} + +trait T {} + +class Br(t : T) : T by t {} + +open enum class E() {} + +class Test2(e : E) : E by e {} \ No newline at end of file From afad00fac532357deea161d2149209f26e6cf747 Mon Sep 17 00:00:00 2001 From: Andrey Breslav Date: Tue, 27 Sep 2011 12:32:14 +0400 Subject: [PATCH 4/6] Overriding var by val prohibited --- .../jet/lang/diagnostics/Errors.java | 1 + .../jetbrains/jet/lang/psi/JetProperty.java | 15 ++++++- .../jet/lang/resolve/OverrideResolver.java | 42 +++++++++++++++++-- .../quick/OverridingVarByVal.jet | 11 +++++ 4 files changed, 63 insertions(+), 6 deletions(-) create mode 100644 idea/testData/checkerWithErrorTypes/quick/OverridingVarByVal.jet diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Errors.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Errors.java index a834d74feee..6f52f0882ce 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Errors.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Errors.java @@ -316,6 +316,7 @@ public interface Errors { } }; + ParameterizedDiagnosticFactory2 VAR_OVERRIDDEN_BY_VAL = new ParameterizedDiagnosticFactory2(ERROR, "Var-property {0} cannot be overridden by val-property {1}", DescriptorRenderer.TEXT); ParameterizedDiagnosticFactory2 ABSTRACT_MEMBER_NOT_IMPLEMENTED = new ParameterizedDiagnosticFactory2(ERROR, "Class ''{0}'' must be declared abstract or implement abstract member {1}") { @Override diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetProperty.java b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetProperty.java index 679b6a2adb1..6e5b0f476ec 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetProperty.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetProperty.java @@ -3,6 +3,7 @@ package org.jetbrains.jet.lang.psi; import com.intellij.lang.ASTNode; import com.intellij.psi.PsiElement; import com.intellij.psi.tree.IElementType; +import com.intellij.psi.tree.TokenSet; import com.intellij.psi.util.PsiTreeUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -11,6 +12,11 @@ import org.jetbrains.jet.lexer.JetTokens; import java.util.List; +import static org.jetbrains.jet.JetNodeTypes.PROPERTY_ACCESSOR; +import static org.jetbrains.jet.lexer.JetTokens.EQ; +import static org.jetbrains.jet.lexer.JetTokens.VAL_KEYWORD; +import static org.jetbrains.jet.lexer.JetTokens.VAR_KEYWORD; + /** * @author max */ @@ -69,7 +75,7 @@ public class JetProperty extends JetTypeParameterListOwner implements JetModifie @NotNull public List getAccessors() { - return findChildrenByType(JetNodeTypes.PROPERTY_ACCESSOR); + return findChildrenByType(PROPERTY_ACCESSOR); } @Nullable @@ -92,7 +98,12 @@ public class JetProperty extends JetTypeParameterListOwner implements JetModifie @Nullable public JetExpression getInitializer() { - PsiElement eq = findChildByType(JetTokens.EQ); + PsiElement eq = findChildByType(EQ); return PsiTreeUtil.getNextSiblingOfType(eq, JetExpression.class); } + + @NotNull + public ASTNode getValOrVarNode() { + return getNode().findChildByType(TokenSet.create(VAL_KEYWORD, VAR_KEYWORD)); + } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverrideResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverrideResolver.java index 97af644f0b3..a59a66ac7ff 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverrideResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverrideResolver.java @@ -1,7 +1,6 @@ package org.jetbrains.jet.lang.resolve; -import com.google.common.collect.Multimap; -import com.google.common.collect.Sets; +import com.google.common.collect.*; import com.intellij.lang.ASTNode; import com.intellij.psi.PsiElement; import org.jetbrains.annotations.NotNull; @@ -105,12 +104,28 @@ public class OverrideResolver { // Check if everything that must be overridden, actually is // Everything from supertypes + Set 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 implementedWithDelegationBy = Maps.newHashMap(); Set 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)); + } } } } @@ -123,7 +138,7 @@ public class OverrideResolver { for (CallableMemberDescriptor one : filteredMembers) { if (factoredMembers.values().contains(one)) continue; for (CallableMemberDescriptor another : filteredMembers) { - if (one == another) continue; +// if (one == another) continue; factoredMembers.put(one, one); if (OverridingUtil.isOverridableBy(one, another).isSuccess() || OverridingUtil.isOverridableBy(another, one).isSuccess()) { @@ -154,7 +169,7 @@ public class OverrideResolver { } // Members actually present (declared) in the class - Set actuallyOverridden = Sets.newHashSet(); + Set actuallyOverridden = Sets.newHashSet(implementedWithDelegationBy.keySet()); for (CallableMemberDescriptor member : classDescriptor.getCallableMembers()) { actuallyOverridden.addAll(member.getOverriddenDescriptors()); } @@ -215,6 +230,11 @@ 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; @@ -224,6 +244,7 @@ public class OverrideResolver { boolean finalOverriddenError = false; boolean typeMismatchError = false; + boolean kindMismatchError = false; for (CallableMemberDescriptor overridden : declared.getOverriddenDescriptors()) { if (overridden != null) { if (hasOverrideModifier) { @@ -237,6 +258,11 @@ public class OverrideResolver { context.getTrace().report(RETURN_TYPE_MISMATCH_ON_OVERRIDE.on(member, declared, overridden)); typeMismatchError = true; } + + if (checkPropertyKind(overridden, true) && checkPropertyKind(declared, false) && !kindMismatchError) { + context.getTrace().report(VAR_OVERRIDDEN_BY_VAL.on(member, ((JetProperty) member).getValOrVarNode(), (PropertyDescriptor) declared, (PropertyDescriptor) overridden)); + typeMismatchError = true; + } } } } @@ -253,4 +279,12 @@ public class OverrideResolver { context.getTrace().report(VIRTUAL_MEMBER_HIDDEN.on(member, nameIdentifier, declared, overridden, overridden.getContainingDeclaration())); } } + + private boolean checkPropertyKind(CallableMemberDescriptor descriptor, boolean isVar) { + if (descriptor instanceof PropertyDescriptor) { + PropertyDescriptor propertyDescriptor = (PropertyDescriptor) descriptor; + return propertyDescriptor.isVar() == isVar; + } + return false; + } } diff --git a/idea/testData/checkerWithErrorTypes/quick/OverridingVarByVal.jet b/idea/testData/checkerWithErrorTypes/quick/OverridingVarByVal.jet new file mode 100644 index 00000000000..d77e85744b9 --- /dev/null +++ b/idea/testData/checkerWithErrorTypes/quick/OverridingVarByVal.jet @@ -0,0 +1,11 @@ +open class Var() { + open var v : Int = 1 +} + +class Val() : Var() { + override val v : Int = 1 +} + +class Var2() : Var() { + override var v : Int = 1 +} From cc68fcabc648be812087ff4484a31968786e1685 Mon Sep 17 00:00:00 2001 From: Andrey Breslav Date: Tue, 27 Sep 2011 12:35:03 +0400 Subject: [PATCH 5/6] Multiple errors of the same kind fixed --- .../org/jetbrains/jet/lang/resolve/OverrideResolver.java | 2 +- .../checkerWithErrorTypes/quick/OverridingVarByVal.jet | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverrideResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverrideResolver.java index a59a66ac7ff..dfd60ff8dd5 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverrideResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverrideResolver.java @@ -261,7 +261,7 @@ public class OverrideResolver { if (checkPropertyKind(overridden, true) && checkPropertyKind(declared, false) && !kindMismatchError) { context.getTrace().report(VAR_OVERRIDDEN_BY_VAL.on(member, ((JetProperty) member).getValOrVarNode(), (PropertyDescriptor) declared, (PropertyDescriptor) overridden)); - typeMismatchError = true; + kindMismatchError = true; } } } diff --git a/idea/testData/checkerWithErrorTypes/quick/OverridingVarByVal.jet b/idea/testData/checkerWithErrorTypes/quick/OverridingVarByVal.jet index d77e85744b9..e14eef6b41e 100644 --- a/idea/testData/checkerWithErrorTypes/quick/OverridingVarByVal.jet +++ b/idea/testData/checkerWithErrorTypes/quick/OverridingVarByVal.jet @@ -2,7 +2,11 @@ open class Var() { open var v : Int = 1 } -class Val() : Var() { +trait VarT { + var v : Int +} + +class Val() : Var(), VarT { override val v : Int = 1 } From c8c740c52fc1b211ee1a2a98513d7fa72adfb583 Mon Sep 17 00:00:00 2001 From: Andrey Breslav Date: Tue, 27 Sep 2011 15:32:29 +0400 Subject: [PATCH 6/6] Delegation by expression is accounted for in OverrideResolver Delegated descriptors are generated and stored under DELEGATED trace slice --- .../descriptors/CallableMemberDescriptor.java | 3 + .../ConstructorDescriptorImpl.java | 8 ++- .../lang/descriptors/FunctionDescriptor.java | 4 ++ .../descriptors/FunctionDescriptorImpl.java | 35 +++++----- .../jet/lang/descriptors/Modality.java | 10 +-- .../descriptors/MutableClassDescriptor.java | 2 +- .../PropertyAccessorDescriptor.java | 6 ++ .../lang/descriptors/PropertyDescriptor.java | 23 +++++++ .../descriptors/PropertyGetterDescriptor.java | 2 +- .../descriptors/PropertySetterDescriptor.java | 1 - .../descriptors/TypeParameterDescriptor.java | 6 ++ .../descriptors/ValueParameterDescriptor.java | 3 + .../ValueParameterDescriptorImpl.java | 9 ++- .../VariableAsFunctionDescriptor.java | 8 ++- .../jet/lang/resolve/BindingContext.java | 1 + .../lang/resolve/ClassDescriptorResolver.java | 8 +-- .../jet/lang/resolve/DelegationResolver.java | 66 +++++++++++++++++++ .../jet/lang/resolve/DescriptorUtils.java | 22 +++++++ .../jet/lang/resolve/OverrideResolver.java | 29 ++------ .../jet/lang/resolve/TopDownAnalyzer.java | 2 + .../quick/DelegationAndOverriding.jet | 38 +++++++++++ 21 files changed, 229 insertions(+), 57 deletions(-) create mode 100644 compiler/frontend/src/org/jetbrains/jet/lang/resolve/DelegationResolver.java create mode 100644 idea/testData/checkerWithErrorTypes/quick/DelegationAndOverriding.jet diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/CallableMemberDescriptor.java b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/CallableMemberDescriptor.java index 1b8889a40b3..db805687a7b 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/CallableMemberDescriptor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/CallableMemberDescriptor.java @@ -11,4 +11,7 @@ public interface CallableMemberDescriptor extends CallableDescriptor, MemberDesc @NotNull @Override Set getOverriddenDescriptors(); + + @NotNull + CallableMemberDescriptor copy(DeclarationDescriptor newOwner, boolean makeNonAbstract); } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/ConstructorDescriptorImpl.java b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/ConstructorDescriptorImpl.java index 0f00d025056..5afac7ed85c 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/ConstructorDescriptorImpl.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/ConstructorDescriptorImpl.java @@ -28,7 +28,7 @@ public class ConstructorDescriptorImpl extends FunctionDescriptorImpl implements @Override @Deprecated - public FunctionDescriptorImpl initialize(@Nullable JetType receiverType, @NotNull List typeParameters, @NotNull List unsubstitutedValueParameters, @Nullable JetType unsubstitutedReturnType, Modality modality, Visibility visibility) { + public FunctionDescriptorImpl initialize(@Nullable JetType receiverType, @NotNull List typeParameters, @NotNull List 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.emptyList(), // TODO isPrimary); } + + @NotNull + @Override + public ConstructorDescriptor copy(DeclarationDescriptor newOwner, boolean makeNonAbstract) { + throw new UnsupportedOperationException("Constructors should not be copied for overriding"); + } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/FunctionDescriptor.java b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/FunctionDescriptor.java index ecfe2a80bc5..e69f6d3cbe2 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/FunctionDescriptor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/FunctionDescriptor.java @@ -23,4 +23,8 @@ public interface FunctionDescriptor extends CallableMemberDescriptor { @Override @NotNull Set getOverriddenDescriptors(); + + @NotNull + @Override + FunctionDescriptor copy(DeclarationDescriptor newOwner, boolean makeNonAbstract); } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/FunctionDescriptorImpl.java b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/FunctionDescriptorImpl.java index c087c90fdd5..a6c3f0b9872 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/FunctionDescriptorImpl.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/FunctionDescriptorImpl.java @@ -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; + } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/Modality.java b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/Modality.java index e836f719f34..33e2f6e8235 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/Modality.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/Modality.java @@ -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) { diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/MutableClassDescriptor.java b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/MutableClassDescriptor.java index 39014c9d2fc..2400cad6510 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/MutableClassDescriptor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/MutableClassDescriptor.java @@ -172,7 +172,7 @@ public class MutableClassDescriptor extends MutableDeclarationDescriptor impleme this.typeConstructor = new TypeConstructorImpl( this, Collections.emptyList(), // TODO : pass annotations from the class? - !modality.isOpen(), + !modality.isOverridable(), getName(), typeParameters, supertypes); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/PropertyAccessorDescriptor.java b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/PropertyAccessorDescriptor.java index d626a45417d..023a235c3d8 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/PropertyAccessorDescriptor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/PropertyAccessorDescriptor.java @@ -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"); + } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/PropertyDescriptor.java b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/PropertyDescriptor.java index a4c897e05bd..5c6c5212c78 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/PropertyDescriptor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/PropertyDescriptor.java @@ -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 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; } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/PropertyGetterDescriptor.java b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/PropertyGetterDescriptor.java index 677f34481bc..747a27e64a7 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/PropertyGetterDescriptor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/PropertyGetterDescriptor.java @@ -18,7 +18,7 @@ public class PropertyGetterDescriptor extends PropertyAccessorDescriptor { private final Set overriddenGetters = Sets.newHashSet(); private JetType returnType; - public PropertyGetterDescriptor(@NotNull Modality modality, @NotNull Visibility visibility, @NotNull PropertyDescriptor correspondingProperty, @NotNull List annotations, @Nullable JetType returnType, boolean hasBody, boolean isDefault) { + public PropertyGetterDescriptor(@NotNull PropertyDescriptor correspondingProperty, @NotNull List 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; } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/PropertySetterDescriptor.java b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/PropertySetterDescriptor.java index 5381a9e7d85..13752d9743c 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/PropertySetterDescriptor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/PropertySetterDescriptor.java @@ -64,5 +64,4 @@ public class PropertySetterDescriptor extends PropertyAccessorDescriptor { public R accept(DeclarationDescriptorVisitor visitor, D data) { return visitor.visitPropertySetterDescriptor(this, data); } - } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/TypeParameterDescriptor.java b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/TypeParameterDescriptor.java index d441e8a3756..f67fa35e749 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/TypeParameterDescriptor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/TypeParameterDescriptor.java @@ -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); + } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/ValueParameterDescriptor.java b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/ValueParameterDescriptor.java index 7ac25d5dc5e..ba7131b36c0 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/ValueParameterDescriptor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/ValueParameterDescriptor.java @@ -23,4 +23,7 @@ public interface ValueParameterDescriptor extends VariableDescriptor { @Override ValueParameterDescriptor getOriginal(); + + @NotNull + ValueParameterDescriptor copy(DeclarationDescriptor newOwner); } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/ValueParameterDescriptorImpl.java b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/ValueParameterDescriptorImpl.java index 12c3be36e8c..8b13a526dc7 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/ValueParameterDescriptorImpl.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/ValueParameterDescriptorImpl.java @@ -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 accept(DeclarationDescriptorVisitor 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); + } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/VariableAsFunctionDescriptor.java b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/VariableAsFunctionDescriptor.java index af1840edf05..88462653cfc 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/VariableAsFunctionDescriptor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/VariableAsFunctionDescriptor.java @@ -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"); + } +} \ No newline at end of file diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BindingContext.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BindingContext.java index ec82ca8b18a..01c4cb717ad 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BindingContext.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BindingContext.java @@ -40,6 +40,7 @@ public interface BindingContext { WritableSlice VARIABLE_ASSIGNMENT = Slices.createSimpleSlice("VARIABLE_ASSIGNMENT"); WritableSlice PROCESSED = Slices.createSimpleSetSlice("PROCESSED"); WritableSlice STATEMENT = Slices.createRemovableSetSlice("STATEMENT"); + WritableSlice DELEGATED = Slices.createRemovableSetSlice("DELEGATED"); WritableSlice BACKING_FIELD_REQUIRED = new Slices.SetSlice("BACKING_FIELD_REQUIRED", RewritePolicy.DO_NOTHING) { @Override diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ClassDescriptorResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ClassDescriptorResolver.java index c34fe426683..4690faad394 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ClassDescriptorResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ClassDescriptorResolver.java @@ -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.emptyList(), propertyDescriptor.getModality(), propertyDescriptor.getVisibility(), - propertyDescriptor, Collections.emptyList(), propertyDescriptor.getOutType(), false, true); + propertyDescriptor.getOutType(), false, true); } return getterDescriptor; } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DelegationResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DelegationResolver.java new file mode 100644 index 00000000000..9fb7350d280 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DelegationResolver.java @@ -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 entry : context.getClasses().entrySet()) { + addDelegatedMembers(entry.getKey(), entry.getValue()); + } + for (Map.Entry 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); + } + } + } + } + } + } + } + +} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorUtils.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorUtils.java index cd8bdea4078..42fb64620ed 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorUtils.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorUtils.java @@ -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 copyValueParameters(DeclarationDescriptor newOwner, List parameters) { + List result = Lists.newArrayList(); + for (ValueParameterDescriptor parameter : parameters) { + result.add(parameter.copy(newOwner)); + } + return result; + } + + public static List copyTypeParameters(DeclarationDescriptor newOwner, List parameters) { + List 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; + } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverrideResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverrideResolver.java index dfd60ff8dd5..67e12a470e7 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverrideResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverrideResolver.java @@ -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 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 implementedWithDelegationBy = Maps.newHashMap(); Set 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; diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java index 457807e60f0..43d992ed5ce 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java @@ -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) { diff --git a/idea/testData/checkerWithErrorTypes/quick/DelegationAndOverriding.jet b/idea/testData/checkerWithErrorTypes/quick/DelegationAndOverriding.jet new file mode 100644 index 00000000000..388653da85a --- /dev/null +++ b/idea/testData/checkerWithErrorTypes/quick/DelegationAndOverriding.jet @@ -0,0 +1,38 @@ +//namespace override + +trait T { + fun foo() + val v : Int +} + +open class Br(t : T) : T { + +} + +class Br3(t : T) : Br(t) { + +} + +open class Br1(t : T) : T by t { + +} + +class Br2(t : T) : Br1(t) { + +} + +trait G { + fun foo(t : T) : T +} + +class GC() : G { + +} + +open class GC1(g : G) : G by g { + +} + +open class GC2(g : G) : GC1(g) { + +} \ No newline at end of file