1 //===-- TypeSynthetic.cpp -------------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
12 #include "lldb/lldb-enumerations.h"
13 #include "lldb/lldb-public.h"
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"
24 using namespace lldb_private
;
26 void TypeFilterImpl::AddExpressionPath(const std::string
&path
) {
27 bool need_add_dot
= true;
28 if (path
[0] == '.' || (path
[0] == '-' && path
[1] == '>') || path
[0] == '[')
30 // add a '.' symbol to help forgetful users
32 m_expression_paths
.push_back(path
);
34 m_expression_paths
.push_back(std::string(".") + path
);
37 bool TypeFilterImpl::SetExpressionPathAtIndex(size_t i
,
38 const std::string
&path
) {
41 bool need_add_dot
= true;
42 if (path
[0] == '.' || (path
[0] == '-' && path
[1] == '>') || path
[0] == '[')
44 // add a '.' symbol to help forgetful users
46 m_expression_paths
[i
] = path
;
48 m_expression_paths
[i
] = std::string(".") + path
;
53 TypeFilterImpl::FrontEnd::GetIndexOfChildWithName(ConstString name
) {
54 const char *name_cstr
= name
.GetCString();
56 for (size_t i
= 0; i
< filter
->GetCount(); i
++) {
57 const char *expr_cstr
= filter
->GetExpressionPathAtIndex(i
);
59 if (*expr_cstr
== '.')
61 else if (*expr_cstr
== '-' && *(expr_cstr
+ 1) == '>')
65 if (!::strcmp(name_cstr
, expr_cstr
))
73 std::string
TypeFilterImpl::GetDescription() {
75 sstr
.Printf("%s%s%s {\n", Cascades() ? "" : " (not cascading)",
76 SkipsPointers() ? " (skip pointers)" : "",
77 SkipsReferences() ? " (skip references)" : "");
79 for (size_t i
= 0; i
< GetCount(); i
++) {
80 sstr
.Printf(" %s\n", GetExpressionPathAtIndex(i
));
84 return std::string(sstr
.GetString());
87 SyntheticChildren::SyntheticChildren(const Flags
&flags
) : m_flags(flags
) {}
89 SyntheticChildren::~SyntheticChildren() = default;
91 CXXSyntheticChildren::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
: "") {}
97 CXXSyntheticChildren::~CXXSyntheticChildren() = default;
99 bool SyntheticChildren::IsScripted() { return false; }
101 std::string
SyntheticChildren::GetDescription() { return ""; }
103 SyntheticChildrenFrontEnd::AutoPointer
104 SyntheticChildren::GetFrontEnd(ValueObject
&backend
) {
108 std::string
CXXSyntheticChildren::GetDescription() {
110 sstr
.Printf("%s%s%s %s", Cascades() ? "" : " (not cascading)",
111 SkipsPointers() ? " (skip pointers)" : "",
112 SkipsReferences() ? " (skip references)" : "",
113 m_description
.c_str());
115 return std::string(sstr
.GetString());
119 SyntheticChildrenFrontEnd::CalculateNumChildrenIgnoringErrors(uint32_t max
) {
120 auto value_or_err
= CalculateNumChildren(max
);
122 return *value_or_err
;
123 LLDB_LOG_ERRORV(GetLog(LLDBLog::DataFormatters
), value_or_err
.takeError(),
128 lldb::ValueObjectSP
SyntheticChildrenFrontEnd::CreateValueObjectFromExpression(
129 llvm::StringRef name
, llvm::StringRef expression
,
130 const ExecutionContext
&exe_ctx
) {
131 ValueObjectSP
valobj_sp(
132 ValueObject::CreateValueObjectFromExpression(name
, expression
, exe_ctx
));
134 valobj_sp
->SetSyntheticChildrenGenerated(true);
138 lldb::ValueObjectSP
SyntheticChildrenFrontEnd::CreateValueObjectFromAddress(
139 llvm::StringRef name
, uint64_t address
, const ExecutionContext
&exe_ctx
,
141 ValueObjectSP
valobj_sp(
142 ValueObject::CreateValueObjectFromAddress(name
, address
, exe_ctx
, type
));
144 valobj_sp
->SetSyntheticChildrenGenerated(true);
148 lldb::ValueObjectSP
SyntheticChildrenFrontEnd::CreateValueObjectFromData(
149 llvm::StringRef name
, const DataExtractor
&data
,
150 const ExecutionContext
&exe_ctx
, CompilerType type
) {
151 ValueObjectSP
valobj_sp(
152 ValueObject::CreateValueObjectFromData(name
, data
, exe_ctx
, type
));
154 valobj_sp
->SetSyntheticChildrenGenerated(true);
158 ScriptedSyntheticChildren::FrontEnd::FrontEnd(std::string pclass
,
159 ValueObject
&backend
)
160 : SyntheticChildrenFrontEnd(backend
), m_python_class(pclass
),
161 m_wrapper_sp(), m_interpreter(nullptr) {
162 if (backend
.GetID() == LLDB_INVALID_UID
)
165 TargetSP target_sp
= backend
.GetTargetSP();
170 m_interpreter
= target_sp
->GetDebugger().GetScriptInterpreter();
172 if (m_interpreter
!= nullptr)
173 m_wrapper_sp
= m_interpreter
->CreateSyntheticScriptedProvider(
174 m_python_class
.c_str(), backend
.GetSP());
177 ScriptedSyntheticChildren::FrontEnd::~FrontEnd() = default;
180 ScriptedSyntheticChildren::FrontEnd::GetChildAtIndex(uint32_t idx
) {
181 if (!m_wrapper_sp
|| !m_interpreter
)
182 return lldb::ValueObjectSP();
184 return m_interpreter
->GetChildAtIndex(m_wrapper_sp
, idx
);
187 bool ScriptedSyntheticChildren::FrontEnd::IsValid() {
188 return (m_wrapper_sp
&& m_wrapper_sp
->IsValid() && m_interpreter
);
191 llvm::Expected
<uint32_t>
192 ScriptedSyntheticChildren::FrontEnd::CalculateNumChildren() {
193 if (!m_wrapper_sp
|| m_interpreter
== nullptr)
195 return m_interpreter
->CalculateNumChildren(m_wrapper_sp
, UINT32_MAX
);
198 llvm::Expected
<uint32_t>
199 ScriptedSyntheticChildren::FrontEnd::CalculateNumChildren(uint32_t max
) {
200 if (!m_wrapper_sp
|| m_interpreter
== nullptr)
202 return m_interpreter
->CalculateNumChildren(m_wrapper_sp
, max
);
205 lldb::ChildCacheState
ScriptedSyntheticChildren::FrontEnd::Update() {
206 if (!m_wrapper_sp
|| m_interpreter
== nullptr)
207 return lldb::ChildCacheState::eRefetch
;
209 return m_interpreter
->UpdateSynthProviderInstance(m_wrapper_sp
)
210 ? lldb::ChildCacheState::eReuse
211 : lldb::ChildCacheState::eRefetch
;
214 bool ScriptedSyntheticChildren::FrontEnd::MightHaveChildren() {
215 if (!m_wrapper_sp
|| m_interpreter
== nullptr)
218 return m_interpreter
->MightHaveChildrenSynthProviderInstance(m_wrapper_sp
);
221 size_t ScriptedSyntheticChildren::FrontEnd::GetIndexOfChildWithName(
223 if (!m_wrapper_sp
|| m_interpreter
== nullptr)
225 return m_interpreter
->GetIndexOfChildWithName(m_wrapper_sp
,
229 lldb::ValueObjectSP
ScriptedSyntheticChildren::FrontEnd::GetSyntheticValue() {
230 if (!m_wrapper_sp
|| m_interpreter
== nullptr)
233 return m_interpreter
->GetSyntheticValue(m_wrapper_sp
);
236 ConstString
ScriptedSyntheticChildren::FrontEnd::GetSyntheticTypeName() {
237 if (!m_wrapper_sp
|| m_interpreter
== nullptr)
238 return ConstString();
240 return m_interpreter
->GetSyntheticTypeName(m_wrapper_sp
);
243 std::string
ScriptedSyntheticChildren::GetDescription() {
245 sstr
.Printf("%s%s%s Python class %s", Cascades() ? "" : " (not cascading)",
246 SkipsPointers() ? " (skip pointers)" : "",
247 SkipsReferences() ? " (skip references)" : "",
248 m_python_class
.c_str());
250 return std::string(sstr
.GetString());