diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ClassBodyCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ClassBodyCodegen.java index f0f7bb7d2a5..5afe5359c37 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ClassBodyCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ClassBodyCodegen.java @@ -81,7 +81,8 @@ public abstract class ClassBodyCodegen extends MemberCodegen { protected abstract void generateKotlinAnnotation(); - protected abstract void generateSyntheticParts(); + protected void generateSyntheticParts() { + } private void generateClassBody() { FunctionCodegen functionCodegen = new FunctionCodegen(context, v, state, this); diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/PropertyCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/PropertyCodegen.java index 35dba84e684..beb84b15188 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/PropertyCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/PropertyCodegen.java @@ -94,8 +94,8 @@ public class PropertyCodegen extends GenerationStateAware { Type ownerType = ((NamespaceFacadeContext) context).getDelegateToClassType(); v.getMemberMap().recordImplClassNameForCallable(propertyDescriptor, shortNameByAsmType(ownerType)); } - else if (kind != OwnerKind.TRAIT_IMPL) { - generateBackingField(p, propertyDescriptor); + else if (!generateBackingField(p, propertyDescriptor)) { + generateSyntheticMethodIfNeeded(propertyDescriptor); } generateGetter(p, propertyDescriptor, p.getGetter()); @@ -126,60 +126,55 @@ public class PropertyCodegen extends GenerationStateAware { } } - private void generateBackingField(JetNamedDeclaration p, PropertyDescriptor propertyDescriptor) { - boolean hasBackingField = Boolean.TRUE.equals(bindingContext.get(BindingContext.BACKING_FIELD_REQUIRED, propertyDescriptor)); - boolean isDelegated = p instanceof JetProperty && ((JetProperty) p).getDelegateExpression() != null; - if (hasBackingField || isDelegated) { - DeclarationDescriptor containingDeclaration = propertyDescriptor.getContainingDeclaration(); - if (isInterface(containingDeclaration)) { - return; - } - - FieldVisitor fieldVisitor = hasBackingField - ? generateBackingFieldAccess(p, propertyDescriptor) - : generatePropertyDelegateAccess((JetProperty) p, propertyDescriptor); - - AnnotationCodegen.forField(fieldVisitor, typeMapper).genAnnotations(propertyDescriptor); + private boolean generateBackingField(@NotNull JetNamedDeclaration p, @NotNull PropertyDescriptor descriptor) { + if (isInterface(descriptor.getContainingDeclaration()) || kind == OwnerKind.TRAIT_IMPL) { + return false; } - else if (!propertyDescriptor.getAnnotations().isEmpty()) { - Method method = getSyntheticMethodSignature(typeMapper, propertyDescriptor); - DeclarationDescriptor descriptor = context.getContextDescriptor(); - if (isTrait(descriptor)) { - Type tImplType = typeMapper.mapTraitImpl((ClassDescriptor) descriptor); - v.getMemberMap().recordImplClassNameForCallable(propertyDescriptor, shortNameByAsmType(tImplType)); - } - else { - generateSyntheticMethodForAnnotatedProperty(v, typeMapper, propertyDescriptor, method); - } - v.getMemberMap().recordSyntheticMethodOfProperty(propertyDescriptor, method); + + FieldVisitor fv; + if (Boolean.TRUE.equals(bindingContext.get(BindingContext.BACKING_FIELD_REQUIRED, descriptor))) { + fv = generateBackingFieldAccess(p, descriptor); } + else if (p instanceof JetProperty && ((JetProperty) p).getDelegateExpression() != null) { + fv = generatePropertyDelegateAccess((JetProperty) p, descriptor); + } + else { + return false; + } + + AnnotationCodegen.forField(fv, typeMapper).genAnnotations(descriptor); + return true; } // Annotations on properties without backing fields are stored in bytecode on an empty synthetic method. This way they're still // accessible via reflection, and 'deprecated' and 'private' flags prevent this method from being called accidentally - public static void generateSyntheticMethodForAnnotatedProperty( - @NotNull ClassBuilder v, - @NotNull JetTypeMapper typeMapper, - @NotNull PropertyDescriptor propertyDescriptor, - @NotNull Method method - ) { - MethodVisitor mv = v.newMethod(null, - ACC_DEPRECATED | ACC_FINAL | ACC_PRIVATE | ACC_STATIC | ACC_SYNTHETIC, - method.getName(), - method.getDescriptor(), - null, - null); - AnnotationCodegen.forMethod(mv, typeMapper).genAnnotations(propertyDescriptor); - mv.visitCode(); - mv.visitInsn(Opcodes.RETURN); - mv.visitEnd(); - } + private void generateSyntheticMethodIfNeeded(@NotNull PropertyDescriptor descriptor) { + if (descriptor.getAnnotations().isEmpty()) return; - @NotNull - public static Method getSyntheticMethodSignature(@NotNull JetTypeMapper typeMapper, @NotNull PropertyDescriptor propertyDescriptor) { - ReceiverParameterDescriptor receiver = propertyDescriptor.getReceiverParameter(); + ReceiverParameterDescriptor receiver = descriptor.getReceiverParameter(); Type receiverAsmType = receiver == null ? null : typeMapper.mapType(receiver.getType()); - return JvmAbi.getSyntheticMethodSignatureForAnnotatedProperty(propertyDescriptor.getName(), receiverAsmType); + Method method = JvmAbi.getSyntheticMethodSignatureForAnnotatedProperty(descriptor.getName(), receiverAsmType); + + if (!isTrait(context.getContextDescriptor()) || kind == OwnerKind.TRAIT_IMPL) { + MethodVisitor mv = v.newMethod(null, + ACC_DEPRECATED | ACC_FINAL | ACC_PRIVATE | ACC_STATIC | ACC_SYNTHETIC, + method.getName(), + method.getDescriptor(), + null, + null); + AnnotationCodegen.forMethod(mv, typeMapper).genAnnotations(descriptor); + mv.visitCode(); + mv.visitInsn(Opcodes.RETURN); + mv.visitEnd(); + } + else { + Type tImplType = typeMapper.mapTraitImpl((ClassDescriptor) context.getContextDescriptor()); + v.getMemberMap().recordImplClassNameForCallable(descriptor, shortNameByAsmType(tImplType)); + } + + if (kind != OwnerKind.TRAIT_IMPL) { + v.getMemberMap().recordSyntheticMethodOfProperty(descriptor, method); + } } private FieldVisitor generateBackingField(JetNamedDeclaration element, PropertyDescriptor propertyDescriptor, boolean isDelegate, JetType jetType, Object defaultValue) { diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/TraitImplBodyCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/TraitImplBodyCodegen.java index 899c9c1db9c..3537eca605b 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/TraitImplBodyCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/TraitImplBodyCodegen.java @@ -19,15 +19,9 @@ package org.jetbrains.jet.codegen; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.asm4.AnnotationVisitor; -import org.jetbrains.asm4.commons.Method; import org.jetbrains.jet.codegen.context.ClassContext; import org.jetbrains.jet.codegen.state.GenerationState; -import org.jetbrains.jet.lang.descriptors.PropertyDescriptor; -import org.jetbrains.jet.lang.descriptors.VariableDescriptor; import org.jetbrains.jet.lang.psi.JetClassOrObject; -import org.jetbrains.jet.lang.psi.JetDeclaration; -import org.jetbrains.jet.lang.psi.JetProperty; -import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.java.JvmAbi; import org.jetbrains.jet.lang.resolve.java.JvmAnnotationNames; @@ -65,23 +59,4 @@ public class TraitImplBodyCodegen extends ClassBodyCodegen { av.visit(JvmAnnotationNames.ABI_VERSION_FIELD_NAME, JvmAbi.VERSION); av.visitEnd(); } - - @Override - protected void generateSyntheticParts() { - generateSyntheticMethodsForAnnotatedProperties(); - } - - private void generateSyntheticMethodsForAnnotatedProperties() { - for (JetDeclaration declaration : myClass.getDeclarations()) { - if (declaration instanceof JetProperty) { - VariableDescriptor variable = bindingContext.get(BindingContext.VARIABLE, declaration); - assert variable instanceof PropertyDescriptor : "Variable in trait should be a property: " + variable; - PropertyDescriptor property = (PropertyDescriptor) variable; - if (!property.getAnnotations().isEmpty()) { - Method method = PropertyCodegen.getSyntheticMethodSignature(typeMapper, property); - PropertyCodegen.generateSyntheticMethodForAnnotatedProperty(v, typeMapper, property, method); - } - } - } - } }