2 * Copyright 2003-2006 Dave Griffith, 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
.psiutils
;
18 import com
.intellij
.psi
.*;
19 import com
.intellij
.psi
.tree
.IElementType
;
20 import com
.intellij
.psi
.util
.PsiTreeUtil
;
21 import org
.jetbrains
.annotations
.NotNull
;
22 import org
.jetbrains
.annotations
.Nullable
;
24 import java
.util
.ArrayList
;
25 import java
.util
.List
;
27 public class EquivalenceChecker
{
29 private EquivalenceChecker(){
33 public static boolean modifierListsAreEquivalent(
34 @Nullable PsiModifierList list1
, @Nullable PsiModifierList list2
) {
37 } else if (list2
== null) {
40 final PsiAnnotation
[] annotations
= list1
.getAnnotations();
41 for (PsiAnnotation annotation
: annotations
) {
42 final String qualifiedName
= annotation
.getQualifiedName();
43 if (qualifiedName
== null) {
46 if (list2
.findAnnotation(qualifiedName
) == null) {
50 if (list1
.hasModifierProperty(PsiModifier
.ABSTRACT
) &&
51 !list2
.hasModifierProperty(PsiModifier
.ABSTRACT
)) {
54 if (list1
.hasModifierProperty(PsiModifier
.FINAL
) &&
55 !list2
.hasModifierProperty(PsiModifier
.FINAL
)) {
58 if (list1
.hasModifierProperty(PsiModifier
.NATIVE
) &&
59 !list2
.hasModifierProperty(PsiModifier
.NATIVE
)) {
62 if (list1
.hasModifierProperty(PsiModifier
.PACKAGE_LOCAL
) &&
63 !list2
.hasModifierProperty(PsiModifier
.PACKAGE_LOCAL
)) {
66 if (list1
.hasModifierProperty(PsiModifier
.PRIVATE
) &&
67 !list2
.hasModifierProperty(PsiModifier
.PRIVATE
)) {
70 if (list1
.hasModifierProperty(PsiModifier
.PROTECTED
) &&
71 !list2
.hasModifierProperty(PsiModifier
.PROTECTED
)) {
74 if (list1
.hasModifierProperty(PsiModifier
.PUBLIC
) &&
75 !list2
.hasModifierProperty(PsiModifier
.PUBLIC
)) {
78 if (list1
.hasModifierProperty(PsiModifier
.STATIC
) &&
79 !list2
.hasModifierProperty(PsiModifier
.STATIC
)) {
82 if (list1
.hasModifierProperty(PsiModifier
.STRICTFP
) &&
83 !list2
.hasModifierProperty(PsiModifier
.STRICTFP
)) {
86 if (list1
.hasModifierProperty(PsiModifier
.SYNCHRONIZED
) &&
87 !list2
.hasModifierProperty(PsiModifier
.SYNCHRONIZED
)) {
90 if (list1
.hasModifierProperty(PsiModifier
.TRANSIENT
) &&
91 !list2
.hasModifierProperty(PsiModifier
.TRANSIENT
)) {
94 return !(list1
.hasModifierProperty(PsiModifier
.VOLATILE
) &&
95 !list2
.hasModifierProperty(PsiModifier
.VOLATILE
));
98 public static boolean statementsAreEquivalent(
99 @Nullable PsiStatement statement1
,
100 @Nullable PsiStatement statement2
) {
101 if(statement1
== null && statement2
== null){
104 if(statement1
== null || statement2
== null){
107 if(statement1
.getClass() != statement2
.getClass()){
110 if(statement1
instanceof PsiAssertStatement
){
111 final PsiAssertStatement assertStatement1
=
112 (PsiAssertStatement
)statement1
;
113 final PsiAssertStatement assertStatement2
=
114 (PsiAssertStatement
)statement2
;
115 return assertStatementsAreEquivalent(assertStatement1
,
118 if(statement1
instanceof PsiBlockStatement
){
119 final PsiBlockStatement blockStatement1
=
120 (PsiBlockStatement
)statement1
;
121 final PsiBlockStatement blockStatement2
=
122 (PsiBlockStatement
)statement2
;
123 return blockStatementsAreEquivalent(blockStatement1
,
126 if(statement1
instanceof PsiBreakStatement
){
127 final PsiBreakStatement breakStatement1
=
128 (PsiBreakStatement
)statement1
;
129 final PsiBreakStatement breakStatement2
=
130 (PsiBreakStatement
)statement2
;
131 return breakStatementsAreEquivalent(breakStatement1
,
134 if(statement1
instanceof PsiContinueStatement
){
135 final PsiContinueStatement continueStatement1
=
136 (PsiContinueStatement
)statement1
;
137 final PsiContinueStatement continueStatement2
=
138 (PsiContinueStatement
)statement2
;
139 return continueStatementsAreEquivalent(continueStatement1
,
142 if(statement1
instanceof PsiDeclarationStatement
){
143 final PsiDeclarationStatement declarationStatement1
=
144 (PsiDeclarationStatement
)statement1
;
145 final PsiDeclarationStatement declarationStatement2
=
146 (PsiDeclarationStatement
)statement2
;
147 return declarationStatementsAreEquivalent(declarationStatement1
,
148 declarationStatement2
);
150 if(statement1
instanceof PsiDoWhileStatement
){
151 final PsiDoWhileStatement doWhileStatement1
=
152 (PsiDoWhileStatement
)statement1
;
153 final PsiDoWhileStatement doWhileStatement2
=
154 (PsiDoWhileStatement
)statement2
;
155 return doWhileStatementsAreEquivalent(
156 doWhileStatement1
, doWhileStatement2
);
158 if(statement1
instanceof PsiEmptyStatement
){
161 if(statement1
instanceof PsiExpressionListStatement
){
162 final PsiExpressionListStatement expressionListStatement1
=
163 (PsiExpressionListStatement
)statement1
;
164 final PsiExpressionListStatement expressionListStatement2
=
165 (PsiExpressionListStatement
)statement2
;
166 return expressionListStatementsAreEquivalent(
167 expressionListStatement1
,
168 expressionListStatement2
);
170 if(statement1
instanceof PsiExpressionStatement
){
171 final PsiExpressionStatement expressionStatement1
=
172 (PsiExpressionStatement
)statement1
;
173 final PsiExpressionStatement expressionStatement2
=
174 (PsiExpressionStatement
)statement2
;
175 return expressionStatementsAreEquivalent(
176 expressionStatement1
,
177 expressionStatement2
);
179 if(statement1
instanceof PsiForStatement
){
180 final PsiForStatement forStatement1
=
181 (PsiForStatement
)statement1
;
182 final PsiForStatement forStatement2
=
183 (PsiForStatement
)statement2
;
184 return forStatementsAreEquivalent(forStatement1
, forStatement2
);
186 if(statement1
instanceof PsiForeachStatement
){
187 final PsiForeachStatement forEachStatement1
=
188 (PsiForeachStatement
)statement1
;
189 final PsiForeachStatement forEachStatement2
=
190 (PsiForeachStatement
)statement2
;
191 return forEachStatementsAreEquivalent(forEachStatement1
,
194 if(statement1
instanceof PsiIfStatement
){
195 return ifStatementsAreEquivalent(
196 (PsiIfStatement
) statement1
,
197 (PsiIfStatement
) statement2
);
199 if(statement1
instanceof PsiLabeledStatement
){
200 final PsiLabeledStatement labeledStatement1
=
201 (PsiLabeledStatement
)statement1
;
202 final PsiLabeledStatement labeledStatement2
=
203 (PsiLabeledStatement
)statement2
;
204 return labeledStatementsAreEquivalent(labeledStatement1
,
207 if(statement1
instanceof PsiReturnStatement
){
208 final PsiReturnStatement returnStatement1
=
209 (PsiReturnStatement
)statement1
;
210 final PsiReturnStatement returnStatement2
=
211 (PsiReturnStatement
)statement2
;
212 return returnStatementsAreEquivalent(returnStatement1
,
215 if(statement1
instanceof PsiSwitchStatement
){
216 final PsiSwitchStatement switchStatement1
=
217 (PsiSwitchStatement
)statement1
;
218 final PsiSwitchStatement switchStatement2
=
219 (PsiSwitchStatement
)statement2
;
220 return switchStatementsAreEquivalent(switchStatement1
,
223 if(statement1
instanceof PsiSwitchLabelStatement
){
224 final PsiSwitchLabelStatement switchLabelStatement1
=
225 (PsiSwitchLabelStatement
)statement1
;
226 final PsiSwitchLabelStatement switchLabelStatement2
=
227 (PsiSwitchLabelStatement
)statement2
;
228 return switchLabelStatementsAreEquivalent(switchLabelStatement1
,
229 switchLabelStatement2
);
231 if(statement1
instanceof PsiSynchronizedStatement
){
232 final PsiSynchronizedStatement synchronizedStatement1
=
233 (PsiSynchronizedStatement
)statement1
;
234 final PsiSynchronizedStatement synchronizedStatement2
=
235 (PsiSynchronizedStatement
)statement2
;
236 return synchronizedStatementsAreEquivalent(
237 synchronizedStatement1
, synchronizedStatement2
);
239 if(statement1
instanceof PsiThrowStatement
){
240 final PsiThrowStatement throwStatement1
=
241 (PsiThrowStatement
)statement1
;
242 final PsiThrowStatement throwStatement2
=
243 (PsiThrowStatement
)statement2
;
244 return throwStatementsAreEquivalent(throwStatement1
,
247 if(statement1
instanceof PsiTryStatement
){
248 final PsiTryStatement tryStatement1
=
249 (PsiTryStatement
)statement1
;
250 final PsiTryStatement tryStatement2
=
251 (PsiTryStatement
)statement2
;
252 return tryStatementsAreEquivalent(tryStatement1
,
255 if(statement1
instanceof PsiWhileStatement
){
256 final PsiWhileStatement whileStatement1
=
257 (PsiWhileStatement
)statement1
;
258 final PsiWhileStatement whileStatement2
=
259 (PsiWhileStatement
)statement2
;
260 return whileStatementsAreEquivalent(whileStatement1
,
263 final String text1
= statement1
.getText();
264 final String text2
= statement2
.getText();
265 return text1
.equals(text2
);
268 private static boolean declarationStatementsAreEquivalent(
269 @NotNull PsiDeclarationStatement statement1
,
270 @NotNull PsiDeclarationStatement statement2
){
271 final PsiElement
[] elements1
= statement1
.getDeclaredElements();
272 final List
<PsiLocalVariable
> vars1
=
273 new ArrayList
<PsiLocalVariable
>(elements1
.length
);
274 for(PsiElement anElement
: elements1
){
275 if(anElement
instanceof PsiLocalVariable
){
276 vars1
.add((PsiLocalVariable
) anElement
);
279 final PsiElement
[] elements2
= statement2
.getDeclaredElements();
280 final List
<PsiLocalVariable
> vars2
=
281 new ArrayList
<PsiLocalVariable
>(elements2
.length
);
282 for(PsiElement anElement
: elements2
){
283 if(anElement
instanceof PsiLocalVariable
){
284 vars2
.add((PsiLocalVariable
) anElement
);
287 final int size
= vars1
.size();
288 if(size
!= vars2
.size()){
291 for(int i
= 0; i
< size
; i
++){
292 final PsiLocalVariable var1
= vars1
.get(i
);
293 final PsiLocalVariable var2
= vars2
.get(i
);
294 if(!localVariableAreEquivalent(var1
, var2
)){
301 private static boolean localVariableAreEquivalent(
302 @NotNull PsiLocalVariable var1
, @NotNull PsiLocalVariable var2
) {
303 final PsiType type1
= var1
.getType();
304 final PsiType type2
= var2
.getType();
305 if(!typesAreEquivalent(type1
, type2
)){
308 final String name1
= var1
.getName();
309 final String name2
= var2
.getName();
314 } else if (name2
== null) {
316 } else if (!name1
.equals(name2
)) {
319 final PsiExpression initializer1
= var1
.getInitializer();
320 final PsiExpression initializer2
= var2
.getInitializer();
321 return expressionsAreEquivalent(initializer1
, initializer2
);
324 private static boolean tryStatementsAreEquivalent(
325 @NotNull PsiTryStatement statement1
,
326 @NotNull PsiTryStatement statement2
) {
327 final PsiCodeBlock tryBlock1
= statement1
.getTryBlock();
328 final PsiCodeBlock tryBlock2
= statement2
.getTryBlock();
329 if(!codeBlocksAreEquivalent(tryBlock1
, tryBlock2
)){
332 final PsiCodeBlock finallyBlock1
= statement1
.getFinallyBlock();
333 final PsiCodeBlock finallyBlock2
= statement2
.getFinallyBlock();
334 if(!codeBlocksAreEquivalent(finallyBlock1
, finallyBlock2
)){
337 final PsiCodeBlock
[] catchBlocks1
= statement1
.getCatchBlocks();
338 final PsiCodeBlock
[] catchBlocks2
= statement2
.getCatchBlocks();
339 if(catchBlocks1
.length
!= catchBlocks2
.length
){
342 for(int i
= 0; i
< catchBlocks2
.length
; i
++){
343 if(!codeBlocksAreEquivalent(catchBlocks1
[i
], catchBlocks2
[i
])){
347 final PsiParameter
[] catchParameters1
=
348 statement1
.getCatchBlockParameters();
349 final PsiParameter
[] catchParameters2
=
350 statement2
.getCatchBlockParameters();
351 if(catchParameters1
.length
!= catchParameters2
.length
){
354 for(int i
= 0; i
< catchParameters2
.length
; i
++){
355 if(!parametersAreEquivalent(catchParameters2
[i
],
356 catchParameters1
[i
])){
363 private static boolean parametersAreEquivalent(
364 @NotNull PsiParameter parameter1
,
365 @NotNull PsiParameter parameter2
) {
366 final PsiType type1
= parameter1
.getType();
367 final PsiType type2
= parameter2
.getType();
368 if(!typesAreEquivalent(type1
, type2
)){
371 final String name1
= parameter1
.getName();
372 final String name2
= parameter2
.getName();
374 return name2
== null;
376 return name1
.equals(name2
);
379 public static boolean typesAreEquivalent(
380 @Nullable PsiType type1
, @Nullable PsiType type2
){
382 return type2
== null;
387 final String type1Text
= type1
.getCanonicalText();
388 final String type2Text
= type2
.getCanonicalText();
389 return type1Text
.equals(type2Text
);
392 private static boolean whileStatementsAreEquivalent(
393 @NotNull PsiWhileStatement statement1
,
394 @NotNull PsiWhileStatement statement2
){
395 final PsiExpression condition1
= statement1
.getCondition();
396 final PsiExpression condition2
= statement2
.getCondition();
397 final PsiStatement body1
= statement1
.getBody();
398 final PsiStatement body2
= statement2
.getBody();
399 return expressionsAreEquivalent(condition1
, condition2
) &&
400 statementsAreEquivalent(body1
, body2
);
403 private static boolean forStatementsAreEquivalent(
404 @NotNull PsiForStatement statement1
,
405 @NotNull PsiForStatement statement2
) {
406 final PsiExpression condition1
= statement1
.getCondition();
407 final PsiExpression condition2
= statement2
.getCondition();
408 if(!expressionsAreEquivalent(condition1
, condition2
)){
411 final PsiStatement initialization1
= statement1
.getInitialization();
412 final PsiStatement initialization2
= statement2
.getInitialization();
413 if(!statementsAreEquivalent(initialization1
, initialization2
)){
416 final PsiStatement update1
= statement1
.getUpdate();
417 final PsiStatement update2
= statement2
.getUpdate();
418 if(!statementsAreEquivalent(update1
, update2
)){
421 final PsiStatement body1
= statement1
.getBody();
422 final PsiStatement body2
= statement2
.getBody();
423 return statementsAreEquivalent(body1
, body2
);
426 private static boolean forEachStatementsAreEquivalent(
427 @NotNull PsiForeachStatement statement1
,
428 @NotNull PsiForeachStatement statement2
) {
429 final PsiExpression value1
= statement1
.getIteratedValue();
430 final PsiExpression value2
= statement2
.getIteratedValue();
431 if(!expressionsAreEquivalent(value1
, value2
)){
434 final PsiParameter parameter1
= statement1
.getIterationParameter();
435 final PsiParameter parameter2
= statement1
.getIterationParameter();
436 final String name1
= parameter1
.getName();
437 final String name2
= parameter2
.getName();
442 } else if (name2
== null) {
444 } else if (!name1
.equals(name2
)){
447 final PsiType type1
= parameter1
.getType();
448 if(!type1
.equals(parameter2
.getType())){
451 final PsiStatement body1
= statement1
.getBody();
452 final PsiStatement body2
= statement2
.getBody();
453 return statementsAreEquivalent(body1
, body2
);
456 private static boolean switchStatementsAreEquivalent(
457 @NotNull PsiSwitchStatement statement1
,
458 @NotNull PsiSwitchStatement statement2
) {
459 final PsiExpression switchExpression1
= statement1
.getExpression();
460 final PsiExpression swithcExpression2
= statement2
.getExpression();
461 final PsiCodeBlock body1
= statement1
.getBody();
462 final PsiCodeBlock body2
= statement2
.getBody();
463 return expressionsAreEquivalent(switchExpression1
, swithcExpression2
) &&
464 codeBlocksAreEquivalent(body1
, body2
);
467 private static boolean doWhileStatementsAreEquivalent(
468 @NotNull PsiDoWhileStatement statement1
,
469 @NotNull PsiDoWhileStatement statement2
) {
470 final PsiExpression condition1
= statement1
.getCondition();
471 final PsiExpression condition2
= statement2
.getCondition();
472 final PsiStatement body1
= statement1
.getBody();
473 final PsiStatement body2
= statement2
.getBody();
474 return expressionsAreEquivalent(condition1
, condition2
) &&
475 statementsAreEquivalent(body1
, body2
);
478 private static boolean assertStatementsAreEquivalent(
479 @NotNull PsiAssertStatement statement1
,
480 @NotNull PsiAssertStatement statement2
) {
481 final PsiExpression condition1
= statement1
.getAssertCondition();
482 final PsiExpression condition2
= statement2
.getAssertCondition();
483 final PsiExpression description1
= statement1
.getAssertDescription();
484 final PsiExpression description2
= statement2
.getAssertDescription();
485 return expressionsAreEquivalent(condition1
, condition2
) &&
486 expressionsAreEquivalent(description1
, description2
);
489 private static boolean synchronizedStatementsAreEquivalent(
490 @NotNull PsiSynchronizedStatement statement1
,
491 @NotNull PsiSynchronizedStatement statement2
) {
492 final PsiExpression lock1
= statement1
.getLockExpression();
493 final PsiExpression lock2
= statement2
.getLockExpression();
494 final PsiCodeBlock body1
= statement1
.getBody();
495 final PsiCodeBlock body2
= statement2
.getBody();
496 return expressionsAreEquivalent(lock1
, lock2
) &&
497 codeBlocksAreEquivalent(body1
, body2
);
500 private static boolean blockStatementsAreEquivalent(
501 @NotNull PsiBlockStatement statement1
,
502 @NotNull PsiBlockStatement statement2
){
503 final PsiCodeBlock block1
= statement1
.getCodeBlock();
504 final PsiCodeBlock block2
= statement2
.getCodeBlock();
505 return codeBlocksAreEquivalent(block1
, block2
);
508 private static boolean breakStatementsAreEquivalent(
509 @NotNull PsiBreakStatement statement1
,
510 @NotNull PsiBreakStatement statement2
) {
511 final PsiIdentifier identifier1
= statement1
.getLabelIdentifier();
512 final PsiIdentifier identifier2
= statement2
.getLabelIdentifier();
513 if(identifier1
== null){
514 return identifier2
== null;
516 if(identifier2
== null){
519 final String text1
= identifier1
.getText();
520 final String text2
= identifier2
.getText();
521 return text1
.equals(text2
);
524 private static boolean continueStatementsAreEquivalent(
525 @NotNull PsiContinueStatement statement1
,
526 @NotNull PsiContinueStatement statement2
) {
527 final PsiIdentifier identifier1
= statement1
.getLabelIdentifier();
528 final PsiIdentifier identifier2
= statement2
.getLabelIdentifier();
529 if(identifier1
== null){
530 return identifier2
== null;
532 if(identifier2
== null){
535 final String text1
= identifier1
.getText();
536 final String text2
= identifier2
.getText();
537 return text1
.equals(text2
);
540 private static boolean switchLabelStatementsAreEquivalent(
541 @NotNull PsiSwitchLabelStatement statement1
,
542 @NotNull PsiSwitchLabelStatement statement2
) {
543 if (statement1
.isDefaultCase()){
544 return statement2
.isDefaultCase();
546 if(statement2
.isDefaultCase()){
549 final PsiExpression caseExpression1
= statement1
.getCaseValue();
550 final PsiExpression caseExpression2
= statement2
.getCaseValue();
551 return expressionsAreEquivalent(caseExpression1
, caseExpression2
);
554 private static boolean labeledStatementsAreEquivalent(
555 @NotNull PsiLabeledStatement statement1
,
556 @NotNull PsiLabeledStatement statement2
) {
557 final PsiIdentifier identifier1
= statement1
.getLabelIdentifier();
558 final PsiIdentifier identifier2
= statement2
.getLabelIdentifier();
559 final String text1
= identifier1
.getText();
560 final String text2
= identifier2
.getText();
561 return text1
.equals(text2
);
564 public static boolean codeBlocksAreEquivalent(
565 @Nullable PsiCodeBlock block1
, @Nullable PsiCodeBlock block2
) {
566 if (block1
== null && block2
== null){
569 if(block1
== null || block2
== null){
572 final PsiStatement
[] statements1
= block1
.getStatements();
573 final PsiStatement
[] statements2
= block2
.getStatements();
574 if(statements2
.length
!= statements1
.length
){
577 for(int i
= 0; i
< statements2
.length
; i
++){
578 if(!statementsAreEquivalent(statements2
[i
], statements1
[i
])){
585 private static boolean ifStatementsAreEquivalent(
586 @NotNull PsiIfStatement statement1
,
587 @NotNull PsiIfStatement statement2
) {
588 final PsiExpression condition1
= statement1
.getCondition();
589 final PsiExpression condition2
= statement2
.getCondition();
590 final PsiStatement thenBranch1
= statement1
.getThenBranch();
591 final PsiStatement thenBranch2
= statement2
.getThenBranch();
592 final PsiStatement elseBranch1
= statement1
.getElseBranch();
593 final PsiStatement elseBranch2
= statement2
.getElseBranch();
594 return expressionsAreEquivalent(condition1
, condition2
) &&
595 statementsAreEquivalent(thenBranch1
, thenBranch2
) &&
596 statementsAreEquivalent(elseBranch1
, elseBranch2
);
599 private static boolean expressionStatementsAreEquivalent(
600 @NotNull PsiExpressionStatement statement1
,
601 @NotNull PsiExpressionStatement statement2
) {
602 final PsiExpression expression1
= statement1
.getExpression();
603 final PsiExpression expression2
= statement2
.getExpression();
604 return expressionsAreEquivalent(expression1
, expression2
);
607 private static boolean returnStatementsAreEquivalent(
608 @NotNull PsiReturnStatement statement1
,
609 @NotNull PsiReturnStatement statement2
) {
610 final PsiExpression returnValue1
= statement1
.getReturnValue();
611 final PsiExpression returnValue2
= statement2
.getReturnValue();
612 return expressionsAreEquivalent(returnValue1
, returnValue2
);
615 private static boolean throwStatementsAreEquivalent(
616 @NotNull PsiThrowStatement statement1
,
617 @NotNull PsiThrowStatement statement2
) {
618 final PsiExpression exception1
= statement1
.getException();
619 final PsiExpression exception2
= statement2
.getException();
620 return expressionsAreEquivalent(exception1
, exception2
);
623 private static boolean expressionListStatementsAreEquivalent(
624 @NotNull PsiExpressionListStatement statement1
,
625 @NotNull PsiExpressionListStatement statement2
) {
626 final PsiExpressionList expressionList1
=
627 statement1
.getExpressionList();
628 final PsiExpression
[] expressions1
= expressionList1
.getExpressions();
629 final PsiExpressionList expressionList2
=
630 statement2
.getExpressionList();
631 final PsiExpression
[] expressions2
= expressionList2
.getExpressions();
632 return expressionListsAreEquivalent(expressions1
, expressions2
);
635 public static boolean expressionsAreEquivalent(
636 @Nullable PsiExpression exp1
, @Nullable PsiExpression exp2
) {
637 if (exp1
== null && exp2
== null){
640 if(exp1
== null || exp2
== null){
643 PsiExpression expToCompare1
= exp1
;
644 while(expToCompare1
instanceof PsiParenthesizedExpression
){
645 final PsiParenthesizedExpression parenthesizedExpression
=
646 (PsiParenthesizedExpression
)expToCompare1
;
647 expToCompare1
= parenthesizedExpression
.getExpression();
649 PsiExpression expToCompare2
= exp2
;
650 while(expToCompare2
instanceof PsiParenthesizedExpression
){
651 final PsiParenthesizedExpression parenthesizedExpression
=
652 (PsiParenthesizedExpression
)expToCompare2
;
653 expToCompare2
= parenthesizedExpression
.getExpression();
655 if (expToCompare1
== null && expToCompare2
== null){
658 if(expToCompare1
== null || expToCompare2
== null){
661 if (expToCompare1
.getClass() != expToCompare2
.getClass()) {
664 if (expToCompare1
instanceof PsiThisExpression
) {
666 } else if (expToCompare1
instanceof PsiSuperExpression
) {
668 } else if (expToCompare1
instanceof PsiLiteralExpression
) {
669 final String text1
= expToCompare1
.getText();
670 final String text2
= expToCompare2
.getText();
671 return text1
.equals(text2
);
672 } else if (expToCompare1
instanceof PsiClassObjectAccessExpression
) {
673 final String text1
= expToCompare1
.getText();
674 final String text2
= expToCompare2
.getText();
675 return text1
.equals(text2
);
676 } else if (expToCompare1
instanceof PsiReferenceExpression
) {
677 return referenceExpressionsAreEquivalent(
678 (PsiReferenceExpression
) expToCompare1
,
679 (PsiReferenceExpression
) expToCompare2
);
680 } else if (expToCompare1
instanceof PsiMethodCallExpression
) {
681 return methodCallExpressionsAreEquivalent(
682 (PsiMethodCallExpression
) expToCompare1
,
683 (PsiMethodCallExpression
) expToCompare2
);
684 } else if (expToCompare1
instanceof PsiNewExpression
) {
685 return newExpressionsAreEquivalent(
686 (PsiNewExpression
) expToCompare1
,
687 (PsiNewExpression
) expToCompare2
);
688 } else if (expToCompare1
instanceof PsiArrayInitializerExpression
) {
689 return arrayInitializerExpressionsAreEquivalent(
690 (PsiArrayInitializerExpression
) expToCompare1
,
691 (PsiArrayInitializerExpression
) expToCompare2
);
692 } else if (expToCompare1
instanceof PsiTypeCastExpression
) {
693 return typecastExpressionsAreEquivalent(
694 (PsiTypeCastExpression
) expToCompare1
,
695 (PsiTypeCastExpression
) expToCompare2
);
696 } else if (expToCompare1
instanceof PsiArrayAccessExpression
) {
697 return arrayAccessExpressionsAreEquivalent(
698 (PsiArrayAccessExpression
) expToCompare2
,
699 (PsiArrayAccessExpression
) expToCompare1
);
700 } else if (expToCompare1
instanceof PsiPrefixExpression
) {
701 return prefixExpressionsAreEquivalent(
702 (PsiPrefixExpression
) expToCompare1
,
703 (PsiPrefixExpression
) expToCompare2
);
704 } else if (expToCompare1
instanceof PsiPostfixExpression
) {
705 return postfixExpressionsAreEquivalent(
706 (PsiPostfixExpression
) expToCompare1
,
707 (PsiPostfixExpression
) expToCompare2
);
708 } else if (expToCompare1
instanceof PsiBinaryExpression
) {
709 return binaryExpressionsAreEquivalent(
710 (PsiBinaryExpression
) expToCompare1
,
711 (PsiBinaryExpression
) expToCompare2
);
712 } else if (expToCompare1
instanceof PsiAssignmentExpression
) {
713 return assignmentExpressionsAreEquivalent(
714 (PsiAssignmentExpression
) expToCompare1
,
715 (PsiAssignmentExpression
) expToCompare2
);
716 } else if (expToCompare1
instanceof PsiConditionalExpression
) {
717 return conditionalExpressionsAreEquivalent(
718 (PsiConditionalExpression
) expToCompare1
,
719 (PsiConditionalExpression
) expToCompare2
);
720 } else if (expToCompare1
instanceof PsiInstanceOfExpression
) {
721 return instanceofExpressionsAreEquivalent(
722 (PsiInstanceOfExpression
) expToCompare1
,
723 (PsiInstanceOfExpression
) expToCompare2
);
728 private static boolean referenceExpressionsAreEquivalent(
729 PsiReferenceExpression referenceExpression1
,
730 PsiReferenceExpression referenceExpression2
) {
731 final PsiElement element1
= referenceExpression1
.resolve();
732 final PsiElement element2
= referenceExpression2
.resolve();
733 if (element1
!= null) {
734 if (!element1
.equals(element2
)) {
738 return element2
== null;
740 if (element1
instanceof PsiMember
) {
741 final PsiMember member1
= (PsiMember
)element1
;
742 if (member1
.hasModifierProperty(PsiModifier
.STATIC
)) {
744 } else if (member1
instanceof PsiClass
) {
750 final PsiExpression qualifier1
=
751 referenceExpression1
.getQualifierExpression();
752 final PsiExpression qualifier2
=
753 referenceExpression2
.getQualifierExpression();
754 if (qualifier1
!= null &&
755 !(qualifier1
instanceof PsiThisExpression
||
756 qualifier1
instanceof PsiSuperExpression
)) {
757 if (qualifier2
== null) {
759 } else if (!expressionsAreEquivalent(qualifier1
, qualifier2
)) {
763 if (qualifier2
!= null &&
764 !(qualifier2
instanceof PsiThisExpression
||
765 qualifier2
instanceof PsiSuperExpression
)) {
769 final String text1
= referenceExpression1
.getText();
770 final String text2
= referenceExpression2
.getText();
771 return text1
.equals(text2
);
774 private static boolean instanceofExpressionsAreEquivalent(
775 PsiInstanceOfExpression instanceOfExpression1
,
776 PsiInstanceOfExpression instanceOfExpression2
) {
777 final PsiExpression operand1
= instanceOfExpression1
.getOperand();
778 final PsiExpression operand2
= instanceOfExpression2
.getOperand();
779 if (!expressionsAreEquivalent(operand1
, operand2
)) {
782 final PsiTypeElement typeElement1
=
783 instanceOfExpression1
.getCheckType();
784 final PsiTypeElement typeElement2
=
785 instanceOfExpression2
.getCheckType();
786 if (typeElement1
== null) {
787 return typeElement2
== null;
788 } else if (typeElement2
== null) {
791 final PsiType type1
= typeElement1
.getType();
792 final PsiType type2
= typeElement2
.getType();
793 return typesAreEquivalent(type1
, type2
);
796 private static boolean methodCallExpressionsAreEquivalent(
797 @NotNull PsiMethodCallExpression methodExp1
,
798 @NotNull PsiMethodCallExpression methodExp2
){
799 final PsiReferenceExpression methodExpression1
=
800 methodExp1
.getMethodExpression();
801 final PsiReferenceExpression methodExpression2
=
802 methodExp2
.getMethodExpression();
803 if(!expressionsAreEquivalent(methodExpression1
, methodExpression2
)){
806 final PsiExpressionList argumentList1
= methodExp1
.getArgumentList();
807 final PsiExpression
[] args1
= argumentList1
.getExpressions();
808 final PsiExpressionList argumentList2
= methodExp2
.getArgumentList();
809 final PsiExpression
[] args2
= argumentList2
.getExpressions();
810 return expressionListsAreEquivalent(args1
, args2
);
813 private static boolean newExpressionsAreEquivalent(
814 @NotNull PsiNewExpression newExp1
,
815 @NotNull PsiNewExpression newExp2
) {
816 final PsiJavaCodeReferenceElement classRef1
=
817 newExp1
.getClassReference();
818 final PsiJavaCodeReferenceElement classRef2
=
819 newExp2
.getClassReference();
820 if (classRef1
== null || classRef2
== null) {
823 final String text
= classRef1
.getText();
824 if (!text
.equals(classRef2
.getText())) {
827 final PsiExpression
[] arrayDimensions1
= newExp1
.getArrayDimensions();
828 final PsiExpression
[] arrayDimensions2
= newExp2
.getArrayDimensions();
829 if (!expressionListsAreEquivalent(arrayDimensions1
, arrayDimensions2
)) {
832 final PsiArrayInitializerExpression arrayInitializer1
=
833 newExp1
.getArrayInitializer();
834 final PsiArrayInitializerExpression arrayInitializer2
=
835 newExp2
.getArrayInitializer();
836 if (!expressionsAreEquivalent(arrayInitializer1
, arrayInitializer2
)) {
839 final PsiExpression qualifier1
= newExp1
.getQualifier();
840 final PsiExpression qualifier2
= newExp2
.getQualifier();
841 if (!expressionsAreEquivalent(qualifier1
, qualifier2
)) {
844 final PsiExpressionList argumentList1
= newExp1
.getArgumentList();
845 final PsiExpression
[] args1
;
846 if (argumentList1
== null) {
849 args1
= argumentList1
.getExpressions();
851 final PsiExpressionList argumentList2
= newExp2
.getArgumentList();
852 final PsiExpression
[] args2
;
853 if (argumentList2
== null) {
856 args2
= argumentList2
.getExpressions();
858 return expressionListsAreEquivalent(args1
, args2
);
861 private static boolean arrayInitializerExpressionsAreEquivalent(
862 @NotNull PsiArrayInitializerExpression arrInitExp1
,
863 @NotNull PsiArrayInitializerExpression arrInitExp2
){
864 final PsiExpression
[] initializers1
= arrInitExp1
.getInitializers();
865 final PsiExpression
[] initializers2
= arrInitExp2
.getInitializers();
866 return expressionListsAreEquivalent(initializers1
, initializers2
);
869 private static boolean typecastExpressionsAreEquivalent(
870 @NotNull PsiTypeCastExpression typecastExp1
,
871 @NotNull PsiTypeCastExpression typecastExp2
) {
872 final PsiTypeElement typeElement1
= typecastExp1
.getCastType();
873 final PsiTypeElement typeElement2
= typecastExp2
.getCastType();
874 if (typeElement1
== null && typeElement2
== null) {
877 if (typeElement1
== null || typeElement2
== null) {
880 final PsiType type1
= typeElement1
.getType();
881 final PsiType type2
= typeElement2
.getType();
882 if(!typesAreEquivalent(type1
, type2
)) {
885 final PsiExpression operand1
= typecastExp1
.getOperand();
886 final PsiExpression operand2
= typecastExp2
.getOperand();
887 return expressionsAreEquivalent(operand1
, operand2
);
890 private static boolean arrayAccessExpressionsAreEquivalent(
891 @NotNull PsiArrayAccessExpression arrAccessExp2
,
892 @NotNull PsiArrayAccessExpression arrAccessExp1
){
893 final PsiExpression arrayExpression2
=
894 arrAccessExp2
.getArrayExpression();
895 final PsiExpression arrayExpression1
=
896 arrAccessExp1
.getArrayExpression();
897 final PsiExpression indexExpression2
=
898 arrAccessExp2
.getIndexExpression();
899 final PsiExpression indexExpression1
=
900 arrAccessExp1
.getIndexExpression();
901 return expressionsAreEquivalent(arrayExpression2
, arrayExpression1
)
902 && expressionsAreEquivalent(indexExpression2
, indexExpression1
);
905 private static boolean prefixExpressionsAreEquivalent(
906 @NotNull PsiPrefixExpression prefixExp1
,
907 @NotNull PsiPrefixExpression prefixExp2
){
908 final PsiJavaToken sign1
= prefixExp1
.getOperationSign();
909 final PsiJavaToken sign2
= prefixExp2
.getOperationSign();
910 final IElementType tokenType1
= sign1
.getTokenType();
911 if(!tokenType1
.equals(sign2
.getTokenType())){
914 final PsiExpression operand1
= prefixExp1
.getOperand();
915 final PsiExpression operand2
= prefixExp2
.getOperand();
916 return expressionsAreEquivalent(operand1
, operand2
);
919 private static boolean postfixExpressionsAreEquivalent(
920 @NotNull PsiPostfixExpression postfixExp1
,
921 @NotNull PsiPostfixExpression postfixExp2
){
922 final PsiJavaToken sign1
= postfixExp1
.getOperationSign();
923 final PsiJavaToken sign2
= postfixExp2
.getOperationSign();
924 final IElementType tokenType1
= sign1
.getTokenType();
925 if(!tokenType1
.equals(sign2
.getTokenType())){
928 final PsiExpression operand1
= postfixExp1
.getOperand();
929 final PsiExpression operand2
= postfixExp2
.getOperand();
930 return expressionsAreEquivalent(operand1
, operand2
);
933 private static boolean binaryExpressionsAreEquivalent(
934 @NotNull PsiBinaryExpression binaryExp1
,
935 @NotNull PsiBinaryExpression binaryExp2
){
936 final PsiJavaToken sign1
= binaryExp1
.getOperationSign();
937 final PsiJavaToken sign2
= binaryExp2
.getOperationSign();
938 final IElementType tokenType1
= sign1
.getTokenType();
939 if(!tokenType1
.equals(sign2
.getTokenType())){
942 final PsiExpression lhs1
= binaryExp1
.getLOperand();
943 final PsiExpression lhs2
= binaryExp2
.getLOperand();
944 final PsiExpression rhs1
= binaryExp1
.getROperand();
945 final PsiExpression rhs2
= binaryExp2
.getROperand();
946 return expressionsAreEquivalent(lhs1
, lhs2
)
947 && expressionsAreEquivalent(rhs1
, rhs2
);
950 private static boolean assignmentExpressionsAreEquivalent(
951 @NotNull PsiAssignmentExpression assignExp1
,
952 @NotNull PsiAssignmentExpression assignExp2
){
953 final PsiJavaToken sign1
= assignExp1
.getOperationSign();
954 final PsiJavaToken sign2
= assignExp2
.getOperationSign();
955 final IElementType tokenType1
= sign1
.getTokenType();
956 if(!tokenType1
.equals(sign2
.getTokenType())){
959 final PsiExpression lhs1
= assignExp1
.getLExpression();
960 final PsiExpression lhs2
= assignExp2
.getLExpression();
961 final PsiExpression rhs1
= assignExp1
.getRExpression();
962 final PsiExpression rhs2
= assignExp2
.getRExpression();
963 return expressionsAreEquivalent(lhs1
, lhs2
)
964 && expressionsAreEquivalent(rhs1
, rhs2
);
967 private static boolean conditionalExpressionsAreEquivalent(
968 @NotNull PsiConditionalExpression condExp1
,
969 @NotNull PsiConditionalExpression condExp2
){
970 final PsiExpression condition1
= condExp1
.getCondition();
971 final PsiExpression condition2
= condExp2
.getCondition();
972 final PsiExpression thenExpression1
= condExp1
.getThenExpression();
973 final PsiExpression thenExpression2
= condExp2
.getThenExpression();
974 final PsiExpression elseExpression1
= condExp1
.getElseExpression();
975 final PsiExpression elseExpression2
= condExp2
.getElseExpression();
976 return expressionsAreEquivalent(condition1
, condition2
)
977 && expressionsAreEquivalent(thenExpression1
, thenExpression2
)
978 && expressionsAreEquivalent(elseExpression1
, elseExpression2
);
981 private static boolean expressionListsAreEquivalent(
982 @Nullable PsiExpression
[] expressions1
,
983 @Nullable PsiExpression
[] expressions2
){
984 if(expressions1
== null && expressions2
== null){
987 if(expressions1
== null || expressions2
== null){
990 if(expressions1
.length
!= expressions2
.length
){
993 for(int i
= 0; i
< expressions1
.length
; i
++){
994 if(!expressionsAreEquivalent(expressions1
[i
], expressions2
[i
])){