//===-- ValueObjectPrinter.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/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 (!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) {
        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 *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 || 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) {
    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 && !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(
    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) {
    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;
}
