Atomicfu plugin (JS IR): fix for private delegated properties
Fixes https://github.com/Kotlin/kotlinx-atomicfu/issues/260
This commit is contained in:
+11
-10
@@ -125,13 +125,13 @@ class AtomicfuJsIrTransformer(private val context: IrPluginContext) {
|
||||
// fun <get-a>() = a$delegate.value -> _a.value
|
||||
// fun <set-a>(value: Int) = { a$delegate.value = value } -> { _a.value = value }
|
||||
val originalField = initializer.getBackingField()
|
||||
declaration.transform(DelegatePropertyTransformer(originalField, initializer.dispatchReceiver, false), null)
|
||||
declaration.transform(DelegatePropertyTransformer(originalField), null)
|
||||
}
|
||||
initializer.isAtomicFactory() -> {
|
||||
// var a by atomic(77) -> var a: Int = 77
|
||||
it.expression = initializer.eraseAtomicFactory()
|
||||
?: error("Atomic factory was expected but found ${initializer.render()}")
|
||||
declaration.transform(DelegatePropertyTransformer(delegateBackingField, initializer.dispatchReceiver, true), null)
|
||||
declaration.transform(DelegatePropertyTransformer(delegateBackingField), null)
|
||||
}
|
||||
else -> error("Unexpected initializer of the delegated property: $initializer")
|
||||
}
|
||||
@@ -275,9 +275,7 @@ class AtomicfuJsIrTransformer(private val context: IrPluginContext) {
|
||||
}
|
||||
|
||||
private inner class DelegatePropertyTransformer(
|
||||
val originalField: IrField,
|
||||
val receiver: IrExpression?,
|
||||
val isInitializedWithAtomicFactory: Boolean
|
||||
val originalField: IrField
|
||||
): IrElementTransformerVoid() {
|
||||
override fun visitCall(expression: IrCall): IrExpression {
|
||||
// Accessors of the delegated property have following signatures:
|
||||
@@ -291,11 +289,14 @@ class AtomicfuJsIrTransformer(private val context: IrPluginContext) {
|
||||
val type = originalField.type.atomicToValueType()
|
||||
val isSetter = name == SET_VALUE
|
||||
val runtimeFunction = getRuntimeFunctionSymbol(name, type)
|
||||
val dispatchReceiver = if (isInitializedWithAtomicFactory) {
|
||||
val thisRef = expression.getValueArgument(0)!!
|
||||
if (thisRef.isConstNull()) null else thisRef
|
||||
} else {
|
||||
receiver
|
||||
// val _a = atomic(77)
|
||||
// var a: Int by _a
|
||||
// This is the delegate getValue operator of property `a`, which should be transformed to getting the value of the original atomic `_a`
|
||||
// operator fun getValue(thisRef: Any?, property: kotlin.reflect.KProperty<*>) {
|
||||
// return thisRef._a
|
||||
// }
|
||||
val dispatchReceiver = expression.getValueArgument(0)?.let {
|
||||
if (it.isConstNull()) null else it
|
||||
}
|
||||
val fieldAccessors = listOf(
|
||||
context.buildFieldAccessor(originalField, dispatchReceiver, false),
|
||||
|
||||
+27
-18
@@ -7,37 +7,47 @@ var topLevelInt: Int by _topLevelInt
|
||||
private var topLevelVolatile by atomic(56)
|
||||
|
||||
class DelegatedProperties {
|
||||
// Delegated properties should be declared in the same scope as the original atomic values
|
||||
private val _a = atomic(42)
|
||||
var a: Int by _a
|
||||
private var privateA: Int by _a
|
||||
|
||||
private val _l = atomic(55555555555)
|
||||
var l: Long by _l
|
||||
private var l: Long by _l
|
||||
|
||||
private val _b = atomic(false)
|
||||
var b: Boolean by _b
|
||||
private var b: Boolean by _b
|
||||
|
||||
private val _ref = atomic(A(B(77)))
|
||||
var ref: A by _ref
|
||||
private var ref: A by _ref
|
||||
|
||||
var vInt by atomic(77)
|
||||
private var vInt by atomic(77)
|
||||
|
||||
var vLong by atomic(777777777)
|
||||
private var vLong by atomic(777777777)
|
||||
|
||||
var vBoolean by atomic(false)
|
||||
private var vBoolean by atomic(false)
|
||||
|
||||
var vRef by atomic(A(B(77)))
|
||||
private var vRef by atomic(A(B(77)))
|
||||
|
||||
class A (val b: B)
|
||||
class B (val n: Int)
|
||||
|
||||
fun testDelegatedAtomicInt() {
|
||||
assertEquals(42, a)
|
||||
assertEquals(42, privateA)
|
||||
_a.compareAndSet(42, 56)
|
||||
assertEquals(56, a)
|
||||
assertEquals(56, privateA)
|
||||
a = 77
|
||||
_a.compareAndSet(77, 66)
|
||||
privateA = 88
|
||||
_a.compareAndSet(88, 66)
|
||||
assertEquals(66, _a.value)
|
||||
assertEquals(66, a)
|
||||
assertEquals(66, privateA)
|
||||
|
||||
val aValue = a + privateA
|
||||
assertEquals(132, aValue)
|
||||
}
|
||||
|
||||
fun testDelegatedAtomicLong() {
|
||||
@@ -95,25 +105,23 @@ class DelegatedProperties {
|
||||
}
|
||||
|
||||
inner class D {
|
||||
var b: Int by _a
|
||||
var c by atomic("aaa")
|
||||
}
|
||||
|
||||
fun testScopedDelegatedProperties() {
|
||||
fun testScopedVolatileProperties() {
|
||||
val clazz = D()
|
||||
clazz.b = 42
|
||||
_a.compareAndSet(42, 56)
|
||||
assertEquals(56, clazz.b)
|
||||
clazz.b = 77
|
||||
_a.compareAndSet(77, 66)
|
||||
assertEquals(66, _a.value)
|
||||
assertEquals(66, clazz.b)
|
||||
|
||||
assertEquals("aaa", clazz.c)
|
||||
clazz.c = "bbb"
|
||||
assertEquals("bbb", clazz.c)
|
||||
}
|
||||
|
||||
fun testDelegatedVariablesFlow() {
|
||||
_a.lazySet(55)
|
||||
assertEquals(55, _a.value)
|
||||
assertEquals(55, a)
|
||||
var aValue = a
|
||||
}
|
||||
|
||||
fun test() {
|
||||
testDelegatedAtomicInt()
|
||||
testDelegatedAtomicLong()
|
||||
@@ -123,7 +131,8 @@ class DelegatedProperties {
|
||||
testVolatileBoolean()
|
||||
testVolatileLong()
|
||||
testVolatileRef()
|
||||
testScopedDelegatedProperties()
|
||||
testScopedVolatileProperties()
|
||||
testDelegatedVariablesFlow()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user