1//===-- TypeSummary.cpp ----------------------------------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "lldb/DataFormatters/TypeSummary.h"
10
11
12
13
14#include "lldb/lldb-enumerations.h"
15#include "lldb/lldb-public.h"
16
17#include "lldb/Core/Debugger.h"
18#include "lldb/Core/ValueObject.h"
19#include "lldb/DataFormatters/ValueObjectPrinter.h"
20#include "lldb/Interpreter/CommandInterpreter.h"
21#include "lldb/Symbol/CompilerType.h"
22#include "lldb/Target/StackFrame.h"
23#include "lldb/Target/Target.h"
24#include "lldb/Utility/StreamString.h"
25
26using namespace lldb;
27using namespace lldb_private;
28
29TypeSummaryOptions::TypeSummaryOptions()
30    : m_lang(eLanguageTypeUnknown), m_capping(eTypeSummaryCapped) {}
31
32lldb::LanguageType TypeSummaryOptions::GetLanguage() const { return m_lang; }
33
34lldb::TypeSummaryCapping TypeSummaryOptions::GetCapping() const {
35  return m_capping;
36}
37
38TypeSummaryOptions &TypeSummaryOptions::SetLanguage(lldb::LanguageType lang) {
39  m_lang = lang;
40  return *this;
41}
42
43TypeSummaryOptions &
44TypeSummaryOptions::SetCapping(lldb::TypeSummaryCapping cap) {
45  m_capping = cap;
46  return *this;
47}
48
49TypeSummaryImpl::TypeSummaryImpl(Kind kind, const TypeSummaryImpl::Flags &flags)
50    : m_flags(flags), m_kind(kind) {}
51
52StringSummaryFormat::StringSummaryFormat(const TypeSummaryImpl::Flags &flags,
53                                         const char *format_cstr)
54    : TypeSummaryImpl(Kind::eSummaryString, flags), m_format_str() {
55  SetSummaryString(format_cstr);
56}
57
58void StringSummaryFormat::SetSummaryString(const char *format_cstr) {
59  m_format.Clear();
60  if (format_cstr && format_cstr[0]) {
61    m_format_str = format_cstr;
62    m_error = FormatEntity::Parse(format_cstr, m_format);
63  } else {
64    m_format_str.clear();
65    m_error.Clear();
66  }
67}
68
69bool StringSummaryFormat::FormatObject(ValueObject *valobj, std::string &retval,
70                                       const TypeSummaryOptions &options) {
71  if (!valobj) {
72    retval.assign("NULL ValueObject");
73    return false;
74  }
75
76  StreamString s;
77  ExecutionContext exe_ctx(valobj->GetExecutionContextRef());
78  SymbolContext sc;
79  StackFrame *frame = exe_ctx.GetFramePtr();
80  if (frame)
81    sc = frame->GetSymbolContext(lldb::eSymbolContextEverything);
82
83  if (IsOneLiner()) {
84    ValueObjectPrinter printer(valobj, &s, DumpValueObjectOptions());
85    printer.PrintChildrenOneLiner(HideNames(valobj));
86    retval = s.GetString();
87    return true;
88  } else {
89    if (FormatEntity::Format(m_format, s, &sc, &exe_ctx,
90                             &sc.line_entry.range.GetBaseAddress(), valobj,
91                             false, false)) {
92      retval.assign(s.GetString());
93      return true;
94    } else {
95      retval.assign("error: summary string parsing error");
96      return false;
97    }
98  }
99}
100
101std::string StringSummaryFormat::GetDescription() {
102  StreamString sstr;
103
104  sstr.Printf("`%s`%s%s%s%s%s%s%s%s%s", m_format_str.c_str(),
105              m_error.Fail() ? " error: " : "",
106              m_error.Fail() ? m_error.AsCString() : "",
107              Cascades() ? "" : " (not cascading)",
108              !DoesPrintChildren(nullptr) ? "" : " (show children)",
109              !DoesPrintValue(nullptr) ? " (hide value)" : "",
110              IsOneLiner() ? " (one-line printout)" : "",
111              SkipsPointers() ? " (skip pointers)" : "",
112              SkipsReferences() ? " (skip references)" : "",
113              HideNames(nullptr) ? " (hide member names)" : "");
114  return sstr.GetString();
115}
116
117CXXFunctionSummaryFormat::CXXFunctionSummaryFormat(
118    const TypeSummaryImpl::Flags &flags, Callback impl, const char *description)
119    : TypeSummaryImpl(Kind::eCallback, flags), m_impl(impl),
120      m_description(description ? description : "") {}
121
122bool CXXFunctionSummaryFormat::FormatObject(ValueObject *valobj,
123                                            std::string &dest,
124                                            const TypeSummaryOptions &options) {
125  dest.clear();
126  StreamString stream;
127  if (!m_impl || !m_impl(*valobj, stream, options))
128    return false;
129  dest = stream.GetString();
130  return true;
131}
132
133std::string CXXFunctionSummaryFormat::GetDescription() {
134  StreamString sstr;
135  sstr.Printf("%s%s%s%s%s%s%s %s", Cascades() ? "" : " (not cascading)",
136              !DoesPrintChildren(nullptr) ? "" : " (show children)",
137              !DoesPrintValue(nullptr) ? " (hide value)" : "",
138              IsOneLiner() ? " (one-line printout)" : "",
139              SkipsPointers() ? " (skip pointers)" : "",
140              SkipsReferences() ? " (skip references)" : "",
141              HideNames(nullptr) ? " (hide member names)" : "",
142              m_description.c_str());
143  return sstr.GetString();
144}
145
146ScriptSummaryFormat::ScriptSummaryFormat(const TypeSummaryImpl::Flags &flags,
147                                         const char *function_name,
148                                         const char *python_script)
149    : TypeSummaryImpl(Kind::eScript, flags), m_function_name(),
150      m_python_script(), m_script_function_sp() {
151  if (function_name)
152    m_function_name.assign(function_name);
153  if (python_script)
154    m_python_script.assign(python_script);
155}
156
157bool ScriptSummaryFormat::FormatObject(ValueObject *valobj, std::string &retval,
158                                       const TypeSummaryOptions &options) {
159  if (!valobj)
160    return false;
161
162  TargetSP target_sp(valobj->GetTargetSP());
163
164  if (!target_sp) {
165    retval.assign("error: no target");
166    return false;
167  }
168
169  ScriptInterpreter *script_interpreter =
170      target_sp->GetDebugger().GetScriptInterpreter();
171
172  if (!script_interpreter) {
173    retval.assign("error: no ScriptInterpreter");
174    return false;
175  }
176
177  return script_interpreter->GetScriptedSummary(
178      m_function_name.c_str(), valobj->GetSP(), m_script_function_sp, options,
179      retval);
180}
181
182std::string ScriptSummaryFormat::GetDescription() {
183  StreamString sstr;
184  sstr.Printf("%s%s%s%s%s%s%s\n  ", Cascades() ? "" : " (not cascading)",
185              !DoesPrintChildren(nullptr) ? "" : " (show children)",
186              !DoesPrintValue(nullptr) ? " (hide value)" : "",
187              IsOneLiner() ? " (one-line printout)" : "",
188              SkipsPointers() ? " (skip pointers)" : "",
189              SkipsReferences() ? " (skip references)" : "",
190              HideNames(nullptr) ? " (hide member names)" : "");
191  if (m_python_script.empty()) {
192    if (m_function_name.empty()) {
193      sstr.PutCString("no backing script");
194    } else {
195      sstr.PutCString(m_function_name);
196    }
197  } else {
198    sstr.PutCString(m_python_script);
199  }
200  return sstr.GetString();
201}
202