Do not offer to convert to infix call when calling non-infix function
This commit is contained in:
@@ -17,8 +17,11 @@
|
||||
package org.jetbrains.kotlin.idea.intentions
|
||||
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
||||
|
||||
public class ToInfixCallIntention : JetSelfTargetingIntention<JetCallExpression>(javaClass(), "Replace with infix function call") {
|
||||
override fun isApplicableTo(element: JetCallExpression, caretOffset: Int): Boolean {
|
||||
@@ -33,9 +36,13 @@ public class ToInfixCallIntention : JetSelfTargetingIntention<JetCallExpression>
|
||||
if (argument.isNamed()) return false
|
||||
if (argument.getArgumentExpression() == null) return false
|
||||
|
||||
val bindingContext = element.analyze(BodyResolveMode.PARTIAL)
|
||||
val resolvedCall = element.getResolvedCall(bindingContext) ?: return false
|
||||
val function = resolvedCall.resultingDescriptor as? FunctionDescriptor ?: return false
|
||||
if (!function.isInfix) return false
|
||||
|
||||
// check that receiver has type to filter out calls with package/java class qualifier
|
||||
val receiver = dotQualified.getReceiverExpression()
|
||||
if (element.analyze().getType(receiver) == null) return false
|
||||
if (bindingContext.getType(dotQualified.receiverExpression) == null) return false
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
fun foo(x: Int) {
|
||||
interface X {
|
||||
infix fun compareTo(p: Int): Int
|
||||
}
|
||||
|
||||
fun foo(x: X) {
|
||||
x.<caret>compareTo(1 + 2)
|
||||
}
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
fun foo(x: Int) {
|
||||
interface X {
|
||||
infix fun compareTo(p: Int): Int
|
||||
}
|
||||
|
||||
fun foo(x: X) {
|
||||
x compareTo 1 + 2
|
||||
}
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
fun foo(x: Int) {
|
||||
x.tim<caret>es(1)
|
||||
interface X {
|
||||
infix fun infix(p: Int): X
|
||||
}
|
||||
|
||||
fun foo(x: X) {
|
||||
x.in<caret>fix(1)
|
||||
}
|
||||
@@ -1,3 +1,7 @@
|
||||
fun foo(x: Int) {
|
||||
x times 1
|
||||
interface X {
|
||||
infix fun infix(p: Int): X
|
||||
}
|
||||
|
||||
fun foo(x: X) {
|
||||
x infix 1
|
||||
}
|
||||
@@ -1,4 +1,8 @@
|
||||
// IS_APPLICABLE: false
|
||||
fun foo(num: Int) {
|
||||
n<caret>um.times(1)
|
||||
interface X {
|
||||
infix fun infix(p: Int): X
|
||||
}
|
||||
|
||||
fun foo(num: X) {
|
||||
n<caret>um.infix(1)
|
||||
}
|
||||
@@ -1,3 +1,7 @@
|
||||
fun foo(x: Int) {
|
||||
interface X {
|
||||
infix fun times(p: Int): Int
|
||||
}
|
||||
|
||||
fun foo(x: X) {
|
||||
(x.<caret>times(1)).div(2)
|
||||
}
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
fun foo(x: Int) {
|
||||
interface X {
|
||||
infix fun times(p: Int): Int
|
||||
}
|
||||
|
||||
fun foo(x: X) {
|
||||
(x times 1).div(2)
|
||||
}
|
||||
|
||||
+5
-1
@@ -1,3 +1,7 @@
|
||||
fun foo(x: Int) {
|
||||
interface X {
|
||||
infix fun plus(p: Int): Int
|
||||
}
|
||||
|
||||
fun foo(x: X) {
|
||||
x.<caret>plus(1).minus(2)
|
||||
}
|
||||
|
||||
+5
-1
@@ -1,3 +1,7 @@
|
||||
fun foo(x: Int) {
|
||||
interface X {
|
||||
infix fun plus(p: Int): Int
|
||||
}
|
||||
|
||||
fun foo(x: X) {
|
||||
(x plus 1).minus(2)
|
||||
}
|
||||
|
||||
@@ -3,5 +3,5 @@ fun foo(x: Foo) {
|
||||
}
|
||||
|
||||
interface Foo {
|
||||
fun foo(f: (Int) -> Int)
|
||||
infix fun foo(f: (Int) -> Int)
|
||||
}
|
||||
|
||||
@@ -3,5 +3,5 @@ fun foo(x: Foo) {
|
||||
}
|
||||
|
||||
interface Foo {
|
||||
fun foo(f: (Int) -> Int)
|
||||
infix fun foo(f: (Int) -> Int)
|
||||
}
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
// IS_APPLICABLE: false
|
||||
fun String.xxx(p: String): Int = 0
|
||||
|
||||
fun foo(x: String?) {
|
||||
x?.<caret>compareTo("1")
|
||||
x?.<caret>xxx("1")
|
||||
}
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
// IS_APPLICABLE: false
|
||||
fun foo(x: Int) {
|
||||
x.times(<caret>1)
|
||||
fun String.xxx(p: Int): Int = 0
|
||||
|
||||
fun foo(x: String) {
|
||||
x.xxx(<caret>1)
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
// IS_APPLICABLE: false
|
||||
// ERROR: 'infix' modifier is inapplicable on this function
|
||||
interface Foo {
|
||||
fun foo(a: Int, b: Int)
|
||||
infix fun foo(a: Int, b: Int)
|
||||
}
|
||||
|
||||
fun foo(x: Foo) {
|
||||
|
||||
+1
-1
@@ -4,5 +4,5 @@ fun foo(x: Foo) {
|
||||
}
|
||||
|
||||
interface Foo {
|
||||
fun foo(baz: Int = 0, bar: Foo? = null)
|
||||
infix fun foo(baz: Int = 0, bar: Foo? = null)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
// IS_APPLICABLE: false
|
||||
fun Int.xxx(p: Int) = 1
|
||||
|
||||
fun foo(x: Int) {
|
||||
x.<caret>xxx(1)
|
||||
}
|
||||
@@ -1,3 +1,5 @@
|
||||
infix fun String.xxx(p: Int): String = this
|
||||
|
||||
fun foo(x: String?) {
|
||||
x!!.<caret>plus(1)
|
||||
x!!.<caret>xxx(1)
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
infix fun String.xxx(p: Int): String = this
|
||||
|
||||
fun foo(x: String?) {
|
||||
x!! plus 1
|
||||
x!! xxx 1
|
||||
}
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
// IS_APPLICABLE: false
|
||||
// WITH_RUNTIME
|
||||
// ERROR: 'infix' modifier is inapplicable on this function
|
||||
package ppp
|
||||
|
||||
infix fun foo(p: String){}
|
||||
|
||||
fun main() {
|
||||
kotlin.io.<caret>println("")
|
||||
ppp.<caret>foo("")
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
// IS_APPLICABLE: false
|
||||
class Foo {
|
||||
fun foo(x: Int = 0, y: Int = 0) {
|
||||
infix fun foo(x: Int = 0, y: Int = 0) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+3
-1
@@ -1,8 +1,10 @@
|
||||
// IS_APPLICABLE: false
|
||||
// ERROR: 'infix' modifier is inapplicable on this function
|
||||
|
||||
fun foo(x: Foo) {
|
||||
x.<caret>foo(1) { it * 2 }
|
||||
}
|
||||
|
||||
interface Foo {
|
||||
fun foo(a: Int, f: (Int) -> Int)
|
||||
infix fun foo(a: Int, f: (Int) -> Int)
|
||||
}
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
fun foo(x: Int) {
|
||||
interface X {
|
||||
infix fun times(p: Int): Int
|
||||
}
|
||||
|
||||
fun foo(x: X) {
|
||||
x.<caret>times(1)
|
||||
}
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
fun foo(x: Int) {
|
||||
interface X {
|
||||
infix fun times(p: Int): Int
|
||||
}
|
||||
|
||||
fun foo(x: X) {
|
||||
x times 1
|
||||
}
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
// WITH_RUNTIME
|
||||
// IS_APPLICABLE: false
|
||||
// ERROR: 'infix' modifier is inapplicable on this function
|
||||
|
||||
package demo
|
||||
|
||||
fun foo(str: String) = kotlin.io.println(str)
|
||||
infix fun foo(str: String) = kotlin.io.println(str)
|
||||
|
||||
fun main() {
|
||||
<caret>demo.foo("")
|
||||
|
||||
+4
-1
@@ -1,4 +1,7 @@
|
||||
// IS_APPLICABLE: false
|
||||
// ERROR: No value passed for parameter p
|
||||
infix fun Int.xxx(p: Int) = 1
|
||||
|
||||
fun foo(x: Int) {
|
||||
x.<caret>toString()
|
||||
x.<caret>xxx()
|
||||
}
|
||||
|
||||
Vendored
-1
@@ -1,6 +1,5 @@
|
||||
// "Create class 'Foo'" "false"
|
||||
// ACTION: Create extension function 'Foo'
|
||||
// ACTION: Replace with infix function call
|
||||
// ERROR: Unresolved reference: Foo
|
||||
|
||||
fun test() {
|
||||
|
||||
-1
@@ -1,6 +1,5 @@
|
||||
// "Create member function 'foo'" "false"
|
||||
// ACTION: Convert to expression body
|
||||
// ACTION: Replace with infix function call
|
||||
// ERROR: Unresolved reference: x
|
||||
|
||||
class A<T>(val n: T) {
|
||||
|
||||
-1
@@ -1,7 +1,6 @@
|
||||
// "Create property 'foo'" "false"
|
||||
// ACTION: Create extension function 'bar'
|
||||
// ACTION: Create member function 'bar'
|
||||
// ACTION: Replace with infix function call
|
||||
// ERROR: Unresolved reference: bar
|
||||
// ERROR: Unresolved reference: foo
|
||||
|
||||
|
||||
@@ -7707,6 +7707,12 @@ public class IntentionTestGenerated extends AbstractIntentionTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("notInfix.kt")
|
||||
public void testNotInfix() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/intentions/toInfixCall/notInfix.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("nullAssertedReceiver.kt")
|
||||
public void testNullAssertedReceiver() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/intentions/toInfixCall/nullAssertedReceiver.kt");
|
||||
|
||||
Reference in New Issue
Block a user