| /* |
| * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. |
| * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. |
| */ |
| |
| package test.properties.delegation.references |
| |
| import kotlin.reflect.* |
| import kotlin.test.* |
| import kotlin.internal.* |
| import kotlin.native.concurrent.ThreadLocal |
| import kotlin.random.* |
| |
| open class Data(val stringVal: String, var intVar: Int, var builderVar: StringBuilder = StringBuilder("default")) |
| val Data.formattedVal: String get() = "Hello $stringVal" |
| var Data.displacedVar: Int |
| get() = intVar + 2 |
| set(value) { intVar = value - 2 } |
| |
| @ThreadLocal |
| val data = Data("bound string", 42) |
| |
| val topVal: Double get() = 3.14 |
| @ThreadLocal |
| var topVar: ULong = 0xFFFFUL |
| |
| // top-level properties |
| |
| // val to bound val |
| @ThreadLocal |
| val tlValBoundVal by data::stringVal |
| // val to bound var |
| @ThreadLocal |
| val tlValBoundVar by data::intVar |
| // var to bound var |
| @ThreadLocal |
| var tlVarBoundVar by data::intVar |
| |
| // val to top-level val |
| @ThreadLocal |
| val tlValTopLevelVal by ::topVal |
| // val to top-level var |
| @ThreadLocal |
| val tlValTopLevelVar by ::topVar |
| // var to top-level var |
| @ThreadLocal |
| var tlVarTopLevelVar by ::topVar |
| |
| // member properties |
| class DataExt : Data("member string", -1) { |
| |
| // val to top-level val |
| val valTopLevelVal by ::topVal |
| |
| // val to top-level var |
| val valTopLevelVar by ::topVar |
| |
| // var to top-level var |
| var varTopLevelVar by ::topVar |
| |
| |
| // val to bound val |
| val valBoundVal by this::stringVal |
| |
| // val to bound var |
| val valBoundVar by data::intVar |
| |
| // var to bound var |
| var varBoundVar by ::intVar |
| |
| |
| // val to extension val |
| val valExtVal by Data::formattedVal |
| |
| // val to extension var |
| val valExtVar by Data::displacedVar |
| |
| // var to extension var |
| var varExtVar by Data::displacedVar |
| } |
| |
| |
| // extension properties |
| // val to bound val |
| @ThreadLocal |
| val Data.extValBoundVal by data::stringVal |
| // val to bound var |
| @ThreadLocal |
| val Data.extValBoundVar by data::intVar |
| // var to bound var |
| @ThreadLocal |
| var Data.extVarBoundVar by data::intVar |
| |
| // val to top-level val |
| @ThreadLocal |
| val Data.extValTopLevelVal by ::topVal |
| // val to top-level var |
| @ThreadLocal |
| val Data.extValTopLevelVar by ::topVar |
| // var to top-level var |
| @ThreadLocal |
| var Data.extVarTopLevelVar by ::topVar |
| |
| // val to member val |
| @ThreadLocal |
| val Data.extValMemberVal by Data::stringVal |
| // val to member var |
| @ThreadLocal |
| val Data.extValMemberVar by Data::intVar |
| // var to member var |
| @ThreadLocal |
| var Data.extVarMemberVar by Data::intVar |
| |
| // val to extension val |
| @ThreadLocal |
| val Data.extValExtVal by Data::formattedVal |
| // val to extension var |
| @ThreadLocal |
| val Data.extValExtVar by Data::displacedVar |
| // var to extension var |
| @ThreadLocal |
| var Data.extVarExtVar by Data::displacedVar |
| |
| |
| // covariance |
| @ThreadLocal |
| val covariantVal: Number by ::topVal |
| @ThreadLocal |
| val Data.extCovariantVal: CharSequence by Data::builderVar |
| |
| |
| @Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE") |
| class PropertyReferenceTest { |
| |
| private fun <V> checkDelegate0(delegated: KProperty0<@NoInfer V>, source: KProperty0<V>) { |
| assertEquals(delegated.get(), source.get()) |
| } |
| |
| private fun <V> checkDelegate1(delegated: KProperty0<@NoInfer V>, source: KMutableProperty0<V>, newValue: @NoInfer V) { |
| assertEquals(delegated.get(), source.get()) |
| source.set(newValue) |
| assertEquals(newValue, source.get()) |
| assertEquals(newValue, delegated.get()) |
| } |
| |
| private fun <V> checkDelegate2(delegated: KMutableProperty0<@NoInfer V>, source: KMutableProperty0<V>, newValue1: @NoInfer V, newValue2: @NoInfer V) { |
| assertEquals(delegated.get(), source.get()) |
| source.set(newValue1) |
| assertEquals(newValue1, source.get()) |
| assertEquals(newValue1, delegated.get()) |
| |
| delegated.set(newValue2) |
| assertEquals(newValue2, source.get()) |
| assertEquals(newValue2, delegated.get()) |
| } |
| |
| private fun int(): Int = Random.nextInt() |
| private fun ulong(): ULong = Random.nextULong() |
| |
| |
| @Test |
| fun topLevelProperties() { |
| checkDelegate0(::tlValBoundVal, data::stringVal) |
| checkDelegate1(::tlValBoundVar, data::intVar, int()) |
| checkDelegate2(::tlVarBoundVar, data::intVar, int(), int()) |
| |
| checkDelegate0(::tlValTopLevelVal, ::topVal) |
| checkDelegate1(::tlValTopLevelVar, ::topVar, ulong()) |
| checkDelegate2(::tlVarTopLevelVar, ::topVar, ulong(), ulong()) |
| } |
| |
| @Test |
| fun memberProperties() { |
| val local = DataExt() |
| checkDelegate0(local::valBoundVal, local::stringVal) |
| checkDelegate1(local::valBoundVar, data::intVar, int()) |
| checkDelegate2(local::varBoundVar, local::intVar, int(), int()) |
| |
| checkDelegate0(local::valTopLevelVal, ::topVal) |
| checkDelegate1(local::valTopLevelVar, ::topVar, ulong()) |
| checkDelegate2(local::varTopLevelVar, ::topVar, ulong(), ulong()) |
| |
| checkDelegate0(local::valExtVal, local::formattedVal) |
| checkDelegate1(local::valExtVar, local::displacedVar, int()) |
| checkDelegate2(local::varExtVar, local::displacedVar, int(), int()) |
| } |
| |
| @Test |
| fun extensionProperties() { |
| val local = Data("ext", Int.MAX_VALUE) |
| |
| checkDelegate0(local::extValBoundVal, data::stringVal) |
| checkDelegate1(local::extValBoundVar, data::intVar, int()) |
| checkDelegate2(local::extVarBoundVar, data::intVar, int(), int()) |
| |
| checkDelegate0(local::extValMemberVal, local::stringVal) |
| checkDelegate1(local::extValMemberVar, local::intVar, int()) |
| checkDelegate2(local::extVarMemberVar, local::intVar, int(), int()) |
| |
| checkDelegate0(local::extValTopLevelVal, ::topVal) |
| checkDelegate1(local::extValTopLevelVar, ::topVar, ulong()) |
| checkDelegate2(local::extVarTopLevelVar, ::topVar, ulong(), ulong()) |
| |
| checkDelegate0(local::extValExtVal, local::formattedVal) |
| checkDelegate1(local::extValExtVar, local::displacedVar, int()) |
| checkDelegate2(local::extVarExtVar, local::displacedVar, int(), int()) |
| } |
| |
| @Test |
| fun covariantProperties() { |
| checkDelegate0<Number>(::covariantVal, ::topVal) |
| checkDelegate0<CharSequence>(data::extCovariantVal, data::builderVar) |
| } |
| |
| } |