//===-- 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/Core/ValueObject.h"
#include "lldb/DataFormatters/DataVisualization.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Target/Language.h"
#include "lldb/Target/Target.h"
#include "lldb/Utility/Stream.h"

using namespace lldb;
using namespace lldb_private;

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

ValueObjectPrinter::ValueObjectPrinter(ValueObject *valobj, Stream *s,
                                       const DumpValueObjectOptions &options) {
  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) {
  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_orig_valobj = valobj;
  m_valobj = nullptr;
  m_stream = s;
  m_options = options;
  m_ptr_depth = ptr_depth;
  m_curr_depth = curr_depth;
  assert(m_orig_valobj && "cannot print a NULL ValueObject");
  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
          : InstancePointersSetSP(new InstancePointersSet());
}

bool ValueObjectPrinter::PrintValueObject() {
  if (!m_orig_valobj)
    return false;

  // 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()) {
    m_stream->Printf("Error: '%s'", m_orig_valobj->GetError().AsCString());
    return true;
  }
   
  if (!GetMostSpecializedValue() || m_valobj == nullptr)
    return false;

  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)
    PrintChildrenIfNeeded(value_printed, summary_printed);
  else
    m_stream->EOL();

  return true;
}

bool ValueObjectPrinter::GetMostSpecializedValue() {
  if (m_valobj)
    return true;
  bool update_success = m_orig_valobj->UpdateValueIfNeeded(true);
  if (!update_success) {
    m_valobj = m_orig_valobj;
  } else {
    if (m_orig_valobj->IsDynamic()) {
      if (m_options.m_use_dynamic == eNoDynamicValues) {
        ValueObject *static_value = m_orig_valobj->GetStaticValue().get();
        if (static_value)
          m_valobj = static_value;
        else
          m_valobj = m_orig_valobj;
      } else
        m_valobj = m_orig_valobj;
    } 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_valobj = dynamic_value;
        else
          m_valobj = m_orig_valobj;
      } else
        m_valobj = m_orig_valobj;
    }

    if (m_valobj->IsSynthetic()) {
      if (!m_options.m_use_synthetic) {
        ValueObject *non_synthetic = m_valobj->GetNonSyntheticValue().get();
        if (non_synthetic)
          m_valobj = non_synthetic;
      }
    } else {
      if (m_options.m_use_synthetic) {
        ValueObject *synthetic = m_valobj->GetSyntheticValue().get();
        if (synthetic)
          m_valobj = synthetic;
      }
    }
  }
  m_compiler_type = m_valobj->GetCompilerType();
  m_type_flags = m_compiler_type.GetTypeInfo();
  return true;
}

const char *ValueObjectPrinter::GetDescriptionForDisplay() {
  const char *str = m_valobj->GetObjectDescription();
  if (!str)
    str = m_valobj->GetSummaryAsCString();
  if (!str)
    str = m_valobj->GetValueAsCString();
  return str;
}

const char *ValueObjectPrinter::GetRootNameForDisplay() {
  const char *root_valobj_name = m_options.m_root_valobj_name.empty()
                                     ? m_valobj->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 = m_valobj->IsNilReference() ? eLazyBoolYes : eLazyBoolNo;
  return m_is_nil == eLazyBoolYes;
}

bool ValueObjectPrinter::IsUninitialized() {
  if (m_is_uninit == eLazyBoolCalculate)
    m_is_uninit =
        m_valobj->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
  if (m_is_instance_ptr == eLazyBoolCalculate)
    m_is_instance_ptr = (m_valobj->GetValue().GetCompilerType().GetTypeInfo() &
                         eTypeInstanceIsPointer) != 0
                            ? eLazyBoolYes
                            : eLazyBoolNo;
  if ((eLazyBoolYes == m_is_instance_ptr) && m_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: ", m_valobj->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;

  // 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
                      ? m_valobj->GetDisplayTypeName()
                      : m_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)
      m_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)
            ? m_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 m_valobj->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()
                                 : m_valobj->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;
  // if I am printing synthetized elements, apply the format to those elements
  // only
  if (m_options.m_pointer_as_array)
    m_valobj->GetValueAsCString(lldb::eFormatDefault, value);
  else if (format != eFormatDefault && format != m_valobj->GetFormat())
    m_valobj->GetValueAsCString(format, value);
  else {
    const char *val_cstr = m_valobj->GetValueAsCString();
    if (val_cstr)
      value.assign(val_cstr);
  }
  const char *err_cstr = m_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)
            ? m_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) {
      m_valobj->GetSummaryAsCString(entry, summary,
                                    m_options.m_varformat_language);
    } else {
      const char *sum_cstr =
          m_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();
      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(m_valobj) ||
            m_options.m_format != eFormatDefault) ||
           m_summary.empty()) &&
          !m_options.m_hide_value) {
        if (m_options.m_hide_pointer_value &&
            IsPointerValue(m_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;
}

bool ValueObjectPrinter::PrintObjectDescriptionIfNeeded(bool value_printed,
                                                        bool summary_printed) {
  if (ShouldPrintValueObject()) {
    // let's avoid the overly verbose no description error for a nil thing
    if (m_options.m_use_objc && !IsNil() && !IsUninitialized() &&
        (!m_options.m_pointer_as_array)) {
      if (!m_options.m_hide_value || ShouldShowName())
        m_stream->Printf(" ");
      const char *object_desc = nullptr;
      if (value_printed || summary_printed)
        object_desc = m_valobj->GetObjectDescription();
      else
        object_desc = GetDescriptionForDisplay();
      if (object_desc && *object_desc) {
        // If the description already ends with a \n don't add another one.
        size_t object_end = strlen(object_desc) - 1;
        if (object_desc[object_end] == '\n')
          m_stream->Printf("%s", object_desc);
        else
          m_stream->Printf("%s\n", object_desc);
        return true;
      } else if (!value_printed && !summary_printed)
        return true;
      else
        return false;
    }
  }
  return true;
}

bool DumpValueObjectOptions::PointerDepth::CanAllowExpansion() const {
  switch (m_mode) {
  case Mode::Always:
  case Mode::Default:
    return m_count > 0;
  case Mode::Never:
    return false;
  }
  return false;
}

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_objc)
    return false;

  bool print_children = true;
  if (TypeSummaryImpl *type_summary = GetSummaryFormatter())
    print_children = type_summary->DoesPrintChildren(m_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
    AddressType ptr_address_type;
    if (m_valobj->GetPointerValue(&ptr_address_type) == 0)
      return false;

    const bool is_root_level = m_curr_depth == 0;

    if (is_ref && is_root_level && print_children) {
      // If this is the root object (depth is zero) that we are showing and
      // it is a reference, and no pointer depth has been supplied print out
      // what it references. 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 m_valobj;
}

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);
    child_printer.PrintValueObject();
  }
}

uint32_t ValueObjectPrinter::GetMaxNumChildrenToPrint(bool &print_dotdotdot) {
  ValueObject *synth_m_valobj = GetValueObjectForChildrenGeneration();

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

  size_t num_children = synth_m_valobj->GetNumChildren();
  print_dotdotdot = false;
  if (num_children) {
    const size_t max_num_children =
        m_valobj->GetTargetSP()->GetMaximumNumberOfChildrenToDisplay();

    if (num_children > max_num_children && !m_options.m_ignore_cap) {
      print_dotdotdot = true;
      return max_num_children;
    }
  }
  return num_children;
}

void ValueObjectPrinter::PrintChildrenPostamble(bool print_dotdotdot) {
  if (!m_options.m_flat_output) {
    if (print_dotdotdot) {
      m_valobj->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_m_valobj = GetValueObjectForChildrenGeneration();

  if (!IsAggregate())
    return false;

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

  if (synth_m_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_m_valobj = GetValueObjectForChildrenGeneration();

  bool print_dotdotdot = false;
  size_t num_children = GetMaxNumChildrenToPrint(print_dotdotdot);
  if (num_children) {
    bool any_children_printed = false;

    for (size_t idx = 0; idx < num_children; ++idx) {
      if (ValueObjectSP child_sp = GenerateChild(synth_m_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 (m_valobj->DoesProvideSyntheticValue() ||
          !ShouldExpandEmptyAggregates())
        m_stream->PutCString("\n");
      else
        m_stream->PutCString(" {}\n");
    }
  } else {
    if (ShouldPrintValueObject())
      m_stream->EOL();
  }
}

bool ValueObjectPrinter::PrintChildrenOneLiner(bool hide_names) {
  if (!GetMostSpecializedValue() || m_valobj == nullptr)
    return false;

  ValueObject *synth_m_valobj = GetValueObjectForChildrenGeneration();

  bool print_dotdotdot = false;
  size_t num_children = GetMaxNumChildrenToPrint(print_dotdotdot);

  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_m_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;
}

void ValueObjectPrinter::PrintChildrenIfNeeded(bool value_printed,
                                               bool summary_printed) {
  PrintObjectDescriptionIfNeeded(value_printed, summary_printed);

  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(*m_valobj);
  if (print_children && IsInstancePointer()) {
    uint64_t instance_ptr_value = m_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;
    } 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)
      m_valobj->GetTargetSP()
          ->GetDebugger()
          .GetCommandInterpreter()
          .SetReachedMaximumDepth();
  } else
    m_stream->EOL();
}

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;
}
