Search in sources :

Example 11 with PsiArrayType

use of com.intellij.psi.PsiArrayType 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 12 with PsiArrayType

use of com.intellij.psi.PsiArrayType in project google-cloud-intellij by GoogleCloudPlatform.

the class ResourceParameterInspection method buildVisitor.

@NotNull
@Override
public PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder holder, boolean isOnTheFly) {
    return new EndpointPsiElementVisitor() {

        private int resourceParameterCount = 0;

        @Override
        public void visitMethod(PsiMethod method) {
            if (!EndpointUtilities.isEndpointClass(method)) {
                return;
            }
            if (method.isConstructor()) {
                return;
            }
            // Check if method is public or non-static
            if (!EndpointUtilities.isApiMethod(method)) {
                return;
            }
            Project project;
            try {
                project = method.getContainingFile().getProject();
                if (project == null) {
                    return;
                }
            } catch (PsiInvalidElementAccessException ex) {
                LOG.error("Error getting project with parameter " + method.getText(), ex);
                return;
            }
            resourceParameterCount = 0;
            for (PsiParameter param : method.getParameterList().getParameters()) {
                validateMethodParameters(param, project);
            }
            // Check that there is no more than one resource (entity) parameter for this method.
            if (resourceParameterCount > 1) {
                holder.registerProblem(method, "Multiple entity parameters. There can only be a single entity parameter per method.", LocalQuickFix.EMPTY_ARRAY);
            }
        }

        private void validateMethodParameters(PsiParameter psiParameter, Project project) {
            // Check if parameter is of entity (resource) type which is not of parameter type or
            // injected type.
            PsiType type = psiParameter.getType();
            if (!isEntityParameter(type, project)) {
                return;
            }
            // Update count of resource (entity) parameters for this method
            resourceParameterCount++;
            // Check that parameter is not a collection or an array
            if (type instanceof PsiArrayType || isCollectionType(type, project)) {
                holder.registerProblem(psiParameter, "Illegal parameter type (\'" + psiParameter.getType().getPresentableText() + "\'). Arrays or collections of entity types are not allowed.", LocalQuickFix.EMPTY_ARRAY);
            }
            // Check that parameter does not have an @Named annotation
            PsiModifierList modifierList = psiParameter.getModifierList();
            PsiAnnotation annotation = modifierList.findAnnotation("javax.inject.Named");
            if (annotation == null) {
                annotation = modifierList.findAnnotation(GctConstants.APP_ENGINE_ANNOTATION_NAMED);
                if (annotation == null) {
                    return;
                }
            }
            holder.registerProblem(psiParameter, "Bad parameter name. Parameter is entity (resource)" + " type and should not be named.", LocalQuickFix.EMPTY_ARRAY);
        }
    };
}
Also used : PsiInvalidElementAccessException(com.intellij.psi.PsiInvalidElementAccessException) Project(com.intellij.openapi.project.Project) PsiParameter(com.intellij.psi.PsiParameter) PsiMethod(com.intellij.psi.PsiMethod) PsiAnnotation(com.intellij.psi.PsiAnnotation) PsiArrayType(com.intellij.psi.PsiArrayType) PsiType(com.intellij.psi.PsiType) PsiModifierList(com.intellij.psi.PsiModifierList) NotNull(org.jetbrains.annotations.NotNull)

Aggregations

PsiArrayType (com.intellij.psi.PsiArrayType)12 PsiType (com.intellij.psi.PsiType)10 PsiClassType (com.intellij.psi.PsiClassType)4 PsiElement (com.intellij.psi.PsiElement)3 PsiExpression (com.intellij.psi.PsiExpression)3 Nullable (com.android.annotations.Nullable)2 LookupElement (com.intellij.codeInsight.lookup.LookupElement)2 PsiTypeLookupItem (com.intellij.codeInsight.lookup.PsiTypeLookupItem)2 PsiAssignmentExpression (com.intellij.psi.PsiAssignmentExpression)2 PsiDeclarationStatement (com.intellij.psi.PsiDeclarationStatement)2 PsiExpressionStatement (com.intellij.psi.PsiExpressionStatement)2 PsiField (com.intellij.psi.PsiField)2 PsiLocalVariable (com.intellij.psi.PsiLocalVariable)2 PsiNewExpression (com.intellij.psi.PsiNewExpression)2 PsiParenthesizedExpression (com.intellij.psi.PsiParenthesizedExpression)2 PsiPrimitiveType (com.intellij.psi.PsiPrimitiveType)2 PsiReference (com.intellij.psi.PsiReference)2 PsiReferenceExpression (com.intellij.psi.PsiReferenceExpression)2 PsiStatement (com.intellij.psi.PsiStatement)2 PsiTypeCastExpression (com.intellij.psi.PsiTypeCastExpression)2