Search in sources :

Example 1 with ArrayCreation

use of lombok.ast.ArrayCreation 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
     * @deprecated Use {@link #evaluate(PsiElement)} instead
     */
@Deprecated
@Nullable
public Object evaluate(@NonNull Node node) {
    if (node instanceof NullLiteral) {
        return null;
    } else if (node instanceof BooleanLiteral) {
        return ((BooleanLiteral) node).astValue();
    } else if (node instanceof StringLiteral) {
        StringLiteral string = (StringLiteral) node;
        return string.astValue();
    } else if (node instanceof CharLiteral) {
        return ((CharLiteral) node).astValue();
    } else if (node instanceof IntegralLiteral) {
        IntegralLiteral literal = (IntegralLiteral) node;
        // Don't combine to ?: since that will promote astIntValue to a long
        if (literal.astMarkedAsLong()) {
            return literal.astLongValue();
        } else {
            return literal.astIntValue();
        }
    } else if (node instanceof FloatingPointLiteral) {
        FloatingPointLiteral literal = (FloatingPointLiteral) node;
        // Don't combine to ?: since that will promote astFloatValue to a double
        if (literal.astMarkedAsFloat()) {
            return literal.astFloatValue();
        } else {
            return literal.astDoubleValue();
        }
    } else if (node instanceof UnaryExpression) {
        UnaryOperator operator = ((UnaryExpression) node).astOperator();
        Object operand = evaluate(((UnaryExpression) node).astOperand());
        if (operand == null) {
            return null;
        }
        switch(operator) {
            case LOGICAL_NOT:
                if (operand instanceof Boolean) {
                    return !(Boolean) operand;
                }
                break;
            case UNARY_PLUS:
                return operand;
            case BINARY_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;
                }
                break;
            case 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;
                }
                break;
        }
    } else if (node instanceof InlineIfExpression) {
        InlineIfExpression expression = (InlineIfExpression) node;
        Object known = evaluate(expression.astCondition());
        if (known == Boolean.TRUE && expression.astIfTrue() != null) {
            return evaluate(expression.astIfTrue());
        } else if (known == Boolean.FALSE && expression.astIfFalse() != null) {
            return evaluate(expression.astIfFalse());
        }
    } else if (node instanceof BinaryExpression) {
        BinaryOperator operator = ((BinaryExpression) node).astOperator();
        Object operandLeft = evaluate(((BinaryExpression) node).astLeft());
        Object operandRight = evaluate(((BinaryExpression) node).astRight());
        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 == BinaryOperator.PLUS) {
                return operandLeft.toString() + operandRight.toString();
            }
            return null;
        } else if (operandLeft instanceof Boolean && operandRight instanceof Boolean) {
            boolean left = (Boolean) operandLeft;
            boolean right = (Boolean) operandRight;
            switch(operator) {
                case LOGICAL_OR:
                    return left || right;
                case LOGICAL_AND:
                    return left && right;
                case BITWISE_OR:
                    return left | right;
                case BITWISE_XOR:
                    return left ^ right;
                case BITWISE_AND:
                    return left & right;
                case EQUALS:
                    return left == right;
                case 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);
            switch(operator) {
                case BITWISE_OR:
                    if (isWide) {
                        return left.longValue() | right.longValue();
                    } else {
                        return left.intValue() | right.intValue();
                    }
                case BITWISE_XOR:
                    if (isWide) {
                        return left.longValue() ^ right.longValue();
                    } else {
                        return left.intValue() ^ right.intValue();
                    }
                case BITWISE_AND:
                    if (isWide) {
                        return left.longValue() & right.longValue();
                    } else {
                        return left.intValue() & right.intValue();
                    }
                case EQUALS:
                    if (isInteger) {
                        return left.longValue() == right.longValue();
                    } else {
                        return left.doubleValue() == right.doubleValue();
                    }
                case NOT_EQUALS:
                    if (isInteger) {
                        return left.longValue() != right.longValue();
                    } else {
                        return left.doubleValue() != right.doubleValue();
                    }
                case GREATER:
                    if (isInteger) {
                        return left.longValue() > right.longValue();
                    } else {
                        return left.doubleValue() > right.doubleValue();
                    }
                case GREATER_OR_EQUAL:
                    if (isInteger) {
                        return left.longValue() >= right.longValue();
                    } else {
                        return left.doubleValue() >= right.doubleValue();
                    }
                case LESS:
                    if (isInteger) {
                        return left.longValue() < right.longValue();
                    } else {
                        return left.doubleValue() < right.doubleValue();
                    }
                case LESS_OR_EQUAL:
                    if (isInteger) {
                        return left.longValue() <= right.longValue();
                    } else {
                        return left.doubleValue() <= right.doubleValue();
                    }
                case SHIFT_LEFT:
                    if (isWide) {
                        return left.longValue() << right.intValue();
                    } else {
                        return left.intValue() << right.intValue();
                    }
                case SHIFT_RIGHT:
                    if (isWide) {
                        return left.longValue() >> right.intValue();
                    } else {
                        return left.intValue() >> right.intValue();
                    }
                case BITWISE_SHIFT_RIGHT:
                    if (isWide) {
                        return left.longValue() >>> right.intValue();
                    } else {
                        return left.intValue() >>> right.intValue();
                    }
                case 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();
                        }
                    }
                case 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();
                        }
                    }
                case 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();
                        }
                    }
                case DIVIDE:
                    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();
                        }
                    }
                case REMAINDER:
                    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();
                        }
                    }
                default:
                    return null;
            }
        }
    } else if (node instanceof Cast) {
        Cast cast = (Cast) node;
        Object operandValue = evaluate(cast.astOperand());
        if (operandValue instanceof Number) {
            Number number = (Number) operandValue;
            String typeName = cast.astTypeReference().getTypeName();
            if (typeName.equals("float")) {
                return number.floatValue();
            } else if (typeName.equals("double")) {
                return number.doubleValue();
            } else if (typeName.equals("int")) {
                return number.intValue();
            } else if (typeName.equals("long")) {
                return number.longValue();
            } else if (typeName.equals("short")) {
                return number.shortValue();
            } else if (typeName.equals("byte")) {
                return number.byteValue();
            }
        }
        return operandValue;
    } else if (mContext != null && (node instanceof VariableReference || node instanceof Select)) {
        ResolvedNode resolved = mContext.resolve(node);
        if (resolved instanceof ResolvedField) {
            ResolvedField field = (ResolvedField) resolved;
            Object value = field.getValue();
            if (value != null) {
                return value;
            }
            Node astNode = field.findAstNode();
            if (astNode instanceof VariableDeclaration) {
                VariableDeclaration declaration = (VariableDeclaration) astNode;
                VariableDefinition definition = declaration.astDefinition();
                if (definition != null && definition.astModifiers().isFinal()) {
                    StrictListAccessor<VariableDefinitionEntry, VariableDefinition> variables = definition.astVariables();
                    if (variables.size() == 1) {
                        VariableDefinitionEntry first = variables.first();
                        if (first.astInitializer() != null) {
                            return evaluate(first.astInitializer());
                        }
                    }
                }
            }
            return null;
        } else if (node instanceof VariableReference) {
            Statement statement = getParentOfType(node, Statement.class, false);
            if (statement != null) {
                ListIterator<Node> iterator = statement.getParent().getChildren().listIterator();
                while (iterator.hasNext()) {
                    if (iterator.next() == statement) {
                        if (iterator.hasPrevious()) {
                            // should always be true
                            iterator.previous();
                        }
                        break;
                    }
                }
                String targetName = ((VariableReference) node).astIdentifier().astValue();
                while (iterator.hasPrevious()) {
                    Node previous = iterator.previous();
                    if (previous instanceof VariableDeclaration) {
                        VariableDeclaration declaration = (VariableDeclaration) previous;
                        VariableDefinition definition = declaration.astDefinition();
                        for (VariableDefinitionEntry entry : definition.astVariables()) {
                            if (entry.astInitializer() != null && entry.astName().astValue().equals(targetName)) {
                                return evaluate(entry.astInitializer());
                            }
                        }
                    } else if (previous instanceof ExpressionStatement) {
                        ExpressionStatement expressionStatement = (ExpressionStatement) previous;
                        Expression expression = expressionStatement.astExpression();
                        if (expression instanceof BinaryExpression && ((BinaryExpression) expression).astOperator() == BinaryOperator.ASSIGN) {
                            BinaryExpression binaryExpression = (BinaryExpression) expression;
                            if (targetName.equals(binaryExpression.astLeft().toString())) {
                                return evaluate(binaryExpression.astRight());
                            }
                        }
                    }
                }
            }
        }
    } else if (node instanceof ArrayCreation) {
        ArrayCreation creation = (ArrayCreation) node;
        ArrayInitializer initializer = creation.astInitializer();
        if (initializer != null) {
            TypeReference typeReference = creation.astComponentTypeReference();
            StrictListAccessor<Expression, ArrayInitializer> expressions = initializer.astExpressions();
            List<Object> values = Lists.newArrayListWithExpectedSize(expressions.size());
            Class<?> commonType = null;
            for (Expression expression : expressions) {
                Object value = evaluate(expression);
                if (value != null) {
                    values.add(value);
                    if (commonType == null) {
                        commonType = value.getClass();
                    } else {
                        while (!commonType.isAssignableFrom(value.getClass())) {
                            commonType = commonType.getSuperclass();
                        }
                    }
                } else if (!mAllowUnknown) {
                    // Inconclusive
                    return null;
                }
            }
            if (!values.isEmpty()) {
                Object o = Array.newInstance(commonType, values.size());
                return values.toArray((Object[]) o);
            } else if (mContext != null) {
                ResolvedNode type = mContext.resolve(typeReference);
                System.out.println(type);
            // TODO: return new array of this type
            }
        } else {
            // something like "new byte[3]" but with no initializer.
            String type = creation.astComponentTypeReference().toString();
            // TODO: Look up the size and only if small, use it. E.g. if it was byte[3]
            // we could return a byte[3] array, but if it's say byte[1024*1024] we don't
            // want to do that.
            int size = 0;
            if (TYPE_BYTE.equals(type)) {
                return new byte[size];
            }
            if (TYPE_BOOLEAN.equals(type)) {
                return new boolean[size];
            }
            if (TYPE_INT.equals(type)) {
                return new int[size];
            }
            if (TYPE_LONG.equals(type)) {
                return new long[size];
            }
            if (TYPE_CHAR.equals(type)) {
                return new char[size];
            }
            if (TYPE_FLOAT.equals(type)) {
                return new float[size];
            }
            if (TYPE_DOUBLE.equals(type)) {
                return new double[size];
            }
            if (TYPE_STRING.equals(type)) {
                //noinspection SSBasedInspection
                return new String[size];
            }
            if (TYPE_SHORT.equals(type)) {
                return new short[size];
            }
            if (TYPE_OBJECT.equals(type)) {
                //noinspection SSBasedInspection
                return new Object[size];
            }
        }
    }
    return null;
}
Also used : Cast(lombok.ast.Cast) VariableDefinition(lombok.ast.VariableDefinition) BooleanLiteral(lombok.ast.BooleanLiteral) Node(lombok.ast.Node) ResolvedNode(com.android.tools.klint.client.api.JavaParser.ResolvedNode) UnaryExpression(lombok.ast.UnaryExpression) IntegralLiteral(lombok.ast.IntegralLiteral) ResolvedNode(com.android.tools.klint.client.api.JavaParser.ResolvedNode) ResolvedField(com.android.tools.klint.client.api.JavaParser.ResolvedField) PsiBinaryExpression(com.intellij.psi.PsiBinaryExpression) BinaryExpression(lombok.ast.BinaryExpression) VariableDeclaration(lombok.ast.VariableDeclaration) List(java.util.List) ArrayList(java.util.ArrayList) TypeReference(lombok.ast.TypeReference) UnaryOperator(lombok.ast.UnaryOperator) InlineIfExpression(lombok.ast.InlineIfExpression) BinaryOperator(lombok.ast.BinaryOperator) StrictListAccessor(lombok.ast.StrictListAccessor) CharLiteral(lombok.ast.CharLiteral) VariableReference(lombok.ast.VariableReference) Statement(lombok.ast.Statement) PsiStatement(com.intellij.psi.PsiStatement) PsiExpressionStatement(com.intellij.psi.PsiExpressionStatement) ExpressionStatement(lombok.ast.ExpressionStatement) PsiDeclarationStatement(com.intellij.psi.PsiDeclarationStatement) ListIterator(java.util.ListIterator) StringLiteral(lombok.ast.StringLiteral) FloatingPointLiteral(lombok.ast.FloatingPointLiteral) VariableDefinitionEntry(lombok.ast.VariableDefinitionEntry) PsiAssignmentExpression(com.intellij.psi.PsiAssignmentExpression) PsiArrayInitializerExpression(com.intellij.psi.PsiArrayInitializerExpression) UReferenceExpression(org.jetbrains.uast.UReferenceExpression) UnaryExpression(lombok.ast.UnaryExpression) PsiPrefixExpression(com.intellij.psi.PsiPrefixExpression) InlineIfExpression(lombok.ast.InlineIfExpression) PsiBinaryExpression(com.intellij.psi.PsiBinaryExpression) PsiExpression(com.intellij.psi.PsiExpression) PsiReferenceExpression(com.intellij.psi.PsiReferenceExpression) PsiNewExpression(com.intellij.psi.PsiNewExpression) PsiConditionalExpression(com.intellij.psi.PsiConditionalExpression) PsiTypeCastExpression(com.intellij.psi.PsiTypeCastExpression) Expression(lombok.ast.Expression) PsiParenthesizedExpression(com.intellij.psi.PsiParenthesizedExpression) BinaryExpression(lombok.ast.BinaryExpression) PsiExpressionStatement(com.intellij.psi.PsiExpressionStatement) ExpressionStatement(lombok.ast.ExpressionStatement) Select(lombok.ast.Select) ArrayCreation(lombok.ast.ArrayCreation) PsiClass(com.intellij.psi.PsiClass) NullLiteral(lombok.ast.NullLiteral) ArrayInitializer(lombok.ast.ArrayInitializer) Nullable(com.android.annotations.Nullable)

Aggregations

Nullable (com.android.annotations.Nullable)1 ResolvedField (com.android.tools.klint.client.api.JavaParser.ResolvedField)1 ResolvedNode (com.android.tools.klint.client.api.JavaParser.ResolvedNode)1 PsiArrayInitializerExpression (com.intellij.psi.PsiArrayInitializerExpression)1 PsiAssignmentExpression (com.intellij.psi.PsiAssignmentExpression)1 PsiBinaryExpression (com.intellij.psi.PsiBinaryExpression)1 PsiClass (com.intellij.psi.PsiClass)1 PsiConditionalExpression (com.intellij.psi.PsiConditionalExpression)1 PsiDeclarationStatement (com.intellij.psi.PsiDeclarationStatement)1 PsiExpression (com.intellij.psi.PsiExpression)1 PsiExpressionStatement (com.intellij.psi.PsiExpressionStatement)1 PsiNewExpression (com.intellij.psi.PsiNewExpression)1 PsiParenthesizedExpression (com.intellij.psi.PsiParenthesizedExpression)1 PsiPrefixExpression (com.intellij.psi.PsiPrefixExpression)1 PsiReferenceExpression (com.intellij.psi.PsiReferenceExpression)1 PsiStatement (com.intellij.psi.PsiStatement)1 PsiTypeCastExpression (com.intellij.psi.PsiTypeCastExpression)1 ArrayList (java.util.ArrayList)1 List (java.util.List)1 ListIterator (java.util.ListIterator)1