remove VariableAccessUtils duplication

This commit is contained in:
Bas Leijdekkers
2014-02-28 11:43:11 +01:00
parent a8412d20b4
commit bcf9217a54
8 changed files with 183 additions and 415 deletions
@@ -1,5 +1,5 @@
/*
* Copyright 2003-2012 Dave Griffith, Bas Leijdekkers
* 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.
@@ -20,6 +20,9 @@ import com.intellij.psi.tree.IElementType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
public class VariableAccessUtils {
@@ -446,4 +449,43 @@ public class VariableAccessUtils {
}
return child;
}
public static Set<PsiVariable> collectUsedVariables(PsiElement context) {
if (context == null) {
return Collections.emptySet();
}
final VariableCollectingVisitor visitor = new VariableCollectingVisitor();
context.accept(visitor);
return visitor.getUsedVariables();
}
public static boolean isAnyVariableAssigned(@NotNull Collection<PsiVariable> variables, @Nullable PsiElement context) {
if (context == null) {
return false;
}
final VariableAssignedVisitor visitor = new VariableAssignedVisitor(variables, true);
context.accept(visitor);
return visitor.isAssigned();
}
private static class VariableCollectingVisitor extends JavaRecursiveElementVisitor {
private final Set<PsiVariable> usedVariables = new HashSet();
@Override
public void visitReferenceExpression(
PsiReferenceExpression expression) {
super.visitReferenceExpression(expression);
final PsiElement target = expression.resolve();
if (!(target instanceof PsiVariable)) {
return;
}
final PsiVariable variable = (PsiVariable)target;
usedVariables.add(variable);
}
public Set<PsiVariable> getUsedVariables() {
return usedVariables;
}
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2003-2013 Dave Griffith, Bas Leijdekkers
* 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.
@@ -20,16 +20,25 @@ import com.intellij.psi.tree.IElementType;
import com.intellij.psi.util.TypeConversionUtil;
import org.jetbrains.annotations.NotNull;
import java.util.Collection;
import java.util.Collections;
public class VariableAssignedVisitor extends JavaRecursiveElementWalkingVisitor {
@NotNull private final PsiVariable variable;
@NotNull private final Collection<PsiVariable> variables;
private final boolean recurseIntoClasses;
private final boolean checkUnaryExpressions;
private boolean assigned = false;
private PsiElement excludedElement = null;
public VariableAssignedVisitor(@NotNull Collection<PsiVariable> variables, boolean recurseIntoClasses) {
this.variables = variables;
checkUnaryExpressions = true;
this.recurseIntoClasses = recurseIntoClasses;
}
public VariableAssignedVisitor(@NotNull PsiVariable variable, boolean recurseIntoClasses) {
this.variable = variable;
variables = Collections.singleton(variable);
final PsiType type = variable.getType();
checkUnaryExpressions = TypeConversionUtil.isNumericType(type);
this.recurseIntoClasses = recurseIntoClasses;
@@ -58,8 +67,11 @@ public class VariableAssignedVisitor extends JavaRecursiveElementWalkingVisitor
}
super.visitAssignmentExpression(assignment);
final PsiExpression lhs = assignment.getLExpression();
if (VariableAccessUtils.evaluatesToVariable(lhs, variable)) {
assigned = true;
for (PsiVariable variable : variables) {
if (VariableAccessUtils.evaluatesToVariable(lhs, variable)) {
assigned = true;
break;
}
}
}
@@ -85,8 +97,11 @@ public class VariableAssignedVisitor extends JavaRecursiveElementWalkingVisitor
return;
}
final PsiExpression operand = prefixExpression.getOperand();
if (VariableAccessUtils.evaluatesToVariable(operand, variable)) {
assigned = true;
for (PsiVariable variable : variables) {
if (VariableAccessUtils.evaluatesToVariable(operand, variable)) {
assigned = true;
break;
}
}
}
@@ -104,8 +119,11 @@ public class VariableAssignedVisitor extends JavaRecursiveElementWalkingVisitor
return;
}
final PsiExpression operand = postfixExpression.getOperand();
if (VariableAccessUtils.evaluatesToVariable(operand, variable)) {
assigned = true;
for (PsiVariable variable : variables) {
if (VariableAccessUtils.evaluatesToVariable(operand, variable)) {
assigned = true;
break;
}
}
}
@@ -22,9 +22,9 @@ import com.intellij.util.IncorrectOperationException;
import com.siyeh.ig.psiutils.ComparisonUtils;
import com.siyeh.ig.psiutils.ExpressionUtils;
import com.siyeh.ig.psiutils.ParenthesesUtils;
import com.siyeh.ig.psiutils.VariableAccessUtils;
import com.siyeh.ipp.base.Intention;
import com.siyeh.ipp.base.PsiElementPredicate;
import com.siyeh.ipp.psiutils.VariableAccessUtils;
import org.jetbrains.annotations.NotNull;
public class ReverseForLoopDirectionIntention extends Intention {
@@ -1,5 +1,5 @@
/*
* Copyright 2009-2013 Bas Leijdekkers
* 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.
@@ -15,10 +15,14 @@
*/
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.siyeh.ipp.psiutils.VariableAccessUtils;
import com.intellij.psi.*;
import com.intellij.psi.tree.IElementType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
class ReverseForLoopDirectionPredicate implements PsiElementPredicate {
@@ -57,11 +61,109 @@ class ReverseForLoopDirectionPredicate implements PsiElementPredicate {
return false;
}
final PsiExpression condition = forStatement.getCondition();
if (!VariableAccessUtils.isVariableCompared(variable, condition)) {
if (!isVariableCompared(variable, condition)) {
return false;
}
final PsiStatement update = forStatement.getUpdate();
return VariableAccessUtils.isVariableIncrementOrDecremented(variable,
update);
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;
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2009-2013 Bas Leijdekkers
* 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.
@@ -18,8 +18,8 @@ package com.siyeh.ipp.opassign;
import com.intellij.psi.*;
import com.intellij.psi.tree.IElementType;
import com.siyeh.ig.psiutils.ParenthesesUtils;
import com.siyeh.ig.psiutils.VariableAccessUtils;
import com.siyeh.ipp.base.PsiElementPredicate;
import com.siyeh.ipp.psiutils.VariableAccessUtils;
class ReplaceAssignmentWithPostfixExpressionPredicate implements PsiElementPredicate {
@@ -1,195 +0,0 @@
/*
* 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.psiutils;
import com.intellij.psi.*;
import com.intellij.psi.tree.IElementType;
import com.siyeh.ig.psiutils.ComparisonUtils;
import com.siyeh.ig.psiutils.ParenthesesUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
public class VariableAccessUtils {
private VariableAccessUtils() {
}
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 (evaluatesToVariable(lhs, variable)) {
return true;
}
else if (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 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 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 (!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 (evaluatesToVariable(rOperand, variable)) {
return true;
}
else if (evaluatesToVariable(lOperand, variable)) {
return true;
}
}
else if (tokenType == JavaTokenType.PLUSEQ ||
tokenType == JavaTokenType.MINUSEQ) {
return true;
}
}
return false;
}
public static boolean evaluatesToVariable(
@Nullable PsiExpression expression,
@NotNull PsiVariable variable) {
final PsiExpression strippedExpression =
ParenthesesUtils.stripParentheses(expression);
if (strippedExpression == null) {
return false;
}
if (!(expression instanceof PsiReferenceExpression)) {
return false;
}
final PsiReferenceExpression referenceExpression =
(PsiReferenceExpression)expression;
final PsiElement referent = referenceExpression.resolve();
return variable.equals(referent);
}
public static boolean isAnyVariableAssigned(
@NotNull Collection<PsiVariable> variables,
@Nullable PsiElement context) {
if (context == null) {
return false;
}
final VariableAssignedVisitor visitor =
new VariableAssignedVisitor(variables, true);
context.accept(visitor);
return visitor.isAssigned();
}
public static Set<PsiVariable> collectUsedVariables(
PsiElement context) {
if (context == null) {
return Collections.emptySet();
}
final VariableCollectingVisitor visitor =
new VariableCollectingVisitor();
context.accept(visitor);
return visitor.getUsedVariables();
}
private static class VariableCollectingVisitor
extends JavaRecursiveElementVisitor {
private final Set<PsiVariable> usedVariables = new HashSet();
@Override
public void visitReferenceExpression(
PsiReferenceExpression expression) {
super.visitReferenceExpression(expression);
final PsiElement target = expression.resolve();
if (!(target instanceof PsiVariable)) {
return;
}
final PsiVariable variable = (PsiVariable)target;
usedVariables.add(variable);
}
public Set<PsiVariable> getUsedVariables() {
return usedVariables;
}
}
}
@@ -1,199 +0,0 @@
/*
* Copyright 2003-2013 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.psiutils;
import com.intellij.psi.*;
import com.intellij.psi.tree.IElementType;
import com.siyeh.ig.psiutils.ParenthesesUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collection;
class VariableAssignedVisitor extends JavaRecursiveElementVisitor {
@NotNull private final Collection<PsiVariable> variables;
private final boolean recurseIntoClasses;
private boolean assigned = false;
public VariableAssignedVisitor(@NotNull Collection<PsiVariable> variables,
boolean recurseIntoClasses) {
this.variables = variables;
this.recurseIntoClasses = recurseIntoClasses;
}
@Override
public void visitElement(@NotNull PsiElement element) {
if (assigned) {
return;
}
super.visitElement(element);
}
@Override
public void visitAssignmentExpression(
@NotNull PsiAssignmentExpression assignment) {
if (assigned) {
return;
}
super.visitAssignmentExpression(assignment);
final PsiExpression lhs = assignment.getLExpression();
for (PsiVariable variable : variables) {
if (mayEvaluateToVariable(lhs, variable)) {
assigned = true;
}
}
}
@Override
public void visitClass(PsiClass aClass) {
if (!recurseIntoClasses) {
return;
}
if (assigned) {
return;
}
super.visitClass(aClass);
}
@Override
public void visitPrefixExpression(
@NotNull PsiPrefixExpression prefixExpression) {
if (assigned) {
return;
}
super.visitPrefixExpression(prefixExpression);
final IElementType tokenType = prefixExpression.getOperationTokenType();
if (!tokenType.equals(JavaTokenType.PLUSPLUS) &&
!tokenType.equals(JavaTokenType.MINUSMINUS)) {
return;
}
final PsiExpression operand = prefixExpression.getOperand();
for (PsiVariable variable : variables) {
if (mayEvaluateToVariable(operand, variable)) {
assigned = true;
}
}
}
@Override
public void visitPostfixExpression(
@NotNull PsiPostfixExpression postfixExpression) {
if (assigned) {
return;
}
super.visitPostfixExpression(postfixExpression);
final IElementType tokenType = postfixExpression.getOperationTokenType();
if (!tokenType.equals(JavaTokenType.PLUSPLUS) &&
!tokenType.equals(JavaTokenType.MINUSMINUS)) {
return;
}
final PsiExpression operand = postfixExpression.getOperand();
for (PsiVariable variable : variables) {
if (mayEvaluateToVariable(operand, variable)) {
assigned = true;
}
}
}
public static boolean mayEvaluateToVariable(
@Nullable PsiExpression expression,
@NotNull PsiVariable variable) {
if (expression == null) {
return false;
}
if (expression instanceof PsiBinaryExpression) {
final PsiBinaryExpression binaryExpression =
(PsiBinaryExpression)expression;
final PsiExpression lOperand = binaryExpression.getLOperand();
final PsiExpression rOperand = binaryExpression.getROperand();
return mayEvaluateToVariable(lOperand, variable) ||
mayEvaluateToVariable(rOperand, variable);
}
if (expression instanceof PsiParenthesizedExpression) {
final PsiParenthesizedExpression parenthesizedExpression =
(PsiParenthesizedExpression)expression;
final PsiExpression containedExpression =
parenthesizedExpression.getExpression();
return mayEvaluateToVariable(containedExpression, variable);
}
if (expression instanceof PsiTypeCastExpression) {
final PsiTypeCastExpression typeCastExpression =
(PsiTypeCastExpression)expression;
final PsiExpression containedExpression =
typeCastExpression.getOperand();
return mayEvaluateToVariable(containedExpression, variable);
}
if (expression instanceof PsiConditionalExpression) {
final PsiConditionalExpression conditional =
(PsiConditionalExpression)expression;
final PsiExpression thenExpression = conditional.getThenExpression();
final PsiExpression elseExpression = conditional.getElseExpression();
return mayEvaluateToVariable(thenExpression, variable) ||
mayEvaluateToVariable(elseExpression, variable);
}
if (expression instanceof PsiArrayAccessExpression) {
final PsiElement parent = expression.getParent();
if (parent instanceof PsiArrayAccessExpression) {
return false;
}
final PsiType type = variable.getType();
if (!(type instanceof PsiArrayType)) {
return false;
}
final PsiArrayType arrayType = (PsiArrayType)type;
final int dimensions = arrayType.getArrayDimensions();
if (dimensions <= 1) {
return false;
}
PsiArrayAccessExpression arrayAccessExpression =
(PsiArrayAccessExpression)expression;
PsiExpression arrayExpression =
arrayAccessExpression.getArrayExpression();
int count = 1;
while (arrayExpression instanceof PsiArrayAccessExpression) {
arrayAccessExpression =
(PsiArrayAccessExpression)arrayExpression;
arrayExpression = arrayAccessExpression.getArrayExpression();
count++;
}
return count != dimensions &&
mayEvaluateToVariable(arrayExpression, variable);
}
return evaluatesToVariable(expression, variable);
}
public static boolean evaluatesToVariable(
@Nullable PsiExpression expression,
@NotNull PsiVariable variable) {
final PsiExpression strippedExpression =
ParenthesesUtils.stripParentheses(expression);
if (strippedExpression == null) {
return false;
}
if (!(expression instanceof PsiReferenceExpression)) {
return false;
}
final PsiReferenceExpression referenceExpression =
(PsiReferenceExpression)expression;
final PsiElement referent = referenceExpression.resolve();
return variable.equals(referent);
}
public boolean isAssigned() {
return assigned;
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2003-2010 Dave Griffith, Bas Leijdekkers
* 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.
@@ -17,11 +17,11 @@ package com.siyeh.ipp.trivialif;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiTreeUtil;
import com.siyeh.ig.psiutils.ControlFlowUtils;
import com.siyeh.ig.psiutils.EquivalenceChecker;
import com.siyeh.ig.psiutils.VariableAccessUtils;
import com.siyeh.ipp.base.PsiElementPredicate;
import com.siyeh.ipp.psiutils.ControlFlowUtils;
import com.siyeh.ipp.psiutils.ErrorUtil;
import com.siyeh.ipp.psiutils.VariableAccessUtils;
import java.util.Collection;
import java.util.HashSet;