[LL API] Fix smart-cast collection for special 'FirElement's

'DFANode' is not created for certain elements, such as types or
references. Before the change, only the target element itself was
queried for DFA, making the 'ContextCollector' return an empty map of
smart casts.

^KTIJ-26973 Fixed
This commit is contained in:
Yan Zhulanow
2023-09-09 02:04:48 +09:00
committed by Space Team
parent 6c1711c52a
commit 4690a430f4
9 changed files with 251 additions and 15 deletions
@@ -25,6 +25,10 @@ Tower Data Context:
FirValueParameterSymbol it: R|kotlin/String|
Element 10
Scope: FirLocalScope
Smart Casts:
FirValueParameterSymbol param: R|kotlin/String?|
Types:
kotlin/Any
FILE: [ResolvedTo(IMPORTS)] KT-61728.kt
public final [ResolvedTo(BODY_RESOLVE)] fun foo([ResolvedTo(BODY_RESOLVE)] param: R|kotlin/String?|): R|kotlin/String?| {
@@ -0,0 +1,17 @@
fun test(a: Any) {
if (a !is Foo) {
return
}
var result: Int = 0
<expr>loop@</expr> while (true) {
if (!a.process()) {
break@loop
}
}
}
interface Foo {
fun process(): Boolean
}
@@ -0,0 +1,52 @@
Tower Data Context:
Element 0
Scope: FirDefaultStarImportingScope
Element 1
Scope: FirDefaultSimpleImportingScope
Element 2
Scope: FirExplicitStarImportingScope
Element 3
Scope: FirDefaultSimpleImportingScope
Element 4
Scope: FirDefaultSimpleImportingScope
Element 5
Scope: FirPackageMemberScope
Element 6
Scope: FirExplicitSimpleImportingScope
Element 7
Scope: FirLocalScope
Properties:
FirValueParameterSymbol a: R|kotlin/Any|
Element 8
Scope: FirLocalScope
Properties:
FirPropertySymbol lvar result: R|kotlin/Int|
Smart Casts:
FirValueParameterSymbol a: R|kotlin/Any|
Types:
Foo
kotlin/Any
FILE: [ResolvedTo(IMPORTS)] onLabel.kt
public final [ResolvedTo(BODY_RESOLVE)] fun test([ResolvedTo(BODY_RESOLVE)] a: R|kotlin/Any|): R|kotlin/Unit| {
when () {
(R|<local>/a| !is R|Foo|) -> {
^test Unit
}
}
[ResolvedTo(BODY_RESOLVE)] lvar result: R|kotlin/Int| = Int(0)
loop@while(Boolean(true)) {
when () {
R|<local>/a|.R|/Foo.process|().R|kotlin/Boolean.not|() -> {
break@@@[Boolean(true)]
}
}
}
}
public abstract [ResolvedTo(STATUS)] interface Foo : R|kotlin/Any| {
public abstract [ResolvedTo(CONTRACTS)] fun process(): R|kotlin/Boolean|
}
@@ -0,0 +1,13 @@
fun test(a: Any) {
if (a !is Foo) {
return
}
<expr>check</expr>(a.process())
}
fun check(condition: Boolean) {}
interface Foo {
fun process(): Boolean
}
@@ -0,0 +1,43 @@
Tower Data Context:
Element 0
Scope: FirDefaultStarImportingScope
Element 1
Scope: FirDefaultSimpleImportingScope
Element 2
Scope: FirExplicitStarImportingScope
Element 3
Scope: FirDefaultSimpleImportingScope
Element 4
Scope: FirDefaultSimpleImportingScope
Element 5
Scope: FirPackageMemberScope
Element 6
Scope: FirExplicitSimpleImportingScope
Element 7
Scope: FirLocalScope
Properties:
FirValueParameterSymbol a: R|kotlin/Any|
Element 8
Scope: FirLocalScope
Smart Casts:
FirValueParameterSymbol a: R|kotlin/Any|
Types:
Foo
kotlin/Any
FILE: [ResolvedTo(IMPORTS)] onReference.kt
public final [ResolvedTo(BODY_RESOLVE)] fun test([ResolvedTo(BODY_RESOLVE)] a: R|kotlin/Any|): R|kotlin/Unit| {
when () {
(R|<local>/a| !is R|Foo|) -> {
^test Unit
}
}
R|/check|(R|<local>/a|.R|/Foo.process|())
}
public final [ResolvedTo(CONTRACTS)] fun check([ResolvedTo(CONTRACTS)] condition: R|kotlin/Boolean|): R|kotlin/Unit| {
}
public abstract [ResolvedTo(STATUS)] interface Foo : R|kotlin/Any| {
public abstract [ResolvedTo(CONTRACTS)] fun process(): R|kotlin/Boolean|
}
@@ -0,0 +1,13 @@
fun test(a: Any) {
if (a !is Foo) {
return
}
call<List<<expr>Int</expr>>>()
}
inline fun <reified T : Any> call() {}
interface Foo {
fun process(): Boolean
}
@@ -0,0 +1,43 @@
Tower Data Context:
Element 0
Scope: FirDefaultStarImportingScope
Element 1
Scope: FirDefaultSimpleImportingScope
Element 2
Scope: FirExplicitStarImportingScope
Element 3
Scope: FirDefaultSimpleImportingScope
Element 4
Scope: FirDefaultSimpleImportingScope
Element 5
Scope: FirPackageMemberScope
Element 6
Scope: FirExplicitSimpleImportingScope
Element 7
Scope: FirLocalScope
Properties:
FirValueParameterSymbol a: R|kotlin/Any|
Element 8
Scope: FirLocalScope
Smart Casts:
FirValueParameterSymbol a: R|kotlin/Any|
Types:
Foo
kotlin/Any
FILE: [ResolvedTo(IMPORTS)] onType.kt
public final [ResolvedTo(BODY_RESOLVE)] fun test([ResolvedTo(BODY_RESOLVE)] a: R|kotlin/Any|): R|kotlin/Unit| {
when () {
(R|<local>/a| !is R|Foo|) -> {
^test Unit
}
}
R|/call|<R|kotlin/collections/List<kotlin/Int>|>()
}
public final inline [ResolvedTo(CONTRACTS)] fun <reified [ResolvedTo(CONTRACTS)] T : R|kotlin/Any|> call(): R|kotlin/Unit| {
}
public? final? [ResolvedTo(RAW_FIR)] interface Foo : R|kotlin/Any| {
public? final? [ResolvedTo(RAW_FIR)] fun process(): Boolean
}