PHondogo
10/16/2023, 11:09 AMclass Context {
val v: Int = 1
}
class X {
val v: Int = 0
fun Context.test() {
println(v) // such cases are difficult for code readers. Suggest to issue warning if not explicitly specified this@... for them
}
}
dmitriy.novozhilov
10/16/2023, 11:20 AMx
vs member `x`" or "member x
vs top-level `x`"? Should they be reported too?X.v
will win
class Context {
val v: Int = 1 // (1)
}
class X {
val v: Int = 2 // (2)
fun Context.test_2() {
v // resolved to (1)
}
context(Context)
fun test_2() {
v // resolved to (2)
}
}
In presence of context receivers tower looks like this (simplified):
• scope of function extension receiver
• scope of function dispatch receiver (this
of parent class)
• scopes of context receiversPHondogo
10/16/2023, 11:36 AMLoney Chou
10/17/2023, 5:48 AMbuildJsonObject {
literal("a", "ObjectBuilder")
array("b") {
literal("ArrayBuilder")
}
}
Real world example speaks more.PHondogo
10/17/2023, 5:51 AMLoney Chou
10/17/2023, 5:53 AM@DslMarker
annotation is all we need.PHondogo
10/17/2023, 5:54 AMLoney Chou
10/17/2023, 5:54 AMclass Outer {
val a: Int
inner class Inner {
val a: Int
fun foo() {
a // Will you warn?
}
}
}
PHondogo
10/17/2023, 5:54 AMLoney Chou
10/17/2023, 5:57 AMthis
of parent class)
> • scopes of context receivers
I don't think it's a fault to the language. After someone learns how the resolution happens, it's not a problem anymore. It's consistent.PHondogo
10/17/2023, 5:59 AMLoney Chou
10/17/2023, 6:13 AMPHondogo
10/17/2023, 6:18 AMclass T{
val x: Int
fun test Context.() {
println(x) // while reading code you have to go to Context declaration to check if it has or not x member
}
}
Loney Chou
10/17/2023, 6:21 AMPHondogo
10/17/2023, 6:25 AMLoney Chou
10/17/2023, 6:26 AMPHondogo
10/17/2023, 6:30 AMLoney Chou
10/17/2023, 6:41 AMPHondogo
10/17/2023, 6:43 AM