static TypeAndOrName
FixupTypeAndOrName (const TypeAndOrName& type_andor_name,
                    ValueObject& parent)
{
    TypeAndOrName ret(type_andor_name);
    if (type_andor_name.HasType())
    {
        // The type will always be the type of the dynamic object.  If our parent's type was a pointer,
        // then our type should be a pointer to the type of the dynamic object.  If a reference, then the original type
        // should be okay...
        ClangASTType orig_type = type_andor_name.GetClangASTType();
        ClangASTType corrected_type = orig_type;
        if (parent.IsPointerType())
            corrected_type = orig_type.GetPointerType ();
        else if (parent.IsPointerOrReferenceType())
            corrected_type = orig_type.GetLValueReferenceType ();
        ret.SetClangASTType(corrected_type);
    }
    else /*if (m_dynamic_type_info.HasName())*/
    {
        // If we are here we need to adjust our dynamic type name to include the correct & or * symbol
        std::string corrected_name (type_andor_name.GetName().GetCString());
        if (parent.IsPointerType())
            corrected_name.append(" *");
        else if (parent.IsPointerOrReferenceType())
            corrected_name.append(" &");
        // the parent type should be a correctly pointer'ed or referenc'ed type
        ret.SetClangASTType(parent.GetClangType());
        ret.SetName(corrected_name.c_str());
    }
    return ret;
}
bool lldb_private::formatters::JavaStringSummaryProvider(
    ValueObject &valobj, Stream &stream, const TypeSummaryOptions &opts) {
  if (valobj.IsPointerOrReferenceType()) {
    Error error;
    ValueObjectSP deref = valobj.Dereference(error);
    if (error.Fail())
      return false;
    return JavaStringSummaryProvider(*deref, stream, opts);
  }

  ProcessSP process_sp = valobj.GetProcessSP();
  if (!process_sp)
    return false;

  ConstString data_name("value");
  ConstString length_name("count");

  ValueObjectSP length_sp = valobj.GetChildMemberWithName(length_name, true);
  ValueObjectSP data_sp = valobj.GetChildMemberWithName(data_name, true);
  if (!data_sp || !length_sp)
    return false;

  bool success = false;
  uint64_t length = length_sp->GetValueAsUnsigned(0, &success);
  if (!success)
    return false;

  if (length == 0) {
    stream.Printf("\"\"");
    return true;
  }
  lldb::addr_t valobj_addr = data_sp->GetAddressOf();

  StringPrinter::ReadStringAndDumpToStreamOptions options(valobj);
  options.SetLocation(valobj_addr);
  options.SetProcessSP(process_sp);
  options.SetStream(&stream);
  options.SetSourceSize(length);
  options.SetNeedsZeroTermination(false);
  options.SetLanguage(eLanguageTypeJava);

  if (StringPrinter::ReadStringAndDumpToStream<
          StringPrinter::StringElementType::UTF16>(options))
    return true;

  stream.Printf("Summary Unavailable");
  return true;
}
bool lldb_private::formatters::JavaArraySummaryProvider(
    ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
  if (valobj.IsPointerOrReferenceType()) {
    Error error;
    ValueObjectSP deref = valobj.Dereference(error);
    if (error.Fail())
      return false;
    return JavaArraySummaryProvider(*deref, stream, options);
  }

  CompilerType type = valobj.GetCompilerType();
  uint32_t size = JavaASTContext::CalculateArraySize(type, valobj);
  if (size == UINT32_MAX)
    return false;
  stream.Printf("[%u]{...}", size);
  return true;
}