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 25 namespace lldb_private { 26 class TypeSummaryOptions { 27 public: 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 40 private: 41 lldb::LanguageType m_lang = lldb::eLanguageTypeUnknown; 42 lldb::TypeSummaryCapping m_capping = lldb::eTypeSummaryCapped; 43 }; 44 45 class TypeSummaryImpl { 46 public: 47 enum class Kind { eSummaryString, eScript, eCallback, eInternal }; 48 49 virtual ~TypeSummaryImpl() = default; 50 GetKind()51 Kind GetKind() const { return m_kind; } 52 53 class Flags { 54 public: 55 Flags() = default; 56 Flags(const Flags & other)57 Flags(const Flags &other) : m_flags(other.m_flags) {} 58 Flags(uint32_t value)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 Clear()73 Flags &Clear() { 74 m_flags = 0; 75 return *this; 76 } 77 GetCascades()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 GetSkipPointers()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 GetSkipReferences()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 GetDontShowChildren()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 GetHideEmptyAggregates()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 GetDontShowValue()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 GetShowMembersOneLiner()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 GetHideItemNames()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 GetNonCacheable()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 GetValue()194 uint32_t GetValue() { return m_flags; } 195 SetValue(uint32_t value)196 void SetValue(uint32_t value) { m_flags = value; } 197 198 private: 199 uint32_t m_flags = lldb::eTypeOptionCascade; 200 }; 201 Cascades()202 bool Cascades() const { return m_flags.GetCascades(); } 203 SkipsPointers()204 bool SkipsPointers() const { return m_flags.GetSkipPointers(); } 205 SkipsReferences()206 bool SkipsReferences() const { return m_flags.GetSkipReferences(); } 207 NonCacheable()208 bool NonCacheable() const { return m_flags.GetNonCacheable(); } 209 DoesPrintChildren(ValueObject * valobj)210 virtual bool DoesPrintChildren(ValueObject *valobj) const { 211 return !m_flags.GetDontShowChildren(); 212 } 213 DoesPrintEmptyAggregates()214 virtual bool DoesPrintEmptyAggregates() const { 215 return !m_flags.GetHideEmptyAggregates(); 216 } 217 DoesPrintValue(ValueObject * valobj)218 virtual bool DoesPrintValue(ValueObject *valobj) const { 219 return !m_flags.GetDontShowValue(); 220 } 221 IsOneLiner()222 bool IsOneLiner() const { return m_flags.GetShowMembersOneLiner(); } 223 HideNames(ValueObject * valobj)224 virtual bool HideNames(ValueObject *valobj) const { 225 return m_flags.GetHideItemNames(); 226 } 227 SetCascades(bool value)228 void SetCascades(bool value) { m_flags.SetCascades(value); } 229 SetSkipsPointers(bool value)230 void SetSkipsPointers(bool value) { m_flags.SetSkipPointers(value); } 231 SetSkipsReferences(bool value)232 void SetSkipsReferences(bool value) { m_flags.SetSkipReferences(value); } 233 SetDoesPrintChildren(bool value)234 virtual void SetDoesPrintChildren(bool value) { 235 m_flags.SetDontShowChildren(!value); 236 } 237 SetDoesPrintValue(bool value)238 virtual void SetDoesPrintValue(bool value) { 239 m_flags.SetDontShowValue(!value); 240 } 241 SetIsOneLiner(bool value)242 void SetIsOneLiner(bool value) { m_flags.SetShowMembersOneLiner(value); } 243 SetHideNames(bool value)244 virtual void SetHideNames(bool value) { m_flags.SetHideItemNames(value); } 245 SetNonCacheable(bool value)246 virtual void SetNonCacheable(bool value) { m_flags.SetNonCacheable(value); } 247 GetOptions()248 uint32_t GetOptions() { return m_flags.GetValue(); } 249 SetOptions(uint32_t value)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 GetRevision()261 uint32_t &GetRevision() { return m_my_revision; } 262 263 typedef std::shared_ptr<TypeSummaryImpl> SharedPointer; 264 265 protected: 266 uint32_t m_my_revision = 0; 267 Flags m_flags; 268 269 TypeSummaryImpl(Kind kind, const TypeSummaryImpl::Flags &flags); 270 271 private: 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 278 struct 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 GetSummaryStringStringSummaryFormat287 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 classofStringSummaryFormat296 static bool classof(const TypeSummaryImpl *S) { 297 return S->GetKind() == Kind::eSummaryString; 298 } 299 300 private: 301 StringSummaryFormat(const StringSummaryFormat &) = delete; 302 const StringSummaryFormat &operator=(const StringSummaryFormat &) = delete; 303 }; 304 305 // summaries implemented via a C++ function 306 struct 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 GetBackendFunctionCXXFunctionSummaryFormat321 Callback GetBackendFunction() const { return m_impl; } 322 GetTextualInfoCXXFunctionSummaryFormat323 const char *GetTextualInfo() const { return m_description.c_str(); } 324 SetBackendFunctionCXXFunctionSummaryFormat325 void SetBackendFunction(Callback cb_func) { m_impl = std::move(cb_func); } 326 SetTextualInfoCXXFunctionSummaryFormat327 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 classofCXXFunctionSummaryFormat339 static bool classof(const TypeSummaryImpl *S) { 340 return S->GetKind() == Kind::eCallback; 341 } 342 343 typedef std::shared_ptr<CXXFunctionSummaryFormat> SharedPointer; 344 345 private: 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 352 struct 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 GetFunctionNameScriptSummaryFormat363 const char *GetFunctionName() const { return m_function_name.c_str(); } 364 GetPythonScriptScriptSummaryFormat365 const char *GetPythonScript() const { return m_python_script.c_str(); } 366 SetFunctionNameScriptSummaryFormat367 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 SetPythonScriptScriptSummaryFormat375 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 classofScriptSummaryFormat387 static bool classof(const TypeSummaryImpl *S) { 388 return S->GetKind() == Kind::eScript; 389 } 390 391 typedef std::shared_ptr<ScriptSummaryFormat> SharedPointer; 392 393 private: 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