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(ConstString(name), 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(m_opaque_sp);
67   else
68     DataVisualization::Categories::Disable(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(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(spec.GetSP());
186 
187   if (!children_sp)
188     return lldb::SBTypeFilter();
189 
190   TypeFilterImplSP filter_sp =
191       std::static_pointer_cast<TypeFilterImpl>(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(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(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(spec.GetSP());
242 
243   if (!children_sp)
244     return lldb::SBTypeSynthetic();
245 
246   ScriptedSyntheticChildrenSP synth_sp =
247       std::static_pointer_cast<ScriptedSyntheticChildren>(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>(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>(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_name.GetSP(), 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_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(script, strlen(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(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_name.GetSP(), 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_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_name.GetSP(), 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_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(script, strlen(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(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_name.GetSP(), 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_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("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(m_opaque_sp->GetName(), "default") == 0);
544 }
545