14d93b8cdSEnrico Granata //===-- ValueObjectPrinter.cpp -------------------------------------*- C++ -*-===//
24d93b8cdSEnrico Granata //
34d93b8cdSEnrico Granata //                     The LLVM Compiler Infrastructure
44d93b8cdSEnrico Granata //
54d93b8cdSEnrico Granata // This file is distributed under the University of Illinois Open Source
64d93b8cdSEnrico Granata // License. See LICENSE.TXT for details.
74d93b8cdSEnrico Granata //
84d93b8cdSEnrico Granata //===----------------------------------------------------------------------===//
94d93b8cdSEnrico Granata 
104d93b8cdSEnrico Granata #include "lldb/DataFormatters/ValueObjectPrinter.h"
114d93b8cdSEnrico Granata 
124d93b8cdSEnrico Granata // C Includes
134d93b8cdSEnrico Granata // C++ Includes
144d93b8cdSEnrico Granata // Other libraries and framework includes
154d93b8cdSEnrico Granata // Project includes
164d93b8cdSEnrico Granata #include "lldb/Core/Debugger.h"
17a29cb0baSEnrico Granata #include "lldb/DataFormatters/DataVisualization.h"
184d93b8cdSEnrico Granata #include "lldb/Interpreter/CommandInterpreter.h"
194d93b8cdSEnrico Granata #include "lldb/Target/Target.h"
204d93b8cdSEnrico Granata 
214d93b8cdSEnrico Granata using namespace lldb;
224d93b8cdSEnrico Granata using namespace lldb_private;
234d93b8cdSEnrico Granata 
244d93b8cdSEnrico Granata ValueObjectPrinter::ValueObjectPrinter (ValueObject* valobj,
254d93b8cdSEnrico Granata                                         Stream* s,
26938d1d67SEnrico Granata                                         const DumpValueObjectOptions& options)
274d93b8cdSEnrico Granata {
28938d1d67SEnrico Granata     Init(valobj,s,options,options.m_max_ptr_depth,0);
294d93b8cdSEnrico Granata }
304d93b8cdSEnrico Granata 
314d93b8cdSEnrico Granata ValueObjectPrinter::ValueObjectPrinter (ValueObject* valobj,
324d93b8cdSEnrico Granata                                         Stream* s,
334d93b8cdSEnrico Granata                                         const DumpValueObjectOptions& options,
344d93b8cdSEnrico Granata                                         uint32_t ptr_depth,
35938d1d67SEnrico Granata                                         uint32_t curr_depth)
36938d1d67SEnrico Granata {
37938d1d67SEnrico Granata     Init(valobj,s,options,ptr_depth,curr_depth);
38938d1d67SEnrico Granata }
39938d1d67SEnrico Granata 
40938d1d67SEnrico Granata void
41938d1d67SEnrico Granata ValueObjectPrinter::Init (ValueObject* valobj,
42938d1d67SEnrico Granata                           Stream* s,
43938d1d67SEnrico Granata                           const DumpValueObjectOptions& options,
44938d1d67SEnrico Granata                           uint32_t ptr_depth,
45938d1d67SEnrico Granata                           uint32_t curr_depth)
46938d1d67SEnrico Granata {
47938d1d67SEnrico Granata     m_orig_valobj = valobj;
48938d1d67SEnrico Granata     m_valobj = nullptr;
49938d1d67SEnrico Granata     m_stream = s;
50938d1d67SEnrico Granata     this->options = options;
51938d1d67SEnrico Granata     m_ptr_depth = ptr_depth;
52938d1d67SEnrico Granata     m_curr_depth = curr_depth;
53938d1d67SEnrico Granata     assert (m_orig_valobj && "cannot print a NULL ValueObject");
54938d1d67SEnrico Granata     assert (m_stream && "cannot print to a NULL Stream");
55938d1d67SEnrico Granata     m_should_print = eLazyBoolCalculate;
56938d1d67SEnrico Granata     m_is_nil = eLazyBoolCalculate;
57938d1d67SEnrico Granata     m_is_ptr = eLazyBoolCalculate;
58938d1d67SEnrico Granata     m_is_ref = eLazyBoolCalculate;
59938d1d67SEnrico Granata     m_is_aggregate = eLazyBoolCalculate;
60938d1d67SEnrico Granata     m_summary_formatter = {nullptr,false};
61938d1d67SEnrico Granata     m_value.assign("");
62938d1d67SEnrico Granata     m_summary.assign("");
63938d1d67SEnrico Granata     m_error.assign("");
64938d1d67SEnrico Granata }
654d93b8cdSEnrico Granata 
664d93b8cdSEnrico Granata bool
674d93b8cdSEnrico Granata ValueObjectPrinter::PrintValueObject ()
684d93b8cdSEnrico Granata {
694d93b8cdSEnrico Granata     if (!GetDynamicValueIfNeeded () || m_valobj == nullptr)
704d93b8cdSEnrico Granata         return false;
714d93b8cdSEnrico Granata 
724d93b8cdSEnrico Granata     if (ShouldPrintValueObject())
734d93b8cdSEnrico Granata     {
74*0f883ffbSEnrico Granata         PrintValidationMarkerIfNeeded();
75*0f883ffbSEnrico Granata 
764d93b8cdSEnrico Granata         PrintLocationIfNeeded();
774d93b8cdSEnrico Granata         m_stream->Indent();
784d93b8cdSEnrico Granata 
794d93b8cdSEnrico Granata         bool show_type = PrintTypeIfNeeded();
804d93b8cdSEnrico Granata 
814d93b8cdSEnrico Granata         PrintNameIfNeeded(show_type);
824d93b8cdSEnrico Granata     }
834d93b8cdSEnrico Granata 
844d93b8cdSEnrico Granata     bool value_printed = false;
854d93b8cdSEnrico Granata     bool summary_printed = false;
864d93b8cdSEnrico Granata 
874d93b8cdSEnrico Granata     bool val_summary_ok = PrintValueAndSummaryIfNeeded (value_printed,summary_printed);
884d93b8cdSEnrico Granata 
894d93b8cdSEnrico Granata     if (val_summary_ok)
904d93b8cdSEnrico Granata         PrintChildrenIfNeeded (value_printed, summary_printed);
9139938938SEnrico Granata     else
924d93b8cdSEnrico Granata         m_stream->EOL();
934d93b8cdSEnrico Granata 
94*0f883ffbSEnrico Granata     PrintValidationErrorIfNeeded();
95*0f883ffbSEnrico Granata 
964d93b8cdSEnrico Granata     return true;
974d93b8cdSEnrico Granata }
984d93b8cdSEnrico Granata 
994d93b8cdSEnrico Granata bool
1004d93b8cdSEnrico Granata ValueObjectPrinter::GetDynamicValueIfNeeded ()
1014d93b8cdSEnrico Granata {
102a29cb0baSEnrico Granata     if (m_valobj)
103a29cb0baSEnrico Granata         return true;
1044d93b8cdSEnrico Granata     bool update_success = m_orig_valobj->UpdateValueIfNeeded (true);
1054d93b8cdSEnrico Granata     if (!update_success)
106106260c5SEnrico Granata     {
107106260c5SEnrico Granata         m_valobj = m_orig_valobj;
108106260c5SEnrico Granata     }
109106260c5SEnrico Granata     else
110106260c5SEnrico Granata     {
111106260c5SEnrico Granata         if (m_orig_valobj->IsDynamic())
112106260c5SEnrico Granata         {
113106260c5SEnrico Granata             if (options.m_use_dynamic == eNoDynamicValues)
114106260c5SEnrico Granata             {
115106260c5SEnrico Granata                 ValueObject *static_value = m_orig_valobj->GetStaticValue().get();
116106260c5SEnrico Granata                 if (static_value)
117106260c5SEnrico Granata                     m_valobj = static_value;
118106260c5SEnrico Granata                 else
119106260c5SEnrico Granata                     m_valobj = m_orig_valobj;
120106260c5SEnrico Granata             }
121106260c5SEnrico Granata             else
122106260c5SEnrico Granata                 m_valobj = m_orig_valobj;
123106260c5SEnrico Granata         }
124106260c5SEnrico Granata         else
125106260c5SEnrico Granata         {
1264d93b8cdSEnrico Granata             if (options.m_use_dynamic != eNoDynamicValues)
1274d93b8cdSEnrico Granata             {
1284d93b8cdSEnrico Granata                 ValueObject *dynamic_value = m_orig_valobj->GetDynamicValue(options.m_use_dynamic).get();
1294d93b8cdSEnrico Granata                 if (dynamic_value)
1304d93b8cdSEnrico Granata                     m_valobj = dynamic_value;
1314d93b8cdSEnrico Granata                 else
1324d93b8cdSEnrico Granata                     m_valobj = m_orig_valobj;
1334d93b8cdSEnrico Granata             }
1344d93b8cdSEnrico Granata             else
1354d93b8cdSEnrico Granata                 m_valobj = m_orig_valobj;
136106260c5SEnrico Granata         }
137106260c5SEnrico Granata     }
1384d93b8cdSEnrico Granata     m_clang_type = m_valobj->GetClangType();
1394d93b8cdSEnrico Granata     m_type_flags = m_clang_type.GetTypeInfo ();
1404d93b8cdSEnrico Granata     return true;
1414d93b8cdSEnrico Granata }
1424d93b8cdSEnrico Granata 
1434d93b8cdSEnrico Granata const char*
1444d93b8cdSEnrico Granata ValueObjectPrinter::GetDescriptionForDisplay ()
1454d93b8cdSEnrico Granata {
1464d93b8cdSEnrico Granata     const char* str = m_valobj->GetObjectDescription();
1474d93b8cdSEnrico Granata     if (!str)
1484d93b8cdSEnrico Granata         str = m_valobj->GetSummaryAsCString();
1494d93b8cdSEnrico Granata     if (!str)
1504d93b8cdSEnrico Granata         str = m_valobj->GetValueAsCString();
1514d93b8cdSEnrico Granata     return str;
1524d93b8cdSEnrico Granata }
1534d93b8cdSEnrico Granata 
1544d93b8cdSEnrico Granata const char*
1554d93b8cdSEnrico Granata ValueObjectPrinter::GetRootNameForDisplay (const char* if_fail)
1564d93b8cdSEnrico Granata {
1574d93b8cdSEnrico Granata     const char *root_valobj_name = options.m_root_valobj_name.empty() ?
1584d93b8cdSEnrico Granata         m_valobj->GetName().AsCString() :
1594d93b8cdSEnrico Granata         options.m_root_valobj_name.c_str();
1604d93b8cdSEnrico Granata     return root_valobj_name ? root_valobj_name : if_fail;
1614d93b8cdSEnrico Granata }
1624d93b8cdSEnrico Granata 
1634d93b8cdSEnrico Granata bool
1644d93b8cdSEnrico Granata ValueObjectPrinter::ShouldPrintValueObject ()
1654d93b8cdSEnrico Granata {
1664d93b8cdSEnrico Granata     if (m_should_print == eLazyBoolCalculate)
1674d93b8cdSEnrico Granata         m_should_print = (options.m_flat_output == false || m_type_flags.Test (ClangASTType::eTypeHasValue)) ? eLazyBoolYes : eLazyBoolNo;
1684d93b8cdSEnrico Granata     return m_should_print == eLazyBoolYes;
1694d93b8cdSEnrico Granata }
1704d93b8cdSEnrico Granata 
1714d93b8cdSEnrico Granata bool
1724d93b8cdSEnrico Granata ValueObjectPrinter::IsNil ()
1734d93b8cdSEnrico Granata {
1744d93b8cdSEnrico Granata     if (m_is_nil == eLazyBoolCalculate)
1754d93b8cdSEnrico Granata         m_is_nil = m_valobj->IsObjCNil() ? eLazyBoolYes : eLazyBoolNo;
1764d93b8cdSEnrico Granata     return m_is_nil == eLazyBoolYes;
1774d93b8cdSEnrico Granata }
1784d93b8cdSEnrico Granata 
1794d93b8cdSEnrico Granata bool
1804d93b8cdSEnrico Granata ValueObjectPrinter::IsPtr ()
1814d93b8cdSEnrico Granata {
1824d93b8cdSEnrico Granata     if (m_is_ptr == eLazyBoolCalculate)
1834d93b8cdSEnrico Granata         m_is_ptr = m_type_flags.Test (ClangASTType::eTypeIsPointer) ? eLazyBoolYes : eLazyBoolNo;
1844d93b8cdSEnrico Granata     return m_is_ptr == eLazyBoolYes;
1854d93b8cdSEnrico Granata }
1864d93b8cdSEnrico Granata 
1874d93b8cdSEnrico Granata bool
1884d93b8cdSEnrico Granata ValueObjectPrinter::IsRef ()
1894d93b8cdSEnrico Granata {
1904d93b8cdSEnrico Granata     if (m_is_ref == eLazyBoolCalculate)
1914d93b8cdSEnrico Granata         m_is_ref = m_type_flags.Test (ClangASTType::eTypeIsReference) ? eLazyBoolYes : eLazyBoolNo;
1924d93b8cdSEnrico Granata     return m_is_ref == eLazyBoolYes;
1934d93b8cdSEnrico Granata }
1944d93b8cdSEnrico Granata 
1954d93b8cdSEnrico Granata bool
1964d93b8cdSEnrico Granata ValueObjectPrinter::IsAggregate ()
1974d93b8cdSEnrico Granata {
1984d93b8cdSEnrico Granata     if (m_is_aggregate == eLazyBoolCalculate)
1994d93b8cdSEnrico Granata         m_is_aggregate = m_type_flags.Test (ClangASTType::eTypeHasChildren) ? eLazyBoolYes : eLazyBoolNo;
2004d93b8cdSEnrico Granata     return m_is_aggregate == eLazyBoolYes;
2014d93b8cdSEnrico Granata }
2024d93b8cdSEnrico Granata 
2034d93b8cdSEnrico Granata bool
2044d93b8cdSEnrico Granata ValueObjectPrinter::PrintLocationIfNeeded ()
2054d93b8cdSEnrico Granata {
2064d93b8cdSEnrico Granata     if (options.m_show_location)
2074d93b8cdSEnrico Granata     {
2084d93b8cdSEnrico Granata         m_stream->Printf("%s: ", m_valobj->GetLocationAsCString());
2094d93b8cdSEnrico Granata         return true;
2104d93b8cdSEnrico Granata     }
2114d93b8cdSEnrico Granata     return false;
2124d93b8cdSEnrico Granata }
2134d93b8cdSEnrico Granata 
2144d93b8cdSEnrico Granata bool
2154d93b8cdSEnrico Granata ValueObjectPrinter::PrintTypeIfNeeded ()
2164d93b8cdSEnrico Granata {
2174d93b8cdSEnrico Granata     bool show_type = true;
2184d93b8cdSEnrico Granata     // if we are at the root-level and been asked to hide the root's type, then hide it
2194d93b8cdSEnrico Granata     if (m_curr_depth == 0 && options.m_hide_root_type)
2204d93b8cdSEnrico Granata         show_type = false;
2214d93b8cdSEnrico Granata     else
2224d93b8cdSEnrico Granata         // otherwise decide according to the usual rules (asked to show types - always at the root level)
2234d93b8cdSEnrico Granata         show_type = options.m_show_types || (m_curr_depth == 0 && !options.m_flat_output);
2244d93b8cdSEnrico Granata 
2254d93b8cdSEnrico Granata     if (show_type)
2264d93b8cdSEnrico Granata     {
2274d93b8cdSEnrico Granata         // Some ValueObjects don't have types (like registers sets). Only print
2284d93b8cdSEnrico Granata         // the type if there is one to print
229e8daa2f8SEnrico Granata         ConstString qualified_type_name;
230e8daa2f8SEnrico Granata         if (options.m_be_raw)
231e8daa2f8SEnrico Granata             qualified_type_name = m_valobj->GetQualifiedTypeName();
232e8daa2f8SEnrico Granata         else
233e8daa2f8SEnrico Granata             qualified_type_name = m_valobj->GetDisplayTypeName();
2344d93b8cdSEnrico Granata         if (qualified_type_name)
2354d93b8cdSEnrico Granata             m_stream->Printf("(%s) ", qualified_type_name.GetCString());
2364d93b8cdSEnrico Granata         else
2374d93b8cdSEnrico Granata             show_type = false;
2384d93b8cdSEnrico Granata     }
2394d93b8cdSEnrico Granata     return show_type;
2404d93b8cdSEnrico Granata }
2414d93b8cdSEnrico Granata 
2424d93b8cdSEnrico Granata bool
2434d93b8cdSEnrico Granata ValueObjectPrinter::PrintNameIfNeeded (bool show_type)
2444d93b8cdSEnrico Granata {
2454d93b8cdSEnrico Granata     if (options.m_flat_output)
2464d93b8cdSEnrico Granata     {
2474d93b8cdSEnrico Granata         // If we are showing types, also qualify the C++ base classes
2484d93b8cdSEnrico Granata         const bool qualify_cxx_base_classes = show_type;
2494d93b8cdSEnrico Granata         if (!options.m_hide_name)
2504d93b8cdSEnrico Granata         {
2514d93b8cdSEnrico Granata             m_valobj->GetExpressionPath(*m_stream, qualify_cxx_base_classes);
2524d93b8cdSEnrico Granata             m_stream->PutCString(" =");
2534d93b8cdSEnrico Granata             return true;
2544d93b8cdSEnrico Granata         }
2554d93b8cdSEnrico Granata     }
2564d93b8cdSEnrico Granata     else if (!options.m_hide_name)
2574d93b8cdSEnrico Granata     {
2584d93b8cdSEnrico Granata         const char *name_cstr = GetRootNameForDisplay("");
2594d93b8cdSEnrico Granata         m_stream->Printf ("%s =", name_cstr);
2604d93b8cdSEnrico Granata         return true;
2614d93b8cdSEnrico Granata     }
2624d93b8cdSEnrico Granata     return false;
2634d93b8cdSEnrico Granata }
2644d93b8cdSEnrico Granata 
2654d93b8cdSEnrico Granata bool
2664d93b8cdSEnrico Granata ValueObjectPrinter::CheckScopeIfNeeded ()
2674d93b8cdSEnrico Granata {
2684d93b8cdSEnrico Granata     if (options.m_scope_already_checked)
2694d93b8cdSEnrico Granata         return true;
2704d93b8cdSEnrico Granata     return m_valobj->IsInScope();
2714d93b8cdSEnrico Granata }
2724d93b8cdSEnrico Granata 
2734d93b8cdSEnrico Granata TypeSummaryImpl*
2744d93b8cdSEnrico Granata ValueObjectPrinter::GetSummaryFormatter ()
2754d93b8cdSEnrico Granata {
2764d93b8cdSEnrico Granata     if (m_summary_formatter.second == false)
2774d93b8cdSEnrico Granata     {
2784d93b8cdSEnrico Granata         TypeSummaryImpl* entry = options.m_summary_sp ? options.m_summary_sp.get() : m_valobj->GetSummaryFormat().get();
2794d93b8cdSEnrico Granata 
2804d93b8cdSEnrico Granata         if (options.m_omit_summary_depth > 0)
2814d93b8cdSEnrico Granata             entry = NULL;
2824d93b8cdSEnrico Granata         m_summary_formatter.first = entry;
2834d93b8cdSEnrico Granata         m_summary_formatter.second = true;
2844d93b8cdSEnrico Granata     }
2854d93b8cdSEnrico Granata     return m_summary_formatter.first;
2864d93b8cdSEnrico Granata }
2874d93b8cdSEnrico Granata 
2884d93b8cdSEnrico Granata void
2894d93b8cdSEnrico Granata ValueObjectPrinter::GetValueSummaryError (std::string& value,
2904d93b8cdSEnrico Granata                                           std::string& summary,
2914d93b8cdSEnrico Granata                                           std::string& error)
2924d93b8cdSEnrico Granata {
293465f4bc2SEnrico Granata     if (options.m_format != eFormatDefault && options.m_format != m_valobj->GetFormat())
2944d93b8cdSEnrico Granata     {
295465f4bc2SEnrico Granata         m_valobj->GetValueAsCString(options.m_format,
296465f4bc2SEnrico Granata                                     value);
2974d93b8cdSEnrico Granata     }
298465f4bc2SEnrico Granata     else
299465f4bc2SEnrico Granata     {
3004d93b8cdSEnrico Granata         const char* val_cstr = m_valobj->GetValueAsCString();
301465f4bc2SEnrico Granata         if (val_cstr)
302465f4bc2SEnrico Granata             value.assign(val_cstr);
303465f4bc2SEnrico Granata     }
3044d93b8cdSEnrico Granata     const char* err_cstr = m_valobj->GetError().AsCString();
3054d93b8cdSEnrico Granata     if (err_cstr)
3064d93b8cdSEnrico Granata         error.assign(err_cstr);
3074d93b8cdSEnrico Granata 
3084d93b8cdSEnrico Granata     if (ShouldPrintValueObject())
3094d93b8cdSEnrico Granata     {
3104d93b8cdSEnrico Granata         if (IsNil())
3114d93b8cdSEnrico Granata             summary.assign("nil");
3124d93b8cdSEnrico Granata         else if (options.m_omit_summary_depth == 0)
3134d93b8cdSEnrico Granata         {
3144d93b8cdSEnrico Granata             TypeSummaryImpl* entry = GetSummaryFormatter();
3154d93b8cdSEnrico Granata             if (entry)
3164d93b8cdSEnrico Granata                 m_valobj->GetSummaryAsCString(entry, summary);
3174d93b8cdSEnrico Granata             else
3184d93b8cdSEnrico Granata             {
3194d93b8cdSEnrico Granata                 const char* sum_cstr = m_valobj->GetSummaryAsCString();
3204d93b8cdSEnrico Granata                 if (sum_cstr)
3214d93b8cdSEnrico Granata                     summary.assign(sum_cstr);
3224d93b8cdSEnrico Granata             }
3234d93b8cdSEnrico Granata         }
3244d93b8cdSEnrico Granata     }
3254d93b8cdSEnrico Granata }
3264d93b8cdSEnrico Granata 
3274d93b8cdSEnrico Granata bool
3284d93b8cdSEnrico Granata ValueObjectPrinter::PrintValueAndSummaryIfNeeded (bool& value_printed,
3294d93b8cdSEnrico Granata                                                   bool& summary_printed)
3304d93b8cdSEnrico Granata {
3314d93b8cdSEnrico Granata     bool error_printed = false;
3324d93b8cdSEnrico Granata     if (ShouldPrintValueObject())
3334d93b8cdSEnrico Granata     {
3344d93b8cdSEnrico Granata         if (!CheckScopeIfNeeded())
3354d93b8cdSEnrico Granata             m_error.assign("out of scope");
3364d93b8cdSEnrico Granata         if (m_error.empty())
3374d93b8cdSEnrico Granata         {
3384d93b8cdSEnrico Granata             GetValueSummaryError(m_value, m_summary, m_error);
3394d93b8cdSEnrico Granata         }
3404d93b8cdSEnrico Granata         if (m_error.size())
3414d93b8cdSEnrico Granata         {
3424d93b8cdSEnrico Granata             error_printed = true;
3434d93b8cdSEnrico Granata             m_stream->Printf (" <%s>\n", m_error.c_str());
3444d93b8cdSEnrico Granata         }
3454d93b8cdSEnrico Granata         else
3464d93b8cdSEnrico Granata         {
3474d93b8cdSEnrico Granata             // Make sure we have a value and make sure the summary didn't
3484d93b8cdSEnrico Granata             // specify that the value should not be printed - and do not print
3494d93b8cdSEnrico Granata             // the value if this thing is nil
3504d93b8cdSEnrico Granata             // (but show the value if the user passes a format explicitly)
3514d93b8cdSEnrico Granata             TypeSummaryImpl* entry = GetSummaryFormatter();
3528a068e6cSEnrico Granata             if (!IsNil() && !m_value.empty() && (entry == NULL || (entry->DoesPrintValue(m_valobj) || options.m_format != eFormatDefault) || m_summary.empty()) && !options.m_hide_value)
3534d93b8cdSEnrico Granata             {
3544d93b8cdSEnrico Granata                 m_stream->Printf(" %s", m_value.c_str());
3554d93b8cdSEnrico Granata                 value_printed = true;
3564d93b8cdSEnrico Granata             }
3574d93b8cdSEnrico Granata 
3584d93b8cdSEnrico Granata             if (m_summary.size())
3594d93b8cdSEnrico Granata             {
3604d93b8cdSEnrico Granata                 m_stream->Printf(" %s", m_summary.c_str());
3614d93b8cdSEnrico Granata                 summary_printed = true;
3624d93b8cdSEnrico Granata             }
3634d93b8cdSEnrico Granata         }
3644d93b8cdSEnrico Granata     }
3654d93b8cdSEnrico Granata     return !error_printed;
3664d93b8cdSEnrico Granata }
3674d93b8cdSEnrico Granata 
3684d93b8cdSEnrico Granata bool
3694d93b8cdSEnrico Granata ValueObjectPrinter::PrintObjectDescriptionIfNeeded (bool value_printed,
3704d93b8cdSEnrico Granata                                                     bool summary_printed)
3714d93b8cdSEnrico Granata {
3724d93b8cdSEnrico Granata     if (ShouldPrintValueObject())
3734d93b8cdSEnrico Granata     {
3744d93b8cdSEnrico Granata         // let's avoid the overly verbose no description error for a nil thing
3754d93b8cdSEnrico Granata         if (options.m_use_objc && !IsNil())
3764d93b8cdSEnrico Granata         {
3774d93b8cdSEnrico Granata             if (!options.m_hide_value || !options.m_hide_name)
3784d93b8cdSEnrico Granata                 m_stream->Printf(" ");
3794d93b8cdSEnrico Granata             const char *object_desc = nullptr;
3804d93b8cdSEnrico Granata             if (value_printed || summary_printed)
3814d93b8cdSEnrico Granata                 object_desc = m_valobj->GetObjectDescription();
3824d93b8cdSEnrico Granata             else
3834d93b8cdSEnrico Granata                 object_desc = GetDescriptionForDisplay();
3844d93b8cdSEnrico Granata             if (object_desc && *object_desc)
3854d93b8cdSEnrico Granata             {
3864d93b8cdSEnrico Granata                 m_stream->Printf("%s\n", object_desc);
3874d93b8cdSEnrico Granata                 return true;
3884d93b8cdSEnrico Granata             }
3894d93b8cdSEnrico Granata             else if (value_printed == false && summary_printed == false)
3904d93b8cdSEnrico Granata                 return true;
3914d93b8cdSEnrico Granata             else
3924d93b8cdSEnrico Granata                 return false;
3934d93b8cdSEnrico Granata         }
3944d93b8cdSEnrico Granata     }
3954d93b8cdSEnrico Granata     return true;
3964d93b8cdSEnrico Granata }
3974d93b8cdSEnrico Granata 
3984d93b8cdSEnrico Granata bool
3994d93b8cdSEnrico Granata ValueObjectPrinter::ShouldPrintChildren (bool is_failed_description,
4004d93b8cdSEnrico Granata                                          uint32_t& curr_ptr_depth)
4014d93b8cdSEnrico Granata {
4024d93b8cdSEnrico Granata     const bool is_ref = IsRef ();
4034d93b8cdSEnrico Granata     const bool is_ptr = IsPtr ();
4044d93b8cdSEnrico Granata 
4054d93b8cdSEnrico Granata     if (is_failed_description || m_curr_depth < options.m_max_depth)
4064d93b8cdSEnrico Granata     {
4074d93b8cdSEnrico Granata         // We will show children for all concrete types. We won't show
4084d93b8cdSEnrico Granata         // pointer contents unless a pointer depth has been specified.
4094d93b8cdSEnrico Granata         // We won't reference contents unless the reference is the
4104d93b8cdSEnrico Granata         // root object (depth of zero).
4114d93b8cdSEnrico Granata 
4124d93b8cdSEnrico Granata         // Use a new temporary pointer depth in case we override the
4134d93b8cdSEnrico Granata         // current pointer depth below...
4144d93b8cdSEnrico Granata 
4154d93b8cdSEnrico Granata         if (is_ptr || is_ref)
4164d93b8cdSEnrico Granata         {
4174d93b8cdSEnrico Granata             // We have a pointer or reference whose value is an address.
4184d93b8cdSEnrico Granata             // Make sure that address is not NULL
4194d93b8cdSEnrico Granata             AddressType ptr_address_type;
4204d93b8cdSEnrico Granata             if (m_valobj->GetPointerValue (&ptr_address_type) == 0)
4214d93b8cdSEnrico Granata                 return false;
4224d93b8cdSEnrico Granata 
4235000ee16SEnrico Granata             else if (is_ref && m_curr_depth == 0 && curr_ptr_depth == 0)
4244d93b8cdSEnrico Granata             {
4254d93b8cdSEnrico Granata                 // If this is the root object (depth is zero) that we are showing
4264d93b8cdSEnrico Granata                 // and it is a reference, and no pointer depth has been supplied
4274d93b8cdSEnrico Granata                 // print out what it references. Don't do this at deeper depths
4284d93b8cdSEnrico Granata                 // otherwise we can end up with infinite recursion...
4294d93b8cdSEnrico Granata                 curr_ptr_depth = 1;
4304d93b8cdSEnrico Granata             }
4314d93b8cdSEnrico Granata 
432fcf0c4e3SEnrico Granata             return (curr_ptr_depth > 0);
4334d93b8cdSEnrico Granata         }
4344d93b8cdSEnrico Granata 
4354d93b8cdSEnrico Granata         TypeSummaryImpl* entry = GetSummaryFormatter();
4364d93b8cdSEnrico Granata 
4378a068e6cSEnrico Granata         return (!entry || entry->DoesPrintChildren(m_valobj) || m_summary.empty());
4384d93b8cdSEnrico Granata     }
4394d93b8cdSEnrico Granata     return false;
4404d93b8cdSEnrico Granata }
4414d93b8cdSEnrico Granata 
4424d93b8cdSEnrico Granata ValueObject*
4434d93b8cdSEnrico Granata ValueObjectPrinter::GetValueObjectForChildrenGeneration ()
4444d93b8cdSEnrico Granata {
4454d93b8cdSEnrico Granata     ValueObjectSP synth_valobj_sp = m_valobj->GetSyntheticValue (options.m_use_synthetic);
4464d93b8cdSEnrico Granata     return (synth_valobj_sp ? synth_valobj_sp.get() : m_valobj);
4474d93b8cdSEnrico Granata }
4484d93b8cdSEnrico Granata 
4494d93b8cdSEnrico Granata void
4504d93b8cdSEnrico Granata ValueObjectPrinter::PrintChildrenPreamble ()
4514d93b8cdSEnrico Granata {
4524d93b8cdSEnrico Granata     if (options.m_flat_output)
4534d93b8cdSEnrico Granata     {
4544d93b8cdSEnrico Granata         if (ShouldPrintValueObject())
4554d93b8cdSEnrico Granata             m_stream->EOL();
4564d93b8cdSEnrico Granata     }
4574d93b8cdSEnrico Granata     else
4584d93b8cdSEnrico Granata     {
4594d93b8cdSEnrico Granata         if (ShouldPrintValueObject())
4604d93b8cdSEnrico Granata             m_stream->PutCString(IsRef () ? ": {\n" : " {\n");
4614d93b8cdSEnrico Granata         m_stream->IndentMore();
4624d93b8cdSEnrico Granata     }
4634d93b8cdSEnrico Granata }
4644d93b8cdSEnrico Granata 
4654d93b8cdSEnrico Granata void
4664d93b8cdSEnrico Granata ValueObjectPrinter::PrintChild (ValueObjectSP child_sp,
4674d93b8cdSEnrico Granata                                 uint32_t curr_ptr_depth)
4684d93b8cdSEnrico Granata {
4694d93b8cdSEnrico Granata     DumpValueObjectOptions child_options(options);
4704d93b8cdSEnrico Granata     child_options.SetFormat(options.m_format).SetSummary().SetRootValueObjectName();
4714d93b8cdSEnrico Granata     child_options.SetScopeChecked(true).SetHideName(options.m_hide_name).SetHideValue(options.m_hide_value)
4724d93b8cdSEnrico Granata     .SetOmitSummaryDepth(child_options.m_omit_summary_depth > 1 ? child_options.m_omit_summary_depth - 1 : 0);
4734d93b8cdSEnrico Granata     if (child_sp.get())
4744d93b8cdSEnrico Granata     {
4754d93b8cdSEnrico Granata         ValueObjectPrinter child_printer(child_sp.get(),
4764d93b8cdSEnrico Granata                                          m_stream,
4774d93b8cdSEnrico Granata                                          child_options,
4785000ee16SEnrico Granata                                          (IsPtr() || IsRef()) && curr_ptr_depth >= 1 ? curr_ptr_depth - 1 : curr_ptr_depth,
4794d93b8cdSEnrico Granata                                          m_curr_depth + 1);
4804d93b8cdSEnrico Granata         child_printer.PrintValueObject();
4814d93b8cdSEnrico Granata     }
4824d93b8cdSEnrico Granata 
4834d93b8cdSEnrico Granata }
4844d93b8cdSEnrico Granata 
4854d93b8cdSEnrico Granata uint32_t
4864d93b8cdSEnrico Granata ValueObjectPrinter::GetMaxNumChildrenToPrint (bool& print_dotdotdot)
4874d93b8cdSEnrico Granata {
4884d93b8cdSEnrico Granata     ValueObject* synth_m_valobj = GetValueObjectForChildrenGeneration();
4894d93b8cdSEnrico Granata 
4904d93b8cdSEnrico Granata     size_t num_children = synth_m_valobj->GetNumChildren();
4914d93b8cdSEnrico Granata     print_dotdotdot = false;
4924d93b8cdSEnrico Granata     if (num_children)
4934d93b8cdSEnrico Granata     {
4944d93b8cdSEnrico Granata         const size_t max_num_children = m_valobj->GetTargetSP()->GetMaximumNumberOfChildrenToDisplay();
4954d93b8cdSEnrico Granata 
4964d93b8cdSEnrico Granata         if (num_children > max_num_children && !options.m_ignore_cap)
4974d93b8cdSEnrico Granata         {
4984d93b8cdSEnrico Granata             print_dotdotdot = true;
4994d93b8cdSEnrico Granata             return max_num_children;
5004d93b8cdSEnrico Granata         }
5014d93b8cdSEnrico Granata     }
5024d93b8cdSEnrico Granata     return num_children;
5034d93b8cdSEnrico Granata }
5044d93b8cdSEnrico Granata 
5054d93b8cdSEnrico Granata void
5064d93b8cdSEnrico Granata ValueObjectPrinter::PrintChildrenPostamble (bool print_dotdotdot)
5074d93b8cdSEnrico Granata {
5084d93b8cdSEnrico Granata     if (!options.m_flat_output)
5094d93b8cdSEnrico Granata     {
5104d93b8cdSEnrico Granata         if (print_dotdotdot)
5114d93b8cdSEnrico Granata         {
5124d93b8cdSEnrico Granata             m_valobj->GetTargetSP()->GetDebugger().GetCommandInterpreter().ChildrenTruncated();
5134d93b8cdSEnrico Granata             m_stream->Indent("...\n");
5144d93b8cdSEnrico Granata         }
5154d93b8cdSEnrico Granata         m_stream->IndentLess();
5164d93b8cdSEnrico Granata         m_stream->Indent("}\n");
5174d93b8cdSEnrico Granata     }
5184d93b8cdSEnrico Granata }
5194d93b8cdSEnrico Granata 
5204d93b8cdSEnrico Granata void
5214d93b8cdSEnrico Granata ValueObjectPrinter::PrintChildren (uint32_t curr_ptr_depth)
5224d93b8cdSEnrico Granata {
5234d93b8cdSEnrico Granata     ValueObject* synth_m_valobj = GetValueObjectForChildrenGeneration();
5244d93b8cdSEnrico Granata 
5254d93b8cdSEnrico Granata     bool print_dotdotdot = false;
5264d93b8cdSEnrico Granata     size_t num_children = GetMaxNumChildrenToPrint(print_dotdotdot);
5274d93b8cdSEnrico Granata     if (num_children)
5284d93b8cdSEnrico Granata     {
5294d93b8cdSEnrico Granata         PrintChildrenPreamble ();
5304d93b8cdSEnrico Granata 
5314d93b8cdSEnrico Granata         for (size_t idx=0; idx<num_children; ++idx)
5324d93b8cdSEnrico Granata         {
5334d93b8cdSEnrico Granata             ValueObjectSP child_sp(synth_m_valobj->GetChildAtIndex(idx, true));
5344d93b8cdSEnrico Granata             PrintChild (child_sp, curr_ptr_depth);
5354d93b8cdSEnrico Granata         }
5364d93b8cdSEnrico Granata 
5374d93b8cdSEnrico Granata         PrintChildrenPostamble (print_dotdotdot);
5384d93b8cdSEnrico Granata     }
5394d93b8cdSEnrico Granata     else if (IsAggregate())
5404d93b8cdSEnrico Granata     {
5414d93b8cdSEnrico Granata         // Aggregate, no children...
5424d93b8cdSEnrico Granata         if (ShouldPrintValueObject())
5434d93b8cdSEnrico Granata             m_stream->PutCString(" {}\n");
5444d93b8cdSEnrico Granata     }
5454d93b8cdSEnrico Granata     else
5464d93b8cdSEnrico Granata     {
5474d93b8cdSEnrico Granata         if (ShouldPrintValueObject())
5484d93b8cdSEnrico Granata             m_stream->EOL();
5494d93b8cdSEnrico Granata     }
5504d93b8cdSEnrico Granata }
5514d93b8cdSEnrico Granata 
552a29cb0baSEnrico Granata bool
553a29cb0baSEnrico Granata ValueObjectPrinter::PrintChildrenOneLiner (bool hide_names)
554a29cb0baSEnrico Granata {
555a29cb0baSEnrico Granata     if (!GetDynamicValueIfNeeded () || m_valobj == nullptr)
556a29cb0baSEnrico Granata         return false;
557a29cb0baSEnrico Granata 
558a29cb0baSEnrico Granata     ValueObject* synth_m_valobj = GetValueObjectForChildrenGeneration();
559a29cb0baSEnrico Granata 
560a29cb0baSEnrico Granata     bool print_dotdotdot = false;
561a29cb0baSEnrico Granata     size_t num_children = GetMaxNumChildrenToPrint(print_dotdotdot);
562a29cb0baSEnrico Granata 
563a29cb0baSEnrico Granata     if (num_children)
564a29cb0baSEnrico Granata     {
565a29cb0baSEnrico Granata         m_stream->PutChar('(');
566a29cb0baSEnrico Granata 
567a29cb0baSEnrico Granata         for (uint32_t idx=0; idx<num_children; ++idx)
568a29cb0baSEnrico Granata         {
569a29cb0baSEnrico Granata             lldb::ValueObjectSP child_sp(synth_m_valobj->GetChildAtIndex(idx, true));
570a29cb0baSEnrico Granata             lldb::ValueObjectSP child_dyn_sp = child_sp.get() ? child_sp->GetDynamicValue(options.m_use_dynamic) : child_sp;
571a29cb0baSEnrico Granata             if (child_dyn_sp)
572a29cb0baSEnrico Granata                 child_sp = child_dyn_sp;
573a29cb0baSEnrico Granata             if (child_sp)
574a29cb0baSEnrico Granata             {
575a29cb0baSEnrico Granata                 if (idx)
576a29cb0baSEnrico Granata                     m_stream->PutCString(", ");
577a29cb0baSEnrico Granata                 if (!hide_names)
578a29cb0baSEnrico Granata                 {
579a29cb0baSEnrico Granata                     const char* name = child_sp.get()->GetName().AsCString();
580a29cb0baSEnrico Granata                     if (name && *name)
581a29cb0baSEnrico Granata                     {
582a29cb0baSEnrico Granata                         m_stream->PutCString(name);
583a29cb0baSEnrico Granata                         m_stream->PutCString(" = ");
584a29cb0baSEnrico Granata                     }
585a29cb0baSEnrico Granata                 }
586a29cb0baSEnrico Granata                 child_sp->DumpPrintableRepresentation(*m_stream,
587a29cb0baSEnrico Granata                                                       ValueObject::eValueObjectRepresentationStyleSummary,
588a29cb0baSEnrico Granata                                                       lldb::eFormatInvalid,
589a29cb0baSEnrico Granata                                                       ValueObject::ePrintableRepresentationSpecialCasesDisable);
590a29cb0baSEnrico Granata             }
591a29cb0baSEnrico Granata         }
592a29cb0baSEnrico Granata 
593a29cb0baSEnrico Granata         if (print_dotdotdot)
594a29cb0baSEnrico Granata             m_stream->PutCString(", ...)");
595a29cb0baSEnrico Granata         else
596a29cb0baSEnrico Granata             m_stream->PutChar(')');
597a29cb0baSEnrico Granata     }
598a29cb0baSEnrico Granata     return true;
599a29cb0baSEnrico Granata }
600a29cb0baSEnrico Granata 
6014d93b8cdSEnrico Granata void
6024d93b8cdSEnrico Granata ValueObjectPrinter::PrintChildrenIfNeeded (bool value_printed,
6034d93b8cdSEnrico Granata                                            bool summary_printed)
6044d93b8cdSEnrico Granata {
6054d93b8cdSEnrico Granata     // this flag controls whether we tried to display a description for this object and failed
6064d93b8cdSEnrico Granata     // if that happens, we want to display the children, if any
6074d93b8cdSEnrico Granata     bool is_failed_description = !PrintObjectDescriptionIfNeeded(value_printed, summary_printed);
6084d93b8cdSEnrico Granata 
6094d93b8cdSEnrico Granata     uint32_t curr_ptr_depth = m_ptr_depth;
6104d93b8cdSEnrico Granata     bool print_children = ShouldPrintChildren (is_failed_description,curr_ptr_depth);
61141b16533SEnrico Granata     bool print_oneline = (curr_ptr_depth > 0 || options.m_show_types || options.m_be_raw) ? false : DataVisualization::ShouldPrintAsOneLiner(*m_valobj);
6124d93b8cdSEnrico Granata 
6134d93b8cdSEnrico Granata     if (print_children)
6144d93b8cdSEnrico Granata     {
615a29cb0baSEnrico Granata         if (print_oneline)
616a29cb0baSEnrico Granata         {
617a29cb0baSEnrico Granata             m_stream->PutChar(' ');
618a29cb0baSEnrico Granata             PrintChildrenOneLiner (false);
619a29cb0baSEnrico Granata             m_stream->EOL();
620a29cb0baSEnrico Granata         }
621a29cb0baSEnrico Granata         else
6224d93b8cdSEnrico Granata             PrintChildren (curr_ptr_depth);
6234d93b8cdSEnrico Granata     }
6244d93b8cdSEnrico Granata     else if (m_curr_depth >= options.m_max_depth && IsAggregate() && ShouldPrintValueObject())
6254d93b8cdSEnrico Granata     {
6264d93b8cdSEnrico Granata             m_stream->PutCString("{...}\n");
6274d93b8cdSEnrico Granata     }
628245b3caaSEnrico Granata     else
629245b3caaSEnrico Granata         m_stream->EOL();
6304d93b8cdSEnrico Granata }
631*0f883ffbSEnrico Granata 
632*0f883ffbSEnrico Granata bool
633*0f883ffbSEnrico Granata ValueObjectPrinter::ShouldPrintValidation ()
634*0f883ffbSEnrico Granata {
635*0f883ffbSEnrico Granata     return options.m_run_validator;
636*0f883ffbSEnrico Granata }
637*0f883ffbSEnrico Granata 
638*0f883ffbSEnrico Granata bool
639*0f883ffbSEnrico Granata ValueObjectPrinter::PrintValidationMarkerIfNeeded ()
640*0f883ffbSEnrico Granata {
641*0f883ffbSEnrico Granata     if (!ShouldPrintValidation())
642*0f883ffbSEnrico Granata         return false;
643*0f883ffbSEnrico Granata 
644*0f883ffbSEnrico Granata     m_validation = m_valobj->GetValidationStatus();
645*0f883ffbSEnrico Granata 
646*0f883ffbSEnrico Granata     if (TypeValidatorResult::Failure == m_validation.first)
647*0f883ffbSEnrico Granata     {
648*0f883ffbSEnrico Granata         m_stream->Printf("! ");
649*0f883ffbSEnrico Granata         return true;
650*0f883ffbSEnrico Granata     }
651*0f883ffbSEnrico Granata 
652*0f883ffbSEnrico Granata     return false;
653*0f883ffbSEnrico Granata }
654*0f883ffbSEnrico Granata 
655*0f883ffbSEnrico Granata bool
656*0f883ffbSEnrico Granata ValueObjectPrinter::PrintValidationErrorIfNeeded ()
657*0f883ffbSEnrico Granata {
658*0f883ffbSEnrico Granata     if (!ShouldPrintValidation())
659*0f883ffbSEnrico Granata         return false;
660*0f883ffbSEnrico Granata 
661*0f883ffbSEnrico Granata     if (TypeValidatorResult::Success == m_validation.first)
662*0f883ffbSEnrico Granata         return false;
663*0f883ffbSEnrico Granata 
664*0f883ffbSEnrico Granata     if (m_validation.second.empty())
665*0f883ffbSEnrico Granata         m_validation.second.assign("unknown error");
666*0f883ffbSEnrico Granata 
667*0f883ffbSEnrico Granata     m_stream->Printf(" ! validation error: %s", m_validation.second.c_str());
668*0f883ffbSEnrico Granata     m_stream->EOL();
669*0f883ffbSEnrico Granata 
670*0f883ffbSEnrico Granata     return true;
671*0f883ffbSEnrico Granata }
672