Search in sources :

Example 1 with Node

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

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

the class JavaParser method getNameLocation.

/**
     * Returns a {@link Location} for the given node. This attempts to pick a shorter
     * location range than the entire node; for a class or method for example, it picks
     * the name node (if found). For statement constructs such as a {@code switch} statement
     * it will highlight the keyword, etc.
     *
     * @param context information about the file being parsed
     * @param node the node to create a location for
     * @return a location for the given node
     * @deprecated Use {@link #getNameLocation(JavaContext, PsiElement)} instead
     */
@Deprecated
@NonNull
public Location getNameLocation(@NonNull JavaContext context, @NonNull Node node) {
    Node nameNode = JavaContext.findNameNode(node);
    if (nameNode != null) {
        node = nameNode;
    } else {
        if (node instanceof Switch || node instanceof For || node instanceof If || node instanceof While || node instanceof Throw || node instanceof Return) {
            // Lint doesn't want to highlight the entire statement/block associated
            // with this node, it wants to just highlight the keyword.
            Location location = getLocation(context, node);
            Position start = location.getStart();
            if (start != null) {
                // The Lombok classes happen to have the same length as the target keyword
                int length = node.getClass().getSimpleName().length();
                return Location.create(location.getFile(), start, new DefaultPosition(start.getLine(), start.getColumn() + length, start.getOffset() + length));
            }
        }
    }
    return getLocation(context, node);
}
Also used : Return(lombok.ast.Return) Switch(lombok.ast.Switch) Position(com.android.tools.klint.detector.api.Position) DefaultPosition(com.android.tools.klint.detector.api.DefaultPosition) Throw(lombok.ast.Throw) Node(lombok.ast.Node) DefaultPosition(com.android.tools.klint.detector.api.DefaultPosition) For(lombok.ast.For) While(lombok.ast.While) If(lombok.ast.If) Location(com.android.tools.klint.detector.api.Location) NonNull(com.android.annotations.NonNull)

Example 3 with Node

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

the class WrongTimberUsageDetector method visitMethod.

@Override
public void visitMethod(@NonNull JavaContext context, AstVisitor visitor, @NonNull MethodInvocation node) {
    String methodName = node.astName().getDescription();
    if ("format".equals(methodName)) {
        if (!(node.astOperand() instanceof VariableReference)) {
            return;
        }
        VariableReference ref = (VariableReference) node.astOperand();
        if (!"String".equals(ref.astIdentifier().astValue())) {
            return;
        }
        // Found a String.format call
        // Look outside to see if we inside of a Timber call
        Node current = node.getParent();
        while (current != null && !(current instanceof ExpressionStatement)) {
            current = current.getParent();
        }
        if (current == null) {
            return;
        }
        ExpressionStatement statement = (ExpressionStatement) current;
        if (!statement.toString().startsWith("Timber.")) {
            return;
        }
        context.report(ISSUE_FORMAT, node, context.getLocation(node), "Using 'String.format' instead of 'Timber'");
    } else {
        if (node.astOperand() instanceof VariableReference) {
            VariableReference ref = (VariableReference) node.astOperand();
            if ("Log".equals(ref.astIdentifier().astValue())) {
                context.report(ISSUE_LOG, node, context.getLocation(node), "Using 'Log' instead of 'Timber'");
                return;
            }
            String callName = node.astName().astValue();
            if ("d".equals(callName)) {
                String message = String.format("Use another method from timber.log.Timber or remove %1$s()", callName);
                context.report(ISSUE_D_USAGE, node, context.getLocation(node), message);
            }
            checkThrowablePosition(context, node);
            checkArguments(context, node);
        }
    }
}
Also used : VariableReference(lombok.ast.VariableReference) Node(lombok.ast.Node) ExpressionStatement(lombok.ast.ExpressionStatement)

Example 4 with Node

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

the class WrongTimberUsageDetector method checkConditionalUsage.

private boolean checkConditionalUsage(JavaContext context, MethodInvocation node, Node argument) {
    Node thenStatement;
    Node elseStatement;
    if (argument instanceof If) {
        thenStatement = ((If) argument).astStatement();
        elseStatement = ((If) argument).astElseStatement();
    } else if (argument instanceof InlineIfExpression) {
        thenStatement = ((InlineIfExpression) argument).astIfFalse();
        elseStatement = ((InlineIfExpression) argument).astIfTrue();
    } else {
        return false;
    }
    if (!checkNode(context, node, thenStatement)) {
        return checkNode(context, node, elseStatement);
    }
    return false;
}
Also used : Node(lombok.ast.Node) InlineIfExpression(lombok.ast.InlineIfExpression) If(lombok.ast.If)

Example 5 with Node

use of lombok.ast.Node in project android by JetBrains.

the class LintIdeJavaParser method findClass.

@Nullable
@Override
public ResolvedClass findClass(@NonNull JavaContext context, @NonNull final String fullyQualifiedName) {
    Node compilationUnit = context.getCompilationUnit();
    if (compilationUnit == null) {
        return null;
    }
    final PsiElement element = getPsiElement(compilationUnit);
    if (element == null) {
        return null;
    }
    return ApplicationManager.getApplication().runReadAction(new Computable<ResolvedClass>() {

        @Nullable
        @Override
        public ResolvedClass compute() {
            PsiClass aClass = JavaPsiFacade.getInstance(element.getProject()).findClass(fullyQualifiedName, element.getResolveScope());
            if (aClass != null) {
                return new ResolvedPsiClass(aClass);
            }
            return null;
        }
    });
}
Also used : Node(lombok.ast.Node) Nullable(com.android.annotations.Nullable) Nullable(com.android.annotations.Nullable)

Aggregations

Node (lombok.ast.Node)10 Nullable (com.android.annotations.Nullable)5 ResolvedNode (com.android.tools.klint.client.api.JavaParser.ResolvedNode)3 ExpressionStatement (lombok.ast.ExpressionStatement)3 InlineIfExpression (lombok.ast.InlineIfExpression)3 ResolvedField (com.android.tools.klint.client.api.JavaParser.ResolvedField)2 PsiAssignmentExpression (com.intellij.psi.PsiAssignmentExpression)2 PsiDeclarationStatement (com.intellij.psi.PsiDeclarationStatement)2 PsiExpression (com.intellij.psi.PsiExpression)2 PsiExpressionStatement (com.intellij.psi.PsiExpressionStatement)2 PsiReferenceExpression (com.intellij.psi.PsiReferenceExpression)2 PsiStatement (com.intellij.psi.PsiStatement)2 BinaryExpression (lombok.ast.BinaryExpression)2 BinaryOperator (lombok.ast.BinaryOperator)2 BooleanLiteral (lombok.ast.BooleanLiteral)2 Cast (lombok.ast.Cast)2 CharLiteral (lombok.ast.CharLiteral)2 CompilationUnit (lombok.ast.CompilationUnit)2 Expression (lombok.ast.Expression)2 FloatingPointLiteral (lombok.ast.FloatingPointLiteral)2