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