Remove ComparisonUtils duplication
[idea/community.git] / plugins / IntentionPowerPak / src / com / siyeh / ipp / psiutils / VariableAccessUtils.java
1 /*
2  * Copyright 2009-2014 Bas Leijdekkers
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.siyeh.ipp.psiutils;
17
18 import com.intellij.psi.*;
19 import com.intellij.psi.tree.IElementType;
20 import com.siyeh.ig.psiutils.ComparisonUtils;
21 import com.siyeh.ig.psiutils.ParenthesesUtils;
22 import org.jetbrains.annotations.NotNull;
23 import org.jetbrains.annotations.Nullable;
24
25 import java.util.Collection;
26 import java.util.Collections;
27 import java.util.HashSet;
28 import java.util.Set;
29
30 public class VariableAccessUtils {
31
32   private VariableAccessUtils() {
33   }
34
35   public static boolean isVariableCompared(
36     @NotNull PsiVariable variable, @Nullable PsiExpression expression) {
37     if (!(expression instanceof PsiBinaryExpression)) {
38       return false;
39     }
40     final PsiBinaryExpression binaryExpression =
41       (PsiBinaryExpression)expression;
42     final IElementType tokenType = binaryExpression.getOperationTokenType();
43     if (!ComparisonUtils.isComparisonOperation(tokenType)) {
44       return false;
45     }
46     final PsiExpression lhs = binaryExpression.getLOperand();
47     final PsiExpression rhs = binaryExpression.getROperand();
48     if (rhs == null) {
49       return false;
50     }
51     if (evaluatesToVariable(lhs, variable)) {
52       return true;
53     }
54     else if (evaluatesToVariable(rhs, variable)) {
55       return true;
56     }
57     return false;
58   }
59
60   public static boolean isVariableIncrementOrDecremented(
61     @NotNull PsiVariable variable, @Nullable PsiStatement statement) {
62     if (!(statement instanceof PsiExpressionStatement)) {
63       return false;
64     }
65     final PsiExpressionStatement expressionStatement =
66       (PsiExpressionStatement)statement;
67     PsiExpression expression = expressionStatement.getExpression();
68     expression = ParenthesesUtils.stripParentheses(expression);
69     if (expression instanceof PsiPrefixExpression) {
70       final PsiPrefixExpression prefixExpression =
71         (PsiPrefixExpression)expression;
72       final IElementType tokenType = prefixExpression.getOperationTokenType();
73       if (!tokenType.equals(JavaTokenType.PLUSPLUS) &&
74           !tokenType.equals(JavaTokenType.MINUSMINUS)) {
75         return false;
76       }
77       final PsiExpression operand = prefixExpression.getOperand();
78       return evaluatesToVariable(operand, variable);
79     }
80     else if (expression instanceof PsiPostfixExpression) {
81       final PsiPostfixExpression postfixExpression =
82         (PsiPostfixExpression)expression;
83       final IElementType tokenType = postfixExpression.getOperationTokenType();
84       if (!tokenType.equals(JavaTokenType.PLUSPLUS) &&
85           !tokenType.equals(JavaTokenType.MINUSMINUS)) {
86         return false;
87       }
88       final PsiExpression operand = postfixExpression.getOperand();
89       return evaluatesToVariable(operand, variable);
90     }
91     else if (expression instanceof PsiAssignmentExpression) {
92       final PsiAssignmentExpression assignmentExpression =
93         (PsiAssignmentExpression)expression;
94       final IElementType tokenType =
95         assignmentExpression.getOperationTokenType();
96       PsiExpression lhs = assignmentExpression.getLExpression();
97       lhs = ParenthesesUtils.stripParentheses(lhs);
98       if (!evaluatesToVariable(lhs, variable)) {
99         return false;
100       }
101       PsiExpression rhs = assignmentExpression.getRExpression();
102       rhs = ParenthesesUtils.stripParentheses(rhs);
103       if (tokenType == JavaTokenType.EQ) {
104         if (!(rhs instanceof PsiBinaryExpression)) {
105           return false;
106         }
107         final PsiBinaryExpression binaryExpression =
108           (PsiBinaryExpression)rhs;
109         final IElementType token =
110           binaryExpression.getOperationTokenType();
111         if (!token.equals(JavaTokenType.PLUS) &&
112             !token.equals(JavaTokenType.MINUS)) {
113           return false;
114         }
115         PsiExpression lOperand = binaryExpression.getLOperand();
116         lOperand = ParenthesesUtils.stripParentheses(lOperand);
117         PsiExpression rOperand = binaryExpression.getROperand();
118         rOperand = ParenthesesUtils.stripParentheses(rOperand);
119         if (evaluatesToVariable(rOperand, variable)) {
120           return true;
121         }
122         else if (evaluatesToVariable(lOperand, variable)) {
123           return true;
124         }
125       }
126       else if (tokenType == JavaTokenType.PLUSEQ ||
127                tokenType == JavaTokenType.MINUSEQ) {
128         return true;
129       }
130     }
131     return false;
132   }
133
134   public static boolean evaluatesToVariable(
135     @Nullable PsiExpression expression,
136     @NotNull PsiVariable variable) {
137     final PsiExpression strippedExpression =
138       ParenthesesUtils.stripParentheses(expression);
139     if (strippedExpression == null) {
140       return false;
141     }
142     if (!(expression instanceof PsiReferenceExpression)) {
143       return false;
144     }
145     final PsiReferenceExpression referenceExpression =
146       (PsiReferenceExpression)expression;
147     final PsiElement referent = referenceExpression.resolve();
148     return variable.equals(referent);
149   }
150
151   public static boolean isAnyVariableAssigned(
152     @NotNull Collection<PsiVariable> variables,
153     @Nullable PsiElement context) {
154     if (context == null) {
155       return false;
156     }
157     final VariableAssignedVisitor visitor =
158       new VariableAssignedVisitor(variables, true);
159     context.accept(visitor);
160     return visitor.isAssigned();
161   }
162
163   public static Set<PsiVariable> collectUsedVariables(
164     PsiElement context) {
165     if (context == null) {
166       return Collections.emptySet();
167     }
168     final VariableCollectingVisitor visitor =
169       new VariableCollectingVisitor();
170     context.accept(visitor);
171     return visitor.getUsedVariables();
172   }
173
174   private static class VariableCollectingVisitor
175     extends JavaRecursiveElementVisitor {
176
177     private final Set<PsiVariable> usedVariables = new HashSet();
178
179     @Override
180     public void visitReferenceExpression(
181       PsiReferenceExpression expression) {
182       super.visitReferenceExpression(expression);
183       final PsiElement target = expression.resolve();
184       if (!(target instanceof PsiVariable)) {
185         return;
186       }
187       final PsiVariable variable = (PsiVariable)target;
188       usedVariables.add(variable);
189     }
190
191     public Set<PsiVariable> getUsedVariables() {
192       return usedVariables;
193     }
194   }
195 }