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(ConstString(name), 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(m_opaque_sp);
67  else
68    DataVisualization::Categories::Disable(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(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(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}
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(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(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(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
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>(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>(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_name.GetSP(), 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_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(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
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_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_name.GetSP(), 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_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(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
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_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("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(m_opaque_sp->GetName(), "default") == 0);
544}
545