1 //===-- TypeCategory.cpp -----------------------------------------*- C++-*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #include "lldb/DataFormatters/TypeCategory.h"
11 #include "lldb/Target/Language.h"
15 // Other libraries and framework includes
19 using namespace lldb_private;
21 TypeCategoryImpl::TypeCategoryImpl(
22 IFormatChangeListener *clist, ConstString name,
23 std::initializer_list<lldb::LanguageType> langs)
24 : m_format_cont("format", "regex-format", clist),
25 m_summary_cont("summary", "regex-summary", clist),
26 m_filter_cont("filter", "regex-filter", clist),
27 #ifndef LLDB_DISABLE_PYTHON
28 m_synth_cont("synth", "regex-synth", clist),
30 m_validator_cont("validator", "regex-validator", clist), m_enabled(false),
31 m_change_listener(clist), m_mutex(), m_name(name), m_languages() {
32 for (const lldb::LanguageType lang : langs)
36 static bool IsApplicable(lldb::LanguageType category_lang,
37 lldb::LanguageType valobj_lang) {
38 switch (category_lang) {
39 // Unless we know better, allow only exact equality.
41 return category_lang == valobj_lang;
43 // the C family, we consider it as one
44 case eLanguageTypeC89:
46 case eLanguageTypeC99:
47 return valobj_lang == eLanguageTypeC89 || valobj_lang == eLanguageTypeC ||
48 valobj_lang == eLanguageTypeC99;
50 // ObjC knows about C and itself
51 case eLanguageTypeObjC:
52 return valobj_lang == eLanguageTypeC89 || valobj_lang == eLanguageTypeC ||
53 valobj_lang == eLanguageTypeC99 || valobj_lang == eLanguageTypeObjC;
55 // C++ knows about C and C++
56 case eLanguageTypeC_plus_plus:
57 return valobj_lang == eLanguageTypeC89 || valobj_lang == eLanguageTypeC ||
58 valobj_lang == eLanguageTypeC99 ||
59 valobj_lang == eLanguageTypeC_plus_plus;
61 // ObjC++ knows about C,C++,ObjC and ObjC++
62 case eLanguageTypeObjC_plus_plus:
63 return valobj_lang == eLanguageTypeC89 || valobj_lang == eLanguageTypeC ||
64 valobj_lang == eLanguageTypeC99 ||
65 valobj_lang == eLanguageTypeC_plus_plus ||
66 valobj_lang == eLanguageTypeObjC;
68 // Categories with unspecified language match everything.
69 case eLanguageTypeUnknown:
74 bool TypeCategoryImpl::IsApplicable(ValueObject &valobj) {
75 lldb::LanguageType valobj_lang = valobj.GetObjectRuntimeLanguage();
76 for (size_t idx = 0; idx < GetNumLanguages(); idx++) {
77 const lldb::LanguageType category_lang = GetLanguageAtIndex(idx);
78 if (::IsApplicable(category_lang, valobj_lang))
84 size_t TypeCategoryImpl::GetNumLanguages() {
85 if (m_languages.empty())
87 return m_languages.size();
90 lldb::LanguageType TypeCategoryImpl::GetLanguageAtIndex(size_t idx) {
91 if (m_languages.empty())
92 return lldb::eLanguageTypeUnknown;
93 return m_languages[idx];
96 void TypeCategoryImpl::AddLanguage(lldb::LanguageType lang) {
97 m_languages.push_back(lang);
100 bool TypeCategoryImpl::HasLanguage(lldb::LanguageType lang) {
101 const auto iter = std::find(m_languages.begin(), m_languages.end(), lang),
102 end = m_languages.end();
103 return (iter != end);
106 bool TypeCategoryImpl::Get(ValueObject &valobj,
107 const FormattersMatchVector &candidates,
108 lldb::TypeFormatImplSP &entry, uint32_t *reason) {
109 if (!IsEnabled() || !IsApplicable(valobj))
111 if (GetTypeFormatsContainer()->Get(candidates, entry, reason))
113 bool regex = GetRegexTypeFormatsContainer()->Get(candidates, entry, reason);
115 *reason |= lldb_private::eFormatterChoiceCriterionRegularExpressionSummary;
119 bool TypeCategoryImpl::Get(ValueObject &valobj,
120 const FormattersMatchVector &candidates,
121 lldb::TypeSummaryImplSP &entry, uint32_t *reason) {
122 if (!IsEnabled() || !IsApplicable(valobj))
124 if (GetTypeSummariesContainer()->Get(candidates, entry, reason))
126 bool regex = GetRegexTypeSummariesContainer()->Get(candidates, entry, reason);
128 *reason |= lldb_private::eFormatterChoiceCriterionRegularExpressionSummary;
132 bool TypeCategoryImpl::Get(ValueObject &valobj,
133 const FormattersMatchVector &candidates,
134 lldb::SyntheticChildrenSP &entry, uint32_t *reason) {
135 if (!IsEnabled() || !IsApplicable(valobj))
137 TypeFilterImpl::SharedPointer filter_sp;
138 uint32_t reason_filter = 0;
139 bool regex_filter = false;
140 // first find both Filter and Synth, and then check which is most recent
142 if (!GetTypeFiltersContainer()->Get(candidates, filter_sp, &reason_filter))
143 regex_filter = GetRegexTypeFiltersContainer()->Get(candidates, filter_sp,
146 #ifndef LLDB_DISABLE_PYTHON
147 bool regex_synth = false;
148 uint32_t reason_synth = 0;
149 bool pick_synth = false;
150 ScriptedSyntheticChildren::SharedPointer synth;
151 if (!GetTypeSyntheticsContainer()->Get(candidates, synth, &reason_synth))
152 regex_synth = GetRegexTypeSyntheticsContainer()->Get(candidates, synth,
154 if (!filter_sp.get() && !synth.get())
156 else if (!filter_sp.get() && synth.get())
159 else if (filter_sp.get() && !synth.get())
162 else /*if (filter_sp.get() && synth.get())*/
164 if (filter_sp->GetRevision() > synth->GetRevision())
170 if (regex_synth && reason)
171 *reason |= lldb_private::eFormatterChoiceCriterionRegularExpressionFilter;
175 if (regex_filter && reason)
176 *reason |= lldb_private::eFormatterChoiceCriterionRegularExpressionFilter;
191 bool TypeCategoryImpl::Get(ValueObject &valobj,
192 const FormattersMatchVector &candidates,
193 lldb::TypeValidatorImplSP &entry, uint32_t *reason) {
196 if (GetTypeValidatorsContainer()->Get(candidates, entry, reason))
199 GetRegexTypeValidatorsContainer()->Get(candidates, entry, reason);
201 *reason |= lldb_private::eFormatterChoiceCriterionRegularExpressionSummary;
205 void TypeCategoryImpl::Clear(FormatCategoryItems items) {
206 if ((items & eFormatCategoryItemValue) == eFormatCategoryItemValue)
207 GetTypeFormatsContainer()->Clear();
208 if ((items & eFormatCategoryItemRegexValue) == eFormatCategoryItemRegexValue)
209 GetRegexTypeFormatsContainer()->Clear();
211 if ((items & eFormatCategoryItemSummary) == eFormatCategoryItemSummary)
212 GetTypeSummariesContainer()->Clear();
213 if ((items & eFormatCategoryItemRegexSummary) ==
214 eFormatCategoryItemRegexSummary)
215 GetRegexTypeSummariesContainer()->Clear();
217 if ((items & eFormatCategoryItemFilter) == eFormatCategoryItemFilter)
218 GetTypeFiltersContainer()->Clear();
219 if ((items & eFormatCategoryItemRegexFilter) ==
220 eFormatCategoryItemRegexFilter)
221 GetRegexTypeFiltersContainer()->Clear();
223 #ifndef LLDB_DISABLE_PYTHON
224 if ((items & eFormatCategoryItemSynth) == eFormatCategoryItemSynth)
225 GetTypeSyntheticsContainer()->Clear();
226 if ((items & eFormatCategoryItemRegexSynth) == eFormatCategoryItemRegexSynth)
227 GetRegexTypeSyntheticsContainer()->Clear();
230 if ((items & eFormatCategoryItemValidator) == eFormatCategoryItemValidator)
231 GetTypeValidatorsContainer()->Clear();
232 if ((items & eFormatCategoryItemRegexValidator) ==
233 eFormatCategoryItemRegexValidator)
234 GetRegexTypeValidatorsContainer()->Clear();
237 bool TypeCategoryImpl::Delete(ConstString name, FormatCategoryItems items) {
238 bool success = false;
240 if ((items & eFormatCategoryItemValue) == eFormatCategoryItemValue)
241 success = GetTypeFormatsContainer()->Delete(name) || success;
242 if ((items & eFormatCategoryItemRegexValue) == eFormatCategoryItemRegexValue)
243 success = GetRegexTypeFormatsContainer()->Delete(name) || success;
245 if ((items & eFormatCategoryItemSummary) == eFormatCategoryItemSummary)
246 success = GetTypeSummariesContainer()->Delete(name) || success;
247 if ((items & eFormatCategoryItemRegexSummary) ==
248 eFormatCategoryItemRegexSummary)
249 success = GetRegexTypeSummariesContainer()->Delete(name) || success;
251 if ((items & eFormatCategoryItemFilter) == eFormatCategoryItemFilter)
252 success = GetTypeFiltersContainer()->Delete(name) || success;
253 if ((items & eFormatCategoryItemRegexFilter) ==
254 eFormatCategoryItemRegexFilter)
255 success = GetRegexTypeFiltersContainer()->Delete(name) || success;
257 #ifndef LLDB_DISABLE_PYTHON
258 if ((items & eFormatCategoryItemSynth) == eFormatCategoryItemSynth)
259 success = GetTypeSyntheticsContainer()->Delete(name) || success;
260 if ((items & eFormatCategoryItemRegexSynth) == eFormatCategoryItemRegexSynth)
261 success = GetRegexTypeSyntheticsContainer()->Delete(name) || success;
264 if ((items & eFormatCategoryItemValidator) == eFormatCategoryItemValidator)
265 success = GetTypeValidatorsContainer()->Delete(name) || success;
266 if ((items & eFormatCategoryItemRegexValidator) ==
267 eFormatCategoryItemRegexValidator)
268 success = GetRegexTypeValidatorsContainer()->Delete(name) || success;
273 uint32_t TypeCategoryImpl::GetCount(FormatCategoryItems items) {
276 if ((items & eFormatCategoryItemValue) == eFormatCategoryItemValue)
277 count += GetTypeFormatsContainer()->GetCount();
278 if ((items & eFormatCategoryItemRegexValue) == eFormatCategoryItemRegexValue)
279 count += GetRegexTypeFormatsContainer()->GetCount();
281 if ((items & eFormatCategoryItemSummary) == eFormatCategoryItemSummary)
282 count += GetTypeSummariesContainer()->GetCount();
283 if ((items & eFormatCategoryItemRegexSummary) ==
284 eFormatCategoryItemRegexSummary)
285 count += GetRegexTypeSummariesContainer()->GetCount();
287 if ((items & eFormatCategoryItemFilter) == eFormatCategoryItemFilter)
288 count += GetTypeFiltersContainer()->GetCount();
289 if ((items & eFormatCategoryItemRegexFilter) ==
290 eFormatCategoryItemRegexFilter)
291 count += GetRegexTypeFiltersContainer()->GetCount();
293 #ifndef LLDB_DISABLE_PYTHON
294 if ((items & eFormatCategoryItemSynth) == eFormatCategoryItemSynth)
295 count += GetTypeSyntheticsContainer()->GetCount();
296 if ((items & eFormatCategoryItemRegexSynth) == eFormatCategoryItemRegexSynth)
297 count += GetRegexTypeSyntheticsContainer()->GetCount();
300 if ((items & eFormatCategoryItemValidator) == eFormatCategoryItemValidator)
301 count += GetTypeValidatorsContainer()->GetCount();
302 if ((items & eFormatCategoryItemRegexValidator) ==
303 eFormatCategoryItemRegexValidator)
304 count += GetRegexTypeValidatorsContainer()->GetCount();
309 bool TypeCategoryImpl::AnyMatches(ConstString type_name,
310 FormatCategoryItems items, bool only_enabled,
311 const char **matching_category,
312 FormatCategoryItems *matching_type) {
313 if (!IsEnabled() && only_enabled)
316 lldb::TypeFormatImplSP format_sp;
317 lldb::TypeSummaryImplSP summary_sp;
318 TypeFilterImpl::SharedPointer filter_sp;
319 #ifndef LLDB_DISABLE_PYTHON
320 ScriptedSyntheticChildren::SharedPointer synth_sp;
322 TypeValidatorImpl::SharedPointer validator_sp;
324 if ((items & eFormatCategoryItemValue) == eFormatCategoryItemValue) {
325 if (GetTypeFormatsContainer()->Get(type_name, format_sp)) {
326 if (matching_category)
327 *matching_category = m_name.GetCString();
329 *matching_type = eFormatCategoryItemValue;
333 if ((items & eFormatCategoryItemRegexValue) ==
334 eFormatCategoryItemRegexValue) {
335 if (GetRegexTypeFormatsContainer()->Get(type_name, format_sp)) {
336 if (matching_category)
337 *matching_category = m_name.GetCString();
339 *matching_type = eFormatCategoryItemRegexValue;
344 if ((items & eFormatCategoryItemSummary) == eFormatCategoryItemSummary) {
345 if (GetTypeSummariesContainer()->Get(type_name, summary_sp)) {
346 if (matching_category)
347 *matching_category = m_name.GetCString();
349 *matching_type = eFormatCategoryItemSummary;
353 if ((items & eFormatCategoryItemRegexSummary) ==
354 eFormatCategoryItemRegexSummary) {
355 if (GetRegexTypeSummariesContainer()->Get(type_name, summary_sp)) {
356 if (matching_category)
357 *matching_category = m_name.GetCString();
359 *matching_type = eFormatCategoryItemRegexSummary;
364 if ((items & eFormatCategoryItemFilter) == eFormatCategoryItemFilter) {
365 if (GetTypeFiltersContainer()->Get(type_name, filter_sp)) {
366 if (matching_category)
367 *matching_category = m_name.GetCString();
369 *matching_type = eFormatCategoryItemFilter;
373 if ((items & eFormatCategoryItemRegexFilter) ==
374 eFormatCategoryItemRegexFilter) {
375 if (GetRegexTypeFiltersContainer()->Get(type_name, filter_sp)) {
376 if (matching_category)
377 *matching_category = m_name.GetCString();
379 *matching_type = eFormatCategoryItemRegexFilter;
384 #ifndef LLDB_DISABLE_PYTHON
385 if ((items & eFormatCategoryItemSynth) == eFormatCategoryItemSynth) {
386 if (GetTypeSyntheticsContainer()->Get(type_name, synth_sp)) {
387 if (matching_category)
388 *matching_category = m_name.GetCString();
390 *matching_type = eFormatCategoryItemSynth;
394 if ((items & eFormatCategoryItemRegexSynth) ==
395 eFormatCategoryItemRegexSynth) {
396 if (GetRegexTypeSyntheticsContainer()->Get(type_name, synth_sp)) {
397 if (matching_category)
398 *matching_category = m_name.GetCString();
400 *matching_type = eFormatCategoryItemRegexSynth;
406 if ((items & eFormatCategoryItemValidator) == eFormatCategoryItemValidator) {
407 if (GetTypeValidatorsContainer()->Get(type_name, validator_sp)) {
408 if (matching_category)
409 *matching_category = m_name.GetCString();
411 *matching_type = eFormatCategoryItemValidator;
415 if ((items & eFormatCategoryItemRegexValidator) ==
416 eFormatCategoryItemRegexValidator) {
417 if (GetRegexTypeValidatorsContainer()->Get(type_name, validator_sp)) {
418 if (matching_category)
419 *matching_category = m_name.GetCString();
421 *matching_type = eFormatCategoryItemRegexValidator;
429 TypeCategoryImpl::FormatContainer::MapValueType
430 TypeCategoryImpl::GetFormatForType(lldb::TypeNameSpecifierImplSP type_sp) {
431 FormatContainer::MapValueType retval;
434 if (type_sp->IsRegex())
435 GetRegexTypeFormatsContainer()->GetExact(ConstString(type_sp->GetName()),
438 GetTypeFormatsContainer()->GetExact(ConstString(type_sp->GetName()),
445 TypeCategoryImpl::SummaryContainer::MapValueType
446 TypeCategoryImpl::GetSummaryForType(lldb::TypeNameSpecifierImplSP type_sp) {
447 SummaryContainer::MapValueType retval;
450 if (type_sp->IsRegex())
451 GetRegexTypeSummariesContainer()->GetExact(
452 ConstString(type_sp->GetName()), retval);
454 GetTypeSummariesContainer()->GetExact(ConstString(type_sp->GetName()),
461 TypeCategoryImpl::FilterContainer::MapValueType
462 TypeCategoryImpl::GetFilterForType(lldb::TypeNameSpecifierImplSP type_sp) {
463 FilterContainer::MapValueType retval;
466 if (type_sp->IsRegex())
467 GetRegexTypeFiltersContainer()->GetExact(ConstString(type_sp->GetName()),
470 GetTypeFiltersContainer()->GetExact(ConstString(type_sp->GetName()),
477 #ifndef LLDB_DISABLE_PYTHON
478 TypeCategoryImpl::SynthContainer::MapValueType
479 TypeCategoryImpl::GetSyntheticForType(lldb::TypeNameSpecifierImplSP type_sp) {
480 SynthContainer::MapValueType retval;
483 if (type_sp->IsRegex())
484 GetRegexTypeSyntheticsContainer()->GetExact(
485 ConstString(type_sp->GetName()), retval);
487 GetTypeSyntheticsContainer()->GetExact(ConstString(type_sp->GetName()),
495 TypeCategoryImpl::ValidatorContainer::MapValueType
496 TypeCategoryImpl::GetValidatorForType(lldb::TypeNameSpecifierImplSP type_sp) {
497 ValidatorContainer::MapValueType retval;
500 if (type_sp->IsRegex())
501 GetRegexTypeValidatorsContainer()->GetExact(
502 ConstString(type_sp->GetName()), retval);
504 GetTypeValidatorsContainer()->GetExact(ConstString(type_sp->GetName()),
511 lldb::TypeNameSpecifierImplSP
512 TypeCategoryImpl::GetTypeNameSpecifierForSummaryAtIndex(size_t index) {
513 if (index < GetTypeSummariesContainer()->GetCount())
514 return GetTypeSummariesContainer()->GetTypeNameSpecifierAtIndex(index);
516 return GetRegexTypeSummariesContainer()->GetTypeNameSpecifierAtIndex(
517 index - GetTypeSummariesContainer()->GetCount());
520 TypeCategoryImpl::FormatContainer::MapValueType
521 TypeCategoryImpl::GetFormatAtIndex(size_t index) {
522 if (index < GetTypeFormatsContainer()->GetCount())
523 return GetTypeFormatsContainer()->GetAtIndex(index);
525 return GetRegexTypeFormatsContainer()->GetAtIndex(
526 index - GetTypeFormatsContainer()->GetCount());
529 TypeCategoryImpl::SummaryContainer::MapValueType
530 TypeCategoryImpl::GetSummaryAtIndex(size_t index) {
531 if (index < GetTypeSummariesContainer()->GetCount())
532 return GetTypeSummariesContainer()->GetAtIndex(index);
534 return GetRegexTypeSummariesContainer()->GetAtIndex(
535 index - GetTypeSummariesContainer()->GetCount());
538 TypeCategoryImpl::FilterContainer::MapValueType
539 TypeCategoryImpl::GetFilterAtIndex(size_t index) {
540 if (index < GetTypeFiltersContainer()->GetCount())
541 return GetTypeFiltersContainer()->GetAtIndex(index);
543 return GetRegexTypeFiltersContainer()->GetAtIndex(
544 index - GetTypeFiltersContainer()->GetCount());
547 lldb::TypeNameSpecifierImplSP
548 TypeCategoryImpl::GetTypeNameSpecifierForFormatAtIndex(size_t index) {
549 if (index < GetTypeFormatsContainer()->GetCount())
550 return GetTypeFormatsContainer()->GetTypeNameSpecifierAtIndex(index);
552 return GetRegexTypeFormatsContainer()->GetTypeNameSpecifierAtIndex(
553 index - GetTypeFormatsContainer()->GetCount());
556 lldb::TypeNameSpecifierImplSP
557 TypeCategoryImpl::GetTypeNameSpecifierForFilterAtIndex(size_t index) {
558 if (index < GetTypeFiltersContainer()->GetCount())
559 return GetTypeFiltersContainer()->GetTypeNameSpecifierAtIndex(index);
561 return GetRegexTypeFiltersContainer()->GetTypeNameSpecifierAtIndex(
562 index - GetTypeFiltersContainer()->GetCount());
565 #ifndef LLDB_DISABLE_PYTHON
566 TypeCategoryImpl::SynthContainer::MapValueType
567 TypeCategoryImpl::GetSyntheticAtIndex(size_t index) {
568 if (index < GetTypeSyntheticsContainer()->GetCount())
569 return GetTypeSyntheticsContainer()->GetAtIndex(index);
571 return GetRegexTypeSyntheticsContainer()->GetAtIndex(
572 index - GetTypeSyntheticsContainer()->GetCount());
575 lldb::TypeNameSpecifierImplSP
576 TypeCategoryImpl::GetTypeNameSpecifierForSyntheticAtIndex(size_t index) {
577 if (index < GetTypeSyntheticsContainer()->GetCount())
578 return GetTypeSyntheticsContainer()->GetTypeNameSpecifierAtIndex(index);
580 return GetRegexTypeSyntheticsContainer()->GetTypeNameSpecifierAtIndex(
581 index - GetTypeSyntheticsContainer()->GetCount());
585 TypeCategoryImpl::ValidatorContainer::MapValueType
586 TypeCategoryImpl::GetValidatorAtIndex(size_t index) {
587 if (index < GetTypeValidatorsContainer()->GetCount())
588 return GetTypeValidatorsContainer()->GetAtIndex(index);
590 return GetRegexTypeValidatorsContainer()->GetAtIndex(
591 index - GetTypeValidatorsContainer()->GetCount());
594 lldb::TypeNameSpecifierImplSP
595 TypeCategoryImpl::GetTypeNameSpecifierForValidatorAtIndex(size_t index) {
596 if (index < GetTypeValidatorsContainer()->GetCount())
597 return GetTypeValidatorsContainer()->GetTypeNameSpecifierAtIndex(index);
599 return GetRegexTypeValidatorsContainer()->GetTypeNameSpecifierAtIndex(
600 index - GetTypeValidatorsContainer()->GetCount());
603 void TypeCategoryImpl::Enable(bool value, uint32_t position) {
604 std::lock_guard<std::recursive_mutex> guard(m_mutex);
605 if ((m_enabled = value))
606 m_enabled_position = position;
607 if (m_change_listener)
608 m_change_listener->Changed();
611 std::string TypeCategoryImpl::GetDescription() {
613 stream.Printf("%s (%s", GetName(), (IsEnabled() ? "enabled" : "disabled"));
614 StreamString lang_stream;
615 lang_stream.Printf(", applicable for language(s): ");
616 bool print_lang = false;
617 for (size_t idx = 0; idx < GetNumLanguages(); idx++) {
618 const lldb::LanguageType lang = GetLanguageAtIndex(idx);
619 if (lang != lldb::eLanguageTypeUnknown)
621 lang_stream.Printf("%s%s", Language::GetNameForLanguageType(lang),
622 idx + 1 < GetNumLanguages() ? ", " : "");
625 stream.PutCString(lang_stream.GetString());
627 return stream.GetString();