Added KT-4549 SwapBinaryExpression Intention

This commit is contained in:
kuity
2014-02-08 15:44:39 -08:00
committed by Andrey Breslav
parent 80737bdfcf
commit 48b9dcf5ae
69 changed files with 346 additions and 2 deletions
@@ -381,6 +381,7 @@ fun main(args: Array<String>) {
model("intentions/simplifyNegatedBinaryExpressionIntention", testMethod = "doTestSimplifyNegatedBinaryExpressionIntention")
model("intentions/convertNegatedBooleanSequence", testMethod="doTestConvertNegatedBooleanSequence")
model("intentions/convertNegatedExpressionWithDemorgansLaw", testMethod = "doTestConvertNegatedExpressionWithDemorgansLaw")
model("intentions/swapBinaryExpression", testMethod = "doTestSwapBinaryExpression")
}
testClass(javaClass<AbstractHierarchyTest>()) {
@@ -0,0 +1 @@
val n = <spot>y + x</spot>
@@ -0,0 +1 @@
val n = <spot>x + y</spot>
@@ -0,0 +1,5 @@
<html>
<body>
This intention swaps the operands of a binary expression.
</body>
</html>
+5
View File
@@ -624,6 +624,11 @@
<category>Kotlin</category>
</intentionAction>
<intentionAction>
<className>org.jetbrains.jet.plugin.intentions.SwapBinaryExpression</className>
<category>Kotlin</category>
</intentionAction>
<project.converterProvider implementation="org.jetbrains.jet.plugin.converters.JetRunConfigurationSettingsFormatConverterProvider"/>
</extensions>
@@ -258,6 +258,8 @@ remove.unnecessary.curly.brackets.from.string.template=Remove curly braces from
remove.unnecessary.curly.brackets.from.string.template.family=Remove curly braces from variable
insert.curly.brackets.to.string.template=Insert curly braces around variable
insert.curly.brackets.to.string.template.family=Insert curly braces around variable
swap.binary.expression=Flip Binary Expression
swap.binary.expression.family=Flip Binary Expression
add.name.to.argument.family=Add Name to Argument
add.name.to.argument.single=Add name to argument\: ''{0}''
add.name.to.argument.multiple=Add name to argument...
@@ -0,0 +1,84 @@
/*
* 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.JetBinaryExpression
import org.jetbrains.jet.lang.psi.JetPsiFactory
import org.jetbrains.jet.lang.psi.JetExpression
import org.jetbrains.jet.plugin.intentions.SwapBinaryExpression.Position.*
public class SwapBinaryExpression : JetSelfTargetingIntention<JetBinaryExpression>(
"swap.binary.expression", javaClass()
) {
enum class Position {
FIRST_LEFT
FIRST_RIGHT
NEXT_LEFT
NEXT_RIGHT
}
fun getInnermostOperand(element: JetBinaryExpression, position: Position): JetExpression? {
val left = element.getLeft()
val right = element.getRight()
if (left == null || right == null) {
return null
}
return when (position) {
FIRST_LEFT -> if (left is JetBinaryExpression) getInnermostOperand(left, NEXT_RIGHT) else left as JetExpression
FIRST_RIGHT -> if (right is JetBinaryExpression) getInnermostOperand(right, NEXT_LEFT) else right as JetExpression
NEXT_LEFT -> if (left is JetBinaryExpression) getInnermostOperand(left, NEXT_LEFT) else left as JetExpression
NEXT_RIGHT -> if (right is JetBinaryExpression) getInnermostOperand(right, NEXT_RIGHT) else right as JetExpression
}
}
override fun isApplicableTo(element: JetBinaryExpression): Boolean {
if (getInnermostOperand(element, FIRST_LEFT) == null || getInnermostOperand(element, FIRST_RIGHT) == null) {
return false
}
val operatorTextLiteral = element.getOperationReference().getText()
val approvedOperators = setOf("+", "plus", "*", "times", "||", "or", "and",
"&&", "==", "!=", "xor", ">", "<", ">=", "<=", "equals")
if (approvedOperators.contains(operatorTextLiteral)) {
setText("Flip '$operatorTextLiteral'")
return true
}
return false
}
override fun applyTo(element: JetBinaryExpression, editor: Editor) {
val operator = element.getOperationReference().getText()!!
val convertedOperator = when (operator) {
">" -> "<"
"<" -> ">"
"<=" -> ">="
">=" -> "<="
else -> operator
}
val left = getInnermostOperand(element, FIRST_LEFT)!!
val right = getInnermostOperand(element, FIRST_RIGHT)!!
val newRight = JetPsiFactory.createExpression(element.getProject(), left.getText())
val newLeft = JetPsiFactory.createExpression(element.getProject(), right.getText())
left.replace(newLeft)
right.replace(newRight)
element.replace(JetPsiFactory.createBinaryExpression(element.getProject(), element.getLeft(), convertedOperator, element.getRight()))
}
}
@@ -0,0 +1,4 @@
// IS_APPLICABLE: false
fun main() {
val testing = 5 compareTo 10
}
@@ -0,0 +1,3 @@
fun neq(a: Int, b: Int) {
if (a &&<caret> b) {}
}
@@ -0,0 +1,3 @@
fun neq(a: Int, b: Int) {
if (b && a) {}
}
@@ -0,0 +1,3 @@
fun neq(a: Int, b: Int) {
if (a <caret>and b) {}
}
@@ -0,0 +1,3 @@
fun neq(a: Int, b: Int) {
if (b and a) {}
}
@@ -0,0 +1,3 @@
fun neq(a: Int, b: Int) {
if (a <caret>|| b) {}
}
@@ -0,0 +1,3 @@
fun neq(a: Int, b: Int) {
if (b || a) {}
}
@@ -0,0 +1,3 @@
fun neq(a: Int, b: Int) {
if (a <caret>or b) {}
}
@@ -0,0 +1,3 @@
fun neq(a: Int, b: Int) {
if (b or a) {}
}
@@ -0,0 +1,4 @@
// IS_APPLICABLE: false
fun main() {
val test = 5<caret>/2
}
@@ -0,0 +1,6 @@
// IS_APPLICABLE: false
fun new(x: Int, y: Int): Int {
var c = 5
c /= <caret>10
return 1
}
@@ -0,0 +1,4 @@
// IS_APPLICABLE: false
fun main() {
val test = 5<caret> div 2
}
@@ -0,0 +1,3 @@
fun neq(a: Int, b: Int) {
if (a ==<caret> b) {}
}
@@ -0,0 +1,3 @@
fun neq(a: Int, b: Int) {
if (b == a) {}
}
@@ -0,0 +1,5 @@
// IS_APPLICABLE: false
fun main() {
var mutablevar = 20
mutablevar = <caret>10
}
@@ -0,0 +1,3 @@
fun neq(a: Int, b: Int) {
if (a equals<caret> b) {}
}
@@ -0,0 +1,3 @@
fun neq(a: Int, b: Int) {
if (b equals a) {}
}
@@ -0,0 +1,3 @@
fun main() {
val ex = 4 > <caret>5
}
@@ -0,0 +1,3 @@
fun main() {
val ex = 5 < 4
}
@@ -0,0 +1,4 @@
fun main() {
val y = 20
val ex = 5 >=<caret> y
}
@@ -0,0 +1,4 @@
fun main() {
val y = 20
val ex = y <= 5
}
@@ -0,0 +1,6 @@
// IS_APPLICABLE: false
fun main() {
for (elt<caret> in array(1, 2, 3)) {
println("Hello")
}
}
@@ -0,0 +1,8 @@
// IS_APPLICABLE: false
class Foo() {
fun cat(x: Int): Int {return x}
}
fun main() {
val catter = Foo() c<caret>at 5
}
@@ -0,0 +1,6 @@
// IS_APPLICABLE: false
fun main() {
if <caret>"test" is String {
println("Hello")
}
}
@@ -0,0 +1,3 @@
fun main() {
val ex = 4 < <caret>5
}
@@ -0,0 +1,3 @@
fun main() {
val ex = 5 > 4
}
@@ -0,0 +1,4 @@
fun main() {
val y = 20
val ex = 5 <=<caret> y
}
@@ -0,0 +1,4 @@
fun main() {
val y = 20
val ex = y >= 5
}
@@ -0,0 +1,4 @@
// IS_APPLICABLE: false
fun new(x: Int, y: Int): Int {
return y <caret>- x
}
@@ -0,0 +1,6 @@
// IS_APPLICABLE: false
fun new(x: Int, y: Int): Int {
var c = 5
c -= <caret>10
return 1
}
@@ -0,0 +1,4 @@
// IS_APPLICABLE: false
fun new(x: Int, y: Int): Int {
return y <caret>minus x
}
@@ -0,0 +1,3 @@
fun main() {
return a + b + <caret>c + d + e
}
@@ -0,0 +1,3 @@
fun main() {
return a + c + b + d + e
}
@@ -0,0 +1,3 @@
fun new(x: Int, y: Int): Int {
return y <caret>* x
}
@@ -0,0 +1,3 @@
fun new(x: Int, y: Int): Int {
return x * y
}
@@ -0,0 +1,6 @@
// IS_APPLICABLE: false
fun new(x: Int, y: Int): Int {
var c = 5
c *= <caret>10
return 1
}
@@ -0,0 +1,5 @@
// IS_APPLICABLE: false
fun main() {
val c = 500
println(<caret>"Today is Friday")
}
@@ -0,0 +1,4 @@
// IS_APPLICABLE: false
fun neq(a: Int, b: Int) {
if (<caret>a !== b) {}
}
@@ -0,0 +1,5 @@
fun main(): Boolean {
if (5 != <caret>20) {
return false
}
}
@@ -0,0 +1,5 @@
fun main(): Boolean {
if (20 != 5) {
return false
}
}
@@ -0,0 +1,6 @@
// IS_APPLICABLE: false
fun main() {
if (x !in 5..6) {
println("test")
}
}
@@ -0,0 +1,6 @@
// IS_APPLICABLE: false
fun main() {
if (x !is Int) {
println("test")
}
}
@@ -0,0 +1,4 @@
// IS_APPLICABLE: false
fun new(x: Int, y: Int): Int {
return y <caret>-
}
@@ -0,0 +1,3 @@
fun main() {
return <caret>a + b
}
@@ -0,0 +1,3 @@
fun main() {
return b + a
}
@@ -0,0 +1,6 @@
// IS_APPLICABLE: false
fun new(x: Int, y: Int): Int {
var c = 5
c += <caret>10
return 1
}
@@ -0,0 +1,3 @@
fun main() {
return <caret>a + b
}
@@ -0,0 +1,3 @@
fun main() {
return b + a
}
@@ -0,0 +1,3 @@
fun main() {
return <caret>a plus b
}
@@ -0,0 +1,3 @@
fun main() {
return b plus a
}
@@ -0,0 +1,6 @@
// IS_APPLICABLE: false
fun main() {
for (i in 1<caret>..10) {
println("Hello World")
}
}
@@ -0,0 +1,6 @@
// IS_APPLICABLE: false
fun main() {
for (i in 1<caret> rangeTo 10) {
println("Hello World")
}
}
@@ -0,0 +1,4 @@
// IS_APPLICABLE: false
fun main() {
val num = 5<caret> % 2
}
@@ -0,0 +1,6 @@
// IS_APPLICABLE: false
fun new(x: Int, y: Int): Int {
var c = 5
c %= <caret>10
return 1
}
@@ -0,0 +1,3 @@
fun new(x: Int, y: Int): Int {
return y <caret>* x
}
@@ -0,0 +1,3 @@
fun new(x: Int, y: Int): Int {
return x * y
}
@@ -0,0 +1,6 @@
// IS_APPLICABLE: false
fun new(x: Int, y: Int): Int {
var c = 5
c *= <caret>10
return 1
}
@@ -0,0 +1,3 @@
fun main() {
return <caret>a times b
}
@@ -0,0 +1,3 @@
fun main() {
return b times a
}
@@ -0,0 +1,3 @@
fun neq(a: Int, b: Int) {
if (a <caret>xor b) {}
}
@@ -0,0 +1,3 @@
fun neq(a: Int, b: Int) {
if (b xor a) {}
}
@@ -138,11 +138,12 @@ public abstract class AbstractCodeTransformationTest extends LightCodeInsightTes
public void doTestMoveLambdaInsideParentheses(@NotNull String path) throws Exception {
doTestIntention(path, new MoveLambdaInsideParenthesesIntention());
}
public void doTestMoveLambdaOutsideParentheses(@NotNull String path) throws Exception {
doTestIntention(path, new MoveLambdaOutsideParenthesesIntention());
}
public void doTestSwapBinaryExpression(@NotNull String path) throws Exception {
doTestIntention(path, new SwapBinaryExpression());
}
public void doTestConvertMemberToExtension(@NotNull String path) throws Exception {
doTestIntention(path, new ConvertMemberToExtension());
}