//===-- ValueObjectPrinter.cpp --------------------------------------------===//
//
// 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/DataFormatters/ValueObjectPrinter.h"

#include "lldb/DataFormatters/DataVisualization.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Target/Language.h"
#include "lldb/Target/Target.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/Stream.h"
#include "lldb/ValueObject/ValueObject.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/MathExtras.h"
#include <cstdint>
#include <memory>
#include <optional>

using namespace lldb;
using namespace lldb_private;

ValueObjectPrinter::ValueObjectPrinter(ValueObject &valobj, Stream *s)
    : m_orig_valobj(valobj) {
  DumpValueObjectOptions options(valobj);
  Init(valobj, s, options, m_options.m_max_ptr_depth, 0, nullptr);
}

ValueObjectPrinter::ValueObjectPrinter(ValueObject &valobj, Stream *s,
                                       const DumpValueObjectOptions &options)
    : m_orig_valobj(valobj) {
  Init(valobj, s, options, m_options.m_max_ptr_depth, 0, nullptr);
}

ValueObjectPrinter::ValueObjectPrinter(
    ValueObject &valobj, Stream *s, const DumpValueObjectOptions &options,
    const DumpValueObjectOptions::PointerDepth &ptr_depth, uint32_t curr_depth,
    InstancePointersSetSP printed_instance_pointers)
    : m_orig_valobj(valobj) {
  Init(valobj, s, options, ptr_depth, curr_depth, printed_instance_pointers);
}

void ValueObjectPrinter::Init(
    ValueObject &valobj, Stream *s, const DumpValueObjectOptions &options,
    const DumpValueObjectOptions::PointerDepth &ptr_depth, uint32_t curr_depth,
    InstancePointersSetSP printed_instance_pointers) {
  m_cached_valobj = nullptr;
  m_stream = s;
  m_options = options;
  m_ptr_depth = ptr_depth;
  m_curr_depth = curr_depth;
  assert(m_stream && "cannot print to a NULL Stream");
  m_should_print = eLazyBoolCalculate;
  m_is_nil = eLazyBoolCalculate;
  m_is_uninit = eLazyBoolCalculate;
  m_is_ptr = eLazyBoolCalculate;
  m_is_ref = eLazyBoolCalculate;
  m_is_aggregate = eLazyBoolCalculate;
  m_is_instance_ptr = eLazyBoolCalculate;
  m_summary_formatter = {nullptr, false};
  m_value.assign("");
  m_summary.assign("");
  m_error.assign("");
  m_val_summary_ok = false;
  m_printed_instance_pointers = printed_instance_pointers
                                    ? printed_instance_pointers
                                    : std::make_shared<InstancePointersSet>();
  SetupMostSpecializedValue();
}

static const char *maybeNewline(const std::string &s) {
  // If the string already ends with a \n don't add another one.
  if (s.empty() || s.back() != '\n')
    return "\n";
  return "";
}

bool ValueObjectPrinter::ShouldPrintObjectDescription() {
  return ShouldPrintValueObject() && m_options.m_use_object_desc && !IsNil() &&
         !IsUninitialized() && !m_options.m_pointer_as_array;
}

llvm::Error ValueObjectPrinter::PrintValueObject() {
  // If the incoming ValueObject is in an error state, the best we're going to 
  // get out of it is its type.  But if we don't even have that, just print
  // the error and exit early.
  if (m_orig_valobj.GetError().Fail() &&
      !m_orig_valobj.GetCompilerType().IsValid())
    return m_orig_valobj.GetError().ToError();

  std::optional<std::string> object_desc;
  if (ShouldPrintObjectDescription()) {
    // The object description is invoked now, but not printed until after
    // value/summary. Calling GetObjectDescription at the outset of printing
    // allows for early discovery of errors. In the case of an error, the value
    // object is printed normally.
    llvm::Expected<std::string> object_desc_or_err =
        GetMostSpecializedValue().GetObjectDescription();
    if (!object_desc_or_err) {
      *m_stream << "warning: `po` was unsuccessful, running `p` instead\n";
      LLDB_LOG_ERROR(GetLog(LLDBLog::Expressions),
                     object_desc_or_err.takeError(),
                     "Object description fallback due to error: {0}");

      // Print the value object directly.
      m_options.DisableObjectDescription();
    } else {
      object_desc = *object_desc_or_err;
    }
  }

  if (ShouldPrintValueObject()) {
    PrintLocationIfNeeded();
    m_stream->Indent();

    PrintDecl();
  }

  bool value_printed = false;
  bool summary_printed = false;

  m_val_summary_ok =
      PrintValueAndSummaryIfNeeded(value_printed, summary_printed);

  if (m_val_summary_ok) {
    PrintObjectDescriptionIfNeeded(object_desc);
    return PrintChildrenIfNeeded(value_printed, summary_printed);
  }
  m_stream->EOL();

  return llvm::Error::success();
}

ValueObject &ValueObjectPrinter::GetMostSpecializedValue() {
  assert(m_cached_valobj && "ValueObjectPrinter must have a valid ValueObject");
  return *m_cached_valobj;
}

void ValueObjectPrinter::SetupMostSpecializedValue() {
  bool update_success = m_orig_valobj.UpdateValueIfNeeded(true);
  // If we can't find anything better, we'll fall back on the original
  // ValueObject.
  m_cached_valobj = &m_orig_valobj;
  if (update_success) {
    if (m_orig_valobj.IsDynamic()) {
      if (m_options.m_use_dynamic == eNoDynamicValues) {
        ValueObject *static_value = m_orig_valobj.GetStaticValue().get();
        if (static_value)
          m_cached_valobj = static_value;
      }
    } else {
      if (m_options.m_use_dynamic != eNoDynamicValues) {
        ValueObject *dynamic_value =
            m_orig_valobj.GetDynamicValue(m_options.m_use_dynamic).get();
        if (dynamic_value)
          m_cached_valobj = dynamic_value;
      }
    }

    if (m_cached_valobj->IsSynthetic()) {
      if (!m_options.m_use_synthetic) {
        ValueObject *non_synthetic =
            m_cached_valobj->GetNonSyntheticValue().get();
        if (non_synthetic)
          m_cached_valobj = non_synthetic;
      }
    } else {
      if (m_options.m_use_synthetic) {
        ValueObject *synthetic = m_cached_valobj->GetSyntheticValue().get();
        if (synthetic)
          m_cached_valobj = synthetic;
      }
    }
  }
  m_compiler_type = m_cached_valobj->GetCompilerType();
  m_type_flags = m_compiler_type.GetTypeInfo();
  assert(m_cached_valobj &&
         "SetupMostSpecialized value must compute a valid ValueObject");
}

const char *ValueObjectPrinter::GetRootNameForDisplay() {
  const char *root_valobj_name =
      m_options.m_root_valobj_name.empty()
          ? GetMostSpecializedValue().GetName().AsCString()
          : m_options.m_root_valobj_name.c_str();
  return root_valobj_name ? root_valobj_name : "";
}

bool ValueObjectPrinter::ShouldPrintValueObject() {
  if (m_should_print == eLazyBoolCalculate)
    m_should_print =
        (!m_options.m_flat_output || m_type_flags.Test(eTypeHasValue))
            ? eLazyBoolYes
            : eLazyBoolNo;
  return m_should_print == eLazyBoolYes;
}

bool ValueObjectPrinter::IsNil() {
  if (m_is_nil == eLazyBoolCalculate)
    m_is_nil =
        GetMostSpecializedValue().IsNilReference() ? eLazyBoolYes : eLazyBoolNo;
  return m_is_nil == eLazyBoolYes;
}

bool ValueObjectPrinter::IsUninitialized() {
  if (m_is_uninit == eLazyBoolCalculate)
    m_is_uninit = GetMostSpecializedValue().IsUninitializedReference()
                      ? eLazyBoolYes
                      : eLazyBoolNo;
  return m_is_uninit == eLazyBoolYes;
}

bool ValueObjectPrinter::IsPtr() {
  if (m_is_ptr == eLazyBoolCalculate)
    m_is_ptr = m_type_flags.Test(eTypeIsPointer) ? eLazyBoolYes : eLazyBoolNo;
  return m_is_ptr == eLazyBoolYes;
}

bool ValueObjectPrinter::IsRef() {
  if (m_is_ref == eLazyBoolCalculate)
    m_is_ref = m_type_flags.Test(eTypeIsReference) ? eLazyBoolYes : eLazyBoolNo;
  return m_is_ref == eLazyBoolYes;
}

bool ValueObjectPrinter::IsAggregate() {
  if (m_is_aggregate == eLazyBoolCalculate)
    m_is_aggregate =
        m_type_flags.Test(eTypeHasChildren) ? eLazyBoolYes : eLazyBoolNo;
  return m_is_aggregate == eLazyBoolYes;
}

bool ValueObjectPrinter::IsInstancePointer() {
  // you need to do this check on the value's clang type
  ValueObject &valobj = GetMostSpecializedValue();
  if (m_is_instance_ptr == eLazyBoolCalculate)
    m_is_instance_ptr = (valobj.GetValue().GetCompilerType().GetTypeInfo() &
                         eTypeInstanceIsPointer) != 0
                            ? eLazyBoolYes
                            : eLazyBoolNo;
  if ((eLazyBoolYes == m_is_instance_ptr) && valobj.IsBaseClass())
    m_is_instance_ptr = eLazyBoolNo;
  return m_is_instance_ptr == eLazyBoolYes;
}

bool ValueObjectPrinter::PrintLocationIfNeeded() {
  if (m_options.m_show_location) {
    m_stream->Printf("%s: ", GetMostSpecializedValue().GetLocationAsCString());
    return true;
  }
  return false;
}

void ValueObjectPrinter::PrintDecl() {
  bool show_type = true;
  // if we are at the root-level and been asked to hide the root's type, then
  // hide it
  if (m_curr_depth == 0 && m_options.m_hide_root_type)
    show_type = false;
  else
    // otherwise decide according to the usual rules (asked to show types -
    // always at the root level)
    show_type = m_options.m_show_types ||
                (m_curr_depth == 0 && !m_options.m_flat_output);

  StreamString typeName;
  // Figure out which ValueObject we're acting on
  ValueObject &valobj = GetMostSpecializedValue();

  // always show the type at the root level if it is invalid
  if (show_type) {
    // Some ValueObjects don't have types (like registers sets). Only print the
    // type if there is one to print
    ConstString type_name;
    if (m_compiler_type.IsValid()) {
      type_name = m_options.m_use_type_display_name
                      ? valobj.GetDisplayTypeName()
                      : valobj.GetQualifiedTypeName();
    } else {
      // only show an invalid type name if the user explicitly triggered
      // show_type
      if (m_options.m_show_types)
        type_name = ConstString("<invalid type>");
    }

    if (type_name) {
      std::string type_name_str(type_name.GetCString());
      if (m_options.m_hide_pointer_value) {
        for (auto iter = type_name_str.find(" *"); iter != std::string::npos;
             iter = type_name_str.find(" *")) {
          type_name_str.erase(iter, 2);
        }
      }
      typeName << type_name_str.c_str();
    }
  }

  StreamString varName;

  if (ShouldShowName()) {
    if (m_options.m_flat_output)
      valobj.GetExpressionPath(varName);
    else
      varName << GetRootNameForDisplay();
  }

  bool decl_printed = false;
  if (!m_options.m_decl_printing_helper) {
    // if the user didn't give us a custom helper, pick one based upon the
    // language, either the one that this printer is bound to, or the preferred
    // one for the ValueObject
    lldb::LanguageType lang_type =
        (m_options.m_varformat_language == lldb::eLanguageTypeUnknown)
            ? valobj.GetPreferredDisplayLanguage()
            : m_options.m_varformat_language;
    if (Language *lang_plugin = Language::FindPlugin(lang_type)) {
      m_options.m_decl_printing_helper = lang_plugin->GetDeclPrintingHelper();
    }
  }

  if (m_options.m_decl_printing_helper) {
    ConstString type_name_cstr(typeName.GetString());
    ConstString var_name_cstr(varName.GetString());

    DumpValueObjectOptions decl_print_options = m_options;
    // Pass printing helpers an option object that indicates whether the name
    // should be shown or hidden.
    decl_print_options.SetHideName(!ShouldShowName());

    StreamString dest_stream;
    if (m_options.m_decl_printing_helper(type_name_cstr, var_name_cstr,
                                         decl_print_options, dest_stream)) {
      decl_printed = true;
      m_stream->PutCString(dest_stream.GetString());
    }
  }

  // if the helper failed, or there is none, do a default thing
  if (!decl_printed) {
    if (!typeName.Empty())
      m_stream->Printf("(%s) ", typeName.GetData());
    if (!varName.Empty())
      m_stream->Printf("%s =", varName.GetData());
    else if (ShouldShowName())
      m_stream->Printf(" =");
  }
}

bool ValueObjectPrinter::CheckScopeIfNeeded() {
  if (m_options.m_scope_already_checked)
    return true;
  return GetMostSpecializedValue().IsInScope();
}

TypeSummaryImpl *ValueObjectPrinter::GetSummaryFormatter(bool null_if_omitted) {
  if (!m_summary_formatter.second) {
    TypeSummaryImpl *entry =
        m_options.m_summary_sp
            ? m_options.m_summary_sp.get()
            : GetMostSpecializedValue().GetSummaryFormat().get();

    if (m_options.m_omit_summary_depth > 0)
      entry = nullptr;
    m_summary_formatter.first = entry;
    m_summary_formatter.second = true;
  }
  if (m_options.m_omit_summary_depth > 0 && null_if_omitted)
    return nullptr;
  return m_summary_formatter.first;
}

static bool IsPointerValue(const CompilerType &type) {
  Flags type_flags(type.GetTypeInfo());
  if (type_flags.AnySet(eTypeInstanceIsPointer | eTypeIsPointer))
    return type_flags.AllClear(eTypeIsBuiltIn);
  return false;
}

void ValueObjectPrinter::GetValueSummaryError(std::string &value,
                                              std::string &summary,
                                              std::string &error) {
  lldb::Format format = m_options.m_format;
  ValueObject &valobj = GetMostSpecializedValue();
  // if I am printing synthetized elements, apply the format to those elements
  // only
  if (m_options.m_pointer_as_array)
    valobj.GetValueAsCString(lldb::eFormatDefault, value);
  else if (format != eFormatDefault && format != valobj.GetFormat())
    valobj.GetValueAsCString(format, value);
  else {
    const char *val_cstr = valobj.GetValueAsCString();
    if (val_cstr)
      value.assign(val_cstr);
  }
  const char *err_cstr = valobj.GetError().AsCString();
  if (err_cstr)
    error.assign(err_cstr);

  if (!ShouldPrintValueObject())
    return;

  if (IsNil()) {
    lldb::LanguageType lang_type =
        (m_options.m_varformat_language == lldb::eLanguageTypeUnknown)
            ? valobj.GetPreferredDisplayLanguage()
            : m_options.m_varformat_language;
    if (Language *lang_plugin = Language::FindPlugin(lang_type)) {
      summary.assign(lang_plugin->GetNilReferenceSummaryString().str());
    } else {
      // We treat C as the fallback language rather than as a separate Language
      // plugin.
      summary.assign("NULL");
    }
  } else if (IsUninitialized()) {
    summary.assign("<uninitialized>");
  } else if (m_options.m_omit_summary_depth == 0) {
    TypeSummaryImpl *entry = GetSummaryFormatter();
    if (entry) {
      valobj.GetSummaryAsCString(entry, summary,
                                 m_options.m_varformat_language);
    } else {
      const char *sum_cstr =
          valobj.GetSummaryAsCString(m_options.m_varformat_language);
      if (sum_cstr)
        summary.assign(sum_cstr);
    }
  }
}

bool ValueObjectPrinter::PrintValueAndSummaryIfNeeded(bool &value_printed,
                                                      bool &summary_printed) {
  bool error_printed = false;
  if (ShouldPrintValueObject()) {
    if (!CheckScopeIfNeeded())
      m_error.assign("out of scope");
    if (m_error.empty()) {
      GetValueSummaryError(m_value, m_summary, m_error);
    }
    if (m_error.size()) {
      // we need to support scenarios in which it is actually fine for a value
      // to have no type but - on the other hand - if we get an error *AND*
      // have no type, we try to get out gracefully, since most often that
      // combination means "could not resolve a type" and the default failure
      // mode is quite ugly
      if (!m_compiler_type.IsValid()) {
        m_stream->Printf(" <could not resolve type>");
        return false;
      }

      error_printed = true;
      m_stream->Printf(" <%s>\n", m_error.c_str());
    } else {
      // Make sure we have a value and make sure the summary didn't specify
      // that the value should not be printed - and do not print the value if
      // this thing is nil (but show the value if the user passes a format
      // explicitly)
      TypeSummaryImpl *entry = GetSummaryFormatter();
      ValueObject &valobj = GetMostSpecializedValue();
      const bool has_nil_or_uninitialized_summary =
          (IsNil() || IsUninitialized()) && !m_summary.empty();
      if (!has_nil_or_uninitialized_summary && !m_value.empty() &&
          (entry == nullptr ||
           (entry->DoesPrintValue(&valobj) ||
            m_options.m_format != eFormatDefault) ||
           m_summary.empty()) &&
          !m_options.m_hide_value) {
        if (m_options.m_hide_pointer_value &&
            IsPointerValue(valobj.GetCompilerType())) {
        } else {
          if (ShouldShowName())
            m_stream->PutChar(' ');
          m_stream->PutCString(m_value);
          value_printed = true;
        }
      }

      if (m_summary.size()) {
        if (ShouldShowName() || value_printed)
          m_stream->PutChar(' ');
        m_stream->PutCString(m_summary);
        summary_printed = true;
      }
    }
  }
  return !error_printed;
}

void ValueObjectPrinter::PrintObjectDescriptionIfNeeded(
    std::optional<std::string> object_desc) {
  if (!object_desc)
    return;

  if (!m_options.m_hide_value || ShouldShowName())
    *m_stream << ' ';
  *m_stream << *object_desc << maybeNewline(*object_desc);
}

bool DumpValueObjectOptions::PointerDepth::CanAllowExpansion() const {
  return m_count > 0;
}

bool ValueObjectPrinter::ShouldPrintChildren(
    DumpValueObjectOptions::PointerDepth &curr_ptr_depth) {
  const bool is_ref = IsRef();
  const bool is_ptr = IsPtr();
  const bool is_uninit = IsUninitialized();

  if (is_uninit)
    return false;

  // If we have reached the maximum depth we shouldn't print any more children.
  if (HasReachedMaximumDepth())
    return false;

  // if the user has specified an element count, always print children as it is
  // explicit user demand being honored
  if (m_options.m_pointer_as_array)
    return true;

  if (m_options.m_use_object_desc)
    return false;

  bool print_children = true;
  ValueObject &valobj = GetMostSpecializedValue();
  if (TypeSummaryImpl *type_summary = GetSummaryFormatter())
    print_children = type_summary->DoesPrintChildren(&valobj);

  // We will show children for all concrete types. We won't show pointer
  // contents unless a pointer depth has been specified. We won't reference
  // contents unless the reference is the root object (depth of zero).

  // Use a new temporary pointer depth in case we override the current
  // pointer depth below...

  if (is_ptr || is_ref) {
    // We have a pointer or reference whose value is an address. Make sure
    // that address is not NULL
    if (valobj.GetPointerValue().address == 0)
      return false;

    const bool is_root_level = m_curr_depth == 0;
    const bool is_expanded_ptr =
        is_ptr && m_type_flags.Test(m_options.m_expand_ptr_type_flags);

    if ((is_ref || is_expanded_ptr) && is_root_level && print_children) {
      // If this is the root object (depth is zero) that we are showing and it
      // is either a reference or a preferred type of pointer, then print it.
      // Don't do this at deeper depths otherwise we can end up with infinite
      // recursion...
      return true;
    }

    return curr_ptr_depth.CanAllowExpansion();
  }

  return print_children || m_summary.empty();
}

bool ValueObjectPrinter::ShouldExpandEmptyAggregates() {
  TypeSummaryImpl *entry = GetSummaryFormatter();

  if (!entry)
    return true;

  return entry->DoesPrintEmptyAggregates();
}

ValueObject &ValueObjectPrinter::GetValueObjectForChildrenGeneration() {
  return GetMostSpecializedValue();
}

void ValueObjectPrinter::PrintChildrenPreamble(bool value_printed,
                                               bool summary_printed) {
  if (m_options.m_flat_output) {
    if (ShouldPrintValueObject())
      m_stream->EOL();
  } else {
    if (ShouldPrintValueObject()) {
      if (IsRef()) {
        m_stream->PutCString(": ");
      } else if (value_printed || summary_printed || ShouldShowName()) {
        m_stream->PutChar(' ');
      }
      m_stream->PutCString("{\n");
    }
    m_stream->IndentMore();
  }
}

void ValueObjectPrinter::PrintChild(
    ValueObjectSP child_sp,
    const DumpValueObjectOptions::PointerDepth &curr_ptr_depth) {
  const uint32_t consumed_summary_depth = m_options.m_pointer_as_array ? 0 : 1;
  const bool does_consume_ptr_depth =
      ((IsPtr() && !m_options.m_pointer_as_array) || IsRef());

  DumpValueObjectOptions child_options(m_options);
  child_options.SetFormat(m_options.m_format)
      .SetSummary()
      .SetRootValueObjectName();
  child_options.SetScopeChecked(true)
      .SetHideName(m_options.m_hide_name)
      .SetHideValue(m_options.m_hide_value)
      .SetOmitSummaryDepth(child_options.m_omit_summary_depth > 1
                               ? child_options.m_omit_summary_depth -
                                     consumed_summary_depth
                               : 0)
      .SetElementCount(0);

  if (child_sp.get()) {
    auto ptr_depth = curr_ptr_depth;
    if (does_consume_ptr_depth)
      ptr_depth = curr_ptr_depth.Decremented();

    ValueObjectPrinter child_printer(*(child_sp.get()), m_stream, child_options,
                                     ptr_depth, m_curr_depth + 1,
                                     m_printed_instance_pointers);
    llvm::Error error = child_printer.PrintValueObject();
    if (error) {
      if (m_stream)
        *m_stream << "error: " << toString(std::move(error));
      else
        llvm::consumeError(std::move(error));
    }
  }
}

llvm::Expected<uint32_t>
ValueObjectPrinter::GetMaxNumChildrenToPrint(bool &print_dotdotdot) {
  ValueObject &synth_valobj = GetValueObjectForChildrenGeneration();

  if (m_options.m_pointer_as_array)
    return m_options.m_pointer_as_array.m_element_count;

  const uint32_t max_num_children =
      m_options.m_ignore_cap ? UINT32_MAX
                             : GetMostSpecializedValue()
                                   .GetTargetSP()
                                   ->GetMaximumNumberOfChildrenToDisplay();
  // Ask for one more child than the maximum to see if we should print "...".
  auto num_children_or_err = synth_valobj.GetNumChildren(
      llvm::SaturatingAdd(max_num_children, uint32_t(1)));
  if (!num_children_or_err)
    return num_children_or_err;
  if (*num_children_or_err > max_num_children) {
    print_dotdotdot = true;
    return max_num_children;
  }
  return num_children_or_err;
}

void ValueObjectPrinter::PrintChildrenPostamble(bool print_dotdotdot) {
  if (!m_options.m_flat_output) {
    if (print_dotdotdot) {
      GetMostSpecializedValue()
          .GetTargetSP()
          ->GetDebugger()
          .GetCommandInterpreter()
          .ChildrenTruncated();
      m_stream->Indent("...\n");
    }
    m_stream->IndentLess();
    m_stream->Indent("}\n");
  }
}

bool ValueObjectPrinter::ShouldPrintEmptyBrackets(bool value_printed,
                                                  bool summary_printed) {
  ValueObject &synth_valobj = GetValueObjectForChildrenGeneration();

  if (!IsAggregate())
    return false;

  if (!m_options.m_reveal_empty_aggregates) {
    if (value_printed || summary_printed)
      return false;
  }

  if (synth_valobj.MightHaveChildren())
    return true;

  if (m_val_summary_ok)
    return false;

  return true;
}

static constexpr size_t PhysicalIndexForLogicalIndex(size_t base, size_t stride,
                                                     size_t logical) {
  return base + logical * stride;
}

ValueObjectSP ValueObjectPrinter::GenerateChild(ValueObject &synth_valobj,
                                                size_t idx) {
  if (m_options.m_pointer_as_array) {
    // if generating pointer-as-array children, use GetSyntheticArrayMember
    return synth_valobj.GetSyntheticArrayMember(
        PhysicalIndexForLogicalIndex(
            m_options.m_pointer_as_array.m_base_element,
            m_options.m_pointer_as_array.m_stride, idx),
        true);
  } else {
    // otherwise, do the usual thing
    return synth_valobj.GetChildAtIndex(idx);
  }
}

void ValueObjectPrinter::PrintChildren(
    bool value_printed, bool summary_printed,
    const DumpValueObjectOptions::PointerDepth &curr_ptr_depth) {
  ValueObject &synth_valobj = GetValueObjectForChildrenGeneration();

  bool print_dotdotdot = false;
  auto num_children_or_err = GetMaxNumChildrenToPrint(print_dotdotdot);
  if (!num_children_or_err) {
    *m_stream << " <" << llvm::toString(num_children_or_err.takeError()) << '>';
    return;
  }
  uint32_t num_children = *num_children_or_err;
  if (num_children) {
    bool any_children_printed = false;

    for (size_t idx = 0; idx < num_children; ++idx) {
      if (ValueObjectSP child_sp = GenerateChild(synth_valobj, idx)) {
        if (m_options.m_child_printing_decider &&
            !m_options.m_child_printing_decider(child_sp->GetName()))
          continue;
        if (!any_children_printed) {
          PrintChildrenPreamble(value_printed, summary_printed);
          any_children_printed = true;
        }
        PrintChild(child_sp, curr_ptr_depth);
      }
    }

    if (any_children_printed)
      PrintChildrenPostamble(print_dotdotdot);
    else {
      if (ShouldPrintEmptyBrackets(value_printed, summary_printed)) {
        if (ShouldPrintValueObject())
          m_stream->PutCString(" {}\n");
        else
          m_stream->EOL();
      } else
        m_stream->EOL();
    }
  } else if (ShouldPrintEmptyBrackets(value_printed, summary_printed)) {
    // Aggregate, no children...
    if (ShouldPrintValueObject()) {
      // if it has a synthetic value, then don't print {}, the synthetic
      // children are probably only being used to vend a value
      if (GetMostSpecializedValue().DoesProvideSyntheticValue() ||
          !ShouldExpandEmptyAggregates())
        m_stream->PutCString("\n");
      else
        m_stream->PutCString(" {}\n");
    }
  } else {
    if (ShouldPrintValueObject())
      m_stream->EOL();
  }
}

bool ValueObjectPrinter::PrintChildrenOneLiner(bool hide_names) {
  ValueObject &synth_valobj = GetValueObjectForChildrenGeneration();

  bool print_dotdotdot = false;
  auto num_children_or_err = GetMaxNumChildrenToPrint(print_dotdotdot);
  if (!num_children_or_err) {
    *m_stream << '<' << llvm::toString(num_children_or_err.takeError()) << '>';
    return true;
  }
  uint32_t num_children = *num_children_or_err;

  if (num_children) {
    m_stream->PutChar('(');

    bool did_print_children = false;
    for (uint32_t idx = 0; idx < num_children; ++idx) {
      lldb::ValueObjectSP child_sp(synth_valobj.GetChildAtIndex(idx));
      if (child_sp)
        child_sp = child_sp->GetQualifiedRepresentationIfAvailable(
            m_options.m_use_dynamic, m_options.m_use_synthetic);
      if (child_sp) {
        if (m_options.m_child_printing_decider &&
            !m_options.m_child_printing_decider(child_sp->GetName()))
          continue;
        if (idx && did_print_children)
          m_stream->PutCString(", ");
        did_print_children = true;
        if (!hide_names) {
          const char *name = child_sp.get()->GetName().AsCString();
          if (name && *name) {
            m_stream->PutCString(name);
            m_stream->PutCString(" = ");
          }
        }
        child_sp->DumpPrintableRepresentation(
            *m_stream, ValueObject::eValueObjectRepresentationStyleSummary,
            m_options.m_format,
            ValueObject::PrintableRepresentationSpecialCases::eDisable);
      }
    }

    if (print_dotdotdot)
      m_stream->PutCString(", ...)");
    else
      m_stream->PutChar(')');
  }
  return true;
}

llvm::Error ValueObjectPrinter::PrintChildrenIfNeeded(bool value_printed,
                                                      bool summary_printed) {

  ValueObject &valobj = GetMostSpecializedValue();

  DumpValueObjectOptions::PointerDepth curr_ptr_depth = m_ptr_depth;
  const bool print_children = ShouldPrintChildren(curr_ptr_depth);
  const bool print_oneline =
      (curr_ptr_depth.CanAllowExpansion() || m_options.m_show_types ||
       !m_options.m_allow_oneliner_mode || m_options.m_flat_output ||
       (m_options.m_pointer_as_array) || m_options.m_show_location)
          ? false
          : DataVisualization::ShouldPrintAsOneLiner(valobj);
  if (print_children && IsInstancePointer()) {
    uint64_t instance_ptr_value = valobj.GetValueAsUnsigned(0);
    if (m_printed_instance_pointers->count(instance_ptr_value)) {
      // We already printed this instance-is-pointer thing, so don't expand it.
      m_stream->PutCString(" {...}\n");
      return llvm::Error::success();
    } else {
      // Remember this guy for future reference.
      m_printed_instance_pointers->emplace(instance_ptr_value);
    }
  }

  if (print_children) {
    if (print_oneline) {
      m_stream->PutChar(' ');
      PrintChildrenOneLiner(false);
      m_stream->EOL();
    } else
      PrintChildren(value_printed, summary_printed, curr_ptr_depth);
  } else if (HasReachedMaximumDepth() && IsAggregate() &&
             ShouldPrintValueObject()) {
    m_stream->PutCString(" {...}\n");
    // The maximum child depth has been reached. If `m_max_depth` is the default
    // (i.e. the user has _not_ customized it), then lldb presents a warning to
    // the user. The warning tells the user that the limit has been reached, but
    // more importantly tells them how to expand the limit if desired.
    if (m_options.m_max_depth_is_default)
      valobj.GetTargetSP()
          ->GetDebugger()
          .GetCommandInterpreter()
          .SetReachedMaximumDepth();
  } else
    m_stream->EOL();
  return llvm::Error::success();
}

bool ValueObjectPrinter::HasReachedMaximumDepth() {
  return m_curr_depth >= m_options.m_max_depth;
}

bool ValueObjectPrinter::ShouldShowName() const {
  if (m_curr_depth == 0)
    return !m_options.m_hide_root_name && !m_options.m_hide_name;
  return !m_options.m_hide_name;
}
