1 //===-- TypeCategory.cpp -----------------------------------------*- C++-*-===//
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
7 //===----------------------------------------------------------------------===//
9 #include "lldb/DataFormatters/TypeCategory.h"
10 #include "lldb/Target/Language.h"
14 using namespace lldb_private;
16 TypeCategoryImpl::TypeCategoryImpl(
17 IFormatChangeListener *clist, ConstString name,
18 std::initializer_list<lldb::LanguageType> langs)
19 : m_format_cont("format", "regex-format", clist),
20 m_summary_cont("summary", "regex-summary", clist),
21 m_filter_cont("filter", "regex-filter", clist),
22 m_synth_cont("synth", "regex-synth", clist),
23 m_validator_cont("validator", "regex-validator", clist), m_enabled(false),
24 m_change_listener(clist), m_mutex(), m_name(name), m_languages() {
25 for (const lldb::LanguageType lang : langs)
29 static bool IsApplicable(lldb::LanguageType category_lang,
30 lldb::LanguageType valobj_lang) {
31 switch (category_lang) {
32 // Unless we know better, allow only exact equality.
34 return category_lang == valobj_lang;
36 // the C family, we consider it as one
37 case eLanguageTypeC89:
39 case eLanguageTypeC99:
40 return valobj_lang == eLanguageTypeC89 || valobj_lang == eLanguageTypeC ||
41 valobj_lang == eLanguageTypeC99;
43 // ObjC knows about C and itself
44 case eLanguageTypeObjC:
45 return valobj_lang == eLanguageTypeC89 || valobj_lang == eLanguageTypeC ||
46 valobj_lang == eLanguageTypeC99 || valobj_lang == eLanguageTypeObjC;
48 // C++ knows about C and C++
49 case eLanguageTypeC_plus_plus:
50 return valobj_lang == eLanguageTypeC89 || valobj_lang == eLanguageTypeC ||
51 valobj_lang == eLanguageTypeC99 ||
52 valobj_lang == eLanguageTypeC_plus_plus;
54 // ObjC++ knows about C,C++,ObjC and ObjC++
55 case eLanguageTypeObjC_plus_plus:
56 return valobj_lang == eLanguageTypeC89 || valobj_lang == eLanguageTypeC ||
57 valobj_lang == eLanguageTypeC99 ||
58 valobj_lang == eLanguageTypeC_plus_plus ||
59 valobj_lang == eLanguageTypeObjC;
61 // Categories with unspecified language match everything.
62 case eLanguageTypeUnknown:
67 bool TypeCategoryImpl::IsApplicable(ValueObject &valobj) {
68 lldb::LanguageType valobj_lang = valobj.GetObjectRuntimeLanguage();
69 for (size_t idx = 0; idx < GetNumLanguages(); idx++) {
70 const lldb::LanguageType category_lang = GetLanguageAtIndex(idx);
71 if (::IsApplicable(category_lang, valobj_lang))
77 size_t TypeCategoryImpl::GetNumLanguages() {
78 if (m_languages.empty())
80 return m_languages.size();
83 lldb::LanguageType TypeCategoryImpl::GetLanguageAtIndex(size_t idx) {
84 if (m_languages.empty())
85 return lldb::eLanguageTypeUnknown;
86 return m_languages[idx];
89 void TypeCategoryImpl::AddLanguage(lldb::LanguageType lang) {
90 m_languages.push_back(lang);
93 bool TypeCategoryImpl::HasLanguage(lldb::LanguageType lang) {
94 const auto iter = std::find(m_languages.begin(), m_languages.end(), lang),
95 end = m_languages.end();
99 bool TypeCategoryImpl::Get(ValueObject &valobj,
100 const FormattersMatchVector &candidates,
101 lldb::TypeFormatImplSP &entry, uint32_t *reason) {
102 if (!IsEnabled() || !IsApplicable(valobj))
104 if (GetTypeFormatsContainer()->Get(candidates, entry, reason))
106 bool regex = GetRegexTypeFormatsContainer()->Get(candidates, entry, reason);
108 *reason |= lldb_private::eFormatterChoiceCriterionRegularExpressionSummary;
112 bool TypeCategoryImpl::Get(ValueObject &valobj,
113 const FormattersMatchVector &candidates,
114 lldb::TypeSummaryImplSP &entry, uint32_t *reason) {
115 if (!IsEnabled() || !IsApplicable(valobj))
117 if (GetTypeSummariesContainer()->Get(candidates, entry, reason))
119 bool regex = GetRegexTypeSummariesContainer()->Get(candidates, entry, reason);
121 *reason |= lldb_private::eFormatterChoiceCriterionRegularExpressionSummary;
125 bool TypeCategoryImpl::Get(ValueObject &valobj,
126 const FormattersMatchVector &candidates,
127 lldb::SyntheticChildrenSP &entry, uint32_t *reason) {
128 if (!IsEnabled() || !IsApplicable(valobj))
130 TypeFilterImpl::SharedPointer filter_sp;
131 uint32_t reason_filter = 0;
132 bool regex_filter = false;
133 // first find both Filter and Synth, and then check which is most recent
135 if (!GetTypeFiltersContainer()->Get(candidates, filter_sp, &reason_filter))
136 regex_filter = GetRegexTypeFiltersContainer()->Get(candidates, filter_sp,
139 bool regex_synth = false;
140 uint32_t reason_synth = 0;
141 bool pick_synth = false;
142 ScriptedSyntheticChildren::SharedPointer synth;
143 if (!GetTypeSyntheticsContainer()->Get(candidates, synth, &reason_synth))
144 regex_synth = GetRegexTypeSyntheticsContainer()->Get(candidates, synth,
146 if (!filter_sp.get() && !synth.get())
148 else if (!filter_sp.get() && synth.get())
151 else if (filter_sp.get() && !synth.get())
154 else /*if (filter_sp.get() && synth.get())*/
156 pick_synth = filter_sp->GetRevision() <= synth->GetRevision();
159 if (regex_synth && reason)
160 *reason |= lldb_private::eFormatterChoiceCriterionRegularExpressionFilter;
164 if (regex_filter && reason)
165 *reason |= lldb_private::eFormatterChoiceCriterionRegularExpressionFilter;
172 bool TypeCategoryImpl::Get(ValueObject &valobj,
173 const FormattersMatchVector &candidates,
174 lldb::TypeValidatorImplSP &entry, uint32_t *reason) {
177 if (GetTypeValidatorsContainer()->Get(candidates, entry, reason))
180 GetRegexTypeValidatorsContainer()->Get(candidates, entry, reason);
182 *reason |= lldb_private::eFormatterChoiceCriterionRegularExpressionSummary;
186 void TypeCategoryImpl::Clear(FormatCategoryItems items) {
187 if ((items & eFormatCategoryItemValue) == eFormatCategoryItemValue)
188 GetTypeFormatsContainer()->Clear();
189 if ((items & eFormatCategoryItemRegexValue) == eFormatCategoryItemRegexValue)
190 GetRegexTypeFormatsContainer()->Clear();
192 if ((items & eFormatCategoryItemSummary) == eFormatCategoryItemSummary)
193 GetTypeSummariesContainer()->Clear();
194 if ((items & eFormatCategoryItemRegexSummary) ==
195 eFormatCategoryItemRegexSummary)
196 GetRegexTypeSummariesContainer()->Clear();
198 if ((items & eFormatCategoryItemFilter) == eFormatCategoryItemFilter)
199 GetTypeFiltersContainer()->Clear();
200 if ((items & eFormatCategoryItemRegexFilter) ==
201 eFormatCategoryItemRegexFilter)
202 GetRegexTypeFiltersContainer()->Clear();
204 if ((items & eFormatCategoryItemSynth) == eFormatCategoryItemSynth)
205 GetTypeSyntheticsContainer()->Clear();
206 if ((items & eFormatCategoryItemRegexSynth) == eFormatCategoryItemRegexSynth)
207 GetRegexTypeSyntheticsContainer()->Clear();
209 if ((items & eFormatCategoryItemValidator) == eFormatCategoryItemValidator)
210 GetTypeValidatorsContainer()->Clear();
211 if ((items & eFormatCategoryItemRegexValidator) ==
212 eFormatCategoryItemRegexValidator)
213 GetRegexTypeValidatorsContainer()->Clear();
216 bool TypeCategoryImpl::Delete(ConstString name, FormatCategoryItems items) {
217 bool success = false;
219 if ((items & eFormatCategoryItemValue) == eFormatCategoryItemValue)
220 success = GetTypeFormatsContainer()->Delete(name) || success;
221 if ((items & eFormatCategoryItemRegexValue) == eFormatCategoryItemRegexValue)
222 success = GetRegexTypeFormatsContainer()->Delete(name) || success;
224 if ((items & eFormatCategoryItemSummary) == eFormatCategoryItemSummary)
225 success = GetTypeSummariesContainer()->Delete(name) || success;
226 if ((items & eFormatCategoryItemRegexSummary) ==
227 eFormatCategoryItemRegexSummary)
228 success = GetRegexTypeSummariesContainer()->Delete(name) || success;
230 if ((items & eFormatCategoryItemFilter) == eFormatCategoryItemFilter)
231 success = GetTypeFiltersContainer()->Delete(name) || success;
232 if ((items & eFormatCategoryItemRegexFilter) ==
233 eFormatCategoryItemRegexFilter)
234 success = GetRegexTypeFiltersContainer()->Delete(name) || success;
236 if ((items & eFormatCategoryItemSynth) == eFormatCategoryItemSynth)
237 success = GetTypeSyntheticsContainer()->Delete(name) || success;
238 if ((items & eFormatCategoryItemRegexSynth) == eFormatCategoryItemRegexSynth)
239 success = GetRegexTypeSyntheticsContainer()->Delete(name) || success;
241 if ((items & eFormatCategoryItemValidator) == eFormatCategoryItemValidator)
242 success = GetTypeValidatorsContainer()->Delete(name) || success;
243 if ((items & eFormatCategoryItemRegexValidator) ==
244 eFormatCategoryItemRegexValidator)
245 success = GetRegexTypeValidatorsContainer()->Delete(name) || success;
250 uint32_t TypeCategoryImpl::GetCount(FormatCategoryItems items) {
253 if ((items & eFormatCategoryItemValue) == eFormatCategoryItemValue)
254 count += GetTypeFormatsContainer()->GetCount();
255 if ((items & eFormatCategoryItemRegexValue) == eFormatCategoryItemRegexValue)
256 count += GetRegexTypeFormatsContainer()->GetCount();
258 if ((items & eFormatCategoryItemSummary) == eFormatCategoryItemSummary)
259 count += GetTypeSummariesContainer()->GetCount();
260 if ((items & eFormatCategoryItemRegexSummary) ==
261 eFormatCategoryItemRegexSummary)
262 count += GetRegexTypeSummariesContainer()->GetCount();
264 if ((items & eFormatCategoryItemFilter) == eFormatCategoryItemFilter)
265 count += GetTypeFiltersContainer()->GetCount();
266 if ((items & eFormatCategoryItemRegexFilter) ==
267 eFormatCategoryItemRegexFilter)
268 count += GetRegexTypeFiltersContainer()->GetCount();
270 if ((items & eFormatCategoryItemSynth) == eFormatCategoryItemSynth)
271 count += GetTypeSyntheticsContainer()->GetCount();
272 if ((items & eFormatCategoryItemRegexSynth) == eFormatCategoryItemRegexSynth)
273 count += GetRegexTypeSyntheticsContainer()->GetCount();
275 if ((items & eFormatCategoryItemValidator) == eFormatCategoryItemValidator)
276 count += GetTypeValidatorsContainer()->GetCount();
277 if ((items & eFormatCategoryItemRegexValidator) ==
278 eFormatCategoryItemRegexValidator)
279 count += GetRegexTypeValidatorsContainer()->GetCount();
284 bool TypeCategoryImpl::AnyMatches(ConstString type_name,
285 FormatCategoryItems items, bool only_enabled,
286 const char **matching_category,
287 FormatCategoryItems *matching_type) {
288 if (!IsEnabled() && only_enabled)
291 lldb::TypeFormatImplSP format_sp;
292 lldb::TypeSummaryImplSP summary_sp;
293 TypeFilterImpl::SharedPointer filter_sp;
294 ScriptedSyntheticChildren::SharedPointer synth_sp;
295 TypeValidatorImpl::SharedPointer validator_sp;
297 if ((items & eFormatCategoryItemValue) == eFormatCategoryItemValue) {
298 if (GetTypeFormatsContainer()->Get(type_name, format_sp)) {
299 if (matching_category)
300 *matching_category = m_name.GetCString();
302 *matching_type = eFormatCategoryItemValue;
306 if ((items & eFormatCategoryItemRegexValue) ==
307 eFormatCategoryItemRegexValue) {
308 if (GetRegexTypeFormatsContainer()->Get(type_name, format_sp)) {
309 if (matching_category)
310 *matching_category = m_name.GetCString();
312 *matching_type = eFormatCategoryItemRegexValue;
317 if ((items & eFormatCategoryItemSummary) == eFormatCategoryItemSummary) {
318 if (GetTypeSummariesContainer()->Get(type_name, summary_sp)) {
319 if (matching_category)
320 *matching_category = m_name.GetCString();
322 *matching_type = eFormatCategoryItemSummary;
326 if ((items & eFormatCategoryItemRegexSummary) ==
327 eFormatCategoryItemRegexSummary) {
328 if (GetRegexTypeSummariesContainer()->Get(type_name, summary_sp)) {
329 if (matching_category)
330 *matching_category = m_name.GetCString();
332 *matching_type = eFormatCategoryItemRegexSummary;
337 if ((items & eFormatCategoryItemFilter) == eFormatCategoryItemFilter) {
338 if (GetTypeFiltersContainer()->Get(type_name, filter_sp)) {
339 if (matching_category)
340 *matching_category = m_name.GetCString();
342 *matching_type = eFormatCategoryItemFilter;
346 if ((items & eFormatCategoryItemRegexFilter) ==
347 eFormatCategoryItemRegexFilter) {
348 if (GetRegexTypeFiltersContainer()->Get(type_name, filter_sp)) {
349 if (matching_category)
350 *matching_category = m_name.GetCString();
352 *matching_type = eFormatCategoryItemRegexFilter;
357 if ((items & eFormatCategoryItemSynth) == eFormatCategoryItemSynth) {
358 if (GetTypeSyntheticsContainer()->Get(type_name, synth_sp)) {
359 if (matching_category)
360 *matching_category = m_name.GetCString();
362 *matching_type = eFormatCategoryItemSynth;
366 if ((items & eFormatCategoryItemRegexSynth) ==
367 eFormatCategoryItemRegexSynth) {
368 if (GetRegexTypeSyntheticsContainer()->Get(type_name, synth_sp)) {
369 if (matching_category)
370 *matching_category = m_name.GetCString();
372 *matching_type = eFormatCategoryItemRegexSynth;
377 if ((items & eFormatCategoryItemValidator) == eFormatCategoryItemValidator) {
378 if (GetTypeValidatorsContainer()->Get(type_name, validator_sp)) {
379 if (matching_category)
380 *matching_category = m_name.GetCString();
382 *matching_type = eFormatCategoryItemValidator;
386 if ((items & eFormatCategoryItemRegexValidator) ==
387 eFormatCategoryItemRegexValidator) {
388 if (GetRegexTypeValidatorsContainer()->Get(type_name, validator_sp)) {
389 if (matching_category)
390 *matching_category = m_name.GetCString();
392 *matching_type = eFormatCategoryItemRegexValidator;
400 TypeCategoryImpl::FormatContainer::MapValueType
401 TypeCategoryImpl::GetFormatForType(lldb::TypeNameSpecifierImplSP type_sp) {
402 FormatContainer::MapValueType retval;
405 if (type_sp->IsRegex())
406 GetRegexTypeFormatsContainer()->GetExact(ConstString(type_sp->GetName()),
409 GetTypeFormatsContainer()->GetExact(ConstString(type_sp->GetName()),
416 TypeCategoryImpl::SummaryContainer::MapValueType
417 TypeCategoryImpl::GetSummaryForType(lldb::TypeNameSpecifierImplSP type_sp) {
418 SummaryContainer::MapValueType retval;
421 if (type_sp->IsRegex())
422 GetRegexTypeSummariesContainer()->GetExact(
423 ConstString(type_sp->GetName()), retval);
425 GetTypeSummariesContainer()->GetExact(ConstString(type_sp->GetName()),
432 TypeCategoryImpl::FilterContainer::MapValueType
433 TypeCategoryImpl::GetFilterForType(lldb::TypeNameSpecifierImplSP type_sp) {
434 FilterContainer::MapValueType retval;
437 if (type_sp->IsRegex())
438 GetRegexTypeFiltersContainer()->GetExact(ConstString(type_sp->GetName()),
441 GetTypeFiltersContainer()->GetExact(ConstString(type_sp->GetName()),
448 TypeCategoryImpl::SynthContainer::MapValueType
449 TypeCategoryImpl::GetSyntheticForType(lldb::TypeNameSpecifierImplSP type_sp) {
450 SynthContainer::MapValueType retval;
453 if (type_sp->IsRegex())
454 GetRegexTypeSyntheticsContainer()->GetExact(
455 ConstString(type_sp->GetName()), retval);
457 GetTypeSyntheticsContainer()->GetExact(ConstString(type_sp->GetName()),
464 TypeCategoryImpl::ValidatorContainer::MapValueType
465 TypeCategoryImpl::GetValidatorForType(lldb::TypeNameSpecifierImplSP type_sp) {
466 ValidatorContainer::MapValueType retval;
469 if (type_sp->IsRegex())
470 GetRegexTypeValidatorsContainer()->GetExact(
471 ConstString(type_sp->GetName()), retval);
473 GetTypeValidatorsContainer()->GetExact(ConstString(type_sp->GetName()),
480 lldb::TypeNameSpecifierImplSP
481 TypeCategoryImpl::GetTypeNameSpecifierForSummaryAtIndex(size_t index) {
482 if (index < GetTypeSummariesContainer()->GetCount())
483 return GetTypeSummariesContainer()->GetTypeNameSpecifierAtIndex(index);
485 return GetRegexTypeSummariesContainer()->GetTypeNameSpecifierAtIndex(
486 index - GetTypeSummariesContainer()->GetCount());
489 TypeCategoryImpl::FormatContainer::MapValueType
490 TypeCategoryImpl::GetFormatAtIndex(size_t index) {
491 if (index < GetTypeFormatsContainer()->GetCount())
492 return GetTypeFormatsContainer()->GetAtIndex(index);
494 return GetRegexTypeFormatsContainer()->GetAtIndex(
495 index - GetTypeFormatsContainer()->GetCount());
498 TypeCategoryImpl::SummaryContainer::MapValueType
499 TypeCategoryImpl::GetSummaryAtIndex(size_t index) {
500 if (index < GetTypeSummariesContainer()->GetCount())
501 return GetTypeSummariesContainer()->GetAtIndex(index);
503 return GetRegexTypeSummariesContainer()->GetAtIndex(
504 index - GetTypeSummariesContainer()->GetCount());
507 TypeCategoryImpl::FilterContainer::MapValueType
508 TypeCategoryImpl::GetFilterAtIndex(size_t index) {
509 if (index < GetTypeFiltersContainer()->GetCount())
510 return GetTypeFiltersContainer()->GetAtIndex(index);
512 return GetRegexTypeFiltersContainer()->GetAtIndex(
513 index - GetTypeFiltersContainer()->GetCount());
516 lldb::TypeNameSpecifierImplSP
517 TypeCategoryImpl::GetTypeNameSpecifierForFormatAtIndex(size_t index) {
518 if (index < GetTypeFormatsContainer()->GetCount())
519 return GetTypeFormatsContainer()->GetTypeNameSpecifierAtIndex(index);
521 return GetRegexTypeFormatsContainer()->GetTypeNameSpecifierAtIndex(
522 index - GetTypeFormatsContainer()->GetCount());
525 lldb::TypeNameSpecifierImplSP
526 TypeCategoryImpl::GetTypeNameSpecifierForFilterAtIndex(size_t index) {
527 if (index < GetTypeFiltersContainer()->GetCount())
528 return GetTypeFiltersContainer()->GetTypeNameSpecifierAtIndex(index);
530 return GetRegexTypeFiltersContainer()->GetTypeNameSpecifierAtIndex(
531 index - GetTypeFiltersContainer()->GetCount());
534 TypeCategoryImpl::SynthContainer::MapValueType
535 TypeCategoryImpl::GetSyntheticAtIndex(size_t index) {
536 if (index < GetTypeSyntheticsContainer()->GetCount())
537 return GetTypeSyntheticsContainer()->GetAtIndex(index);
539 return GetRegexTypeSyntheticsContainer()->GetAtIndex(
540 index - GetTypeSyntheticsContainer()->GetCount());
543 lldb::TypeNameSpecifierImplSP
544 TypeCategoryImpl::GetTypeNameSpecifierForSyntheticAtIndex(size_t index) {
545 if (index < GetTypeSyntheticsContainer()->GetCount())
546 return GetTypeSyntheticsContainer()->GetTypeNameSpecifierAtIndex(index);
548 return GetRegexTypeSyntheticsContainer()->GetTypeNameSpecifierAtIndex(
549 index - GetTypeSyntheticsContainer()->GetCount());
552 TypeCategoryImpl::ValidatorContainer::MapValueType
553 TypeCategoryImpl::GetValidatorAtIndex(size_t index) {
554 if (index < GetTypeValidatorsContainer()->GetCount())
555 return GetTypeValidatorsContainer()->GetAtIndex(index);
557 return GetRegexTypeValidatorsContainer()->GetAtIndex(
558 index - GetTypeValidatorsContainer()->GetCount());
561 lldb::TypeNameSpecifierImplSP
562 TypeCategoryImpl::GetTypeNameSpecifierForValidatorAtIndex(size_t index) {
563 if (index < GetTypeValidatorsContainer()->GetCount())
564 return GetTypeValidatorsContainer()->GetTypeNameSpecifierAtIndex(index);
566 return GetRegexTypeValidatorsContainer()->GetTypeNameSpecifierAtIndex(
567 index - GetTypeValidatorsContainer()->GetCount());
570 void TypeCategoryImpl::Enable(bool value, uint32_t position) {
571 std::lock_guard<std::recursive_mutex> guard(m_mutex);
572 if ((m_enabled = value))
573 m_enabled_position = position;
574 if (m_change_listener)
575 m_change_listener->Changed();
578 std::string TypeCategoryImpl::GetDescription() {
580 stream.Printf("%s (%s", GetName(), (IsEnabled() ? "enabled" : "disabled"));
581 StreamString lang_stream;
582 lang_stream.Printf(", applicable for language(s): ");
583 bool print_lang = false;
584 for (size_t idx = 0; idx < GetNumLanguages(); idx++) {
585 const lldb::LanguageType lang = GetLanguageAtIndex(idx);
586 if (lang != lldb::eLanguageTypeUnknown)
588 lang_stream.Printf("%s%s", Language::GetNameForLanguageType(lang),
589 idx + 1 < GetNumLanguages() ? ", " : "");
592 stream.PutCString(lang_stream.GetString());
594 return stream.GetString();