FIR IDE: Enable AddExclExclCallFix for UNSAFE_CALL,

UNSAFE_OPERATOR_CALL, UNSAFE_INFIX_CALL, ITERATOR_ON_NULLABLE,
ARGUMENT_TYPE_MISMATCH, RETURN_TYPE_MISMATCH.

TODO: Don't offer fix when target is known to be null (from data flow
analysis).
This commit is contained in:
Mark Punzalan
2021-04-25 21:39:25 +00:00
committed by Ilya Kirillov
parent 71a8d9c0bb
commit db82797f58
53 changed files with 311 additions and 42 deletions
@@ -5,4 +5,6 @@ class Foo {
fun test(foo: Foo?) {
val f = foo::f<caret>
}
}
// TODO: Enable when FIR reports UNSAFE_CALL for function reference on nullable (currently UNRESOLVED_REFERENCE)
/* IGNORE_FIR */
@@ -5,4 +5,6 @@ class Foo {
fun test(foo: Foo?) {
val f = foo!!::f
}
}
// TODO: Enable when FIR reports UNSAFE_CALL for function reference on nullable (currently UNRESOLVED_REFERENCE)
/* IGNORE_FIR */
@@ -9,4 +9,6 @@ class Bar {
fun test(foo: Foo?) {
val f = foo?.bar::f<caret>
}
}
// TODO: Enable when FIR reports UNSAFE_CALL for function reference on nullable (currently UNRESOLVED_REFERENCE)
/* IGNORE_FIR */
@@ -9,4 +9,6 @@ class Bar {
fun test(foo: Foo?) {
val f = foo?.bar!!::f
}
}
// TODO: Enable when FIR reports UNSAFE_CALL for function reference on nullable (currently UNRESOLVED_REFERENCE)
/* IGNORE_FIR */
@@ -5,4 +5,6 @@ class Foo {
fun Foo?.test() {
val f = ::f<caret>
}
}
// TODO: Enable when FIR reports UNSAFE_CALL for function reference on nullable (currently UNRESOLVED_REFERENCE)
/* IGNORE_FIR */
@@ -5,4 +5,6 @@ class Foo {
fun Foo?.test() {
val f = this!!::f
}
}
// TODO: Enable when FIR reports UNSAFE_CALL for function reference on nullable (currently UNRESOLVED_REFERENCE)
/* IGNORE_FIR */
+7
View File
@@ -0,0 +1,7 @@
// "Add non-null asserted (!!) call" "true"
infix fun Int.bar(i: Int) = this
fun foo(i: Int?) {
i <caret>bar 1
}
@@ -0,0 +1,7 @@
// "Add non-null asserted (!!) call" "true"
infix fun Int.bar(i: Int) = this
fun foo(i: Int?) {
i!! bar 1
}
@@ -0,0 +1,5 @@
// "Add non-null asserted (!!) call" "true"
fun foo(i: Int?) {
i <caret>+ 1
}
@@ -0,0 +1,5 @@
// "Add non-null asserted (!!) call" "true"
fun foo(i: Int?) {
i!! + 1
}
@@ -0,0 +1,5 @@
// "Add non-null asserted (!!) call" "true"
fun foo(i: Int?) {
<caret>-i
}
@@ -0,0 +1,5 @@
// "Add non-null asserted (!!) call" "true"
fun foo(i: Int?) {
-i!!
}
@@ -0,0 +1,18 @@
// "Add non-null asserted (!!) call" "false"
// ACTION: Add 'i =' to argument
// ACTION: Change parameter 'i' type of function 'other' to 'Int?'
// ACTION: Create function 'other'
// ACTION: Remove braces from 'if' statement
// ACTION: Surround with null check
// ACTION: Wrap with '?.let { ... }' call
// ERROR: Type mismatch: inferred type is Nothing? but Int was expected
fun test(i: Int?) {
if (i == null) {
other(<caret>i)
}
}
fun other(i: Int) {}
// TODO: Need data flow info from null check
/* IGNORE_FIR */
@@ -3,3 +3,5 @@ fun test() {
val s: String? = null
val z: String = <caret>s
}
// TODO: Enable when FIR reports TYPE_MISMATCH for assignments
/* IGNORE_FIR */
@@ -3,3 +3,5 @@ fun test() {
val s: String? = null
val z: String = s!!
}
// TODO: Enable when FIR reports TYPE_MISMATCH for assignments
/* IGNORE_FIR */
@@ -7,3 +7,5 @@ class C {
fun C.test() {
val z: String = <caret>s
}
// TODO: Enable when FIR reports TYPE_MISMATCH for assignments
/* IGNORE_FIR */
@@ -7,3 +7,5 @@ class C {
fun C.test() {
val z: String = s!!
}
// TODO: Enable when FIR reports TYPE_MISMATCH for assignments
/* IGNORE_FIR */
@@ -0,0 +1,10 @@
// "Add non-null asserted (!!) call" "false"
// ACTION: Add 'i =' to argument
// ACTION: Change parameter 'i' type of function 'other' to 'Int?'
// ACTION: Do not show hints for current method
// ERROR: Null can not be a value of a non-null type Int
fun test() {
other(<caret>null)
}
fun other(i: Int) {}
@@ -1,6 +1,8 @@
// "class org.jetbrains.kotlin.idea.quickfix.AddExclExclCallFix" "false"
// "Add non-null asserted (!!) call" "false"
// ACTION: Change parameter 's' type of function 'other' to 'String?'
// ACTION: Create function 'other'
// ACTION: Convert to also
// ACTION: Convert to apply
// ERROR: Type mismatch: inferred type is String? but Int was expected
fun test() {
val s: String? = ""
@@ -14,4 +14,5 @@ open class MyClass {
}
}
}
// TODO: Enable when FIR reports SMARTCAST_IMPOSSIBLE
/* IGNORE_FIR */
@@ -14,4 +14,5 @@ open class MyClass {
}
}
}
// TODO: Enable when FIR reports SMARTCAST_IMPOSSIBLE
/* IGNORE_FIR */
@@ -7,4 +7,3 @@ class SafeType {
fun safeB(p: SafeType?) {
val v = p <caret>+ 42
}
/* IGNORE_FIR */
@@ -7,4 +7,3 @@ class SafeType {
fun safeB(p: SafeType?) {
val v = p!! + 42
}
/* IGNORE_FIR */
@@ -7,4 +7,3 @@ class SafeType {
fun safeB(p: SafeType?) {
val v = p <caret>op 42
}
/* IGNORE_FIR */
@@ -7,4 +7,3 @@ class SafeType {
fun safeB(p: SafeType?) {
val v = p!! op 42
}
/* IGNORE_FIR */
@@ -3,4 +3,3 @@ fun <T: Collection<Int>?> foo(c: T) {
for (i in <caret>c) { }
}
/* IGNORE_FIR */
@@ -3,4 +3,3 @@ fun <T: Collection<Int>?> foo(c: T) {
for (i in c!!) { }
}
/* IGNORE_FIR */
@@ -4,4 +4,3 @@ fun foo() {
for (i in <caret>test) { }
}
/* IGNORE_FIR */
@@ -4,4 +4,3 @@ fun foo() {
for (i in <caret>test!!) { }
}
/* IGNORE_FIR */
@@ -7,4 +7,3 @@ class SafeType {
fun safeB(p: SafeType?) {
val v = <caret>-p
}
/* IGNORE_FIR */
@@ -7,4 +7,3 @@ class SafeType {
fun safeB(p: SafeType?) {
val v = -p!!
}
/* IGNORE_FIR */
@@ -1,4 +1,4 @@
// "class org.jetbrains.kotlin.idea.quickfix.AddExclExclCallFix" "false"
// "Add non-null asserted (!!) call" "false"
// ACTION: Replace with a 'forEach' function call
// ACTION: Surround with null check
// ERROR: Not nullable value required to call an 'iterator()' method on for-loop range
@@ -7,5 +7,3 @@ fun foo() {
val test: Some? = Some()
for (i in <caret>test) { }
}
/* IGNORE_FIR */
@@ -7,5 +7,3 @@ fun foo() {
val test: Some? = Some()
for (i in test!!) { }
}
/* IGNORE_FIR */
-1
View File
@@ -5,4 +5,3 @@ fun callMe(p: String) {}
fun callIt(p: Any) {
callMe(<caret>p as String?)
}
/* IGNORE_FIR */
-1
View File
@@ -5,4 +5,3 @@ fun callMe(p: String) {}
fun callIt(p: Any) {
callMe(<caret>(p as String?)!!)
}
/* IGNORE_FIR */
-2
View File
@@ -2,5 +2,3 @@
fun foo(a: Int?) {
a<caret>.plus(1)
}
/* IGNORE_FIR */
@@ -2,5 +2,3 @@
fun foo(a: Int?) {
a!!.plus(1)
}
/* IGNORE_FIR */
-2
View File
@@ -2,5 +2,3 @@
fun foo(a: Int?) {
a.<caret>plus(1)
}
/* IGNORE_FIR */
@@ -2,5 +2,3 @@
fun foo(a: Int?) {
a!!.plus(1)
}
/* IGNORE_FIR */
-1
View File
@@ -2,4 +2,3 @@
operator fun Int.get(row: Int, column: Int) = this
fun foo(arg: Int?) = arg<caret>[42, 13]
/* IGNORE_FIR */
@@ -2,4 +2,3 @@
operator fun Int.get(row: Int, column: Int) = this
fun foo(arg: Int?) = arg!![42, 13]
/* IGNORE_FIR */
-1
View File
@@ -2,4 +2,3 @@
operator fun Int.get(row: Int, column: Int) = if (row == column) this else null
fun foo(arg: Int) = arg[42, 13]<caret>.hashCode()
/* IGNORE_FIR */
@@ -2,4 +2,3 @@
operator fun Int.get(row: Int, column: Int) = if (row == column) this else null
fun foo(arg: Int) = arg[42, 13]!!.hashCode()
/* IGNORE_FIR */