Merge pull request #95 from udalov/kt2224
object literals now capture expressions from 'by' delegate specifier
This commit is contained in:
@@ -493,6 +493,25 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
constructorMethod = callableMethod.getSignature();
|
||||
}
|
||||
|
||||
if (context.closure != null) {
|
||||
for (JetDelegationSpecifier specifier : myClass.getDelegationSpecifiers()) {
|
||||
if (specifier != superCall && specifier instanceof JetDelegatorByExpressionSpecifier) {
|
||||
JetExpression delegateExpression = ((JetDelegatorByExpressionSpecifier) specifier).getDelegateExpression();
|
||||
delegateExpression.accept(new JetVisitorVoid() {
|
||||
@Override
|
||||
public void visitJetElement(JetElement e) {
|
||||
e.acceptChildren(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitSimpleNameExpression(JetSimpleNameExpression expr) {
|
||||
context.closure.lookupInContext(bindingContext.get(BindingContext.REFERENCE_TARGET, expr), null);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ObjectOrClosureCodegen closure = context.closure;
|
||||
int firstSuperArgument = -1;
|
||||
final LinkedList<JvmMethodParameterSignature> consArgTypes = new LinkedList<JvmMethodParameterSignature>(constructorMethod.getKotlinParameterTypes());
|
||||
@@ -638,33 +657,6 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
generateDelegatorToConstructorCall(iv, codegen, (JetDelegatorToSuperCall) superCall, constructorDescriptor1, frameMap, firstSuperArgument);
|
||||
}
|
||||
|
||||
int n = 0;
|
||||
for (JetDelegationSpecifier specifier : myClass.getDelegationSpecifiers()) {
|
||||
if (specifier == superCall)
|
||||
continue;
|
||||
|
||||
if (specifier instanceof JetDelegatorByExpressionSpecifier) {
|
||||
iv.load(0, classType);
|
||||
codegen.genToJVMStack(((JetDelegatorByExpressionSpecifier) specifier).getDelegateExpression());
|
||||
|
||||
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(), MapTypeMode.VALUE);
|
||||
String fieldDesc = fieldType.getDescriptor();
|
||||
v.newField(specifier, ACC_PRIVATE, delegateField, fieldDesc, /*TODO*/null, null);
|
||||
StackValue field = StackValue.field(fieldType, classname, delegateField, false);
|
||||
field.store(fieldType, iv);
|
||||
|
||||
JetClass superClass = (JetClass) BindingContextUtils.classDescriptorToDeclaration(bindingContext, superClassDescriptor);
|
||||
final CodegenContext delegateContext = context.intoClass(superClassDescriptor,
|
||||
new OwnerKind.DelegateKind(StackValue.field(fieldType, classname, delegateField, false),
|
||||
typeMapper.mapType(superClassDescriptor.getDefaultType(), MapTypeMode.IMPL).getInternalName()), state.getInjector().getJetTypeMapper());
|
||||
generateDelegates(superClass, delegateContext, field);
|
||||
}
|
||||
}
|
||||
|
||||
final ClassDescriptor outerDescriptor = typeMapper.getClosureAnnotator().getEclosingClassDescriptor(descriptor);
|
||||
final boolean hasOuterThis = typeMapper.hasThis0(descriptor) && outerDescriptor != null;
|
||||
if (hasOuterThis) {
|
||||
@@ -702,6 +694,33 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
}
|
||||
}
|
||||
|
||||
int n = 0;
|
||||
for (JetDelegationSpecifier specifier : myClass.getDelegationSpecifiers()) {
|
||||
if (specifier == superCall)
|
||||
continue;
|
||||
|
||||
if (specifier instanceof JetDelegatorByExpressionSpecifier) {
|
||||
iv.load(0, classType);
|
||||
codegen.genToJVMStack(((JetDelegatorByExpressionSpecifier) specifier).getDelegateExpression());
|
||||
|
||||
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(), MapTypeMode.VALUE);
|
||||
String fieldDesc = fieldType.getDescriptor();
|
||||
v.newField(specifier, ACC_PRIVATE, delegateField, fieldDesc, /*TODO*/null, null);
|
||||
StackValue field = StackValue.field(fieldType, classname, delegateField, false);
|
||||
field.store(fieldType, iv);
|
||||
|
||||
JetClass superClass = (JetClass) BindingContextUtils.classDescriptorToDeclaration(bindingContext, superClassDescriptor);
|
||||
final CodegenContext delegateContext = context.intoClass(superClassDescriptor,
|
||||
new OwnerKind.DelegateKind(StackValue.field(fieldType, classname, delegateField, false),
|
||||
typeMapper.mapType(superClassDescriptor.getDefaultType(), MapTypeMode.IMPL).getInternalName()), state.getInjector().getJetTypeMapper());
|
||||
generateDelegates(superClass, delegateContext, field);
|
||||
}
|
||||
}
|
||||
|
||||
int curParam = 0;
|
||||
List<JetParameter> constructorParameters = getPrimaryConstructorParameters();
|
||||
for (JetParameter parameter : constructorParameters) {
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.jetbrains.jet.codegen;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.descriptors.*;
|
||||
import org.jetbrains.jet.lang.psi.JetDelegatorToSuperCall;
|
||||
import org.jetbrains.jet.lang.psi.JetElement;
|
||||
@@ -48,7 +49,7 @@ public class ObjectOrClosureCodegen {
|
||||
this.state = state;
|
||||
}
|
||||
|
||||
public StackValue lookupInContext(DeclarationDescriptor d, StackValue result) {
|
||||
public StackValue lookupInContext(DeclarationDescriptor d, @Nullable StackValue result) {
|
||||
EnclosedValueDescriptor answer = closure.get(d);
|
||||
if (answer != null) {
|
||||
StackValue innerValue = answer.getInnerValue();
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
trait A {
|
||||
fun foo(): Int
|
||||
}
|
||||
|
||||
class B1 : A {
|
||||
override fun foo() = 10
|
||||
}
|
||||
|
||||
class B2(val z: Int) : A {
|
||||
override fun foo() = z
|
||||
}
|
||||
|
||||
|
||||
|
||||
fun f1(b: B1): Int {
|
||||
val o = object : A by b { }
|
||||
return o.foo()
|
||||
}
|
||||
|
||||
fun f2(b: B2): Int {
|
||||
val o = object : A by B2(b.z) { }
|
||||
return o.foo()
|
||||
}
|
||||
|
||||
fun f3(b: B2, mult: Int): Int {
|
||||
val o = object : A by B2(mult * b.z) { }
|
||||
return o.foo()
|
||||
}
|
||||
|
||||
fun f4(b: B1, x: Int, y: Int, z: Int): Int {
|
||||
val o = object : A by b {
|
||||
fun bar() = x + y + z
|
||||
}
|
||||
return o.foo()
|
||||
}
|
||||
|
||||
|
||||
fun box(): String {
|
||||
if (f1(B1()) != 10) return "fail #1"
|
||||
if (f2(B2(239)) != 239) return "fail #2"
|
||||
if (f3(B2(239), 2) != 239*2) return "fail #3"
|
||||
if (f4(B1(), 1, 2, 3) != 10) return "fail #4"
|
||||
return "OK"
|
||||
}
|
||||
@@ -446,4 +446,9 @@ public class ClassGenTest extends CodegenTestCase {
|
||||
createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.JDK_ONLY);
|
||||
blackBoxFile("regressions/kt1891.kt");
|
||||
}
|
||||
|
||||
public void testKt2224() {
|
||||
createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.JDK_ONLY);
|
||||
blackBoxFile("regressions/kt2224.kt");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user