1//===-- SBTypeCategory.cpp ------------------------------------------------===//
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#include "lldb/API/SBTypeCategory.h"
10#include "lldb/Utility/Instrumentation.h"
11
12#include "lldb/API/SBStream.h"
13#include "lldb/API/SBTypeFilter.h"
14#include "lldb/API/SBTypeFormat.h"
15#include "lldb/API/SBTypeNameSpecifier.h"
16#include "lldb/API/SBTypeSummary.h"
17#include "lldb/API/SBTypeSynthetic.h"
18
19#include "lldb/Core/Debugger.h"
20#include "lldb/DataFormatters/DataVisualization.h"
21#include "lldb/Interpreter/CommandInterpreter.h"
22#include "lldb/Interpreter/ScriptInterpreter.h"
23
24using namespace lldb;
25using namespace lldb_private;
26
27typedef std::pair<lldb::TypeCategoryImplSP, user_id_t> ImplType;
28
29SBTypeCategory::SBTypeCategory() { LLDB_INSTRUMENT_VA(this); }
30
31SBTypeCategory::SBTypeCategory(const char *name) {
32 DataVisualization::Categories::GetCategory(category: ConstString(name), entry&: m_opaque_sp);
33}
34
35SBTypeCategory::SBTypeCategory(const lldb::SBTypeCategory &rhs)
36 : m_opaque_sp(rhs.m_opaque_sp) {
37 LLDB_INSTRUMENT_VA(this, rhs);
38}
39
40SBTypeCategory::~SBTypeCategory() = default;
41
42bool SBTypeCategory::IsValid() const {
43 LLDB_INSTRUMENT_VA(this);
44 return this->operator bool();
45}
46SBTypeCategory::operator bool() const {
47 LLDB_INSTRUMENT_VA(this);
48
49 return (m_opaque_sp.get() != nullptr);
50}
51
52bool SBTypeCategory::GetEnabled() {
53 LLDB_INSTRUMENT_VA(this);
54
55 if (!IsValid())
56 return false;
57 return m_opaque_sp->IsEnabled();
58}
59
60void SBTypeCategory::SetEnabled(bool enabled) {
61 LLDB_INSTRUMENT_VA(this, enabled);
62
63 if (!IsValid())
64 return;
65 if (enabled)
66 DataVisualization::Categories::Enable(category: m_opaque_sp);
67 else
68 DataVisualization::Categories::Disable(category: m_opaque_sp);
69}
70
71const char *SBTypeCategory::GetName() {
72 LLDB_INSTRUMENT_VA(this);
73
74 if (!IsValid())
75 return nullptr;
76 return ConstString(m_opaque_sp->GetName()).GetCString();
77}
78
79lldb::LanguageType SBTypeCategory::GetLanguageAtIndex(uint32_t idx) {
80 LLDB_INSTRUMENT_VA(this, idx);
81
82 if (IsValid())
83 return m_opaque_sp->GetLanguageAtIndex(idx);
84 return lldb::eLanguageTypeUnknown;
85}
86
87uint32_t SBTypeCategory::GetNumLanguages() {
88 LLDB_INSTRUMENT_VA(this);
89
90 if (IsValid())
91 return m_opaque_sp->GetNumLanguages();
92 return 0;
93}
94
95void SBTypeCategory::AddLanguage(lldb::LanguageType language) {
96 LLDB_INSTRUMENT_VA(this, language);
97
98 if (IsValid())
99 m_opaque_sp->AddLanguage(lang: language);
100}
101
102uint32_t SBTypeCategory::GetNumFormats() {
103 LLDB_INSTRUMENT_VA(this);
104
105 if (!IsValid())
106 return 0;
107
108 return m_opaque_sp->GetNumFormats();
109}
110
111uint32_t SBTypeCategory::GetNumSummaries() {
112 LLDB_INSTRUMENT_VA(this);
113
114 if (!IsValid())
115 return 0;
116 return m_opaque_sp->GetNumSummaries();
117}
118
119uint32_t SBTypeCategory::GetNumFilters() {
120 LLDB_INSTRUMENT_VA(this);
121
122 if (!IsValid())
123 return 0;
124 return m_opaque_sp->GetNumFilters();
125}
126
127uint32_t SBTypeCategory::GetNumSynthetics() {
128 LLDB_INSTRUMENT_VA(this);
129
130 if (!IsValid())
131 return 0;
132 return m_opaque_sp->GetNumSynthetics();
133}
134
135lldb::SBTypeNameSpecifier
136SBTypeCategory::GetTypeNameSpecifierForFilterAtIndex(uint32_t index) {
137 LLDB_INSTRUMENT_VA(this, index);
138
139 if (!IsValid())
140 return SBTypeNameSpecifier();
141 return SBTypeNameSpecifier(
142 m_opaque_sp->GetTypeNameSpecifierForFilterAtIndex(index));
143}
144
145lldb::SBTypeNameSpecifier
146SBTypeCategory::GetTypeNameSpecifierForFormatAtIndex(uint32_t index) {
147 LLDB_INSTRUMENT_VA(this, index);
148
149 if (!IsValid())
150 return SBTypeNameSpecifier();
151 return SBTypeNameSpecifier(
152 m_opaque_sp->GetTypeNameSpecifierForFormatAtIndex(index));
153}
154
155lldb::SBTypeNameSpecifier
156SBTypeCategory::GetTypeNameSpecifierForSummaryAtIndex(uint32_t index) {
157 LLDB_INSTRUMENT_VA(this, index);
158
159 if (!IsValid())
160 return SBTypeNameSpecifier();
161 return SBTypeNameSpecifier(
162 m_opaque_sp->GetTypeNameSpecifierForSummaryAtIndex(index));
163}
164
165lldb::SBTypeNameSpecifier
166SBTypeCategory::GetTypeNameSpecifierForSyntheticAtIndex(uint32_t index) {
167 LLDB_INSTRUMENT_VA(this, index);
168
169 if (!IsValid())
170 return SBTypeNameSpecifier();
171 return SBTypeNameSpecifier(
172 m_opaque_sp->GetTypeNameSpecifierForSyntheticAtIndex(index));
173}
174
175SBTypeFilter SBTypeCategory::GetFilterForType(SBTypeNameSpecifier spec) {
176 LLDB_INSTRUMENT_VA(this, spec);
177
178 if (!IsValid())
179 return SBTypeFilter();
180
181 if (!spec.IsValid())
182 return SBTypeFilter();
183
184 lldb::TypeFilterImplSP children_sp =
185 m_opaque_sp->GetFilterForType(type_sp: spec.GetSP());
186
187 if (!children_sp)
188 return lldb::SBTypeFilter();
189
190 TypeFilterImplSP filter_sp =
191 std::static_pointer_cast<TypeFilterImpl>(r: children_sp);
192
193 return lldb::SBTypeFilter(filter_sp);
194}
195SBTypeFormat SBTypeCategory::GetFormatForType(SBTypeNameSpecifier spec) {
196 LLDB_INSTRUMENT_VA(this, spec);
197
198 if (!IsValid())
199 return SBTypeFormat();
200
201 if (!spec.IsValid())
202 return SBTypeFormat();
203
204 lldb::TypeFormatImplSP format_sp =
205 m_opaque_sp->GetFormatForType(type_sp: spec.GetSP());
206
207 if (!format_sp)
208 return lldb::SBTypeFormat();
209
210 return lldb::SBTypeFormat(format_sp);
211}
212
213SBTypeSummary SBTypeCategory::GetSummaryForType(SBTypeNameSpecifier spec) {
214 LLDB_INSTRUMENT_VA(this, spec);
215
216 if (!IsValid())
217 return SBTypeSummary();
218
219 if (!spec.IsValid())
220 return SBTypeSummary();
221
222 lldb::TypeSummaryImplSP summary_sp =
223 m_opaque_sp->GetSummaryForType(type_sp: spec.GetSP());
224
225 if (!summary_sp)
226 return lldb::SBTypeSummary();
227
228 return lldb::SBTypeSummary(summary_sp);
229}
230
231SBTypeSynthetic SBTypeCategory::GetSyntheticForType(SBTypeNameSpecifier spec) {
232 LLDB_INSTRUMENT_VA(this, spec);
233
234 if (!IsValid())
235 return SBTypeSynthetic();
236
237 if (!spec.IsValid())
238 return SBTypeSynthetic();
239
240 lldb::SyntheticChildrenSP children_sp =
241 m_opaque_sp->GetSyntheticForType(type_sp: spec.GetSP());
242
243 if (!children_sp)
244 return lldb::SBTypeSynthetic();
245
246 ScriptedSyntheticChildrenSP synth_sp =
247 std::static_pointer_cast<ScriptedSyntheticChildren>(r: children_sp);
248
249 return lldb::SBTypeSynthetic(synth_sp);
250}
251
252SBTypeFilter SBTypeCategory::GetFilterAtIndex(uint32_t index) {
253 LLDB_INSTRUMENT_VA(this, index);
254
255 if (!IsValid())
256 return SBTypeFilter();
257 lldb::SyntheticChildrenSP children_sp =
258 m_opaque_sp->GetSyntheticAtIndex((index));
259
260 if (!children_sp.get())
261 return lldb::SBTypeFilter();
262
263 TypeFilterImplSP filter_sp =
264 std::static_pointer_cast<TypeFilterImpl>(r: children_sp);
265
266 return lldb::SBTypeFilter(filter_sp);
267}
268
269SBTypeFormat SBTypeCategory::GetFormatAtIndex(uint32_t index) {
270 LLDB_INSTRUMENT_VA(this, index);
271
272 if (!IsValid())
273 return SBTypeFormat();
274 return SBTypeFormat(m_opaque_sp->GetFormatAtIndex((index)));
275}
276
277SBTypeSummary SBTypeCategory::GetSummaryAtIndex(uint32_t index) {
278 LLDB_INSTRUMENT_VA(this, index);
279
280 if (!IsValid())
281 return SBTypeSummary();
282 return SBTypeSummary(m_opaque_sp->GetSummaryAtIndex((index)));
283}
284
285SBTypeSynthetic SBTypeCategory::GetSyntheticAtIndex(uint32_t index) {
286 LLDB_INSTRUMENT_VA(this, index);
287
288 if (!IsValid())
289 return SBTypeSynthetic();
290 lldb::SyntheticChildrenSP children_sp =
291 m_opaque_sp->GetSyntheticAtIndex((index));
292
293 if (!children_sp.get())
294 return lldb::SBTypeSynthetic();
295
296 ScriptedSyntheticChildrenSP synth_sp =
297 std::static_pointer_cast<ScriptedSyntheticChildren>(r: children_sp);
298
299 return lldb::SBTypeSynthetic(synth_sp);
300}
301
302bool SBTypeCategory::AddTypeFormat(SBTypeNameSpecifier type_name,
303 SBTypeFormat format) {
304 LLDB_INSTRUMENT_VA(this, type_name, format);
305
306 if (!IsValid())
307 return false;
308
309 if (!type_name.IsValid())
310 return false;
311
312 if (!format.IsValid())
313 return false;
314
315 m_opaque_sp->AddTypeFormat(type_sp: type_name.GetSP(), format_sp: format.GetSP());
316 return true;
317}
318
319bool SBTypeCategory::DeleteTypeFormat(SBTypeNameSpecifier type_name) {
320 LLDB_INSTRUMENT_VA(this, type_name);
321
322 if (!IsValid())
323 return false;
324
325 if (!type_name.IsValid())
326 return false;
327
328 return m_opaque_sp->DeleteTypeFormat(type_sp: type_name.GetSP());
329}
330
331bool SBTypeCategory::AddTypeSummary(SBTypeNameSpecifier type_name,
332 SBTypeSummary summary) {
333 LLDB_INSTRUMENT_VA(this, type_name, summary);
334
335 if (!IsValid())
336 return false;
337
338 if (!type_name.IsValid())
339 return false;
340
341 if (!summary.IsValid())
342 return false;
343
344 // FIXME: we need to iterate over all the Debugger objects and have each of
345 // them contain a copy of the function
346 // since we currently have formatters live in a global space, while Python
347 // code lives in a specific Debugger-related environment this should
348 // eventually be fixed by deciding a final location in the LLDB object space
349 // for formatters
350 if (summary.IsFunctionCode()) {
351 const void *name_token =
352 (const void *)ConstString(type_name.GetName()).GetCString();
353 const char *script = summary.GetData();
354 StringList input;
355 input.SplitIntoLines(lines: script, len: strlen(s: script));
356 uint32_t num_debuggers = lldb_private::Debugger::GetNumDebuggers();
357 bool need_set = true;
358 for (uint32_t j = 0; j < num_debuggers; j++) {
359 DebuggerSP debugger_sp = lldb_private::Debugger::GetDebuggerAtIndex(index: j);
360 if (debugger_sp) {
361 ScriptInterpreter *interpreter_ptr =
362 debugger_sp->GetScriptInterpreter();
363 if (interpreter_ptr) {
364 std::string output;
365 if (interpreter_ptr->GenerateTypeScriptFunction(input, output,
366 name_token) &&
367 !output.empty()) {
368 if (need_set) {
369 need_set = false;
370 summary.SetFunctionName(output.c_str());
371 }
372 }
373 }
374 }
375 }
376 }
377
378 m_opaque_sp->AddTypeSummary(type_sp: type_name.GetSP(), summary_sp: summary.GetSP());
379 return true;
380}
381
382bool SBTypeCategory::DeleteTypeSummary(SBTypeNameSpecifier type_name) {
383 LLDB_INSTRUMENT_VA(this, type_name);
384
385 if (!IsValid())
386 return false;
387
388 if (!type_name.IsValid())
389 return false;
390
391 return m_opaque_sp->DeleteTypeSummary(type_sp: type_name.GetSP());
392}
393
394bool SBTypeCategory::AddTypeFilter(SBTypeNameSpecifier type_name,
395 SBTypeFilter filter) {
396 LLDB_INSTRUMENT_VA(this, type_name, filter);
397
398 if (!IsValid())
399 return false;
400
401 if (!type_name.IsValid())
402 return false;
403
404 if (!filter.IsValid())
405 return false;
406
407 m_opaque_sp->AddTypeFilter(type_sp: type_name.GetSP(), filter_sp: filter.GetSP());
408 return true;
409}
410
411bool SBTypeCategory::DeleteTypeFilter(SBTypeNameSpecifier type_name) {
412 LLDB_INSTRUMENT_VA(this, type_name);
413
414 if (!IsValid())
415 return false;
416
417 if (!type_name.IsValid())
418 return false;
419
420 return m_opaque_sp->DeleteTypeFilter(type_sp: type_name.GetSP());
421}
422
423bool SBTypeCategory::AddTypeSynthetic(SBTypeNameSpecifier type_name,
424 SBTypeSynthetic synth) {
425 LLDB_INSTRUMENT_VA(this, type_name, synth);
426
427 if (!IsValid())
428 return false;
429
430 if (!type_name.IsValid())
431 return false;
432
433 if (!synth.IsValid())
434 return false;
435
436 // FIXME: we need to iterate over all the Debugger objects and have each of
437 // them contain a copy of the function
438 // since we currently have formatters live in a global space, while Python
439 // code lives in a specific Debugger-related environment this should
440 // eventually be fixed by deciding a final location in the LLDB object space
441 // for formatters
442 if (synth.IsClassCode()) {
443 const void *name_token =
444 (const void *)ConstString(type_name.GetName()).GetCString();
445 const char *script = synth.GetData();
446 StringList input;
447 input.SplitIntoLines(lines: script, len: strlen(s: script));
448 uint32_t num_debuggers = lldb_private::Debugger::GetNumDebuggers();
449 bool need_set = true;
450 for (uint32_t j = 0; j < num_debuggers; j++) {
451 DebuggerSP debugger_sp = lldb_private::Debugger::GetDebuggerAtIndex(index: j);
452 if (debugger_sp) {
453 ScriptInterpreter *interpreter_ptr =
454 debugger_sp->GetScriptInterpreter();
455 if (interpreter_ptr) {
456 std::string output;
457 if (interpreter_ptr->GenerateTypeSynthClass(input, output,
458 name_token) &&
459 !output.empty()) {
460 if (need_set) {
461 need_set = false;
462 synth.SetClassName(output.c_str());
463 }
464 }
465 }
466 }
467 }
468 }
469
470 m_opaque_sp->AddTypeSynthetic(type_sp: type_name.GetSP(), synth_sp: synth.GetSP());
471 return true;
472}
473
474bool SBTypeCategory::DeleteTypeSynthetic(SBTypeNameSpecifier type_name) {
475 LLDB_INSTRUMENT_VA(this, type_name);
476
477 if (!IsValid())
478 return false;
479
480 if (!type_name.IsValid())
481 return false;
482
483 return m_opaque_sp->DeleteTypeSynthetic(type_sp: type_name.GetSP());
484}
485
486bool SBTypeCategory::GetDescription(lldb::SBStream &description,
487 lldb::DescriptionLevel description_level) {
488 LLDB_INSTRUMENT_VA(this, description, description_level);
489
490 if (!IsValid())
491 return false;
492 description.Printf(format: "Category name: %s\n", GetName());
493 return true;
494}
495
496lldb::SBTypeCategory &SBTypeCategory::
497operator=(const lldb::SBTypeCategory &rhs) {
498 LLDB_INSTRUMENT_VA(this, rhs);
499
500 if (this != &rhs) {
501 m_opaque_sp = rhs.m_opaque_sp;
502 }
503 return *this;
504}
505
506bool SBTypeCategory::operator==(lldb::SBTypeCategory &rhs) {
507 LLDB_INSTRUMENT_VA(this, rhs);
508
509 if (!IsValid())
510 return !rhs.IsValid();
511
512 return m_opaque_sp.get() == rhs.m_opaque_sp.get();
513}
514
515bool SBTypeCategory::operator!=(lldb::SBTypeCategory &rhs) {
516 LLDB_INSTRUMENT_VA(this, rhs);
517
518 if (!IsValid())
519 return rhs.IsValid();
520
521 return m_opaque_sp.get() != rhs.m_opaque_sp.get();
522}
523
524lldb::TypeCategoryImplSP SBTypeCategory::GetSP() {
525 if (!IsValid())
526 return lldb::TypeCategoryImplSP();
527 return m_opaque_sp;
528}
529
530void SBTypeCategory::SetSP(
531 const lldb::TypeCategoryImplSP &typecategory_impl_sp) {
532 m_opaque_sp = typecategory_impl_sp;
533}
534
535SBTypeCategory::SBTypeCategory(
536 const lldb::TypeCategoryImplSP &typecategory_impl_sp)
537 : m_opaque_sp(typecategory_impl_sp) {}
538
539bool SBTypeCategory::IsDefaultCategory() {
540 if (!IsValid())
541 return false;
542
543 return (strcmp(s1: m_opaque_sp->GetName(), s2: "default") == 0);
544}
545

source code of lldb/source/API/SBTypeCategory.cpp