//===-- ValueObjectPrinter.cpp -----------------------------------*- C++-*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "lldb/DataFormatters/ValueObjectPrinter.h"

// C Includes
// C++ Includes
// Other libraries and framework includes
// Project includes
#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 (!GetMostSpecializedValue() || m_valobj == nullptr)
    return false;

  if (ShouldPrintValueObject()) {
    PrintValidationMarkerIfNeeded();

    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();

  PrintValidationErrorIfNeeded();

  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 == false) {
        ValueObject *non_synthetic = m_valobj->GetNonSyntheticValue().get();
        if (non_synthetic)
          m_valobj = non_synthetic;
      }
    } else {
      if (m_options.m_use_synthetic == true) {
        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 *if_fail) {
  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 : if_fail;
}

bool ValueObjectPrinter::ShouldPrintValueObject() {
  if (m_should_print == eLazyBoolCalculate)
    m_should_print =
        (m_options.m_flat_output == false || 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()) {
      if (m_options.m_use_type_display_name)
        type_name = m_valobj->GetDisplayTypeName();
      else
        type_name = 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>");
      else
        type_name.Clear();
    }

    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.Printf("%s", type_name_str.c_str());
    }
  }

  StreamString varName;

  if (m_options.m_flat_output) {
    // If we are showing types, also qualify the C++ base classes
    const bool qualify_cxx_base_classes = show_type;
    if (!m_options.m_hide_name) {
      m_valobj->GetExpressionPath(varName, qualify_cxx_base_classes);
    }
  } else if (!m_options.m_hide_name) {
    const char *name_cstr = GetRootNameForDisplay("");
    varName.Printf("%s", name_cstr);
  }

  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());

    StreamString dest_stream;
    if (m_options.m_decl_printing_helper(type_name_cstr, var_name_cstr,
                                         m_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 (!m_options.m_hide_name)
      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 == false) {
    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 = NULL;
    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()) {
    if (IsNil())
      summary.assign("nil");
    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();
      if (!IsNil() && !IsUninitialized() && !m_value.empty() &&
          (entry == NULL || (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 {
          m_stream->Printf(" %s", m_value.c_str());
          value_printed = true;
        }
      }

      if (m_summary.size()) {
        m_stream->Printf(" %s", m_summary.c_str());
        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 || !m_options.m_hide_name)
        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 == false && summary_printed == false)
        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(
    bool is_failed_description,
    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 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;

  TypeSummaryImpl *entry = GetSummaryFormatter();

  if (m_options.m_use_objc)
    return false;

  if (is_failed_description || m_curr_depth < m_options.m_max_depth) {
    // 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) {
        // 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 (!entry || entry->DoesPrintChildren(m_valobj) || m_summary.empty());
  }
  return false;
}

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

  if (!entry)
    return true;

  return entry->DoesPrintEmptyAggregates();
}

ValueObject *ValueObjectPrinter::GetValueObjectForChildrenGeneration() {
  return m_valobj;
}

void ValueObjectPrinter::PrintChildrenPreamble() {
  if (m_options.m_flat_output) {
    if (ShouldPrintValueObject())
      m_stream->EOL();
  } else {
    if (ShouldPrintValueObject())
      m_stream->PutCString(IsRef() ? ": {\n" : " {\n");
    m_stream->IndentMore();
  }
}

void ValueObjectPrinter::PrintChild(
    ValueObjectSP child_sp,
    const DumpValueObjectOptions::PointerDepth &curr_ptr_depth) {
  const uint32_t consumed_depth = (!m_options.m_pointer_as_array) ? 1 : 0;
  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_depth
                               : 0)
      .SetElementCount(0);

  if (child_sp.get()) {
    ValueObjectPrinter child_printer(
        child_sp.get(), m_stream, child_options,
        does_consume_ptr_depth ? --curr_ptr_depth : curr_ptr_depth,
        m_curr_depth + consumed_depth, 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 == false) {
    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, true);
  }
}

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 (!any_children_printed) {
          PrintChildrenPreamble();
          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('(');

    for (uint32_t idx = 0; idx < num_children; ++idx) {
      lldb::ValueObjectSP child_sp(synth_m_valobj->GetChildAtIndex(idx, true));
      if (child_sp)
        child_sp = child_sp->GetQualifiedRepresentationIfAvailable(
            m_options.m_use_dynamic, m_options.m_use_synthetic);
      if (child_sp) {
        if (idx)
          m_stream->PutCString(", ");
        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) {
  // this flag controls whether we tried to display a description for this
  // object and failed
  // if that happens, we want to display the children, if any
  bool is_failed_description =
      !PrintObjectDescriptionIfNeeded(value_printed, summary_printed);

  auto curr_ptr_depth = m_ptr_depth;
  bool print_children =
      ShouldPrintChildren(is_failed_description, curr_ptr_depth);
  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);
  bool is_instance_ptr = IsInstancePointer();
  uint64_t instance_ptr_value = LLDB_INVALID_ADDRESS;

  if (print_children && is_instance_ptr) {
    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");

      // we're done here - get out fast
      return;
    } else
      m_printed_instance_pointers->emplace(
          instance_ptr_value); // remember this guy for future reference
  }

  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 (m_curr_depth >= m_options.m_max_depth && IsAggregate() &&
             ShouldPrintValueObject()) {
    m_stream->PutCString("{...}\n");
  } else
    m_stream->EOL();
}

bool ValueObjectPrinter::ShouldPrintValidation() {
  return m_options.m_run_validator;
}

bool ValueObjectPrinter::PrintValidationMarkerIfNeeded() {
  if (!ShouldPrintValidation())
    return false;

  m_validation = m_valobj->GetValidationStatus();

  if (TypeValidatorResult::Failure == m_validation.first) {
    m_stream->Printf("! ");
    return true;
  }

  return false;
}

bool ValueObjectPrinter::PrintValidationErrorIfNeeded() {
  if (!ShouldPrintValidation())
    return false;

  if (TypeValidatorResult::Success == m_validation.first)
    return false;

  if (m_validation.second.empty())
    m_validation.second.assign("unknown error");

  m_stream->Printf(" ! validation error: %s", m_validation.second.c_str());
  m_stream->EOL();

  return true;
}
