![JAR search and dependency download from the Maven repository](/logo.png)
com.siyeh.ig.psiutils.VariableAccessUtils Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of java-analysis-impl Show documentation
Show all versions of java-analysis-impl Show documentation
A packaging of the IntelliJ Community Edition java-analysis-impl library.
This is release number 1 of trunk branch 142.
The newest version!
/*
* Copyright 2003-2015 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.search.searches.ReferencesSearch;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.util.Processor;
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 variableIsAssignedFrom(@NotNull PsiVariable variable,
@Nullable PsiElement context) {
if (context == null) {
return false;
}
final VariableAssignedFromVisitor visitor =
new VariableAssignedFromVisitor(variable);
context.accept(visitor);
return visitor.isAssignedFrom();
}
public static boolean variableIsPassedAsMethodArgument(
@NotNull PsiVariable variable, @Nullable PsiElement context) {
if (context == null) {
return false;
}
final VariablePassedAsArgumentVisitor visitor =
new VariablePassedAsArgumentVisitor(variable);
context.accept(visitor);
return visitor.isPassed();
}
public static boolean variableIsPassedAsMethodArgument(@NotNull PsiVariable variable, @Nullable PsiElement context,
Processor callProcessor) {
return variableIsPassedAsMethodArgument(variable, context, false, callProcessor);
}
public static boolean variableIsPassedAsMethodArgument(@NotNull PsiVariable variable, @Nullable PsiElement context,
boolean builderPattern, Processor callProcessor) {
if (context == null) {
return false;
}
final VariablePassedAsArgumentExcludedVisitor visitor =
new VariablePassedAsArgumentExcludedVisitor(variable, builderPattern, callProcessor);
context.accept(visitor);
return visitor.isPassed();
}
public static boolean variableIsUsedInArrayInitializer(
@NotNull PsiVariable variable, @Nullable PsiElement context) {
if (context == null) {
return false;
}
final VariableUsedInArrayInitializerVisitor visitor =
new VariableUsedInArrayInitializerVisitor(variable);
context.accept(visitor);
return visitor.isPassed();
}
public static boolean variableIsAssigned(@NotNull PsiVariable variable) {
if (variable instanceof PsiField) {
if (variable.hasModifierProperty(PsiModifier.PRIVATE)) {
final PsiClass aClass = PsiUtil.getTopLevelClass(variable);
return variableIsAssigned(variable, aClass);
}
return !ReferencesSearch.search(variable, variable.getUseScope()).forEach(new Processor() {
@Override
public boolean process(PsiReference reference) {
final PsiElement element = reference.getElement();
if (!(element instanceof PsiExpression)) {
return true;
}
final PsiExpression expression = (PsiExpression)element;
return !PsiUtil.isAccessedForWriting(expression);
}
});
}
final PsiElement context =
PsiTreeUtil.getParentOfType(variable, PsiCodeBlock.class, PsiMethod.class, PsiLambdaExpression.class,
PsiCatchSection.class, PsiForStatement.class, PsiForeachStatement.class);
return variableIsAssigned(variable, context);
}
public static boolean variableIsAssigned(
@NotNull PsiVariable variable, @Nullable PsiElement context) {
if (context == null) {
return false;
}
final VariableAssignedVisitor visitor =
new VariableAssignedVisitor(variable, true);
context.accept(visitor);
return visitor.isAssigned();
}
public static boolean variableIsAssigned(
@NotNull PsiVariable variable, @Nullable PsiElement context,
boolean recurseIntoClasses) {
if (context == null) {
return false;
}
final VariableAssignedVisitor visitor =
new VariableAssignedVisitor(variable, recurseIntoClasses);
context.accept(visitor);
return visitor.isAssigned();
}
public static boolean variableIsReturned(@NotNull PsiVariable variable, @Nullable PsiElement context) {
return variableIsReturned(variable, context, false);
}
public static boolean variableIsReturned(@NotNull PsiVariable variable, @Nullable PsiElement context, boolean builderPattern) {
if (context == null) {
return false;
}
final VariableReturnedVisitor visitor = new VariableReturnedVisitor(variable, builderPattern);
context.accept(visitor);
return visitor.isReturned();
}
public static boolean variableValueIsUsed(
@NotNull PsiVariable variable, @Nullable PsiElement context) {
if (context == null) {
return false;
}
final VariableValueUsedVisitor visitor =
new VariableValueUsedVisitor(variable);
context.accept(visitor);
return visitor.isVariableValueUsed();
}
public static boolean arrayContentsAreAccessed(
@NotNull PsiVariable variable, @Nullable PsiElement context) {
if (context == null) {
return false;
}
final ArrayContentsAccessedVisitor visitor =
new ArrayContentsAccessedVisitor(variable);
context.accept(visitor);
return visitor.isAccessed();
}
public static boolean arrayContentsAreAssigned(
@NotNull PsiVariable variable, @Nullable PsiElement context) {
if (context == null) {
return false;
}
final ArrayContentsAssignedVisitor visitor =
new ArrayContentsAssignedVisitor(variable);
context.accept(visitor);
return visitor.isAssigned();
}
public static boolean variableIsUsedInInnerClass(
@NotNull PsiVariable variable, @Nullable PsiElement context) {
if (context == null) {
return false;
}
final VariableUsedInInnerClassVisitor visitor =
new VariableUsedInInnerClassVisitor(variable);
context.accept(visitor);
return visitor.isUsedInInnerClass();
}
public static boolean mayEvaluateToVariable(@Nullable PsiExpression expression, @NotNull PsiVariable variable) {
return mayEvaluateToVariable(expression, variable, false);
}
public static boolean mayEvaluateToVariable(@Nullable PsiExpression expression, @NotNull PsiVariable variable, boolean builderPattern) {
if (expression == null) {
return false;
}
if (expression instanceof PsiParenthesizedExpression) {
final PsiParenthesizedExpression parenthesizedExpression = (PsiParenthesizedExpression)expression;
final PsiExpression containedExpression = parenthesizedExpression.getExpression();
return mayEvaluateToVariable(containedExpression, variable, builderPattern);
}
if (expression instanceof PsiTypeCastExpression) {
final PsiTypeCastExpression typeCastExpression = (PsiTypeCastExpression)expression;
final PsiExpression containedExpression = typeCastExpression.getOperand();
return mayEvaluateToVariable(containedExpression, variable, builderPattern);
}
if (expression instanceof PsiConditionalExpression) {
final PsiConditionalExpression conditional = (PsiConditionalExpression)expression;
final PsiExpression thenExpression = conditional.getThenExpression();
final PsiExpression elseExpression = conditional.getElseExpression();
return mayEvaluateToVariable(thenExpression, variable, builderPattern) ||
mayEvaluateToVariable(elseExpression, variable, builderPattern);
}
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, builderPattern);
}
if (builderPattern && expression instanceof PsiMethodCallExpression) {
final PsiMethodCallExpression methodCallExpression = (PsiMethodCallExpression)expression;
final PsiMethod method = methodCallExpression.resolveMethod();
if (method == null) {
return false;
}
final PsiType returnType = method.getReturnType();
final PsiType variableType = variable.getType();
if (!variableType.equals(returnType)) {
return false;
}
final PsiReferenceExpression methodExpression = methodCallExpression.getMethodExpression();
final PsiExpression qualifier = methodExpression.getQualifierExpression();
return mayEvaluateToVariable(qualifier, variable, builderPattern);
}
return evaluatesToVariable(expression, variable);
}
public static boolean evaluatesToVariable(
@Nullable PsiExpression expression,
@NotNull PsiVariable variable) {
expression = ParenthesesUtils.stripParentheses(expression);
if (!(expression instanceof PsiReferenceExpression)) {
return false;
}
final PsiReferenceExpression referenceExpression =
(PsiReferenceExpression)expression;
final PsiElement target = referenceExpression.resolve();
return variable.equals(target);
}
public static boolean variableIsUsed(@NotNull PsiVariable variable,
@Nullable PsiElement context) {
if (context == null) {
return false;
}
final VariableUsedVisitor visitor =
new VariableUsedVisitor(variable);
context.accept(visitor);
return visitor.isUsed();
}
public static boolean variableIsDecremented(@NotNull PsiVariable variable, @Nullable PsiStatement statement) {
return variableIsIncrementedOrDecremented(variable, statement, false); }
public static boolean variableIsIncremented(@NotNull PsiVariable variable, @Nullable PsiStatement statement) {
return variableIsIncrementedOrDecremented(variable, statement, true);
}
private static boolean variableIsIncrementedOrDecremented(@NotNull PsiVariable variable, @Nullable PsiStatement statement,
boolean incremented) {
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 (incremented ? !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 (incremented ? !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();
final PsiExpression lhs = assignmentExpression.getLExpression();
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 binaryTokenType =
binaryExpression.getOperationTokenType();
if (incremented ? binaryTokenType != JavaTokenType.PLUS : binaryTokenType != JavaTokenType.MINUS) {
return false;
}
final PsiExpression lOperand = binaryExpression.getLOperand();
final PsiExpression rOperand = binaryExpression.getROperand();
if (ExpressionUtils.isOne(lOperand)) {
if (evaluatesToVariable(rOperand, variable)) {
return true;
}
}
else if (ExpressionUtils.isOne(rOperand)) {
if (evaluatesToVariable(lOperand, variable)) {
return true;
}
}
}
else if (incremented ? tokenType == JavaTokenType.PLUSEQ : tokenType == JavaTokenType.MINUSEQ) {
if (ExpressionUtils.isOne(rhs)) {
return true;
}
}
}
return false;
}
public static boolean variableIsAssignedBeforeReference(
@NotNull PsiReferenceExpression referenceExpression,
@Nullable PsiElement context) {
if (context == null) {
return false;
}
final PsiElement target = referenceExpression.resolve();
if (!(target instanceof PsiVariable)) {
return false;
}
final PsiVariable variable = (PsiVariable)target;
return variableIsAssignedAtPoint(variable, context,
referenceExpression);
}
public static boolean variableIsAssignedAtPoint(
@NotNull PsiVariable variable, @Nullable PsiElement context,
@NotNull PsiElement point) {
if (context == null) {
return false;
}
final PsiElement directChild =
getDirectChildWhichContainsElement(context, point);
if (directChild == null) {
return false;
}
final PsiElement[] children = context.getChildren();
for (PsiElement child : children) {
if (child == directChild) {
return variableIsAssignedAtPoint(variable, directChild, point);
}
if (variableIsAssigned(variable, child)) {
return true;
}
}
return false;
}
@Nullable
private static PsiElement getDirectChildWhichContainsElement(
@NotNull PsiElement ancestor,
@NotNull PsiElement descendant) {
if (ancestor == descendant) {
return null;
}
PsiElement child = descendant;
PsiElement parent = child.getParent();
while (!parent.equals(ancestor)) {
child = parent;
parent = child.getParent();
if (parent == null) {
return null;
}
}
return child;
}
public static Set 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 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 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 getUsedVariables() {
return usedVariables;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy