Bug Fix: KT-4613
Fix replace with infix function intention to be inapplicable in the case of package function calls, such as “kotlin.io.println(“”).”
This commit is contained in:
@@ -276,6 +276,8 @@ replace.with.dot.qualified.method.call.intention=Replace with simple method call
|
||||
replace.with.dot.qualified.method.call.intention.family=Replace with simple method call
|
||||
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
|
||||
replace.explicit.function.literal.param.with.it=Replace explicit parameter ''{0}'' with ''it''
|
||||
replace.explicit.function.literal.param.with.it.family=Replace Explicit Parameter With 'it'
|
||||
move.lambda.inside.parentheses=Move lambda function into parentheses
|
||||
|
||||
+36
-11
@@ -19,14 +19,18 @@ package org.jetbrains.jet.plugin.intentions
|
||||
import org.jetbrains.jet.lang.psi.JetCallExpression
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import org.jetbrains.jet.lang.psi.JetDotQualifiedExpression
|
||||
import org.jetbrains.jet.lang.psi.JetValueArgument
|
||||
import org.jetbrains.jet.lang.psi.JetPsiFactory
|
||||
import org.jetbrains.jet.lang.psi.JetPsiUnparsingUtils
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext
|
||||
import org.jetbrains.jet.lang.psi.JetFile
|
||||
import org.jetbrains.jet.plugin.caches.resolve.getBindingContext
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext
|
||||
import org.jetbrains.jet.plugin.JetBundle
|
||||
import com.intellij.openapi.ui.popup.JBPopupFactory
|
||||
import org.jetbrains.jet.lang.psi.JetValueArgument
|
||||
import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache
|
||||
import org.jetbrains.jet.analyzer.computeTypeInfoInContext
|
||||
import org.jetbrains.jet.lang.types.PackageType
|
||||
import org.jetbrains.jet.lang.psi.JetPsiUnparsingUtils
|
||||
import org.jetbrains.jet.lang.psi.JetPsiFactory
|
||||
|
||||
public class ReplaceWithInfixFunctionCallIntention : JetSelfTargetingIntention<JetCallExpression>("replace.with.infix.function.call.intention", javaClass()) {
|
||||
public open class ReplaceWithInfixFunctionCallIntention : JetSelfTargetingIntention<JetCallExpression>("replace.with.infix.function.call.intention", javaClass()) {
|
||||
override fun isApplicableTo(element: JetCallExpression): Boolean {
|
||||
throw IllegalStateException("isApplicableTo(JetExpressionImpl, Editor) should be called instead")
|
||||
}
|
||||
@@ -54,11 +58,12 @@ public class ReplaceWithInfixFunctionCallIntention : JetSelfTargetingIntention<J
|
||||
if (typeArguments?.getArguments()?.size() ?: 0 == 0 &&
|
||||
numOfTotalValueArguments == 1 &&
|
||||
callee != null) {
|
||||
|
||||
if (valueArguments?.getArguments()?.size() == 1 && valueArguments?.getArguments()?.first()?.isNamed() ?: false) {
|
||||
val file: JetFile = element.getContainingJetFile()
|
||||
val file = element.getContainingJetFile()
|
||||
val bindingContext = file.getBindingContext()
|
||||
val descriptor = bindingContext.get(BindingContext.RESOLVED_CALL, callee)
|
||||
val valueArgumentsMap = descriptor?.getValueArguments()
|
||||
val resolvedCallDescriptor = bindingContext[BindingContext.RESOLVED_CALL, callee]
|
||||
val valueArgumentsMap = resolvedCallDescriptor?.getValueArguments()
|
||||
val firstArgument = valueArguments?.getArguments()?.first()
|
||||
|
||||
return valueArgumentsMap?.keySet()?.any { it.getName().asString() == firstArgument?.getArgumentName()?.getText() && it.getIndex() == 0 } ?: false
|
||||
@@ -73,13 +78,34 @@ public class ReplaceWithInfixFunctionCallIntention : JetSelfTargetingIntention<J
|
||||
}
|
||||
}
|
||||
|
||||
open fun intentionFailed(editor: Editor, messageID: String) {
|
||||
JBPopupFactory.getInstance()!!.createMessage("Intention failed: ${JetBundle.message("replace.with.infix.function.call.intention.error.$messageID")}").showInBestPositionFor(editor)
|
||||
}
|
||||
|
||||
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 operatorText = element.getCalleeExpression()!!.getText()
|
||||
val valueArguments = element.getValueArgumentList()?.getArguments() ?: listOf<JetValueArgument>()
|
||||
val functionLiteralArguments = element.getFunctionLiteralArguments()
|
||||
val bindingContext = AnalyzerFacadeWithCache.getContextForElement(parent)
|
||||
val scope = bindingContext[BindingContext.RESOLUTION_SCOPE, parent]
|
||||
|
||||
when {
|
||||
scope == null -> {
|
||||
intentionFailed(editor, "resolution.failed")
|
||||
return
|
||||
}
|
||||
else ->
|
||||
when (receiver.computeTypeInfoInContext(scope).getType()) {
|
||||
is PackageType -> {
|
||||
intentionFailed(editor, "package.call")
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rightHandTextStringBuilder.append(
|
||||
if (valueArguments.size() > 0)
|
||||
@@ -92,5 +118,4 @@ public class ReplaceWithInfixFunctionCallIntention : JetSelfTargetingIntention<J
|
||||
|
||||
parent.replace(replacement)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
// WITH_RUNTIME
|
||||
// SHOULD_FAIL_WITH: package.call
|
||||
fun main() {
|
||||
kotlin.io.<caret>println("")
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
// WITH_RUNTIME
|
||||
// IS_APPLICABLE: false
|
||||
package demo
|
||||
|
||||
fun foo(str: String) = kotlin.io.println(str)
|
||||
|
||||
fun main() {
|
||||
<caret>demo.foo("")
|
||||
}
|
||||
@@ -179,7 +179,7 @@ public abstract class AbstractCodeTransformationTest extends LightCodeInsightTes
|
||||
}
|
||||
|
||||
public void doTestReplaceWithInfixFunctionCall(@NotNull String path) throws Exception {
|
||||
doTestIntention(path, new ReplaceWithInfixFunctionCallIntention());
|
||||
doTestIntention(path, new TestableReplaceWithInfixFunctionCallIntention());
|
||||
}
|
||||
|
||||
public void doTestReplaceExplicitFunctionLiteralParamWithIt(@NotNull String path) throws Exception {
|
||||
|
||||
@@ -2067,6 +2067,11 @@ public class CodeTransformationTestGenerated extends AbstractCodeTransformationT
|
||||
doTestReplaceWithInfixFunctionCall("idea/testData/intentions/replaceWithInfixFunctionCall/nullAssertedReceiver.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("packageFunctionCall.kt")
|
||||
public void testPackageFunctionCall() throws Exception {
|
||||
doTestReplaceWithInfixFunctionCall("idea/testData/intentions/replaceWithInfixFunctionCall/packageFunctionCall.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("propertyAccess.kt")
|
||||
public void testPropertyAccess() throws Exception {
|
||||
doTestReplaceWithInfixFunctionCall("idea/testData/intentions/replaceWithInfixFunctionCall/propertyAccess.kt");
|
||||
@@ -2087,6 +2092,11 @@ public class CodeTransformationTestGenerated extends AbstractCodeTransformationT
|
||||
doTestReplaceWithInfixFunctionCall("idea/testData/intentions/replaceWithInfixFunctionCall/simpleMethodCall.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("singlePackageFunctionCall.kt")
|
||||
public void testSinglePackageFunctionCall() throws Exception {
|
||||
doTestReplaceWithInfixFunctionCall("idea/testData/intentions/replaceWithInfixFunctionCall/singlePackageFunctionCall.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("zeroArguments.kt")
|
||||
public void testZeroArguments() throws Exception {
|
||||
doTestReplaceWithInfixFunctionCall("idea/testData/intentions/replaceWithInfixFunctionCall/zeroArguments.kt");
|
||||
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright 2010-2014 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.jet.plugin.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