Updated version of the "conditionalOperatorConvertor" sample plugin.
[idea/community.git] / samples / conditionalOperatorConvertor / source / com / intellij / codeInsight / intention / ConditionalOperatorConvertor.java
1 package com.intellij.codeInsight.intention;
2
3 import com.intellij.openapi.editor.Editor;
4 import com.intellij.openapi.project.Project;
5 import com.intellij.psi.*;
6 import com.intellij.psi.codeStyle.CodeStyleManager;
7 import com.intellij.psi.util.PsiTreeUtil;
8 import com.intellij.util.IncorrectOperationException;
9 import org.jetbrains.annotations.NonNls;
10 import org.jetbrains.annotations.NotNull;
11 import org.jetbrains.annotations.Nullable;
12
13 /**
14  * @author dsl
15  */
16 @NonNls public class ConditionalOperatorConvertor extends PsiElementBaseIntentionAction implements IntentionAction {
17
18   @NotNull
19   public String getText() {
20     return "Convert ternary operator to if statement";
21   }
22
23   @NotNull
24   public String getFamilyName() {
25     return getText();
26   }
27
28   public boolean isAvailable(@NotNull Project project, Editor editor, @Nullable PsiElement element) {
29     if (element == null) return false;
30     if (!element.isWritable()) return false;
31
32     if (element instanceof PsiJavaToken) {
33       final PsiJavaToken token = (PsiJavaToken)element;
34       if (token.getTokenType() != JavaTokenType.QUEST) return false;
35       if (token.getParent() instanceof PsiConditionalExpression) {
36         final PsiConditionalExpression conditionalExpression = (PsiConditionalExpression)token.getParent();
37         if (conditionalExpression.getThenExpression() == null
38             || conditionalExpression.getElseExpression() == null) {
39           return false;
40         }
41         return true;
42       }
43       return false;
44     }
45     return false;
46   }
47
48   public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
49     final int offset = editor.getCaretModel().getOffset();
50     final PsiElement element = file.findElementAt(offset);
51     PsiConditionalExpression conditionalExpression = PsiTreeUtil.getParentOfType(element,
52                                                                                  PsiConditionalExpression.class, false);
53     if (conditionalExpression == null) return;
54     if (conditionalExpression.getThenExpression() == null || conditionalExpression.getElseExpression() == null) return;
55
56     final PsiElementFactory factory = JavaPsiFacade.getInstance(project).getElementFactory();
57
58     PsiElement originalStatement = PsiTreeUtil.getParentOfType(conditionalExpression, PsiStatement.class, false);
59     while (originalStatement instanceof PsiForStatement) {
60       originalStatement = PsiTreeUtil.getParentOfType(originalStatement, PsiStatement.class, true);
61     }
62     if (originalStatement == null) return;
63
64     // Maintain declrations
65     if (originalStatement instanceof PsiDeclarationStatement) {
66       final PsiDeclarationStatement declaration = (PsiDeclarationStatement)originalStatement;
67       final PsiElement[] declaredElements = declaration.getDeclaredElements();
68       PsiLocalVariable variable = null;
69       for (PsiElement declaredElement : declaredElements) {
70         if (declaredElement instanceof PsiLocalVariable && PsiTreeUtil.isAncestor(declaredElement, conditionalExpression, true)) {
71           variable = (PsiLocalVariable)declaredElement;
72           break;
73         }
74       }
75       if (variable == null) return;
76       variable.normalizeDeclaration();
77       final Object marker = new Object();
78       PsiTreeUtil.mark(conditionalExpression, marker);
79       PsiExpressionStatement statement =
80         (PsiExpressionStatement)factory.createStatementFromText(variable.getName() + " = 0;", null);
81       statement = (PsiExpressionStatement)CodeStyleManager.getInstance(project).reformat(statement);
82       ((PsiAssignmentExpression)statement.getExpression()).getRExpression().replace(variable.getInitializer());
83       variable.getInitializer().delete();
84       final PsiElement variableParent = variable.getParent();
85       originalStatement = variableParent.getParent().addAfter(statement, variableParent);
86       conditionalExpression = (PsiConditionalExpression)PsiTreeUtil.releaseMark(originalStatement, marker);
87     }
88
89     // create then and else branches
90     final PsiElement[] originalElements = new PsiElement[]{originalStatement, conditionalExpression};
91     final PsiExpression condition = (PsiExpression)conditionalExpression.getCondition().copy();
92     final PsiElement[] thenElements = PsiTreeUtil.copyElements(originalElements);
93     final PsiElement[] elseElements = PsiTreeUtil.copyElements(originalElements);
94     thenElements[1].replace(conditionalExpression.getThenExpression());
95     elseElements[1].replace(conditionalExpression.getElseExpression());
96
97     PsiIfStatement statement = (PsiIfStatement)factory.createStatementFromText("if (true) { a = b } else { c = d }",
98                                                                                null);
99     statement = (PsiIfStatement)CodeStyleManager.getInstance(project).reformat(statement);
100     statement.getCondition().replace(condition);
101     statement = (PsiIfStatement)originalStatement.replace(statement);
102
103     ((PsiBlockStatement)statement.getThenBranch()).getCodeBlock().getStatements()[0].replace(thenElements[0]);
104     ((PsiBlockStatement)statement.getElseBranch()).getCodeBlock().getStatements()[0].replace(elseElements[0]);
105   }
106
107   public boolean startInWriteAction() {
108     return true;
109   }
110 }