From eb3ddf50bfe13cfc059a8ecf9d8a37cc0258a9ff Mon Sep 17 00:00:00 2001 From: Pradyoth Kukkapalli Date: Sat, 5 Apr 2014 01:13:49 -0400 Subject: [PATCH] New Intention Action: Replace with traditional assign. This takes an expression of the form a += b and converts it to an expression form a = a + b. --- .../jet/generators/tests/GenerateTests.kt | 1 + .../after.kt.template | 4 ++ .../before.kt.template | 4 ++ .../description.html | 5 ++ idea/src/META-INF/plugin.xml | 5 ++ .../jetbrains/jet/plugin/JetBundle.properties | 2 + ...placeWithTraditionalAssignmentIntention.kt | 58 +++++++++++++++++++ .../complexRightExpression.kt | 6 ++ .../complexRightExpression.kt.after | 6 ++ .../nonAssignmentExpression.kt | 5 ++ .../nonAugmentedAssign.kt | 7 +++ .../simple.kt | 4 ++ .../simple.kt.after | 4 ++ .../AbstractCodeTransformationTest.java | 4 ++ .../CodeTransformationTestGenerated.java | 31 +++++++++- 15 files changed, 145 insertions(+), 1 deletion(-) create mode 100644 idea/resources/intentionDescriptions/ReplaceWithTraditionalAssignmentIntention/after.kt.template create mode 100644 idea/resources/intentionDescriptions/ReplaceWithTraditionalAssignmentIntention/before.kt.template create mode 100644 idea/resources/intentionDescriptions/ReplaceWithTraditionalAssignmentIntention/description.html create mode 100644 idea/src/org/jetbrains/jet/plugin/intentions/ReplaceWithTraditionalAssignmentIntention.kt create mode 100644 idea/testData/intentions/replaceWithTraditionalAssignment/complexRightExpression.kt create mode 100644 idea/testData/intentions/replaceWithTraditionalAssignment/complexRightExpression.kt.after create mode 100644 idea/testData/intentions/replaceWithTraditionalAssignment/nonAssignmentExpression.kt create mode 100644 idea/testData/intentions/replaceWithTraditionalAssignment/nonAugmentedAssign.kt create mode 100644 idea/testData/intentions/replaceWithTraditionalAssignment/simple.kt create mode 100644 idea/testData/intentions/replaceWithTraditionalAssignment/simple.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 018f2c5bd0c..3014280c0a4 100644 --- a/generators/src/org/jetbrains/jet/generators/tests/GenerateTests.kt +++ b/generators/src/org/jetbrains/jet/generators/tests/GenerateTests.kt @@ -387,6 +387,7 @@ fun main(args: Array) { model("intentions/swapBinaryExpression", testMethod = "doTestSwapBinaryExpression") model("intentions/splitIf", testMethod = "doTestSplitIf") model("intentions/replaceWithOperatorAssign", testMethod = "doTestReplaceWithOperatorAssign") + model("intentions/replaceWithTraditionalAssignment", testMethod = "doTestReplaceWithTraditionalAssignment") } testClass(javaClass()) { diff --git a/idea/resources/intentionDescriptions/ReplaceWithTraditionalAssignmentIntention/after.kt.template b/idea/resources/intentionDescriptions/ReplaceWithTraditionalAssignmentIntention/after.kt.template new file mode 100644 index 00000000000..093df1de06e --- /dev/null +++ b/idea/resources/intentionDescriptions/ReplaceWithTraditionalAssignmentIntention/after.kt.template @@ -0,0 +1,4 @@ +fun foo() { + var x = 0 + x = x + y +} \ No newline at end of file diff --git a/idea/resources/intentionDescriptions/ReplaceWithTraditionalAssignmentIntention/before.kt.template b/idea/resources/intentionDescriptions/ReplaceWithTraditionalAssignmentIntention/before.kt.template new file mode 100644 index 00000000000..60886332ecc --- /dev/null +++ b/idea/resources/intentionDescriptions/ReplaceWithTraditionalAssignmentIntention/before.kt.template @@ -0,0 +1,4 @@ +fun foo() { + var x = 0 + x += y +} \ No newline at end of file diff --git a/idea/resources/intentionDescriptions/ReplaceWithTraditionalAssignmentIntention/description.html b/idea/resources/intentionDescriptions/ReplaceWithTraditionalAssignmentIntention/description.html new file mode 100644 index 00000000000..673b63e1921 --- /dev/null +++ b/idea/resources/intentionDescriptions/ReplaceWithTraditionalAssignmentIntention/description.html @@ -0,0 +1,5 @@ + + +This intention modifies an expression with an augment assignment to an expression that separates the assignment and operator. + + \ No newline at end of file diff --git a/idea/src/META-INF/plugin.xml b/idea/src/META-INF/plugin.xml index 2bc632fff87..3c317df1cba 100644 --- a/idea/src/META-INF/plugin.xml +++ b/idea/src/META-INF/plugin.xml @@ -650,6 +650,11 @@ Kotlin + + org.jetbrains.jet.plugin.intentions.ReplaceWithTraditionalAssignmentIntention + Kotlin + + diff --git a/idea/src/org/jetbrains/jet/plugin/JetBundle.properties b/idea/src/org/jetbrains/jet/plugin/JetBundle.properties index 0ac820e9b2b..05327ae58c0 100644 --- a/idea/src/org/jetbrains/jet/plugin/JetBundle.properties +++ b/idea/src/org/jetbrains/jet/plugin/JetBundle.properties @@ -289,6 +289,8 @@ split.if=Split into 2 if's split.if.family=Split If replace.with.operator.assign.intention=Replace with an Operator-Assign Expression replace.with.operator.assign.intention.family=Replace with an Operator-Assign Expression +replace.with.traditional.assignment.intention=Replace with Traditional Assignment +replace.with.traditional.assignment.intention.family=Replace with Traditional Assignment 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/ReplaceWithTraditionalAssignmentIntention.kt b/idea/src/org/jetbrains/jet/plugin/intentions/ReplaceWithTraditionalAssignmentIntention.kt new file mode 100644 index 00000000000..190d06fd2f9 --- /dev/null +++ b/idea/src/org/jetbrains/jet/plugin/intentions/ReplaceWithTraditionalAssignmentIntention.kt @@ -0,0 +1,58 @@ +/* + * 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 org.jetbrains.jet.lang.psi.JetBinaryExpression +import com.intellij.openapi.editor.Editor +import org.jetbrains.jet.lang.psi.JetSimpleNameExpression +import org.jetbrains.jet.lexer.JetTokens +import org.jetbrains.jet.lang.psi.JetPsiFactory +import org.jetbrains.jet.lang.psi.JetPsiUnparsingUtils + +public class ReplaceWithTraditionalAssignmentIntention : JetSelfTargetingIntention("replace.with.traditional.assignment.intention", javaClass()) { + override fun isApplicableTo(element: JetBinaryExpression): Boolean { + fun checkForNullSafety(element: JetBinaryExpression): Boolean = element.getLeft() != null && element.getRight() != null && element.getOperationToken() != null + + fun checkValidity(element: JetBinaryExpression): Boolean { + return element.getLeft() is JetSimpleNameExpression && + JetTokens.AUGMENTED_ASSIGNMENTS.contains(element.getOperationToken()) + } + + return checkForNullSafety(element) && checkValidity(element) + } + + override fun applyTo(element: JetBinaryExpression, editor: Editor) { + fun buildReplacement(element: JetBinaryExpression): String { + val replacementStringBuilder = StringBuilder("${element.getLeft()!!.getText()} = ${element.getLeft()!!.getText()} ") + + replacementStringBuilder.append( + when { + element.getOperationToken() == JetTokens.PLUSEQ -> "+" + element.getOperationToken() == JetTokens.MINUSEQ -> "-" + element.getOperationToken() == JetTokens.MULTEQ -> "*" + element.getOperationToken() == JetTokens.DIVEQ -> "/" + element.getOperationToken() == JetTokens.PERC -> "%" + else -> "" + } + ).append(" ${JetPsiUnparsingUtils.parenthesizeIfNeeded(element.getRight())}") + + return replacementStringBuilder.toString() + } + + element.replace(JetPsiFactory.createExpression(element.getProject(), buildReplacement(element))) + } +} \ No newline at end of file diff --git a/idea/testData/intentions/replaceWithTraditionalAssignment/complexRightExpression.kt b/idea/testData/intentions/replaceWithTraditionalAssignment/complexRightExpression.kt new file mode 100644 index 00000000000..44ddf918fa8 --- /dev/null +++ b/idea/testData/intentions/replaceWithTraditionalAssignment/complexRightExpression.kt @@ -0,0 +1,6 @@ +fun foo() { + var x = 0 + val a = 1 + val b = 1 + x += a / b +} \ No newline at end of file diff --git a/idea/testData/intentions/replaceWithTraditionalAssignment/complexRightExpression.kt.after b/idea/testData/intentions/replaceWithTraditionalAssignment/complexRightExpression.kt.after new file mode 100644 index 00000000000..29e9ec2c9e9 --- /dev/null +++ b/idea/testData/intentions/replaceWithTraditionalAssignment/complexRightExpression.kt.after @@ -0,0 +1,6 @@ +fun foo() { + var x = 0 + val a = 1 + val b = 1 + x = x + (a / b) +} \ No newline at end of file diff --git a/idea/testData/intentions/replaceWithTraditionalAssignment/nonAssignmentExpression.kt b/idea/testData/intentions/replaceWithTraditionalAssignment/nonAssignmentExpression.kt new file mode 100644 index 00000000000..d0c68128fce --- /dev/null +++ b/idea/testData/intentions/replaceWithTraditionalAssignment/nonAssignmentExpression.kt @@ -0,0 +1,5 @@ +// IS_APPLICABLE: false +fun foo() { + var x = 0 + x + 1 +} \ No newline at end of file diff --git a/idea/testData/intentions/replaceWithTraditionalAssignment/nonAugmentedAssign.kt b/idea/testData/intentions/replaceWithTraditionalAssignment/nonAugmentedAssign.kt new file mode 100644 index 00000000000..f5c86babf49 --- /dev/null +++ b/idea/testData/intentions/replaceWithTraditionalAssignment/nonAugmentedAssign.kt @@ -0,0 +1,7 @@ +// IS_APPLICABLE: false +fun foo() { + var x = 0 + val a = 1 + val b = 1 + x = a / b +} \ No newline at end of file diff --git a/idea/testData/intentions/replaceWithTraditionalAssignment/simple.kt b/idea/testData/intentions/replaceWithTraditionalAssignment/simple.kt new file mode 100644 index 00000000000..dd626cf344a --- /dev/null +++ b/idea/testData/intentions/replaceWithTraditionalAssignment/simple.kt @@ -0,0 +1,4 @@ +fun foo() { + var x = 0 + x += 1 +} \ No newline at end of file diff --git a/idea/testData/intentions/replaceWithTraditionalAssignment/simple.kt.after b/idea/testData/intentions/replaceWithTraditionalAssignment/simple.kt.after new file mode 100644 index 00000000000..c4922fceaf2 --- /dev/null +++ b/idea/testData/intentions/replaceWithTraditionalAssignment/simple.kt.after @@ -0,0 +1,4 @@ +fun foo() { + var x = 0 + x = x + 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 499fdd203bd..b6812a17f49 100644 --- a/idea/tests/org/jetbrains/jet/plugin/intentions/AbstractCodeTransformationTest.java +++ b/idea/tests/org/jetbrains/jet/plugin/intentions/AbstractCodeTransformationTest.java @@ -223,6 +223,10 @@ public abstract class AbstractCodeTransformationTest extends LightCodeInsightTes doTestIntention(path, new ReplaceWithOperatorAssignIntention()); } + public void doTestReplaceWithTraditionalAssignment(@NotNull String path) throws Exception { + doTestIntention(path, new ReplaceWithTraditionalAssignmentIntention()); + } + 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 b13bb6fe0b9..dbaee1285b4 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.ElvisToIfThen.class, CodeTransformationTestGenerated.IfThenToElvis.class, CodeTransformationTestGenerated.SafeAccessToIfThen.class, CodeTransformationTestGenerated.IfThenToSafeAccess.class, 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, CodeTransformationTestGenerated.ReplaceWithInfixFunctionCall.class, CodeTransformationTestGenerated.RemoveCurlyBracesFromTemplate.class, CodeTransformationTestGenerated.MoveLambdaInsideParentheses.class, CodeTransformationTestGenerated.MoveLambdaOutsideParentheses.class, CodeTransformationTestGenerated.ReplaceExplicitFunctionLiteralParamWithIt.class, CodeTransformationTestGenerated.ReplaceItWithExplicitFunctionLiteralParam.class, CodeTransformationTestGenerated.RemoveBraces.class, CodeTransformationTestGenerated.AddBraces.class, CodeTransformationTestGenerated.ReplaceGetIntention.class, CodeTransformationTestGenerated.ReplaceContainsIntention.class, CodeTransformationTestGenerated.ReplaceBinaryInfixIntention.class, CodeTransformationTestGenerated.ReplaceUnaryPrefixIntention.class, CodeTransformationTestGenerated.ReplaceInvokeIntention.class, CodeTransformationTestGenerated.SimplifyNegatedBinaryExpressionIntention.class, CodeTransformationTestGenerated.ConvertNegatedBooleanSequence.class, CodeTransformationTestGenerated.ConvertNegatedExpressionWithDemorgansLaw.class, CodeTransformationTestGenerated.SwapBinaryExpression.class, CodeTransformationTestGenerated.SplitIf.class, CodeTransformationTestGenerated.ReplaceWithOperatorAssign.class}) +@InnerTestClasses({CodeTransformationTestGenerated.ElvisToIfThen.class, CodeTransformationTestGenerated.IfThenToElvis.class, CodeTransformationTestGenerated.SafeAccessToIfThen.class, CodeTransformationTestGenerated.IfThenToSafeAccess.class, 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, CodeTransformationTestGenerated.ReplaceWithInfixFunctionCall.class, CodeTransformationTestGenerated.RemoveCurlyBracesFromTemplate.class, CodeTransformationTestGenerated.MoveLambdaInsideParentheses.class, CodeTransformationTestGenerated.MoveLambdaOutsideParentheses.class, CodeTransformationTestGenerated.ReplaceExplicitFunctionLiteralParamWithIt.class, CodeTransformationTestGenerated.ReplaceItWithExplicitFunctionLiteralParam.class, CodeTransformationTestGenerated.RemoveBraces.class, CodeTransformationTestGenerated.AddBraces.class, CodeTransformationTestGenerated.ReplaceGetIntention.class, CodeTransformationTestGenerated.ReplaceContainsIntention.class, CodeTransformationTestGenerated.ReplaceBinaryInfixIntention.class, CodeTransformationTestGenerated.ReplaceUnaryPrefixIntention.class, CodeTransformationTestGenerated.ReplaceInvokeIntention.class, CodeTransformationTestGenerated.SimplifyNegatedBinaryExpressionIntention.class, CodeTransformationTestGenerated.ConvertNegatedBooleanSequence.class, CodeTransformationTestGenerated.ConvertNegatedExpressionWithDemorgansLaw.class, CodeTransformationTestGenerated.SwapBinaryExpression.class, CodeTransformationTestGenerated.SplitIf.class, CodeTransformationTestGenerated.ReplaceWithOperatorAssign.class, CodeTransformationTestGenerated.ReplaceWithTraditionalAssignment.class}) public class CodeTransformationTestGenerated extends AbstractCodeTransformationTest { @TestMetadata("idea/testData/intentions/branched/elvisToIfThen") public static class ElvisToIfThen extends AbstractCodeTransformationTest { @@ -3145,6 +3145,34 @@ public class CodeTransformationTestGenerated extends AbstractCodeTransformationT } + @TestMetadata("idea/testData/intentions/replaceWithTraditionalAssignment") + public static class ReplaceWithTraditionalAssignment extends AbstractCodeTransformationTest { + public void testAllFilesPresentInReplaceWithTraditionalAssignment() throws Exception { + JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.TestsPackage", new File("idea/testData/intentions/replaceWithTraditionalAssignment"), Pattern.compile("^(.+)\\.kt$"), true); + } + + @TestMetadata("complexRightExpression.kt") + public void testComplexRightExpression() throws Exception { + doTestReplaceWithTraditionalAssignment("idea/testData/intentions/replaceWithTraditionalAssignment/complexRightExpression.kt"); + } + + @TestMetadata("nonAssignmentExpression.kt") + public void testNonAssignmentExpression() throws Exception { + doTestReplaceWithTraditionalAssignment("idea/testData/intentions/replaceWithTraditionalAssignment/nonAssignmentExpression.kt"); + } + + @TestMetadata("nonAugmentedAssign.kt") + public void testNonAugmentedAssign() throws Exception { + doTestReplaceWithTraditionalAssignment("idea/testData/intentions/replaceWithTraditionalAssignment/nonAugmentedAssign.kt"); + } + + @TestMetadata("simple.kt") + public void testSimple() throws Exception { + doTestReplaceWithTraditionalAssignment("idea/testData/intentions/replaceWithTraditionalAssignment/simple.kt"); + } + + } + public static Test suite() { TestSuite suite = new TestSuite("CodeTransformationTestGenerated"); suite.addTestSuite(ElvisToIfThen.class); @@ -3193,6 +3221,7 @@ public class CodeTransformationTestGenerated extends AbstractCodeTransformationT suite.addTestSuite(SwapBinaryExpression.class); suite.addTestSuite(SplitIf.class); suite.addTestSuite(ReplaceWithOperatorAssign.class); + suite.addTestSuite(ReplaceWithTraditionalAssignment.class); return suite; } }