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.action=Add name to argument...
|
||||
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.family=Split If
|
||||
replace.with.operator.assign.intention=Replace with an operator-assign expression
|
||||
|
||||
+22
-72
@@ -16,92 +16,42 @@
|
||||
|
||||
package org.jetbrains.kotlin.idea.intentions
|
||||
|
||||
import org.jetbrains.kotlin.psi.JetCallExpression
|
||||
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.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 {
|
||||
val calleeExpr = element.getCalleeExpression()
|
||||
if (calleeExpr == null) return false
|
||||
val calleeExpr = element.getCalleeExpression() ?: return false
|
||||
if (!calleeExpr.getTextRange().containsOffset(caretOffset)) return false
|
||||
|
||||
val textRange = calleeExpr.getTextRange()
|
||||
if (textRange == null) return false
|
||||
val dotQualified = element.getParent() as? JetDotQualifiedExpression ?: 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 typeArguments = element.getTypeArgumentList()
|
||||
val valueArguments = element.getValueArgumentList()
|
||||
val functionLiteralArguments = element.getFunctionLiteralArguments()
|
||||
val numOfTotalValueArguments = (valueArguments?.getArguments()?.size() ?: 0) + functionLiteralArguments.size()
|
||||
val receiver = dotQualified.getReceiverExpression()
|
||||
if (element.analyze().getType(receiver) == null) return false
|
||||
|
||||
if (typeArguments?.getArguments()?.size() ?: 0 == 0 &&
|
||||
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)
|
||||
return true
|
||||
}
|
||||
|
||||
override fun applyTo(element: JetCallExpression, editor: Editor) {
|
||||
val parent = element.getParent() as JetDotQualifiedExpression
|
||||
val receiver = parent.getReceiverExpression()
|
||||
val leftHandText = parent.getReceiverExpression().getText()
|
||||
val rightHandTextStringBuilder = StringBuilder()
|
||||
val dotQualified = element.getParent() as JetDotQualifiedExpression
|
||||
val receiver = dotQualified.getReceiverExpression()
|
||||
|
||||
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(
|
||||
if (valueArguments.size() > 0)
|
||||
JetPsiUnparsingUtils.parenthesizeIfNeeded(valueArguments.first().getArgumentExpression())
|
||||
else
|
||||
functionLiteralArguments.first().getText()
|
||||
)
|
||||
val newCall = JetPsiFactory(element).createExpression("${receiver.getText()} $operatorText x") as JetBinaryExpression
|
||||
val argument = element.getValueArguments().single()
|
||||
newCall.getRight()!!.replace(argument.getArgumentExpression()!!)
|
||||
|
||||
val replacement = JetPsiFactory(element).createExpression("$leftHandText $operatorText ${rightHandTextStringBuilder.toString()}")
|
||||
|
||||
parent.replace(replacement)
|
||||
dotQualified.replace(newCall)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1 +1 @@
|
||||
org.jetbrains.kotlin.idea.intentions.TestableReplaceWithInfixFunctionCallIntention
|
||||
org.jetbrains.kotlin.idea.intentions.ReplaceWithInfixFunctionCallIntention
|
||||
|
||||
+1
-1
@@ -1,3 +1,3 @@
|
||||
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
|
||||
// SHOULD_FAIL_WITH: package.call
|
||||
fun main() {
|
||||
kotlin.io.<caret>println("")
|
||||
}
|
||||
@@ -5393,12 +5393,6 @@ public class IntentionTestGenerated extends AbstractIntentionTest {
|
||||
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")
|
||||
public void testFunctionLiteralArgument() throws Exception {
|
||||
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