blob: e6f88ab42457c48d5856080351f68a574c45d797 [file] [log] [blame]
/*
* Copyright 2003-2014 Dave Griffith, Bas Leijdekkers
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.siyeh.ig.psiutils;
import com.intellij.psi.*;
import com.intellij.psi.tree.IElementType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.List;
public class EquivalenceChecker {
private EquivalenceChecker() {}
public static boolean statementsAreEquivalent(@Nullable PsiStatement statement1, @Nullable PsiStatement statement2) {
if (statement1 == null) {
return statement2 == null;
} else if (statement2 == null) {
return false;
}
if (statement1.getClass() != statement2.getClass()) {
if (statement1 instanceof PsiBlockStatement && !(statement2 instanceof PsiBlockStatement)) {
final PsiBlockStatement blockStatement = (PsiBlockStatement)statement1;
final PsiStatement[] statements = blockStatement.getCodeBlock().getStatements();
if (statements.length != 1) {
return false;
}
statement1 = statements[0];
}
else if (!(statement1 instanceof PsiBlockStatement) && statement2 instanceof PsiBlockStatement) {
final PsiBlockStatement blockStatement = (PsiBlockStatement)statement2;
final PsiStatement[] statements = blockStatement.getCodeBlock().getStatements();
if (statements.length != 1) {
return false;
}
statement2 = statements[0];
}
else {
return false;
}
if (statement1.getClass() != statement2.getClass()) {
return false;
}
}
if (statement1 instanceof PsiAssertStatement) {
return assertStatementsAreEquivalent((PsiAssertStatement)statement1, (PsiAssertStatement)statement2);
}
if (statement1 instanceof PsiBlockStatement) {
return blockStatementsAreEquivalent((PsiBlockStatement)statement1, (PsiBlockStatement)statement2);
}
if (statement1 instanceof PsiBreakStatement) {
return breakStatementsAreEquivalent((PsiBreakStatement)statement1, (PsiBreakStatement)statement2);
}
if (statement1 instanceof PsiContinueStatement) {
return continueStatementsAreEquivalent((PsiContinueStatement)statement1, (PsiContinueStatement)statement2);
}
if (statement1 instanceof PsiDeclarationStatement) {
return declarationStatementsAreEquivalent((PsiDeclarationStatement)statement1, (PsiDeclarationStatement)statement2);
}
if (statement1 instanceof PsiDoWhileStatement) {
return doWhileStatementsAreEquivalent((PsiDoWhileStatement)statement1, (PsiDoWhileStatement)statement2);
}
if (statement1 instanceof PsiEmptyStatement) {
return true;
}
if (statement1 instanceof PsiExpressionListStatement) {
return expressionListStatementsAreEquivalent((PsiExpressionListStatement)statement1, (PsiExpressionListStatement)statement2);
}
if (statement1 instanceof PsiExpressionStatement) {
return expressionStatementsAreEquivalent((PsiExpressionStatement)statement1, (PsiExpressionStatement)statement2);
}
if (statement1 instanceof PsiForStatement) {
return forStatementsAreEquivalent((PsiForStatement)statement1, (PsiForStatement)statement2);
}
if (statement1 instanceof PsiForeachStatement) {
return forEachStatementsAreEquivalent((PsiForeachStatement)statement1, (PsiForeachStatement)statement2);
}
if (statement1 instanceof PsiIfStatement) {
return ifStatementsAreEquivalent((PsiIfStatement)statement1, (PsiIfStatement)statement2);
}
if (statement1 instanceof PsiLabeledStatement) {
return labeledStatementsAreEquivalent((PsiLabeledStatement)statement1, (PsiLabeledStatement)statement2);
}
if (statement1 instanceof PsiReturnStatement) {
return returnStatementsAreEquivalent((PsiReturnStatement)statement1, (PsiReturnStatement)statement2);
}
if (statement1 instanceof PsiSwitchStatement) {
return switchStatementsAreEquivalent((PsiSwitchStatement)statement1, (PsiSwitchStatement)statement2);
}
if (statement1 instanceof PsiSwitchLabelStatement) {
return switchLabelStatementsAreEquivalent((PsiSwitchLabelStatement)statement1, (PsiSwitchLabelStatement)statement2);
}
if (statement1 instanceof PsiSynchronizedStatement) {
return synchronizedStatementsAreEquivalent((PsiSynchronizedStatement)statement1, (PsiSynchronizedStatement)statement2);
}
if (statement1 instanceof PsiThrowStatement) {
return throwStatementsAreEquivalent((PsiThrowStatement)statement1, (PsiThrowStatement)statement2);
}
if (statement1 instanceof PsiTryStatement) {
return tryStatementsAreEquivalent((PsiTryStatement)statement1, (PsiTryStatement)statement2);
}
if (statement1 instanceof PsiWhileStatement) {
return whileStatementsAreEquivalent((PsiWhileStatement)statement1, (PsiWhileStatement)statement2);
}
final String text1 = statement1.getText();
final String text2 = statement2.getText();
return text1.equals(text2);
}
private static boolean declarationStatementsAreEquivalent(
@NotNull PsiDeclarationStatement statement1,
@NotNull PsiDeclarationStatement statement2) {
final PsiElement[] elements1 = statement1.getDeclaredElements();
final List<PsiLocalVariable> vars1 =
new ArrayList<PsiLocalVariable>(elements1.length);
for (PsiElement anElement : elements1) {
if (anElement instanceof PsiLocalVariable) {
vars1.add((PsiLocalVariable)anElement);
}
}
final PsiElement[] elements2 = statement2.getDeclaredElements();
final List<PsiLocalVariable> vars2 =
new ArrayList<PsiLocalVariable>(elements2.length);
for (PsiElement anElement : elements2) {
if (anElement instanceof PsiLocalVariable) {
vars2.add((PsiLocalVariable)anElement);
}
}
final int size = vars1.size();
if (size != vars2.size()) {
return false;
}
for (int i = 0; i < size; i++) {
final PsiLocalVariable var1 = vars1.get(i);
final PsiLocalVariable var2 = vars2.get(i);
if (!localVariablesAreEquivalent(var1, var2)) {
return false;
}
}
return true;
}
private static boolean localVariablesAreEquivalent(
@NotNull PsiLocalVariable localVariable1,
@NotNull PsiLocalVariable localVariable2) {
final PsiType type1 = localVariable1.getType();
final PsiType type2 = localVariable2.getType();
if (!typesAreEquivalent(type1, type2)) {
return false;
}
final String name1 = localVariable1.getName();
final String name2 = localVariable2.getName();
if (name1 == null) {
return name2 == null;
}
if (!name1.equals(name2)) {
return false;
}
final PsiExpression initializer1 = localVariable1.getInitializer();
final PsiExpression initializer2 = localVariable2.getInitializer();
return expressionsAreEquivalent(initializer1, initializer2);
}
private static boolean tryStatementsAreEquivalent(@NotNull PsiTryStatement statement1, @NotNull PsiTryStatement statement2) {
final PsiCodeBlock tryBlock1 = statement1.getTryBlock();
final PsiCodeBlock tryBlock2 = statement2.getTryBlock();
if (!codeBlocksAreEquivalent(tryBlock1, tryBlock2)) {
return false;
}
final PsiCodeBlock finallyBlock1 = statement1.getFinallyBlock();
final PsiCodeBlock finallyBlock2 = statement2.getFinallyBlock();
if (!codeBlocksAreEquivalent(finallyBlock1, finallyBlock2)) {
return false;
}
final PsiCodeBlock[] catchBlocks1 = statement1.getCatchBlocks();
final PsiCodeBlock[] catchBlocks2 = statement2.getCatchBlocks();
if (catchBlocks1.length != catchBlocks2.length) {
return false;
}
for (int i = 0; i < catchBlocks2.length; i++) {
if (!codeBlocksAreEquivalent(catchBlocks1[i], catchBlocks2[i])) {
return false;
}
}
final PsiResourceList resourceList1 = statement1.getResourceList();
final PsiResourceList resourceList2 = statement2.getResourceList();
if (resourceList1 != null) {
if (resourceList2 == null) {
return false;
}
if (resourceList1.getResourceVariablesCount() != resourceList2.getResourceVariablesCount()) {
return false;
}
final List<PsiResourceVariable> resourceVariables1 = resourceList1.getResourceVariables();
final List<PsiResourceVariable> resourceVariables2 = resourceList2.getResourceVariables();
for (int i1 = 0, size = resourceVariables1.size(); i1 < size; i1++) {
final PsiResourceVariable variable1 = resourceVariables1.get(i1);
final PsiResourceVariable variable2 = resourceVariables2.get(i1);
if (!localVariablesAreEquivalent(variable1, variable2)) {
return false;
}
}
} else if (resourceList2 != null) {
return false;
}
final PsiParameter[] catchParameters1 = statement1.getCatchBlockParameters();
final PsiParameter[] catchParameters2 = statement2.getCatchBlockParameters();
if (catchParameters1.length != catchParameters2.length) {
return false;
}
for (int i = 0; i < catchParameters2.length; i++) {
if (!parametersAreEquivalent(catchParameters2[i], catchParameters1[i])) {
return false;
}
}
return true;
}
private static boolean parametersAreEquivalent(
@NotNull PsiParameter parameter1,
@NotNull PsiParameter parameter2) {
final PsiType type1 = parameter1.getType();
final PsiType type2 = parameter2.getType();
if (!typesAreEquivalent(type1, type2)) {
return false;
}
final String name1 = parameter1.getName();
final String name2 = parameter2.getName();
if (name1 == null) {
return name2 == null;
}
return name1.equals(name2);
}
public static boolean typesAreEquivalent(
@Nullable PsiType type1, @Nullable PsiType type2) {
if (type1 == null) {
return type2 == null;
}
if (type2 == null) {
return false;
}
final String type1Text = type1.getCanonicalText();
final String type2Text = type2.getCanonicalText();
return type1Text.equals(type2Text);
}
private static boolean whileStatementsAreEquivalent(
@NotNull PsiWhileStatement statement1,
@NotNull PsiWhileStatement statement2) {
final PsiExpression condition1 = statement1.getCondition();
final PsiExpression condition2 = statement2.getCondition();
final PsiStatement body1 = statement1.getBody();
final PsiStatement body2 = statement2.getBody();
return expressionsAreEquivalent(condition1, condition2) &&
statementsAreEquivalent(body1, body2);
}
private static boolean forStatementsAreEquivalent(
@NotNull PsiForStatement statement1,
@NotNull PsiForStatement statement2) {
final PsiExpression condition1 = statement1.getCondition();
final PsiExpression condition2 = statement2.getCondition();
if (!expressionsAreEquivalent(condition1, condition2)) {
return false;
}
final PsiStatement initialization1 = statement1.getInitialization();
final PsiStatement initialization2 = statement2.getInitialization();
if (!statementsAreEquivalent(initialization1, initialization2)) {
return false;
}
final PsiStatement update1 = statement1.getUpdate();
final PsiStatement update2 = statement2.getUpdate();
if (!statementsAreEquivalent(update1, update2)) {
return false;
}
final PsiStatement body1 = statement1.getBody();
final PsiStatement body2 = statement2.getBody();
return statementsAreEquivalent(body1, body2);
}
private static boolean forEachStatementsAreEquivalent(
@NotNull PsiForeachStatement statement1,
@NotNull PsiForeachStatement statement2) {
final PsiExpression value1 = statement1.getIteratedValue();
final PsiExpression value2 = statement2.getIteratedValue();
if (!expressionsAreEquivalent(value1, value2)) {
return false;
}
final PsiParameter parameter1 = statement1.getIterationParameter();
final PsiParameter parameter2 = statement1.getIterationParameter();
final String name1 = parameter1.getName();
if (name1 == null) {
return parameter2.getName() == null;
}
if (!name1.equals(parameter2.getName())) {
return false;
}
final PsiType type1 = parameter1.getType();
if (!type1.equals(parameter2.getType())) {
return false;
}
final PsiStatement body1 = statement1.getBody();
final PsiStatement body2 = statement2.getBody();
return statementsAreEquivalent(body1, body2);
}
private static boolean switchStatementsAreEquivalent(
@NotNull PsiSwitchStatement statement1,
@NotNull PsiSwitchStatement statement2) {
final PsiExpression switchExpression1 = statement1.getExpression();
final PsiExpression swithcExpression2 = statement2.getExpression();
final PsiCodeBlock body1 = statement1.getBody();
final PsiCodeBlock body2 = statement2.getBody();
return expressionsAreEquivalent(switchExpression1, swithcExpression2) &&
codeBlocksAreEquivalent(body1, body2);
}
private static boolean doWhileStatementsAreEquivalent(
@NotNull PsiDoWhileStatement statement1,
@NotNull PsiDoWhileStatement statement2) {
final PsiExpression condition1 = statement1.getCondition();
final PsiExpression condition2 = statement2.getCondition();
final PsiStatement body1 = statement1.getBody();
final PsiStatement body2 = statement2.getBody();
return expressionsAreEquivalent(condition1, condition2) &&
statementsAreEquivalent(body1, body2);
}
private static boolean assertStatementsAreEquivalent(
@NotNull PsiAssertStatement statement1,
@NotNull PsiAssertStatement statement2) {
final PsiExpression condition1 = statement1.getAssertCondition();
final PsiExpression condition2 = statement2.getAssertCondition();
final PsiExpression description1 = statement1.getAssertDescription();
final PsiExpression description2 = statement2.getAssertDescription();
return expressionsAreEquivalent(condition1, condition2) &&
expressionsAreEquivalent(description1, description2);
}
private static boolean synchronizedStatementsAreEquivalent(
@NotNull PsiSynchronizedStatement statement1,
@NotNull PsiSynchronizedStatement statement2) {
final PsiExpression lock1 = statement1.getLockExpression();
final PsiExpression lock2 = statement2.getLockExpression();
final PsiCodeBlock body1 = statement1.getBody();
final PsiCodeBlock body2 = statement2.getBody();
return expressionsAreEquivalent(lock1, lock2) &&
codeBlocksAreEquivalent(body1, body2);
}
private static boolean blockStatementsAreEquivalent(
@NotNull PsiBlockStatement statement1,
@NotNull PsiBlockStatement statement2) {
final PsiCodeBlock block1 = statement1.getCodeBlock();
final PsiCodeBlock block2 = statement2.getCodeBlock();
return codeBlocksAreEquivalent(block1, block2);
}
private static boolean breakStatementsAreEquivalent(
@NotNull PsiBreakStatement statement1,
@NotNull PsiBreakStatement statement2) {
final PsiIdentifier identifier1 = statement1.getLabelIdentifier();
final PsiIdentifier identifier2 = statement2.getLabelIdentifier();
if (identifier1 == null) {
return identifier2 == null;
}
if (identifier2 == null) {
return false;
}
final String text1 = identifier1.getText();
final String text2 = identifier2.getText();
return text1.equals(text2);
}
private static boolean continueStatementsAreEquivalent(
@NotNull PsiContinueStatement statement1,
@NotNull PsiContinueStatement statement2) {
final PsiIdentifier identifier1 = statement1.getLabelIdentifier();
final PsiIdentifier identifier2 = statement2.getLabelIdentifier();
if (identifier1 == null) {
return identifier2 == null;
}
if (identifier2 == null) {
return false;
}
final String text1 = identifier1.getText();
final String text2 = identifier2.getText();
return text1.equals(text2);
}
private static boolean switchLabelStatementsAreEquivalent(
@NotNull PsiSwitchLabelStatement statement1,
@NotNull PsiSwitchLabelStatement statement2) {
if (statement1.isDefaultCase()) {
return statement2.isDefaultCase();
}
if (statement2.isDefaultCase()) {
return false;
}
final PsiExpression caseExpression1 = statement1.getCaseValue();
final PsiExpression caseExpression2 = statement2.getCaseValue();
return expressionsAreEquivalent(caseExpression1, caseExpression2);
}
private static boolean labeledStatementsAreEquivalent(
@NotNull PsiLabeledStatement statement1,
@NotNull PsiLabeledStatement statement2) {
final PsiIdentifier identifier1 = statement1.getLabelIdentifier();
final PsiIdentifier identifier2 = statement2.getLabelIdentifier();
final String text1 = identifier1.getText();
final String text2 = identifier2.getText();
return text1.equals(text2);
}
public static boolean codeBlocksAreEquivalent(
@Nullable PsiCodeBlock block1, @Nullable PsiCodeBlock block2) {
if (block1 == null && block2 == null) {
return true;
}
if (block1 == null || block2 == null) {
return false;
}
final PsiStatement[] statements1 = block1.getStatements();
final PsiStatement[] statements2 = block2.getStatements();
if (statements2.length != statements1.length) {
return false;
}
for (int i = 0; i < statements2.length; i++) {
if (!statementsAreEquivalent(statements2[i], statements1[i])) {
return false;
}
}
return true;
}
private static boolean ifStatementsAreEquivalent(
@NotNull PsiIfStatement statement1,
@NotNull PsiIfStatement statement2) {
final PsiExpression condition1 = statement1.getCondition();
final PsiExpression condition2 = statement2.getCondition();
final PsiStatement thenBranch1 = statement1.getThenBranch();
final PsiStatement thenBranch2 = statement2.getThenBranch();
final PsiStatement elseBranch1 = statement1.getElseBranch();
final PsiStatement elseBranch2 = statement2.getElseBranch();
return expressionsAreEquivalent(condition1, condition2) &&
statementsAreEquivalent(thenBranch1, thenBranch2) &&
statementsAreEquivalent(elseBranch1, elseBranch2);
}
private static boolean expressionStatementsAreEquivalent(
@NotNull PsiExpressionStatement statement1,
@NotNull PsiExpressionStatement statement2) {
final PsiExpression expression1 = statement1.getExpression();
final PsiExpression expression2 = statement2.getExpression();
return expressionsAreEquivalent(expression1, expression2);
}
private static boolean returnStatementsAreEquivalent(
@NotNull PsiReturnStatement statement1,
@NotNull PsiReturnStatement statement2) {
final PsiExpression returnValue1 = statement1.getReturnValue();
final PsiExpression returnValue2 = statement2.getReturnValue();
return expressionsAreEquivalent(returnValue1, returnValue2);
}
private static boolean throwStatementsAreEquivalent(
@NotNull PsiThrowStatement statement1,
@NotNull PsiThrowStatement statement2) {
final PsiExpression exception1 = statement1.getException();
final PsiExpression exception2 = statement2.getException();
return expressionsAreEquivalent(exception1, exception2);
}
private static boolean expressionListStatementsAreEquivalent(
@NotNull PsiExpressionListStatement statement1,
@NotNull PsiExpressionListStatement statement2) {
final PsiExpressionList expressionList1 =
statement1.getExpressionList();
final PsiExpression[] expressions1 = expressionList1.getExpressions();
final PsiExpressionList expressionList2 =
statement2.getExpressionList();
final PsiExpression[] expressions2 = expressionList2.getExpressions();
return expressionListsAreEquivalent(expressions1, expressions2);
}
public static boolean expressionsAreEquivalent(@Nullable PsiExpression expression1, @Nullable PsiExpression expression2) {
expression1 = ParenthesesUtils.stripParentheses(expression1);
expression2 = ParenthesesUtils.stripParentheses(expression2);
if (expression1 == null) {
return expression2 == null;
} else if (expression2 == null) {
return false;
}
if (expression1.getClass() != expression2.getClass()) {
return false;
}
if (expression1 instanceof PsiThisExpression) {
return true;
}
else if (expression1 instanceof PsiSuperExpression) {
return true;
}
else if (expression1 instanceof PsiLiteralExpression) {
return literalExpressionsAreEquivalent((PsiLiteralExpression)expression1, (PsiLiteralExpression)expression2);
}
else if (expression1 instanceof PsiClassObjectAccessExpression) {
return classObjectAccessExpressionsAreEquivalent((PsiClassObjectAccessExpression)expression1,
(PsiClassObjectAccessExpression)expression2);
}
else if (expression1 instanceof PsiReferenceExpression) {
return referenceExpressionsAreEquivalent((PsiReferenceExpression)expression1, (PsiReferenceExpression)expression2);
}
else if (expression1 instanceof PsiMethodCallExpression) {
return methodCallExpressionsAreEquivalent((PsiMethodCallExpression)expression1, (PsiMethodCallExpression)expression2);
}
else if (expression1 instanceof PsiNewExpression) {
return newExpressionsAreEquivalent((PsiNewExpression)expression1, (PsiNewExpression)expression2);
}
else if (expression1 instanceof PsiArrayInitializerExpression) {
return arrayInitializerExpressionsAreEquivalent((PsiArrayInitializerExpression)expression1,
(PsiArrayInitializerExpression)expression2);
}
else if (expression1 instanceof PsiTypeCastExpression) {
return typeCastExpressionsAreEquivalent((PsiTypeCastExpression)expression1, (PsiTypeCastExpression)expression2);
}
else if (expression1 instanceof PsiArrayAccessExpression) {
return arrayAccessExpressionsAreEquivalent((PsiArrayAccessExpression)expression2, (PsiArrayAccessExpression)expression1);
}
else if (expression1 instanceof PsiPrefixExpression) {
return prefixExpressionsAreEquivalent((PsiPrefixExpression)expression1, (PsiPrefixExpression)expression2);
}
else if (expression1 instanceof PsiPostfixExpression) {
return postfixExpressionsAreEquivalent((PsiPostfixExpression)expression1, (PsiPostfixExpression)expression2);
}
else if (expression1 instanceof PsiPolyadicExpression) {
return polyadicExpressionsAreEquivalent((PsiPolyadicExpression)expression1, (PsiPolyadicExpression)expression2);
}
else if (expression1 instanceof PsiAssignmentExpression) {
return assignmentExpressionsAreEquivalent((PsiAssignmentExpression)expression1, (PsiAssignmentExpression)expression2);
}
else if (expression1 instanceof PsiConditionalExpression) {
return conditionalExpressionsAreEquivalent((PsiConditionalExpression)expression1, (PsiConditionalExpression)expression2);
}
else if (expression1 instanceof PsiInstanceOfExpression) {
return instanceofExpressionsAreEquivalent((PsiInstanceOfExpression)expression1, (PsiInstanceOfExpression)expression2);
}
return false;
}
private static boolean literalExpressionsAreEquivalent(PsiLiteralExpression expression1, PsiLiteralExpression expression2) {
final Object value1 = expression1.getValue();
final Object value2 = expression2.getValue();
if (value1 == null) {
return value2 == null;
} else if (value2 == null) {
return false;
}
return value1.equals(value2);
}
private static boolean classObjectAccessExpressionsAreEquivalent(PsiClassObjectAccessExpression expression1,
PsiClassObjectAccessExpression expression2) {
final PsiTypeElement operand1 = expression1.getOperand();
final PsiTypeElement operand2 = expression2.getOperand();
return typeElementsAreEquivalent(operand1, operand2);
}
private static boolean referenceExpressionsAreEquivalent(
PsiReferenceExpression referenceExpression1,
PsiReferenceExpression referenceExpression2) {
final PsiElement element1 = referenceExpression1.resolve();
final PsiElement element2 = referenceExpression2.resolve();
if (element1 != null) {
if (!element1.equals(element2)) {
return false;
}
}
else {
return false; // incomplete code
}
if (element1 instanceof PsiMember) {
final PsiMember member1 = (PsiMember)element1;
if (member1.hasModifierProperty(PsiModifier.STATIC)) {
return true;
}
else if (member1 instanceof PsiClass) {
return true;
}
}
else {
return true;
}
final PsiExpression qualifier1 =
referenceExpression1.getQualifierExpression();
final PsiExpression qualifier2 =
referenceExpression2.getQualifierExpression();
if (qualifier1 != null &&
!(qualifier1 instanceof PsiThisExpression ||
qualifier1 instanceof PsiSuperExpression)) {
if (qualifier2 == null) {
return false;
}
else if (!expressionsAreEquivalent(qualifier1, qualifier2)) {
return false;
}
}
else {
if (qualifier2 != null &&
!(qualifier2 instanceof PsiThisExpression ||
qualifier2 instanceof PsiSuperExpression)) {
return false;
}
}
final String text1 = referenceExpression1.getText();
final String text2 = referenceExpression2.getText();
return text1.equals(text2);
}
private static boolean instanceofExpressionsAreEquivalent(
PsiInstanceOfExpression instanceOfExpression1,
PsiInstanceOfExpression instanceOfExpression2) {
final PsiExpression operand1 = instanceOfExpression1.getOperand();
final PsiExpression operand2 = instanceOfExpression2.getOperand();
if (!expressionsAreEquivalent(operand1, operand2)) {
return false;
}
final PsiTypeElement typeElement1 = instanceOfExpression1.getCheckType();
final PsiTypeElement typeElement2 = instanceOfExpression2.getCheckType();
return typeElementsAreEquivalent(typeElement1, typeElement2);
}
private static boolean typeElementsAreEquivalent(PsiTypeElement typeElement1, PsiTypeElement typeElement2) {
if (typeElement1 == null) {
return typeElement2 == null;
}
else if (typeElement2 == null) {
return false;
}
final PsiType type1 = typeElement1.getType();
final PsiType type2 = typeElement2.getType();
return typesAreEquivalent(type1, type2);
}
private static boolean methodCallExpressionsAreEquivalent(
@NotNull PsiMethodCallExpression methodCallExpression1,
@NotNull PsiMethodCallExpression methodCallExpression2) {
final PsiReferenceExpression methodExpression1 =
methodCallExpression1.getMethodExpression();
final PsiReferenceExpression methodExpression2 =
methodCallExpression2.getMethodExpression();
if (!expressionsAreEquivalent(methodExpression1, methodExpression2)) {
return false;
}
final PsiExpressionList argumentList1 =
methodCallExpression1.getArgumentList();
final PsiExpression[] args1 = argumentList1.getExpressions();
final PsiExpressionList argumentList2 =
methodCallExpression2.getArgumentList();
final PsiExpression[] args2 = argumentList2.getExpressions();
return expressionListsAreEquivalent(args1, args2);
}
private static boolean newExpressionsAreEquivalent(
@NotNull PsiNewExpression newExpression1,
@NotNull PsiNewExpression newExpression2) {
final PsiJavaCodeReferenceElement classReference1 =
newExpression1.getClassReference();
final PsiJavaCodeReferenceElement classReference2 =
newExpression2.getClassReference();
if (classReference1 == null || classReference2 == null) {
return false;
}
final String text = classReference1.getText();
if (!text.equals(classReference2.getText())) {
return false;
}
final PsiExpression[] arrayDimensions1 =
newExpression1.getArrayDimensions();
final PsiExpression[] arrayDimensions2 =
newExpression2.getArrayDimensions();
if (!expressionListsAreEquivalent(arrayDimensions1, arrayDimensions2)) {
return false;
}
final PsiArrayInitializerExpression arrayInitializer1 =
newExpression1.getArrayInitializer();
final PsiArrayInitializerExpression arrayInitializer2 =
newExpression2.getArrayInitializer();
if (!expressionsAreEquivalent(arrayInitializer1, arrayInitializer2)) {
return false;
}
final PsiExpression qualifier1 = newExpression1.getQualifier();
final PsiExpression qualifier2 = newExpression2.getQualifier();
if (!expressionsAreEquivalent(qualifier1, qualifier2)) {
return false;
}
final PsiExpressionList argumentList1 = newExpression1.getArgumentList();
final PsiExpression[] args1;
if (argumentList1 == null) {
args1 = null;
}
else {
args1 = argumentList1.getExpressions();
}
final PsiExpressionList argumentList2 = newExpression2.getArgumentList();
final PsiExpression[] args2;
if (argumentList2 == null) {
args2 = null;
}
else {
args2 = argumentList2.getExpressions();
}
return expressionListsAreEquivalent(args1, args2);
}
private static boolean arrayInitializerExpressionsAreEquivalent(
@NotNull PsiArrayInitializerExpression arrayInitializerExpression1,
@NotNull PsiArrayInitializerExpression arrayInitializerExpression2) {
final PsiExpression[] initializers1 =
arrayInitializerExpression1.getInitializers();
final PsiExpression[] initializers2 =
arrayInitializerExpression2.getInitializers();
return expressionListsAreEquivalent(initializers1, initializers2);
}
private static boolean typeCastExpressionsAreEquivalent(
@NotNull PsiTypeCastExpression typeCastExpression1,
@NotNull PsiTypeCastExpression typeCastExpression2) {
final PsiTypeElement typeElement1 = typeCastExpression1.getCastType();
final PsiTypeElement typeElement2 = typeCastExpression2.getCastType();
if (!typeElementsAreEquivalent(typeElement1, typeElement2)) {
return false;
}
final PsiExpression operand1 = typeCastExpression1.getOperand();
final PsiExpression operand2 = typeCastExpression2.getOperand();
return expressionsAreEquivalent(operand1, operand2);
}
private static boolean arrayAccessExpressionsAreEquivalent(
@NotNull PsiArrayAccessExpression arrayAccessExpression1,
@NotNull PsiArrayAccessExpression arrayAccessExpression2) {
final PsiExpression arrayExpression2 =
arrayAccessExpression1.getArrayExpression();
final PsiExpression arrayExpression1 =
arrayAccessExpression2.getArrayExpression();
final PsiExpression indexExpression2 =
arrayAccessExpression1.getIndexExpression();
final PsiExpression indexExpression1 =
arrayAccessExpression2.getIndexExpression();
return expressionsAreEquivalent(arrayExpression2, arrayExpression1)
&& expressionsAreEquivalent(indexExpression2, indexExpression1);
}
private static boolean prefixExpressionsAreEquivalent(
@NotNull PsiPrefixExpression prefixExpression1,
@NotNull PsiPrefixExpression prefixExpression2) {
final IElementType tokenType1 = prefixExpression1.getOperationTokenType();
if (!tokenType1.equals(prefixExpression2.getOperationTokenType())) {
return false;
}
final PsiExpression operand1 = prefixExpression1.getOperand();
final PsiExpression operand2 = prefixExpression2.getOperand();
return expressionsAreEquivalent(operand1, operand2);
}
private static boolean postfixExpressionsAreEquivalent(
@NotNull PsiPostfixExpression postfixExpression1,
@NotNull PsiPostfixExpression postfixExpression2) {
final IElementType tokenType1 = postfixExpression1.getOperationTokenType();
if (!tokenType1.equals(postfixExpression2.getOperationTokenType())) {
return false;
}
final PsiExpression operand1 = postfixExpression1.getOperand();
final PsiExpression operand2 = postfixExpression2.getOperand();
return expressionsAreEquivalent(operand1, operand2);
}
private static boolean polyadicExpressionsAreEquivalent(
@NotNull PsiPolyadicExpression polyadicExpression1,
@NotNull PsiPolyadicExpression polyadicExpression2) {
final IElementType tokenType1 = polyadicExpression1.getOperationTokenType();
final IElementType tokenType2 = polyadicExpression2.getOperationTokenType();
if (!tokenType1.equals(tokenType2)) {
return false;
}
final PsiExpression[] operands1 = polyadicExpression1.getOperands();
final PsiExpression[] operands2 = polyadicExpression2.getOperands();
if (operands1.length != operands2.length) {
return false;
}
for (int i = 0, length = operands1.length; i < length; i++) {
if (!expressionsAreEquivalent(operands1[i], operands2[i])) {
return false;
}
}
return true;
}
private static boolean assignmentExpressionsAreEquivalent(
@NotNull PsiAssignmentExpression assignmentExpression1,
@NotNull PsiAssignmentExpression assignmentExpression2) {
final IElementType tokenType1 = assignmentExpression1.getOperationTokenType();
if (!tokenType1.equals(assignmentExpression2.getOperationTokenType())) {
return false;
}
final PsiExpression lhs1 = assignmentExpression1.getLExpression();
final PsiExpression lhs2 = assignmentExpression2.getLExpression();
final PsiExpression rhs1 = assignmentExpression1.getRExpression();
final PsiExpression rhs2 = assignmentExpression2.getRExpression();
return expressionsAreEquivalent(lhs1, lhs2)
&& expressionsAreEquivalent(rhs1, rhs2);
}
private static boolean conditionalExpressionsAreEquivalent(
@NotNull PsiConditionalExpression conditionalExpression1,
@NotNull PsiConditionalExpression conditionalExpression2) {
final PsiExpression condition1 = conditionalExpression1.getCondition();
final PsiExpression condition2 = conditionalExpression2.getCondition();
final PsiExpression thenExpression1 =
conditionalExpression1.getThenExpression();
final PsiExpression thenExpression2 =
conditionalExpression2.getThenExpression();
final PsiExpression elseExpression1 =
conditionalExpression1.getElseExpression();
final PsiExpression elseExpression2 =
conditionalExpression2.getElseExpression();
return expressionsAreEquivalent(condition1, condition2)
&& expressionsAreEquivalent(thenExpression1, thenExpression2)
&& expressionsAreEquivalent(elseExpression1, elseExpression2);
}
private static boolean expressionListsAreEquivalent(
@Nullable PsiExpression[] expressions1,
@Nullable PsiExpression[] expressions2) {
if (expressions1 == null && expressions2 == null) {
return true;
}
if (expressions1 == null || expressions2 == null) {
return false;
}
if (expressions1.length != expressions2.length) {
return false;
}
for (int i = 0; i < expressions1.length; i++) {
if (!expressionsAreEquivalent(expressions1[i], expressions2[i])) {
return false;
}
}
return true;
}
}