bug with delegation from EA
This commit is contained in:
@@ -459,9 +459,47 @@ public class FunctionCodegen {
|
||||
iv.aconst(null);
|
||||
iv.areturn(overriden.getReturnType());
|
||||
endVisit(mv, "bridge method", state.getBindingContext().get(BindingContext.DESCRIPTOR_TO_DECLARATION, functionDescriptor));
|
||||
mv.visitEnd();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void genDelegate(FunctionDescriptor functionDescriptor, CallableMemberDescriptor overriddenDescriptor, StackValue field) {
|
||||
JvmMethodSignature jvmMethodSignature = state.getTypeMapper().mapSignature(functionDescriptor.getName(), functionDescriptor);
|
||||
genDelegate(functionDescriptor, overriddenDescriptor, field, jvmMethodSignature);
|
||||
}
|
||||
|
||||
public void genDelegate(CallableMemberDescriptor functionDescriptor, CallableMemberDescriptor overriddenDescriptor, StackValue field, JvmMethodSignature jvmMethodSignature) {
|
||||
Method method = jvmMethodSignature.getAsmMethod();
|
||||
int flags = ACC_PUBLIC | ACC_SYNTHETIC; // TODO.
|
||||
|
||||
final MethodVisitor mv = v.newMethod(null, flags, method.getName(), method.getDescriptor(), null, null);
|
||||
if (v.generateCode()) {
|
||||
mv.visitCode();
|
||||
|
||||
Type[] argTypes = method.getArgumentTypes();
|
||||
InstructionAdapter iv = new InstructionAdapter(mv);
|
||||
iv.load(0, JetTypeMapper.TYPE_OBJECT);
|
||||
for (int i = 0, reg = 1; i < argTypes.length; i++) {
|
||||
Type argType = argTypes[i];
|
||||
iv.load(reg, argType);
|
||||
if(argType.getSort() == Type.OBJECT) {
|
||||
StackValue.onStack(JetTypeMapper.TYPE_OBJECT).put(method.getArgumentTypes()[i], iv);
|
||||
}
|
||||
|
||||
//noinspection AssignmentToForLoopParameter
|
||||
reg += argType.getSize();
|
||||
}
|
||||
|
||||
iv.load(0, JetTypeMapper.TYPE_OBJECT);
|
||||
field.put(field.type, iv);
|
||||
ClassDescriptor classDescriptor = (ClassDescriptor) overriddenDescriptor.getContainingDeclaration();
|
||||
String internalName = state.getTypeMapper().mapType(classDescriptor.getDefaultType()).getInternalName();
|
||||
if(classDescriptor.getKind() == ClassKind.TRAIT)
|
||||
iv.invokeinterface(internalName, method.getName(), method.getDescriptor());
|
||||
else
|
||||
iv.invokevirtual(internalName, method.getName(), method.getDescriptor());
|
||||
iv.areturn(method.getReturnType());
|
||||
endVisit(mv, "delegate method", state.getBindingContext().get(BindingContext.DESCRIPTOR_TO_DECLARATION, functionDescriptor));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -567,17 +567,18 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
JetType superType = bindingContext.get(BindingContext.TYPE, specifier.getTypeReference());
|
||||
assert superType != null;
|
||||
ClassDescriptor superClassDescriptor = (ClassDescriptor) superType.getConstructor().getDeclarationDescriptor();
|
||||
String delegateField = "$delegate_" + n;
|
||||
Type fieldType = typeMapper.mapType(superClassDescriptor.getDefaultType(), OwnerKind.IMPLEMENTATION);
|
||||
String delegateField = "$delegate_" + (n++);
|
||||
Type fieldType = typeMapper.mapType(superClassDescriptor.getDefaultType());
|
||||
String fieldDesc = fieldType.getDescriptor();
|
||||
v.newField(specifier, ACC_PRIVATE, delegateField, fieldDesc, /*TODO*/null, null);
|
||||
iv.putfield(classname, delegateField, fieldDesc);
|
||||
StackValue field = StackValue.field(fieldType, classname, delegateField, false);
|
||||
field.store(iv);
|
||||
|
||||
JetClass superClass = (JetClass) bindingContext.get(BindingContext.DESCRIPTOR_TO_DECLARATION, superClassDescriptor);
|
||||
final CodegenContext delegateContext = context.intoClass(superClassDescriptor,
|
||||
new OwnerKind.DelegateKind(StackValue.field(fieldType, classname, delegateField, false),
|
||||
typeMapper.mapType(superClassDescriptor.getDefaultType(), OwnerKind.IMPLEMENTATION).getInternalName()), state.getTypeMapper());
|
||||
generateDelegates(superClass, delegateContext, overridden);
|
||||
typeMapper.mapType(superClassDescriptor.getDefaultType()).getInternalName()), state.getTypeMapper());
|
||||
generateDelegates(superClass, delegateContext, field);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -657,7 +658,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
}
|
||||
}
|
||||
|
||||
private void generateDelegationToTraitImpl(ExpressionCodegen codegen, @NotNull FunctionDescriptor fun) {
|
||||
private void generateDelegationToTraitImpl(ExpressionCodegen codegen, FunctionDescriptor fun) {
|
||||
DeclarationDescriptor containingDeclaration = fun.getContainingDeclaration();
|
||||
if(containingDeclaration instanceof ClassDescriptor) {
|
||||
ClassDescriptor declaration = (ClassDescriptor) containingDeclaration;
|
||||
@@ -902,17 +903,26 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
}
|
||||
}
|
||||
|
||||
protected void generateDelegates(JetClass toClass, CodegenContext delegateContext, Set<FunctionDescriptor> overriden) {
|
||||
protected void generateDelegates(JetClass toClass, CodegenContext delegateContext, StackValue field) {
|
||||
final FunctionCodegen functionCodegen = new FunctionCodegen(delegateContext, v, state);
|
||||
final PropertyCodegen propertyCodegen = new PropertyCodegen(delegateContext, v, functionCodegen, state);
|
||||
|
||||
for (JetDeclaration declaration : toClass.getDeclarations()) {
|
||||
if (declaration instanceof JetProperty) {
|
||||
propertyCodegen.gen((JetProperty) declaration);
|
||||
}
|
||||
else if (declaration instanceof JetNamedFunction) {
|
||||
if (!overriden.contains(bindingContext.get(BindingContext.FUNCTION, declaration))) {
|
||||
functionCodegen.gen((JetNamedFunction) declaration);
|
||||
ClassDescriptor classDescriptor = bindingContext.get(BindingContext.CLASS, toClass);
|
||||
for (DeclarationDescriptor declaration : descriptor.getDefaultType().getMemberScope().getAllDescriptors()) {
|
||||
if (declaration instanceof CallableMemberDescriptor) {
|
||||
CallableMemberDescriptor callableMemberDescriptor = (CallableMemberDescriptor) declaration;
|
||||
if (callableMemberDescriptor.getKind() == CallableMemberDescriptor.Kind.DELEGATION) {
|
||||
Set<? extends CallableMemberDescriptor> overriddenDescriptors = callableMemberDescriptor.getOverriddenDescriptors();
|
||||
for (CallableMemberDescriptor overriddenDescriptor : overriddenDescriptors) {
|
||||
if(overriddenDescriptor.getContainingDeclaration() == classDescriptor) {
|
||||
if (declaration instanceof PropertyDescriptor) {
|
||||
propertyCodegen.genDelegate((PropertyDescriptor) declaration, (PropertyDescriptor) overriddenDescriptor, field);
|
||||
}
|
||||
else if (declaration instanceof NamedFunctionDescriptor) {
|
||||
functionCodegen.genDelegate((NamedFunctionDescriptor) declaration, overriddenDescriptor, field);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,6 +30,10 @@ import org.objectweb.asm.MethodVisitor;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
import org.objectweb.asm.Type;
|
||||
import org.objectweb.asm.commons.InstructionAdapter;
|
||||
import org.objectweb.asm.commons.Method;
|
||||
|
||||
import static org.objectweb.asm.Opcodes.ACC_PUBLIC;
|
||||
import static org.objectweb.asm.Opcodes.ACC_SYNTHETIC;
|
||||
|
||||
/**
|
||||
* @author max
|
||||
@@ -271,4 +275,14 @@ public class PropertyCodegen {
|
||||
public static String setterName(String propertyName) {
|
||||
return JvmAbi.SETTER_PREFIX + StringUtil.capitalizeWithJavaBeanConvention(propertyName);
|
||||
}
|
||||
|
||||
public void genDelegate(PropertyDescriptor declaration, PropertyDescriptor overriddenDescriptor, StackValue field) {
|
||||
JvmPropertyAccessorSignature jvmPropertyAccessorSignature = state.getTypeMapper().mapGetterSignature(declaration, OwnerKind.IMPLEMENTATION);
|
||||
functionCodegen.genDelegate(declaration, overriddenDescriptor, field, jvmPropertyAccessorSignature.getJvmMethodSignature());
|
||||
|
||||
if(declaration.isVar()) {
|
||||
jvmPropertyAccessorSignature = state.getTypeMapper().mapSetterSignature(declaration, OwnerKind.IMPLEMENTATION);
|
||||
functionCodegen.genDelegate(declaration, overriddenDescriptor, field, jvmPropertyAccessorSignature.getJvmMethodSignature());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
trait Trait1 {
|
||||
fun foo() : String
|
||||
}
|
||||
|
||||
trait Trait2 {
|
||||
fun bar() : String
|
||||
}
|
||||
|
||||
class T1 : Trait1{
|
||||
override fun foo() = "aaa"
|
||||
}
|
||||
|
||||
class T2 : Trait2{
|
||||
override fun bar() = "bbb"
|
||||
}
|
||||
|
||||
class C(a:Trait1, b:Trait2) : Trait1 by a, Trait2 by b
|
||||
|
||||
fun box() : String {
|
||||
val c = C(T1(),T2())
|
||||
if(c.foo() != "aaa") return "fail"
|
||||
if(c.bar() != "bbb") return "fail"
|
||||
return "OK"
|
||||
}
|
||||
@@ -47,6 +47,10 @@ public class ClassGenTest extends CodegenTestCase {
|
||||
blackBoxFile("classes/inheritance.jet");
|
||||
}
|
||||
|
||||
public void testInheritanceAndDelegation2() throws Exception {
|
||||
blackBoxFile("classes/delegation2.kt");
|
||||
}
|
||||
|
||||
public void testFunDelegation() throws Exception {
|
||||
blackBoxFile("classes/funDelegation.jet");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user