[atomicfu] Added a check that atomic properties are declared as final values.
Fixes: https://github.com/Kotlin/kotlinx-atomicfu/issues/237 YT: KT-61550 Merge-request: KT-MR-11886 Merged-by: Maria Sokolova <maria.sokolova@jetbrains.com>
This commit is contained in:
+18
-7
@@ -156,18 +156,19 @@ abstract class AbstractAtomicfuTransformer(val pluginContext: IrPluginContext) {
|
|||||||
val isTopLevel = parentContainer is IrFile || (parentContainer is IrClass && parentContainer.kind == ClassKind.OBJECT)
|
val isTopLevel = parentContainer is IrFile || (parentContainer is IrClass && parentContainer.kind == ClassKind.OBJECT)
|
||||||
when {
|
when {
|
||||||
atomicProperty.isAtomic() -> {
|
atomicProperty.isAtomic() -> {
|
||||||
|
atomicProperty.checkIsFinal(isArray = false)
|
||||||
|
atomicProperty.checkVisibility(isArray = false)
|
||||||
if (isTopLevel) {
|
if (isTopLevel) {
|
||||||
atomicProperty.checkVisibility()
|
|
||||||
parentContainer.addTransformedStaticAtomic(atomicProperty, index)
|
parentContainer.addTransformedStaticAtomic(atomicProperty, index)
|
||||||
} else {
|
} else {
|
||||||
atomicProperty.checkVisibility()
|
|
||||||
(parentContainer as IrClass).addTransformedInClassAtomic(atomicProperty, index)
|
(parentContainer as IrClass).addTransformedInClassAtomic(atomicProperty, index)
|
||||||
}.also {
|
}.also {
|
||||||
declarationsToBeRemoved.add(atomicProperty)
|
declarationsToBeRemoved.add(atomicProperty)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
atomicProperty.isAtomicArray() -> {
|
atomicProperty.isAtomicArray() -> {
|
||||||
atomicProperty.checkVisibility()
|
atomicProperty.checkIsFinal(isArray = true)
|
||||||
|
atomicProperty.checkVisibility(isArray = true)
|
||||||
parentContainer.addTransformedAtomicArray(atomicProperty, index).also {
|
parentContainer.addTransformedAtomicArray(atomicProperty, index).also {
|
||||||
declarationsToBeRemoved.add(atomicProperty)
|
declarationsToBeRemoved.add(atomicProperty)
|
||||||
}
|
}
|
||||||
@@ -448,18 +449,28 @@ abstract class AbstractAtomicfuTransformer(val pluginContext: IrPluginContext) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun IrProperty.checkVisibility() =
|
private fun IrProperty.checkIsFinal(isArray: Boolean) =
|
||||||
|
check(!isVar) {
|
||||||
|
"Please consider declaring [${this.atomicfuRender()}] from [${this.parent.render()}] as a private val or internal val.\n" +
|
||||||
|
if (!isArray) "If you need to declare a variable with accessors delegated to the atomic property value, you can use a delegated property declared within the same scope, e.g:\n" +
|
||||||
|
"```\n" +
|
||||||
|
"private val _a = atomic<T>(initial) \n" +
|
||||||
|
"public var a: T by _a \n" +
|
||||||
|
"```\n" else ""
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun IrProperty.checkVisibility(isArray: Boolean) =
|
||||||
check((visibility == DescriptorVisibilities.PRIVATE || visibility == DescriptorVisibilities.INTERNAL) ||
|
check((visibility == DescriptorVisibilities.PRIVATE || visibility == DescriptorVisibilities.INTERNAL) ||
|
||||||
(parent is IrClass &&
|
(parent is IrClass &&
|
||||||
(parentAsClass.visibility == DescriptorVisibilities.PRIVATE || parentAsClass.visibility == DescriptorVisibilities.INTERNAL))) {
|
(parentAsClass.visibility == DescriptorVisibilities.PRIVATE || parentAsClass.visibility == DescriptorVisibilities.INTERNAL))) {
|
||||||
"To ensure that atomic properties are not accessed out of the current Kotlin module, it is necessary to declare atomic properties as private or internal.\n" +
|
"To ensure that atomic properties are not accessed out of the current Kotlin module, it is necessary to declare atomic properties as private or internal.\n" +
|
||||||
"Please consider declaring [${this.atomicfuRender()}] from [${this.parent.render()}] as a private or internal property.\n" +
|
"Please consider declaring [${this.atomicfuRender()}] from [${this.parent.render()}] as a private or internal property.\n" +
|
||||||
(if (parent is IrClass) "You may also make the containing class [${parentAsClass.render()}] private or internal.\n" else "") +
|
(if (parent is IrClass) "You may also make the containing class [${parentAsClass.render()}] private or internal.\n" else "") +
|
||||||
"Alternatively, if you need to expose the atomic property value to the public, you can use a delegated property declared within the same scope, e.g:\n" +
|
if (!isArray) "Alternatively, if you need to expose the atomic property value to the public, you can use a delegated property declared within the same scope, e.g:\n" +
|
||||||
"```\n" +
|
"```\n" +
|
||||||
"private val _a = atomic<T>(initial) \n" +
|
"private val _a = atomic<T>(initial) \n" +
|
||||||
"public var a: T by _a \n" +
|
"public var a: T by _a \n" +
|
||||||
"```\n"
|
"```\n" else ""
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun IrProperty.getMinVisibility(): DescriptorVisibility {
|
protected fun IrProperty.getMinVisibility(): DescriptorVisibility {
|
||||||
@@ -1141,5 +1152,5 @@ abstract class AbstractAtomicfuTransformer(val pluginContext: IrPluginContext) {
|
|||||||
protected fun IrType.isObject() = classOrNull?.owner?.kind == ClassKind.OBJECT
|
protected fun IrType.isObject() = classOrNull?.owner?.kind == ClassKind.OBJECT
|
||||||
|
|
||||||
protected fun IrProperty.atomicfuRender(): String =
|
protected fun IrProperty.atomicfuRender(): String =
|
||||||
"val " + name.asString() + ": " + backingField?.type?.render()
|
(if (isVar) "var" else "val") + " " + name.asString() + ": " + backingField?.type?.render()
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user