| var log = "" |
| |
| fun <T> logged(value: T): T = |
| value.also { log += "$value;" } |
| |
| fun doTest(id: String, expected: Int, expectedLog: String, test: () -> Int) { |
| log = "" |
| val actual = test() |
| if (actual != expected) throw AssertionError("$id expected: $expected, actual: $actual") |
| if (log != expectedLog) throw AssertionError("$id expectedLog: $expectedLog, actual: $log") |
| } |
| |
| object A { |
| var x = 0 |
| get() = field.also { log += "get-A.x;" } |
| set(value: Int) { |
| log += "set-A.x;" |
| field = value |
| } |
| |
| } |
| |
| fun getA() = A.also { log += "getA();" } |
| |
| object B { |
| var x = 0 |
| |
| operator fun get(i1: Int, i2: Int, i3: Int): Int = x.also { log += "get-B($i1, $i2, $i3);" } |
| |
| operator fun set(i1: Int, i2: Int, i3: Int, value: Int) { |
| log += "set-B($i1, $i2, $i3, $value);" |
| x = value |
| } |
| } |
| |
| fun getB() = B.also { log += "getB();" } |
| |
| fun box(): String { |
| // NOTE: Getter is currently called twice for prefix increment; 1st for initial value, 2nd for return value. See KT-42077. |
| doTest("++getA().x", 1, "getA();get-A.x;set-A.x;get-A.x;") { ++getA().x } |
| doTest("getA().x--", 1, "getA();get-A.x;set-A.x;") { getA().x-- } |
| |
| doTest("++getB()[1, 2, 3]", 1, "getB();1;2;3;get-B(1, 2, 3);set-B(1, 2, 3, 1);get-B(1, 2, 3);") { |
| ++getB()[logged(1), logged(2), logged(3)] |
| } |
| doTest("getB()[1, 2, 3].x--", 1, "getB();1;2;3;get-B(1, 2, 3);set-B(1, 2, 3, 0);") { getB()[logged(1), logged(2), logged(3)]-- } |
| |
| return "OK" |
| } |