//===-- CommandObjectDWIMPrint.cpp ------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "CommandObjectDWIMPrint.h"

#include "lldb/DataFormatters/DumpValueObjectOptions.h"
#include "lldb/Expression/ExpressionVariable.h"
#include "lldb/Expression/UserExpression.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandObject.h"
#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Interpreter/OptionGroupFormat.h"
#include "lldb/Interpreter/OptionGroupValueObjectDisplay.h"
#include "lldb/Target/StackFrame.h"
#include "lldb/Utility/ConstString.h"
#include "lldb/ValueObject/ValueObject.h"
#include "lldb/lldb-defines.h"
#include "lldb/lldb-enumerations.h"
#include "lldb/lldb-forward.h"
#include "llvm/ADT/StringRef.h"

#include <regex>

using namespace llvm;
using namespace lldb;
using namespace lldb_private;

CommandObjectDWIMPrint::CommandObjectDWIMPrint(CommandInterpreter &interpreter)
    : CommandObjectRaw(interpreter, "dwim-print",
                       "Print a variable or expression.",
                       "dwim-print [<variable-name> | <expression>]",
                       eCommandProcessMustBePaused | eCommandTryTargetAPILock |
                           eCommandAllowsDummyTarget) {

  AddSimpleArgumentList(eArgTypeVarName);

  m_option_group.Append(&m_format_options,
                        OptionGroupFormat::OPTION_GROUP_FORMAT |
                            OptionGroupFormat::OPTION_GROUP_GDB_FMT,
                        LLDB_OPT_SET_1);
  StringRef exclude_expr_options[] = {"debug", "top-level"};
  m_option_group.Append(&m_expr_options, exclude_expr_options);
  m_option_group.Append(&m_varobj_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
  m_option_group.Finalize();
}

Options *CommandObjectDWIMPrint::GetOptions() { return &m_option_group; }

void CommandObjectDWIMPrint::DoExecute(StringRef command,
                                       CommandReturnObject &result) {
  m_option_group.NotifyOptionParsingStarting(&m_exe_ctx);
  OptionsWithRaw args{command};
  StringRef expr = args.GetRawPart();

  if (expr.empty()) {
    result.AppendErrorWithFormatv("'{0}' takes a variable or expression",
                                  m_cmd_name);
    return;
  }

  if (args.HasArgs()) {
    if (!ParseOptionsAndNotify(args.GetArgs(), result, m_option_group,
                               m_exe_ctx))
      return;
  }

  // If the user has not specified, default to disabling persistent results.
  if (m_expr_options.suppress_persistent_result == eLazyBoolCalculate)
    m_expr_options.suppress_persistent_result = eLazyBoolYes;
  bool suppress_result = m_expr_options.ShouldSuppressResult(m_varobj_options);

  auto verbosity = GetDebugger().GetDWIMPrintVerbosity();

  Target &target = m_exe_ctx.GetTargetRef();

  EvaluateExpressionOptions eval_options =
      m_expr_options.GetEvaluateExpressionOptions(target, m_varobj_options);
  // This command manually removes the result variable, make sure expression
  // evaluation doesn't do it first.
  eval_options.SetSuppressPersistentResult(false);

  DumpValueObjectOptions dump_options = m_varobj_options.GetAsDumpOptions(
      m_expr_options.m_verbosity, m_format_options.GetFormat());
  dump_options.SetHideRootName(suppress_result)
      .SetExpandPointerTypeFlags(lldb::eTypeIsObjC);

  bool is_po = m_varobj_options.use_object_desc;

  StackFrame *frame = m_exe_ctx.GetFramePtr();

  // Either the language was explicitly specified, or we check the frame.
  SourceLanguage language{m_expr_options.language};
  if (!language && frame)
    language = frame->GuessLanguage();

  // Add a hint if object description was requested, but no description
  // function was implemented.
  auto maybe_add_hint = [&](llvm::StringRef output) {
    static bool note_shown = false;
    if (note_shown)
      return;

    // Identify the default output of object description for Swift and
    // Objective-C
    // "<Name: 0x...>. The regex is:
    // - Start with "<".
    // - Capture 1 or more non-whitespace characters (the class name).
    // - Followed by ": 0x".
    // - Followed by 5 or more hex digits.
    // - Followed by ">".
    // - End with zero or more whitespace characters.
    static const std::regex swift_class_regex(
        "^<(\\S+): 0x[[:xdigit:]]{5,}>\\s*$");

    std::cmatch match;
    if (GetDebugger().GetShowDontUsePoHint() && !target.IsDummyTarget() &&
        (language.AsLanguageType() == lldb::eLanguageTypeSwift ||
         language.IsObjC()) &&
        std::regex_match(output.data(), match, swift_class_regex)) {

      result.AppendNoteWithFormatv(
          "{0} has no custom object description, use \"p\" to see its children",
          match[1].str());
      note_shown = true;
    }
  };

  // Dump `valobj` according to whether `po` was requested or not.
  auto dump_val_object = [&](ValueObject &valobj) {
    if (is_po) {
      StreamString temp_result_stream;
      if (llvm::Error error = valobj.Dump(temp_result_stream, dump_options)) {
        result.AppendError(toString(std::move(error)));
        return;
      }
      llvm::StringRef output = temp_result_stream.GetString();
      maybe_add_hint(output);
      result.GetOutputStream() << output;
    } else {
      llvm::Error error =
        valobj.Dump(result.GetOutputStream(), dump_options);
      if (error) {
        result.AppendError(toString(std::move(error)));
        return;
      }
    }
    m_interpreter.PrintWarningsIfNecessary(result.GetOutputStream(),
                                           m_cmd_name);
    result.SetStatus(eReturnStatusSuccessFinishResult);
  };

  // First, try `expr` as a _limited_ frame variable expression path: only the
  // dot operator (`.`) is permitted for this case.
  //
  // This is limited to support only unambiguous expression paths. Of note,
  // expression paths are not attempted if the expression contain either the
  // arrow operator (`->`) or the subscript operator (`[]`). This is because
  // both operators can be overloaded in C++, and could result in ambiguity in
  // how the expression is handled. Additionally, `*` and `&` are not supported.
  const bool try_variable_path =
      expr.find_first_of("*&->[]") == StringRef::npos;
  if (frame && try_variable_path) {
    VariableSP var_sp;
    Status status;
    auto valobj_sp = frame->GetValueForVariableExpressionPath(
        expr, eval_options.GetUseDynamic(),
        StackFrame::eExpressionPathOptionsAllowDirectIVarAccess |
            StackFrame::eExpressionPathOptionsDisallowGlobals,
        var_sp, status, lldb::eDILModeSimple);
    if (valobj_sp && status.Success() && valobj_sp->GetError().Success()) {
      if (!suppress_result) {
        if (auto persisted_valobj = valobj_sp->Persist())
          valobj_sp = persisted_valobj;
      }

      if (verbosity == eDWIMPrintVerbosityFull) {
        StringRef flags;
        if (args.HasArgs())
          flags = args.GetArgString();
        result.AppendNoteWithFormatv("ran `frame variable {0}{1}`", flags,
                                     expr);
      }

      dump_val_object(*valobj_sp);
      return;
    }
  }

  // Second, try `expr` as a persistent variable.
  if (expr.starts_with("$"))
    if (auto *state = target.GetPersistentExpressionStateForLanguage(
            language.AsLanguageType()))
      if (auto var_sp = state->GetVariable(expr))
        if (auto valobj_sp = var_sp->GetValueObject()) {
          dump_val_object(*valobj_sp);
          return;
        }

  // Third, and lastly, try `expr` as a source expression to evaluate.
  {
    auto *exe_scope = m_exe_ctx.GetBestExecutionContextScope();
    ValueObjectSP valobj_sp;
    std::string fixed_expression;

    ExpressionResults expr_result = target.EvaluateExpression(
        expr, exe_scope, valobj_sp, eval_options, &fixed_expression);

    if (valobj_sp)
      result.GetValueObjectList().Append(valobj_sp);

    // Record the position of the expression in the command.
    std::optional<uint16_t> indent;
    if (fixed_expression.empty()) {
      size_t pos = m_original_command.rfind(expr);
      if (pos != llvm::StringRef::npos)
        indent = pos;
    }
    // Previously the indent was set up for diagnosing command line
    // parsing errors. Now point it to the expression.
    result.SetDiagnosticIndent(indent);

    // Only mention Fix-Its if the expression evaluator applied them.
    // Compiler errors refer to the final expression after applying Fix-It(s).
    if (!fixed_expression.empty() && target.GetEnableNotifyAboutFixIts()) {
      Stream &error_stream = result.GetErrorStream();
      error_stream << "  Evaluated this expression after applying Fix-It(s):\n";
      error_stream << "    " << fixed_expression << "\n";
    }

    // If the expression failed, return an error.
    if (expr_result != eExpressionCompleted) {
      if (valobj_sp)
        result.SetError(valobj_sp->GetError().Clone());
      else
        result.AppendErrorWithFormatv(
            "unknown error evaluating expression `{0}`", expr);
      return;
    }

    if (verbosity != eDWIMPrintVerbosityNone) {
      StringRef flags;
      if (args.HasArgs())
        flags = args.GetArgStringWithDelimiter();
      result.AppendNoteWithFormatv("ran `expression {0}{1}`", flags, expr);
    }

    if (valobj_sp->GetError().GetError() != UserExpression::kNoResult)
      dump_val_object(*valobj_sp);
    else
      result.SetStatus(eReturnStatusSuccessFinishNoResult);

    if (suppress_result)
      if (auto result_var_sp =
              target.GetPersistentVariable(valobj_sp->GetName())) {
        auto language = valobj_sp->GetPreferredDisplayLanguage();
        if (auto *persistent_state =
                target.GetPersistentExpressionStateForLanguage(language))
          persistent_state->RemovePersistentVariable(result_var_sp);
      }
  }
}
