use of com.intellij.psi.PsiVariable in project intellij-community by JetBrains.
the class LocalVariableEvaluator method evaluate.
@Override
public Object evaluate(EvaluationContextImpl context) throws EvaluateException {
StackFrameProxyImpl frameProxy = context.getFrameProxy();
if (frameProxy == null) {
throw EvaluateExceptionUtil.createEvaluateException(DebuggerBundle.message("evaluation.error.no.stackframe"));
}
try {
ThreadReferenceProxyImpl threadProxy = null;
int lastFrameIndex = -1;
PsiVariable variable = null;
DebugProcessImpl process = context.getDebugProcess();
boolean topFrame = true;
while (true) {
try {
LocalVariableProxyImpl local = frameProxy.visibleVariableByName(myLocalVariableName);
if (local != null) {
if (topFrame || variable.equals(resolveVariable(frameProxy, myLocalVariableName, context.getProject(), process))) {
myEvaluatedVariable = local;
myContext = context;
return frameProxy.getValue(local);
}
}
} catch (EvaluateException e) {
if (!(e.getCause() instanceof AbsentInformationException)) {
throw e;
}
// try to look in slots
try {
Map<DecompiledLocalVariable, Value> vars = LocalVariablesUtil.fetchValues(frameProxy, process, true);
for (Map.Entry<DecompiledLocalVariable, Value> entry : vars.entrySet()) {
DecompiledLocalVariable var = entry.getKey();
if (var.getMatchedNames().contains(myLocalVariableName) || var.getDefaultName().equals(myLocalVariableName)) {
myEvaluatedDecompiledVariable = var;
myContext = context;
return entry.getValue();
}
}
} catch (Exception e1) {
LOG.info(e1);
}
}
if (myCanScanFrames) {
if (topFrame) {
variable = resolveVariable(frameProxy, myLocalVariableName, context.getProject(), process);
if (variable == null)
break;
}
if (threadProxy == null) /* initialize it lazily */
{
threadProxy = frameProxy.threadProxy();
lastFrameIndex = threadProxy.frameCount() - 1;
}
int currentFrameIndex = frameProxy.getFrameIndex();
if (currentFrameIndex < lastFrameIndex) {
frameProxy = threadProxy.frame(currentFrameIndex + 1);
if (frameProxy != null) {
topFrame = false;
continue;
}
}
}
break;
}
throw EvaluateExceptionUtil.createEvaluateException(DebuggerBundle.message("evaluation.error.local.variable.missing", myLocalVariableName));
} catch (EvaluateException e) {
myEvaluatedVariable = null;
myContext = null;
throw e;
}
}
use of com.intellij.psi.PsiVariable in project kotlin by JetBrains.
the class ResourceEvaluator method getResourceTypes.
/**
* Evaluates the given node and returns the resource types applicable to the
* node, if any.
*
* @param element the element to compute the types for
* @return the corresponding resource types
*/
@Nullable
public EnumSet<ResourceType> getResourceTypes(@Nullable UElement element) {
if (element == null) {
return null;
}
if (element instanceof UIfExpression) {
UIfExpression expression = (UIfExpression) element;
Object known = ConstantEvaluator.evaluate(null, expression.getCondition());
if (known == Boolean.TRUE && expression.getThenExpression() != null) {
return getResourceTypes(expression.getThenExpression());
} else if (known == Boolean.FALSE && expression.getElseExpression() != null) {
return getResourceTypes(expression.getElseExpression());
} else {
EnumSet<ResourceType> left = getResourceTypes(expression.getThenExpression());
EnumSet<ResourceType> right = getResourceTypes(expression.getElseExpression());
if (left == null) {
return right;
} else if (right == null) {
return left;
} else {
EnumSet<ResourceType> copy = EnumSet.copyOf(left);
copy.addAll(right);
return copy;
}
}
} else if (element instanceof UParenthesizedExpression) {
UParenthesizedExpression parenthesizedExpression = (UParenthesizedExpression) element;
return getResourceTypes(parenthesizedExpression.getExpression());
} else if ((element instanceof UQualifiedReferenceExpression && mAllowDereference) || element instanceof UCallExpression) {
UElement probablyCallExpression = element;
if (element instanceof UQualifiedReferenceExpression) {
UQualifiedReferenceExpression qualifiedExpression = (UQualifiedReferenceExpression) element;
probablyCallExpression = qualifiedExpression.getSelector();
}
if ((probablyCallExpression instanceof UCallExpression)) {
UCallExpression call = (UCallExpression) probablyCallExpression;
PsiMethod method = call.resolve();
PsiClass containingClass = UastUtils.getContainingClass(method);
if (method != null && containingClass != null) {
EnumSet<ResourceType> types = getTypesFromAnnotations(method);
if (types != null) {
return types;
}
String qualifiedName = containingClass.getQualifiedName();
String name = call.getMethodName();
if ((CLASS_RESOURCES.equals(qualifiedName) || CLASS_CONTEXT.equals(qualifiedName) || CLASS_FRAGMENT.equals(qualifiedName) || CLASS_V4_FRAGMENT.equals(qualifiedName) || CLS_TYPED_ARRAY.equals(qualifiedName)) && name != null && name.startsWith("get")) {
List<UExpression> args = call.getValueArguments();
if (!args.isEmpty()) {
types = getResourceTypes(args.get(0));
if (types != null) {
return types;
}
}
}
}
}
}
if (element instanceof UReferenceExpression) {
ResourceUrl url = getResourceConstant(element);
if (url != null) {
return EnumSet.of(url.type);
}
PsiElement resolved = ((UReferenceExpression) element).resolve();
if (resolved instanceof PsiVariable) {
PsiVariable variable = (PsiVariable) resolved;
UElement lastAssignment = UastLintUtils.findLastAssignment(variable, element, mContext);
if (lastAssignment != null) {
return getResourceTypes(lastAssignment);
}
return null;
}
}
return null;
}
use of com.intellij.psi.PsiVariable in project kotlin by JetBrains.
the class ResourceEvaluator method getResource.
/**
* Evaluates the given node and returns the resource reference (type and name) it
* points to, if any
*
* @param element the node to compute the constant value for
* @return the corresponding constant value - a String, an Integer, a Float, and so on
*/
@Nullable
public ResourceUrl getResource(@Nullable UElement element) {
if (element == null) {
return null;
}
if (element instanceof UIfExpression) {
UIfExpression expression = (UIfExpression) element;
Object known = ConstantEvaluator.evaluate(null, expression.getCondition());
if (known == Boolean.TRUE && expression.getThenExpression() != null) {
return getResource(expression.getThenExpression());
} else if (known == Boolean.FALSE && expression.getElseExpression() != null) {
return getResource(expression.getElseExpression());
}
} else if (element instanceof UParenthesizedExpression) {
UParenthesizedExpression parenthesizedExpression = (UParenthesizedExpression) element;
return getResource(parenthesizedExpression.getExpression());
} else if (mAllowDereference && element instanceof UQualifiedReferenceExpression) {
UQualifiedReferenceExpression qualifiedExpression = (UQualifiedReferenceExpression) element;
UExpression selector = qualifiedExpression.getSelector();
if ((selector instanceof UCallExpression)) {
UCallExpression call = (UCallExpression) selector;
PsiMethod function = call.resolve();
PsiClass containingClass = UastUtils.getContainingClass(function);
if (function != null && containingClass != null) {
String qualifiedName = containingClass.getQualifiedName();
String name = call.getMethodName();
if ((CLASS_RESOURCES.equals(qualifiedName) || CLASS_CONTEXT.equals(qualifiedName) || CLASS_FRAGMENT.equals(qualifiedName) || CLASS_V4_FRAGMENT.equals(qualifiedName) || CLS_TYPED_ARRAY.equals(qualifiedName)) && name != null && name.startsWith("get")) {
List<UExpression> args = call.getValueArguments();
if (!args.isEmpty()) {
return getResource(args.get(0));
}
}
}
}
}
if (element instanceof UReferenceExpression) {
ResourceUrl url = getResourceConstant(element);
if (url != null) {
return url;
}
PsiElement resolved = ((UReferenceExpression) element).resolve();
if (resolved instanceof PsiVariable) {
PsiVariable variable = (PsiVariable) resolved;
UElement lastAssignment = UastLintUtils.findLastAssignment(variable, element, mContext);
if (lastAssignment != null) {
return getResource(lastAssignment);
}
return null;
}
}
return null;
}
use of com.intellij.psi.PsiVariable in project kotlin by JetBrains.
the class ConstantEvaluator method evaluate.
/**
* Evaluates the given node and returns the constant value it resolves to, if any
*
* @param node the node to compute the constant value for
* @return the corresponding constant value - a String, an Integer, a Float, and so on
*/
@Nullable
public Object evaluate(@Nullable UElement node) {
if (node == null) {
return null;
}
if (node instanceof ULiteralExpression) {
return ((ULiteralExpression) node).getValue();
} else if (node instanceof UPrefixExpression) {
UastPrefixOperator operator = ((UPrefixExpression) node).getOperator();
Object operand = evaluate(((UPrefixExpression) node).getOperand());
if (operand == null) {
return null;
}
if (operator == UastPrefixOperator.LOGICAL_NOT) {
if (operand instanceof Boolean) {
return !(Boolean) operand;
}
} else if (operator == UastPrefixOperator.UNARY_PLUS) {
return operand;
} else if (operator == UastPrefixOperator.BITWISE_NOT) {
if (operand instanceof Integer) {
return ~(Integer) operand;
} else if (operand instanceof Long) {
return ~(Long) operand;
} else if (operand instanceof Short) {
return ~(Short) operand;
} else if (operand instanceof Character) {
return ~(Character) operand;
} else if (operand instanceof Byte) {
return ~(Byte) operand;
}
} else if (operator == UastPrefixOperator.UNARY_MINUS) {
if (operand instanceof Integer) {
return -(Integer) operand;
} else if (operand instanceof Long) {
return -(Long) operand;
} else if (operand instanceof Double) {
return -(Double) operand;
} else if (operand instanceof Float) {
return -(Float) operand;
} else if (operand instanceof Short) {
return -(Short) operand;
} else if (operand instanceof Character) {
return -(Character) operand;
} else if (operand instanceof Byte) {
return -(Byte) operand;
}
}
} else if (node instanceof UIfExpression && ((UIfExpression) node).getExpressionType() != null) {
UIfExpression expression = (UIfExpression) node;
Object known = evaluate(expression.getCondition());
if (known == Boolean.TRUE && expression.getThenExpression() != null) {
return evaluate(expression.getThenExpression());
} else if (known == Boolean.FALSE && expression.getElseExpression() != null) {
return evaluate(expression.getElseExpression());
}
} else if (node instanceof UParenthesizedExpression) {
UParenthesizedExpression parenthesizedExpression = (UParenthesizedExpression) node;
UExpression expression = parenthesizedExpression.getExpression();
return evaluate(expression);
} else if (node instanceof UBinaryExpression) {
UastBinaryOperator operator = ((UBinaryExpression) node).getOperator();
Object operandLeft = evaluate(((UBinaryExpression) node).getLeftOperand());
Object operandRight = evaluate(((UBinaryExpression) node).getRightOperand());
if (operandLeft == null || operandRight == null) {
if (mAllowUnknown) {
if (operandLeft == null) {
return operandRight;
} else {
return operandLeft;
}
}
return null;
}
if (operandLeft instanceof String && operandRight instanceof String) {
if (operator == UastBinaryOperator.PLUS) {
return operandLeft.toString() + operandRight.toString();
}
return null;
} else if (operandLeft instanceof Boolean && operandRight instanceof Boolean) {
boolean left = (Boolean) operandLeft;
boolean right = (Boolean) operandRight;
if (operator == UastBinaryOperator.LOGICAL_OR) {
return left || right;
} else if (operator == UastBinaryOperator.LOGICAL_AND) {
return left && right;
} else if (operator == UastBinaryOperator.BITWISE_OR) {
return left | right;
} else if (operator == UastBinaryOperator.BITWISE_XOR) {
return left ^ right;
} else if (operator == UastBinaryOperator.BITWISE_AND) {
return left & right;
} else if (operator == UastBinaryOperator.IDENTITY_EQUALS || operator == UastBinaryOperator.EQUALS) {
return left == right;
} else if (operator == UastBinaryOperator.IDENTITY_NOT_EQUALS || operator == UastBinaryOperator.NOT_EQUALS) {
return left != right;
}
} else if (operandLeft instanceof Number && operandRight instanceof Number) {
Number left = (Number) operandLeft;
Number right = (Number) operandRight;
boolean isInteger = !(left instanceof Float || left instanceof Double || right instanceof Float || right instanceof Double);
boolean isWide = isInteger ? (left instanceof Long || right instanceof Long) : (left instanceof Double || right instanceof Double);
if (operator == UastBinaryOperator.BITWISE_OR) {
if (isWide) {
return left.longValue() | right.longValue();
} else {
return left.intValue() | right.intValue();
}
} else if (operator == UastBinaryOperator.BITWISE_XOR) {
if (isWide) {
return left.longValue() ^ right.longValue();
} else {
return left.intValue() ^ right.intValue();
}
} else if (operator == UastBinaryOperator.BITWISE_AND) {
if (isWide) {
return left.longValue() & right.longValue();
} else {
return left.intValue() & right.intValue();
}
} else if (operator == UastBinaryOperator.EQUALS || operator == UastBinaryOperator.IDENTITY_EQUALS) {
if (isInteger) {
return left.longValue() == right.longValue();
} else {
return left.doubleValue() == right.doubleValue();
}
} else if (operator == UastBinaryOperator.NOT_EQUALS || operator == UastBinaryOperator.IDENTITY_NOT_EQUALS) {
if (isInteger) {
return left.longValue() != right.longValue();
} else {
return left.doubleValue() != right.doubleValue();
}
} else if (operator == UastBinaryOperator.GREATER) {
if (isInteger) {
return left.longValue() > right.longValue();
} else {
return left.doubleValue() > right.doubleValue();
}
} else if (operator == UastBinaryOperator.GREATER_OR_EQUALS) {
if (isInteger) {
return left.longValue() >= right.longValue();
} else {
return left.doubleValue() >= right.doubleValue();
}
} else if (operator == UastBinaryOperator.LESS) {
if (isInteger) {
return left.longValue() < right.longValue();
} else {
return left.doubleValue() < right.doubleValue();
}
} else if (operator == UastBinaryOperator.LESS_OR_EQUALS) {
if (isInteger) {
return left.longValue() <= right.longValue();
} else {
return left.doubleValue() <= right.doubleValue();
}
} else if (operator == UastBinaryOperator.SHIFT_LEFT) {
if (isWide) {
return left.longValue() << right.intValue();
} else {
return left.intValue() << right.intValue();
}
} else if (operator == UastBinaryOperator.SHIFT_RIGHT) {
if (isWide) {
return left.longValue() >> right.intValue();
} else {
return left.intValue() >> right.intValue();
}
} else if (operator == UastBinaryOperator.UNSIGNED_SHIFT_RIGHT) {
if (isWide) {
return left.longValue() >>> right.intValue();
} else {
return left.intValue() >>> right.intValue();
}
} else if (operator == UastBinaryOperator.PLUS) {
if (isInteger) {
if (isWide) {
return left.longValue() + right.longValue();
} else {
return left.intValue() + right.intValue();
}
} else {
if (isWide) {
return left.doubleValue() + right.doubleValue();
} else {
return left.floatValue() + right.floatValue();
}
}
} else if (operator == UastBinaryOperator.MINUS) {
if (isInteger) {
if (isWide) {
return left.longValue() - right.longValue();
} else {
return left.intValue() - right.intValue();
}
} else {
if (isWide) {
return left.doubleValue() - right.doubleValue();
} else {
return left.floatValue() - right.floatValue();
}
}
} else if (operator == UastBinaryOperator.MULTIPLY) {
if (isInteger) {
if (isWide) {
return left.longValue() * right.longValue();
} else {
return left.intValue() * right.intValue();
}
} else {
if (isWide) {
return left.doubleValue() * right.doubleValue();
} else {
return left.floatValue() * right.floatValue();
}
}
} else if (operator == UastBinaryOperator.DIV) {
if (isInteger) {
if (isWide) {
return left.longValue() / right.longValue();
} else {
return left.intValue() / right.intValue();
}
} else {
if (isWide) {
return left.doubleValue() / right.doubleValue();
} else {
return left.floatValue() / right.floatValue();
}
}
} else if (operator == UastBinaryOperator.MOD) {
if (isInteger) {
if (isWide) {
return left.longValue() % right.longValue();
} else {
return left.intValue() % right.intValue();
}
} else {
if (isWide) {
return left.doubleValue() % right.doubleValue();
} else {
return left.floatValue() % right.floatValue();
}
}
} else {
return null;
}
}
} else if (node instanceof UBinaryExpressionWithType && ((UBinaryExpressionWithType) node).getOperationKind() == TYPE_CAST) {
UBinaryExpressionWithType cast = (UBinaryExpressionWithType) node;
Object operandValue = evaluate(cast.getOperand());
if (operandValue instanceof Number) {
Number number = (Number) operandValue;
PsiType type = cast.getType();
if (PsiType.FLOAT.equals(type)) {
return number.floatValue();
} else if (PsiType.DOUBLE.equals(type)) {
return number.doubleValue();
} else if (PsiType.INT.equals(type)) {
return number.intValue();
} else if (PsiType.LONG.equals(type)) {
return number.longValue();
} else if (PsiType.SHORT.equals(type)) {
return number.shortValue();
} else if (PsiType.BYTE.equals(type)) {
return number.byteValue();
}
}
return operandValue;
} else if (node instanceof UReferenceExpression) {
PsiElement resolved = ((UReferenceExpression) node).resolve();
if (resolved instanceof PsiVariable) {
PsiVariable variable = (PsiVariable) resolved;
Object value = UastLintUtils.findLastValue(variable, node, mContext, this);
if (value != null) {
return value;
}
if (variable.getInitializer() != null) {
return evaluate(variable.getInitializer());
}
return null;
}
} else if (UastExpressionUtils.isNewArrayWithDimensions((UExpression) node)) {
UCallExpression call = (UCallExpression) node;
PsiType arrayType = call.getExpressionType();
if (arrayType instanceof PsiArrayType) {
PsiType componentType = ((PsiArrayType) arrayType).getComponentType();
// Single-dimension array
if (!(componentType instanceof PsiArrayType) && call.getValueArgumentCount() == 1) {
Object lengthObj = evaluate(call.getValueArguments().get(0));
if (lengthObj instanceof Number) {
int length = ((Number) lengthObj).intValue();
if (length > 30) {
length = 30;
}
if (componentType == PsiType.BOOLEAN) {
return new boolean[length];
} else if (isObjectType(componentType)) {
return new Object[length];
} else if (componentType == PsiType.CHAR) {
return new char[length];
} else if (componentType == PsiType.BYTE) {
return new byte[length];
} else if (componentType == PsiType.DOUBLE) {
return new double[length];
} else if (componentType == PsiType.FLOAT) {
return new float[length];
} else if (componentType == PsiType.INT) {
return new int[length];
} else if (componentType == PsiType.SHORT) {
return new short[length];
} else if (componentType == PsiType.LONG) {
return new long[length];
} else if (isStringType(componentType)) {
return new String[length];
}
}
}
}
} else if (UastExpressionUtils.isNewArrayWithInitializer(node)) {
UCallExpression call = (UCallExpression) node;
PsiType arrayType = call.getExpressionType();
if (arrayType instanceof PsiArrayType) {
PsiType componentType = ((PsiArrayType) arrayType).getComponentType();
// Single-dimension array
if (!(componentType instanceof PsiArrayType)) {
int length = call.getValueArgumentCount();
List<Object> evaluatedArgs = new ArrayList<Object>(length);
for (UExpression arg : call.getValueArguments()) {
Object evaluatedArg = evaluate(arg);
if (!mAllowUnknown && evaluatedArg == null) {
// Inconclusive
return null;
}
evaluatedArgs.add(evaluatedArg);
}
if (componentType == PsiType.BOOLEAN) {
boolean[] arr = new boolean[length];
for (int i = 0; i < length; ++i) {
Object o = evaluatedArgs.get(i);
if (o instanceof Boolean) {
arr[i] = (Boolean) o;
}
}
return arr;
} else if (isObjectType(componentType)) {
Object[] arr = new Object[length];
for (int i = 0; i < length; ++i) {
arr[i] = evaluatedArgs.get(i);
}
return arr;
} else if (componentType.equals(PsiType.CHAR)) {
char[] arr = new char[length];
for (int i = 0; i < length; ++i) {
Object o = evaluatedArgs.get(i);
if (o instanceof Character) {
arr[i] = (Character) o;
}
}
return arr;
} else if (componentType.equals(PsiType.BYTE)) {
byte[] arr = new byte[length];
for (int i = 0; i < length; ++i) {
Object o = evaluatedArgs.get(i);
if (o instanceof Byte) {
arr[i] = (Byte) o;
}
}
return arr;
} else if (componentType.equals(PsiType.DOUBLE)) {
double[] arr = new double[length];
for (int i = 0; i < length; ++i) {
Object o = evaluatedArgs.get(i);
if (o instanceof Double) {
arr[i] = (Double) o;
}
}
return arr;
} else if (componentType.equals(PsiType.FLOAT)) {
float[] arr = new float[length];
for (int i = 0; i < length; ++i) {
Object o = evaluatedArgs.get(i);
if (o instanceof Float) {
arr[i] = (Float) o;
}
}
return arr;
} else if (componentType.equals(PsiType.INT)) {
int[] arr = new int[length];
for (int i = 0; i < length; ++i) {
Object o = evaluatedArgs.get(i);
if (o instanceof Integer) {
arr[i] = (Integer) o;
}
}
return arr;
} else if (componentType.equals(PsiType.SHORT)) {
short[] arr = new short[length];
for (int i = 0; i < length; ++i) {
Object o = evaluatedArgs.get(i);
if (o instanceof Short) {
arr[i] = (Short) o;
}
}
return arr;
} else if (componentType.equals(PsiType.LONG)) {
long[] arr = new long[length];
for (int i = 0; i < length; ++i) {
Object o = evaluatedArgs.get(i);
if (o instanceof Long) {
arr[i] = (Long) o;
}
}
return arr;
} else if (isStringType(componentType)) {
String[] arr = new String[length];
for (int i = 0; i < length; ++i) {
Object o = evaluatedArgs.get(i);
if (o instanceof String) {
arr[i] = (String) o;
}
}
return arr;
}
}
}
}
if (node instanceof UExpression) {
Object evaluated = ((UExpression) node).evaluate();
if (evaluated != null) {
return evaluated;
}
}
return null;
}
Aggregations