Search in sources :

Example 1 with TypeReference

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

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

Aggregations

PsiArrayInitializerExpression (com.intellij.psi.PsiArrayInitializerExpression)2 PsiExpression (com.intellij.psi.PsiExpression)2 ArrayInitializer (lombok.ast.ArrayInitializer)2 Expression (lombok.ast.Expression)2 StrictListAccessor (lombok.ast.StrictListAccessor)2 StringLiteral (lombok.ast.StringLiteral)2 TypeReference (lombok.ast.TypeReference)2 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 PsiAnnotation (com.intellij.psi.PsiAnnotation)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 PsiExpressionStatement (com.intellij.psi.PsiExpressionStatement)1 PsiNewExpression (com.intellij.psi.PsiNewExpression)1 PsiParenthesizedExpression (com.intellij.psi.PsiParenthesizedExpression)1 PsiPrefixExpression (com.intellij.psi.PsiPrefixExpression)1