diff --git a/compiler/backend-common/src/org/jetbrains/jet/backend/common/CodegenUtil.java b/compiler/backend-common/src/org/jetbrains/jet/backend/common/CodegenUtil.java index 8ecd58263ee..f3c0fa0c7dc 100644 --- a/compiler/backend-common/src/org/jetbrains/jet/backend/common/CodegenUtil.java +++ b/compiler/backend-common/src/org/jetbrains/jet/backend/common/CodegenUtil.java @@ -18,6 +18,7 @@ package org.jetbrains.jet.backend.common; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.codegen.bridges.BridgesPackage; import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.psi.JetDelegationSpecifier; import org.jetbrains.jet.lang.psi.JetExpression; @@ -145,6 +146,40 @@ public class CodegenUtil { return result; } + @NotNull + public static Map getTraitMethods(ClassDescriptor descriptor) { + Map result = new LinkedHashMap(); + for (DeclarationDescriptor declaration : descriptor.getDefaultType().getMemberScope().getAllDescriptors()) { + if (!(declaration instanceof CallableMemberDescriptor)) continue; + + CallableMemberDescriptor inheritedMember = (CallableMemberDescriptor) declaration; + CallableMemberDescriptor traitMember = BridgesPackage.findTraitImplementation(inheritedMember); + if (traitMember == null) continue; + + assert traitMember.getModality() != Modality.ABSTRACT : "Cannot delegate to abstract trait method: " + inheritedMember; + + // inheritedMember can be abstract here. In order for FunctionCodegen to generate the method body, we're creating a copy here + // with traitMember's modality + CallableMemberDescriptor copy = + inheritedMember.copy(inheritedMember.getContainingDeclaration(), traitMember.getModality(), Visibilities.PUBLIC, + CallableMemberDescriptor.Kind.DECLARATION, true); + + if (traitMember instanceof SimpleFunctionDescriptor) { + result.put((FunctionDescriptor) traitMember, (FunctionDescriptor) copy); + } + else if (traitMember instanceof PropertyDescriptor) { + for (PropertyAccessorDescriptor traitAccessor : ((PropertyDescriptor) traitMember).getAccessors()) { + for (PropertyAccessorDescriptor inheritedAccessor : ((PropertyDescriptor) copy).getAccessors()) { + if (inheritedAccessor.getClass() == traitAccessor.getClass()) { // same accessor kind + result.put(traitAccessor, inheritedAccessor); + } + } + } + } + } + return result; + } + @NotNull public static ClassDescriptor getSuperClassByDelegationSpecifier(@NotNull JetDelegationSpecifier specifier, @NotNull BindingContext bindingContext) { JetType superType = bindingContext.get(BindingContext.TYPE, specifier.getTypeReference()); diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java index 053283c190c..ed6f66f56ea 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java @@ -26,7 +26,6 @@ import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.backend.common.CodegenUtil; import org.jetbrains.jet.backend.common.DataClassMethodGenerator; import org.jetbrains.jet.codegen.binding.MutableClosure; -import org.jetbrains.jet.codegen.bridges.BridgesPackage; import org.jetbrains.jet.codegen.context.*; import org.jetbrains.jet.codegen.signature.BothSignatureWriter; import org.jetbrains.jet.codegen.state.GenerationState; @@ -1409,33 +1408,8 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { private void generateTraitMethods() { if (JetPsiUtil.isTrait(myClass)) return; - for (DeclarationDescriptor declaration : descriptor.getDefaultType().getMemberScope().getAllDescriptors()) { - if (!(declaration instanceof CallableMemberDescriptor)) continue; - - CallableMemberDescriptor inheritedMember = (CallableMemberDescriptor) declaration; - CallableMemberDescriptor traitMember = BridgesPackage.findTraitImplementation(inheritedMember); - if (traitMember == null) continue; - - assert traitMember.getModality() != Modality.ABSTRACT : "Cannot delegate to abstract trait method: " + inheritedMember; - - // inheritedMember can be abstract here. In order for FunctionCodegen to generate the method body, we're creating a copy here - // with traitMember's modality - CallableMemberDescriptor copy = - inheritedMember.copy(inheritedMember.getContainingDeclaration(), traitMember.getModality(), Visibilities.PUBLIC, - CallableMemberDescriptor.Kind.DECLARATION, true); - - if (traitMember instanceof SimpleFunctionDescriptor) { - generateDelegationToTraitImpl((FunctionDescriptor) traitMember, (FunctionDescriptor) copy); - } - else if (traitMember instanceof PropertyDescriptor) { - for (PropertyAccessorDescriptor traitAccessor : ((PropertyDescriptor) traitMember).getAccessors()) { - for (PropertyAccessorDescriptor inheritedAccessor : ((PropertyDescriptor) copy).getAccessors()) { - if (inheritedAccessor.getClass() == traitAccessor.getClass()) { // same accessor kind - generateDelegationToTraitImpl(traitAccessor, inheritedAccessor); - } - } - } - } + for(Map.Entry entry : CodegenUtil.getTraitMethods(descriptor).entrySet()) { + generateDelegationToTraitImpl(entry.getKey(), entry.getValue()); } }