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_
18 #include <initializer_list>
23 // Other libraries and framework includes
25 #include "lldb/lldb-enumerations.h"
26 #include "lldb/lldb-public.h"
28 #include "lldb/Core/ValueObject.h"
29 #include "lldb/Utility/StructuredData.h"
31 namespace lldb_private {
32 class SyntheticChildrenFrontEnd {
34 ValueObject &m_backend;
36 void SetValid(bool valid) { m_valid = valid; }
38 bool IsValid() { return m_valid; }
41 SyntheticChildrenFrontEnd(ValueObject &backend)
42 : m_backend(backend), m_valid(true) {}
44 virtual ~SyntheticChildrenFrontEnd() = default;
46 virtual size_t CalculateNumChildren() = 0;
48 virtual size_t CalculateNumChildren(uint32_t max) {
49 auto count = CalculateNumChildren();
50 return count <= max ? count : max;
53 virtual lldb::ValueObjectSP GetChildAtIndex(size_t idx) = 0;
55 virtual size_t GetIndexOfChildWithName(const ConstString &name) = 0;
57 // this function is assumed to always succeed and it if fails, the front-end
58 // should know to deal with it in the correct way (most probably, by refusing
59 // to return any children) the return value of Update() should actually be
60 // interpreted as "ValueObjectSyntheticFilter cache is good/bad" if =true,
61 // ValueObjectSyntheticFilter is allowed to use the children it fetched
62 // previously and cached if =false, ValueObjectSyntheticFilter must throw
63 // away its cache, and query again for children
64 virtual bool Update() = 0;
66 // if this function returns false, then CalculateNumChildren() MUST return 0
67 // since UI frontends might validly decide not to inquire for children given
68 // a false return value from this call if it returns true, then
69 // CalculateNumChildren() can return any number >= 0 (0 being valid) it
70 // should if at all possible be more efficient than CalculateNumChildren()
71 virtual bool MightHaveChildren() = 0;
73 // if this function returns a non-null ValueObject, then the returned
74 // ValueObject will stand for this ValueObject whenever a "value" request is
75 // made to this ValueObject
76 virtual lldb::ValueObjectSP GetSyntheticValue() { return nullptr; }
78 // if this function returns a non-empty ConstString, then clients are
79 // expected to use the return as the name of the type of this ValueObject for
81 virtual ConstString GetSyntheticTypeName() { return ConstString(); }
83 typedef std::shared_ptr<SyntheticChildrenFrontEnd> SharedPointer;
84 typedef std::unique_ptr<SyntheticChildrenFrontEnd> AutoPointer;
88 CreateValueObjectFromExpression(llvm::StringRef name,
89 llvm::StringRef expression,
90 const ExecutionContext &exe_ctx);
93 CreateValueObjectFromAddress(llvm::StringRef name, uint64_t address,
94 const ExecutionContext &exe_ctx,
97 lldb::ValueObjectSP CreateValueObjectFromData(llvm::StringRef name,
98 const DataExtractor &data,
99 const ExecutionContext &exe_ctx,
104 DISALLOW_COPY_AND_ASSIGN(SyntheticChildrenFrontEnd);
107 class SyntheticValueProviderFrontEnd : public SyntheticChildrenFrontEnd {
109 SyntheticValueProviderFrontEnd(ValueObject &backend)
110 : SyntheticChildrenFrontEnd(backend) {}
112 ~SyntheticValueProviderFrontEnd() override = default;
114 size_t CalculateNumChildren() override { return 0; }
116 lldb::ValueObjectSP GetChildAtIndex(size_t idx) override { return nullptr; }
118 size_t GetIndexOfChildWithName(const ConstString &name) override {
122 bool Update() override { return false; }
124 bool MightHaveChildren() override { return false; }
126 lldb::ValueObjectSP GetSyntheticValue() override = 0;
129 DISALLOW_COPY_AND_ASSIGN(SyntheticValueProviderFrontEnd);
132 class SyntheticChildren {
136 Flags() : m_flags(lldb::eTypeOptionCascade) {}
138 Flags(const Flags &other) : m_flags(other.m_flags) {}
140 Flags(uint32_t value) : m_flags(value) {}
142 Flags &operator=(const Flags &rhs) {
144 m_flags = rhs.m_flags;
149 Flags &operator=(const uint32_t &rhs) {
159 bool GetCascades() const {
160 return (m_flags & lldb::eTypeOptionCascade) == lldb::eTypeOptionCascade;
163 Flags &SetCascades(bool value = true) {
165 m_flags |= lldb::eTypeOptionCascade;
167 m_flags &= ~lldb::eTypeOptionCascade;
171 bool GetSkipPointers() const {
172 return (m_flags & lldb::eTypeOptionSkipPointers) ==
173 lldb::eTypeOptionSkipPointers;
176 Flags &SetSkipPointers(bool value = true) {
178 m_flags |= lldb::eTypeOptionSkipPointers;
180 m_flags &= ~lldb::eTypeOptionSkipPointers;
184 bool GetSkipReferences() const {
185 return (m_flags & lldb::eTypeOptionSkipReferences) ==
186 lldb::eTypeOptionSkipReferences;
189 Flags &SetSkipReferences(bool value = true) {
191 m_flags |= lldb::eTypeOptionSkipReferences;
193 m_flags &= ~lldb::eTypeOptionSkipReferences;
197 bool GetNonCacheable() const {
198 return (m_flags & lldb::eTypeOptionNonCacheable) ==
199 lldb::eTypeOptionNonCacheable;
202 Flags &SetNonCacheable(bool value = true) {
204 m_flags |= lldb::eTypeOptionNonCacheable;
206 m_flags &= ~lldb::eTypeOptionNonCacheable;
210 bool GetFrontEndWantsDereference() const {
211 return (m_flags & lldb::eTypeOptionFrontEndWantsDereference) ==
212 lldb::eTypeOptionFrontEndWantsDereference;
215 Flags &SetFrontEndWantsDereference(bool value = true) {
217 m_flags |= lldb::eTypeOptionFrontEndWantsDereference;
219 m_flags &= ~lldb::eTypeOptionFrontEndWantsDereference;
223 uint32_t GetValue() { return m_flags; }
225 void SetValue(uint32_t value) { m_flags = value; }
231 SyntheticChildren(const Flags &flags) : m_flags(flags) {}
233 virtual ~SyntheticChildren() = default;
235 bool Cascades() const { return m_flags.GetCascades(); }
237 bool SkipsPointers() const { return m_flags.GetSkipPointers(); }
239 bool SkipsReferences() const { return m_flags.GetSkipReferences(); }
241 bool NonCacheable() const { return m_flags.GetNonCacheable(); }
243 bool WantsDereference() const { return m_flags.GetFrontEndWantsDereference();}
245 void SetCascades(bool value) { m_flags.SetCascades(value); }
247 void SetSkipsPointers(bool value) { m_flags.SetSkipPointers(value); }
249 void SetSkipsReferences(bool value) { m_flags.SetSkipReferences(value); }
251 void SetNonCacheable(bool value) { m_flags.SetNonCacheable(value); }
253 uint32_t GetOptions() { return m_flags.GetValue(); }
255 void SetOptions(uint32_t value) { m_flags.SetValue(value); }
257 virtual bool IsScripted() = 0;
259 virtual std::string GetDescription() = 0;
261 virtual SyntheticChildrenFrontEnd::AutoPointer
262 GetFrontEnd(ValueObject &backend) = 0;
264 typedef std::shared_ptr<SyntheticChildren> SharedPointer;
266 uint32_t &GetRevision() { return m_my_revision; }
269 uint32_t m_my_revision;
273 DISALLOW_COPY_AND_ASSIGN(SyntheticChildren);
276 class TypeFilterImpl : public SyntheticChildren {
277 std::vector<std::string> m_expression_paths;
280 TypeFilterImpl(const SyntheticChildren::Flags &flags)
281 : SyntheticChildren(flags), m_expression_paths() {}
283 TypeFilterImpl(const SyntheticChildren::Flags &flags,
284 const std::initializer_list<const char *> items)
285 : SyntheticChildren(flags), m_expression_paths() {
286 for (auto path : items)
287 AddExpressionPath(path);
290 void AddExpressionPath(const char *path) {
291 AddExpressionPath(std::string(path));
294 void Clear() { m_expression_paths.clear(); }
296 size_t GetCount() const { return m_expression_paths.size(); }
298 const char *GetExpressionPathAtIndex(size_t i) const {
299 return m_expression_paths[i].c_str();
302 bool SetExpressionPathAtIndex(size_t i, const char *path) {
303 return SetExpressionPathAtIndex(i, std::string(path));
306 void AddExpressionPath(const std::string &path);
308 bool SetExpressionPathAtIndex(size_t i, const std::string &path);
310 bool IsScripted() override { return false; }
312 std::string GetDescription() override;
314 class FrontEnd : public SyntheticChildrenFrontEnd {
316 FrontEnd(TypeFilterImpl *flt, ValueObject &backend)
317 : SyntheticChildrenFrontEnd(backend), filter(flt) {}
319 ~FrontEnd() override = default;
321 size_t CalculateNumChildren() override { return filter->GetCount(); }
323 lldb::ValueObjectSP GetChildAtIndex(size_t idx) override {
324 if (idx >= filter->GetCount())
325 return lldb::ValueObjectSP();
326 return m_backend.GetSyntheticExpressionPathChild(
327 filter->GetExpressionPathAtIndex(idx), true);
330 bool Update() override { return false; }
332 bool MightHaveChildren() override { return filter->GetCount() > 0; }
334 size_t GetIndexOfChildWithName(const ConstString &name) override;
336 typedef std::shared_ptr<SyntheticChildrenFrontEnd> SharedPointer;
339 TypeFilterImpl *filter;
341 DISALLOW_COPY_AND_ASSIGN(FrontEnd);
344 SyntheticChildrenFrontEnd::AutoPointer
345 GetFrontEnd(ValueObject &backend) override {
346 return SyntheticChildrenFrontEnd::AutoPointer(new FrontEnd(this, backend));
349 typedef std::shared_ptr<TypeFilterImpl> SharedPointer;
352 DISALLOW_COPY_AND_ASSIGN(TypeFilterImpl);
355 class CXXSyntheticChildren : public SyntheticChildren {
357 typedef std::function<SyntheticChildrenFrontEnd *(CXXSyntheticChildren *,
358 lldb::ValueObjectSP)>
359 CreateFrontEndCallback;
360 CXXSyntheticChildren(const SyntheticChildren::Flags &flags,
361 const char *description, CreateFrontEndCallback callback)
362 : SyntheticChildren(flags), m_create_callback(callback),
363 m_description(description ? description : "") {}
365 bool IsScripted() override { return false; }
367 std::string GetDescription() override;
369 SyntheticChildrenFrontEnd::AutoPointer
370 GetFrontEnd(ValueObject &backend) override {
371 return SyntheticChildrenFrontEnd::AutoPointer(
372 m_create_callback(this, backend.GetSP()));
376 CreateFrontEndCallback m_create_callback;
377 std::string m_description;
380 DISALLOW_COPY_AND_ASSIGN(CXXSyntheticChildren);
383 #ifndef LLDB_DISABLE_PYTHON
385 class ScriptedSyntheticChildren : public SyntheticChildren {
386 std::string m_python_class;
387 std::string m_python_code;
390 ScriptedSyntheticChildren(const SyntheticChildren::Flags &flags,
391 const char *pclass, const char *pcode = nullptr)
392 : SyntheticChildren(flags), m_python_class(), m_python_code() {
394 m_python_class = pclass;
396 m_python_code = pcode;
399 const char *GetPythonClassName() { return m_python_class.c_str(); }
401 const char *GetPythonCode() { return m_python_code.c_str(); }
403 void SetPythonClassName(const char *fname) {
404 m_python_class.assign(fname);
405 m_python_code.clear();
408 void SetPythonCode(const char *script) { m_python_code.assign(script); }
410 std::string GetDescription() override;
412 bool IsScripted() override { return true; }
414 class FrontEnd : public SyntheticChildrenFrontEnd {
416 FrontEnd(std::string pclass, ValueObject &backend);
418 ~FrontEnd() override;
422 size_t CalculateNumChildren() override;
424 size_t CalculateNumChildren(uint32_t max) override;
426 lldb::ValueObjectSP GetChildAtIndex(size_t idx) override;
428 bool Update() override;
430 bool MightHaveChildren() override;
432 size_t GetIndexOfChildWithName(const ConstString &name) override;
434 lldb::ValueObjectSP GetSyntheticValue() override;
436 ConstString GetSyntheticTypeName() override;
438 typedef std::shared_ptr<SyntheticChildrenFrontEnd> SharedPointer;
441 std::string m_python_class;
442 StructuredData::ObjectSP m_wrapper_sp;
443 ScriptInterpreter *m_interpreter;
445 DISALLOW_COPY_AND_ASSIGN(FrontEnd);
448 SyntheticChildrenFrontEnd::AutoPointer
449 GetFrontEnd(ValueObject &backend) override {
450 auto synth_ptr = SyntheticChildrenFrontEnd::AutoPointer(
451 new FrontEnd(m_python_class, backend));
452 if (synth_ptr && ((FrontEnd *)synth_ptr.get())->IsValid())
458 DISALLOW_COPY_AND_ASSIGN(ScriptedSyntheticChildren);
461 } // namespace lldb_private
463 #endif // lldb_TypeSynthetic_h_