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