Support increment and '+=' on local delegated properties
This commit is contained in:
@@ -2813,11 +2813,14 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
}
|
||||
}
|
||||
|
||||
public int indexOfLocal(KtReferenceExpression lhs) {
|
||||
public int indexOfLocalNotDelegated(KtReferenceExpression lhs) {
|
||||
DeclarationDescriptor declarationDescriptor = bindingContext.get(REFERENCE_TARGET, lhs);
|
||||
if (isVarCapturedInClosure(bindingContext, declarationDescriptor)) {
|
||||
return -1;
|
||||
}
|
||||
if (declarationDescriptor instanceof LocalVariableDescriptor && ((LocalVariableDescriptor) declarationDescriptor).isDelegated()) {
|
||||
return -1;
|
||||
}
|
||||
return lookupLocalIndex(declarationDescriptor);
|
||||
}
|
||||
|
||||
@@ -3346,7 +3349,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
// Optimization for j = i++, when j and i are Int without any smart cast: we just work with primitive int
|
||||
if (operand instanceof KtReferenceExpression && asmResultType == Type.INT_TYPE &&
|
||||
bindingContext.get(BindingContext.SMARTCAST, operand) == null) {
|
||||
int index = indexOfLocal((KtReferenceExpression) operand);
|
||||
int index = indexOfLocalNotDelegated((KtReferenceExpression) operand);
|
||||
if (index >= 0) {
|
||||
return StackValue.postIncrement(index, increment);
|
||||
}
|
||||
|
||||
@@ -672,7 +672,16 @@ public abstract class StackValue {
|
||||
@NotNull CallableMethod getter,
|
||||
@Nullable CallableMethod setter
|
||||
) {
|
||||
super(type, false, false, new Receiver(OBJECT_TYPE, delegateValue, constant(null, OBJECT_TYPE), metadataValue), false);
|
||||
super(type, false, false, new Receiver(OBJECT_TYPE, delegateValue, constant(null, OBJECT_TYPE), metadataValue) {
|
||||
@Override
|
||||
public void dup(@NotNull InstructionAdapter v, boolean withReceiver) {
|
||||
//UGLY HACK
|
||||
//TODO rethink Receiver/StackValue concept
|
||||
//We need to make duplication of delegated var, owner (null) and property metadata: dup 3.
|
||||
//As HACK Type.LONG_TYPE and Type.INT_TYPE passed to dup util to simulate dup 3.
|
||||
AsmUtil.dup(v, Type.LONG_TYPE, Type.INT_TYPE);
|
||||
}
|
||||
}, false);
|
||||
this.delegateValue = delegateValue;
|
||||
this.metadataValue = metadataValue;
|
||||
this.getter = getter;
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
import kotlin.reflect.KProperty
|
||||
|
||||
class Delegate {
|
||||
var inner = 1
|
||||
operator fun getValue(t: Any?, p: KProperty<*>): Int = inner
|
||||
operator fun setValue(t: Any?, p: KProperty<*>, i: Int) {
|
||||
inner = i
|
||||
}
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
var prop: Int by Delegate()
|
||||
var result = prop++
|
||||
if (result != 1) return "fail increment result: $prop"
|
||||
if (prop != 2) return "fail increment: $prop"
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
import kotlin.reflect.KProperty
|
||||
|
||||
class Delegate {
|
||||
var inner = 1
|
||||
operator fun getValue(t: Any?, p: KProperty<*>): Int = inner
|
||||
operator fun setValue(t: Any?, p: KProperty<*>, i: Int) {
|
||||
inner = i
|
||||
}
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
var prop: Int by Delegate()
|
||||
prop += 1
|
||||
if (prop != 2) return "fail : $prop"
|
||||
return "OK"
|
||||
}
|
||||
@@ -4974,6 +4974,27 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/delegatedProperty/varInInnerClass.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/box/delegatedProperty/local")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class Local extends AbstractBlackBoxCodegenTest {
|
||||
public void testAllFilesPresentInLocal() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/delegatedProperty/local"), Pattern.compile("^(.+)\\.kt$"), true);
|
||||
}
|
||||
|
||||
@TestMetadata("iinc.kt")
|
||||
public void testIinc() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/delegatedProperty/local/iinc.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("plusAssign.kt")
|
||||
public void testPlusAssign() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/delegatedProperty/local/plusAssign.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/box/delegation")
|
||||
|
||||
Reference in New Issue
Block a user