2 * Copyright 2008 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
.dataflow
;
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
.PsiUtil
;
23 import com
.intellij
.util
.IncorrectOperationException
;
24 import com
.siyeh
.ig
.BaseInspection
;
25 import com
.siyeh
.ig
.BaseInspectionVisitor
;
26 import com
.siyeh
.ig
.InspectionGadgetsFix
;
27 import com
.siyeh
.InspectionGadgetsBundle
;
28 import org
.jetbrains
.annotations
.NotNull
;
29 import org
.jetbrains
.annotations
.Nullable
;
31 public class ConstantValueVariableUseInspection
extends BaseInspection
{
35 public String
getDisplayName() {
36 return InspectionGadgetsBundle
.message(
37 "constant.value.variable.use.display.name");
42 protected String
buildErrorString(Object
... infos
) {
43 return InspectionGadgetsBundle
.message(
44 "constant.value.variable.use.problem.descriptor");
48 protected InspectionGadgetsFix
buildFix(Object
... infos
) {
49 final PsiExpression expression
= (PsiExpression
) infos
[0];
50 return new ReplaceReferenceWithExpressionFix(expression
);
53 private static class ReplaceReferenceWithExpressionFix
54 extends InspectionGadgetsFix
{
56 private final PsiExpression expression
;
58 ReplaceReferenceWithExpressionFix(
59 PsiExpression expression
) {
60 this.expression
= expression
;
65 public String
getName() {
66 return InspectionGadgetsBundle
.message(
67 "replace.reference.with.expression.quickfix",
68 expression
.getText());
72 protected void doFix(Project project
, ProblemDescriptor descriptor
)
73 throws IncorrectOperationException
{
74 final PsiElement element
= descriptor
.getPsiElement();
75 element
.replace(expression
);
80 public BaseInspectionVisitor
buildVisitor() {
81 return new ConstantValueVariableUseVisitor();
84 private static class ConstantValueVariableUseVisitor
85 extends BaseInspectionVisitor
{
88 public void visitIfStatement(PsiIfStatement statement
) {
89 super.visitIfStatement(statement
);
90 final PsiExpression condition
= statement
.getCondition();
91 final PsiStatement body
= statement
.getThenBranch();
92 checkCondition(condition
, body
);
96 public void visitWhileStatement(PsiWhileStatement statement
) {
97 super.visitWhileStatement(statement
);
98 final PsiExpression condition
= statement
.getCondition();
99 final PsiStatement body
= statement
.getBody();
100 checkCondition(condition
, body
);
103 private boolean checkCondition(@Nullable PsiExpression condition
,
104 @Nullable PsiStatement body
) {
108 if (!(condition
instanceof PsiBinaryExpression
)) {
111 final PsiBinaryExpression binaryExpression
=
112 (PsiBinaryExpression
) condition
;
113 final IElementType tokenType
=
114 binaryExpression
.getOperationTokenType();
115 final PsiExpression lhs
= binaryExpression
.getLOperand();
116 final PsiExpression rhs
= binaryExpression
.getROperand();
117 if (JavaTokenType
.ANDAND
== tokenType
) {
118 return checkCondition(lhs
, body
) ||
119 checkCondition(rhs
, body
);
121 if (JavaTokenType
.EQEQ
!= tokenType
) {
127 if (PsiUtil
.isConstantExpression(lhs
)) {
128 return checkConstantValueVariableUse(rhs
, lhs
, body
);
129 } else if (PsiUtil
.isConstantExpression(rhs
)) {
130 return checkConstantValueVariableUse(lhs
, rhs
, body
);
135 private boolean checkConstantValueVariableUse(
136 @Nullable PsiExpression expression
,
137 @NotNull PsiExpression constantExpression
,
138 @NotNull PsiElement body
) {
139 if (!(expression
instanceof PsiReferenceExpression
)) {
142 final PsiReferenceExpression referenceExpression
=
143 (PsiReferenceExpression
) expression
;
144 final PsiElement target
= referenceExpression
.resolve();
145 if (!(target
instanceof PsiVariable
)) {
148 if (target
instanceof PsiField
) {
151 final PsiVariable variable
= (PsiVariable
) target
;
152 final VariableReadVisitor visitor
=
153 new VariableReadVisitor(variable
);
154 body
.accept(visitor
);
155 if (!visitor
.isRead()) {
158 registerError(visitor
.getReference(), constantExpression
);
163 private static class VariableReadVisitor
164 extends JavaRecursiveElementVisitor
{
167 private final PsiVariable variable
;
168 private boolean read
= false;
169 private boolean written
= false;
170 private PsiReferenceExpression reference
= null;
172 VariableReadVisitor(@NotNull PsiVariable variable
) {
173 this.variable
= variable
;
177 public void visitElement(@NotNull PsiElement element
) {
178 if (read
|| written
) {
181 super.visitElement(element
);
185 public void visitAssignmentExpression(
186 @NotNull PsiAssignmentExpression assignment
) {
187 if (read
|| written
) {
190 super.visitAssignmentExpression(assignment
);
191 final PsiExpression lhs
= assignment
.getLExpression();
192 if (lhs
instanceof PsiReferenceExpression
) {
193 PsiReferenceExpression referenceExpression
=
194 (PsiReferenceExpression
) lhs
;
195 final PsiElement target
= referenceExpression
.resolve();
196 if (variable
.equals(target
)) {
201 final PsiExpression rhs
= assignment
.getRExpression();
205 final VariableUsedVisitor visitor
=
206 new VariableUsedVisitor(variable
);
208 read
= visitor
.isUsed();
209 reference
= visitor
.getReference();
213 public void visitPrefixExpression(
214 @NotNull PsiPrefixExpression prefixExpression
) {
215 if (read
|| written
) {
218 super.visitPrefixExpression(prefixExpression
);
219 final PsiJavaToken operationSign
=
220 prefixExpression
.getOperationSign();
221 final IElementType tokenType
= operationSign
.getTokenType();
222 if (!tokenType
.equals(JavaTokenType
.PLUSPLUS
) &&
223 !tokenType
.equals(JavaTokenType
.MINUSMINUS
)) {
226 final PsiExpression operand
= prefixExpression
.getOperand();
227 if (!(operand
instanceof PsiReferenceExpression
)) {
230 final PsiReferenceExpression referenceExpression
=
231 (PsiReferenceExpression
) operand
;
232 final PsiElement target
= referenceExpression
.resolve();
233 if (!variable
.equals(target
)) {
240 public void visitPostfixExpression(
241 @NotNull PsiPostfixExpression postfixExpression
) {
242 if (read
|| written
) {
245 super.visitPostfixExpression(postfixExpression
);
246 final PsiJavaToken operationSign
=
247 postfixExpression
.getOperationSign();
248 final IElementType tokenType
= operationSign
.getTokenType();
249 if (!tokenType
.equals(JavaTokenType
.PLUSPLUS
) &&
250 !tokenType
.equals(JavaTokenType
.MINUSMINUS
)) {
253 final PsiExpression operand
= postfixExpression
.getOperand();
254 if (!(operand
instanceof PsiReferenceExpression
)) {
257 final PsiReferenceExpression referenceExpression
=
258 (PsiReferenceExpression
) operand
;
259 final PsiElement target
= referenceExpression
.resolve();
260 if (!variable
.equals(target
)) {
267 public void visitVariable(@NotNull PsiVariable variable
) {
268 if (read
|| written
) {
271 super.visitVariable(variable
);
272 final PsiExpression initalizer
= variable
.getInitializer();
273 if (initalizer
== null) {
276 final VariableUsedVisitor visitor
=
277 new VariableUsedVisitor(variable
);
278 initalizer
.accept(visitor
);
279 read
= visitor
.isUsed();
280 reference
= visitor
.getReference();
284 public void visitMethodCallExpression(
285 @NotNull PsiMethodCallExpression call
) {
286 if (read
|| written
) {
289 super.visitMethodCallExpression(call
);
290 final PsiExpressionList argumentList
= call
.getArgumentList();
291 final PsiExpression
[] arguments
= argumentList
.getExpressions();
292 for (final PsiExpression argument
: arguments
) {
293 final VariableUsedVisitor visitor
=
294 new VariableUsedVisitor(variable
);
295 argument
.accept(visitor
);
296 if (visitor
.isUsed()) {
298 reference
= visitor
.getReference();
305 public void visitNewExpression(
306 @NotNull PsiNewExpression newExpression
) {
307 if (read
|| written
) {
310 super.visitNewExpression(newExpression
);
311 final PsiExpressionList argumentList
=
312 newExpression
.getArgumentList();
313 if (argumentList
== null) {
316 final PsiExpression
[] arguments
= argumentList
.getExpressions();
317 for (final PsiExpression argument
: arguments
) {
318 final VariableUsedVisitor visitor
=
319 new VariableUsedVisitor(variable
);
320 argument
.accept(visitor
);
321 if (visitor
.isUsed()) {
323 reference
= visitor
.getReference();
330 public void visitArrayInitializerExpression(
331 PsiArrayInitializerExpression expression
) {
332 if (read
|| written
) {
335 super.visitArrayInitializerExpression(expression
);
336 final PsiExpression
[] arguments
= expression
.getInitializers();
337 for (final PsiExpression argument
: arguments
) {
338 final VariableUsedVisitor visitor
=
339 new VariableUsedVisitor(variable
);
340 argument
.accept(visitor
);
341 if (visitor
.isUsed()) {
343 reference
= visitor
.getReference();
350 public void visitReturnStatement(
351 @NotNull PsiReturnStatement returnStatement
) {
352 if (read
|| written
) {
355 super.visitReturnStatement(returnStatement
);
356 final PsiExpression returnValue
= returnStatement
.getReturnValue();
357 if (returnValue
== null) {
360 final VariableUsedVisitor visitor
=
361 new VariableUsedVisitor(variable
);
362 returnValue
.accept(visitor
);
363 read
= visitor
.isUsed();
364 reference
= visitor
.getReference();
368 * check if variable is used in nested/inner class.
371 public void visitClass(PsiClass aClass
) {
372 if (read
|| written
) {
375 super.visitClass(aClass
);
376 final VariableUsedVisitor visitor
=
377 new VariableUsedVisitor(variable
);
378 aClass
.accept(visitor
);
379 read
= visitor
.isUsed();
380 reference
= visitor
.getReference();
383 public boolean isRead() {
387 public PsiReferenceExpression
getReference() {
392 private static class VariableUsedVisitor
393 extends JavaRecursiveElementVisitor
{
395 private final PsiVariable variable
;
396 private boolean used
= false;
397 private PsiReferenceExpression reference
= null;
399 VariableUsedVisitor(PsiVariable variable
) {
400 this.variable
= variable
;
404 public void visitElement(PsiElement element
) {
408 super.visitElement(element
);
412 public void visitReferenceExpression(
413 @NotNull PsiReferenceExpression expression
) {
417 super.visitReferenceExpression(expression
);
418 final PsiElement referent
= expression
.resolve();
419 if (referent
== null) {
422 if (referent
.equals(variable
)) {
423 reference
= expression
;
428 public boolean isUsed() {
432 public PsiReferenceExpression
getReference() {