1dda28197Spatrick //===-- TypeCategory.cpp --------------------------------------------------===//
2061da546Spatrick //
3061da546Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4061da546Spatrick // See https://llvm.org/LICENSE.txt for license information.
5061da546Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6061da546Spatrick //
7061da546Spatrick //===----------------------------------------------------------------------===//
8061da546Spatrick 
9061da546Spatrick #include "lldb/DataFormatters/TypeCategory.h"
10061da546Spatrick #include "lldb/Target/Language.h"
11061da546Spatrick 
12061da546Spatrick 
13061da546Spatrick using namespace lldb;
14061da546Spatrick using namespace lldb_private;
15061da546Spatrick 
TypeCategoryImpl(IFormatChangeListener * clist,ConstString name)16061da546Spatrick TypeCategoryImpl::TypeCategoryImpl(IFormatChangeListener *clist,
17061da546Spatrick                                    ConstString name)
18be691f3bSpatrick     : m_format_cont(clist), m_summary_cont(clist), m_filter_cont(clist),
19be691f3bSpatrick       m_synth_cont(clist), m_enabled(false), m_change_listener(clist),
20be691f3bSpatrick       m_mutex(), m_name(name), m_languages() {}
21061da546Spatrick 
IsApplicable(lldb::LanguageType category_lang,lldb::LanguageType valobj_lang)22061da546Spatrick static bool IsApplicable(lldb::LanguageType category_lang,
23061da546Spatrick                          lldb::LanguageType valobj_lang) {
24061da546Spatrick   switch (category_lang) {
25061da546Spatrick   // Unless we know better, allow only exact equality.
26061da546Spatrick   default:
27061da546Spatrick     return category_lang == valobj_lang;
28061da546Spatrick 
29061da546Spatrick   // the C family, we consider it as one
30061da546Spatrick   case eLanguageTypeC89:
31061da546Spatrick   case eLanguageTypeC:
32061da546Spatrick   case eLanguageTypeC99:
33061da546Spatrick     return valobj_lang == eLanguageTypeC89 || valobj_lang == eLanguageTypeC ||
34061da546Spatrick            valobj_lang == eLanguageTypeC99;
35061da546Spatrick 
36061da546Spatrick   // ObjC knows about C and itself
37061da546Spatrick   case eLanguageTypeObjC:
38061da546Spatrick     return valobj_lang == eLanguageTypeC89 || valobj_lang == eLanguageTypeC ||
39061da546Spatrick            valobj_lang == eLanguageTypeC99 || valobj_lang == eLanguageTypeObjC;
40061da546Spatrick 
41061da546Spatrick   // C++ knows about C and C++
42061da546Spatrick   case eLanguageTypeC_plus_plus:
43061da546Spatrick     return valobj_lang == eLanguageTypeC89 || valobj_lang == eLanguageTypeC ||
44061da546Spatrick            valobj_lang == eLanguageTypeC99 ||
45061da546Spatrick            valobj_lang == eLanguageTypeC_plus_plus;
46061da546Spatrick 
47061da546Spatrick   // ObjC++ knows about C,C++,ObjC and ObjC++
48061da546Spatrick   case eLanguageTypeObjC_plus_plus:
49061da546Spatrick     return valobj_lang == eLanguageTypeC89 || valobj_lang == eLanguageTypeC ||
50061da546Spatrick            valobj_lang == eLanguageTypeC99 ||
51061da546Spatrick            valobj_lang == eLanguageTypeC_plus_plus ||
52061da546Spatrick            valobj_lang == eLanguageTypeObjC;
53061da546Spatrick 
54061da546Spatrick   // Categories with unspecified language match everything.
55061da546Spatrick   case eLanguageTypeUnknown:
56061da546Spatrick     return true;
57061da546Spatrick   }
58061da546Spatrick }
59061da546Spatrick 
IsApplicable(lldb::LanguageType lang)60061da546Spatrick bool TypeCategoryImpl::IsApplicable(lldb::LanguageType lang) {
61061da546Spatrick   for (size_t idx = 0; idx < GetNumLanguages(); idx++) {
62061da546Spatrick     const lldb::LanguageType category_lang = GetLanguageAtIndex(idx);
63061da546Spatrick     if (::IsApplicable(category_lang, lang))
64061da546Spatrick       return true;
65061da546Spatrick   }
66061da546Spatrick   return false;
67061da546Spatrick }
68061da546Spatrick 
GetNumLanguages()69061da546Spatrick size_t TypeCategoryImpl::GetNumLanguages() {
70061da546Spatrick   if (m_languages.empty())
71061da546Spatrick     return 1;
72061da546Spatrick   return m_languages.size();
73061da546Spatrick }
74061da546Spatrick 
GetLanguageAtIndex(size_t idx)75061da546Spatrick lldb::LanguageType TypeCategoryImpl::GetLanguageAtIndex(size_t idx) {
76061da546Spatrick   if (m_languages.empty())
77061da546Spatrick     return lldb::eLanguageTypeUnknown;
78061da546Spatrick   return m_languages[idx];
79061da546Spatrick }
80061da546Spatrick 
AddLanguage(lldb::LanguageType lang)81061da546Spatrick void TypeCategoryImpl::AddLanguage(lldb::LanguageType lang) {
82061da546Spatrick   m_languages.push_back(lang);
83061da546Spatrick }
84061da546Spatrick 
Get(lldb::LanguageType lang,const FormattersMatchVector & candidates,lldb::TypeFormatImplSP & entry)85061da546Spatrick bool TypeCategoryImpl::Get(lldb::LanguageType lang,
86061da546Spatrick                            const FormattersMatchVector &candidates,
87dda28197Spatrick                            lldb::TypeFormatImplSP &entry) {
88061da546Spatrick   if (!IsEnabled() || !IsApplicable(lang))
89061da546Spatrick     return false;
90*f6aab3d8Srobert   return m_format_cont.Get(candidates, entry);
91061da546Spatrick }
92061da546Spatrick 
Get(lldb::LanguageType lang,const FormattersMatchVector & candidates,lldb::TypeSummaryImplSP & entry)93061da546Spatrick bool TypeCategoryImpl::Get(lldb::LanguageType lang,
94061da546Spatrick                            const FormattersMatchVector &candidates,
95dda28197Spatrick                            lldb::TypeSummaryImplSP &entry) {
96061da546Spatrick   if (!IsEnabled() || !IsApplicable(lang))
97061da546Spatrick     return false;
98*f6aab3d8Srobert   return m_summary_cont.Get(candidates, entry);
99061da546Spatrick }
100061da546Spatrick 
Get(lldb::LanguageType lang,const FormattersMatchVector & candidates,lldb::SyntheticChildrenSP & entry)101061da546Spatrick bool TypeCategoryImpl::Get(lldb::LanguageType lang,
102061da546Spatrick                            const FormattersMatchVector &candidates,
103dda28197Spatrick                            lldb::SyntheticChildrenSP &entry) {
104061da546Spatrick   if (!IsEnabled() || !IsApplicable(lang))
105061da546Spatrick     return false;
106*f6aab3d8Srobert 
107061da546Spatrick   // first find both Filter and Synth, and then check which is most recent
108061da546Spatrick   bool pick_synth = false;
109*f6aab3d8Srobert 
110*f6aab3d8Srobert   TypeFilterImpl::SharedPointer filter_sp;
111*f6aab3d8Srobert   m_filter_cont.Get(candidates, filter_sp);
112*f6aab3d8Srobert 
113*f6aab3d8Srobert   ScriptedSyntheticChildren::SharedPointer synth_sp;
114*f6aab3d8Srobert   m_synth_cont.Get(candidates, synth_sp);
115*f6aab3d8Srobert 
116*f6aab3d8Srobert   if (!filter_sp.get() && !synth_sp.get())
117061da546Spatrick     return false;
118*f6aab3d8Srobert   else if (!filter_sp.get() && synth_sp.get())
119061da546Spatrick     pick_synth = true;
120*f6aab3d8Srobert   else if (filter_sp.get() && !synth_sp.get())
121061da546Spatrick     pick_synth = false;
122*f6aab3d8Srobert   else /*if (filter_sp.get() && synth_sp.get())*/
123061da546Spatrick   {
124*f6aab3d8Srobert     pick_synth = filter_sp->GetRevision() <= synth_sp->GetRevision();
125061da546Spatrick   }
126*f6aab3d8Srobert 
127061da546Spatrick   if (pick_synth) {
128*f6aab3d8Srobert     entry = synth_sp;
129061da546Spatrick     return true;
130061da546Spatrick   } else {
131061da546Spatrick     entry = filter_sp;
132061da546Spatrick     return true;
133061da546Spatrick   }
134061da546Spatrick   return false;
135061da546Spatrick }
136061da546Spatrick 
Clear(FormatCategoryItems items)137061da546Spatrick void TypeCategoryImpl::Clear(FormatCategoryItems items) {
138*f6aab3d8Srobert   if (items & eFormatCategoryItemFormat)
139*f6aab3d8Srobert     m_format_cont.Clear();
140061da546Spatrick 
141*f6aab3d8Srobert   if (items & eFormatCategoryItemSummary)
142*f6aab3d8Srobert     m_summary_cont.Clear();
143061da546Spatrick 
144*f6aab3d8Srobert   if (items & eFormatCategoryItemFilter)
145*f6aab3d8Srobert     m_filter_cont.Clear();
146061da546Spatrick 
147*f6aab3d8Srobert   if (items & eFormatCategoryItemSynth)
148*f6aab3d8Srobert     m_synth_cont.Clear();
149061da546Spatrick }
150061da546Spatrick 
Delete(ConstString name,FormatCategoryItems items)151061da546Spatrick bool TypeCategoryImpl::Delete(ConstString name, FormatCategoryItems items) {
152061da546Spatrick   bool success = false;
153061da546Spatrick 
154*f6aab3d8Srobert   if (items & eFormatCategoryItemFormat)
155*f6aab3d8Srobert     success = m_format_cont.Delete(name) || success;
156061da546Spatrick 
157*f6aab3d8Srobert   if (items & eFormatCategoryItemSummary)
158*f6aab3d8Srobert     success = m_summary_cont.Delete(name) || success;
159061da546Spatrick 
160*f6aab3d8Srobert   if (items & eFormatCategoryItemFilter)
161*f6aab3d8Srobert     success = m_filter_cont.Delete(name) || success;
162061da546Spatrick 
163*f6aab3d8Srobert   if (items & eFormatCategoryItemSynth)
164*f6aab3d8Srobert     success = m_synth_cont.Delete(name) || success;
165061da546Spatrick 
166061da546Spatrick   return success;
167061da546Spatrick }
168061da546Spatrick 
GetCount(FormatCategoryItems items)169061da546Spatrick uint32_t TypeCategoryImpl::GetCount(FormatCategoryItems items) {
170061da546Spatrick   uint32_t count = 0;
171061da546Spatrick 
172*f6aab3d8Srobert   if (items & eFormatCategoryItemFormat)
173*f6aab3d8Srobert     count += m_format_cont.GetCount();
174061da546Spatrick 
175*f6aab3d8Srobert   if (items & eFormatCategoryItemSummary)
176*f6aab3d8Srobert     count += m_summary_cont.GetCount();
177061da546Spatrick 
178*f6aab3d8Srobert   if (items & eFormatCategoryItemFilter)
179*f6aab3d8Srobert     count += m_filter_cont.GetCount();
180061da546Spatrick 
181*f6aab3d8Srobert   if (items & eFormatCategoryItemSynth)
182*f6aab3d8Srobert     count += m_synth_cont.GetCount();
183061da546Spatrick 
184061da546Spatrick   return count;
185061da546Spatrick }
186061da546Spatrick 
AnyMatches(const FormattersMatchCandidate & candidate_type,FormatCategoryItems items,bool only_enabled,const char ** matching_category,FormatCategoryItems * matching_type)187*f6aab3d8Srobert bool TypeCategoryImpl::AnyMatches(
188*f6aab3d8Srobert     const FormattersMatchCandidate &candidate_type, FormatCategoryItems items,
189*f6aab3d8Srobert     bool only_enabled, const char **matching_category,
190061da546Spatrick     FormatCategoryItems *matching_type) {
191061da546Spatrick   if (!IsEnabled() && only_enabled)
192061da546Spatrick     return false;
193061da546Spatrick 
194*f6aab3d8Srobert   if (items & eFormatCategoryItemFormat) {
195*f6aab3d8Srobert     if (m_format_cont.AnyMatches(candidate_type)) {
196061da546Spatrick       if (matching_category)
197061da546Spatrick         *matching_category = m_name.GetCString();
198061da546Spatrick       if (matching_type)
199*f6aab3d8Srobert         *matching_type = eFormatCategoryItemFormat;
200061da546Spatrick       return true;
201061da546Spatrick     }
202061da546Spatrick   }
203061da546Spatrick 
204*f6aab3d8Srobert   if (items & eFormatCategoryItemSummary) {
205*f6aab3d8Srobert     if (m_summary_cont.AnyMatches(candidate_type)) {
206061da546Spatrick       if (matching_category)
207061da546Spatrick         *matching_category = m_name.GetCString();
208061da546Spatrick       if (matching_type)
209061da546Spatrick         *matching_type = eFormatCategoryItemSummary;
210061da546Spatrick       return true;
211061da546Spatrick     }
212061da546Spatrick   }
213061da546Spatrick 
214*f6aab3d8Srobert   if (items & eFormatCategoryItemFilter) {
215*f6aab3d8Srobert     if (m_filter_cont.AnyMatches(candidate_type)) {
216061da546Spatrick       if (matching_category)
217061da546Spatrick         *matching_category = m_name.GetCString();
218061da546Spatrick       if (matching_type)
219061da546Spatrick         *matching_type = eFormatCategoryItemFilter;
220061da546Spatrick       return true;
221061da546Spatrick     }
222061da546Spatrick   }
223061da546Spatrick 
224*f6aab3d8Srobert   if (items & eFormatCategoryItemSynth) {
225*f6aab3d8Srobert     if (m_synth_cont.AnyMatches(candidate_type)) {
226061da546Spatrick       if (matching_category)
227061da546Spatrick         *matching_category = m_name.GetCString();
228061da546Spatrick       if (matching_type)
229061da546Spatrick         *matching_type = eFormatCategoryItemSynth;
230061da546Spatrick       return true;
231061da546Spatrick     }
232061da546Spatrick   }
233061da546Spatrick 
234061da546Spatrick   return false;
235061da546Spatrick }
236061da546Spatrick 
AutoComplete(CompletionRequest & request,FormatCategoryItems items)237*f6aab3d8Srobert void TypeCategoryImpl::AutoComplete(CompletionRequest &request,
238*f6aab3d8Srobert                                     FormatCategoryItems items) {
239*f6aab3d8Srobert   if (items & eFormatCategoryItemFormat)
240*f6aab3d8Srobert     m_format_cont.AutoComplete(request);
241*f6aab3d8Srobert   if (items & eFormatCategoryItemSummary)
242*f6aab3d8Srobert     m_summary_cont.AutoComplete(request);
243*f6aab3d8Srobert   if (items & eFormatCategoryItemFilter)
244*f6aab3d8Srobert     m_filter_cont.AutoComplete(request);
245*f6aab3d8Srobert   if (items & eFormatCategoryItemSynth)
246*f6aab3d8Srobert     m_synth_cont.AutoComplete(request);
247061da546Spatrick }
248061da546Spatrick 
249*f6aab3d8Srobert TypeCategoryImpl::FormatContainer::MapValueType
GetFormatForType(lldb::TypeNameSpecifierImplSP type_sp)250*f6aab3d8Srobert TypeCategoryImpl::GetFormatForType(lldb::TypeNameSpecifierImplSP type_sp) {
251*f6aab3d8Srobert   return m_format_cont.GetForTypeNameSpecifier(type_sp);
252061da546Spatrick }
253061da546Spatrick 
254061da546Spatrick TypeCategoryImpl::SummaryContainer::MapValueType
GetSummaryForType(lldb::TypeNameSpecifierImplSP type_sp)255061da546Spatrick TypeCategoryImpl::GetSummaryForType(lldb::TypeNameSpecifierImplSP type_sp) {
256*f6aab3d8Srobert   return m_summary_cont.GetForTypeNameSpecifier(type_sp);
257061da546Spatrick }
258061da546Spatrick 
259061da546Spatrick TypeCategoryImpl::FilterContainer::MapValueType
GetFilterForType(lldb::TypeNameSpecifierImplSP type_sp)260061da546Spatrick TypeCategoryImpl::GetFilterForType(lldb::TypeNameSpecifierImplSP type_sp) {
261*f6aab3d8Srobert   return m_filter_cont.GetForTypeNameSpecifier(type_sp);
262061da546Spatrick }
263061da546Spatrick 
264061da546Spatrick TypeCategoryImpl::SynthContainer::MapValueType
GetSyntheticForType(lldb::TypeNameSpecifierImplSP type_sp)265061da546Spatrick TypeCategoryImpl::GetSyntheticForType(lldb::TypeNameSpecifierImplSP type_sp) {
266*f6aab3d8Srobert   return m_synth_cont.GetForTypeNameSpecifier(type_sp);
267061da546Spatrick }
268061da546Spatrick 
269061da546Spatrick TypeCategoryImpl::FormatContainer::MapValueType
GetFormatAtIndex(size_t index)270061da546Spatrick TypeCategoryImpl::GetFormatAtIndex(size_t index) {
271*f6aab3d8Srobert   return m_format_cont.GetAtIndex(index);
272061da546Spatrick }
273061da546Spatrick 
274061da546Spatrick TypeCategoryImpl::SummaryContainer::MapValueType
GetSummaryAtIndex(size_t index)275061da546Spatrick TypeCategoryImpl::GetSummaryAtIndex(size_t index) {
276*f6aab3d8Srobert   return m_summary_cont.GetAtIndex(index);
277061da546Spatrick }
278061da546Spatrick 
279061da546Spatrick TypeCategoryImpl::FilterContainer::MapValueType
GetFilterAtIndex(size_t index)280061da546Spatrick TypeCategoryImpl::GetFilterAtIndex(size_t index) {
281*f6aab3d8Srobert   return m_filter_cont.GetAtIndex(index);
282061da546Spatrick }
283061da546Spatrick 
284061da546Spatrick TypeCategoryImpl::SynthContainer::MapValueType
GetSyntheticAtIndex(size_t index)285061da546Spatrick TypeCategoryImpl::GetSyntheticAtIndex(size_t index) {
286*f6aab3d8Srobert   return m_synth_cont.GetAtIndex(index);
287*f6aab3d8Srobert }
288*f6aab3d8Srobert 
289*f6aab3d8Srobert lldb::TypeNameSpecifierImplSP
GetTypeNameSpecifierForFormatAtIndex(size_t index)290*f6aab3d8Srobert TypeCategoryImpl::GetTypeNameSpecifierForFormatAtIndex(size_t index) {
291*f6aab3d8Srobert   return m_format_cont.GetTypeNameSpecifierAtIndex(index);
292*f6aab3d8Srobert }
293*f6aab3d8Srobert 
294*f6aab3d8Srobert lldb::TypeNameSpecifierImplSP
GetTypeNameSpecifierForSummaryAtIndex(size_t index)295*f6aab3d8Srobert TypeCategoryImpl::GetTypeNameSpecifierForSummaryAtIndex(size_t index) {
296*f6aab3d8Srobert   return m_summary_cont.GetTypeNameSpecifierAtIndex(index);
297*f6aab3d8Srobert }
298*f6aab3d8Srobert 
299*f6aab3d8Srobert lldb::TypeNameSpecifierImplSP
GetTypeNameSpecifierForFilterAtIndex(size_t index)300*f6aab3d8Srobert TypeCategoryImpl::GetTypeNameSpecifierForFilterAtIndex(size_t index) {
301*f6aab3d8Srobert   return m_filter_cont.GetTypeNameSpecifierAtIndex(index);
302061da546Spatrick }
303061da546Spatrick 
304061da546Spatrick lldb::TypeNameSpecifierImplSP
GetTypeNameSpecifierForSyntheticAtIndex(size_t index)305061da546Spatrick TypeCategoryImpl::GetTypeNameSpecifierForSyntheticAtIndex(size_t index) {
306*f6aab3d8Srobert   return m_synth_cont.GetTypeNameSpecifierAtIndex(index);
307061da546Spatrick }
308061da546Spatrick 
Enable(bool value,uint32_t position)309061da546Spatrick void TypeCategoryImpl::Enable(bool value, uint32_t position) {
310061da546Spatrick   std::lock_guard<std::recursive_mutex> guard(m_mutex);
311061da546Spatrick   if ((m_enabled = value))
312061da546Spatrick     m_enabled_position = position;
313061da546Spatrick   if (m_change_listener)
314061da546Spatrick     m_change_listener->Changed();
315061da546Spatrick }
316061da546Spatrick 
GetDescription()317061da546Spatrick std::string TypeCategoryImpl::GetDescription() {
318061da546Spatrick   StreamString stream;
319061da546Spatrick   stream.Printf("%s (%s", GetName(), (IsEnabled() ? "enabled" : "disabled"));
320061da546Spatrick   StreamString lang_stream;
321061da546Spatrick   lang_stream.Printf(", applicable for language(s): ");
322061da546Spatrick   bool print_lang = false;
323061da546Spatrick   for (size_t idx = 0; idx < GetNumLanguages(); idx++) {
324061da546Spatrick     const lldb::LanguageType lang = GetLanguageAtIndex(idx);
325061da546Spatrick     if (lang != lldb::eLanguageTypeUnknown)
326061da546Spatrick       print_lang = true;
327061da546Spatrick     lang_stream.Printf("%s%s", Language::GetNameForLanguageType(lang),
328061da546Spatrick                        idx + 1 < GetNumLanguages() ? ", " : "");
329061da546Spatrick   }
330061da546Spatrick   if (print_lang)
331061da546Spatrick     stream.PutCString(lang_stream.GetString());
332061da546Spatrick   stream.PutChar(')');
333dda28197Spatrick   return std::string(stream.GetString());
334061da546Spatrick }
335