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:
committed by
Ilya Kirillov
parent
1d9247ae0f
commit
d2b8204fdc
+26
-7
@@ -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
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
Vendored
+11
@@ -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
|
||||
}
|
||||
|
||||
Vendored
+11
@@ -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
|
||||
}
|
||||
|
||||
Vendored
+1
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user