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(IFormatChangeListener *clist,
18 : m_format_cont("format", "regex-format", clist),
19 m_summary_cont("summary", "regex-summary", clist),
20 m_filter_cont("filter", "regex-filter", clist),
21 m_synth_cont("synth", "regex-synth", clist), m_enabled(false),
22 m_change_listener(clist), m_mutex(), m_name(name), m_languages() {}
24 static bool IsApplicable(lldb::LanguageType category_lang,
25 lldb::LanguageType valobj_lang) {
26 switch (category_lang) {
27 // Unless we know better, allow only exact equality.
29 return category_lang == valobj_lang;
31 // the C family, we consider it as one
32 case eLanguageTypeC89:
34 case eLanguageTypeC99:
35 return valobj_lang == eLanguageTypeC89 || valobj_lang == eLanguageTypeC ||
36 valobj_lang == eLanguageTypeC99;
38 // ObjC knows about C and itself
39 case eLanguageTypeObjC:
40 return valobj_lang == eLanguageTypeC89 || valobj_lang == eLanguageTypeC ||
41 valobj_lang == eLanguageTypeC99 || valobj_lang == eLanguageTypeObjC;
43 // C++ knows about C and C++
44 case eLanguageTypeC_plus_plus:
45 return valobj_lang == eLanguageTypeC89 || valobj_lang == eLanguageTypeC ||
46 valobj_lang == eLanguageTypeC99 ||
47 valobj_lang == eLanguageTypeC_plus_plus;
49 // ObjC++ knows about C,C++,ObjC and ObjC++
50 case eLanguageTypeObjC_plus_plus:
51 return valobj_lang == eLanguageTypeC89 || valobj_lang == eLanguageTypeC ||
52 valobj_lang == eLanguageTypeC99 ||
53 valobj_lang == eLanguageTypeC_plus_plus ||
54 valobj_lang == eLanguageTypeObjC;
56 // Categories with unspecified language match everything.
57 case eLanguageTypeUnknown:
62 bool TypeCategoryImpl::IsApplicable(lldb::LanguageType lang) {
63 for (size_t idx = 0; idx < GetNumLanguages(); idx++) {
64 const lldb::LanguageType category_lang = GetLanguageAtIndex(idx);
65 if (::IsApplicable(category_lang, lang))
71 size_t TypeCategoryImpl::GetNumLanguages() {
72 if (m_languages.empty())
74 return m_languages.size();
77 lldb::LanguageType TypeCategoryImpl::GetLanguageAtIndex(size_t idx) {
78 if (m_languages.empty())
79 return lldb::eLanguageTypeUnknown;
80 return m_languages[idx];
83 void TypeCategoryImpl::AddLanguage(lldb::LanguageType lang) {
84 m_languages.push_back(lang);
87 bool TypeCategoryImpl::Get(lldb::LanguageType lang,
88 const FormattersMatchVector &candidates,
89 lldb::TypeFormatImplSP &entry, uint32_t *reason) {
90 if (!IsEnabled() || !IsApplicable(lang))
92 if (GetTypeFormatsContainer()->Get(candidates, entry, reason))
94 bool regex = GetRegexTypeFormatsContainer()->Get(candidates, entry, reason);
96 *reason |= lldb_private::eFormatterChoiceCriterionRegularExpressionSummary;
100 bool TypeCategoryImpl::Get(lldb::LanguageType lang,
101 const FormattersMatchVector &candidates,
102 lldb::TypeSummaryImplSP &entry, uint32_t *reason) {
103 if (!IsEnabled() || !IsApplicable(lang))
105 if (GetTypeSummariesContainer()->Get(candidates, entry, reason))
107 bool regex = GetRegexTypeSummariesContainer()->Get(candidates, entry, reason);
109 *reason |= lldb_private::eFormatterChoiceCriterionRegularExpressionSummary;
113 bool TypeCategoryImpl::Get(lldb::LanguageType lang,
114 const FormattersMatchVector &candidates,
115 lldb::SyntheticChildrenSP &entry, uint32_t *reason) {
116 if (!IsEnabled() || !IsApplicable(lang))
118 TypeFilterImpl::SharedPointer filter_sp;
119 uint32_t reason_filter = 0;
120 bool regex_filter = false;
121 // first find both Filter and Synth, and then check which is most recent
123 if (!GetTypeFiltersContainer()->Get(candidates, filter_sp, &reason_filter))
124 regex_filter = GetRegexTypeFiltersContainer()->Get(candidates, filter_sp,
127 bool regex_synth = false;
128 uint32_t reason_synth = 0;
129 bool pick_synth = false;
130 ScriptedSyntheticChildren::SharedPointer synth;
131 if (!GetTypeSyntheticsContainer()->Get(candidates, synth, &reason_synth))
132 regex_synth = GetRegexTypeSyntheticsContainer()->Get(candidates, synth,
134 if (!filter_sp.get() && !synth.get())
136 else if (!filter_sp.get() && synth.get())
139 else if (filter_sp.get() && !synth.get())
142 else /*if (filter_sp.get() && synth.get())*/
144 pick_synth = filter_sp->GetRevision() <= synth->GetRevision();
147 if (regex_synth && reason)
148 *reason |= lldb_private::eFormatterChoiceCriterionRegularExpressionFilter;
152 if (regex_filter && reason)
153 *reason |= lldb_private::eFormatterChoiceCriterionRegularExpressionFilter;
160 void TypeCategoryImpl::Clear(FormatCategoryItems items) {
161 if ((items & eFormatCategoryItemValue) == eFormatCategoryItemValue)
162 GetTypeFormatsContainer()->Clear();
163 if ((items & eFormatCategoryItemRegexValue) == eFormatCategoryItemRegexValue)
164 GetRegexTypeFormatsContainer()->Clear();
166 if ((items & eFormatCategoryItemSummary) == eFormatCategoryItemSummary)
167 GetTypeSummariesContainer()->Clear();
168 if ((items & eFormatCategoryItemRegexSummary) ==
169 eFormatCategoryItemRegexSummary)
170 GetRegexTypeSummariesContainer()->Clear();
172 if ((items & eFormatCategoryItemFilter) == eFormatCategoryItemFilter)
173 GetTypeFiltersContainer()->Clear();
174 if ((items & eFormatCategoryItemRegexFilter) ==
175 eFormatCategoryItemRegexFilter)
176 GetRegexTypeFiltersContainer()->Clear();
178 if ((items & eFormatCategoryItemSynth) == eFormatCategoryItemSynth)
179 GetTypeSyntheticsContainer()->Clear();
180 if ((items & eFormatCategoryItemRegexSynth) == eFormatCategoryItemRegexSynth)
181 GetRegexTypeSyntheticsContainer()->Clear();
184 bool TypeCategoryImpl::Delete(ConstString name, FormatCategoryItems items) {
185 bool success = false;
187 if ((items & eFormatCategoryItemValue) == eFormatCategoryItemValue)
188 success = GetTypeFormatsContainer()->Delete(name) || success;
189 if ((items & eFormatCategoryItemRegexValue) == eFormatCategoryItemRegexValue)
190 success = GetRegexTypeFormatsContainer()->Delete(name) || success;
192 if ((items & eFormatCategoryItemSummary) == eFormatCategoryItemSummary)
193 success = GetTypeSummariesContainer()->Delete(name) || success;
194 if ((items & eFormatCategoryItemRegexSummary) ==
195 eFormatCategoryItemRegexSummary)
196 success = GetRegexTypeSummariesContainer()->Delete(name) || success;
198 if ((items & eFormatCategoryItemFilter) == eFormatCategoryItemFilter)
199 success = GetTypeFiltersContainer()->Delete(name) || success;
200 if ((items & eFormatCategoryItemRegexFilter) ==
201 eFormatCategoryItemRegexFilter)
202 success = GetRegexTypeFiltersContainer()->Delete(name) || success;
204 if ((items & eFormatCategoryItemSynth) == eFormatCategoryItemSynth)
205 success = GetTypeSyntheticsContainer()->Delete(name) || success;
206 if ((items & eFormatCategoryItemRegexSynth) == eFormatCategoryItemRegexSynth)
207 success = GetRegexTypeSyntheticsContainer()->Delete(name) || success;
212 uint32_t TypeCategoryImpl::GetCount(FormatCategoryItems items) {
215 if ((items & eFormatCategoryItemValue) == eFormatCategoryItemValue)
216 count += GetTypeFormatsContainer()->GetCount();
217 if ((items & eFormatCategoryItemRegexValue) == eFormatCategoryItemRegexValue)
218 count += GetRegexTypeFormatsContainer()->GetCount();
220 if ((items & eFormatCategoryItemSummary) == eFormatCategoryItemSummary)
221 count += GetTypeSummariesContainer()->GetCount();
222 if ((items & eFormatCategoryItemRegexSummary) ==
223 eFormatCategoryItemRegexSummary)
224 count += GetRegexTypeSummariesContainer()->GetCount();
226 if ((items & eFormatCategoryItemFilter) == eFormatCategoryItemFilter)
227 count += GetTypeFiltersContainer()->GetCount();
228 if ((items & eFormatCategoryItemRegexFilter) ==
229 eFormatCategoryItemRegexFilter)
230 count += GetRegexTypeFiltersContainer()->GetCount();
232 if ((items & eFormatCategoryItemSynth) == eFormatCategoryItemSynth)
233 count += GetTypeSyntheticsContainer()->GetCount();
234 if ((items & eFormatCategoryItemRegexSynth) == eFormatCategoryItemRegexSynth)
235 count += GetRegexTypeSyntheticsContainer()->GetCount();
240 bool TypeCategoryImpl::AnyMatches(ConstString type_name,
241 FormatCategoryItems items, bool only_enabled,
242 const char **matching_category,
243 FormatCategoryItems *matching_type) {
244 if (!IsEnabled() && only_enabled)
247 lldb::TypeFormatImplSP format_sp;
248 lldb::TypeSummaryImplSP summary_sp;
249 TypeFilterImpl::SharedPointer filter_sp;
250 ScriptedSyntheticChildren::SharedPointer synth_sp;
252 if ((items & eFormatCategoryItemValue) == eFormatCategoryItemValue) {
253 if (GetTypeFormatsContainer()->Get(type_name, format_sp)) {
254 if (matching_category)
255 *matching_category = m_name.GetCString();
257 *matching_type = eFormatCategoryItemValue;
261 if ((items & eFormatCategoryItemRegexValue) ==
262 eFormatCategoryItemRegexValue) {
263 if (GetRegexTypeFormatsContainer()->Get(type_name, format_sp)) {
264 if (matching_category)
265 *matching_category = m_name.GetCString();
267 *matching_type = eFormatCategoryItemRegexValue;
272 if ((items & eFormatCategoryItemSummary) == eFormatCategoryItemSummary) {
273 if (GetTypeSummariesContainer()->Get(type_name, summary_sp)) {
274 if (matching_category)
275 *matching_category = m_name.GetCString();
277 *matching_type = eFormatCategoryItemSummary;
281 if ((items & eFormatCategoryItemRegexSummary) ==
282 eFormatCategoryItemRegexSummary) {
283 if (GetRegexTypeSummariesContainer()->Get(type_name, summary_sp)) {
284 if (matching_category)
285 *matching_category = m_name.GetCString();
287 *matching_type = eFormatCategoryItemRegexSummary;
292 if ((items & eFormatCategoryItemFilter) == eFormatCategoryItemFilter) {
293 if (GetTypeFiltersContainer()->Get(type_name, filter_sp)) {
294 if (matching_category)
295 *matching_category = m_name.GetCString();
297 *matching_type = eFormatCategoryItemFilter;
301 if ((items & eFormatCategoryItemRegexFilter) ==
302 eFormatCategoryItemRegexFilter) {
303 if (GetRegexTypeFiltersContainer()->Get(type_name, filter_sp)) {
304 if (matching_category)
305 *matching_category = m_name.GetCString();
307 *matching_type = eFormatCategoryItemRegexFilter;
312 if ((items & eFormatCategoryItemSynth) == eFormatCategoryItemSynth) {
313 if (GetTypeSyntheticsContainer()->Get(type_name, synth_sp)) {
314 if (matching_category)
315 *matching_category = m_name.GetCString();
317 *matching_type = eFormatCategoryItemSynth;
321 if ((items & eFormatCategoryItemRegexSynth) ==
322 eFormatCategoryItemRegexSynth) {
323 if (GetRegexTypeSyntheticsContainer()->Get(type_name, synth_sp)) {
324 if (matching_category)
325 *matching_category = m_name.GetCString();
327 *matching_type = eFormatCategoryItemRegexSynth;
335 TypeCategoryImpl::FormatContainer::MapValueType
336 TypeCategoryImpl::GetFormatForType(lldb::TypeNameSpecifierImplSP type_sp) {
337 FormatContainer::MapValueType retval;
340 if (type_sp->IsRegex())
341 GetRegexTypeFormatsContainer()->GetExact(ConstString(type_sp->GetName()),
344 GetTypeFormatsContainer()->GetExact(ConstString(type_sp->GetName()),
351 TypeCategoryImpl::SummaryContainer::MapValueType
352 TypeCategoryImpl::GetSummaryForType(lldb::TypeNameSpecifierImplSP type_sp) {
353 SummaryContainer::MapValueType retval;
356 if (type_sp->IsRegex())
357 GetRegexTypeSummariesContainer()->GetExact(
358 ConstString(type_sp->GetName()), retval);
360 GetTypeSummariesContainer()->GetExact(ConstString(type_sp->GetName()),
367 TypeCategoryImpl::FilterContainer::MapValueType
368 TypeCategoryImpl::GetFilterForType(lldb::TypeNameSpecifierImplSP type_sp) {
369 FilterContainer::MapValueType retval;
372 if (type_sp->IsRegex())
373 GetRegexTypeFiltersContainer()->GetExact(ConstString(type_sp->GetName()),
376 GetTypeFiltersContainer()->GetExact(ConstString(type_sp->GetName()),
383 TypeCategoryImpl::SynthContainer::MapValueType
384 TypeCategoryImpl::GetSyntheticForType(lldb::TypeNameSpecifierImplSP type_sp) {
385 SynthContainer::MapValueType retval;
388 if (type_sp->IsRegex())
389 GetRegexTypeSyntheticsContainer()->GetExact(
390 ConstString(type_sp->GetName()), retval);
392 GetTypeSyntheticsContainer()->GetExact(ConstString(type_sp->GetName()),
399 lldb::TypeNameSpecifierImplSP
400 TypeCategoryImpl::GetTypeNameSpecifierForSummaryAtIndex(size_t index) {
401 if (index < GetTypeSummariesContainer()->GetCount())
402 return GetTypeSummariesContainer()->GetTypeNameSpecifierAtIndex(index);
404 return GetRegexTypeSummariesContainer()->GetTypeNameSpecifierAtIndex(
405 index - GetTypeSummariesContainer()->GetCount());
408 TypeCategoryImpl::FormatContainer::MapValueType
409 TypeCategoryImpl::GetFormatAtIndex(size_t index) {
410 if (index < GetTypeFormatsContainer()->GetCount())
411 return GetTypeFormatsContainer()->GetAtIndex(index);
413 return GetRegexTypeFormatsContainer()->GetAtIndex(
414 index - GetTypeFormatsContainer()->GetCount());
417 TypeCategoryImpl::SummaryContainer::MapValueType
418 TypeCategoryImpl::GetSummaryAtIndex(size_t index) {
419 if (index < GetTypeSummariesContainer()->GetCount())
420 return GetTypeSummariesContainer()->GetAtIndex(index);
422 return GetRegexTypeSummariesContainer()->GetAtIndex(
423 index - GetTypeSummariesContainer()->GetCount());
426 TypeCategoryImpl::FilterContainer::MapValueType
427 TypeCategoryImpl::GetFilterAtIndex(size_t index) {
428 if (index < GetTypeFiltersContainer()->GetCount())
429 return GetTypeFiltersContainer()->GetAtIndex(index);
431 return GetRegexTypeFiltersContainer()->GetAtIndex(
432 index - GetTypeFiltersContainer()->GetCount());
435 lldb::TypeNameSpecifierImplSP
436 TypeCategoryImpl::GetTypeNameSpecifierForFormatAtIndex(size_t index) {
437 if (index < GetTypeFormatsContainer()->GetCount())
438 return GetTypeFormatsContainer()->GetTypeNameSpecifierAtIndex(index);
440 return GetRegexTypeFormatsContainer()->GetTypeNameSpecifierAtIndex(
441 index - GetTypeFormatsContainer()->GetCount());
444 lldb::TypeNameSpecifierImplSP
445 TypeCategoryImpl::GetTypeNameSpecifierForFilterAtIndex(size_t index) {
446 if (index < GetTypeFiltersContainer()->GetCount())
447 return GetTypeFiltersContainer()->GetTypeNameSpecifierAtIndex(index);
449 return GetRegexTypeFiltersContainer()->GetTypeNameSpecifierAtIndex(
450 index - GetTypeFiltersContainer()->GetCount());
453 TypeCategoryImpl::SynthContainer::MapValueType
454 TypeCategoryImpl::GetSyntheticAtIndex(size_t index) {
455 if (index < GetTypeSyntheticsContainer()->GetCount())
456 return GetTypeSyntheticsContainer()->GetAtIndex(index);
458 return GetRegexTypeSyntheticsContainer()->GetAtIndex(
459 index - GetTypeSyntheticsContainer()->GetCount());
462 lldb::TypeNameSpecifierImplSP
463 TypeCategoryImpl::GetTypeNameSpecifierForSyntheticAtIndex(size_t index) {
464 if (index < GetTypeSyntheticsContainer()->GetCount())
465 return GetTypeSyntheticsContainer()->GetTypeNameSpecifierAtIndex(index);
467 return GetRegexTypeSyntheticsContainer()->GetTypeNameSpecifierAtIndex(
468 index - GetTypeSyntheticsContainer()->GetCount());
471 void TypeCategoryImpl::Enable(bool value, uint32_t position) {
472 std::lock_guard<std::recursive_mutex> guard(m_mutex);
473 if ((m_enabled = value))
474 m_enabled_position = position;
475 if (m_change_listener)
476 m_change_listener->Changed();
479 std::string TypeCategoryImpl::GetDescription() {
481 stream.Printf("%s (%s", GetName(), (IsEnabled() ? "enabled" : "disabled"));
482 StreamString lang_stream;
483 lang_stream.Printf(", applicable for language(s): ");
484 bool print_lang = false;
485 for (size_t idx = 0; idx < GetNumLanguages(); idx++) {
486 const lldb::LanguageType lang = GetLanguageAtIndex(idx);
487 if (lang != lldb::eLanguageTypeUnknown)
489 lang_stream.Printf("%s%s", Language::GetNameForLanguageType(lang),
490 idx + 1 < GetNumLanguages() ? ", " : "");
493 stream.PutCString(lang_stream.GetString());
495 return stream.GetString();