Refactor codegen of property backing fields, TImpl, etc.
- remove synthetic method code generation from TraitImplBodyCodegen, use PropertyCodegen for that - don't try to generate synthetic methods for constructor properties - inline methods, NotNull, renames, etc.
This commit is contained in:
@@ -81,7 +81,8 @@ public abstract class ClassBodyCodegen extends MemberCodegen {
|
|||||||
|
|
||||||
protected abstract void generateKotlinAnnotation();
|
protected abstract void generateKotlinAnnotation();
|
||||||
|
|
||||||
protected abstract void generateSyntheticParts();
|
protected void generateSyntheticParts() {
|
||||||
|
}
|
||||||
|
|
||||||
private void generateClassBody() {
|
private void generateClassBody() {
|
||||||
FunctionCodegen functionCodegen = new FunctionCodegen(context, v, state, this);
|
FunctionCodegen functionCodegen = new FunctionCodegen(context, v, state, this);
|
||||||
|
|||||||
@@ -94,8 +94,8 @@ public class PropertyCodegen extends GenerationStateAware {
|
|||||||
Type ownerType = ((NamespaceFacadeContext) context).getDelegateToClassType();
|
Type ownerType = ((NamespaceFacadeContext) context).getDelegateToClassType();
|
||||||
v.getMemberMap().recordImplClassNameForCallable(propertyDescriptor, shortNameByAsmType(ownerType));
|
v.getMemberMap().recordImplClassNameForCallable(propertyDescriptor, shortNameByAsmType(ownerType));
|
||||||
}
|
}
|
||||||
else if (kind != OwnerKind.TRAIT_IMPL) {
|
else if (!generateBackingField(p, propertyDescriptor)) {
|
||||||
generateBackingField(p, propertyDescriptor);
|
generateSyntheticMethodIfNeeded(propertyDescriptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
generateGetter(p, propertyDescriptor, p.getGetter());
|
generateGetter(p, propertyDescriptor, p.getGetter());
|
||||||
@@ -126,60 +126,55 @@ public class PropertyCodegen extends GenerationStateAware {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generateBackingField(JetNamedDeclaration p, PropertyDescriptor propertyDescriptor) {
|
private boolean generateBackingField(@NotNull JetNamedDeclaration p, @NotNull PropertyDescriptor descriptor) {
|
||||||
boolean hasBackingField = Boolean.TRUE.equals(bindingContext.get(BindingContext.BACKING_FIELD_REQUIRED, propertyDescriptor));
|
if (isInterface(descriptor.getContainingDeclaration()) || kind == OwnerKind.TRAIT_IMPL) {
|
||||||
boolean isDelegated = p instanceof JetProperty && ((JetProperty) p).getDelegateExpression() != null;
|
return false;
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
else if (!propertyDescriptor.getAnnotations().isEmpty()) {
|
|
||||||
Method method = getSyntheticMethodSignature(typeMapper, propertyDescriptor);
|
FieldVisitor fv;
|
||||||
DeclarationDescriptor descriptor = context.getContextDescriptor();
|
if (Boolean.TRUE.equals(bindingContext.get(BindingContext.BACKING_FIELD_REQUIRED, descriptor))) {
|
||||||
if (isTrait(descriptor)) {
|
fv = generateBackingFieldAccess(p, descriptor);
|
||||||
Type tImplType = typeMapper.mapTraitImpl((ClassDescriptor) descriptor);
|
|
||||||
v.getMemberMap().recordImplClassNameForCallable(propertyDescriptor, shortNameByAsmType(tImplType));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
generateSyntheticMethodForAnnotatedProperty(v, typeMapper, propertyDescriptor, method);
|
|
||||||
}
|
|
||||||
v.getMemberMap().recordSyntheticMethodOfProperty(propertyDescriptor, method);
|
|
||||||
}
|
}
|
||||||
|
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
|
// 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
|
// accessible via reflection, and 'deprecated' and 'private' flags prevent this method from being called accidentally
|
||||||
public static void generateSyntheticMethodForAnnotatedProperty(
|
private void generateSyntheticMethodIfNeeded(@NotNull PropertyDescriptor descriptor) {
|
||||||
@NotNull ClassBuilder v,
|
if (descriptor.getAnnotations().isEmpty()) return;
|
||||||
@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();
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
ReceiverParameterDescriptor receiver = descriptor.getReceiverParameter();
|
||||||
public static Method getSyntheticMethodSignature(@NotNull JetTypeMapper typeMapper, @NotNull PropertyDescriptor propertyDescriptor) {
|
|
||||||
ReceiverParameterDescriptor receiver = propertyDescriptor.getReceiverParameter();
|
|
||||||
Type receiverAsmType = receiver == null ? null : typeMapper.mapType(receiver.getType());
|
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) {
|
private FieldVisitor generateBackingField(JetNamedDeclaration element, PropertyDescriptor propertyDescriptor, boolean isDelegate, JetType jetType, Object defaultValue) {
|
||||||
|
|||||||
@@ -19,15 +19,9 @@ package org.jetbrains.jet.codegen;
|
|||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.asm4.AnnotationVisitor;
|
import org.jetbrains.asm4.AnnotationVisitor;
|
||||||
import org.jetbrains.asm4.commons.Method;
|
|
||||||
import org.jetbrains.jet.codegen.context.ClassContext;
|
import org.jetbrains.jet.codegen.context.ClassContext;
|
||||||
import org.jetbrains.jet.codegen.state.GenerationState;
|
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.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.JvmAbi;
|
||||||
import org.jetbrains.jet.lang.resolve.java.JvmAnnotationNames;
|
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.visit(JvmAnnotationNames.ABI_VERSION_FIELD_NAME, JvmAbi.VERSION);
|
||||||
av.visitEnd();
|
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user