1 //===-- TypeSynthetic.h -----------------------------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #ifndef lldb_TypeSynthetic_h_
11 #define lldb_TypeSynthetic_h_
16 #include <initializer_list>
21 #include "lldb/lldb-enumerations.h"
22 #include "lldb/lldb-public.h"
24 #include "lldb/Core/ValueObject.h"
25 #include "lldb/Utility/StructuredData.h"
27 namespace lldb_private {
28 class SyntheticChildrenFrontEnd {
30 ValueObject &m_backend;
32 void SetValid(bool valid) { m_valid = valid; }
34 bool IsValid() { return m_valid; }
37 SyntheticChildrenFrontEnd(ValueObject &backend)
38 : m_backend(backend), m_valid(true) {}
40 virtual ~SyntheticChildrenFrontEnd() = default;
42 virtual size_t CalculateNumChildren() = 0;
44 virtual size_t CalculateNumChildren(uint32_t max) {
45 auto count = CalculateNumChildren();
46 return count <= max ? count : max;
49 virtual lldb::ValueObjectSP GetChildAtIndex(size_t idx) = 0;
51 virtual size_t GetIndexOfChildWithName(const ConstString &name) = 0;
53 // this function is assumed to always succeed and it if fails, the front-end
54 // should know to deal with it in the correct way (most probably, by refusing
55 // to return any children) the return value of Update() should actually be
56 // interpreted as "ValueObjectSyntheticFilter cache is good/bad" if =true,
57 // ValueObjectSyntheticFilter is allowed to use the children it fetched
58 // previously and cached if =false, ValueObjectSyntheticFilter must throw
59 // away its cache, and query again for children
60 virtual bool Update() = 0;
62 // if this function returns false, then CalculateNumChildren() MUST return 0
63 // since UI frontends might validly decide not to inquire for children given
64 // a false return value from this call if it returns true, then
65 // CalculateNumChildren() can return any number >= 0 (0 being valid) it
66 // should if at all possible be more efficient than CalculateNumChildren()
67 virtual bool MightHaveChildren() = 0;
69 // if this function returns a non-null ValueObject, then the returned
70 // ValueObject will stand for this ValueObject whenever a "value" request is
71 // made to this ValueObject
72 virtual lldb::ValueObjectSP GetSyntheticValue() { return nullptr; }
74 // if this function returns a non-empty ConstString, then clients are
75 // expected to use the return as the name of the type of this ValueObject for
77 virtual ConstString GetSyntheticTypeName() { return ConstString(); }
79 typedef std::shared_ptr<SyntheticChildrenFrontEnd> SharedPointer;
80 typedef std::unique_ptr<SyntheticChildrenFrontEnd> AutoPointer;
84 CreateValueObjectFromExpression(llvm::StringRef name,
85 llvm::StringRef expression,
86 const ExecutionContext &exe_ctx);
89 CreateValueObjectFromAddress(llvm::StringRef name, uint64_t address,
90 const ExecutionContext &exe_ctx,
93 lldb::ValueObjectSP CreateValueObjectFromData(llvm::StringRef name,
94 const DataExtractor &data,
95 const ExecutionContext &exe_ctx,
100 DISALLOW_COPY_AND_ASSIGN(SyntheticChildrenFrontEnd);
103 class SyntheticValueProviderFrontEnd : public SyntheticChildrenFrontEnd {
105 SyntheticValueProviderFrontEnd(ValueObject &backend)
106 : SyntheticChildrenFrontEnd(backend) {}
108 ~SyntheticValueProviderFrontEnd() override = default;
110 size_t CalculateNumChildren() override { return 0; }
112 lldb::ValueObjectSP GetChildAtIndex(size_t idx) override { return nullptr; }
114 size_t GetIndexOfChildWithName(const ConstString &name) override {
118 bool Update() override { return false; }
120 bool MightHaveChildren() override { return false; }
122 lldb::ValueObjectSP GetSyntheticValue() override = 0;
125 DISALLOW_COPY_AND_ASSIGN(SyntheticValueProviderFrontEnd);
128 class SyntheticChildren {
132 Flags() : m_flags(lldb::eTypeOptionCascade) {}
134 Flags(const Flags &other) : m_flags(other.m_flags) {}
136 Flags(uint32_t value) : m_flags(value) {}
138 Flags &operator=(const Flags &rhs) {
140 m_flags = rhs.m_flags;
145 Flags &operator=(const uint32_t &rhs) {
155 bool GetCascades() const {
156 return (m_flags & lldb::eTypeOptionCascade) == lldb::eTypeOptionCascade;
159 Flags &SetCascades(bool value = true) {
161 m_flags |= lldb::eTypeOptionCascade;
163 m_flags &= ~lldb::eTypeOptionCascade;
167 bool GetSkipPointers() const {
168 return (m_flags & lldb::eTypeOptionSkipPointers) ==
169 lldb::eTypeOptionSkipPointers;
172 Flags &SetSkipPointers(bool value = true) {
174 m_flags |= lldb::eTypeOptionSkipPointers;
176 m_flags &= ~lldb::eTypeOptionSkipPointers;
180 bool GetSkipReferences() const {
181 return (m_flags & lldb::eTypeOptionSkipReferences) ==
182 lldb::eTypeOptionSkipReferences;
185 Flags &SetSkipReferences(bool value = true) {
187 m_flags |= lldb::eTypeOptionSkipReferences;
189 m_flags &= ~lldb::eTypeOptionSkipReferences;
193 bool GetNonCacheable() const {
194 return (m_flags & lldb::eTypeOptionNonCacheable) ==
195 lldb::eTypeOptionNonCacheable;
198 Flags &SetNonCacheable(bool value = true) {
200 m_flags |= lldb::eTypeOptionNonCacheable;
202 m_flags &= ~lldb::eTypeOptionNonCacheable;
206 bool GetFrontEndWantsDereference() const {
207 return (m_flags & lldb::eTypeOptionFrontEndWantsDereference) ==
208 lldb::eTypeOptionFrontEndWantsDereference;
211 Flags &SetFrontEndWantsDereference(bool value = true) {
213 m_flags |= lldb::eTypeOptionFrontEndWantsDereference;
215 m_flags &= ~lldb::eTypeOptionFrontEndWantsDereference;
219 uint32_t GetValue() { return m_flags; }
221 void SetValue(uint32_t value) { m_flags = value; }
227 SyntheticChildren(const Flags &flags) : m_flags(flags) {}
229 virtual ~SyntheticChildren() = default;
231 bool Cascades() const { return m_flags.GetCascades(); }
233 bool SkipsPointers() const { return m_flags.GetSkipPointers(); }
235 bool SkipsReferences() const { return m_flags.GetSkipReferences(); }
237 bool NonCacheable() const { return m_flags.GetNonCacheable(); }
239 bool WantsDereference() const { return m_flags.GetFrontEndWantsDereference();}
241 void SetCascades(bool value) { m_flags.SetCascades(value); }
243 void SetSkipsPointers(bool value) { m_flags.SetSkipPointers(value); }
245 void SetSkipsReferences(bool value) { m_flags.SetSkipReferences(value); }
247 void SetNonCacheable(bool value) { m_flags.SetNonCacheable(value); }
249 uint32_t GetOptions() { return m_flags.GetValue(); }
251 void SetOptions(uint32_t value) { m_flags.SetValue(value); }
253 virtual bool IsScripted() = 0;
255 virtual std::string GetDescription() = 0;
257 virtual SyntheticChildrenFrontEnd::AutoPointer
258 GetFrontEnd(ValueObject &backend) = 0;
260 typedef std::shared_ptr<SyntheticChildren> SharedPointer;
262 uint32_t &GetRevision() { return m_my_revision; }
265 uint32_t m_my_revision;
269 DISALLOW_COPY_AND_ASSIGN(SyntheticChildren);
272 class TypeFilterImpl : public SyntheticChildren {
273 std::vector<std::string> m_expression_paths;
276 TypeFilterImpl(const SyntheticChildren::Flags &flags)
277 : SyntheticChildren(flags), m_expression_paths() {}
279 TypeFilterImpl(const SyntheticChildren::Flags &flags,
280 const std::initializer_list<const char *> items)
281 : SyntheticChildren(flags), m_expression_paths() {
282 for (auto path : items)
283 AddExpressionPath(path);
286 void AddExpressionPath(const char *path) {
287 AddExpressionPath(std::string(path));
290 void Clear() { m_expression_paths.clear(); }
292 size_t GetCount() const { return m_expression_paths.size(); }
294 const char *GetExpressionPathAtIndex(size_t i) const {
295 return m_expression_paths[i].c_str();
298 bool SetExpressionPathAtIndex(size_t i, const char *path) {
299 return SetExpressionPathAtIndex(i, std::string(path));
302 void AddExpressionPath(const std::string &path);
304 bool SetExpressionPathAtIndex(size_t i, const std::string &path);
306 bool IsScripted() override { return false; }
308 std::string GetDescription() override;
310 class FrontEnd : public SyntheticChildrenFrontEnd {
312 FrontEnd(TypeFilterImpl *flt, ValueObject &backend)
313 : SyntheticChildrenFrontEnd(backend), filter(flt) {}
315 ~FrontEnd() override = default;
317 size_t CalculateNumChildren() override { return filter->GetCount(); }
319 lldb::ValueObjectSP GetChildAtIndex(size_t idx) override {
320 if (idx >= filter->GetCount())
321 return lldb::ValueObjectSP();
322 return m_backend.GetSyntheticExpressionPathChild(
323 filter->GetExpressionPathAtIndex(idx), true);
326 bool Update() override { return false; }
328 bool MightHaveChildren() override { return filter->GetCount() > 0; }
330 size_t GetIndexOfChildWithName(const ConstString &name) override;
332 typedef std::shared_ptr<SyntheticChildrenFrontEnd> SharedPointer;
335 TypeFilterImpl *filter;
337 DISALLOW_COPY_AND_ASSIGN(FrontEnd);
340 SyntheticChildrenFrontEnd::AutoPointer
341 GetFrontEnd(ValueObject &backend) override {
342 return SyntheticChildrenFrontEnd::AutoPointer(new FrontEnd(this, backend));
345 typedef std::shared_ptr<TypeFilterImpl> SharedPointer;
348 DISALLOW_COPY_AND_ASSIGN(TypeFilterImpl);
351 class CXXSyntheticChildren : public SyntheticChildren {
353 typedef std::function<SyntheticChildrenFrontEnd *(CXXSyntheticChildren *,
354 lldb::ValueObjectSP)>
355 CreateFrontEndCallback;
356 CXXSyntheticChildren(const SyntheticChildren::Flags &flags,
357 const char *description, CreateFrontEndCallback callback)
358 : SyntheticChildren(flags), m_create_callback(callback),
359 m_description(description ? description : "") {}
361 bool IsScripted() override { return false; }
363 std::string GetDescription() override;
365 SyntheticChildrenFrontEnd::AutoPointer
366 GetFrontEnd(ValueObject &backend) override {
367 return SyntheticChildrenFrontEnd::AutoPointer(
368 m_create_callback(this, backend.GetSP()));
372 CreateFrontEndCallback m_create_callback;
373 std::string m_description;
376 DISALLOW_COPY_AND_ASSIGN(CXXSyntheticChildren);
379 #ifndef LLDB_DISABLE_PYTHON
381 class ScriptedSyntheticChildren : public SyntheticChildren {
382 std::string m_python_class;
383 std::string m_python_code;
386 ScriptedSyntheticChildren(const SyntheticChildren::Flags &flags,
387 const char *pclass, const char *pcode = nullptr)
388 : SyntheticChildren(flags), m_python_class(), m_python_code() {
390 m_python_class = pclass;
392 m_python_code = pcode;
395 const char *GetPythonClassName() { return m_python_class.c_str(); }
397 const char *GetPythonCode() { return m_python_code.c_str(); }
399 void SetPythonClassName(const char *fname) {
400 m_python_class.assign(fname);
401 m_python_code.clear();
404 void SetPythonCode(const char *script) { m_python_code.assign(script); }
406 std::string GetDescription() override;
408 bool IsScripted() override { return true; }
410 class FrontEnd : public SyntheticChildrenFrontEnd {
412 FrontEnd(std::string pclass, ValueObject &backend);
414 ~FrontEnd() override;
418 size_t CalculateNumChildren() override;
420 size_t CalculateNumChildren(uint32_t max) override;
422 lldb::ValueObjectSP GetChildAtIndex(size_t idx) override;
424 bool Update() override;
426 bool MightHaveChildren() override;
428 size_t GetIndexOfChildWithName(const ConstString &name) override;
430 lldb::ValueObjectSP GetSyntheticValue() override;
432 ConstString GetSyntheticTypeName() override;
434 typedef std::shared_ptr<SyntheticChildrenFrontEnd> SharedPointer;
437 std::string m_python_class;
438 StructuredData::ObjectSP m_wrapper_sp;
439 ScriptInterpreter *m_interpreter;
441 DISALLOW_COPY_AND_ASSIGN(FrontEnd);
444 SyntheticChildrenFrontEnd::AutoPointer
445 GetFrontEnd(ValueObject &backend) override {
446 auto synth_ptr = SyntheticChildrenFrontEnd::AutoPointer(
447 new FrontEnd(m_python_class, backend));
448 if (synth_ptr && ((FrontEnd *)synth_ptr.get())->IsValid())
454 DISALLOW_COPY_AND_ASSIGN(ScriptedSyntheticChildren);
457 } // namespace lldb_private
459 #endif // lldb_TypeSynthetic_h_