Search in sources :

Example 1 with StringLiteral

use of lombok.ast.StringLiteral 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)

Example 2 with StringLiteral

use of lombok.ast.StringLiteral in project kotlin by JetBrains.

the class LintDriver method isSuppressed.

/**
     * Returns true if the given AST modifier has a suppress annotation for the
     * given issue (which can be null to check for the "all" annotation)
     *
     * @param issue the issue to be checked
     * @param modifiers the modifier to check
     * @return true if the issue or all issues should be suppressed for this
     *         modifier
     */
private static boolean isSuppressed(@Nullable Issue issue, @Nullable Modifiers modifiers) {
    if (modifiers == null) {
        return false;
    }
    StrictListAccessor<Annotation, Modifiers> annotations = modifiers.astAnnotations();
    if (annotations == null) {
        return false;
    }
    for (Annotation annotation : annotations) {
        TypeReference t = annotation.astAnnotationTypeReference();
        String typeName = t.getTypeName();
        if (typeName.endsWith(SUPPRESS_LINT) || typeName.endsWith("SuppressWarnings")) {
            //$NON-NLS-1$
            StrictListAccessor<AnnotationElement, Annotation> values = annotation.astElements();
            if (values != null) {
                for (AnnotationElement element : values) {
                    AnnotationValue valueNode = element.astValue();
                    if (valueNode == null) {
                        continue;
                    }
                    if (valueNode instanceof StringLiteral) {
                        StringLiteral literal = (StringLiteral) valueNode;
                        String value = literal.astValue();
                        if (matches(issue, value)) {
                            return true;
                        }
                    } else if (valueNode instanceof ArrayInitializer) {
                        ArrayInitializer array = (ArrayInitializer) valueNode;
                        StrictListAccessor<Expression, ArrayInitializer> expressions = array.astExpressions();
                        if (expressions == null) {
                            continue;
                        }
                        for (Expression arrayElement : expressions) {
                            if (arrayElement instanceof StringLiteral) {
                                String value = ((StringLiteral) arrayElement).astValue();
                                if (matches(issue, value)) {
                                    return true;
                                }
                            }
                        }
                    }
                }
            }
        }
    }
    return false;
}
Also used : StringLiteral(lombok.ast.StringLiteral) AnnotationElement(lombok.ast.AnnotationElement) PsiArrayInitializerExpression(com.intellij.psi.PsiArrayInitializerExpression) PsiExpression(com.intellij.psi.PsiExpression) Expression(lombok.ast.Expression) AnnotationValue(lombok.ast.AnnotationValue) TypeReference(lombok.ast.TypeReference) PsiAnnotation(com.intellij.psi.PsiAnnotation) Annotation(lombok.ast.Annotation) Modifiers(lombok.ast.Modifiers) ArrayInitializer(lombok.ast.ArrayInitializer) StrictListAccessor(lombok.ast.StrictListAccessor)

Example 3 with StringLiteral

use of lombok.ast.StringLiteral in project wire-android by wireapp.

the class WrongTimberUsageDetector method getType.

private Class<?> getType(JavaContext context, Expression expression) {
    if (expression == null) {
        return null;
    }
    if (expression instanceof MethodInvocation) {
        MethodInvocation method = (MethodInvocation) expression;
        String methodName = method.astName().astValue();
        if (methodName.equals(GET_STRING_METHOD)) {
            return String.class;
        }
    } else if (expression instanceof StringLiteral) {
        return String.class;
    } else if (expression instanceof IntegralLiteral) {
        return Integer.TYPE;
    } else if (expression instanceof FloatingPointLiteral) {
        return Float.TYPE;
    } else if (expression instanceof CharLiteral) {
        return Character.TYPE;
    } else if (expression instanceof BooleanLiteral) {
        return Boolean.TYPE;
    } else if (expression instanceof NullLiteral) {
        return Object.class;
    }
    if (context != null) {
        JavaParser.TypeDescriptor type = context.getType(expression);
        if (type != null) {
            Class<?> typeClass = getTypeClass(type);
            if (typeClass != null) {
                return typeClass;
            } else {
                return Object.class;
            }
        }
    }
    return null;
}
Also used : JavaParser(com.android.tools.lint.client.api.JavaParser) IntegralLiteral(lombok.ast.IntegralLiteral) StringLiteral(lombok.ast.StringLiteral) CharLiteral(lombok.ast.CharLiteral) FloatingPointLiteral(lombok.ast.FloatingPointLiteral) BooleanLiteral(lombok.ast.BooleanLiteral) MethodInvocation(lombok.ast.MethodInvocation) NullLiteral(lombok.ast.NullLiteral)

Example 4 with StringLiteral

use of lombok.ast.StringLiteral in project wire-android by wireapp.

the class ObjectAnimatorPropertyDetector method visitMethod.

@Override
public void visitMethod(JavaContext context, AstVisitor visitor, MethodInvocation node) {
    if (!(node.astOperand() instanceof VariableReference)) {
        return;
    }
    final VariableReference ref = (VariableReference) node.astOperand();
    if (!"ObjectAnimator".equals(ref.astIdentifier().astValue())) {
        return;
    }
    final StrictListAccessor<Expression, MethodInvocation> astArguments = node.astArguments();
    if (astArguments.size() <= 2) {
        return;
    }
    final Iterator<Expression> iterator = astArguments.iterator();
    // ignored to get the second
    iterator.next();
    final Expression property = iterator.next();
    if (property instanceof StringLiteral) {
        context.report(ISSUE, context.getLocation(node), String.format("String '%s' should be replaced", ((StringLiteral) property).astValue()));
        return;
    }
    if (context.resolve(property) == null) {
        return;
    }
    if (property instanceof VariableReference) {
        if (!isSubclassOf(context, (VariableReference) property, "android.util.Property") && !isSubclassOf(context, (VariableReference) property, "com.nineoldandroids.util.Property")) {
            context.report(ISSUE, context.getLocation(node), String.format("'%s' should be replaced with a property", ((VariableReference) property).astIdentifier().astValue()));
        }
    }
}
Also used : VariableReference(lombok.ast.VariableReference) StringLiteral(lombok.ast.StringLiteral) Expression(lombok.ast.Expression) MethodInvocation(lombok.ast.MethodInvocation)

Example 5 with StringLiteral

use of lombok.ast.StringLiteral in project kotlin by JetBrains.

the class TypeEvaluator method evaluate.

/**
     * Returns the inferred type of the given node
     * @deprecated Use {@link #evaluate(PsiElement)} instead
     */
@Deprecated
@Nullable
public TypeDescriptor evaluate(@NonNull Node node) {
    ResolvedNode resolved = null;
    if (mContext != null) {
        resolved = mContext.resolve(node);
    }
    if (resolved instanceof ResolvedMethod) {
        TypeDescriptor type;
        ResolvedMethod method = (ResolvedMethod) resolved;
        if (method.isConstructor()) {
            ResolvedClass containingClass = method.getContainingClass();
            type = containingClass.getType();
        } else {
            type = method.getReturnType();
        }
        return type;
    }
    if (resolved instanceof ResolvedField) {
        ResolvedField field = (ResolvedField) resolved;
        Node astNode = field.findAstNode();
        if (astNode instanceof VariableDeclaration) {
            VariableDeclaration declaration = (VariableDeclaration) astNode;
            VariableDefinition definition = declaration.astDefinition();
            if (definition != null) {
                VariableDefinitionEntry first = definition.astVariables().first();
                if (first != null) {
                    Expression initializer = first.astInitializer();
                    if (initializer != null) {
                        TypeDescriptor type = evaluate(initializer);
                        if (type != null) {
                            return type;
                        }
                    }
                }
            }
        }
        return field.getType();
    }
    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 Cast) {
        Cast cast = (Cast) node;
        if (mContext != null) {
            ResolvedNode typeReference = mContext.resolve(cast.astTypeReference());
            if (typeReference instanceof ResolvedClass) {
                return ((ResolvedClass) typeReference).getType();
            }
        }
        TypeDescriptor viewType = evaluate(cast.astOperand());
        if (viewType != null) {
            return viewType;
        }
    } else if (node instanceof Literal) {
        if (node instanceof NullLiteral) {
            return null;
        } else if (node instanceof BooleanLiteral) {
            return new DefaultTypeDescriptor(TYPE_BOOLEAN);
        } else if (node instanceof StringLiteral) {
            return new DefaultTypeDescriptor(TYPE_STRING);
        } else if (node instanceof CharLiteral) {
            return new DefaultTypeDescriptor(TYPE_CHAR);
        } 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 new DefaultTypeDescriptor(TYPE_LONG);
            } else {
                return new DefaultTypeDescriptor(TYPE_INT);
            }
        } 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 new DefaultTypeDescriptor(TYPE_FLOAT);
            } else {
                return new DefaultTypeDescriptor(TYPE_DOUBLE);
            }
        }
    } else if (node instanceof UnaryExpression) {
        return evaluate(((UnaryExpression) node).astOperand());
    } else if (node instanceof InlineIfExpression) {
        InlineIfExpression expression = (InlineIfExpression) node;
        if (expression.astIfTrue() != null) {
            return evaluate(expression.astIfTrue());
        } else if (expression.astIfFalse() != null) {
            return evaluate(expression.astIfFalse());
        }
    } else if (node instanceof BinaryExpression) {
        BinaryExpression expression = (BinaryExpression) node;
        BinaryOperator operator = expression.astOperator();
        switch(operator) {
            case LOGICAL_OR:
            case LOGICAL_AND:
            case EQUALS:
            case NOT_EQUALS:
            case GREATER:
            case GREATER_OR_EQUAL:
            case LESS:
            case LESS_OR_EQUAL:
                return new DefaultTypeDescriptor(TYPE_BOOLEAN);
        }
        TypeDescriptor type = evaluate(expression.astLeft());
        if (type != null) {
            return type;
        }
        return evaluate(expression.astRight());
    }
    if (resolved instanceof ResolvedVariable) {
        ResolvedVariable variable = (ResolvedVariable) resolved;
        return variable.getType();
    }
    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) DefaultTypeDescriptor(com.android.tools.klint.client.api.JavaParser.DefaultTypeDescriptor) IntegralLiteral(lombok.ast.IntegralLiteral) ResolvedNode(com.android.tools.klint.client.api.JavaParser.ResolvedNode) ResolvedField(com.android.tools.klint.client.api.JavaParser.ResolvedField) BinaryExpression(lombok.ast.BinaryExpression) IntegralLiteral(lombok.ast.IntegralLiteral) BooleanLiteral(lombok.ast.BooleanLiteral) Literal(lombok.ast.Literal) FloatingPointLiteral(lombok.ast.FloatingPointLiteral) CharLiteral(lombok.ast.CharLiteral) StringLiteral(lombok.ast.StringLiteral) NullLiteral(lombok.ast.NullLiteral) VariableDeclaration(lombok.ast.VariableDeclaration) InlineIfExpression(lombok.ast.InlineIfExpression) BinaryOperator(lombok.ast.BinaryOperator) ResolvedVariable(com.android.tools.klint.client.api.JavaParser.ResolvedVariable) VariableReference(lombok.ast.VariableReference) CharLiteral(lombok.ast.CharLiteral) Statement(lombok.ast.Statement) PsiStatement(com.intellij.psi.PsiStatement) PsiExpressionStatement(com.intellij.psi.PsiExpressionStatement) ExpressionStatement(lombok.ast.ExpressionStatement) PsiDeclarationStatement(com.intellij.psi.PsiDeclarationStatement) ResolvedClass(com.android.tools.klint.client.api.JavaParser.ResolvedClass) ResolvedMethod(com.android.tools.klint.client.api.JavaParser.ResolvedMethod) TypeDescriptor(com.android.tools.klint.client.api.JavaParser.TypeDescriptor) DefaultTypeDescriptor(com.android.tools.klint.client.api.JavaParser.DefaultTypeDescriptor) StringLiteral(lombok.ast.StringLiteral) VariableDefinitionEntry(lombok.ast.VariableDefinitionEntry) UExpression(org.jetbrains.uast.UExpression) UCallExpression(org.jetbrains.uast.UCallExpression) PsiAssignmentExpression(com.intellij.psi.PsiAssignmentExpression) UReferenceExpression(org.jetbrains.uast.UReferenceExpression) UnaryExpression(lombok.ast.UnaryExpression) InlineIfExpression(lombok.ast.InlineIfExpression) PsiExpression(com.intellij.psi.PsiExpression) PsiReferenceExpression(com.intellij.psi.PsiReferenceExpression) Expression(lombok.ast.Expression) BinaryExpression(lombok.ast.BinaryExpression) FloatingPointLiteral(lombok.ast.FloatingPointLiteral) PsiExpressionStatement(com.intellij.psi.PsiExpressionStatement) ExpressionStatement(lombok.ast.ExpressionStatement) NullLiteral(lombok.ast.NullLiteral) Nullable(com.android.annotations.Nullable)

Aggregations

StringLiteral (lombok.ast.StringLiteral)5 Expression (lombok.ast.Expression)4 PsiExpression (com.intellij.psi.PsiExpression)3 BooleanLiteral (lombok.ast.BooleanLiteral)3 CharLiteral (lombok.ast.CharLiteral)3 FloatingPointLiteral (lombok.ast.FloatingPointLiteral)3 IntegralLiteral (lombok.ast.IntegralLiteral)3 NullLiteral (lombok.ast.NullLiteral)3 Nullable (com.android.annotations.Nullable)2 ResolvedField (com.android.tools.klint.client.api.JavaParser.ResolvedField)2 ResolvedNode (com.android.tools.klint.client.api.JavaParser.ResolvedNode)2 PsiArrayInitializerExpression (com.intellij.psi.PsiArrayInitializerExpression)2 PsiAssignmentExpression (com.intellij.psi.PsiAssignmentExpression)2 PsiDeclarationStatement (com.intellij.psi.PsiDeclarationStatement)2 PsiExpressionStatement (com.intellij.psi.PsiExpressionStatement)2 PsiReferenceExpression (com.intellij.psi.PsiReferenceExpression)2 PsiStatement (com.intellij.psi.PsiStatement)2 ArrayInitializer (lombok.ast.ArrayInitializer)2 BinaryExpression (lombok.ast.BinaryExpression)2 BinaryOperator (lombok.ast.BinaryOperator)2