http://ea.jetbrains.com/browser/ea_problems/17072 (IOE: PsiJavaParserFacadeImpl.creat...
[fedora-idea.git] / plugins / InspectionGadgets / src / com / siyeh / ig / j2me / SimplifiableIfStatementInspection.java
blob5478256ee4360f0e9457e6195d3ce5ecd905b3f2
1 /*
2 * Copyright 2006-2007 Bas Leijdekkers
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
16 package com.siyeh.ig.j2me;
18 import com.intellij.codeInspection.ProblemDescriptor;
19 import com.intellij.openapi.project.Project;
20 import com.intellij.psi.*;
21 import com.intellij.psi.tree.IElementType;
22 import com.intellij.psi.util.PsiTreeUtil;
23 import com.intellij.util.IncorrectOperationException;
24 import com.siyeh.InspectionGadgetsBundle;
25 import com.siyeh.ig.BaseInspection;
26 import com.siyeh.ig.BaseInspectionVisitor;
27 import com.siyeh.ig.InspectionGadgetsFix;
28 import com.siyeh.ig.psiutils.BoolUtils;
29 import com.siyeh.ig.psiutils.ControlFlowUtils;
30 import com.siyeh.ig.psiutils.EquivalenceChecker;
31 import com.siyeh.ig.psiutils.ParenthesesUtils;
32 import org.jetbrains.annotations.NonNls;
33 import org.jetbrains.annotations.NotNull;
34 import org.jetbrains.annotations.Nullable;
36 public class SimplifiableIfStatementInspection extends BaseInspection {
38 @NotNull
39 public String getDisplayName() {
40 return InspectionGadgetsBundle.message(
41 "simplifiable.if.statement.display.name");
44 public boolean isEnabledByDefault() {
45 return true;
48 public BaseInspectionVisitor buildVisitor() {
49 return new SimplifiableIfStatementVisitor();
52 @NotNull
53 public String buildErrorString(Object... infos) {
54 final PsiIfStatement statement = (PsiIfStatement)infos[0];
55 return InspectionGadgetsBundle.message(
56 "simplifiable.if.statement.problem.descriptor",
57 calculateReplacementStatement(statement));
60 @NonNls
61 static String calculateReplacementStatement(
62 PsiIfStatement statement) {
63 PsiStatement thenBranch = statement.getThenBranch();
64 thenBranch = ControlFlowUtils.stripBraces(thenBranch);
65 if (thenBranch == null) {
66 return "";
68 PsiStatement elseBranch = statement.getElseBranch();
69 elseBranch = ControlFlowUtils.stripBraces(elseBranch);
70 if (elseBranch == null) {
71 final PsiElement nextStatement =
72 PsiTreeUtil.skipSiblingsForward(statement,
73 PsiWhiteSpace.class);
74 if (nextStatement instanceof PsiStatement) {
75 elseBranch = (PsiStatement)nextStatement;
78 if (elseBranch == null) {
79 return "";
81 final PsiExpression condition = statement.getCondition();
82 if (condition == null) {
83 return "";
85 if (elseBranch instanceof PsiReturnStatement) {
86 return calculateReplacementReturnStatement(thenBranch, elseBranch,
87 condition);
89 final PsiExpressionStatement thenStatement =
90 (PsiExpressionStatement)thenBranch;
91 final PsiExpressionStatement elseStatement =
92 (PsiExpressionStatement)elseBranch;
93 final PsiAssignmentExpression thenAssignment =
94 (PsiAssignmentExpression)thenStatement.getExpression();
95 final PsiAssignmentExpression elseAssignment =
96 (PsiAssignmentExpression)elseStatement.getExpression();
97 return calculateReplacementAssignmentStatement(thenAssignment,
98 elseAssignment, condition);
101 private static String calculateReplacementAssignmentStatement(
102 PsiAssignmentExpression thenAssignment,
103 PsiAssignmentExpression elseAssignment, PsiExpression condition) {
104 final PsiExpression lhs = thenAssignment.getLExpression();
105 final PsiExpression thenRhs = thenAssignment.getRExpression();
106 if (thenRhs == null) {
107 return "";
109 final PsiExpression elseRhs = elseAssignment.getRExpression();
110 if (elseRhs == null) {
111 return "";
113 final PsiJavaToken token = elseAssignment.getOperationSign();
114 if (BoolUtils.isTrue(thenRhs)) {
115 if (ParenthesesUtils.getPrecedence(elseRhs) >
116 ParenthesesUtils.OR_PRECEDENCE) {
117 return lhs.getText() + ' ' + token.getText() + ' ' +
118 condition.getText() + " || (" + elseRhs.getText() + ");";
119 } else {
120 return lhs.getText() + ' ' + token.getText() + ' ' +
121 condition.getText() + " || " + elseRhs.getText() + ';';
123 } else if (BoolUtils.isFalse(thenRhs)) {
124 if (ParenthesesUtils.getPrecedence(elseRhs) >
125 ParenthesesUtils.AND_PRECEDENCE) {
126 return lhs.getText() + ' ' + token.getText() + ' ' +
127 BoolUtils.getNegatedExpressionText(condition) +
128 " && (" + elseRhs.getText() + ");";
129 } else {
130 return lhs.getText() + ' ' + token.getText() + ' ' +
131 BoolUtils.getNegatedExpressionText(condition) + " && " +
132 elseRhs.getText() + ';';
135 if (BoolUtils.isTrue(elseRhs)) {
136 if (ParenthesesUtils.getPrecedence(thenRhs) >
137 ParenthesesUtils.OR_PRECEDENCE) {
138 return lhs.getText() + ' ' + token.getText() + ' ' +
139 BoolUtils.getNegatedExpressionText(condition) +
140 " || (" + thenRhs.getText() + ");";
141 } else {
142 return lhs.getText() + ' ' + token.getText() + ' ' +
143 BoolUtils.getNegatedExpressionText(condition) + " || " +
144 thenRhs.getText() + ';';
146 } else {
147 final String conditionText;
148 if (ParenthesesUtils.getPrecedence(condition) >
149 ParenthesesUtils.AND_PRECEDENCE) {
150 conditionText = '(' + condition.getText() + ')';
151 } else {
152 conditionText = condition.getText();
154 if (ParenthesesUtils.getPrecedence(thenRhs) >
155 ParenthesesUtils.AND_PRECEDENCE) {
156 return lhs.getText() + ' ' + token.getText() + ' ' +
157 conditionText + " && (" + thenRhs.getText() + ");";
158 } else {
159 return lhs.getText() + ' ' + token.getText() + ' ' +
160 conditionText + " && " + thenRhs.getText() + ';';
165 @NonNls
166 private static String calculateReplacementReturnStatement(
167 PsiStatement thenBranch, PsiStatement elseBranch,
168 PsiExpression condition) {
169 final PsiReturnStatement thenReturnStatement =
170 (PsiReturnStatement)thenBranch;
171 final PsiExpression thenReturnValue =
172 thenReturnStatement.getReturnValue();
173 if (thenReturnValue == null) {
174 return "";
176 final PsiReturnStatement elseReturnStatement =
177 (PsiReturnStatement)elseBranch;
178 final PsiExpression elseReturnValue =
179 elseReturnStatement.getReturnValue();
180 if (elseReturnValue == null) {
181 return "";
183 if (BoolUtils.isTrue(thenReturnValue)) {
184 if (ParenthesesUtils.getPrecedence(elseReturnValue) >
185 ParenthesesUtils.OR_PRECEDENCE) {
186 return "return " + condition.getText() + " || (" +
187 elseReturnValue.getText() + ");";
188 } else {
189 return "return " + condition.getText() + " || " +
190 elseReturnValue.getText() + ';';
192 } else if (BoolUtils.isFalse(thenReturnValue)) {
193 if (ParenthesesUtils.getPrecedence(elseReturnValue) >
194 ParenthesesUtils.AND_PRECEDENCE) {
195 return "return " +
196 BoolUtils.getNegatedExpressionText(condition) +
197 " && (" + elseReturnValue.getText() + ");";
198 } else {
199 return "return " +
200 BoolUtils.getNegatedExpressionText(condition) +
201 " && " + elseReturnValue.getText() + ';';
204 if (BoolUtils.isTrue(elseReturnValue)) {
205 if (ParenthesesUtils.getPrecedence(thenReturnValue) >
206 ParenthesesUtils.OR_PRECEDENCE) {
207 return "return " +
208 BoolUtils.getNegatedExpressionText(condition) +
209 " || (" + thenReturnValue.getText() + ");";
210 } else {
211 return "return " +
212 BoolUtils.getNegatedExpressionText(condition) +
213 " || " + thenReturnValue.getText() + ';';
215 } else {
216 final String conditionText;
217 if (ParenthesesUtils.getPrecedence(condition) >
218 ParenthesesUtils.AND_PRECEDENCE) {
219 conditionText = '(' + condition.getText() + ')';
220 } else {
221 conditionText = condition.getText();
223 if (ParenthesesUtils.getPrecedence(thenReturnValue) >
224 ParenthesesUtils.AND_PRECEDENCE) {
225 return "return " + conditionText + " && (" +
226 thenReturnValue.getText() + ");";
227 } else {
228 return "return " + conditionText + " && " +
229 thenReturnValue.getText() + ';';
234 public InspectionGadgetsFix buildFix(Object... infos) {
235 return new SimplifiableIfStatementFix();
238 private static class SimplifiableIfStatementFix
239 extends InspectionGadgetsFix {
241 @NotNull
242 public String getName() {
243 return InspectionGadgetsBundle.message(
244 "constant.conditional.expression.simplify.quickfix");
247 public void doFix(Project project, ProblemDescriptor descriptor)
248 throws IncorrectOperationException {
249 final PsiElement element = descriptor.getPsiElement();
250 final PsiIfStatement ifStatement =
251 (PsiIfStatement)element.getParent();
252 final String newStatement =
253 calculateReplacementStatement(ifStatement);
254 if ("".equals(newStatement)) {
255 return;
257 if (ifStatement.getElseBranch() == null) {
258 final PsiElement nextStatement =
259 PsiTreeUtil.skipSiblingsForward(ifStatement,
260 PsiWhiteSpace.class);
261 if (nextStatement != null) {
262 nextStatement.delete();
265 replaceStatement(ifStatement, newStatement);
269 private static class SimplifiableIfStatementVisitor
270 extends BaseInspectionVisitor {
272 @Override public void visitIfStatement(PsiIfStatement statement) {
273 super.visitIfStatement(statement);
274 if (statement.getCondition() == null) {
275 return;
277 if (!(isReplaceableAssignment(statement) ||
278 isReplaceableReturn(statement))) {
279 return;
281 registerStatementError(statement, statement);
284 public static boolean isReplaceableReturn(PsiIfStatement ifStatement) {
285 PsiStatement thenBranch = ifStatement.getThenBranch();
286 thenBranch = ControlFlowUtils.stripBraces(thenBranch);
287 PsiStatement elseBranch = ifStatement.getElseBranch();
288 elseBranch = ControlFlowUtils.stripBraces(elseBranch);
289 if (elseBranch == null) {
290 final PsiElement nextStatement =
291 PsiTreeUtil.skipSiblingsForward(ifStatement,
292 PsiWhiteSpace.class);
293 if (nextStatement instanceof PsiStatement) {
294 elseBranch = (PsiStatement)nextStatement;
297 if (!(thenBranch instanceof PsiReturnStatement) ||
298 !(elseBranch instanceof PsiReturnStatement)) {
299 return false;
301 final PsiExpression thenReturn =
302 ((PsiReturnStatement)thenBranch).getReturnValue();
303 if (thenReturn == null) {
304 return false;
306 final PsiExpression elseReturn =
307 ((PsiReturnStatement)elseBranch).getReturnValue();
308 if (elseReturn == null) {
309 return false;
311 final boolean thenConstant = BoolUtils.isFalse(thenReturn) ||
312 BoolUtils.isTrue(thenReturn);
313 final boolean elseConstant = BoolUtils.isFalse(elseReturn) ||
314 BoolUtils.isTrue(elseReturn);
315 return thenConstant != elseConstant;
318 public static boolean isReplaceableAssignment(
319 PsiIfStatement ifStatement) {
320 PsiStatement thenBranch = ifStatement.getThenBranch();
321 if (thenBranch == null) {
322 return false;
324 thenBranch = ControlFlowUtils.stripBraces(thenBranch);
325 if (thenBranch == null || !isAssignment(thenBranch)) {
326 return false;
328 PsiStatement elseBranch = ifStatement.getElseBranch();
329 elseBranch = ControlFlowUtils.stripBraces(elseBranch);
330 if (elseBranch == null || !isAssignment(elseBranch)) {
331 return false;
333 final PsiExpressionStatement thenStatement =
334 (PsiExpressionStatement)thenBranch;
335 final PsiAssignmentExpression thenExpression =
336 (PsiAssignmentExpression)thenStatement.getExpression();
337 final PsiExpressionStatement elseStatement =
338 (PsiExpressionStatement)elseBranch;
339 final PsiAssignmentExpression elseExpression =
340 (PsiAssignmentExpression)elseStatement.getExpression();
341 final PsiJavaToken thenOperationSign =
342 thenExpression.getOperationSign();
343 final IElementType thenTokenType = thenOperationSign.getTokenType();
344 final PsiJavaToken elseOperationSign =
345 elseExpression.getOperationSign();
346 final IElementType elseTokenType = elseOperationSign.getTokenType();
347 if (!thenTokenType.equals(elseTokenType)) {
348 return false;
350 final PsiExpression thenRhs = thenExpression.getRExpression();
351 if (thenRhs == null) {
352 return false;
354 final PsiExpression elseRhs = elseExpression.getRExpression();
355 if (elseRhs == null) {
356 return false;
358 final boolean thenConstant = BoolUtils.isFalse(thenRhs) ||
359 BoolUtils.isTrue(thenRhs);
360 final boolean elseConstant = BoolUtils.isFalse(elseRhs) ||
361 BoolUtils.isTrue(elseRhs);
362 if (thenConstant == elseConstant) {
363 return false;
365 final PsiExpression thenLhs = thenExpression.getLExpression();
366 final PsiExpression elseLhs = elseExpression.getLExpression();
367 return EquivalenceChecker.expressionsAreEquivalent(thenLhs,
368 elseLhs);
371 public static boolean isAssignment(@Nullable PsiStatement statement) {
372 if (!(statement instanceof PsiExpressionStatement)) {
373 return false;
375 final PsiExpressionStatement expressionStatement =
376 (PsiExpressionStatement)statement;
377 final PsiExpression expression =
378 expressionStatement.getExpression();
379 return expression instanceof PsiAssignmentExpression;