From 5550924dc59d581bc9de90ba112d2774259b9611 Mon Sep 17 00:00:00 2001 From: Pradyoth Kukkapalli Date: Mon, 12 May 2014 19:39:32 +0400 Subject: [PATCH] New Intention Action: Invert If Condition Inverts the conditional expression in an if expression. --- .../jet/generators/tests/GenerateTests.kt | 1 + .../after.kt.template | 5 + .../before.kt.template | 5 + .../description.html | 5 + idea/src/META-INF/plugin.xml | 5 + .../jetbrains/jet/plugin/JetBundle.properties | 2 + .../intentions/InvertIfConditionIntention.kt | 170 ++++++++++++++++++ .../invertIfCondition/assignedToValue.kt | 4 + .../assignedToValue.kt.after | 4 + .../invertIfCondition/binaryExpression.kt | 11 ++ .../binaryExpression.kt.after | 11 ++ .../invertIfCondition/booleanLiteral.kt | 7 + .../invertIfCondition/booleanLiteral.kt.after | 5 + .../branchingIfStatements.kt | 10 ++ .../branchingIfStatements.kt.after | 10 ++ .../forLoopWithMultipleExpressions.kt | 11 ++ .../forLoopWithMultipleExpressions.kt.after | 12 ++ .../functionWithReturnExpression.kt | 9 + .../functionWithReturnExpression.kt.after | 10 ++ .../ifExpressionInsideForLoop.kt | 10 ++ .../ifExpressionInsideForLoop.kt.after | 11 ++ .../ifExpressionWithReturn.kt | 8 + .../ifExpressionWithReturn.kt.after | 8 + .../invertIfCondition/invertableOperator.kt | 5 + .../invertableOperator.kt.after | 4 + .../invertIfCondition/negatedExpression.kt | 9 + .../negatedExpression.kt.after | 8 + .../invertIfCondition/returnIfExpression.kt | 9 + .../returnIfExpression.kt.after | 9 + .../intentions/invertIfCondition/simple.kt | 9 + .../invertIfCondition/simple.kt.after | 8 + .../valueAndReturnBranches.kt | 6 + .../valueAndReturnBranches.kt.after | 6 + .../AbstractCodeTransformationTest.java | 4 + .../CodeTransformationTestGenerated.java | 76 +++++++- 35 files changed, 486 insertions(+), 1 deletion(-) create mode 100644 idea/resources/intentionDescriptions/InvertIfConditionIntention/after.kt.template create mode 100644 idea/resources/intentionDescriptions/InvertIfConditionIntention/before.kt.template create mode 100644 idea/resources/intentionDescriptions/InvertIfConditionIntention/description.html create mode 100644 idea/src/org/jetbrains/jet/plugin/intentions/InvertIfConditionIntention.kt create mode 100644 idea/testData/intentions/invertIfCondition/assignedToValue.kt create mode 100644 idea/testData/intentions/invertIfCondition/assignedToValue.kt.after create mode 100644 idea/testData/intentions/invertIfCondition/binaryExpression.kt create mode 100644 idea/testData/intentions/invertIfCondition/binaryExpression.kt.after create mode 100644 idea/testData/intentions/invertIfCondition/booleanLiteral.kt create mode 100644 idea/testData/intentions/invertIfCondition/booleanLiteral.kt.after create mode 100644 idea/testData/intentions/invertIfCondition/branchingIfStatements.kt create mode 100644 idea/testData/intentions/invertIfCondition/branchingIfStatements.kt.after create mode 100644 idea/testData/intentions/invertIfCondition/forLoopWithMultipleExpressions.kt create mode 100644 idea/testData/intentions/invertIfCondition/forLoopWithMultipleExpressions.kt.after create mode 100644 idea/testData/intentions/invertIfCondition/functionWithReturnExpression.kt create mode 100644 idea/testData/intentions/invertIfCondition/functionWithReturnExpression.kt.after create mode 100644 idea/testData/intentions/invertIfCondition/ifExpressionInsideForLoop.kt create mode 100644 idea/testData/intentions/invertIfCondition/ifExpressionInsideForLoop.kt.after create mode 100644 idea/testData/intentions/invertIfCondition/ifExpressionWithReturn.kt create mode 100644 idea/testData/intentions/invertIfCondition/ifExpressionWithReturn.kt.after create mode 100644 idea/testData/intentions/invertIfCondition/invertableOperator.kt create mode 100644 idea/testData/intentions/invertIfCondition/invertableOperator.kt.after create mode 100644 idea/testData/intentions/invertIfCondition/negatedExpression.kt create mode 100644 idea/testData/intentions/invertIfCondition/negatedExpression.kt.after create mode 100644 idea/testData/intentions/invertIfCondition/returnIfExpression.kt create mode 100644 idea/testData/intentions/invertIfCondition/returnIfExpression.kt.after create mode 100644 idea/testData/intentions/invertIfCondition/simple.kt create mode 100644 idea/testData/intentions/invertIfCondition/simple.kt.after create mode 100644 idea/testData/intentions/invertIfCondition/valueAndReturnBranches.kt create mode 100644 idea/testData/intentions/invertIfCondition/valueAndReturnBranches.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 b7cda2aeb85..071f9f7e59d 100644 --- a/generators/src/org/jetbrains/jet/generators/tests/GenerateTests.kt +++ b/generators/src/org/jetbrains/jet/generators/tests/GenerateTests.kt @@ -412,6 +412,7 @@ fun main(args: Array) { model("intentions/convertIfToAssert", testMethod = "doTestConvertIfWithThrowToAssertIntention") model("intentions/makeTypeExplicitInLambda", testMethod = "doTestMakeTypeExplicitInLambda") model("intentions/makeTypeImplicitInLambda", testMethod = "doTestMakeTypeImplicitInLambda") + model("intentions/invertIfCondition", testMethod = "doTestInvertIfCondition") model("intentions/convertToForEachLoop", testMethod = "doTestConvertToForEachLoop") model("intentions/convertToForEachFunctionCall", testMethod = "doTestConvertToForEachFunctionCall") } diff --git a/idea/resources/intentionDescriptions/InvertIfConditionIntention/after.kt.template b/idea/resources/intentionDescriptions/InvertIfConditionIntention/after.kt.template new file mode 100644 index 00000000000..a51e59905f3 --- /dev/null +++ b/idea/resources/intentionDescriptions/InvertIfConditionIntention/after.kt.template @@ -0,0 +1,5 @@ +if (foo()) { + baz() +} else { + bar() +} \ No newline at end of file diff --git a/idea/resources/intentionDescriptions/InvertIfConditionIntention/before.kt.template b/idea/resources/intentionDescriptions/InvertIfConditionIntention/before.kt.template new file mode 100644 index 00000000000..56e25521555 --- /dev/null +++ b/idea/resources/intentionDescriptions/InvertIfConditionIntention/before.kt.template @@ -0,0 +1,5 @@ +if (!foo()) { + bar() +} else { + baz() +} \ No newline at end of file diff --git a/idea/resources/intentionDescriptions/InvertIfConditionIntention/description.html b/idea/resources/intentionDescriptions/InvertIfConditionIntention/description.html new file mode 100644 index 00000000000..84d252b7b4e --- /dev/null +++ b/idea/resources/intentionDescriptions/InvertIfConditionIntention/description.html @@ -0,0 +1,5 @@ + + +This intention inverts the conditional expression in an 'if' expression. + + \ No newline at end of file diff --git a/idea/src/META-INF/plugin.xml b/idea/src/META-INF/plugin.xml index 4aec75214d2..23549465e2b 100644 --- a/idea/src/META-INF/plugin.xml +++ b/idea/src/META-INF/plugin.xml @@ -741,6 +741,11 @@ level="WARNING" /> + + org.jetbrains.jet.plugin.intentions.InvertIfConditionIntention + Kotlin + + diff --git a/idea/src/org/jetbrains/jet/plugin/JetBundle.properties b/idea/src/org/jetbrains/jet/plugin/JetBundle.properties index 942e3a1bf9b..c9161beb75a 100644 --- a/idea/src/org/jetbrains/jet/plugin/JetBundle.properties +++ b/idea/src/org/jetbrains/jet/plugin/JetBundle.properties @@ -312,6 +312,8 @@ make.type.explicit.in.lambda=Make types explicit in lambda make.type.explicit.in.lambda.family=Make Types Explicit In Lambda make.type.implicit.in.lambda=Make types implicit in lambda (may break code) make.type.implicit.in.lambda.family=Make Types Implicit In Lambda (May Break Code) +invert.if.condition=Invert If Condition +invert.if.condition.family=Invert If Condition convert.to.for.each.loop.intention=Replace with a for each loop convert.to.for.each.loop.intention.family=Replace with a For Each Loop convert.to.for.each.function.call.intention=Replace with a forEach function call diff --git a/idea/src/org/jetbrains/jet/plugin/intentions/InvertIfConditionIntention.kt b/idea/src/org/jetbrains/jet/plugin/intentions/InvertIfConditionIntention.kt new file mode 100644 index 00000000000..d2e520403e9 --- /dev/null +++ b/idea/src/org/jetbrains/jet/plugin/intentions/InvertIfConditionIntention.kt @@ -0,0 +1,170 @@ +/* + * 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.JetIfExpression +import com.intellij.openapi.editor.Editor +import org.jetbrains.jet.lang.psi.JetExpression +import org.jetbrains.jet.lang.psi.JetUnaryExpression +import org.jetbrains.jet.lang.psi.JetBinaryExpression +import org.jetbrains.jet.lexer.JetTokens +import org.jetbrains.jet.lexer.JetToken +import com.intellij.psi.tree.IElementType +import org.jetbrains.jet.lang.psi.JetConstantExpression +import org.jetbrains.jet.lang.psi.JetPsiFactory +import org.jetbrains.jet.lang.psi.JetPsiUtil +import org.jetbrains.jet.lang.psi.JetParenthesizedExpression +import com.sun.javaws.exceptions.InvalidArgumentException +import org.jetbrains.jet.lexer.JetSingleValueToken +import org.jetbrains.jet.lexer.JetKeywordToken +import org.jetbrains.jet.lang.psi.psiUtil.getParentByType +import org.jetbrains.jet.lang.psi.JetElement +import org.jetbrains.jet.lang.psi.JetForExpression +import org.jetbrains.jet.lang.psi.JetNamedFunction +import org.jetbrains.jet.lang.psi.JetBlockExpression + +public class InvertIfConditionIntention : JetSelfTargetingIntention("invert.if.condition", javaClass()) { + fun checkForNegation(element: JetUnaryExpression): Boolean { + return element.getOperationReference().getReferencedName().equals("!") + } + + override fun isApplicableTo(element: JetIfExpression): Boolean { + val condition = element.getCondition() + val thenBranch = element.getThen() + + return condition != null && thenBranch != null && when (condition) { + is JetUnaryExpression -> { + when { + checkForNegation(condition) -> { + val baseExpression = condition.getBaseExpression() + + when (baseExpression) { + is JetParenthesizedExpression -> baseExpression.getExpression() != null + else -> condition.getBaseExpression() != null + } + } + else -> true + } + } + is JetBinaryExpression -> { + condition.getOperationToken() != null && condition.getLeft() != null && condition.getRight() != null + } + else -> true + } + } + + override fun applyTo(element: JetIfExpression, editor: Editor) { + fun isNegatableOperator(token: IElementType): Boolean { + return token in array(JetTokens.EQEQ, JetTokens.EXCLEQ, JetTokens.EQEQEQ, JetTokens.EXCLEQEQEQ, JetTokens.IS_KEYWORD, JetTokens.NOT_IS, JetTokens.IN_KEYWORD, JetTokens.NOT_IN, JetTokens.LT, JetTokens.LTEQ, JetTokens.GT, JetTokens.GTEQ) + } + + fun getNegatedOperator(token: IElementType): JetToken { + return when { + token == JetTokens.EQEQ -> JetTokens.EXCLEQ + token == JetTokens.EXCLEQ -> JetTokens.EQEQ + token == JetTokens.EQEQEQ -> JetTokens.EXCLEQEQEQ + token == JetTokens.EXCLEQEQEQ -> JetTokens.EQEQEQ + token == JetTokens.IS_KEYWORD -> JetTokens.NOT_IS + token == JetTokens.NOT_IS -> JetTokens.IS_KEYWORD + token == JetTokens.IN_KEYWORD -> JetTokens.NOT_IN + token == JetTokens.NOT_IN -> JetTokens.IN_KEYWORD + token == JetTokens.LT -> JetTokens.GTEQ + token == JetTokens.LTEQ -> JetTokens.GT + token == JetTokens.GT -> JetTokens.LTEQ + token == JetTokens.GTEQ -> JetTokens.LT + else -> throw InvalidArgumentException(array("The token, \"${token.toString()}\", does not have a negated equivalent.")) + } + } + + fun getTokenText(token: JetToken): String { + return when (token) { + is JetSingleValueToken -> token.getValue() + is JetKeywordToken -> token.getValue() + else -> throw InvalidArgumentException(array("The token, ${token.toString()}, does not have an applicable string value.")) + } + } + + fun negateExpressionText(element: JetExpression): String { + val negatedParenthesizedExpressionText = "!(${element.getText()})" + val possibleNewExpression = JetPsiFactory.createExpression(element.getProject(), negatedParenthesizedExpressionText) as JetUnaryExpression + val innerExpression = possibleNewExpression.getBaseExpression() as JetParenthesizedExpression + + return when { + JetPsiUtil.areParenthesesUseless(innerExpression) -> "!${element.getText()}" + else -> negatedParenthesizedExpressionText + } + } + + fun getNegation(element: JetExpression): JetExpression { + return JetPsiFactory.createExpression(element.getProject(), when (element) { + is JetBinaryExpression -> { + val operator = element.getOperationToken()!! + + when { + isNegatableOperator(operator) -> "${element.getLeft()!!.getText()} ${getTokenText(getNegatedOperator(operator))} ${element.getRight()!!.getText()}" + else -> negateExpressionText(element) + } + } + is JetConstantExpression -> { + when { + element.textMatches("true") -> "false" + element.textMatches("false") -> "true" + else -> negateExpressionText(element) + } + } + else -> negateExpressionText(element) + }) + } + + fun removeNegation(element: JetUnaryExpression): JetExpression { + val baseExpression = element.getBaseExpression()!! + + return when (baseExpression) { + is JetParenthesizedExpression -> baseExpression.getExpression()!! + else -> baseExpression + } + } + + fun getFinalExpressionOfFunction(element: JetNamedFunction): JetExpression? { + val body = element.getBodyExpression() + + return when (body) { + is JetBlockExpression -> body.getStatements().last() as JetExpression + else -> body + } + } + + val condition = element.getCondition()!! + val replacementCondition = when (condition) { + is JetUnaryExpression -> { + when { + checkForNegation(condition) -> removeNegation(condition) + else -> getNegation(condition) + } + } + else -> getNegation(condition) + } + + val thenBranch = element.getThen() + val elseBranch = element.getElse() ?: JetPsiFactory.createEmptyBody(element.getProject()) + + element.replace(JetPsiFactory.createIf(element.getProject(), replacementCondition, when (elseBranch) { + is JetIfExpression -> JetPsiFactory.wrapInABlock(elseBranch) + else -> elseBranch + }, if (thenBranch is JetBlockExpression && thenBranch.getStatements().isEmpty()) null else thenBranch)) + } +} \ No newline at end of file diff --git a/idea/testData/intentions/invertIfCondition/assignedToValue.kt b/idea/testData/intentions/invertIfCondition/assignedToValue.kt new file mode 100644 index 00000000000..f15f416d907 --- /dev/null +++ b/idea/testData/intentions/invertIfCondition/assignedToValue.kt @@ -0,0 +1,4 @@ +fun main() { + val a = -1 + val t = if (a > 0) a else -a +} \ No newline at end of file diff --git a/idea/testData/intentions/invertIfCondition/assignedToValue.kt.after b/idea/testData/intentions/invertIfCondition/assignedToValue.kt.after new file mode 100644 index 00000000000..7831104f66f --- /dev/null +++ b/idea/testData/intentions/invertIfCondition/assignedToValue.kt.after @@ -0,0 +1,4 @@ +fun main() { + val a = -1 + val t = if (a <= 0) -a else a +} \ No newline at end of file diff --git a/idea/testData/intentions/invertIfCondition/binaryExpression.kt b/idea/testData/intentions/invertIfCondition/binaryExpression.kt new file mode 100644 index 00000000000..560f931d24a --- /dev/null +++ b/idea/testData/intentions/invertIfCondition/binaryExpression.kt @@ -0,0 +1,11 @@ +fun foo(): Boolean { + return true +} + +fun main() { + if (foo() && foo()) { + foo() + } else { + foo() + } +} \ No newline at end of file diff --git a/idea/testData/intentions/invertIfCondition/binaryExpression.kt.after b/idea/testData/intentions/invertIfCondition/binaryExpression.kt.after new file mode 100644 index 00000000000..02016d6baec --- /dev/null +++ b/idea/testData/intentions/invertIfCondition/binaryExpression.kt.after @@ -0,0 +1,11 @@ +fun foo(): Boolean { + return true +} + +fun main() { + if (!(foo() && foo())) { + foo() + } else { + foo() + } +} \ No newline at end of file diff --git a/idea/testData/intentions/invertIfCondition/booleanLiteral.kt b/idea/testData/intentions/invertIfCondition/booleanLiteral.kt new file mode 100644 index 00000000000..696a859d5c2 --- /dev/null +++ b/idea/testData/intentions/invertIfCondition/booleanLiteral.kt @@ -0,0 +1,7 @@ +fun main() { + if (true) { + + } else { + + } +} diff --git a/idea/testData/intentions/invertIfCondition/booleanLiteral.kt.after b/idea/testData/intentions/invertIfCondition/booleanLiteral.kt.after new file mode 100644 index 00000000000..8480d11f066 --- /dev/null +++ b/idea/testData/intentions/invertIfCondition/booleanLiteral.kt.after @@ -0,0 +1,5 @@ +fun main() { + if (false) { + + } +} diff --git a/idea/testData/intentions/invertIfCondition/branchingIfStatements.kt b/idea/testData/intentions/invertIfCondition/branchingIfStatements.kt new file mode 100644 index 00000000000..2d5754ee139 --- /dev/null +++ b/idea/testData/intentions/invertIfCondition/branchingIfStatements.kt @@ -0,0 +1,10 @@ +fun main() { + val a = 10 + + if (a > 0) + a + else if (a < -5) + a + 1 + else + a + 2 +} \ No newline at end of file diff --git a/idea/testData/intentions/invertIfCondition/branchingIfStatements.kt.after b/idea/testData/intentions/invertIfCondition/branchingIfStatements.kt.after new file mode 100644 index 00000000000..c08f0ff13a3 --- /dev/null +++ b/idea/testData/intentions/invertIfCondition/branchingIfStatements.kt.after @@ -0,0 +1,10 @@ +fun main() { + val a = 10 + + if (a <= 0) { + if (a < -5) + a + 1 + else + a + 2 + } else a +} \ No newline at end of file diff --git a/idea/testData/intentions/invertIfCondition/forLoopWithMultipleExpressions.kt b/idea/testData/intentions/invertIfCondition/forLoopWithMultipleExpressions.kt new file mode 100644 index 00000000000..909da693976 --- /dev/null +++ b/idea/testData/intentions/invertIfCondition/forLoopWithMultipleExpressions.kt @@ -0,0 +1,11 @@ +// WITH_RUNTIME +fun main() { + val list = 1..4 + + for (x in list) { + if (x == 2) { + list + } + list.equals(list) + } +} \ No newline at end of file diff --git a/idea/testData/intentions/invertIfCondition/forLoopWithMultipleExpressions.kt.after b/idea/testData/intentions/invertIfCondition/forLoopWithMultipleExpressions.kt.after new file mode 100644 index 00000000000..6c4002a4e01 --- /dev/null +++ b/idea/testData/intentions/invertIfCondition/forLoopWithMultipleExpressions.kt.after @@ -0,0 +1,12 @@ +// WITH_RUNTIME +fun main() { + val list = 1..4 + + for (x in list) { + if (x != 2) { + } else { + list + } + list.equals(list) + } +} \ No newline at end of file diff --git a/idea/testData/intentions/invertIfCondition/functionWithReturnExpression.kt b/idea/testData/intentions/invertIfCondition/functionWithReturnExpression.kt new file mode 100644 index 00000000000..a94169951d9 --- /dev/null +++ b/idea/testData/intentions/invertIfCondition/functionWithReturnExpression.kt @@ -0,0 +1,9 @@ +fun foo(): Int { + val x = 0 + + if (x == 1) { + x + 1 + } + + return x +} \ No newline at end of file diff --git a/idea/testData/intentions/invertIfCondition/functionWithReturnExpression.kt.after b/idea/testData/intentions/invertIfCondition/functionWithReturnExpression.kt.after new file mode 100644 index 00000000000..94639b414f9 --- /dev/null +++ b/idea/testData/intentions/invertIfCondition/functionWithReturnExpression.kt.after @@ -0,0 +1,10 @@ +fun foo(): Int { + val x = 0 + + if (x != 1) { + } else { + x + 1 + } + + return x +} \ No newline at end of file diff --git a/idea/testData/intentions/invertIfCondition/ifExpressionInsideForLoop.kt b/idea/testData/intentions/invertIfCondition/ifExpressionInsideForLoop.kt new file mode 100644 index 00000000000..a0b806d93b8 --- /dev/null +++ b/idea/testData/intentions/invertIfCondition/ifExpressionInsideForLoop.kt @@ -0,0 +1,10 @@ +// WITH_RUNTIME +fun main() { + val list = 1..4 + + for (x in list) { + if (x == 2) { + list + } + } +} \ No newline at end of file diff --git a/idea/testData/intentions/invertIfCondition/ifExpressionInsideForLoop.kt.after b/idea/testData/intentions/invertIfCondition/ifExpressionInsideForLoop.kt.after new file mode 100644 index 00000000000..75e181c964d --- /dev/null +++ b/idea/testData/intentions/invertIfCondition/ifExpressionInsideForLoop.kt.after @@ -0,0 +1,11 @@ +// WITH_RUNTIME +fun main() { + val list = 1..4 + + for (x in list) { + if (x != 2) { + } else { + list + } + } +} \ No newline at end of file diff --git a/idea/testData/intentions/invertIfCondition/ifExpressionWithReturn.kt b/idea/testData/intentions/invertIfCondition/ifExpressionWithReturn.kt new file mode 100644 index 00000000000..23f07e73a5f --- /dev/null +++ b/idea/testData/intentions/invertIfCondition/ifExpressionWithReturn.kt @@ -0,0 +1,8 @@ +fun foo(): Int { + val x = 0 + + if (x == 1) + return x + 1 + + return 0 +} \ No newline at end of file diff --git a/idea/testData/intentions/invertIfCondition/ifExpressionWithReturn.kt.after b/idea/testData/intentions/invertIfCondition/ifExpressionWithReturn.kt.after new file mode 100644 index 00000000000..847267c7430 --- /dev/null +++ b/idea/testData/intentions/invertIfCondition/ifExpressionWithReturn.kt.after @@ -0,0 +1,8 @@ +fun foo(): Int { + val x = 0 + + if (x != 1) { + } else return x + 1 + + return 0 +} \ No newline at end of file diff --git a/idea/testData/intentions/invertIfCondition/invertableOperator.kt b/idea/testData/intentions/invertIfCondition/invertableOperator.kt new file mode 100644 index 00000000000..341005d872e --- /dev/null +++ b/idea/testData/intentions/invertIfCondition/invertableOperator.kt @@ -0,0 +1,5 @@ +fun main() { + if (true == false) { + + } +} \ No newline at end of file diff --git a/idea/testData/intentions/invertIfCondition/invertableOperator.kt.after b/idea/testData/intentions/invertIfCondition/invertableOperator.kt.after new file mode 100644 index 00000000000..7575021022e --- /dev/null +++ b/idea/testData/intentions/invertIfCondition/invertableOperator.kt.after @@ -0,0 +1,4 @@ +fun main() { + if (true != false) { + } +} \ No newline at end of file diff --git a/idea/testData/intentions/invertIfCondition/negatedExpression.kt b/idea/testData/intentions/invertIfCondition/negatedExpression.kt new file mode 100644 index 00000000000..ca889c11b42 --- /dev/null +++ b/idea/testData/intentions/invertIfCondition/negatedExpression.kt @@ -0,0 +1,9 @@ +fun foo(): Boolean { + return true +} + +fun main() { + if (!foo()) { + + } +} \ No newline at end of file diff --git a/idea/testData/intentions/invertIfCondition/negatedExpression.kt.after b/idea/testData/intentions/invertIfCondition/negatedExpression.kt.after new file mode 100644 index 00000000000..e4d069162c8 --- /dev/null +++ b/idea/testData/intentions/invertIfCondition/negatedExpression.kt.after @@ -0,0 +1,8 @@ +fun foo(): Boolean { + return true +} + +fun main() { + if (foo()) { + } +} \ No newline at end of file diff --git a/idea/testData/intentions/invertIfCondition/returnIfExpression.kt b/idea/testData/intentions/invertIfCondition/returnIfExpression.kt new file mode 100644 index 00000000000..5fbb7686940 --- /dev/null +++ b/idea/testData/intentions/invertIfCondition/returnIfExpression.kt @@ -0,0 +1,9 @@ +fun foo(): Int { + val a = 10 + + return if (a > 0) { + a + } else { + a + 1 + } +} \ No newline at end of file diff --git a/idea/testData/intentions/invertIfCondition/returnIfExpression.kt.after b/idea/testData/intentions/invertIfCondition/returnIfExpression.kt.after new file mode 100644 index 00000000000..a2be084c514 --- /dev/null +++ b/idea/testData/intentions/invertIfCondition/returnIfExpression.kt.after @@ -0,0 +1,9 @@ +fun foo(): Int { + val a = 10 + + return if (a <= 0) { + a + 1 + } else { + a + } +} \ No newline at end of file diff --git a/idea/testData/intentions/invertIfCondition/simple.kt b/idea/testData/intentions/invertIfCondition/simple.kt new file mode 100644 index 00000000000..109e6c6fb7a --- /dev/null +++ b/idea/testData/intentions/invertIfCondition/simple.kt @@ -0,0 +1,9 @@ +fun foo(): Boolean { + return true +} + +fun main() { + if (foo()) { + + } +} \ No newline at end of file diff --git a/idea/testData/intentions/invertIfCondition/simple.kt.after b/idea/testData/intentions/invertIfCondition/simple.kt.after new file mode 100644 index 00000000000..97f9907aad2 --- /dev/null +++ b/idea/testData/intentions/invertIfCondition/simple.kt.after @@ -0,0 +1,8 @@ +fun foo(): Boolean { + return true +} + +fun main() { + if (!foo()) { + } +} \ No newline at end of file diff --git a/idea/testData/intentions/invertIfCondition/valueAndReturnBranches.kt b/idea/testData/intentions/invertIfCondition/valueAndReturnBranches.kt new file mode 100644 index 00000000000..69bac3765cf --- /dev/null +++ b/idea/testData/intentions/invertIfCondition/valueAndReturnBranches.kt @@ -0,0 +1,6 @@ +fun foo(): Int { + val a = 1 + val t = if (a > 1) a else return 0 + + return t +} \ No newline at end of file diff --git a/idea/testData/intentions/invertIfCondition/valueAndReturnBranches.kt.after b/idea/testData/intentions/invertIfCondition/valueAndReturnBranches.kt.after new file mode 100644 index 00000000000..fa93f7dd340 --- /dev/null +++ b/idea/testData/intentions/invertIfCondition/valueAndReturnBranches.kt.after @@ -0,0 +1,6 @@ +fun foo(): Int { + val a = 1 + val t = if (a <= 1) return 0 else a + + return t +} \ 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 3c807bcdf24..dce19dd0184 100644 --- a/idea/tests/org/jetbrains/jet/plugin/intentions/AbstractCodeTransformationTest.java +++ b/idea/tests/org/jetbrains/jet/plugin/intentions/AbstractCodeTransformationTest.java @@ -258,6 +258,10 @@ public abstract class AbstractCodeTransformationTest extends LightCodeInsightTes doTestIntention(path, new SimplifyBooleanWithConstantsIntention()); } + public void doTestInvertIfCondition(@NotNull String path) throws Exception { + doTestIntention(path, new InvertIfConditionIntention()); + } + public void doTestMakeTypeExplicitInLambda(@NotNull String path) throws Exception { doTestIntention(path, new MakeTypeExplicitInLambdaIntention()); } diff --git a/idea/tests/org/jetbrains/jet/plugin/intentions/CodeTransformationTestGenerated.java b/idea/tests/org/jetbrains/jet/plugin/intentions/CodeTransformationTestGenerated.java index f1fdf1a6ed1..bda793cdf5e 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.DoubleBangToIfThen.class, CodeTransformationTestGenerated.IfThenToDoubleBang.class, 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, CodeTransformationTestGenerated.SimplifyBooleanWithConstants.class, CodeTransformationTestGenerated.InsertExplicitTypeArguments.class, CodeTransformationTestGenerated.RemoveExplicitTypeArguments.class, CodeTransformationTestGenerated.ConvertAssertToIf.class, CodeTransformationTestGenerated.ConvertIfToAssert.class, CodeTransformationTestGenerated.MakeTypeExplicitInLambda.class, CodeTransformationTestGenerated.MakeTypeImplicitInLambda.class, CodeTransformationTestGenerated.ConvertToForEachLoop.class, CodeTransformationTestGenerated.ConvertToForEachFunctionCall.class}) +@InnerTestClasses({CodeTransformationTestGenerated.DoubleBangToIfThen.class, CodeTransformationTestGenerated.IfThenToDoubleBang.class, 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, CodeTransformationTestGenerated.SimplifyBooleanWithConstants.class, CodeTransformationTestGenerated.InsertExplicitTypeArguments.class, CodeTransformationTestGenerated.RemoveExplicitTypeArguments.class, CodeTransformationTestGenerated.ConvertAssertToIf.class, CodeTransformationTestGenerated.ConvertIfToAssert.class, CodeTransformationTestGenerated.MakeTypeExplicitInLambda.class, CodeTransformationTestGenerated.MakeTypeImplicitInLambda.class, CodeTransformationTestGenerated.InvertIfCondition.class, CodeTransformationTestGenerated.ConvertToForEachLoop.class, CodeTransformationTestGenerated.ConvertToForEachFunctionCall.class}) public class CodeTransformationTestGenerated extends AbstractCodeTransformationTest { @TestMetadata("idea/testData/intentions/branched/doubleBangToIfThen") public static class DoubleBangToIfThen extends AbstractCodeTransformationTest { @@ -4140,6 +4140,79 @@ public class CodeTransformationTestGenerated extends AbstractCodeTransformationT } + @TestMetadata("idea/testData/intentions/invertIfCondition") + public static class InvertIfCondition extends AbstractCodeTransformationTest { + public void testAllFilesPresentInInvertIfCondition() throws Exception { + JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.TestsPackage", new File("idea/testData/intentions/invertIfCondition"), Pattern.compile("^(.+)\\.kt$"), true); + } + + @TestMetadata("assignedToValue.kt") + public void testAssignedToValue() throws Exception { + doTestInvertIfCondition("idea/testData/intentions/invertIfCondition/assignedToValue.kt"); + } + + @TestMetadata("binaryExpression.kt") + public void testBinaryExpression() throws Exception { + doTestInvertIfCondition("idea/testData/intentions/invertIfCondition/binaryExpression.kt"); + } + + @TestMetadata("booleanLiteral.kt") + public void testBooleanLiteral() throws Exception { + doTestInvertIfCondition("idea/testData/intentions/invertIfCondition/booleanLiteral.kt"); + } + + @TestMetadata("branchingIfStatements.kt") + public void testBranchingIfStatements() throws Exception { + doTestInvertIfCondition("idea/testData/intentions/invertIfCondition/branchingIfStatements.kt"); + } + + @TestMetadata("forLoopWithMultipleExpressions.kt") + public void testForLoopWithMultipleExpressions() throws Exception { + doTestInvertIfCondition("idea/testData/intentions/invertIfCondition/forLoopWithMultipleExpressions.kt"); + } + + @TestMetadata("functionWithReturnExpression.kt") + public void testFunctionWithReturnExpression() throws Exception { + doTestInvertIfCondition("idea/testData/intentions/invertIfCondition/functionWithReturnExpression.kt"); + } + + @TestMetadata("ifExpressionInsideForLoop.kt") + public void testIfExpressionInsideForLoop() throws Exception { + doTestInvertIfCondition("idea/testData/intentions/invertIfCondition/ifExpressionInsideForLoop.kt"); + } + + @TestMetadata("ifExpressionWithReturn.kt") + public void testIfExpressionWithReturn() throws Exception { + doTestInvertIfCondition("idea/testData/intentions/invertIfCondition/ifExpressionWithReturn.kt"); + } + + @TestMetadata("invertableOperator.kt") + public void testInvertableOperator() throws Exception { + doTestInvertIfCondition("idea/testData/intentions/invertIfCondition/invertableOperator.kt"); + } + + @TestMetadata("negatedExpression.kt") + public void testNegatedExpression() throws Exception { + doTestInvertIfCondition("idea/testData/intentions/invertIfCondition/negatedExpression.kt"); + } + + @TestMetadata("returnIfExpression.kt") + public void testReturnIfExpression() throws Exception { + doTestInvertIfCondition("idea/testData/intentions/invertIfCondition/returnIfExpression.kt"); + } + + @TestMetadata("simple.kt") + public void testSimple() throws Exception { + doTestInvertIfCondition("idea/testData/intentions/invertIfCondition/simple.kt"); + } + + @TestMetadata("valueAndReturnBranches.kt") + public void testValueAndReturnBranches() throws Exception { + doTestInvertIfCondition("idea/testData/intentions/invertIfCondition/valueAndReturnBranches.kt"); + } + + } + @TestMetadata("idea/testData/intentions/convertToForEachLoop") public static class ConvertToForEachLoop extends AbstractCodeTransformationTest { public void testAllFilesPresentInConvertToForEachLoop() throws Exception { @@ -4299,6 +4372,7 @@ public class CodeTransformationTestGenerated extends AbstractCodeTransformationT suite.addTestSuite(ConvertIfToAssert.class); suite.addTestSuite(MakeTypeExplicitInLambda.class); suite.addTestSuite(MakeTypeImplicitInLambda.class); + suite.addTestSuite(InvertIfCondition.class); suite.addTestSuite(ConvertToForEachLoop.class); suite.addTestSuite(ConvertToForEachFunctionCall.class); return suite;