1//===-- TypeSynthetic.cpp -------------------------------------------------===//
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
10
11
12#include "lldb/lldb-enumerations.h"
13#include "lldb/lldb-public.h"
14
15#include "lldb/Core/Debugger.h"
16#include "lldb/DataFormatters/TypeSynthetic.h"
17#include "lldb/Interpreter/CommandInterpreter.h"
18#include "lldb/Interpreter/ScriptInterpreter.h"
19#include "lldb/Symbol/CompilerType.h"
20#include "lldb/Target/Target.h"
21#include "lldb/Utility/StreamString.h"
22
23using namespace lldb;
24using namespace lldb_private;
25
26void TypeFilterImpl::AddExpressionPath(const std::string &path) {
27  bool need_add_dot = true;
28  if (path[0] == '.' || (path[0] == '-' && path[1] == '>') || path[0] == '[')
29    need_add_dot = false;
30  // add a '.' symbol to help forgetful users
31  if (!need_add_dot)
32    m_expression_paths.push_back(path);
33  else
34    m_expression_paths.push_back(std::string(".") + path);
35}
36
37bool TypeFilterImpl::SetExpressionPathAtIndex(size_t i,
38                                              const std::string &path) {
39  if (i >= GetCount())
40    return false;
41  bool need_add_dot = true;
42  if (path[0] == '.' || (path[0] == '-' && path[1] == '>') || path[0] == '[')
43    need_add_dot = false;
44  // add a '.' symbol to help forgetful users
45  if (!need_add_dot)
46    m_expression_paths[i] = path;
47  else
48    m_expression_paths[i] = std::string(".") + path;
49  return true;
50}
51
52size_t
53TypeFilterImpl::FrontEnd::GetIndexOfChildWithName(ConstString name) {
54  const char *name_cstr = name.GetCString();
55  if (name_cstr) {
56    for (size_t i = 0; i < filter->GetCount(); i++) {
57      const char *expr_cstr = filter->GetExpressionPathAtIndex(i);
58      if (expr_cstr) {
59        if (*expr_cstr == '.')
60          expr_cstr++;
61        else if (*expr_cstr == '-' && *(expr_cstr + 1) == '>')
62          expr_cstr += 2;
63      }
64      if (expr_cstr) {
65        if (!::strcmp(name_cstr, expr_cstr))
66          return i;
67      }
68    }
69  }
70  return UINT32_MAX;
71}
72
73std::string TypeFilterImpl::GetDescription() {
74  StreamString sstr;
75  sstr.Printf("%s%s%s {\n", Cascades() ? "" : " (not cascading)",
76              SkipsPointers() ? " (skip pointers)" : "",
77              SkipsReferences() ? " (skip references)" : "");
78
79  for (size_t i = 0; i < GetCount(); i++) {
80    sstr.Printf("    %s\n", GetExpressionPathAtIndex(i));
81  }
82
83  sstr.Printf("}");
84  return std::string(sstr.GetString());
85}
86
87SyntheticChildren::SyntheticChildren(const Flags &flags) : m_flags(flags) {}
88
89SyntheticChildren::~SyntheticChildren() = default;
90
91CXXSyntheticChildren::CXXSyntheticChildren(
92    const SyntheticChildren::Flags &flags, const char *description,
93    CreateFrontEndCallback callback)
94    : SyntheticChildren(flags), m_create_callback(std::move(callback)),
95      m_description(description ? description : "") {}
96
97CXXSyntheticChildren::~CXXSyntheticChildren() = default;
98
99bool SyntheticChildren::IsScripted() { return false; }
100
101std::string SyntheticChildren::GetDescription() { return ""; }
102
103SyntheticChildrenFrontEnd::AutoPointer
104SyntheticChildren::GetFrontEnd(ValueObject &backend) {
105  return nullptr;
106}
107
108std::string CXXSyntheticChildren::GetDescription() {
109  StreamString sstr;
110  sstr.Printf("%s%s%s %s", Cascades() ? "" : " (not cascading)",
111              SkipsPointers() ? " (skip pointers)" : "",
112              SkipsReferences() ? " (skip references)" : "",
113              m_description.c_str());
114
115  return std::string(sstr.GetString());
116}
117
118lldb::ValueObjectSP SyntheticChildrenFrontEnd::CreateValueObjectFromExpression(
119    llvm::StringRef name, llvm::StringRef expression,
120    const ExecutionContext &exe_ctx) {
121  ValueObjectSP valobj_sp(
122      ValueObject::CreateValueObjectFromExpression(name, expression, exe_ctx));
123  if (valobj_sp)
124    valobj_sp->SetSyntheticChildrenGenerated(true);
125  return valobj_sp;
126}
127
128lldb::ValueObjectSP SyntheticChildrenFrontEnd::CreateValueObjectFromAddress(
129    llvm::StringRef name, uint64_t address, const ExecutionContext &exe_ctx,
130    CompilerType type) {
131  ValueObjectSP valobj_sp(
132      ValueObject::CreateValueObjectFromAddress(name, address, exe_ctx, type));
133  if (valobj_sp)
134    valobj_sp->SetSyntheticChildrenGenerated(true);
135  return valobj_sp;
136}
137
138lldb::ValueObjectSP SyntheticChildrenFrontEnd::CreateValueObjectFromData(
139    llvm::StringRef name, const DataExtractor &data,
140    const ExecutionContext &exe_ctx, CompilerType type) {
141  ValueObjectSP valobj_sp(
142      ValueObject::CreateValueObjectFromData(name, data, exe_ctx, type));
143  if (valobj_sp)
144    valobj_sp->SetSyntheticChildrenGenerated(true);
145  return valobj_sp;
146}
147
148ScriptedSyntheticChildren::FrontEnd::FrontEnd(std::string pclass,
149                                              ValueObject &backend)
150    : SyntheticChildrenFrontEnd(backend), m_python_class(pclass),
151      m_wrapper_sp(), m_interpreter(nullptr) {
152  if (backend.GetID() == LLDB_INVALID_UID)
153    return;
154
155  TargetSP target_sp = backend.GetTargetSP();
156
157  if (!target_sp)
158    return;
159
160  m_interpreter = target_sp->GetDebugger().GetScriptInterpreter();
161
162  if (m_interpreter != nullptr)
163    m_wrapper_sp = m_interpreter->CreateSyntheticScriptedProvider(
164        m_python_class.c_str(), backend.GetSP());
165}
166
167ScriptedSyntheticChildren::FrontEnd::~FrontEnd() = default;
168
169lldb::ValueObjectSP
170ScriptedSyntheticChildren::FrontEnd::GetChildAtIndex(size_t idx) {
171  if (!m_wrapper_sp || !m_interpreter)
172    return lldb::ValueObjectSP();
173
174  return m_interpreter->GetChildAtIndex(m_wrapper_sp, idx);
175}
176
177bool ScriptedSyntheticChildren::FrontEnd::IsValid() {
178  return (m_wrapper_sp && m_wrapper_sp->IsValid() && m_interpreter);
179}
180
181size_t ScriptedSyntheticChildren::FrontEnd::CalculateNumChildren() {
182  if (!m_wrapper_sp || m_interpreter == nullptr)
183    return 0;
184  return m_interpreter->CalculateNumChildren(m_wrapper_sp, UINT32_MAX);
185}
186
187size_t ScriptedSyntheticChildren::FrontEnd::CalculateNumChildren(uint32_t max) {
188  if (!m_wrapper_sp || m_interpreter == nullptr)
189    return 0;
190  return m_interpreter->CalculateNumChildren(m_wrapper_sp, max);
191}
192
193bool ScriptedSyntheticChildren::FrontEnd::Update() {
194  if (!m_wrapper_sp || m_interpreter == nullptr)
195    return false;
196
197  return m_interpreter->UpdateSynthProviderInstance(m_wrapper_sp);
198}
199
200bool ScriptedSyntheticChildren::FrontEnd::MightHaveChildren() {
201  if (!m_wrapper_sp || m_interpreter == nullptr)
202    return false;
203
204  return m_interpreter->MightHaveChildrenSynthProviderInstance(m_wrapper_sp);
205}
206
207size_t ScriptedSyntheticChildren::FrontEnd::GetIndexOfChildWithName(
208    ConstString name) {
209  if (!m_wrapper_sp || m_interpreter == nullptr)
210    return UINT32_MAX;
211  return m_interpreter->GetIndexOfChildWithName(m_wrapper_sp,
212                                                name.GetCString());
213}
214
215lldb::ValueObjectSP ScriptedSyntheticChildren::FrontEnd::GetSyntheticValue() {
216  if (!m_wrapper_sp || m_interpreter == nullptr)
217    return nullptr;
218
219  return m_interpreter->GetSyntheticValue(m_wrapper_sp);
220}
221
222ConstString ScriptedSyntheticChildren::FrontEnd::GetSyntheticTypeName() {
223  if (!m_wrapper_sp || m_interpreter == nullptr)
224    return ConstString();
225
226  return m_interpreter->GetSyntheticTypeName(m_wrapper_sp);
227}
228
229std::string ScriptedSyntheticChildren::GetDescription() {
230  StreamString sstr;
231  sstr.Printf("%s%s%s Python class %s", Cascades() ? "" : " (not cascading)",
232              SkipsPointers() ? " (skip pointers)" : "",
233              SkipsReferences() ? " (skip references)" : "",
234              m_python_class.c_str());
235
236  return std::string(sstr.GetString());
237}
238