FIR/FIR IDE: Use entire FirVariableAssignment when reporting UNSAFE_CALL

(e.g., `nullable.a = b`), and use positioning strategies to locate the
dot in the LHS expression.

Without it, only the callee reference is reported on, which makes the
highlighting of the error and application of quickfixes incorrect in the
IDE.

Also fixed issue with annotated and/or labeled expressions on LHS of
assignment (e.g., `(@Ann label@ i) = 34`).
This commit is contained in:
Mark Punzalan
2021-05-13 09:24:29 +00:00
committed by Ilya Kirillov
parent 1d9247ae0f
commit d2b8204fdc
28 changed files with 342 additions and 92 deletions
+26 -7
View File
@@ -51,18 +51,25 @@ fun cannotBe() {
<!VARIABLE_EXPECTED!>5<!> = 34
}
@Retention(AnnotationRetention.SOURCE)
@Target(AnnotationTarget.EXPRESSION)
annotation class Ann
fun canBe(i0: Int, j: Int) {
var i = i0
(<!VARIABLE_EXPECTED!>label@ i<!>) = 34
(label@ i) = 34
(<!VARIABLE_EXPECTED!>label@ j<!>) = 34 //repeat for j
(label@ j) = 34 //repeat for j
val a = A()
(<!VARIABLE_EXPECTED!>l@ a.a<!>) = 3894
(l@ a.a) = 3894
@Ann
l@ (i) = 123
}
fun canBe2(j: Int) {
(<!VARIABLE_EXPECTED!>label@ j<!>) = 34
(label@ j) = 34
}
class A() {
@@ -78,10 +85,13 @@ class Test() {
(f@ <!VARIABLE_EXPECTED!>getInt()<!>) += 343
<!VARIABLE_EXPECTED!>1<!>++
(r@ <!VARIABLE_EXPECTED!>1<!>)++
(r@ <!VARIABLE_EXPECTED!>1<!>)--
<!VARIABLE_EXPECTED!>getInt()<!>++
(m@ <!VARIABLE_EXPECTED!>getInt()<!>)++
(m@ <!VARIABLE_EXPECTED!>getInt()<!>)--
++<!VARIABLE_EXPECTED!>2<!>
--(r@ <!VARIABLE_EXPECTED!>2<!>)
this<!UNRESOLVED_REFERENCE!>++<!>
@@ -89,6 +99,9 @@ class Test() {
s += "ss"
s += this
s += (a@ 2)
@Ann
l@ (<!VARIABLE_EXPECTED!>1<!>) = 123
}
fun testIncompleteSyntax() {
@@ -106,8 +119,11 @@ class Test() {
<!VAL_REASSIGNMENT!>b<!> += 34
a++
(l@ a)++
(@Ann l@ a)--
(a)++
--a
++(@Ann l@ a)
--(a)
}
fun testVariables1() {
@@ -122,6 +138,9 @@ class Test() {
a[3] = 4
a[4]++
a[6] += 43
@Ann
a[7] = 7
(@Ann l@ (a))[8] = 8
ab.getArray()[54] = 23
ab.getArray()[54]++
+22 -3
View File
@@ -51,6 +51,10 @@ fun cannotBe() {
<!VARIABLE_EXPECTED!>5<!> = 34
}
@Retention(AnnotationRetention.SOURCE)
@Target(AnnotationTarget.EXPRESSION)
annotation class Ann
fun canBe(i0: Int, j: Int) {
var <!ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE!>i<!> = i0
(label@ i) = 34
@@ -59,6 +63,9 @@ fun canBe(i0: Int, j: Int) {
val a = A()
(l@ a.a) = 3894
@Ann
l@ (i) = 123
}
fun canBe2(j: Int) {
@@ -78,10 +85,13 @@ class Test() {
(f@ <!VARIABLE_EXPECTED!>getInt()<!>) += 343
<!VARIABLE_EXPECTED!>1<!>++
(<!REDUNDANT_LABEL_WARNING!>r@<!> <!VARIABLE_EXPECTED!>1<!>)++
(<!REDUNDANT_LABEL_WARNING!>r@<!> <!VARIABLE_EXPECTED!>1<!>)--
<!VARIABLE_EXPECTED!>getInt()<!>++
(<!REDUNDANT_LABEL_WARNING!>m@<!> <!VARIABLE_EXPECTED!>getInt()<!>)++
(<!REDUNDANT_LABEL_WARNING!>m@<!> <!VARIABLE_EXPECTED!>getInt()<!>)--
++<!VARIABLE_EXPECTED!>2<!>
--(<!REDUNDANT_LABEL_WARNING!>r@<!> <!VARIABLE_EXPECTED!>2<!>)
this<!UNRESOLVED_REFERENCE!>++<!>
@@ -89,6 +99,9 @@ class Test() {
s += "ss"
s += this
s += (<!REDUNDANT_LABEL_WARNING!>a@<!> 2)
@Ann
l@ (<!VARIABLE_EXPECTED!>1<!>) = 123
}
fun testIncompleteSyntax() {
@@ -106,8 +119,11 @@ class Test() {
<!VAL_REASSIGNMENT!>b<!> += 34
a++
(<!REDUNDANT_LABEL_WARNING!>l@<!> a)++
(@Ann <!REDUNDANT_LABEL_WARNING!>l@<!> a)--
(a)++
--a
++(@Ann <!REDUNDANT_LABEL_WARNING!>l@<!> a)
--(a)
}
fun testVariables1() {
@@ -122,6 +138,9 @@ class Test() {
a[3] = 4
a[4]++
a[6] += 43
@Ann
a[7] = 7
(@Ann <!REDUNDANT_LABEL_WARNING!>l@<!> (a))[8] = 8
ab.getArray()[54] = 23
ab.getArray()[54]++
@@ -24,6 +24,13 @@ package lvalue_assignment {
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
@kotlin.annotation.Retention(value = AnnotationRetention.SOURCE) @kotlin.annotation.Target(allowedTargets = {AnnotationTarget.EXPRESSION}) public final annotation class Ann : kotlin.Annotation {
public constructor Ann()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public open class B {
public constructor B()
public final var b: kotlin.Int
@@ -47,7 +47,7 @@ class R {
fun test() {
val o = object {
fun run() {
<!UNRESOLVED_REFERENCE!>p<!>.<!UNRESOLVED_REFERENCE!>x<!> = 43
<!UNRESOLVED_REFERENCE!>p<!>.x = 43
}
}
}
@@ -1,6 +1,7 @@
// !DIAGNOSTICS: -DEBUG_INFO_SMARTCAST
class Foo {
fun foo(a: Foo): Foo = a
var f: Foo? = null
}
fun main() {
@@ -27,4 +28,14 @@ fun main() {
val z: Foo? = null
z!!.foo(z<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!>)
val w: Foo? = null
w<!UNSAFE_CALL!>.<!>f = z
(w<!UNSAFE_CALL!>.<!>f) = z
(label@ w<!UNSAFE_CALL!>.<!>f) = z
w!!.f = z
w.f = z
w<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!>.f = z
w.f<!UNSAFE_CALL!>.<!>f = z
w.f!!.f = z
}
@@ -1,6 +1,7 @@
// !DIAGNOSTICS: -DEBUG_INFO_SMARTCAST
class Foo {
fun foo(a: Foo): Foo = a
var f: Foo? = null
}
fun main() {
@@ -27,4 +28,14 @@ fun main() {
val z: Foo? = null
z!!.foo(z<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!>)
val w: Foo? = null
w<!UNSAFE_CALL!>.<!>f = z
(w<!UNSAFE_CALL!>.<!>f) = z
(label@ w<!UNSAFE_CALL!>.<!>f) = z
w!!.f = z
w.f = z
w<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!>.f = z
<!SMARTCAST_IMPOSSIBLE!>w.f<!>.f = z
w.f!!.f = z
}
@@ -4,6 +4,7 @@ public fun main(): kotlin.Unit
public final class Foo {
public constructor Foo()
public final var f: Foo?
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public final fun foo(/*0*/ a: Foo): Foo
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int