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