1//===-- TypeSummary.h -------------------------------------------*- 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#ifndef LLDB_DATAFORMATTERS_TYPESUMMARY_H
10#define LLDB_DATAFORMATTERS_TYPESUMMARY_H
11
12#include <cstdint>
13
14#include <functional>
15#include <memory>
16#include <string>
17
18#include "lldb/lldb-enumerations.h"
19#include "lldb/lldb-public.h"
20
21#include "lldb/Core/FormatEntity.h"
22#include "lldb/Utility/Status.h"
23#include "lldb/Utility/StructuredData.h"
24
25namespace lldb_private {
26class TypeSummaryOptions {
27public:
28  TypeSummaryOptions();
29
30  ~TypeSummaryOptions() = default;
31
32  lldb::LanguageType GetLanguage() const;
33
34  lldb::TypeSummaryCapping GetCapping() const;
35
36  TypeSummaryOptions &SetLanguage(lldb::LanguageType);
37
38  TypeSummaryOptions &SetCapping(lldb::TypeSummaryCapping);
39
40private:
41  lldb::LanguageType m_lang = lldb::eLanguageTypeUnknown;
42  lldb::TypeSummaryCapping m_capping = lldb::eTypeSummaryCapped;
43};
44
45class TypeSummaryImpl {
46public:
47  enum class Kind { eSummaryString, eScript, eCallback, eInternal };
48
49  virtual ~TypeSummaryImpl() = default;
50
51  Kind GetKind() const { return m_kind; }
52
53  class Flags {
54  public:
55    Flags() = default;
56
57    Flags(const Flags &other) : m_flags(other.m_flags) {}
58
59    Flags(uint32_t value) : m_flags(value) {}
60
61    Flags &operator=(const Flags &rhs) {
62      if (&rhs != this)
63        m_flags = rhs.m_flags;
64
65      return *this;
66    }
67
68    Flags &operator=(const uint32_t &rhs) {
69      m_flags = rhs;
70      return *this;
71    }
72
73    Flags &Clear() {
74      m_flags = 0;
75      return *this;
76    }
77
78    bool GetCascades() const {
79      return (m_flags & lldb::eTypeOptionCascade) == lldb::eTypeOptionCascade;
80    }
81
82    Flags &SetCascades(bool value = true) {
83      if (value)
84        m_flags |= lldb::eTypeOptionCascade;
85      else
86        m_flags &= ~lldb::eTypeOptionCascade;
87      return *this;
88    }
89
90    bool GetSkipPointers() const {
91      return (m_flags & lldb::eTypeOptionSkipPointers) ==
92             lldb::eTypeOptionSkipPointers;
93    }
94
95    Flags &SetSkipPointers(bool value = true) {
96      if (value)
97        m_flags |= lldb::eTypeOptionSkipPointers;
98      else
99        m_flags &= ~lldb::eTypeOptionSkipPointers;
100      return *this;
101    }
102
103    bool GetSkipReferences() const {
104      return (m_flags & lldb::eTypeOptionSkipReferences) ==
105             lldb::eTypeOptionSkipReferences;
106    }
107
108    Flags &SetSkipReferences(bool value = true) {
109      if (value)
110        m_flags |= lldb::eTypeOptionSkipReferences;
111      else
112        m_flags &= ~lldb::eTypeOptionSkipReferences;
113      return *this;
114    }
115
116    bool GetDontShowChildren() const {
117      return (m_flags & lldb::eTypeOptionHideChildren) ==
118             lldb::eTypeOptionHideChildren;
119    }
120
121    Flags &SetDontShowChildren(bool value = true) {
122      if (value)
123        m_flags |= lldb::eTypeOptionHideChildren;
124      else
125        m_flags &= ~lldb::eTypeOptionHideChildren;
126      return *this;
127    }
128
129    bool GetHideEmptyAggregates() const {
130      return (m_flags & lldb::eTypeOptionHideEmptyAggregates) ==
131             lldb::eTypeOptionHideEmptyAggregates;
132    }
133
134    Flags &SetHideEmptyAggregates(bool value = true) {
135      if (value)
136        m_flags |= lldb::eTypeOptionHideEmptyAggregates;
137      else
138        m_flags &= ~lldb::eTypeOptionHideEmptyAggregates;
139      return *this;
140    }
141
142    bool GetDontShowValue() const {
143      return (m_flags & lldb::eTypeOptionHideValue) ==
144             lldb::eTypeOptionHideValue;
145    }
146
147    Flags &SetDontShowValue(bool value = true) {
148      if (value)
149        m_flags |= lldb::eTypeOptionHideValue;
150      else
151        m_flags &= ~lldb::eTypeOptionHideValue;
152      return *this;
153    }
154
155    bool GetShowMembersOneLiner() const {
156      return (m_flags & lldb::eTypeOptionShowOneLiner) ==
157             lldb::eTypeOptionShowOneLiner;
158    }
159
160    Flags &SetShowMembersOneLiner(bool value = true) {
161      if (value)
162        m_flags |= lldb::eTypeOptionShowOneLiner;
163      else
164        m_flags &= ~lldb::eTypeOptionShowOneLiner;
165      return *this;
166    }
167
168    bool GetHideItemNames() const {
169      return (m_flags & lldb::eTypeOptionHideNames) ==
170             lldb::eTypeOptionHideNames;
171    }
172
173    Flags &SetHideItemNames(bool value = true) {
174      if (value)
175        m_flags |= lldb::eTypeOptionHideNames;
176      else
177        m_flags &= ~lldb::eTypeOptionHideNames;
178      return *this;
179    }
180
181    bool GetNonCacheable() const {
182      return (m_flags & lldb::eTypeOptionNonCacheable) ==
183             lldb::eTypeOptionNonCacheable;
184    }
185
186    Flags &SetNonCacheable(bool value = true) {
187      if (value)
188        m_flags |= lldb::eTypeOptionNonCacheable;
189      else
190        m_flags &= ~lldb::eTypeOptionNonCacheable;
191      return *this;
192    }
193
194    uint32_t GetValue() { return m_flags; }
195
196    void SetValue(uint32_t value) { m_flags = value; }
197
198  private:
199    uint32_t m_flags = lldb::eTypeOptionCascade;
200  };
201
202  bool Cascades() const { return m_flags.GetCascades(); }
203
204  bool SkipsPointers() const { return m_flags.GetSkipPointers(); }
205
206  bool SkipsReferences() const { return m_flags.GetSkipReferences(); }
207
208  bool NonCacheable() const { return m_flags.GetNonCacheable(); }
209
210  virtual bool DoesPrintChildren(ValueObject *valobj) const {
211    return !m_flags.GetDontShowChildren();
212  }
213
214  virtual bool DoesPrintEmptyAggregates() const {
215    return !m_flags.GetHideEmptyAggregates();
216  }
217
218  virtual bool DoesPrintValue(ValueObject *valobj) const {
219    return !m_flags.GetDontShowValue();
220  }
221
222  bool IsOneLiner() const { return m_flags.GetShowMembersOneLiner(); }
223
224  virtual bool HideNames(ValueObject *valobj) const {
225    return m_flags.GetHideItemNames();
226  }
227
228  void SetCascades(bool value) { m_flags.SetCascades(value); }
229
230  void SetSkipsPointers(bool value) { m_flags.SetSkipPointers(value); }
231
232  void SetSkipsReferences(bool value) { m_flags.SetSkipReferences(value); }
233
234  virtual void SetDoesPrintChildren(bool value) {
235    m_flags.SetDontShowChildren(!value);
236  }
237
238  virtual void SetDoesPrintValue(bool value) {
239    m_flags.SetDontShowValue(!value);
240  }
241
242  void SetIsOneLiner(bool value) { m_flags.SetShowMembersOneLiner(value); }
243
244  virtual void SetHideNames(bool value) { m_flags.SetHideItemNames(value); }
245
246  virtual void SetNonCacheable(bool value) { m_flags.SetNonCacheable(value); }
247
248  uint32_t GetOptions() { return m_flags.GetValue(); }
249
250  void SetOptions(uint32_t value) { m_flags.SetValue(value); }
251
252  // we are using a ValueObject* instead of a ValueObjectSP because we do not
253  // need to hold on to this for extended periods of time and we trust the
254  // ValueObject to stay around for as long as it is required for us to
255  // generate its summary
256  virtual bool FormatObject(ValueObject *valobj, std::string &dest,
257                            const TypeSummaryOptions &options) = 0;
258
259  virtual std::string GetDescription() = 0;
260
261  uint32_t &GetRevision() { return m_my_revision; }
262
263  typedef std::shared_ptr<TypeSummaryImpl> SharedPointer;
264
265protected:
266  uint32_t m_my_revision = 0;
267  Flags m_flags;
268
269  TypeSummaryImpl(Kind kind, const TypeSummaryImpl::Flags &flags);
270
271private:
272  Kind m_kind;
273  TypeSummaryImpl(const TypeSummaryImpl &) = delete;
274  const TypeSummaryImpl &operator=(const TypeSummaryImpl &) = delete;
275};
276
277// simple string-based summaries, using ${var to show data
278struct StringSummaryFormat : public TypeSummaryImpl {
279  std::string m_format_str;
280  FormatEntity::Entry m_format;
281  Status m_error;
282
283  StringSummaryFormat(const TypeSummaryImpl::Flags &flags, const char *f);
284
285  ~StringSummaryFormat() override = default;
286
287  const char *GetSummaryString() const { return m_format_str.c_str(); }
288
289  void SetSummaryString(const char *f);
290
291  bool FormatObject(ValueObject *valobj, std::string &dest,
292                    const TypeSummaryOptions &options) override;
293
294  std::string GetDescription() override;
295
296  static bool classof(const TypeSummaryImpl *S) {
297    return S->GetKind() == Kind::eSummaryString;
298  }
299
300private:
301  StringSummaryFormat(const StringSummaryFormat &) = delete;
302  const StringSummaryFormat &operator=(const StringSummaryFormat &) = delete;
303};
304
305// summaries implemented via a C++ function
306struct CXXFunctionSummaryFormat : public TypeSummaryImpl {
307  // we should convert these to SBValue and SBStream if we ever cross the
308  // boundary towards the external world
309  typedef std::function<bool(ValueObject &, Stream &,
310                             const TypeSummaryOptions &)>
311      Callback;
312
313  Callback m_impl;
314  std::string m_description;
315
316  CXXFunctionSummaryFormat(const TypeSummaryImpl::Flags &flags, Callback impl,
317                           const char *description);
318
319  ~CXXFunctionSummaryFormat() override = default;
320
321  Callback GetBackendFunction() const { return m_impl; }
322
323  const char *GetTextualInfo() const { return m_description.c_str(); }
324
325  void SetBackendFunction(Callback cb_func) { m_impl = std::move(cb_func); }
326
327  void SetTextualInfo(const char *descr) {
328    if (descr)
329      m_description.assign(descr);
330    else
331      m_description.clear();
332  }
333
334  bool FormatObject(ValueObject *valobj, std::string &dest,
335                    const TypeSummaryOptions &options) override;
336
337  std::string GetDescription() override;
338
339  static bool classof(const TypeSummaryImpl *S) {
340    return S->GetKind() == Kind::eCallback;
341  }
342
343  typedef std::shared_ptr<CXXFunctionSummaryFormat> SharedPointer;
344
345private:
346  CXXFunctionSummaryFormat(const CXXFunctionSummaryFormat &) = delete;
347  const CXXFunctionSummaryFormat &
348  operator=(const CXXFunctionSummaryFormat &) = delete;
349};
350
351// Python-based summaries, running script code to show data
352struct ScriptSummaryFormat : public TypeSummaryImpl {
353  std::string m_function_name;
354  std::string m_python_script;
355  StructuredData::ObjectSP m_script_function_sp;
356
357  ScriptSummaryFormat(const TypeSummaryImpl::Flags &flags,
358                      const char *function_name,
359                      const char *python_script = nullptr);
360
361  ~ScriptSummaryFormat() override = default;
362
363  const char *GetFunctionName() const { return m_function_name.c_str(); }
364
365  const char *GetPythonScript() const { return m_python_script.c_str(); }
366
367  void SetFunctionName(const char *function_name) {
368    if (function_name)
369      m_function_name.assign(function_name);
370    else
371      m_function_name.clear();
372    m_python_script.clear();
373  }
374
375  void SetPythonScript(const char *script) {
376    if (script)
377      m_python_script.assign(script);
378    else
379      m_python_script.clear();
380  }
381
382  bool FormatObject(ValueObject *valobj, std::string &dest,
383                    const TypeSummaryOptions &options) override;
384
385  std::string GetDescription() override;
386
387  static bool classof(const TypeSummaryImpl *S) {
388    return S->GetKind() == Kind::eScript;
389  }
390
391  typedef std::shared_ptr<ScriptSummaryFormat> SharedPointer;
392
393private:
394  ScriptSummaryFormat(const ScriptSummaryFormat &) = delete;
395  const ScriptSummaryFormat &operator=(const ScriptSummaryFormat &) = delete;
396};
397} // namespace lldb_private
398
399#endif // LLDB_DATAFORMATTERS_TYPESUMMARY_H
400