IDEA-106711 Groovy: intention: replace if with conditional

This commit is contained in:
Max Medvedev
2013-05-06 10:26:52 +04:00
parent 571641d72a
commit 356b65d2e6
7 changed files with 211 additions and 1 deletions
@@ -0,0 +1 @@
return cond() : first() : second()
@@ -0,0 +1,6 @@
<spot>if</spot> (cond()) {
return first()
}
else {
return second()
}
@@ -0,0 +1,7 @@
<html>
<body>
This intention replaces if-statement with equivalent ternary operator
<!-- tooltip end -->
Text after this comment will not be shown in tooltips.
</body>
</html>
+5
View File
@@ -1019,6 +1019,11 @@
<categoryKey>intention.category.groovy/intention.category.control.flow</categoryKey>
<className>org.jetbrains.plugins.groovy.intentions.control.ReplaceTernaryWithIfElseIntention</className>
</intentionAction>
<intentionAction>
<bundleName>org.jetbrains.plugins.groovy.intentions.GroovyIntentionsBundle</bundleName>
<categoryKey>intention.category.groovy/intention.category.control.flow</categoryKey>
<className>org.jetbrains.plugins.groovy.intentions.control.ReplaceIfWithTernaryIntention</className>
</intentionAction>
<intentionAction>
<bundleName>org.jetbrains.plugins.groovy.intentions.GroovyIntentionsBundle</bundleName>
<categoryKey>intention.category.groovy/intention.category.control.flow</categoryKey>
@@ -198,4 +198,6 @@ cannot.create.class=Cannot create class
gr.introduce.local.variable.intention.name=Introduce local variable
gr.introduce.local.variable.intention.family.name=Groovy Introduce local variable
flip.if.intention.name=Flip if statements
flip.if.intention.family.name=Flip if statements
flip.if.intention.family.name=Flip if statements
replace.if.with.ternary.intention.name=Replace with ?:
replace.if.with.ternary.intention.family.name=Replace if-statement with ternary operator
@@ -0,0 +1,117 @@
/*
* Copyright 2000-2013 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.plugins.groovy.intentions.control;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiElement;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.plugins.groovy.codeInspection.utils.EquivalenceChecker;
import org.jetbrains.plugins.groovy.intentions.base.Intention;
import org.jetbrains.plugins.groovy.intentions.base.PsiElementPredicate;
import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes;
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrBlockStatement;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrIfStatement;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.branch.GrReturnStatement;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrAssignmentExpression;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrConditionalExpression;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
/**
* @author Max Medvedev
*/
public class ReplaceIfWithTernaryIntention extends Intention {
@Override
protected void processIntention(@NotNull PsiElement element, Project project, Editor editor) throws IncorrectOperationException {
final GrIfStatement ifStatement = (GrIfStatement)element.getParent();
final PsiElement thenBranch = skipBlock(ifStatement.getThenBranch());
final PsiElement elseBranch = skipBlock(ifStatement.getElseBranch());
if (thenBranch instanceof GrAssignmentExpression && elseBranch instanceof GrAssignmentExpression) {
final GrAssignmentExpression assignment = (GrAssignmentExpression)GroovyPsiElementFactory.getInstance(project).createStatementFromText("a = b ? c : d");
assignment.getLValue().replaceWithExpression(((GrAssignmentExpression)thenBranch).getLValue(), true);
final GrConditionalExpression conditional = (GrConditionalExpression)assignment.getRValue();
replaceConditional(conditional, ifStatement.getCondition(), ((GrAssignmentExpression)thenBranch).getRValue(), ((GrAssignmentExpression)elseBranch).getRValue());
ifStatement.replaceWithStatement(assignment);
}
if (thenBranch instanceof GrReturnStatement && elseBranch instanceof GrReturnStatement) {
final GrReturnStatement returnSt = (GrReturnStatement)GroovyPsiElementFactory.getInstance(project).createStatementFromText("return a ? b : c");
final GrConditionalExpression conditional = (GrConditionalExpression)returnSt.getReturnValue();
replaceConditional(conditional, ifStatement.getCondition(), ((GrReturnStatement)thenBranch).getReturnValue(), ((GrReturnStatement)elseBranch).getReturnValue());
ifStatement.replaceWithStatement(returnSt);
}
}
@SuppressWarnings("ConstantConditions")
private static void replaceConditional(GrConditionalExpression conditional,
GrExpression condition,
GrExpression then,
GrExpression elze) {
conditional.getCondition().replaceWithExpression(condition, true);
conditional.getThenBranch().replaceWithExpression(then, true);
conditional.getElseBranch().replaceWithExpression(elze, true);
}
@NotNull
@Override
protected PsiElementPredicate getElementPredicate() {
return new PsiElementPredicate() {
@Override
public boolean satisfiedBy(PsiElement e) {
if (!e.getNode().getElementType().equals(GroovyTokenTypes.kIF)) return false;
final GrIfStatement ifStatement = (GrIfStatement)e.getParent();
final PsiElement thenBranch = skipBlock(ifStatement.getThenBranch());
final PsiElement elseBranch = skipBlock(ifStatement.getElseBranch());
if (thenBranch instanceof GrAssignmentExpression &&
elseBranch instanceof GrAssignmentExpression &&
((GrAssignmentExpression)thenBranch).getRValue() != null &&
((GrAssignmentExpression)elseBranch).getRValue() != null) {
final GrExpression lvalue1 = ((GrAssignmentExpression)thenBranch).getLValue();
final GrExpression lvalue2 = ((GrAssignmentExpression)elseBranch).getLValue();
return EquivalenceChecker.expressionsAreEquivalent(lvalue1, lvalue2);
}
if (thenBranch instanceof GrReturnStatement &&
elseBranch instanceof GrReturnStatement &&
((GrReturnStatement)thenBranch).getReturnValue() != null &&
((GrReturnStatement)elseBranch).getReturnValue() != null) {
return true;
}
return false;
}
};
}
private static PsiElement skipBlock(PsiElement e) {
if (e instanceof GrBlockStatement && ((GrBlockStatement)e).getBlock().getStatements().length == 1) {
return ((GrBlockStatement)e).getBlock().getStatements()[0];
}
else {
return e;
}
}
}
@@ -0,0 +1,72 @@
/*
* Copyright 2000-2013 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.plugins.groovy.intentions
/**
* @author Max Medvedev
*/
class ReplaceIfWithTernaryTest extends GrIntentionTestCase {
ReplaceIfWithTernaryTest() {
super('Replace with ?:')
}
public void testReturn() throws Exception {
doTextTest('''\
def foo() {
i<caret>f (cond()) {
return 'a'
}
else return 'b'
}
''', '''\
def foo() {
return cond() ? 'a' : 'b'
}
''')
}
public void testAssign() throws Exception {
doTextTest('''\
def a
i<caret>f (cond()) {
a = 'a'
}
else {
a = 'b'
}
''', '''\
def a
a = cond() ? 'a' : 'b'
''')
}
public void testAntiAssign() throws Exception {
doAntiTest('''\
def a
def b
i<caret>f (cond) {
a = 'a'
}
else {
b = 'b'
}
''')
}
}