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
{
39 public String
getDisplayName() {
40 return InspectionGadgetsBundle
.message(
41 "simplifiable.if.statement.display.name");
44 public boolean isEnabledByDefault() {
48 public BaseInspectionVisitor
buildVisitor() {
49 return new SimplifiableIfStatementVisitor();
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
));
61 static String
calculateReplacementStatement(
62 PsiIfStatement statement
) {
63 PsiStatement thenBranch
= statement
.getThenBranch();
64 thenBranch
= ControlFlowUtils
.stripBraces(thenBranch
);
65 if (thenBranch
== null) {
68 PsiStatement elseBranch
= statement
.getElseBranch();
69 elseBranch
= ControlFlowUtils
.stripBraces(elseBranch
);
70 if (elseBranch
== null) {
71 final PsiElement nextStatement
=
72 PsiTreeUtil
.skipSiblingsForward(statement
,
74 if (nextStatement
instanceof PsiStatement
) {
75 elseBranch
= (PsiStatement
)nextStatement
;
78 if (elseBranch
== null) {
81 final PsiExpression condition
= statement
.getCondition();
82 if (condition
== null) {
85 if (elseBranch
instanceof PsiReturnStatement
) {
86 return calculateReplacementReturnStatement(thenBranch
, elseBranch
,
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) {
109 final PsiExpression elseRhs
= elseAssignment
.getRExpression();
110 if (elseRhs
== null) {
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() + ");";
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() + ");";
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() + ");";
142 return lhs
.getText() + ' ' + token
.getText() + ' ' +
143 BoolUtils
.getNegatedExpressionText(condition
) + " || " +
144 thenRhs
.getText() + ';';
147 final String conditionText
;
148 if (ParenthesesUtils
.getPrecedence(condition
) >
149 ParenthesesUtils
.AND_PRECEDENCE
) {
150 conditionText
= '(' + condition
.getText() + ')';
152 conditionText
= condition
.getText();
154 if (ParenthesesUtils
.getPrecedence(thenRhs
) >
155 ParenthesesUtils
.AND_PRECEDENCE
) {
156 return lhs
.getText() + ' ' + token
.getText() + ' ' +
157 conditionText
+ " && (" + thenRhs
.getText() + ");";
159 return lhs
.getText() + ' ' + token
.getText() + ' ' +
160 conditionText
+ " && " + thenRhs
.getText() + ';';
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) {
176 final PsiReturnStatement elseReturnStatement
=
177 (PsiReturnStatement
)elseBranch
;
178 final PsiExpression elseReturnValue
=
179 elseReturnStatement
.getReturnValue();
180 if (elseReturnValue
== null) {
183 if (BoolUtils
.isTrue(thenReturnValue
)) {
184 if (ParenthesesUtils
.getPrecedence(elseReturnValue
) >
185 ParenthesesUtils
.OR_PRECEDENCE
) {
186 return "return " + condition
.getText() + " || (" +
187 elseReturnValue
.getText() + ");";
189 return "return " + condition
.getText() + " || " +
190 elseReturnValue
.getText() + ';';
192 } else if (BoolUtils
.isFalse(thenReturnValue
)) {
193 if (ParenthesesUtils
.getPrecedence(elseReturnValue
) >
194 ParenthesesUtils
.AND_PRECEDENCE
) {
196 BoolUtils
.getNegatedExpressionText(condition
) +
197 " && (" + elseReturnValue
.getText() + ");";
200 BoolUtils
.getNegatedExpressionText(condition
) +
201 " && " + elseReturnValue
.getText() + ';';
204 if (BoolUtils
.isTrue(elseReturnValue
)) {
205 if (ParenthesesUtils
.getPrecedence(thenReturnValue
) >
206 ParenthesesUtils
.OR_PRECEDENCE
) {
208 BoolUtils
.getNegatedExpressionText(condition
) +
209 " || (" + thenReturnValue
.getText() + ");";
212 BoolUtils
.getNegatedExpressionText(condition
) +
213 " || " + thenReturnValue
.getText() + ';';
216 final String conditionText
;
217 if (ParenthesesUtils
.getPrecedence(condition
) >
218 ParenthesesUtils
.AND_PRECEDENCE
) {
219 conditionText
= '(' + condition
.getText() + ')';
221 conditionText
= condition
.getText();
223 if (ParenthesesUtils
.getPrecedence(thenReturnValue
) >
224 ParenthesesUtils
.AND_PRECEDENCE
) {
225 return "return " + conditionText
+ " && (" +
226 thenReturnValue
.getText() + ");";
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
{
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
)) {
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) {
277 if (!(isReplaceableAssignment(statement
) ||
278 isReplaceableReturn(statement
))) {
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
)) {
301 final PsiExpression thenReturn
=
302 ((PsiReturnStatement
)thenBranch
).getReturnValue();
303 if (thenReturn
== null) {
306 final PsiExpression elseReturn
=
307 ((PsiReturnStatement
)elseBranch
).getReturnValue();
308 if (elseReturn
== null) {
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) {
324 thenBranch
= ControlFlowUtils
.stripBraces(thenBranch
);
325 if (thenBranch
== null || !isAssignment(thenBranch
)) {
328 PsiStatement elseBranch
= ifStatement
.getElseBranch();
329 elseBranch
= ControlFlowUtils
.stripBraces(elseBranch
);
330 if (elseBranch
== null || !isAssignment(elseBranch
)) {
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
)) {
350 final PsiExpression thenRhs
= thenExpression
.getRExpression();
351 if (thenRhs
== null) {
354 final PsiExpression elseRhs
= elseExpression
.getRExpression();
355 if (elseRhs
== null) {
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
) {
365 final PsiExpression thenLhs
= thenExpression
.getLExpression();
366 final PsiExpression elseLhs
= elseExpression
.getLExpression();
367 return EquivalenceChecker
.expressionsAreEquivalent(thenLhs
,
371 public static boolean isAssignment(@Nullable PsiStatement statement
) {
372 if (!(statement
instanceof PsiExpressionStatement
)) {
375 final PsiExpressionStatement expressionStatement
=
376 (PsiExpressionStatement
)statement
;
377 final PsiExpression expression
=
378 expressionStatement
.getExpression();
379 return expression
instanceof PsiAssignmentExpression
;