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 | |
24 | using namespace lldb; |
25 | using namespace lldb_private; |
26 | |
27 | typedef std::pair<lldb::TypeCategoryImplSP, user_id_t> ImplType; |
28 | |
29 | SBTypeCategory::SBTypeCategory() { LLDB_INSTRUMENT_VA(this); } |
30 | |
31 | SBTypeCategory::SBTypeCategory(const char *name) { |
32 | DataVisualization::Categories::GetCategory(category: ConstString(name), entry&: m_opaque_sp); |
33 | } |
34 | |
35 | SBTypeCategory::SBTypeCategory(const lldb::SBTypeCategory &rhs) |
36 | : m_opaque_sp(rhs.m_opaque_sp) { |
37 | LLDB_INSTRUMENT_VA(this, rhs); |
38 | } |
39 | |
40 | SBTypeCategory::~SBTypeCategory() = default; |
41 | |
42 | bool SBTypeCategory::IsValid() const { |
43 | LLDB_INSTRUMENT_VA(this); |
44 | return this->operator bool(); |
45 | } |
46 | SBTypeCategory::operator bool() const { |
47 | LLDB_INSTRUMENT_VA(this); |
48 | |
49 | return (m_opaque_sp.get() != nullptr); |
50 | } |
51 | |
52 | bool SBTypeCategory::GetEnabled() { |
53 | LLDB_INSTRUMENT_VA(this); |
54 | |
55 | if (!IsValid()) |
56 | return false; |
57 | return m_opaque_sp->IsEnabled(); |
58 | } |
59 | |
60 | void 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 | |
71 | const 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 | |
79 | lldb::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 | |
87 | uint32_t SBTypeCategory::GetNumLanguages() { |
88 | LLDB_INSTRUMENT_VA(this); |
89 | |
90 | if (IsValid()) |
91 | return m_opaque_sp->GetNumLanguages(); |
92 | return 0; |
93 | } |
94 | |
95 | void SBTypeCategory::AddLanguage(lldb::LanguageType language) { |
96 | LLDB_INSTRUMENT_VA(this, language); |
97 | |
98 | if (IsValid()) |
99 | m_opaque_sp->AddLanguage(lang: language); |
100 | } |
101 | |
102 | uint32_t SBTypeCategory::GetNumFormats() { |
103 | LLDB_INSTRUMENT_VA(this); |
104 | |
105 | if (!IsValid()) |
106 | return 0; |
107 | |
108 | return m_opaque_sp->GetNumFormats(); |
109 | } |
110 | |
111 | uint32_t SBTypeCategory::GetNumSummaries() { |
112 | LLDB_INSTRUMENT_VA(this); |
113 | |
114 | if (!IsValid()) |
115 | return 0; |
116 | return m_opaque_sp->GetNumSummaries(); |
117 | } |
118 | |
119 | uint32_t SBTypeCategory::GetNumFilters() { |
120 | LLDB_INSTRUMENT_VA(this); |
121 | |
122 | if (!IsValid()) |
123 | return 0; |
124 | return m_opaque_sp->GetNumFilters(); |
125 | } |
126 | |
127 | uint32_t SBTypeCategory::GetNumSynthetics() { |
128 | LLDB_INSTRUMENT_VA(this); |
129 | |
130 | if (!IsValid()) |
131 | return 0; |
132 | return m_opaque_sp->GetNumSynthetics(); |
133 | } |
134 | |
135 | lldb::SBTypeNameSpecifier |
136 | SBTypeCategory::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 | |
145 | lldb::SBTypeNameSpecifier |
146 | SBTypeCategory::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 | |
155 | lldb::SBTypeNameSpecifier |
156 | SBTypeCategory::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 | |
165 | lldb::SBTypeNameSpecifier |
166 | SBTypeCategory::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 | |
175 | SBTypeFilter 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 | } |
195 | SBTypeFormat 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 | |
213 | SBTypeSummary 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 | |
231 | SBTypeSynthetic 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 | |
252 | SBTypeFilter 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 | |
269 | SBTypeFormat 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 | |
277 | SBTypeSummary 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 | |
285 | SBTypeSynthetic 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 | |
302 | bool 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 | |
319 | bool 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 | |
331 | bool 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 | |
382 | bool 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 | |
394 | bool 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 | |
411 | bool 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 | |
423 | bool 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 | |
474 | bool 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 | |
486 | bool 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 | |
496 | lldb::SBTypeCategory &SBTypeCategory:: |
497 | operator=(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 | |
506 | bool 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 | |
515 | bool 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 | |
524 | lldb::TypeCategoryImplSP SBTypeCategory::GetSP() { |
525 | if (!IsValid()) |
526 | return lldb::TypeCategoryImplSP(); |
527 | return m_opaque_sp; |
528 | } |
529 | |
530 | void SBTypeCategory::SetSP( |
531 | const lldb::TypeCategoryImplSP &typecategory_impl_sp) { |
532 | m_opaque_sp = typecategory_impl_sp; |
533 | } |
534 | |
535 | SBTypeCategory::SBTypeCategory( |
536 | const lldb::TypeCategoryImplSP &typecategory_impl_sp) |
537 | : m_opaque_sp(typecategory_impl_sp) {} |
538 | |
539 | bool SBTypeCategory::IsDefaultCategory() { |
540 | if (!IsValid()) |
541 | return false; |
542 | |
543 | return (strcmp(s1: m_opaque_sp->GetName(), s2: "default" ) == 0); |
544 | } |
545 | |