KT-60341 [Analysis API] Provide a type for a FirNameReference only when it refers to an actual property/variable

We cannot always return null, because in such case some expressions
would become not fully explorable from the types perspective (see
the documentation on the `getCorrespondingTypeIfPossible`)

`FirNamedReference` might appear when resolving method references (like
`foo::bar`), but also when IJ Platform tries to resolve other parts of
the Kotlin PSI, notably a `KtNameReferenceExpression` in a
function call (`bar` in `foo.bar(baz)` expression).

N.B. FE10 implementation does not support returning `null` as a type -
currently it always returns `Unit` type in case it cannot figure out
the actual type. This issue should probably be tackled together with
KT-60166, so that both implementations are more or less aligned

^KT-60341 Fixed
^KT-59077 Fixed
^KTIJ-25745 Fixed
This commit is contained in:
Roman Golyshev
2023-06-03 00:21:17 +02:00
committed by teamcity
parent 19a60d6b85
commit b8052761db
66 changed files with 870 additions and 30 deletions
@@ -0,0 +1,5 @@
fun test() {
val foo = 10
<expr>foo</expr> = 20
}
@@ -0,0 +1,2 @@
expression: foo
type: kotlin.Int
@@ -0,0 +1,6 @@
class Foo {
var bar: Int = 0
}
fun test(foo: Foo) {
foo.<expr>bar</expr> = 20
}
@@ -0,0 +1,2 @@
expression: bar
type: kotlin.Int
@@ -0,0 +1,2 @@
expression: myFun
type: kotlin.Unit
@@ -0,0 +1,5 @@
fun myFun(i: Int): String = i.toString()
fun test() {
::<expr>myFun</expr>
}
@@ -0,0 +1,2 @@
expression: myFun
type: null
@@ -0,0 +1,2 @@
expression: functionWithGeneric
type: kotlin.Unit
@@ -0,0 +1,10 @@
interface WithGeneric<S> {
fun <T : S> functionWithGeneric(t: T): T
fun prop(): S
}
fun take(w: WithGeneric<*>) {
// this is an error on purpose!
w.<expr>functionWithGeneric</expr>
}
@@ -0,0 +1,2 @@
expression: functionWithGeneric
type: ERROR(Cannot infer argument for type parameter T)
@@ -0,0 +1,2 @@
expression: foo
type: kotlin.Unit
@@ -0,0 +1,5 @@
fun String.foo(i: Int): String = ""
fun take(s: String) {
s.<expr>foo</expr>(10)
}
@@ -0,0 +1,2 @@
expression: foo
type: null
@@ -0,0 +1,5 @@
fun String.foo(i: Int): String = ""
fun take(s: String) {
s.<expr>foo</expr>
}
@@ -0,0 +1,2 @@
expression: foo
type: kotlin.String
@@ -0,0 +1,5 @@
fun String.foo(i: Int): String = ""
fun take(s: String?) {
s?.<expr>foo</expr>(10)
}
@@ -0,0 +1,3 @@
fun take(lambda: (Int) -> String) {
<expr>lambda</expr>(10)
}
@@ -0,0 +1,2 @@
expression: lambda
type: (kotlin.Int) -> kotlin.String
@@ -0,0 +1,3 @@
fun take(lambda: (Int) -> String) {
(<expr>lambda</expr>)(10)
}
@@ -0,0 +1,2 @@
expression: lambda
type: (kotlin.Int) -> kotlin.String
@@ -0,0 +1,3 @@
fun take(lambda: (Int) -> String) {
<expr>(lambda)</expr>(10)
}
@@ -0,0 +1,2 @@
expression: (lambda)
type: (kotlin.Int) -> kotlin.String
@@ -0,0 +1,3 @@
fun take(lambda: String.(Int) -> String) {
"hello".<expr>lambda</expr>(10)
}
@@ -0,0 +1,2 @@
expression: lambda
type: kotlin.String.(kotlin.Int) -> kotlin.String
@@ -0,0 +1,7 @@
class Foo {
inner class Bar
}
fun foo(foo: Foo) {
foo.<expr>Bar</expr>()
}
@@ -0,0 +1,7 @@
class Foo {
inner class Bar
}
fun foo(foo: Foo) {
foo.<expr>Bar</expr>
}
@@ -0,0 +1,7 @@
object Foo {
operator fun invoke(i: Int): String {}
}
fun take() {
<expr>Foo</expr>(10)
}
@@ -0,0 +1,9 @@
class Foo {
companion object {
operator fun invoke(i: Int): String {}
}
}
fun take() {
<expr>Foo</expr>(10)
}
@@ -0,0 +1,2 @@
expression: Foo
type: Foo.Companion
@@ -0,0 +1,7 @@
class Foo {
class Bar
}
fun foo() {
Foo.<expr>Bar</expr>()
}
@@ -0,0 +1,7 @@
class Foo {
class Bar
}
fun foo() {
Foo.<expr>Bar</expr>
}
@@ -0,0 +1,2 @@
expression: Bar
type: kotlin.Unit
@@ -0,0 +1,7 @@
class Foo {
object Bar
}
fun foo() {
Foo.<expr>Bar</expr>
}
@@ -0,0 +1,2 @@
expression: Bar
type: Foo.Bar
@@ -0,0 +1,9 @@
class Foo {
object Bar
}
operator fun Bar.invoke() {}
fun foo() {
Foo.<expr>Bar</expr>()
}
@@ -0,0 +1,5 @@
val String.foo: String get() = ""
fun take(s: String) {
s.<expr>foo</expr>
}
@@ -0,0 +1,2 @@
expression: foo
type: kotlin.String
@@ -0,0 +1,11 @@
interface WithGeneric<T>
interface Foo<T> {
val foo: WithGeneric<T>
}
val <T> Foo<T>.fooExt: WithGeneric<T> get() = foo
fun take(s: Foo<String>) {
s.<expr>fooExt</expr>
}
@@ -0,0 +1,2 @@
expression: fooExt
type: WithGeneric<kotlin.String>
@@ -0,0 +1,5 @@
val String.foo: String get() = ""
fun take(s: String?) {
s?.<expr>foo</expr>
}
@@ -0,0 +1,2 @@
expression: foo
type: kotlin.String?
@@ -0,0 +1,7 @@
interface BodySpec<B, S : BodySpec<B, S>> {
fun <T : S> isEqualTo(expected: B) : T
}
fun test(b: BodySpec<String, *>) {
b.<expr>isEqualTo</expr>("")
}
@@ -0,0 +1,10 @@
interface WithGeneric<S> {
fun <T : S> functionWithGeneric(t: T): T
fun prop(): S
}
fun take(w: WithGeneric<*>) {
// this is an error on purpose!
w.<expr>functionWithGeneric</expr>
}
@@ -0,0 +1,2 @@
KtType: T
PsiType: null
@@ -1,2 +1 @@
KtType: T & kotlin.Any
PsiType: PsiType:T
null