//===-- OptionGroupValueObjectDisplay.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 "lldb/Interpreter/OptionGroupValueObjectDisplay.h"

#include "lldb/DataFormatters/ValueObjectPrinter.h"
#include "lldb/Host/OptionParser.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/OptionArgParser.h"
#include "lldb/Target/Target.h"

#include "llvm/ADT/ArrayRef.h"

using namespace lldb;
using namespace lldb_private;

OptionGroupValueObjectDisplay::OptionGroupValueObjectDisplay() {}

OptionGroupValueObjectDisplay::~OptionGroupValueObjectDisplay() {}

static const OptionDefinition g_option_table[] = {
    {LLDB_OPT_SET_1, false, "dynamic-type", 'd',
     OptionParser::eRequiredArgument, nullptr, GetDynamicValueTypes(), 0,
     eArgTypeNone, "Show the object as its full dynamic type, not its static "
                   "type, if available."},
    {LLDB_OPT_SET_1, false, "synthetic-type", 'S',
     OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean,
     "Show the object obeying its synthetic provider, if available."},
    {LLDB_OPT_SET_1, false, "depth", 'D', OptionParser::eRequiredArgument,
     nullptr, {}, 0, eArgTypeCount, "Set the max recurse depth when dumping "
                                    "aggregate types (default is infinity)."},
    {LLDB_OPT_SET_1, false, "flat", 'F', OptionParser::eNoArgument, nullptr,
     {}, 0, eArgTypeNone, "Display results in a flat format that uses "
                          "expression paths for each variable or member."},
    {LLDB_OPT_SET_1, false, "location", 'L', OptionParser::eNoArgument, nullptr,
     {}, 0, eArgTypeNone, "Show variable location information."},
    {LLDB_OPT_SET_1, false, "object-description", 'O',
     OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone,
     "Print as an Objective-C object."},
    {LLDB_OPT_SET_1, false, "ptr-depth", 'P', OptionParser::eRequiredArgument,
     nullptr, {}, 0, eArgTypeCount, "The number of pointers to be traversed "
                                    "when dumping values (default is zero)."},
    {LLDB_OPT_SET_1, false, "show-types", 'T', OptionParser::eNoArgument,
     nullptr, {}, 0, eArgTypeNone,
     "Show variable types when dumping values."},
    {LLDB_OPT_SET_1, false, "no-summary-depth", 'Y',
     OptionParser::eOptionalArgument, nullptr, {}, 0, eArgTypeCount,
     "Set the depth at which omitting summary information stops (default is "
     "1)."},
    {LLDB_OPT_SET_1, false, "raw-output", 'R', OptionParser::eNoArgument,
     nullptr, {}, 0, eArgTypeNone, "Don't use formatting options."},
    {LLDB_OPT_SET_1, false, "show-all-children", 'A', OptionParser::eNoArgument,
     nullptr, {}, 0, eArgTypeNone,
     "Ignore the upper bound on the number of children to show."},
    {LLDB_OPT_SET_1, false, "validate", 'V', OptionParser::eRequiredArgument,
     nullptr, {}, 0, eArgTypeBoolean, "Show results of type validators."},
    {LLDB_OPT_SET_1, false, "element-count", 'Z',
     OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeCount,
     "Treat the result of the expression as if its type is an array of this "
     "many values."}};

llvm::ArrayRef<OptionDefinition>
OptionGroupValueObjectDisplay::GetDefinitions() {
  return llvm::makeArrayRef(g_option_table);
}

Status OptionGroupValueObjectDisplay::SetOptionValue(
    uint32_t option_idx, llvm::StringRef option_arg,
    ExecutionContext *execution_context) {
  Status error;
  const int short_option = g_option_table[option_idx].short_option;
  bool success = false;

  switch (short_option) {
  case 'd': {
    int32_t result;
    result = OptionArgParser::ToOptionEnum(option_arg, GetDynamicValueTypes(),
                                           2, error);
    if (error.Success())
      use_dynamic = (lldb::DynamicValueType)result;
  } break;
  case 'T':
    show_types = true;
    break;
  case 'L':
    show_location = true;
    break;
  case 'F':
    flat_output = true;
    break;
  case 'O':
    use_objc = true;
    break;
  case 'R':
    be_raw = true;
    break;
  case 'A':
    ignore_cap = true;
    break;

  case 'D':
    if (option_arg.getAsInteger(0, max_depth)) {
      max_depth = UINT32_MAX;
      error.SetErrorStringWithFormat("invalid max depth '%s'",
                                     option_arg.str().c_str());
    }
    break;

  case 'Z':
    if (option_arg.getAsInteger(0, elem_count)) {
      elem_count = UINT32_MAX;
      error.SetErrorStringWithFormat("invalid element count '%s'",
                                     option_arg.str().c_str());
    }
    break;

  case 'P':
    if (option_arg.getAsInteger(0, ptr_depth)) {
      ptr_depth = 0;
      error.SetErrorStringWithFormat("invalid pointer depth '%s'",
                                     option_arg.str().c_str());
    }
    break;

  case 'Y':
    if (option_arg.empty())
      no_summary_depth = 1;
    else if (option_arg.getAsInteger(0, no_summary_depth)) {
      no_summary_depth = 0;
      error.SetErrorStringWithFormat("invalid pointer depth '%s'",
                                     option_arg.str().c_str());
    }
    break;

  case 'S':
    use_synth = OptionArgParser::ToBoolean(option_arg, true, &success);
    if (!success)
      error.SetErrorStringWithFormat("invalid synthetic-type '%s'",
                                     option_arg.str().c_str());
    break;

  case 'V':
    run_validator = OptionArgParser::ToBoolean(option_arg, true, &success);
    if (!success)
      error.SetErrorStringWithFormat("invalid validate '%s'",
                                     option_arg.str().c_str());
    break;

  default:
    llvm_unreachable("Unimplemented option");
  }

  return error;
}

void OptionGroupValueObjectDisplay::OptionParsingStarting(
    ExecutionContext *execution_context) {
  // If these defaults change, be sure to modify AnyOptionWasSet().
  show_types = false;
  no_summary_depth = 0;
  show_location = false;
  flat_output = false;
  use_objc = false;
  max_depth = UINT32_MAX;
  ptr_depth = 0;
  elem_count = 0;
  use_synth = true;
  be_raw = false;
  ignore_cap = false;
  run_validator = false;

  TargetSP target_sp =
      execution_context ? execution_context->GetTargetSP() : TargetSP();
  if (target_sp)
    use_dynamic = target_sp->GetPreferDynamicValue();
  else {
    // If we don't have any targets, then dynamic values won't do us much good.
    use_dynamic = lldb::eNoDynamicValues;
  }
}

DumpValueObjectOptions OptionGroupValueObjectDisplay::GetAsDumpOptions(
    LanguageRuntimeDescriptionDisplayVerbosity lang_descr_verbosity,
    lldb::Format format, lldb::TypeSummaryImplSP summary_sp) {
  DumpValueObjectOptions options;
  options.SetMaximumPointerDepth(
      {DumpValueObjectOptions::PointerDepth::Mode::Always, ptr_depth});
  if (use_objc)
    options.SetShowSummary(false);
  else
    options.SetOmitSummaryDepth(no_summary_depth);
  options.SetMaximumDepth(max_depth)
      .SetShowTypes(show_types)
      .SetShowLocation(show_location)
      .SetUseObjectiveC(use_objc)
      .SetUseDynamicType(use_dynamic)
      .SetUseSyntheticValue(use_synth)
      .SetFlatOutput(flat_output)
      .SetIgnoreCap(ignore_cap)
      .SetFormat(format)
      .SetSummary(summary_sp);

  if (lang_descr_verbosity ==
      eLanguageRuntimeDescriptionDisplayVerbosityCompact)
    options.SetHideRootType(use_objc).SetHideName(use_objc).SetHideValue(
        use_objc);

  if (be_raw)
    options.SetRawDisplay();

  options.SetRunValidator(run_validator);

  options.SetElementCount(elem_count);

  return options;
}
