/* * Copyright 2009-2014 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.forloop; import com.siyeh.ig.psiutils.ComparisonUtils; import com.siyeh.ig.psiutils.ParenthesesUtils; import com.siyeh.ig.psiutils.VariableAccessUtils; import com.siyeh.ipp.base.PsiElementPredicate; import com.intellij.psi.*; import com.intellij.psi.tree.IElementType; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; class ReverseForLoopDirectionPredicate implements PsiElementPredicate { public boolean satisfiedBy(PsiElement element) { if (!(element instanceof PsiJavaToken)) { return false; } final PsiJavaToken keyword = (PsiJavaToken)element; final IElementType tokenType = keyword.getTokenType(); if (!JavaTokenType.FOR_KEYWORD.equals(tokenType)) { return false; } final PsiElement parent = keyword.getParent(); if (!(parent instanceof PsiForStatement)) { return false; } final PsiForStatement forStatement = (PsiForStatement)parent; final PsiStatement initialization = forStatement.getInitialization(); if (!(initialization instanceof PsiDeclarationStatement)) { return false; } final PsiDeclarationStatement declarationStatement = (PsiDeclarationStatement)initialization; final PsiElement[] declaredElements = declarationStatement.getDeclaredElements(); if (declaredElements.length != 1) { return false; } final PsiElement declaredElement = declaredElements[0]; if (!(declaredElement instanceof PsiLocalVariable)) { return false; } final PsiVariable variable = (PsiVariable)declaredElement; final PsiType type = variable.getType(); if (!PsiType.INT.equals(type) && !PsiType.LONG.equals(type)) { return false; } final PsiExpression condition = forStatement.getCondition(); if (!isVariableCompared(variable, condition)) { return false; } final PsiStatement update = forStatement.getUpdate(); return isVariableIncrementOrDecremented(variable, update); } public static boolean isVariableCompared( @NotNull PsiVariable variable, @Nullable PsiExpression expression) { if (!(expression instanceof PsiBinaryExpression)) { return false; } final PsiBinaryExpression binaryExpression = (PsiBinaryExpression)expression; final IElementType tokenType = binaryExpression.getOperationTokenType(); if (!ComparisonUtils.isComparisonOperation(tokenType)) { return false; } final PsiExpression lhs = binaryExpression.getLOperand(); final PsiExpression rhs = binaryExpression.getROperand(); if (rhs == null) { return false; } if (VariableAccessUtils.evaluatesToVariable(lhs, variable)) { return true; } else if (VariableAccessUtils.evaluatesToVariable(rhs, variable)) { return true; } return false; } public static boolean isVariableIncrementOrDecremented( @NotNull PsiVariable variable, @Nullable PsiStatement statement) { if (!(statement instanceof PsiExpressionStatement)) { return false; } final PsiExpressionStatement expressionStatement = (PsiExpressionStatement)statement; PsiExpression expression = expressionStatement.getExpression(); expression = ParenthesesUtils.stripParentheses(expression); if (expression instanceof PsiPrefixExpression) { final PsiPrefixExpression prefixExpression = (PsiPrefixExpression)expression; final IElementType tokenType = prefixExpression.getOperationTokenType(); if (!tokenType.equals(JavaTokenType.PLUSPLUS) && !tokenType.equals(JavaTokenType.MINUSMINUS)) { return false; } final PsiExpression operand = prefixExpression.getOperand(); return VariableAccessUtils.evaluatesToVariable(operand, variable); } else if (expression instanceof PsiPostfixExpression) { final PsiPostfixExpression postfixExpression = (PsiPostfixExpression)expression; final IElementType tokenType = postfixExpression.getOperationTokenType(); if (!tokenType.equals(JavaTokenType.PLUSPLUS) && !tokenType.equals(JavaTokenType.MINUSMINUS)) { return false; } final PsiExpression operand = postfixExpression.getOperand(); return VariableAccessUtils.evaluatesToVariable(operand, variable); } else if (expression instanceof PsiAssignmentExpression) { final PsiAssignmentExpression assignmentExpression = (PsiAssignmentExpression)expression; final IElementType tokenType = assignmentExpression.getOperationTokenType(); PsiExpression lhs = assignmentExpression.getLExpression(); lhs = ParenthesesUtils.stripParentheses(lhs); if (!VariableAccessUtils.evaluatesToVariable(lhs, variable)) { return false; } PsiExpression rhs = assignmentExpression.getRExpression(); rhs = ParenthesesUtils.stripParentheses(rhs); if (tokenType == JavaTokenType.EQ) { if (!(rhs instanceof PsiBinaryExpression)) { return false; } final PsiBinaryExpression binaryExpression = (PsiBinaryExpression)rhs; final IElementType token = binaryExpression.getOperationTokenType(); if (!token.equals(JavaTokenType.PLUS) && !token.equals(JavaTokenType.MINUS)) { return false; } PsiExpression lOperand = binaryExpression.getLOperand(); lOperand = ParenthesesUtils.stripParentheses(lOperand); PsiExpression rOperand = binaryExpression.getROperand(); rOperand = ParenthesesUtils.stripParentheses(rOperand); if (VariableAccessUtils.evaluatesToVariable(rOperand, variable)) { return true; } else if (VariableAccessUtils.evaluatesToVariable(lOperand, variable)) { return true; } } else if (tokenType == JavaTokenType.PLUSEQ || tokenType == JavaTokenType.MINUSEQ) { return true; } } return false; } }