blob: 9ea58777349a3ec8715fef7d0bca452f722b0579 [file] [log] [blame]
/*
* Copyright 2003-2012 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.ipp.trivialif;
import com.intellij.psi.*;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.util.PsiTreeUtil;
import com.siyeh.ig.psiutils.ControlFlowUtils;
import com.siyeh.ig.psiutils.EquivalenceChecker;
import com.siyeh.ipp.base.PsiElementPredicate;
import com.siyeh.ipp.psiutils.ErrorUtil;
class ReplaceIfWithConditionalPredicate implements PsiElementPredicate {
public boolean satisfiedBy(PsiElement element) {
if (!(element instanceof PsiJavaToken)) {
return false;
}
final PsiJavaToken token = (PsiJavaToken)element;
final PsiElement parent = token.getParent();
if (!(parent instanceof PsiIfStatement)) {
return false;
}
final PsiIfStatement ifStatement = (PsiIfStatement)parent;
if (ErrorUtil.containsError(ifStatement)) {
return false;
}
final PsiExpression condition = ifStatement.getCondition();
if (condition == null) {
return false;
}
if (isReplaceableAssignment(ifStatement)) {
return true;
}
if (isReplaceableReturn(ifStatement)) {
return true;
}
if (isReplaceableMethodCall(ifStatement)) {
return true;
}
return isReplaceableImplicitReturn(ifStatement);
}
public static boolean isReplaceableMethodCall(PsiIfStatement ifStatement) {
final PsiStatement thenBranch = ifStatement.getThenBranch();
final PsiStatement elseBranch = ifStatement.getElseBranch();
final PsiStatement thenStatement = ControlFlowUtils.stripBraces(thenBranch);
if (thenStatement == null) {
return false;
}
final PsiStatement elseStatement = ControlFlowUtils.stripBraces(elseBranch);
if (elseStatement == null) {
return false;
}
if (!(thenStatement instanceof PsiExpressionStatement) || !(elseStatement instanceof PsiExpressionStatement)) {
return false;
}
final PsiExpressionStatement thenExpressionStatement = (PsiExpressionStatement)thenStatement;
final PsiExpression thenExpression = thenExpressionStatement.getExpression();
final PsiExpressionStatement elseExpressionStatement = (PsiExpressionStatement)elseStatement;
final PsiExpression elseExpression = elseExpressionStatement.getExpression();
if (!(thenExpression instanceof PsiMethodCallExpression) || !(elseExpression instanceof PsiMethodCallExpression)) {
return false;
}
final PsiMethodCallExpression thenMethodCallExpression = (PsiMethodCallExpression)thenExpression;
final PsiMethodCallExpression elseMethodCallExpression = (PsiMethodCallExpression)elseExpression;
final PsiReferenceExpression thenMethodExpression = thenMethodCallExpression.getMethodExpression();
final PsiReferenceExpression elseMethodExpression = elseMethodCallExpression.getMethodExpression();
if (!EquivalenceChecker.expressionsAreEquivalent(thenMethodExpression, elseMethodExpression)) {
return false;
}
final PsiExpressionList thenArgumentList = thenMethodCallExpression.getArgumentList();
final PsiExpression[] thenArguments = thenArgumentList.getExpressions();
final PsiExpressionList elseArgumentList = elseMethodCallExpression.getArgumentList();
final PsiExpression[] elseArguments = elseArgumentList.getExpressions();
if (thenArguments.length != elseArguments.length) {
return false;
}
int differences = 0;
for (int i = 0, length = thenArguments.length; i < length; i++) {
final PsiExpression thenArgument = thenArguments[i];
final PsiExpression elseArgument = elseArguments[i];
if (!EquivalenceChecker.expressionsAreEquivalent(thenArgument, elseArgument)) {
differences++;
}
}
return differences == 1;
}
public static boolean isReplaceableImplicitReturn(PsiIfStatement ifStatement) {
if (ifStatement.getElseBranch() != null) {
return false;
}
PsiStatement thenBranch = ifStatement.getThenBranch();
thenBranch = ControlFlowUtils.stripBraces(thenBranch);
if (!(thenBranch instanceof PsiReturnStatement)) {
return false;
}
final PsiReturnStatement thenReturnStatement = (PsiReturnStatement)thenBranch;
final PsiExpression thenReturn = thenReturnStatement.getReturnValue();
if (thenReturn == null) {
return false;
}
final PsiType thenType = thenReturn.getType();
if (thenType == null) {
return false;
}
final PsiElement nextStatement = PsiTreeUtil.skipSiblingsForward(ifStatement, PsiWhiteSpace.class);
if (!(nextStatement instanceof PsiReturnStatement)) {
return false;
}
final PsiReturnStatement elseReturnStatement = (PsiReturnStatement)nextStatement;
final PsiExpression elseReturn = elseReturnStatement.getReturnValue();
if (elseReturn == null) {
return false;
}
final PsiType elseType = elseReturn.getType();
if (elseType == null) {
return false;
}
return thenType.isAssignableFrom(elseType) || elseType.isAssignableFrom(thenType);
}
public static boolean isReplaceableReturn(PsiIfStatement ifStatement) {
PsiStatement thenBranch = ifStatement.getThenBranch();
thenBranch = ControlFlowUtils.stripBraces(thenBranch);
PsiStatement elseBranch = ifStatement.getElseBranch();
elseBranch = ControlFlowUtils.stripBraces(elseBranch);
if (!(thenBranch instanceof PsiReturnStatement) || !(elseBranch instanceof PsiReturnStatement)) {
return false;
}
final PsiExpression thenReturn = ((PsiReturnStatement)thenBranch).getReturnValue();
if (thenReturn == null) {
return false;
}
final PsiExpression elseReturn = ((PsiReturnStatement)elseBranch).getReturnValue();
if (elseReturn == null) {
return false;
}
final PsiType thenType = thenReturn.getType();
final PsiType elseType = elseReturn.getType();
if (thenType == null || elseType == null) {
return false;
}
return thenType.isAssignableFrom(elseType) || elseType.isAssignableFrom(thenType);
}
public static boolean isReplaceableAssignment(PsiIfStatement ifStatement) {
final PsiStatement thenBranch = ControlFlowUtils.stripBraces(ifStatement.getThenBranch());
final PsiStatement elseBranch = ControlFlowUtils.stripBraces(ifStatement.getElseBranch());
if (thenBranch == null || elseBranch == null) {
return false;
}
if (!(thenBranch instanceof PsiExpressionStatement) || !(elseBranch instanceof PsiExpressionStatement)) {
return false;
}
final PsiExpressionStatement thenExpressionStatement = (PsiExpressionStatement)thenBranch;
final PsiExpressionStatement elseExpressionStatement = (PsiExpressionStatement)elseBranch;
final PsiExpression thenExpression = thenExpressionStatement.getExpression();
final PsiExpression elseExpression = elseExpressionStatement.getExpression();
if (!(thenExpression instanceof PsiAssignmentExpression) || !(elseExpression instanceof PsiAssignmentExpression)) {
return false;
}
final PsiAssignmentExpression thenAssignmentExpression = (PsiAssignmentExpression)thenExpression;
final PsiAssignmentExpression elseAssignmentExpression = (PsiAssignmentExpression)elseExpression;
final PsiExpression thenRhs = thenAssignmentExpression.getRExpression();
final PsiExpression elseRhs = elseAssignmentExpression.getRExpression();
if (thenRhs == null || elseRhs == null) {
return false;
}
final IElementType thenTokenType = thenAssignmentExpression.getOperationTokenType();
final IElementType elseTokenType = elseAssignmentExpression.getOperationTokenType();
if (!thenTokenType.equals(elseTokenType)) {
return false;
}
final PsiExpression thenLhs = thenAssignmentExpression.getLExpression();
final PsiExpression elseLhs = elseAssignmentExpression.getLExpression();
return EquivalenceChecker.expressionsAreEquivalent(thenLhs, elseLhs);
}
}