Search in sources :

Example 76 with Nullable

use of com.android.annotations.Nullable in project kotlin by JetBrains.

the class ClassContext method getSourceFile.

/**
     * Returns the source file for this class file, if possible.
     *
     * @return the source file, or null
     */
@Nullable
public File getSourceFile() {
    if (mSourceFile == null && !mSearchedForSource) {
        mSearchedForSource = true;
        String source = mClassNode.sourceFile;
        if (source == null) {
            source = file.getName();
            if (source.endsWith(DOT_CLASS)) {
                source = source.substring(0, source.length() - DOT_CLASS.length()) + ".kt";
            }
            int index = source.indexOf('$');
            if (index != -1) {
                source = source.substring(0, index) + ".kt";
            }
        }
        if (source != null) {
            if (mJarFile != null) {
                String relative = file.getParent() + File.separator + source;
                List<File> sources = getProject().getJavaSourceFolders();
                for (File dir : sources) {
                    File sourceFile = new File(dir, relative);
                    if (sourceFile.exists()) {
                        mSourceFile = sourceFile;
                        break;
                    }
                }
            } else {
                // Determine package
                String topPath = mBinDir.getPath();
                String parentPath = file.getParentFile().getPath();
                if (parentPath.startsWith(topPath)) {
                    int start = topPath.length() + 1;
                    String relative = // default package?
                    start > parentPath.length() ? "" : parentPath.substring(start);
                    List<File> sources = getProject().getJavaSourceFolders();
                    for (File dir : sources) {
                        File sourceFile = new File(dir, relative + File.separator + source);
                        if (sourceFile.exists()) {
                            mSourceFile = sourceFile;
                            break;
                        }
                    }
                }
            }
        }
    }
    return mSourceFile;
}
Also used : File(java.io.File) Nullable(com.android.annotations.Nullable)

Example 77 with Nullable

use of com.android.annotations.Nullable in project kotlin by JetBrains.

the class ConstantEvaluator method evaluate.

/**
     * Evaluates the given node and returns the constant value it resolves to, if any
     *
     * @param node the node to compute the constant value for
     * @return the corresponding constant value - a String, an Integer, a Float, and so on
     */
@Nullable
public Object evaluate(@Nullable PsiElement node) {
    if (node == null) {
        return null;
    }
    if (node instanceof PsiLiteral) {
        return ((PsiLiteral) node).getValue();
    } else if (node instanceof PsiPrefixExpression) {
        IElementType operator = ((PsiPrefixExpression) node).getOperationTokenType();
        Object operand = evaluate(((PsiPrefixExpression) node).getOperand());
        if (operand == null) {
            return null;
        }
        if (operator == JavaTokenType.EXCL) {
            if (operand instanceof Boolean) {
                return !(Boolean) operand;
            }
        } else if (operator == JavaTokenType.PLUS) {
            return operand;
        } else if (operator == JavaTokenType.TILDE) {
            if (operand instanceof Integer) {
                return ~(Integer) operand;
            } else if (operand instanceof Long) {
                return ~(Long) operand;
            } else if (operand instanceof Short) {
                return ~(Short) operand;
            } else if (operand instanceof Character) {
                return ~(Character) operand;
            } else if (operand instanceof Byte) {
                return ~(Byte) operand;
            }
        } else if (operator == JavaTokenType.MINUS) {
            if (operand instanceof Integer) {
                return -(Integer) operand;
            } else if (operand instanceof Long) {
                return -(Long) operand;
            } else if (operand instanceof Double) {
                return -(Double) operand;
            } else if (operand instanceof Float) {
                return -(Float) operand;
            } else if (operand instanceof Short) {
                return -(Short) operand;
            } else if (operand instanceof Character) {
                return -(Character) operand;
            } else if (operand instanceof Byte) {
                return -(Byte) operand;
            }
        }
    } else if (node instanceof PsiConditionalExpression) {
        PsiConditionalExpression expression = (PsiConditionalExpression) node;
        Object known = evaluate(expression.getCondition());
        if (known == Boolean.TRUE && expression.getThenExpression() != null) {
            return evaluate(expression.getThenExpression());
        } else if (known == Boolean.FALSE && expression.getElseExpression() != null) {
            return evaluate(expression.getElseExpression());
        }
    } else if (node instanceof PsiParenthesizedExpression) {
        PsiParenthesizedExpression parenthesizedExpression = (PsiParenthesizedExpression) node;
        PsiExpression expression = parenthesizedExpression.getExpression();
        if (expression != null) {
            return evaluate(expression);
        }
    } else if (node instanceof PsiBinaryExpression) {
        IElementType operator = ((PsiBinaryExpression) node).getOperationTokenType();
        Object operandLeft = evaluate(((PsiBinaryExpression) node).getLOperand());
        Object operandRight = evaluate(((PsiBinaryExpression) node).getROperand());
        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 == JavaTokenType.PLUS) {
                return operandLeft.toString() + operandRight.toString();
            }
            return null;
        } else if (operandLeft instanceof Boolean && operandRight instanceof Boolean) {
            boolean left = (Boolean) operandLeft;
            boolean right = (Boolean) operandRight;
            if (operator == JavaTokenType.OROR) {
                return left || right;
            } else if (operator == JavaTokenType.ANDAND) {
                return left && right;
            } else if (operator == JavaTokenType.OR) {
                return left | right;
            } else if (operator == JavaTokenType.XOR) {
                return left ^ right;
            } else if (operator == JavaTokenType.AND) {
                return left & right;
            } else if (operator == JavaTokenType.EQEQ) {
                return left == right;
            } else if (operator == JavaTokenType.NE) {
                return left != right;
            }
        } else if (operandLeft instanceof Number && operandRight instanceof Number) {
            Number left = (Number) operandLeft;
            Number right = (Number) operandRight;
            boolean isInteger = !(left instanceof Float || left instanceof Double || right instanceof Float || right instanceof Double);
            boolean isWide = isInteger ? (left instanceof Long || right instanceof Long) : (left instanceof Double || right instanceof Double);
            if (operator == JavaTokenType.OR) {
                if (isWide) {
                    return left.longValue() | right.longValue();
                } else {
                    return left.intValue() | right.intValue();
                }
            } else if (operator == JavaTokenType.XOR) {
                if (isWide) {
                    return left.longValue() ^ right.longValue();
                } else {
                    return left.intValue() ^ right.intValue();
                }
            } else if (operator == JavaTokenType.AND) {
                if (isWide) {
                    return left.longValue() & right.longValue();
                } else {
                    return left.intValue() & right.intValue();
                }
            } else if (operator == JavaTokenType.EQEQ) {
                if (isInteger) {
                    return left.longValue() == right.longValue();
                } else {
                    return left.doubleValue() == right.doubleValue();
                }
            } else if (operator == JavaTokenType.NE) {
                if (isInteger) {
                    return left.longValue() != right.longValue();
                } else {
                    return left.doubleValue() != right.doubleValue();
                }
            } else if (operator == JavaTokenType.GT) {
                if (isInteger) {
                    return left.longValue() > right.longValue();
                } else {
                    return left.doubleValue() > right.doubleValue();
                }
            } else if (operator == JavaTokenType.GE) {
                if (isInteger) {
                    return left.longValue() >= right.longValue();
                } else {
                    return left.doubleValue() >= right.doubleValue();
                }
            } else if (operator == JavaTokenType.LT) {
                if (isInteger) {
                    return left.longValue() < right.longValue();
                } else {
                    return left.doubleValue() < right.doubleValue();
                }
            } else if (operator == JavaTokenType.LE) {
                if (isInteger) {
                    return left.longValue() <= right.longValue();
                } else {
                    return left.doubleValue() <= right.doubleValue();
                }
            } else if (operator == JavaTokenType.LTLT) {
                if (isWide) {
                    return left.longValue() << right.intValue();
                } else {
                    return left.intValue() << right.intValue();
                }
            } else if (operator == JavaTokenType.GTGT) {
                if (isWide) {
                    return left.longValue() >> right.intValue();
                } else {
                    return left.intValue() >> right.intValue();
                }
            } else if (operator == JavaTokenType.GTGTGT) {
                if (isWide) {
                    return left.longValue() >>> right.intValue();
                } else {
                    return left.intValue() >>> right.intValue();
                }
            } else if (operator == JavaTokenType.PLUS) {
                if (isInteger) {
                    if (isWide) {
                        return left.longValue() + right.longValue();
                    } else {
                        return left.intValue() + right.intValue();
                    }
                } else {
                    if (isWide) {
                        return left.doubleValue() + right.doubleValue();
                    } else {
                        return left.floatValue() + right.floatValue();
                    }
                }
            } else if (operator == JavaTokenType.MINUS) {
                if (isInteger) {
                    if (isWide) {
                        return left.longValue() - right.longValue();
                    } else {
                        return left.intValue() - right.intValue();
                    }
                } else {
                    if (isWide) {
                        return left.doubleValue() - right.doubleValue();
                    } else {
                        return left.floatValue() - right.floatValue();
                    }
                }
            } else if (operator == JavaTokenType.ASTERISK) {
                if (isInteger) {
                    if (isWide) {
                        return left.longValue() * right.longValue();
                    } else {
                        return left.intValue() * right.intValue();
                    }
                } else {
                    if (isWide) {
                        return left.doubleValue() * right.doubleValue();
                    } else {
                        return left.floatValue() * right.floatValue();
                    }
                }
            } else if (operator == JavaTokenType.DIV) {
                if (isInteger) {
                    if (isWide) {
                        return left.longValue() / right.longValue();
                    } else {
                        return left.intValue() / right.intValue();
                    }
                } else {
                    if (isWide) {
                        return left.doubleValue() / right.doubleValue();
                    } else {
                        return left.floatValue() / right.floatValue();
                    }
                }
            } else if (operator == JavaTokenType.PERC) {
                if (isInteger) {
                    if (isWide) {
                        return left.longValue() % right.longValue();
                    } else {
                        return left.intValue() % right.intValue();
                    }
                } else {
                    if (isWide) {
                        return left.doubleValue() % right.doubleValue();
                    } else {
                        return left.floatValue() % right.floatValue();
                    }
                }
            } else {
                return null;
            }
        }
    } else if (node instanceof PsiTypeCastExpression) {
        PsiTypeCastExpression cast = (PsiTypeCastExpression) node;
        Object operandValue = evaluate(cast.getOperand());
        if (operandValue instanceof Number) {
            Number number = (Number) operandValue;
            PsiTypeElement typeElement = cast.getCastType();
            if (typeElement != null) {
                PsiType type = typeElement.getType();
                if (PsiType.FLOAT.equals(type)) {
                    return number.floatValue();
                } else if (PsiType.DOUBLE.equals(type)) {
                    return number.doubleValue();
                } else if (PsiType.INT.equals(type)) {
                    return number.intValue();
                } else if (PsiType.LONG.equals(type)) {
                    return number.longValue();
                } else if (PsiType.SHORT.equals(type)) {
                    return number.shortValue();
                } else if (PsiType.BYTE.equals(type)) {
                    return number.byteValue();
                }
            }
        }
        return operandValue;
    } else if (node instanceof PsiReference) {
        PsiElement resolved = ((PsiReference) node).resolve();
        if (resolved instanceof PsiField) {
            PsiField field = (PsiField) resolved;
            Object value = field.computeConstantValue();
            if (value != null) {
                return value;
            }
            if (field.getInitializer() != null) {
                return evaluate(field.getInitializer());
            }
            return null;
        } else if (resolved instanceof PsiLocalVariable) {
            PsiLocalVariable variable = (PsiLocalVariable) resolved;
            PsiStatement statement = PsiTreeUtil.getParentOfType(node, PsiStatement.class, false);
            if (statement != null) {
                PsiStatement prev = PsiTreeUtil.getPrevSiblingOfType(statement, PsiStatement.class);
                String targetName = variable.getName();
                if (targetName == null) {
                    return null;
                }
                while (prev != null) {
                    if (prev instanceof PsiDeclarationStatement) {
                        for (PsiElement element : ((PsiDeclarationStatement) prev).getDeclaredElements()) {
                            if (variable.equals(element)) {
                                return evaluate(variable.getInitializer());
                            }
                        }
                    } else if (prev instanceof PsiExpressionStatement) {
                        PsiExpression expression = ((PsiExpressionStatement) prev).getExpression();
                        if (expression instanceof PsiAssignmentExpression) {
                            PsiAssignmentExpression assign = (PsiAssignmentExpression) expression;
                            PsiExpression lhs = assign.getLExpression();
                            if (lhs instanceof PsiReferenceExpression) {
                                PsiReferenceExpression reference = (PsiReferenceExpression) lhs;
                                if (targetName.equals(reference.getReferenceName()) && reference.getQualifier() == null) {
                                    return evaluate(assign.getRExpression());
                                }
                            }
                        }
                    }
                    prev = PsiTreeUtil.getPrevSiblingOfType(prev, PsiStatement.class);
                }
            }
        }
    } else if (node instanceof PsiNewExpression) {
        PsiNewExpression creation = (PsiNewExpression) node;
        PsiArrayInitializerExpression initializer = creation.getArrayInitializer();
        PsiType type = creation.getType();
        if (type instanceof PsiArrayType) {
            if (initializer != null) {
                PsiExpression[] initializers = initializer.getInitializers();
                Class<?> commonType = null;
                List<Object> values = Lists.newArrayListWithExpectedSize(initializers.length);
                int count = 0;
                for (PsiExpression expression : initializers) {
                    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;
                    }
                    count++;
                    if (count == 20) {
                        // avoid large initializers
                        break;
                    }
                }
                type = type.getDeepComponentType();
                if (type == PsiType.INT) {
                    if (!values.isEmpty()) {
                        int[] array = new int[values.size()];
                        for (int i = 0; i < values.size(); i++) {
                            Object o = values.get(i);
                            if (o instanceof Integer) {
                                array[i] = (Integer) o;
                            }
                        }
                        return array;
                    }
                    return new int[0];
                } else if (type == PsiType.BOOLEAN) {
                    if (!values.isEmpty()) {
                        boolean[] array = new boolean[values.size()];
                        for (int i = 0; i < values.size(); i++) {
                            Object o = values.get(i);
                            if (o instanceof Boolean) {
                                array[i] = (Boolean) o;
                            }
                        }
                        return array;
                    }
                    return new boolean[0];
                } else if (type == PsiType.DOUBLE) {
                    if (!values.isEmpty()) {
                        double[] array = new double[values.size()];
                        for (int i = 0; i < values.size(); i++) {
                            Object o = values.get(i);
                            if (o instanceof Double) {
                                array[i] = (Double) o;
                            }
                        }
                        return array;
                    }
                    return new double[0];
                } else if (type == PsiType.LONG) {
                    if (!values.isEmpty()) {
                        long[] array = new long[values.size()];
                        for (int i = 0; i < values.size(); i++) {
                            Object o = values.get(i);
                            if (o instanceof Long) {
                                array[i] = (Long) o;
                            }
                        }
                        return array;
                    }
                    return new long[0];
                } else if (type == PsiType.FLOAT) {
                    if (!values.isEmpty()) {
                        float[] array = new float[values.size()];
                        for (int i = 0; i < values.size(); i++) {
                            Object o = values.get(i);
                            if (o instanceof Float) {
                                array[i] = (Float) o;
                            }
                        }
                        return array;
                    }
                    return new float[0];
                } else if (type == PsiType.CHAR) {
                    if (!values.isEmpty()) {
                        char[] array = new char[values.size()];
                        for (int i = 0; i < values.size(); i++) {
                            Object o = values.get(i);
                            if (o instanceof Character) {
                                array[i] = (Character) o;
                            }
                        }
                        return array;
                    }
                    return new char[0];
                } else if (type == PsiType.BYTE) {
                    if (!values.isEmpty()) {
                        byte[] array = new byte[values.size()];
                        for (int i = 0; i < values.size(); i++) {
                            Object o = values.get(i);
                            if (o instanceof Byte) {
                                array[i] = (Byte) o;
                            }
                        }
                        return array;
                    }
                    return new byte[0];
                } else if (type == PsiType.SHORT) {
                    if (!values.isEmpty()) {
                        short[] array = new short[values.size()];
                        for (int i = 0; i < values.size(); i++) {
                            Object o = values.get(i);
                            if (o instanceof Short) {
                                array[i] = (Short) o;
                            }
                        }
                        return array;
                    }
                    return new short[0];
                } else {
                    if (!values.isEmpty()) {
                        Object o = Array.newInstance(commonType, values.size());
                        return values.toArray((Object[]) o);
                    }
                    return null;
                }
            } else {
                // something like "new byte[3]" but with no initializer.
                // Look up the size and only if small, use it. E.g. if it was byte[3]
                // we return a byte[3] array, but if it's say byte[1024*1024] we don't
                // want to do that.
                PsiExpression[] arrayDimensions = creation.getArrayDimensions();
                int size = 0;
                if (arrayDimensions.length == 1) {
                    Object fixedSize = evaluate(arrayDimensions[0]);
                    if (fixedSize instanceof Number) {
                        size = ((Number) fixedSize).intValue();
                        if (size > 30) {
                            size = 30;
                        }
                    }
                }
                type = type.getDeepComponentType();
                if (type instanceof PsiPrimitiveType) {
                    if (PsiType.BYTE.equals(type)) {
                        return new byte[size];
                    }
                    if (PsiType.BOOLEAN.equals(type)) {
                        return new boolean[size];
                    }
                    if (PsiType.INT.equals(type)) {
                        return new int[size];
                    }
                    if (PsiType.LONG.equals(type)) {
                        return new long[size];
                    }
                    if (PsiType.CHAR.equals(type)) {
                        return new char[size];
                    }
                    if (PsiType.FLOAT.equals(type)) {
                        return new float[size];
                    }
                    if (PsiType.DOUBLE.equals(type)) {
                        return new double[size];
                    }
                    if (PsiType.SHORT.equals(type)) {
                        return new short[size];
                    }
                } else if (type instanceof PsiClassType) {
                    String className = type.getCanonicalText();
                    if (TYPE_STRING.equals(className)) {
                        //noinspection SSBasedInspection
                        return new String[size];
                    }
                    if (TYPE_OBJECT.equals(className)) {
                        //noinspection SSBasedInspection
                        return new Object[size];
                    }
                }
            }
        }
    }
    return null;
}
Also used : PsiPrefixExpression(com.intellij.psi.PsiPrefixExpression) PsiExpression(com.intellij.psi.PsiExpression) PsiReferenceExpression(com.intellij.psi.PsiReferenceExpression) PsiAssignmentExpression(com.intellij.psi.PsiAssignmentExpression) PsiLiteral(com.intellij.psi.PsiLiteral) PsiLocalVariable(com.intellij.psi.PsiLocalVariable) PsiArrayInitializerExpression(com.intellij.psi.PsiArrayInitializerExpression) PsiTypeCastExpression(com.intellij.psi.PsiTypeCastExpression) PsiArrayType(com.intellij.psi.PsiArrayType) PsiParenthesizedExpression(com.intellij.psi.PsiParenthesizedExpression) List(java.util.List) ArrayList(java.util.ArrayList) PsiElement(com.intellij.psi.PsiElement) PsiType(com.intellij.psi.PsiType) PsiStatement(com.intellij.psi.PsiStatement) PsiDeclarationStatement(com.intellij.psi.PsiDeclarationStatement) PsiPrimitiveType(com.intellij.psi.PsiPrimitiveType) PsiReference(com.intellij.psi.PsiReference) PsiNewExpression(com.intellij.psi.PsiNewExpression) PsiConditionalExpression(com.intellij.psi.PsiConditionalExpression) IElementType(com.intellij.psi.tree.IElementType) PsiClassType(com.intellij.psi.PsiClassType) PsiExpressionStatement(com.intellij.psi.PsiExpressionStatement) PsiTypeElement(com.intellij.psi.PsiTypeElement) PsiField(com.intellij.psi.PsiField) PsiClass(com.intellij.psi.PsiClass) PsiBinaryExpression(com.intellij.psi.PsiBinaryExpression) Nullable(com.android.annotations.Nullable)

Example 78 with Nullable

use of com.android.annotations.Nullable in project kotlin by JetBrains.

the class ConstantEvaluator method evaluate.

/**
     * Evaluates the given node and returns the constant value it resolves to, if any
     *
     * @param node the node to compute the constant value for
     * @return the corresponding constant value - a String, an Integer, a Float, and so on
     */
@Nullable
public Object evaluate(@Nullable UElement node) {
    if (node == null) {
        return null;
    }
    if (node instanceof ULiteralExpression) {
        return ((ULiteralExpression) node).getValue();
    } else if (node instanceof UPrefixExpression) {
        UastPrefixOperator operator = ((UPrefixExpression) node).getOperator();
        Object operand = evaluate(((UPrefixExpression) node).getOperand());
        if (operand == null) {
            return null;
        }
        if (operator == UastPrefixOperator.LOGICAL_NOT) {
            if (operand instanceof Boolean) {
                return !(Boolean) operand;
            }
        } else if (operator == UastPrefixOperator.UNARY_PLUS) {
            return operand;
        } else if (operator == UastPrefixOperator.BITWISE_NOT) {
            if (operand instanceof Integer) {
                return ~(Integer) operand;
            } else if (operand instanceof Long) {
                return ~(Long) operand;
            } else if (operand instanceof Short) {
                return ~(Short) operand;
            } else if (operand instanceof Character) {
                return ~(Character) operand;
            } else if (operand instanceof Byte) {
                return ~(Byte) operand;
            }
        } else if (operator == UastPrefixOperator.UNARY_MINUS) {
            if (operand instanceof Integer) {
                return -(Integer) operand;
            } else if (operand instanceof Long) {
                return -(Long) operand;
            } else if (operand instanceof Double) {
                return -(Double) operand;
            } else if (operand instanceof Float) {
                return -(Float) operand;
            } else if (operand instanceof Short) {
                return -(Short) operand;
            } else if (operand instanceof Character) {
                return -(Character) operand;
            } else if (operand instanceof Byte) {
                return -(Byte) operand;
            }
        }
    } else if (node instanceof UIfExpression && ((UIfExpression) node).getExpressionType() != null) {
        UIfExpression expression = (UIfExpression) node;
        Object known = evaluate(expression.getCondition());
        if (known == Boolean.TRUE && expression.getThenExpression() != null) {
            return evaluate(expression.getThenExpression());
        } else if (known == Boolean.FALSE && expression.getElseExpression() != null) {
            return evaluate(expression.getElseExpression());
        }
    } else if (node instanceof UParenthesizedExpression) {
        UParenthesizedExpression parenthesizedExpression = (UParenthesizedExpression) node;
        UExpression expression = parenthesizedExpression.getExpression();
        return evaluate(expression);
    } else if (node instanceof UBinaryExpression) {
        UastBinaryOperator operator = ((UBinaryExpression) node).getOperator();
        Object operandLeft = evaluate(((UBinaryExpression) node).getLeftOperand());
        Object operandRight = evaluate(((UBinaryExpression) node).getRightOperand());
        if (operandLeft == null || operandRight == null) {
            if (mAllowUnknown) {
                if (operandLeft == null) {
                    return operandRight;
                } else {
                    return operandLeft;
                }
            }
            return null;
        }
        if (operandLeft instanceof String && operandRight instanceof String) {
            if (operator == UastBinaryOperator.PLUS) {
                return operandLeft.toString() + operandRight.toString();
            }
            return null;
        } else if (operandLeft instanceof Boolean && operandRight instanceof Boolean) {
            boolean left = (Boolean) operandLeft;
            boolean right = (Boolean) operandRight;
            if (operator == UastBinaryOperator.LOGICAL_OR) {
                return left || right;
            } else if (operator == UastBinaryOperator.LOGICAL_AND) {
                return left && right;
            } else if (operator == UastBinaryOperator.BITWISE_OR) {
                return left | right;
            } else if (operator == UastBinaryOperator.BITWISE_XOR) {
                return left ^ right;
            } else if (operator == UastBinaryOperator.BITWISE_AND) {
                return left & right;
            } else if (operator == UastBinaryOperator.IDENTITY_EQUALS || operator == UastBinaryOperator.EQUALS) {
                return left == right;
            } else if (operator == UastBinaryOperator.IDENTITY_NOT_EQUALS || operator == UastBinaryOperator.NOT_EQUALS) {
                return left != right;
            }
        } else if (operandLeft instanceof Number && operandRight instanceof Number) {
            Number left = (Number) operandLeft;
            Number right = (Number) operandRight;
            boolean isInteger = !(left instanceof Float || left instanceof Double || right instanceof Float || right instanceof Double);
            boolean isWide = isInteger ? (left instanceof Long || right instanceof Long) : (left instanceof Double || right instanceof Double);
            if (operator == UastBinaryOperator.BITWISE_OR) {
                if (isWide) {
                    return left.longValue() | right.longValue();
                } else {
                    return left.intValue() | right.intValue();
                }
            } else if (operator == UastBinaryOperator.BITWISE_XOR) {
                if (isWide) {
                    return left.longValue() ^ right.longValue();
                } else {
                    return left.intValue() ^ right.intValue();
                }
            } else if (operator == UastBinaryOperator.BITWISE_AND) {
                if (isWide) {
                    return left.longValue() & right.longValue();
                } else {
                    return left.intValue() & right.intValue();
                }
            } else if (operator == UastBinaryOperator.EQUALS || operator == UastBinaryOperator.IDENTITY_EQUALS) {
                if (isInteger) {
                    return left.longValue() == right.longValue();
                } else {
                    return left.doubleValue() == right.doubleValue();
                }
            } else if (operator == UastBinaryOperator.NOT_EQUALS || operator == UastBinaryOperator.IDENTITY_NOT_EQUALS) {
                if (isInteger) {
                    return left.longValue() != right.longValue();
                } else {
                    return left.doubleValue() != right.doubleValue();
                }
            } else if (operator == UastBinaryOperator.GREATER) {
                if (isInteger) {
                    return left.longValue() > right.longValue();
                } else {
                    return left.doubleValue() > right.doubleValue();
                }
            } else if (operator == UastBinaryOperator.GREATER_OR_EQUALS) {
                if (isInteger) {
                    return left.longValue() >= right.longValue();
                } else {
                    return left.doubleValue() >= right.doubleValue();
                }
            } else if (operator == UastBinaryOperator.LESS) {
                if (isInteger) {
                    return left.longValue() < right.longValue();
                } else {
                    return left.doubleValue() < right.doubleValue();
                }
            } else if (operator == UastBinaryOperator.LESS_OR_EQUALS) {
                if (isInteger) {
                    return left.longValue() <= right.longValue();
                } else {
                    return left.doubleValue() <= right.doubleValue();
                }
            } else if (operator == UastBinaryOperator.SHIFT_LEFT) {
                if (isWide) {
                    return left.longValue() << right.intValue();
                } else {
                    return left.intValue() << right.intValue();
                }
            } else if (operator == UastBinaryOperator.SHIFT_RIGHT) {
                if (isWide) {
                    return left.longValue() >> right.intValue();
                } else {
                    return left.intValue() >> right.intValue();
                }
            } else if (operator == UastBinaryOperator.UNSIGNED_SHIFT_RIGHT) {
                if (isWide) {
                    return left.longValue() >>> right.intValue();
                } else {
                    return left.intValue() >>> right.intValue();
                }
            } else if (operator == UastBinaryOperator.PLUS) {
                if (isInteger) {
                    if (isWide) {
                        return left.longValue() + right.longValue();
                    } else {
                        return left.intValue() + right.intValue();
                    }
                } else {
                    if (isWide) {
                        return left.doubleValue() + right.doubleValue();
                    } else {
                        return left.floatValue() + right.floatValue();
                    }
                }
            } else if (operator == UastBinaryOperator.MINUS) {
                if (isInteger) {
                    if (isWide) {
                        return left.longValue() - right.longValue();
                    } else {
                        return left.intValue() - right.intValue();
                    }
                } else {
                    if (isWide) {
                        return left.doubleValue() - right.doubleValue();
                    } else {
                        return left.floatValue() - right.floatValue();
                    }
                }
            } else if (operator == UastBinaryOperator.MULTIPLY) {
                if (isInteger) {
                    if (isWide) {
                        return left.longValue() * right.longValue();
                    } else {
                        return left.intValue() * right.intValue();
                    }
                } else {
                    if (isWide) {
                        return left.doubleValue() * right.doubleValue();
                    } else {
                        return left.floatValue() * right.floatValue();
                    }
                }
            } else if (operator == UastBinaryOperator.DIV) {
                if (isInteger) {
                    if (isWide) {
                        return left.longValue() / right.longValue();
                    } else {
                        return left.intValue() / right.intValue();
                    }
                } else {
                    if (isWide) {
                        return left.doubleValue() / right.doubleValue();
                    } else {
                        return left.floatValue() / right.floatValue();
                    }
                }
            } else if (operator == UastBinaryOperator.MOD) {
                if (isInteger) {
                    if (isWide) {
                        return left.longValue() % right.longValue();
                    } else {
                        return left.intValue() % right.intValue();
                    }
                } else {
                    if (isWide) {
                        return left.doubleValue() % right.doubleValue();
                    } else {
                        return left.floatValue() % right.floatValue();
                    }
                }
            } else {
                return null;
            }
        }
    } else if (node instanceof UBinaryExpressionWithType && ((UBinaryExpressionWithType) node).getOperationKind() == TYPE_CAST) {
        UBinaryExpressionWithType cast = (UBinaryExpressionWithType) node;
        Object operandValue = evaluate(cast.getOperand());
        if (operandValue instanceof Number) {
            Number number = (Number) operandValue;
            PsiType type = cast.getType();
            if (PsiType.FLOAT.equals(type)) {
                return number.floatValue();
            } else if (PsiType.DOUBLE.equals(type)) {
                return number.doubleValue();
            } else if (PsiType.INT.equals(type)) {
                return number.intValue();
            } else if (PsiType.LONG.equals(type)) {
                return number.longValue();
            } else if (PsiType.SHORT.equals(type)) {
                return number.shortValue();
            } else if (PsiType.BYTE.equals(type)) {
                return number.byteValue();
            }
        }
        return operandValue;
    } else if (node instanceof UReferenceExpression) {
        PsiElement resolved = ((UReferenceExpression) node).resolve();
        if (resolved instanceof PsiVariable) {
            PsiVariable variable = (PsiVariable) resolved;
            Object value = UastLintUtils.findLastValue(variable, node, mContext, this);
            if (value != null) {
                return value;
            }
            if (variable.getInitializer() != null) {
                return evaluate(variable.getInitializer());
            }
            return null;
        }
    } else if (UastExpressionUtils.isNewArrayWithDimensions((UExpression) node)) {
        UCallExpression call = (UCallExpression) node;
        PsiType arrayType = call.getExpressionType();
        if (arrayType instanceof PsiArrayType) {
            PsiType componentType = ((PsiArrayType) arrayType).getComponentType();
            // Single-dimension array
            if (!(componentType instanceof PsiArrayType) && call.getValueArgumentCount() == 1) {
                Object lengthObj = evaluate(call.getValueArguments().get(0));
                if (lengthObj instanceof Number) {
                    int length = ((Number) lengthObj).intValue();
                    if (length > 30) {
                        length = 30;
                    }
                    if (componentType == PsiType.BOOLEAN) {
                        return new boolean[length];
                    } else if (isObjectType(componentType)) {
                        return new Object[length];
                    } else if (componentType == PsiType.CHAR) {
                        return new char[length];
                    } else if (componentType == PsiType.BYTE) {
                        return new byte[length];
                    } else if (componentType == PsiType.DOUBLE) {
                        return new double[length];
                    } else if (componentType == PsiType.FLOAT) {
                        return new float[length];
                    } else if (componentType == PsiType.INT) {
                        return new int[length];
                    } else if (componentType == PsiType.SHORT) {
                        return new short[length];
                    } else if (componentType == PsiType.LONG) {
                        return new long[length];
                    } else if (isStringType(componentType)) {
                        return new String[length];
                    }
                }
            }
        }
    } else if (UastExpressionUtils.isNewArrayWithInitializer(node)) {
        UCallExpression call = (UCallExpression) node;
        PsiType arrayType = call.getExpressionType();
        if (arrayType instanceof PsiArrayType) {
            PsiType componentType = ((PsiArrayType) arrayType).getComponentType();
            // Single-dimension array
            if (!(componentType instanceof PsiArrayType)) {
                int length = call.getValueArgumentCount();
                List<Object> evaluatedArgs = new ArrayList<Object>(length);
                for (UExpression arg : call.getValueArguments()) {
                    Object evaluatedArg = evaluate(arg);
                    if (!mAllowUnknown && evaluatedArg == null) {
                        // Inconclusive
                        return null;
                    }
                    evaluatedArgs.add(evaluatedArg);
                }
                if (componentType == PsiType.BOOLEAN) {
                    boolean[] arr = new boolean[length];
                    for (int i = 0; i < length; ++i) {
                        Object o = evaluatedArgs.get(i);
                        if (o instanceof Boolean) {
                            arr[i] = (Boolean) o;
                        }
                    }
                    return arr;
                } else if (isObjectType(componentType)) {
                    Object[] arr = new Object[length];
                    for (int i = 0; i < length; ++i) {
                        arr[i] = evaluatedArgs.get(i);
                    }
                    return arr;
                } else if (componentType.equals(PsiType.CHAR)) {
                    char[] arr = new char[length];
                    for (int i = 0; i < length; ++i) {
                        Object o = evaluatedArgs.get(i);
                        if (o instanceof Character) {
                            arr[i] = (Character) o;
                        }
                    }
                    return arr;
                } else if (componentType.equals(PsiType.BYTE)) {
                    byte[] arr = new byte[length];
                    for (int i = 0; i < length; ++i) {
                        Object o = evaluatedArgs.get(i);
                        if (o instanceof Byte) {
                            arr[i] = (Byte) o;
                        }
                    }
                    return arr;
                } else if (componentType.equals(PsiType.DOUBLE)) {
                    double[] arr = new double[length];
                    for (int i = 0; i < length; ++i) {
                        Object o = evaluatedArgs.get(i);
                        if (o instanceof Double) {
                            arr[i] = (Double) o;
                        }
                    }
                    return arr;
                } else if (componentType.equals(PsiType.FLOAT)) {
                    float[] arr = new float[length];
                    for (int i = 0; i < length; ++i) {
                        Object o = evaluatedArgs.get(i);
                        if (o instanceof Float) {
                            arr[i] = (Float) o;
                        }
                    }
                    return arr;
                } else if (componentType.equals(PsiType.INT)) {
                    int[] arr = new int[length];
                    for (int i = 0; i < length; ++i) {
                        Object o = evaluatedArgs.get(i);
                        if (o instanceof Integer) {
                            arr[i] = (Integer) o;
                        }
                    }
                    return arr;
                } else if (componentType.equals(PsiType.SHORT)) {
                    short[] arr = new short[length];
                    for (int i = 0; i < length; ++i) {
                        Object o = evaluatedArgs.get(i);
                        if (o instanceof Short) {
                            arr[i] = (Short) o;
                        }
                    }
                    return arr;
                } else if (componentType.equals(PsiType.LONG)) {
                    long[] arr = new long[length];
                    for (int i = 0; i < length; ++i) {
                        Object o = evaluatedArgs.get(i);
                        if (o instanceof Long) {
                            arr[i] = (Long) o;
                        }
                    }
                    return arr;
                } else if (isStringType(componentType)) {
                    String[] arr = new String[length];
                    for (int i = 0; i < length; ++i) {
                        Object o = evaluatedArgs.get(i);
                        if (o instanceof String) {
                            arr[i] = (String) o;
                        }
                    }
                    return arr;
                }
            }
        }
    }
    if (node instanceof UExpression) {
        Object evaluated = ((UExpression) node).evaluate();
        if (evaluated != null) {
            return evaluated;
        }
    }
    return null;
}
Also used : ArrayList(java.util.ArrayList) PsiArrayType(com.intellij.psi.PsiArrayType) PsiElement(com.intellij.psi.PsiElement) PsiType(com.intellij.psi.PsiType) PsiVariable(com.intellij.psi.PsiVariable) UReferenceExpression(org.jetbrains.uast.UReferenceExpression) Nullable(com.android.annotations.Nullable)

Example 79 with Nullable

use of com.android.annotations.Nullable in project kotlin by JetBrains.

the class LintDriver method getVisitor.

@Nullable
private ResourceVisitor getVisitor(@NonNull ResourceFolderType type, @NonNull List<ResourceXmlDetector> checks, @Nullable List<Detector> binaryChecks) {
    if (type != mCurrentFolderType) {
        mCurrentFolderType = type;
        // Determine which XML resource detectors apply to the given folder type
        List<ResourceXmlDetector> applicableXmlChecks = new ArrayList<ResourceXmlDetector>(checks.size());
        for (ResourceXmlDetector check : checks) {
            if (check.appliesTo(type)) {
                applicableXmlChecks.add(check);
            }
        }
        List<Detector> applicableBinaryChecks = null;
        if (binaryChecks != null) {
            applicableBinaryChecks = new ArrayList<Detector>(binaryChecks.size());
            for (Detector check : binaryChecks) {
                if (check.appliesTo(type)) {
                    applicableBinaryChecks.add(check);
                }
            }
        }
        // If the list of detectors hasn't changed, then just use the current visitor!
        if (mCurrentXmlDetectors != null && mCurrentXmlDetectors.equals(applicableXmlChecks) && Objects.equal(mCurrentBinaryDetectors, applicableBinaryChecks)) {
            return mCurrentVisitor;
        }
        mCurrentXmlDetectors = applicableXmlChecks;
        mCurrentBinaryDetectors = applicableBinaryChecks;
        if (applicableXmlChecks.isEmpty() && (applicableBinaryChecks == null || applicableBinaryChecks.isEmpty())) {
            mCurrentVisitor = null;
            return null;
        }
        XmlParser parser = mClient.getXmlParser();
        if (parser != null) {
            mCurrentVisitor = new ResourceVisitor(parser, applicableXmlChecks, applicableBinaryChecks);
        } else {
            mCurrentVisitor = null;
        }
    }
    return mCurrentVisitor;
}
Also used : ResourceXmlDetector(com.android.tools.klint.detector.api.ResourceXmlDetector) Detector(com.android.tools.klint.detector.api.Detector) ArrayList(java.util.ArrayList) ResourceXmlDetector(com.android.tools.klint.detector.api.ResourceXmlDetector) Nullable(com.android.annotations.Nullable)

Example 80 with Nullable

use of com.android.annotations.Nullable in project kotlin by JetBrains.

the class UastLintUtils method toAndroidReferenceViaResolve.

@Nullable
public static AndroidReference toAndroidReferenceViaResolve(UElement element) {
    if (element instanceof UQualifiedReferenceExpression && element instanceof JavaAbstractUExpression) {
        AndroidReference ref = toAndroidReference((UQualifiedReferenceExpression) element);
        if (ref != null) {
            return ref;
        }
    }
    PsiElement declaration;
    if (element instanceof UVariable) {
        declaration = ((UVariable) element).getPsi();
    } else if (element instanceof UResolvable) {
        declaration = ((UResolvable) element).resolve();
    } else {
        return null;
    }
    if (declaration == null && element instanceof USimpleNameReferenceExpression && element instanceof JavaAbstractUExpression) {
        // R class can't be resolved in tests so we need to use heuristics to calc the reference 
        UExpression maybeQualified = UastUtils.getQualifiedParentOrThis((UExpression) element);
        if (maybeQualified instanceof UQualifiedReferenceExpression) {
            AndroidReference ref = toAndroidReference((UQualifiedReferenceExpression) maybeQualified);
            if (ref != null) {
                return ref;
            }
        }
    }
    if (!(declaration instanceof PsiVariable)) {
        return null;
    }
    PsiVariable variable = (PsiVariable) declaration;
    if (!(variable instanceof PsiField) || variable.getType() != PsiType.INT || !variable.hasModifierProperty(PsiModifier.STATIC) || !variable.hasModifierProperty(PsiModifier.FINAL)) {
        return null;
    }
    PsiClass resTypeClass = ((PsiField) variable).getContainingClass();
    if (resTypeClass == null || !resTypeClass.hasModifierProperty(PsiModifier.STATIC)) {
        return null;
    }
    PsiClass rClass = resTypeClass.getContainingClass();
    if (rClass == null || rClass.getContainingClass() != null || !"R".equals(rClass.getName())) {
        return null;
    }
    String packageName = ((PsiJavaFile) rClass.getContainingFile()).getPackageName();
    if (packageName.isEmpty()) {
        return null;
    }
    String resourceTypeName = resTypeClass.getName();
    ResourceType resourceType = null;
    for (ResourceType value : ResourceType.values()) {
        if (value.getName().equals(resourceTypeName)) {
            resourceType = value;
            break;
        }
    }
    if (resourceType == null) {
        return null;
    }
    String resourceName = variable.getName();
    UExpression node;
    if (element instanceof UExpression) {
        node = (UExpression) element;
    } else if (element instanceof UVariable) {
        node = new JavaUDeclarationsExpression(null, Collections.singletonList(((UVariable) element)));
    } else {
        throw new IllegalArgumentException("element must be an expression or an UVariable");
    }
    return new AndroidReference(node, packageName, resourceType, resourceName);
}
Also used : ResourceType(com.android.resources.ResourceType) JavaAbstractUExpression(org.jetbrains.uast.java.JavaAbstractUExpression) JavaAbstractUExpression(org.jetbrains.uast.java.JavaAbstractUExpression) JavaUDeclarationsExpression(org.jetbrains.uast.java.JavaUDeclarationsExpression) Nullable(com.android.annotations.Nullable)

Aggregations

Nullable (com.android.annotations.Nullable)83 File (java.io.File)21 IOException (java.io.IOException)9 ResourceType (com.android.resources.ResourceType)8 PsiClass (com.intellij.psi.PsiClass)7 PsiElement (com.intellij.psi.PsiElement)7 PsiReferenceExpression (com.intellij.psi.PsiReferenceExpression)7 ResourceUrl (com.android.ide.common.resources.ResourceUrl)6 PsiAssignmentExpression (com.intellij.psi.PsiAssignmentExpression)6 PsiDeclarationStatement (com.intellij.psi.PsiDeclarationStatement)6 PsiExpression (com.intellij.psi.PsiExpression)6 PsiExpressionStatement (com.intellij.psi.PsiExpressionStatement)6 PsiMethod (com.intellij.psi.PsiMethod)6 PsiStatement (com.intellij.psi.PsiStatement)6 ArrayList (java.util.ArrayList)6 PsiField (com.intellij.psi.PsiField)5 PsiFile (com.intellij.psi.PsiFile)4 Node (lombok.ast.Node)4 UReferenceExpression (org.jetbrains.uast.UReferenceExpression)4 AbstractResourceRepository (com.android.ide.common.res2.AbstractResourceRepository)3