@NotNull
  private ReturnValue getExpressionValue(@Nullable LighterASTNode expr) {
    expr = skipParenthesesCastsDown(tree, expr);
    if (expr == null) {
      return ReturnValue.UNKNOWN;
    }
    IElementType type = expr.getTokenType();
    if (isNullLiteralExpression(tree, expr)) {
      return ReturnValue.NULLABLE;
    }
    if (type == LAMBDA_EXPRESSION || type == NEW_EXPRESSION || type == METHOD_REF_EXPRESSION ||
        type == LITERAL_EXPRESSION || type == BINARY_EXPRESSION || type == POLYADIC_EXPRESSION) {
      return ReturnValue.NOT_NULL;
    }
    if (type == METHOD_CALL_EXPRESSION) {
      String calledMethod = getNameIdentifierText(tree, tree.getChildren(expr).get(0));
      if (calledMethod != null) {
        return ReturnValue.delegate(calledMethod, ExpressionRange.create(expr, myBody.getStartOffset()));
      }
    }
    if (type == SWITCH_EXPRESSION) {
      return findValueInSwitchExpression(expr);
    }
    else if (type == CONDITIONAL_EXPRESSION) {
      List<LighterASTNode> expressionChildren = getExpressionChildren(tree, expr);
      if (expressionChildren.size() == 3) {
        return ReturnValue.merge(getExpressionValue(expressionChildren.get(1)), // then-branch
                                 getExpressionValue(expressionChildren.get(2))); // else-branch
      }
    }
    else if (type == REFERENCE_EXPRESSION) {
      LighterASTNode target = new FileLocalResolver(tree).resolveLocally(expr).getTarget();
      if (target != null &&
          (target.getTokenType() == LOCAL_VARIABLE || target.getTokenType() == PARAMETER)) {
        return findVariableValue(expr, target);
      }
    }
    return ReturnValue.UNKNOWN;
  }
@NotNull
  private ReturnValue getExpressionValue(@Nullable LighterASTNode expr)