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 // these are not languages that LLDB would ordinarily deal with
40 // only allow an exact equality here, since we really don't know
42 case eLanguageTypeAda83:
43 case eLanguageTypeCobol74:
44 case eLanguageTypeCobol85:
45 case eLanguageTypeFortran77:
46 case eLanguageTypeFortran90:
47 case eLanguageTypePascal83:
48 case eLanguageTypeModula2:
49 case eLanguageTypeJava:
50 case eLanguageTypeAda95:
51 case eLanguageTypeFortran95:
52 case eLanguageTypePLI:
53 case eLanguageTypeUPC:
55 case eLanguageTypePython:
56 return category_lang == valobj_lang;
58 // the C family, we consider it as one
59 case eLanguageTypeC89:
61 case eLanguageTypeC99:
62 return valobj_lang == eLanguageTypeC89 || valobj_lang == eLanguageTypeC ||
63 valobj_lang == eLanguageTypeC99;
65 // ObjC knows about C and itself
66 case eLanguageTypeObjC:
67 return valobj_lang == eLanguageTypeC89 || valobj_lang == eLanguageTypeC ||
68 valobj_lang == eLanguageTypeC99 || valobj_lang == eLanguageTypeObjC;
70 // C++ knows about C and C++
71 case eLanguageTypeC_plus_plus:
72 return valobj_lang == eLanguageTypeC89 || valobj_lang == eLanguageTypeC ||
73 valobj_lang == eLanguageTypeC99 ||
74 valobj_lang == eLanguageTypeC_plus_plus;
76 // ObjC++ knows about C,C++,ObjC and ObjC++
77 case eLanguageTypeObjC_plus_plus:
78 return valobj_lang == eLanguageTypeC89 || valobj_lang == eLanguageTypeC ||
79 valobj_lang == eLanguageTypeC99 ||
80 valobj_lang == eLanguageTypeC_plus_plus ||
81 valobj_lang == eLanguageTypeObjC;
84 case eLanguageTypeUnknown:
89 bool TypeCategoryImpl::IsApplicable(ValueObject &valobj) {
90 lldb::LanguageType valobj_lang = valobj.GetObjectRuntimeLanguage();
91 for (size_t idx = 0; idx < GetNumLanguages(); idx++) {
92 const lldb::LanguageType category_lang = GetLanguageAtIndex(idx);
93 if (::IsApplicable(category_lang, valobj_lang))
99 size_t TypeCategoryImpl::GetNumLanguages() {
100 if (m_languages.empty())
102 return m_languages.size();
105 lldb::LanguageType TypeCategoryImpl::GetLanguageAtIndex(size_t idx) {
106 if (m_languages.empty())
107 return lldb::eLanguageTypeUnknown;
108 return m_languages[idx];
111 void TypeCategoryImpl::AddLanguage(lldb::LanguageType lang) {
112 m_languages.push_back(lang);
115 bool TypeCategoryImpl::HasLanguage(lldb::LanguageType lang) {
116 const auto iter = std::find(m_languages.begin(), m_languages.end(), lang),
117 end = m_languages.end();
118 return (iter != end);
121 bool TypeCategoryImpl::Get(ValueObject &valobj,
122 const FormattersMatchVector &candidates,
123 lldb::TypeFormatImplSP &entry, uint32_t *reason) {
124 if (!IsEnabled() || !IsApplicable(valobj))
126 if (GetTypeFormatsContainer()->Get(candidates, entry, reason))
128 bool regex = GetRegexTypeFormatsContainer()->Get(candidates, entry, reason);
130 *reason |= lldb_private::eFormatterChoiceCriterionRegularExpressionSummary;
134 bool TypeCategoryImpl::Get(ValueObject &valobj,
135 const FormattersMatchVector &candidates,
136 lldb::TypeSummaryImplSP &entry, uint32_t *reason) {
137 if (!IsEnabled() || !IsApplicable(valobj))
139 if (GetTypeSummariesContainer()->Get(candidates, entry, reason))
141 bool regex = GetRegexTypeSummariesContainer()->Get(candidates, entry, reason);
143 *reason |= lldb_private::eFormatterChoiceCriterionRegularExpressionSummary;
147 bool TypeCategoryImpl::Get(ValueObject &valobj,
148 const FormattersMatchVector &candidates,
149 lldb::SyntheticChildrenSP &entry, uint32_t *reason) {
150 if (!IsEnabled() || !IsApplicable(valobj))
152 TypeFilterImpl::SharedPointer filter_sp;
153 uint32_t reason_filter = 0;
154 bool regex_filter = false;
155 // first find both Filter and Synth, and then check which is most recent
157 if (!GetTypeFiltersContainer()->Get(candidates, filter_sp, &reason_filter))
158 regex_filter = GetRegexTypeFiltersContainer()->Get(candidates, filter_sp,
161 #ifndef LLDB_DISABLE_PYTHON
162 bool regex_synth = false;
163 uint32_t reason_synth = 0;
164 bool pick_synth = false;
165 ScriptedSyntheticChildren::SharedPointer synth;
166 if (!GetTypeSyntheticsContainer()->Get(candidates, synth, &reason_synth))
167 regex_synth = GetRegexTypeSyntheticsContainer()->Get(candidates, synth,
169 if (!filter_sp.get() && !synth.get())
171 else if (!filter_sp.get() && synth.get())
174 else if (filter_sp.get() && !synth.get())
177 else /*if (filter_sp.get() && synth.get())*/
179 if (filter_sp->GetRevision() > synth->GetRevision())
185 if (regex_synth && reason)
186 *reason |= lldb_private::eFormatterChoiceCriterionRegularExpressionFilter;
190 if (regex_filter && reason)
191 *reason |= lldb_private::eFormatterChoiceCriterionRegularExpressionFilter;
206 bool TypeCategoryImpl::Get(ValueObject &valobj,
207 const FormattersMatchVector &candidates,
208 lldb::TypeValidatorImplSP &entry, uint32_t *reason) {
211 if (GetTypeValidatorsContainer()->Get(candidates, entry, reason))
214 GetRegexTypeValidatorsContainer()->Get(candidates, entry, reason);
216 *reason |= lldb_private::eFormatterChoiceCriterionRegularExpressionSummary;
220 void TypeCategoryImpl::Clear(FormatCategoryItems items) {
221 if ((items & eFormatCategoryItemValue) == eFormatCategoryItemValue)
222 GetTypeFormatsContainer()->Clear();
223 if ((items & eFormatCategoryItemRegexValue) == eFormatCategoryItemRegexValue)
224 GetRegexTypeFormatsContainer()->Clear();
226 if ((items & eFormatCategoryItemSummary) == eFormatCategoryItemSummary)
227 GetTypeSummariesContainer()->Clear();
228 if ((items & eFormatCategoryItemRegexSummary) ==
229 eFormatCategoryItemRegexSummary)
230 GetRegexTypeSummariesContainer()->Clear();
232 if ((items & eFormatCategoryItemFilter) == eFormatCategoryItemFilter)
233 GetTypeFiltersContainer()->Clear();
234 if ((items & eFormatCategoryItemRegexFilter) ==
235 eFormatCategoryItemRegexFilter)
236 GetRegexTypeFiltersContainer()->Clear();
238 #ifndef LLDB_DISABLE_PYTHON
239 if ((items & eFormatCategoryItemSynth) == eFormatCategoryItemSynth)
240 GetTypeSyntheticsContainer()->Clear();
241 if ((items & eFormatCategoryItemRegexSynth) == eFormatCategoryItemRegexSynth)
242 GetRegexTypeSyntheticsContainer()->Clear();
245 if ((items & eFormatCategoryItemValidator) == eFormatCategoryItemValidator)
246 GetTypeValidatorsContainer()->Clear();
247 if ((items & eFormatCategoryItemRegexValidator) ==
248 eFormatCategoryItemRegexValidator)
249 GetRegexTypeValidatorsContainer()->Clear();
252 bool TypeCategoryImpl::Delete(ConstString name, FormatCategoryItems items) {
253 bool success = false;
255 if ((items & eFormatCategoryItemValue) == eFormatCategoryItemValue)
256 success = GetTypeFormatsContainer()->Delete(name) || success;
257 if ((items & eFormatCategoryItemRegexValue) == eFormatCategoryItemRegexValue)
258 success = GetRegexTypeFormatsContainer()->Delete(name) || success;
260 if ((items & eFormatCategoryItemSummary) == eFormatCategoryItemSummary)
261 success = GetTypeSummariesContainer()->Delete(name) || success;
262 if ((items & eFormatCategoryItemRegexSummary) ==
263 eFormatCategoryItemRegexSummary)
264 success = GetRegexTypeSummariesContainer()->Delete(name) || success;
266 if ((items & eFormatCategoryItemFilter) == eFormatCategoryItemFilter)
267 success = GetTypeFiltersContainer()->Delete(name) || success;
268 if ((items & eFormatCategoryItemRegexFilter) ==
269 eFormatCategoryItemRegexFilter)
270 success = GetRegexTypeFiltersContainer()->Delete(name) || success;
272 #ifndef LLDB_DISABLE_PYTHON
273 if ((items & eFormatCategoryItemSynth) == eFormatCategoryItemSynth)
274 success = GetTypeSyntheticsContainer()->Delete(name) || success;
275 if ((items & eFormatCategoryItemRegexSynth) == eFormatCategoryItemRegexSynth)
276 success = GetRegexTypeSyntheticsContainer()->Delete(name) || success;
279 if ((items & eFormatCategoryItemValidator) == eFormatCategoryItemValidator)
280 success = GetTypeValidatorsContainer()->Delete(name) || success;
281 if ((items & eFormatCategoryItemRegexValidator) ==
282 eFormatCategoryItemRegexValidator)
283 success = GetRegexTypeValidatorsContainer()->Delete(name) || success;
288 uint32_t TypeCategoryImpl::GetCount(FormatCategoryItems items) {
291 if ((items & eFormatCategoryItemValue) == eFormatCategoryItemValue)
292 count += GetTypeFormatsContainer()->GetCount();
293 if ((items & eFormatCategoryItemRegexValue) == eFormatCategoryItemRegexValue)
294 count += GetRegexTypeFormatsContainer()->GetCount();
296 if ((items & eFormatCategoryItemSummary) == eFormatCategoryItemSummary)
297 count += GetTypeSummariesContainer()->GetCount();
298 if ((items & eFormatCategoryItemRegexSummary) ==
299 eFormatCategoryItemRegexSummary)
300 count += GetRegexTypeSummariesContainer()->GetCount();
302 if ((items & eFormatCategoryItemFilter) == eFormatCategoryItemFilter)
303 count += GetTypeFiltersContainer()->GetCount();
304 if ((items & eFormatCategoryItemRegexFilter) ==
305 eFormatCategoryItemRegexFilter)
306 count += GetRegexTypeFiltersContainer()->GetCount();
308 #ifndef LLDB_DISABLE_PYTHON
309 if ((items & eFormatCategoryItemSynth) == eFormatCategoryItemSynth)
310 count += GetTypeSyntheticsContainer()->GetCount();
311 if ((items & eFormatCategoryItemRegexSynth) == eFormatCategoryItemRegexSynth)
312 count += GetRegexTypeSyntheticsContainer()->GetCount();
315 if ((items & eFormatCategoryItemValidator) == eFormatCategoryItemValidator)
316 count += GetTypeValidatorsContainer()->GetCount();
317 if ((items & eFormatCategoryItemRegexValidator) ==
318 eFormatCategoryItemRegexValidator)
319 count += GetRegexTypeValidatorsContainer()->GetCount();
324 bool TypeCategoryImpl::AnyMatches(ConstString type_name,
325 FormatCategoryItems items, bool only_enabled,
326 const char **matching_category,
327 FormatCategoryItems *matching_type) {
328 if (!IsEnabled() && only_enabled)
331 lldb::TypeFormatImplSP format_sp;
332 lldb::TypeSummaryImplSP summary_sp;
333 TypeFilterImpl::SharedPointer filter_sp;
334 #ifndef LLDB_DISABLE_PYTHON
335 ScriptedSyntheticChildren::SharedPointer synth_sp;
337 TypeValidatorImpl::SharedPointer validator_sp;
339 if ((items & eFormatCategoryItemValue) == eFormatCategoryItemValue) {
340 if (GetTypeFormatsContainer()->Get(type_name, format_sp)) {
341 if (matching_category)
342 *matching_category = m_name.GetCString();
344 *matching_type = eFormatCategoryItemValue;
348 if ((items & eFormatCategoryItemRegexValue) ==
349 eFormatCategoryItemRegexValue) {
350 if (GetRegexTypeFormatsContainer()->Get(type_name, format_sp)) {
351 if (matching_category)
352 *matching_category = m_name.GetCString();
354 *matching_type = eFormatCategoryItemRegexValue;
359 if ((items & eFormatCategoryItemSummary) == eFormatCategoryItemSummary) {
360 if (GetTypeSummariesContainer()->Get(type_name, summary_sp)) {
361 if (matching_category)
362 *matching_category = m_name.GetCString();
364 *matching_type = eFormatCategoryItemSummary;
368 if ((items & eFormatCategoryItemRegexSummary) ==
369 eFormatCategoryItemRegexSummary) {
370 if (GetRegexTypeSummariesContainer()->Get(type_name, summary_sp)) {
371 if (matching_category)
372 *matching_category = m_name.GetCString();
374 *matching_type = eFormatCategoryItemRegexSummary;
379 if ((items & eFormatCategoryItemFilter) == eFormatCategoryItemFilter) {
380 if (GetTypeFiltersContainer()->Get(type_name, filter_sp)) {
381 if (matching_category)
382 *matching_category = m_name.GetCString();
384 *matching_type = eFormatCategoryItemFilter;
388 if ((items & eFormatCategoryItemRegexFilter) ==
389 eFormatCategoryItemRegexFilter) {
390 if (GetRegexTypeFiltersContainer()->Get(type_name, filter_sp)) {
391 if (matching_category)
392 *matching_category = m_name.GetCString();
394 *matching_type = eFormatCategoryItemRegexFilter;
399 #ifndef LLDB_DISABLE_PYTHON
400 if ((items & eFormatCategoryItemSynth) == eFormatCategoryItemSynth) {
401 if (GetTypeSyntheticsContainer()->Get(type_name, synth_sp)) {
402 if (matching_category)
403 *matching_category = m_name.GetCString();
405 *matching_type = eFormatCategoryItemSynth;
409 if ((items & eFormatCategoryItemRegexSynth) ==
410 eFormatCategoryItemRegexSynth) {
411 if (GetRegexTypeSyntheticsContainer()->Get(type_name, synth_sp)) {
412 if (matching_category)
413 *matching_category = m_name.GetCString();
415 *matching_type = eFormatCategoryItemRegexSynth;
421 if ((items & eFormatCategoryItemValidator) == eFormatCategoryItemValidator) {
422 if (GetTypeValidatorsContainer()->Get(type_name, validator_sp)) {
423 if (matching_category)
424 *matching_category = m_name.GetCString();
426 *matching_type = eFormatCategoryItemValidator;
430 if ((items & eFormatCategoryItemRegexValidator) ==
431 eFormatCategoryItemRegexValidator) {
432 if (GetRegexTypeValidatorsContainer()->Get(type_name, validator_sp)) {
433 if (matching_category)
434 *matching_category = m_name.GetCString();
436 *matching_type = eFormatCategoryItemRegexValidator;
444 TypeCategoryImpl::FormatContainer::MapValueType
445 TypeCategoryImpl::GetFormatForType(lldb::TypeNameSpecifierImplSP type_sp) {
446 FormatContainer::MapValueType retval;
449 if (type_sp->IsRegex())
450 GetRegexTypeFormatsContainer()->GetExact(ConstString(type_sp->GetName()),
453 GetTypeFormatsContainer()->GetExact(ConstString(type_sp->GetName()),
460 TypeCategoryImpl::SummaryContainer::MapValueType
461 TypeCategoryImpl::GetSummaryForType(lldb::TypeNameSpecifierImplSP type_sp) {
462 SummaryContainer::MapValueType retval;
465 if (type_sp->IsRegex())
466 GetRegexTypeSummariesContainer()->GetExact(
467 ConstString(type_sp->GetName()), retval);
469 GetTypeSummariesContainer()->GetExact(ConstString(type_sp->GetName()),
476 TypeCategoryImpl::FilterContainer::MapValueType
477 TypeCategoryImpl::GetFilterForType(lldb::TypeNameSpecifierImplSP type_sp) {
478 FilterContainer::MapValueType retval;
481 if (type_sp->IsRegex())
482 GetRegexTypeFiltersContainer()->GetExact(ConstString(type_sp->GetName()),
485 GetTypeFiltersContainer()->GetExact(ConstString(type_sp->GetName()),
492 #ifndef LLDB_DISABLE_PYTHON
493 TypeCategoryImpl::SynthContainer::MapValueType
494 TypeCategoryImpl::GetSyntheticForType(lldb::TypeNameSpecifierImplSP type_sp) {
495 SynthContainer::MapValueType retval;
498 if (type_sp->IsRegex())
499 GetRegexTypeSyntheticsContainer()->GetExact(
500 ConstString(type_sp->GetName()), retval);
502 GetTypeSyntheticsContainer()->GetExact(ConstString(type_sp->GetName()),
510 TypeCategoryImpl::ValidatorContainer::MapValueType
511 TypeCategoryImpl::GetValidatorForType(lldb::TypeNameSpecifierImplSP type_sp) {
512 ValidatorContainer::MapValueType retval;
515 if (type_sp->IsRegex())
516 GetRegexTypeValidatorsContainer()->GetExact(
517 ConstString(type_sp->GetName()), retval);
519 GetTypeValidatorsContainer()->GetExact(ConstString(type_sp->GetName()),
526 lldb::TypeNameSpecifierImplSP
527 TypeCategoryImpl::GetTypeNameSpecifierForSummaryAtIndex(size_t index) {
528 if (index < GetTypeSummariesContainer()->GetCount())
529 return GetTypeSummariesContainer()->GetTypeNameSpecifierAtIndex(index);
531 return GetRegexTypeSummariesContainer()->GetTypeNameSpecifierAtIndex(
532 index - GetTypeSummariesContainer()->GetCount());
535 TypeCategoryImpl::FormatContainer::MapValueType
536 TypeCategoryImpl::GetFormatAtIndex(size_t index) {
537 if (index < GetTypeFormatsContainer()->GetCount())
538 return GetTypeFormatsContainer()->GetAtIndex(index);
540 return GetRegexTypeFormatsContainer()->GetAtIndex(
541 index - GetTypeFormatsContainer()->GetCount());
544 TypeCategoryImpl::SummaryContainer::MapValueType
545 TypeCategoryImpl::GetSummaryAtIndex(size_t index) {
546 if (index < GetTypeSummariesContainer()->GetCount())
547 return GetTypeSummariesContainer()->GetAtIndex(index);
549 return GetRegexTypeSummariesContainer()->GetAtIndex(
550 index - GetTypeSummariesContainer()->GetCount());
553 TypeCategoryImpl::FilterContainer::MapValueType
554 TypeCategoryImpl::GetFilterAtIndex(size_t index) {
555 if (index < GetTypeFiltersContainer()->GetCount())
556 return GetTypeFiltersContainer()->GetAtIndex(index);
558 return GetRegexTypeFiltersContainer()->GetAtIndex(
559 index - GetTypeFiltersContainer()->GetCount());
562 lldb::TypeNameSpecifierImplSP
563 TypeCategoryImpl::GetTypeNameSpecifierForFormatAtIndex(size_t index) {
564 if (index < GetTypeFormatsContainer()->GetCount())
565 return GetTypeFormatsContainer()->GetTypeNameSpecifierAtIndex(index);
567 return GetRegexTypeFormatsContainer()->GetTypeNameSpecifierAtIndex(
568 index - GetTypeFormatsContainer()->GetCount());
571 lldb::TypeNameSpecifierImplSP
572 TypeCategoryImpl::GetTypeNameSpecifierForFilterAtIndex(size_t index) {
573 if (index < GetTypeFiltersContainer()->GetCount())
574 return GetTypeFiltersContainer()->GetTypeNameSpecifierAtIndex(index);
576 return GetRegexTypeFiltersContainer()->GetTypeNameSpecifierAtIndex(
577 index - GetTypeFiltersContainer()->GetCount());
580 #ifndef LLDB_DISABLE_PYTHON
581 TypeCategoryImpl::SynthContainer::MapValueType
582 TypeCategoryImpl::GetSyntheticAtIndex(size_t index) {
583 if (index < GetTypeSyntheticsContainer()->GetCount())
584 return GetTypeSyntheticsContainer()->GetAtIndex(index);
586 return GetRegexTypeSyntheticsContainer()->GetAtIndex(
587 index - GetTypeSyntheticsContainer()->GetCount());
590 lldb::TypeNameSpecifierImplSP
591 TypeCategoryImpl::GetTypeNameSpecifierForSyntheticAtIndex(size_t index) {
592 if (index < GetTypeSyntheticsContainer()->GetCount())
593 return GetTypeSyntheticsContainer()->GetTypeNameSpecifierAtIndex(index);
595 return GetRegexTypeSyntheticsContainer()->GetTypeNameSpecifierAtIndex(
596 index - GetTypeSyntheticsContainer()->GetCount());
600 TypeCategoryImpl::ValidatorContainer::MapValueType
601 TypeCategoryImpl::GetValidatorAtIndex(size_t index) {
602 if (index < GetTypeValidatorsContainer()->GetCount())
603 return GetTypeValidatorsContainer()->GetAtIndex(index);
605 return GetRegexTypeValidatorsContainer()->GetAtIndex(
606 index - GetTypeValidatorsContainer()->GetCount());
609 lldb::TypeNameSpecifierImplSP
610 TypeCategoryImpl::GetTypeNameSpecifierForValidatorAtIndex(size_t index) {
611 if (index < GetTypeValidatorsContainer()->GetCount())
612 return GetTypeValidatorsContainer()->GetTypeNameSpecifierAtIndex(index);
614 return GetRegexTypeValidatorsContainer()->GetTypeNameSpecifierAtIndex(
615 index - GetTypeValidatorsContainer()->GetCount());
618 void TypeCategoryImpl::Enable(bool value, uint32_t position) {
619 std::lock_guard<std::recursive_mutex> guard(m_mutex);
620 if ((m_enabled = value))
621 m_enabled_position = position;
622 if (m_change_listener)
623 m_change_listener->Changed();
626 std::string TypeCategoryImpl::GetDescription() {
628 stream.Printf("%s (%s", GetName(), (IsEnabled() ? "enabled" : "disabled"));
629 StreamString lang_stream;
630 lang_stream.Printf(", applicable for language(s): ");
631 bool print_lang = false;
632 for (size_t idx = 0; idx < GetNumLanguages(); idx++) {
633 const lldb::LanguageType lang = GetLanguageAtIndex(idx);
634 if (lang != lldb::eLanguageTypeUnknown)
636 lang_stream.Printf("%s%s", Language::GetNameForLanguageType(lang),
637 idx + 1 < GetNumLanguages() ? ", " : "");
640 stream.PutCString(lang_stream.GetString());
642 return stream.GetString();