private static boolean isGoodExpression(
      PsiExpression expression,
      @NotNull AllowedValues allowedValues,
      @NotNull PsiElement scope,
      @NotNull PsiManager manager) {
    expression = PsiUtil.deparenthesizeExpression(expression);
    if (expression == null) return true;
    if (expression instanceof PsiConditionalExpression) {
      PsiExpression thenExpression = ((PsiConditionalExpression) expression).getThenExpression();
      boolean thenAllowed =
          thenExpression == null || isAllowed(scope, thenExpression, allowedValues, manager);
      if (!thenAllowed) return false;
      PsiExpression elseExpression = ((PsiConditionalExpression) expression).getElseExpression();
      return elseExpression == null || isAllowed(scope, elseExpression, allowedValues, manager);
    }

    if (isOneOf(expression, allowedValues, manager)) return true;

    if (allowedValues.canBeOred) {
      PsiExpression zero = getLiteralExpression(expression, manager, "0");
      if (same(expression, zero, manager)) return true;
      PsiExpression mOne = getLiteralExpression(expression, manager, "-1");
      if (same(expression, mOne, manager)) return true;
      if (expression instanceof PsiPolyadicExpression) {
        IElementType tokenType = ((PsiPolyadicExpression) expression).getOperationTokenType();
        if (JavaTokenType.OR.equals(tokenType) || JavaTokenType.AND.equals(tokenType)) {
          for (PsiExpression operand : ((PsiPolyadicExpression) expression).getOperands()) {
            if (!isAllowed(scope, operand, allowedValues, manager)) return false;
          }
          return true;
        }
      }
      if (expression instanceof PsiPrefixExpression
          && JavaTokenType.TILDE.equals(
              ((PsiPrefixExpression) expression).getOperationTokenType())) {
        PsiExpression operand = ((PsiPrefixExpression) expression).getOperand();
        return operand == null || isAllowed(scope, operand, allowedValues, manager);
      }
    }

    PsiElement resolved = null;
    if (expression instanceof PsiReference) {
      resolved = ((PsiReference) expression).resolve();
    } else if (expression instanceof PsiCallExpression) {
      resolved = ((PsiCallExpression) expression).resolveMethod();
    }

    AllowedValues allowedForRef;
    if (resolved instanceof PsiModifierListOwner
        && (allowedForRef =
                getAllowedValues(
                    (PsiModifierListOwner) resolved,
                    getType((PsiModifierListOwner) resolved),
                    null))
            != null
        && allowedForRef.isSubsetOf(allowedValues, manager)) return true;

    return PsiType.NULL.equals(expression.getType());
  }
  private static void checkCall(
      @NotNull PsiCallExpression methodCall, @NotNull ProblemsHolder holder) {
    PsiMethod method = methodCall.resolveMethod();
    if (method == null) return;
    PsiParameter[] parameters = method.getParameterList().getParameters();
    PsiExpression[] arguments = methodCall.getArgumentList().getExpressions();
    for (int i = 0; i < parameters.length; i++) {
      PsiParameter parameter = parameters[i];
      AllowedValues values = getAllowedValues(parameter, parameter.getType(), null);
      if (values == null) continue;
      if (i >= arguments.length) break;
      PsiExpression argument = arguments[i];
      argument = PsiUtil.deparenthesizeExpression(argument);
      if (argument == null) continue;

      checkMagicParameterArgument(parameter, argument, values, holder);
    }
  }