IDEA-129305 Settings: remove >> symbols in lists for setting groups
[idea/community.git] / python / src / com / jetbrains / python / inspections / quickfix / StatementEffectFunctionCallQuickFix.java
1 /*
2  * Copyright 2000-2013 JetBrains s.r.o.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.jetbrains.python.inspections.quickfix;
17
18 import com.intellij.codeInspection.LocalQuickFix;
19 import com.intellij.codeInspection.ProblemDescriptor;
20 import com.intellij.openapi.project.Project;
21 import com.intellij.psi.PsiComment;
22 import com.intellij.psi.PsiElement;
23 import com.intellij.psi.PsiWhiteSpace;
24 import com.intellij.psi.impl.source.tree.LeafPsiElement;
25 import com.jetbrains.python.PyBundle;
26 import com.jetbrains.python.PyNames;
27 import com.jetbrains.python.PyTokenTypes;
28 import com.jetbrains.python.psi.*;
29 import org.jetbrains.annotations.NotNull;
30
31 /**
32  * User: catherine
33  *
34  * QuickFix to replace statement that has no effect with function call
35  */
36 public class StatementEffectFunctionCallQuickFix implements LocalQuickFix {
37   @NotNull
38   public String getName() {
39     return PyBundle.message("QFIX.statement.effect");
40   }
41
42   @NotNull
43   public String getFamilyName() {
44     return getName();
45   }
46
47   public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
48     PsiElement expression = descriptor.getPsiElement();
49     if (expression != null && expression.isWritable() && expression instanceof PyReferenceExpression) {
50       final String expressionText = expression.getText();
51       if (PyNames.PRINT.equals(expressionText))
52         replacePrint(expression);
53       else if (PyNames.EXEC.equals(expressionText))
54         replaceExec(expression);
55       else
56         expression.replace(PyElementGenerator.getInstance(project).createCallExpression(LanguageLevel.forElement(expression),
57                                                                                         expressionText));
58     }
59   }
60
61   private static void replaceExec(@NotNull final PsiElement expression) {
62     final PyElementGenerator elementGenerator = PyElementGenerator.getInstance(expression.getProject());
63     final String expressionText = expression.getText();
64     final StringBuilder stringBuilder = new StringBuilder(expressionText + " (");
65
66     final PsiElement whiteSpace = expression.getContainingFile().findElementAt(expression.getTextOffset() + expression.getTextLength());
67     PsiElement next = null;
68     if (whiteSpace instanceof PsiWhiteSpace) {
69       final String whiteSpaceText = whiteSpace.getText();
70       if (!whiteSpaceText.contains("\n")) {
71         next = whiteSpace.getNextSibling();
72         while (next instanceof PsiWhiteSpace && whiteSpaceText.contains("\\")) {
73           next = next.getNextSibling();
74         }
75       }
76     }
77     else
78       next = whiteSpace;
79
80     RemoveUnnecessaryBackslashQuickFix.removeBackSlash(next);
81     if (whiteSpace != null) whiteSpace.delete();
82     if (next == null) {
83       stringBuilder.append(")");
84       expression.replace(elementGenerator.createFromText(LanguageLevel.forElement(expression), PyExpression.class,
85                                                          stringBuilder.toString()));
86       return;
87     }
88     if (next instanceof PyExpressionStatement) {
89       final PyExpression expr = ((PyExpressionStatement)next).getExpression();
90       if (expr instanceof PyBinaryExpression) {
91         addInArguments(stringBuilder, (PyBinaryExpression)expr);
92       }
93       else if (expr instanceof PyTupleExpression) {
94         final PyExpression[] elements = ((PyTupleExpression)expr).getElements();
95         if (elements.length > 1) {
96           if (elements[0] instanceof PyBinaryExpression) {
97             addInArguments(stringBuilder, (PyBinaryExpression)elements[0]);
98           }
99           stringBuilder.append(", ");
100           stringBuilder.append(elements[1].getText());
101         }
102       }
103       else {
104         stringBuilder.append(next.getText());
105       }
106     }
107     else {
108       stringBuilder.append(next.getText());
109     }
110     next.delete();
111     stringBuilder.append(")");
112     expression.replace(elementGenerator.createFromText(LanguageLevel.forElement(expression), PyExpression.class,
113                                                        stringBuilder.toString()));
114   }
115
116   private static void addInArguments(@NotNull final StringBuilder stringBuilder, @NotNull final PyBinaryExpression binaryExpression) {
117     final PsiElement operator = binaryExpression.getPsiOperator();
118     if (operator instanceof LeafPsiElement && ((LeafPsiElement)operator).getElementType() == PyTokenTypes.IN_KEYWORD) {
119       stringBuilder.append(binaryExpression.getLeftExpression().getText());
120       stringBuilder.append(", ");
121       final PyExpression rightExpression = binaryExpression.getRightExpression();
122       if (rightExpression != null)
123         stringBuilder.append(rightExpression.getText());
124     }
125   }
126
127   private static void replacePrint(@NotNull final PsiElement expression) {
128     final PyElementGenerator elementGenerator = PyElementGenerator.getInstance(expression.getProject());
129     final String expressionText = expression.getText();
130     final StringBuilder stringBuilder = new StringBuilder(expressionText + " (");
131
132     final PsiElement whiteSpace = expression.getContainingFile().findElementAt(expression.getTextOffset() + expression.getTextLength());
133     PsiElement next = null;
134     if (whiteSpace instanceof PsiWhiteSpace) {
135       final String whiteSpaceText = whiteSpace.getText();
136       if (!whiteSpaceText.contains("\n")) {
137         next = whiteSpace.getNextSibling();
138         while (next instanceof PsiWhiteSpace && whiteSpaceText.contains("\\")) {
139           next = next.getNextSibling();
140         }
141       }
142     }
143     else
144       next = whiteSpace;
145
146     RemoveUnnecessaryBackslashQuickFix.removeBackSlash(next);
147     if (whiteSpace != null) whiteSpace.delete();
148     String commentText = null;
149     if (next != null) {
150       final PsiElement lastChild = next.getLastChild();
151       if (lastChild instanceof PsiComment) {
152         commentText = lastChild.getText();
153       }
154       final String text = next instanceof PyExpressionStatement ? ((PyExpressionStatement)next).getExpression().getText() : next.getText();
155
156       stringBuilder.append(text);
157       if (text.endsWith(",")) stringBuilder.append(" end=' '");
158       next.delete();
159     }
160     stringBuilder.append(")");
161     if (commentText != null) {
162       stringBuilder.append(commentText);
163     }
164     expression.replace(elementGenerator.createFromText(LanguageLevel.forElement(expression), PyExpression.class,
165                                                        stringBuilder.toString()));
166   }
167 }