ReplaceWithInfixFunctionCallIntention - refactored
This commit is contained in:
@@ -290,10 +290,6 @@ add.name.to.argument.single=Add name to argument\: ''{0}''
|
|||||||
add.name.to.argument.multiple=Add name to argument...
|
add.name.to.argument.multiple=Add name to argument...
|
||||||
add.name.to.argument.action=Add name to argument...
|
add.name.to.argument.action=Add name to argument...
|
||||||
add.name.to.parameter.name.chooser.title=Choose parameter name
|
add.name.to.parameter.name.chooser.title=Choose parameter name
|
||||||
replace.with.infix.function.call.intention=Replace with infix function call
|
|
||||||
replace.with.infix.function.call.intention.family=Replace with Infix Function Call
|
|
||||||
replace.with.infix.function.call.intention.error.resolution.failed=The element cannot be resolved
|
|
||||||
replace.with.infix.function.call.intention.error.package.call=Cannot be applied with a package as the receiver
|
|
||||||
split.if=Split into 2 if's
|
split.if=Split into 2 if's
|
||||||
split.if.family=Split If
|
split.if.family=Split If
|
||||||
replace.with.operator.assign.intention=Replace with an operator-assign expression
|
replace.with.operator.assign.intention=Replace with an operator-assign expression
|
||||||
|
|||||||
+22
-72
@@ -16,92 +16,42 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.idea.intentions
|
package org.jetbrains.kotlin.idea.intentions
|
||||||
|
|
||||||
import org.jetbrains.kotlin.psi.JetCallExpression
|
|
||||||
import com.intellij.openapi.editor.Editor
|
import com.intellij.openapi.editor.Editor
|
||||||
import org.jetbrains.kotlin.psi.JetDotQualifiedExpression
|
|
||||||
import org.jetbrains.kotlin.idea.caches.resolve.analyzeFully
|
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
|
||||||
import org.jetbrains.kotlin.idea.JetBundle
|
|
||||||
import org.jetbrains.kotlin.psi.JetValueArgument
|
|
||||||
import org.jetbrains.kotlin.psi.JetPsiUnparsingUtils
|
|
||||||
import org.jetbrains.kotlin.psi.JetPsiFactory
|
|
||||||
import com.intellij.codeInsight.hint.HintManager
|
|
||||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
|
|
||||||
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
||||||
|
import org.jetbrains.kotlin.psi.JetBinaryExpression
|
||||||
|
import org.jetbrains.kotlin.psi.JetCallExpression
|
||||||
|
import org.jetbrains.kotlin.psi.JetDotQualifiedExpression
|
||||||
|
import org.jetbrains.kotlin.psi.JetPsiFactory
|
||||||
|
|
||||||
public open class ReplaceWithInfixFunctionCallIntention : JetSelfTargetingIntention<JetCallExpression>("replace.with.infix.function.call.intention", javaClass()) {
|
public class ReplaceWithInfixFunctionCallIntention : JetSelfTargetingIntention<JetCallExpression>(javaClass(), "Replace with infix function call") {
|
||||||
override fun isApplicableTo(element: JetCallExpression, caretOffset: Int): Boolean {
|
override fun isApplicableTo(element: JetCallExpression, caretOffset: Int): Boolean {
|
||||||
val calleeExpr = element.getCalleeExpression()
|
val calleeExpr = element.getCalleeExpression() ?: return false
|
||||||
if (calleeExpr == null) return false
|
if (!calleeExpr.getTextRange().containsOffset(caretOffset)) return false
|
||||||
|
|
||||||
val textRange = calleeExpr.getTextRange()
|
val dotQualified = element.getParent() as? JetDotQualifiedExpression ?: return false
|
||||||
if (textRange == null) return false
|
|
||||||
|
|
||||||
if (caretOffset !in textRange) return false
|
if (element.getTypeArgumentList() != null) return false
|
||||||
|
|
||||||
val parent = element.getParent()
|
val argument = element.getValueArguments().singleOrNull() ?: return false
|
||||||
|
if (argument.isNamed()) return false
|
||||||
|
if (argument.getArgumentExpression() == null) return false
|
||||||
|
|
||||||
if (parent is JetDotQualifiedExpression) {
|
val receiver = dotQualified.getReceiverExpression()
|
||||||
val typeArguments = element.getTypeArgumentList()
|
if (element.analyze().getType(receiver) == null) return false
|
||||||
val valueArguments = element.getValueArgumentList()
|
|
||||||
val functionLiteralArguments = element.getFunctionLiteralArguments()
|
|
||||||
val numOfTotalValueArguments = (valueArguments?.getArguments()?.size() ?: 0) + functionLiteralArguments.size()
|
|
||||||
|
|
||||||
if (typeArguments?.getArguments()?.size() ?: 0 == 0 &&
|
return true
|
||||||
numOfTotalValueArguments == 1) {
|
|
||||||
|
|
||||||
if (valueArguments?.getArguments()?.size() == 1 && valueArguments?.getArguments()?.first()?.isNamed() ?: false) {
|
|
||||||
val file = element.getContainingJetFile()
|
|
||||||
val bindingContext = file.analyzeFully()
|
|
||||||
val resolvedCall = element.getResolvedCall(bindingContext)
|
|
||||||
val valueArgumentsMap = resolvedCall?.getValueArguments()
|
|
||||||
val firstArgument = valueArguments?.getArguments()?.first()
|
|
||||||
|
|
||||||
return valueArgumentsMap?.keySet()?.any { it.getName().asString() == firstArgument?.getArgumentName()?.getText() && it.getIndex() == 0 } ?: false
|
|
||||||
} else {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
open fun intentionFailed(editor: Editor, messageID: String) {
|
|
||||||
val message = "Intention failed: ${JetBundle.message("replace.with.infix.function.call.intention.error.$messageID")}"
|
|
||||||
HintManager.getInstance().showErrorHint(editor, message)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun applyTo(element: JetCallExpression, editor: Editor) {
|
override fun applyTo(element: JetCallExpression, editor: Editor) {
|
||||||
val parent = element.getParent() as JetDotQualifiedExpression
|
val dotQualified = element.getParent() as JetDotQualifiedExpression
|
||||||
val receiver = parent.getReceiverExpression()
|
val receiver = dotQualified.getReceiverExpression()
|
||||||
val leftHandText = parent.getReceiverExpression().getText()
|
|
||||||
val rightHandTextStringBuilder = StringBuilder()
|
|
||||||
val operatorText = element.getCalleeExpression()!!.getText()
|
val operatorText = element.getCalleeExpression()!!.getText()
|
||||||
val valueArguments = element.getValueArgumentList()?.getArguments() ?: listOf<JetValueArgument>()
|
|
||||||
val functionLiteralArguments = element.getFunctionLiteralArguments()
|
|
||||||
val bindingContext = parent.analyze()
|
|
||||||
val receiverType = bindingContext.getType(receiver)
|
|
||||||
if (receiverType == null) {
|
|
||||||
if (bindingContext[BindingContext.QUALIFIER, receiver] != null) {
|
|
||||||
intentionFailed(editor, "package.call")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
intentionFailed(editor, "resolution.failed")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
rightHandTextStringBuilder.append(
|
val newCall = JetPsiFactory(element).createExpression("${receiver.getText()} $operatorText x") as JetBinaryExpression
|
||||||
if (valueArguments.size() > 0)
|
val argument = element.getValueArguments().single()
|
||||||
JetPsiUnparsingUtils.parenthesizeIfNeeded(valueArguments.first().getArgumentExpression())
|
newCall.getRight()!!.replace(argument.getArgumentExpression()!!)
|
||||||
else
|
|
||||||
functionLiteralArguments.first().getText()
|
|
||||||
)
|
|
||||||
|
|
||||||
val replacement = JetPsiFactory(element).createExpression("$leftHandText $operatorText ${rightHandTextStringBuilder.toString()}")
|
dotQualified.replace(newCall)
|
||||||
|
|
||||||
parent.replace(replacement)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
org.jetbrains.kotlin.idea.intentions.TestableReplaceWithInfixFunctionCallIntention
|
org.jetbrains.kotlin.idea.intentions.ReplaceWithInfixFunctionCallIntention
|
||||||
|
|||||||
+1
-1
@@ -1,3 +1,3 @@
|
|||||||
fun foo(x: Int) {
|
fun foo(x: Int) {
|
||||||
x compareTo (1 + 2)
|
x compareTo 1 + 2
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +0,0 @@
|
|||||||
fun doSomething<T>(a: T) {}
|
|
||||||
|
|
||||||
class Foo {
|
|
||||||
fun foo(x: Int) {
|
|
||||||
doSomething("lol")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun bar(baz: Foo) {
|
|
||||||
baz.<caret>foo(x = 1)
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
fun doSomething<T>(a: T) {}
|
|
||||||
|
|
||||||
class Foo {
|
|
||||||
fun foo(x: Int) {
|
|
||||||
doSomething("lol")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun bar(baz: Foo) {
|
|
||||||
baz foo 1
|
|
||||||
}
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
|
// IS_APPLICABLE: false
|
||||||
// WITH_RUNTIME
|
// WITH_RUNTIME
|
||||||
// SHOULD_FAIL_WITH: package.call
|
|
||||||
fun main() {
|
fun main() {
|
||||||
kotlin.io.<caret>println("")
|
kotlin.io.<caret>println("")
|
||||||
}
|
}
|
||||||
@@ -5393,12 +5393,6 @@ public class IntentionTestGenerated extends AbstractIntentionTest {
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
@TestMetadata("firstParameterLabeled.kt")
|
|
||||||
public void testFirstParameterLabeled() throws Exception {
|
|
||||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/intentions/replaceWithInfixFunctionCall/firstParameterLabeled.kt");
|
|
||||||
doTest(fileName);
|
|
||||||
}
|
|
||||||
|
|
||||||
@TestMetadata("functionLiteralArgument.kt")
|
@TestMetadata("functionLiteralArgument.kt")
|
||||||
public void testFunctionLiteralArgument() throws Exception {
|
public void testFunctionLiteralArgument() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/intentions/replaceWithInfixFunctionCall/functionLiteralArgument.kt");
|
String fileName = JetTestUtils.navigationMetadata("idea/testData/intentions/replaceWithInfixFunctionCall/functionLiteralArgument.kt");
|
||||||
|
|||||||
-25
@@ -1,25 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010-2015 JetBrains s.r.o.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.jetbrains.kotlin.idea.intentions
|
|
||||||
|
|
||||||
import com.intellij.openapi.editor.Editor
|
|
||||||
|
|
||||||
public class TestableReplaceWithInfixFunctionCallIntention : ReplaceWithInfixFunctionCallIntention() {
|
|
||||||
override fun intentionFailed(editor: Editor, messageID: String) {
|
|
||||||
throw IntentionTestException(messageID)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user