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();
|
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;
|
ObjectOrClosureCodegen closure = context.closure;
|
||||||
int firstSuperArgument = -1;
|
int firstSuperArgument = -1;
|
||||||
final LinkedList<JvmMethodParameterSignature> consArgTypes = new LinkedList<JvmMethodParameterSignature>(constructorMethod.getKotlinParameterTypes());
|
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);
|
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 ClassDescriptor outerDescriptor = typeMapper.getClosureAnnotator().getEclosingClassDescriptor(descriptor);
|
||||||
final boolean hasOuterThis = typeMapper.hasThis0(descriptor) && outerDescriptor != null;
|
final boolean hasOuterThis = typeMapper.hasThis0(descriptor) && outerDescriptor != null;
|
||||||
if (hasOuterThis) {
|
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;
|
int curParam = 0;
|
||||||
List<JetParameter> constructorParameters = getPrimaryConstructorParameters();
|
List<JetParameter> constructorParameters = getPrimaryConstructorParameters();
|
||||||
for (JetParameter parameter : constructorParameters) {
|
for (JetParameter parameter : constructorParameters) {
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
package org.jetbrains.jet.codegen;
|
package org.jetbrains.jet.codegen;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.jet.lang.descriptors.*;
|
import org.jetbrains.jet.lang.descriptors.*;
|
||||||
import org.jetbrains.jet.lang.psi.JetDelegatorToSuperCall;
|
import org.jetbrains.jet.lang.psi.JetDelegatorToSuperCall;
|
||||||
import org.jetbrains.jet.lang.psi.JetElement;
|
import org.jetbrains.jet.lang.psi.JetElement;
|
||||||
@@ -48,7 +49,7 @@ public class ObjectOrClosureCodegen {
|
|||||||
this.state = state;
|
this.state = state;
|
||||||
}
|
}
|
||||||
|
|
||||||
public StackValue lookupInContext(DeclarationDescriptor d, StackValue result) {
|
public StackValue lookupInContext(DeclarationDescriptor d, @Nullable StackValue result) {
|
||||||
EnclosedValueDescriptor answer = closure.get(d);
|
EnclosedValueDescriptor answer = closure.get(d);
|
||||||
if (answer != null) {
|
if (answer != null) {
|
||||||
StackValue innerValue = answer.getInnerValue();
|
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);
|
createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.JDK_ONLY);
|
||||||
blackBoxFile("regressions/kt1891.kt");
|
blackBoxFile("regressions/kt1891.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testKt2224() {
|
||||||
|
createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.JDK_ONLY);
|
||||||
|
blackBoxFile("regressions/kt2224.kt");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user