From 8b6bd8a184496a109e162133fbf40896fdd0d802 Mon Sep 17 00:00:00 2001 From: Pradyoth Kukkapalli Date: Fri, 7 Feb 2014 15:39:43 -0800 Subject: [PATCH] New Intention Action: Replace an infix function call with a dot qualified method call. --- .../jet/generators/tests/GenerateTests.kt | 1 + .../after.kt.template | 3 ++ .../before.kt.template | 3 ++ .../description.html | 5 ++ idea/src/META-INF/plugin.xml | 5 ++ .../jetbrains/jet/plugin/JetBundle.properties | 2 + ...laceWithDotQualifiedMethodCallIntention.kt | 52 +++++++++++++++++++ .../functionCallAfterInfixCall.kt | 3 ++ .../functionCallAfterInfixCall.kt.after | 3 ++ .../functionLiteralArgument.kt | 3 ++ .../functionLiteralArgument.kt.after | 3 ++ .../nonApplicableBinaryOperation.kt | 4 ++ .../nullAssertedCall.kt | 3 ++ .../nullAssertedCall.kt.after | 3 ++ .../parenthesesAroundRightHandArgument.kt | 3 ++ ...arenthesesAroundRightHandArgument.kt.after | 3 ++ .../simpleInfixFunctionCall.kt | 3 ++ .../simpleInfixFunctionCall.kt.after | 3 ++ .../AbstractCodeTransformationTest.java | 4 ++ .../CodeTransformationTestGenerated.java | 41 ++++++++++++++- 20 files changed, 149 insertions(+), 1 deletion(-) create mode 100644 idea/resources/intentionDescriptions/ReplaceWithDotQualifiedMethodCallIntention/after.kt.template create mode 100644 idea/resources/intentionDescriptions/ReplaceWithDotQualifiedMethodCallIntention/before.kt.template create mode 100644 idea/resources/intentionDescriptions/ReplaceWithDotQualifiedMethodCallIntention/description.html create mode 100644 idea/src/org/jetbrains/jet/plugin/intentions/ReplaceWithDotQualifiedMethodCallIntention.kt create mode 100644 idea/testData/intentions/replaceWithDotQualifiedMethodCall/functionCallAfterInfixCall.kt create mode 100644 idea/testData/intentions/replaceWithDotQualifiedMethodCall/functionCallAfterInfixCall.kt.after create mode 100644 idea/testData/intentions/replaceWithDotQualifiedMethodCall/functionLiteralArgument.kt create mode 100644 idea/testData/intentions/replaceWithDotQualifiedMethodCall/functionLiteralArgument.kt.after create mode 100644 idea/testData/intentions/replaceWithDotQualifiedMethodCall/nonApplicableBinaryOperation.kt create mode 100644 idea/testData/intentions/replaceWithDotQualifiedMethodCall/nullAssertedCall.kt create mode 100644 idea/testData/intentions/replaceWithDotQualifiedMethodCall/nullAssertedCall.kt.after create mode 100644 idea/testData/intentions/replaceWithDotQualifiedMethodCall/parenthesesAroundRightHandArgument.kt create mode 100644 idea/testData/intentions/replaceWithDotQualifiedMethodCall/parenthesesAroundRightHandArgument.kt.after create mode 100644 idea/testData/intentions/replaceWithDotQualifiedMethodCall/simpleInfixFunctionCall.kt create mode 100644 idea/testData/intentions/replaceWithDotQualifiedMethodCall/simpleInfixFunctionCall.kt.after diff --git a/generators/src/org/jetbrains/jet/generators/tests/GenerateTests.kt b/generators/src/org/jetbrains/jet/generators/tests/GenerateTests.kt index 9a55fc5124f..0f0fc2fad1d 100644 --- a/generators/src/org/jetbrains/jet/generators/tests/GenerateTests.kt +++ b/generators/src/org/jetbrains/jet/generators/tests/GenerateTests.kt @@ -336,6 +336,7 @@ fun main(args: Array) { model("intentions/declarations/convertMemberToExtension", testMethod = "doTestConvertMemberToExtension") model("intentions/reconstructedType", testMethod = "doTestReconstructType") model("intentions/removeUnnecessaryParentheses", testMethod = "doTestRemoveUnnecessaryParentheses") + model("intentions/replaceWithDotQualifiedMethodCall", testMethod = "doTestReplaceWithDotQualifiedMethodCall") } testClass(javaClass()) { diff --git a/idea/resources/intentionDescriptions/ReplaceWithDotQualifiedMethodCallIntention/after.kt.template b/idea/resources/intentionDescriptions/ReplaceWithDotQualifiedMethodCallIntention/after.kt.template new file mode 100644 index 00000000000..b966b6cea05 --- /dev/null +++ b/idea/resources/intentionDescriptions/ReplaceWithDotQualifiedMethodCallIntention/after.kt.template @@ -0,0 +1,3 @@ +fun foo(x: Foo) { + x.foo(1) +} \ No newline at end of file diff --git a/idea/resources/intentionDescriptions/ReplaceWithDotQualifiedMethodCallIntention/before.kt.template b/idea/resources/intentionDescriptions/ReplaceWithDotQualifiedMethodCallIntention/before.kt.template new file mode 100644 index 00000000000..2d3a1878377 --- /dev/null +++ b/idea/resources/intentionDescriptions/ReplaceWithDotQualifiedMethodCallIntention/before.kt.template @@ -0,0 +1,3 @@ +fun foo(x: Foo) { + x foo 1 +} \ No newline at end of file diff --git a/idea/resources/intentionDescriptions/ReplaceWithDotQualifiedMethodCallIntention/description.html b/idea/resources/intentionDescriptions/ReplaceWithDotQualifiedMethodCallIntention/description.html new file mode 100644 index 00000000000..cd2629b80de --- /dev/null +++ b/idea/resources/intentionDescriptions/ReplaceWithDotQualifiedMethodCallIntention/description.html @@ -0,0 +1,5 @@ + + +This intention converts an infix function call to a dot-qualified function call. + + \ No newline at end of file diff --git a/idea/src/META-INF/plugin.xml b/idea/src/META-INF/plugin.xml index d0de53cebf9..479dea6fa9f 100644 --- a/idea/src/META-INF/plugin.xml +++ b/idea/src/META-INF/plugin.xml @@ -488,6 +488,11 @@ Kotlin + + org.jetbrains.jet.plugin.intentions.ReplaceWithDotQualifiedMethodCallIntention + Kotlin + + diff --git a/idea/src/org/jetbrains/jet/plugin/JetBundle.properties b/idea/src/org/jetbrains/jet/plugin/JetBundle.properties index 3c206016d38..faac0da1282 100644 --- a/idea/src/org/jetbrains/jet/plugin/JetBundle.properties +++ b/idea/src/org/jetbrains/jet/plugin/JetBundle.properties @@ -222,6 +222,8 @@ 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.dot.qualified.method.call.intention=Replace with simple method call +replace.with.dot.qualified.method.call.intention.family=Replace with simple method call property.is.implemented.too.many=Has implementations property.is.overridden.too.many=Is overridden in subclasses diff --git a/idea/src/org/jetbrains/jet/plugin/intentions/ReplaceWithDotQualifiedMethodCallIntention.kt b/idea/src/org/jetbrains/jet/plugin/intentions/ReplaceWithDotQualifiedMethodCallIntention.kt new file mode 100644 index 00000000000..6f15aaca350 --- /dev/null +++ b/idea/src/org/jetbrains/jet/plugin/intentions/ReplaceWithDotQualifiedMethodCallIntention.kt @@ -0,0 +1,52 @@ +/* + * 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 +import org.jetbrains.jet.lang.psi.JetSimpleNameExpression +import org.jetbrains.jet.lang.psi.JetBinaryExpression +import org.jetbrains.jet.lang.psi.JetPsiFactory +import org.jetbrains.jet.lang.psi.JetFunctionLiteralExpression +import org.jetbrains.jet.lang.psi.JetParenthesizedExpression +import org.jetbrains.jet.lang.types.expressions.OperatorConventions +import com.google.common.collect.ImmutableSet +import org.jetbrains.jet.lexer.JetTokens +import org.jetbrains.jet.lexer.JetToken + +public class ReplaceWithDotQualifiedMethodCallIntention : JetSelfTargetingIntention("replace.with.dot.qualified.method.call.intention", javaClass()) { + override fun isApplicableTo(element: JetBinaryExpression): Boolean { + return element.getLeft() != null && element.getRight() != null && element.getOperationToken() == JetTokens.IDENTIFIER + } + + override fun applyTo(element: JetBinaryExpression, editor: Editor) { + val receiverText = element.getLeft()!!.getText() + val argumentText = element.getRight()!!.getText() + val functionName = element.getOperationReference().getText() + val replacementExpressionStringBuilder = StringBuilder("$receiverText.$functionName") + + replacementExpressionStringBuilder.append( + when (element.getRight()) { + is JetFunctionLiteralExpression -> " $argumentText" + is JetParenthesizedExpression -> argumentText + else -> "($argumentText)" + } + ) + + val replacement = JetPsiFactory.createExpression(element.getProject(), replacementExpressionStringBuilder.toString()) + element.replace(replacement) + } +} \ No newline at end of file diff --git a/idea/testData/intentions/replaceWithDotQualifiedMethodCall/functionCallAfterInfixCall.kt b/idea/testData/intentions/replaceWithDotQualifiedMethodCall/functionCallAfterInfixCall.kt new file mode 100644 index 00000000000..e13fc0e9baa --- /dev/null +++ b/idea/testData/intentions/replaceWithDotQualifiedMethodCall/functionCallAfterInfixCall.kt @@ -0,0 +1,3 @@ +fun foo(x: Foo) { + (x foo 1).bar() +} \ No newline at end of file diff --git a/idea/testData/intentions/replaceWithDotQualifiedMethodCall/functionCallAfterInfixCall.kt.after b/idea/testData/intentions/replaceWithDotQualifiedMethodCall/functionCallAfterInfixCall.kt.after new file mode 100644 index 00000000000..28a10b9f1a1 --- /dev/null +++ b/idea/testData/intentions/replaceWithDotQualifiedMethodCall/functionCallAfterInfixCall.kt.after @@ -0,0 +1,3 @@ +fun foo(x: Foo) { + (x.foo(1)).bar() +} \ No newline at end of file diff --git a/idea/testData/intentions/replaceWithDotQualifiedMethodCall/functionLiteralArgument.kt b/idea/testData/intentions/replaceWithDotQualifiedMethodCall/functionLiteralArgument.kt new file mode 100644 index 00000000000..537769d5d06 --- /dev/null +++ b/idea/testData/intentions/replaceWithDotQualifiedMethodCall/functionLiteralArgument.kt @@ -0,0 +1,3 @@ +fun foo(x: Foo) { + x foo { it * 2 } +} \ No newline at end of file diff --git a/idea/testData/intentions/replaceWithDotQualifiedMethodCall/functionLiteralArgument.kt.after b/idea/testData/intentions/replaceWithDotQualifiedMethodCall/functionLiteralArgument.kt.after new file mode 100644 index 00000000000..6b9feefa4d6 --- /dev/null +++ b/idea/testData/intentions/replaceWithDotQualifiedMethodCall/functionLiteralArgument.kt.after @@ -0,0 +1,3 @@ +fun foo(x: Foo) { + x.foo { it * 2 } +} \ No newline at end of file diff --git a/idea/testData/intentions/replaceWithDotQualifiedMethodCall/nonApplicableBinaryOperation.kt b/idea/testData/intentions/replaceWithDotQualifiedMethodCall/nonApplicableBinaryOperation.kt new file mode 100644 index 00000000000..4d7bfd7316e --- /dev/null +++ b/idea/testData/intentions/replaceWithDotQualifiedMethodCall/nonApplicableBinaryOperation.kt @@ -0,0 +1,4 @@ +// IS_APPLICABLE: false +fun foo(x: Foo) { + x == x +} \ No newline at end of file diff --git a/idea/testData/intentions/replaceWithDotQualifiedMethodCall/nullAssertedCall.kt b/idea/testData/intentions/replaceWithDotQualifiedMethodCall/nullAssertedCall.kt new file mode 100644 index 00000000000..bde450537ed --- /dev/null +++ b/idea/testData/intentions/replaceWithDotQualifiedMethodCall/nullAssertedCall.kt @@ -0,0 +1,3 @@ +fun foo(x: Foo) { + x!! foo 1 +} \ No newline at end of file diff --git a/idea/testData/intentions/replaceWithDotQualifiedMethodCall/nullAssertedCall.kt.after b/idea/testData/intentions/replaceWithDotQualifiedMethodCall/nullAssertedCall.kt.after new file mode 100644 index 00000000000..406ad8b358d --- /dev/null +++ b/idea/testData/intentions/replaceWithDotQualifiedMethodCall/nullAssertedCall.kt.after @@ -0,0 +1,3 @@ +fun foo(x: Foo) { + x!!.foo(1) +} \ No newline at end of file diff --git a/idea/testData/intentions/replaceWithDotQualifiedMethodCall/parenthesesAroundRightHandArgument.kt b/idea/testData/intentions/replaceWithDotQualifiedMethodCall/parenthesesAroundRightHandArgument.kt new file mode 100644 index 00000000000..e59e87003f8 --- /dev/null +++ b/idea/testData/intentions/replaceWithDotQualifiedMethodCall/parenthesesAroundRightHandArgument.kt @@ -0,0 +1,3 @@ +fun foo(x: Foo) { + x foo (1 + 2) +} \ No newline at end of file diff --git a/idea/testData/intentions/replaceWithDotQualifiedMethodCall/parenthesesAroundRightHandArgument.kt.after b/idea/testData/intentions/replaceWithDotQualifiedMethodCall/parenthesesAroundRightHandArgument.kt.after new file mode 100644 index 00000000000..3e0027edf7b --- /dev/null +++ b/idea/testData/intentions/replaceWithDotQualifiedMethodCall/parenthesesAroundRightHandArgument.kt.after @@ -0,0 +1,3 @@ +fun foo(x: Foo) { + x.foo(1 + 2) +} \ No newline at end of file diff --git a/idea/testData/intentions/replaceWithDotQualifiedMethodCall/simpleInfixFunctionCall.kt b/idea/testData/intentions/replaceWithDotQualifiedMethodCall/simpleInfixFunctionCall.kt new file mode 100644 index 00000000000..4c324ec3b60 --- /dev/null +++ b/idea/testData/intentions/replaceWithDotQualifiedMethodCall/simpleInfixFunctionCall.kt @@ -0,0 +1,3 @@ +fun foo(x: Foo) { + x foo 1 +} \ No newline at end of file diff --git a/idea/testData/intentions/replaceWithDotQualifiedMethodCall/simpleInfixFunctionCall.kt.after b/idea/testData/intentions/replaceWithDotQualifiedMethodCall/simpleInfixFunctionCall.kt.after new file mode 100644 index 00000000000..5b509a98f79 --- /dev/null +++ b/idea/testData/intentions/replaceWithDotQualifiedMethodCall/simpleInfixFunctionCall.kt.after @@ -0,0 +1,3 @@ +fun foo(x: Foo) { + x.foo(1) +} \ No newline at end of file diff --git a/idea/tests/org/jetbrains/jet/plugin/intentions/AbstractCodeTransformationTest.java b/idea/tests/org/jetbrains/jet/plugin/intentions/AbstractCodeTransformationTest.java index 50a2ad7bd5e..eac6e58589d 100644 --- a/idea/tests/org/jetbrains/jet/plugin/intentions/AbstractCodeTransformationTest.java +++ b/idea/tests/org/jetbrains/jet/plugin/intentions/AbstractCodeTransformationTest.java @@ -118,6 +118,10 @@ public abstract class AbstractCodeTransformationTest extends LightCodeInsightTes doTestIntention(path, new ReconstructTypeInCastOrIsAction()); } + public void doTestReplaceWithDotQualifiedMethodCall(@NotNull String path) throws Exception { + doTestIntention(path, new ReplaceWithDotQualifiedMethodCallIntention()); + } + private void doTestIntention(@NotNull String path, @NotNull IntentionAction intentionAction) throws Exception { configureByFile(path); diff --git a/idea/tests/org/jetbrains/jet/plugin/intentions/CodeTransformationTestGenerated.java b/idea/tests/org/jetbrains/jet/plugin/intentions/CodeTransformationTestGenerated.java index 1aff6c9a6fa..3662d761c05 100644 --- a/idea/tests/org/jetbrains/jet/plugin/intentions/CodeTransformationTestGenerated.java +++ b/idea/tests/org/jetbrains/jet/plugin/intentions/CodeTransformationTestGenerated.java @@ -30,7 +30,7 @@ import org.jetbrains.jet.plugin.intentions.AbstractCodeTransformationTest; /** This class is generated by {@link org.jetbrains.jet.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */ @SuppressWarnings("all") -@InnerTestClasses({CodeTransformationTestGenerated.IfToAssignment.class, CodeTransformationTestGenerated.IfToReturn.class, CodeTransformationTestGenerated.IfToReturnAsymmetrically.class, CodeTransformationTestGenerated.WhenToAssignment.class, CodeTransformationTestGenerated.WhenToReturn.class, CodeTransformationTestGenerated.AssignmentToIf.class, CodeTransformationTestGenerated.AssignmentToWhen.class, CodeTransformationTestGenerated.PropertyToIf.class, CodeTransformationTestGenerated.PropertyToWhen.class, CodeTransformationTestGenerated.ReturnToIf.class, CodeTransformationTestGenerated.ReturnToWhen.class, CodeTransformationTestGenerated.IfToWhen.class, CodeTransformationTestGenerated.WhenToIf.class, CodeTransformationTestGenerated.Flatten.class, CodeTransformationTestGenerated.Merge.class, CodeTransformationTestGenerated.IntroduceSubject.class, CodeTransformationTestGenerated.EliminateSubject.class, CodeTransformationTestGenerated.Split.class, CodeTransformationTestGenerated.Join.class, CodeTransformationTestGenerated.ConvertMemberToExtension.class, CodeTransformationTestGenerated.ReconstructedType.class, CodeTransformationTestGenerated.RemoveUnnecessaryParentheses.class}) +@InnerTestClasses({CodeTransformationTestGenerated.IfToAssignment.class, CodeTransformationTestGenerated.IfToReturn.class, CodeTransformationTestGenerated.IfToReturnAsymmetrically.class, CodeTransformationTestGenerated.WhenToAssignment.class, CodeTransformationTestGenerated.WhenToReturn.class, CodeTransformationTestGenerated.AssignmentToIf.class, CodeTransformationTestGenerated.AssignmentToWhen.class, CodeTransformationTestGenerated.PropertyToIf.class, CodeTransformationTestGenerated.PropertyToWhen.class, CodeTransformationTestGenerated.ReturnToIf.class, CodeTransformationTestGenerated.ReturnToWhen.class, CodeTransformationTestGenerated.IfToWhen.class, CodeTransformationTestGenerated.WhenToIf.class, CodeTransformationTestGenerated.Flatten.class, CodeTransformationTestGenerated.Merge.class, CodeTransformationTestGenerated.IntroduceSubject.class, CodeTransformationTestGenerated.EliminateSubject.class, CodeTransformationTestGenerated.Split.class, CodeTransformationTestGenerated.Join.class, CodeTransformationTestGenerated.ConvertMemberToExtension.class, CodeTransformationTestGenerated.ReconstructedType.class, CodeTransformationTestGenerated.RemoveUnnecessaryParentheses.class, CodeTransformationTestGenerated.ReplaceWithDotQualifiedMethodCall.class}) public class CodeTransformationTestGenerated extends AbstractCodeTransformationTest { @TestMetadata("idea/testData/intentions/branched/folding/ifToAssignment") public static class IfToAssignment extends AbstractCodeTransformationTest { @@ -1183,6 +1183,44 @@ public class CodeTransformationTestGenerated extends AbstractCodeTransformationT } + @TestMetadata("idea/testData/intentions/replaceWithDotQualifiedMethodCall") + public static class ReplaceWithDotQualifiedMethodCall extends AbstractCodeTransformationTest { + public void testAllFilesPresentInReplaceWithDotQualifiedMethodCall() throws Exception { + JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.TestsPackage", new File("idea/testData/intentions/replaceWithDotQualifiedMethodCall"), Pattern.compile("^(.+)\\.kt$"), true); + } + + @TestMetadata("functionCallAfterInfixCall.kt") + public void testFunctionCallAfterInfixCall() throws Exception { + doTestReplaceWithDotQualifiedMethodCall("idea/testData/intentions/replaceWithDotQualifiedMethodCall/functionCallAfterInfixCall.kt"); + } + + @TestMetadata("functionLiteralArgument.kt") + public void testFunctionLiteralArgument() throws Exception { + doTestReplaceWithDotQualifiedMethodCall("idea/testData/intentions/replaceWithDotQualifiedMethodCall/functionLiteralArgument.kt"); + } + + @TestMetadata("nonApplicableBinaryOperation.kt") + public void testNonApplicableBinaryOperation() throws Exception { + doTestReplaceWithDotQualifiedMethodCall("idea/testData/intentions/replaceWithDotQualifiedMethodCall/nonApplicableBinaryOperation.kt"); + } + + @TestMetadata("nullAssertedCall.kt") + public void testNullAssertedCall() throws Exception { + doTestReplaceWithDotQualifiedMethodCall("idea/testData/intentions/replaceWithDotQualifiedMethodCall/nullAssertedCall.kt"); + } + + @TestMetadata("parenthesesAroundRightHandArgument.kt") + public void testParenthesesAroundRightHandArgument() throws Exception { + doTestReplaceWithDotQualifiedMethodCall("idea/testData/intentions/replaceWithDotQualifiedMethodCall/parenthesesAroundRightHandArgument.kt"); + } + + @TestMetadata("simpleInfixFunctionCall.kt") + public void testSimpleInfixFunctionCall() throws Exception { + doTestReplaceWithDotQualifiedMethodCall("idea/testData/intentions/replaceWithDotQualifiedMethodCall/simpleInfixFunctionCall.kt"); + } + + } + public static Test suite() { TestSuite suite = new TestSuite("CodeTransformationTestGenerated"); suite.addTestSuite(IfToAssignment.class); @@ -1207,6 +1245,7 @@ public class CodeTransformationTestGenerated extends AbstractCodeTransformationT suite.addTestSuite(ConvertMemberToExtension.class); suite.addTestSuite(ReconstructedType.class); suite.addTestSuite(RemoveUnnecessaryParentheses.class); + suite.addTestSuite(ReplaceWithDotQualifiedMethodCall.class); return suite; } }