xref: /freebsd/contrib/llvm-project/lldb/source/DataFormatters/TypeCategory.cpp (revision bdd1243df58e60e85101c09001d9812a789b6bc4)
1 //===-- TypeCategory.cpp --------------------------------------------------===//
2 //
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
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "lldb/DataFormatters/TypeCategory.h"
10 #include "lldb/Target/Language.h"
11 
12 
13 using namespace lldb;
14 using namespace lldb_private;
15 
TypeCategoryImpl(IFormatChangeListener * clist,ConstString name)16 TypeCategoryImpl::TypeCategoryImpl(IFormatChangeListener *clist,
17                                    ConstString name)
18     : m_format_cont(clist), m_summary_cont(clist), m_filter_cont(clist),
19       m_synth_cont(clist), m_enabled(false), m_change_listener(clist),
20       m_mutex(), m_name(name), m_languages() {}
21 
IsApplicable(lldb::LanguageType category_lang,lldb::LanguageType valobj_lang)22 static bool IsApplicable(lldb::LanguageType category_lang,
23                          lldb::LanguageType valobj_lang) {
24   switch (category_lang) {
25   // Unless we know better, allow only exact equality.
26   default:
27     return category_lang == valobj_lang;
28 
29   // the C family, we consider it as one
30   case eLanguageTypeC89:
31   case eLanguageTypeC:
32   case eLanguageTypeC99:
33     return valobj_lang == eLanguageTypeC89 || valobj_lang == eLanguageTypeC ||
34            valobj_lang == eLanguageTypeC99;
35 
36   // ObjC knows about C and itself
37   case eLanguageTypeObjC:
38     return valobj_lang == eLanguageTypeC89 || valobj_lang == eLanguageTypeC ||
39            valobj_lang == eLanguageTypeC99 || valobj_lang == eLanguageTypeObjC;
40 
41   // C++ knows about C and C++
42   case eLanguageTypeC_plus_plus:
43     return valobj_lang == eLanguageTypeC89 || valobj_lang == eLanguageTypeC ||
44            valobj_lang == eLanguageTypeC99 ||
45            valobj_lang == eLanguageTypeC_plus_plus;
46 
47   // ObjC++ knows about C,C++,ObjC and ObjC++
48   case eLanguageTypeObjC_plus_plus:
49     return valobj_lang == eLanguageTypeC89 || valobj_lang == eLanguageTypeC ||
50            valobj_lang == eLanguageTypeC99 ||
51            valobj_lang == eLanguageTypeC_plus_plus ||
52            valobj_lang == eLanguageTypeObjC;
53 
54   // Categories with unspecified language match everything.
55   case eLanguageTypeUnknown:
56     return true;
57   }
58 }
59 
IsApplicable(lldb::LanguageType lang)60 bool TypeCategoryImpl::IsApplicable(lldb::LanguageType lang) {
61   for (size_t idx = 0; idx < GetNumLanguages(); idx++) {
62     const lldb::LanguageType category_lang = GetLanguageAtIndex(idx);
63     if (::IsApplicable(category_lang, lang))
64       return true;
65   }
66   return false;
67 }
68 
GetNumLanguages()69 size_t TypeCategoryImpl::GetNumLanguages() {
70   if (m_languages.empty())
71     return 1;
72   return m_languages.size();
73 }
74 
GetLanguageAtIndex(size_t idx)75 lldb::LanguageType TypeCategoryImpl::GetLanguageAtIndex(size_t idx) {
76   if (m_languages.empty())
77     return lldb::eLanguageTypeUnknown;
78   return m_languages[idx];
79 }
80 
AddLanguage(lldb::LanguageType lang)81 void TypeCategoryImpl::AddLanguage(lldb::LanguageType lang) {
82   m_languages.push_back(lang);
83 }
84 
Get(lldb::LanguageType lang,const FormattersMatchVector & candidates,lldb::TypeFormatImplSP & entry)85 bool TypeCategoryImpl::Get(lldb::LanguageType lang,
86                            const FormattersMatchVector &candidates,
87                            lldb::TypeFormatImplSP &entry) {
88   if (!IsEnabled() || !IsApplicable(lang))
89     return false;
90   return m_format_cont.Get(candidates, entry);
91 }
92 
Get(lldb::LanguageType lang,const FormattersMatchVector & candidates,lldb::TypeSummaryImplSP & entry)93 bool TypeCategoryImpl::Get(lldb::LanguageType lang,
94                            const FormattersMatchVector &candidates,
95                            lldb::TypeSummaryImplSP &entry) {
96   if (!IsEnabled() || !IsApplicable(lang))
97     return false;
98   return m_summary_cont.Get(candidates, entry);
99 }
100 
Get(lldb::LanguageType lang,const FormattersMatchVector & candidates,lldb::SyntheticChildrenSP & entry)101 bool TypeCategoryImpl::Get(lldb::LanguageType lang,
102                            const FormattersMatchVector &candidates,
103                            lldb::SyntheticChildrenSP &entry) {
104   if (!IsEnabled() || !IsApplicable(lang))
105     return false;
106 
107   // first find both Filter and Synth, and then check which is most recent
108   bool pick_synth = false;
109 
110   TypeFilterImpl::SharedPointer filter_sp;
111   m_filter_cont.Get(candidates, filter_sp);
112 
113   ScriptedSyntheticChildren::SharedPointer synth_sp;
114   m_synth_cont.Get(candidates, synth_sp);
115 
116   if (!filter_sp.get() && !synth_sp.get())
117     return false;
118   else if (!filter_sp.get() && synth_sp.get())
119     pick_synth = true;
120   else if (filter_sp.get() && !synth_sp.get())
121     pick_synth = false;
122   else /*if (filter_sp.get() && synth_sp.get())*/
123   {
124     pick_synth = filter_sp->GetRevision() <= synth_sp->GetRevision();
125   }
126 
127   if (pick_synth) {
128     entry = synth_sp;
129     return true;
130   } else {
131     entry = filter_sp;
132     return true;
133   }
134   return false;
135 }
136 
Clear(FormatCategoryItems items)137 void TypeCategoryImpl::Clear(FormatCategoryItems items) {
138   if (items & eFormatCategoryItemFormat)
139     m_format_cont.Clear();
140 
141   if (items & eFormatCategoryItemSummary)
142     m_summary_cont.Clear();
143 
144   if (items & eFormatCategoryItemFilter)
145     m_filter_cont.Clear();
146 
147   if (items & eFormatCategoryItemSynth)
148     m_synth_cont.Clear();
149 }
150 
Delete(ConstString name,FormatCategoryItems items)151 bool TypeCategoryImpl::Delete(ConstString name, FormatCategoryItems items) {
152   bool success = false;
153 
154   if (items & eFormatCategoryItemFormat)
155     success = m_format_cont.Delete(name) || success;
156 
157   if (items & eFormatCategoryItemSummary)
158     success = m_summary_cont.Delete(name) || success;
159 
160   if (items & eFormatCategoryItemFilter)
161     success = m_filter_cont.Delete(name) || success;
162 
163   if (items & eFormatCategoryItemSynth)
164     success = m_synth_cont.Delete(name) || success;
165 
166   return success;
167 }
168 
GetCount(FormatCategoryItems items)169 uint32_t TypeCategoryImpl::GetCount(FormatCategoryItems items) {
170   uint32_t count = 0;
171 
172   if (items & eFormatCategoryItemFormat)
173     count += m_format_cont.GetCount();
174 
175   if (items & eFormatCategoryItemSummary)
176     count += m_summary_cont.GetCount();
177 
178   if (items & eFormatCategoryItemFilter)
179     count += m_filter_cont.GetCount();
180 
181   if (items & eFormatCategoryItemSynth)
182     count += m_synth_cont.GetCount();
183 
184   return count;
185 }
186 
AnyMatches(const FormattersMatchCandidate & candidate_type,FormatCategoryItems items,bool only_enabled,const char ** matching_category,FormatCategoryItems * matching_type)187 bool TypeCategoryImpl::AnyMatches(
188     const FormattersMatchCandidate &candidate_type, FormatCategoryItems items,
189     bool only_enabled, const char **matching_category,
190     FormatCategoryItems *matching_type) {
191   if (!IsEnabled() && only_enabled)
192     return false;
193 
194   if (items & eFormatCategoryItemFormat) {
195     if (m_format_cont.AnyMatches(candidate_type)) {
196       if (matching_category)
197         *matching_category = m_name.GetCString();
198       if (matching_type)
199         *matching_type = eFormatCategoryItemFormat;
200       return true;
201     }
202   }
203 
204   if (items & eFormatCategoryItemSummary) {
205     if (m_summary_cont.AnyMatches(candidate_type)) {
206       if (matching_category)
207         *matching_category = m_name.GetCString();
208       if (matching_type)
209         *matching_type = eFormatCategoryItemSummary;
210       return true;
211     }
212   }
213 
214   if (items & eFormatCategoryItemFilter) {
215     if (m_filter_cont.AnyMatches(candidate_type)) {
216       if (matching_category)
217         *matching_category = m_name.GetCString();
218       if (matching_type)
219         *matching_type = eFormatCategoryItemFilter;
220       return true;
221     }
222   }
223 
224   if (items & eFormatCategoryItemSynth) {
225     if (m_synth_cont.AnyMatches(candidate_type)) {
226       if (matching_category)
227         *matching_category = m_name.GetCString();
228       if (matching_type)
229         *matching_type = eFormatCategoryItemSynth;
230       return true;
231     }
232   }
233 
234   return false;
235 }
236 
AutoComplete(CompletionRequest & request,FormatCategoryItems items)237 void TypeCategoryImpl::AutoComplete(CompletionRequest &request,
238                                     FormatCategoryItems items) {
239   if (items & eFormatCategoryItemFormat)
240     m_format_cont.AutoComplete(request);
241   if (items & eFormatCategoryItemSummary)
242     m_summary_cont.AutoComplete(request);
243   if (items & eFormatCategoryItemFilter)
244     m_filter_cont.AutoComplete(request);
245   if (items & eFormatCategoryItemSynth)
246     m_synth_cont.AutoComplete(request);
247 }
248 
249 TypeCategoryImpl::FormatContainer::MapValueType
GetFormatForType(lldb::TypeNameSpecifierImplSP type_sp)250 TypeCategoryImpl::GetFormatForType(lldb::TypeNameSpecifierImplSP type_sp) {
251   return m_format_cont.GetForTypeNameSpecifier(type_sp);
252 }
253 
254 TypeCategoryImpl::SummaryContainer::MapValueType
GetSummaryForType(lldb::TypeNameSpecifierImplSP type_sp)255 TypeCategoryImpl::GetSummaryForType(lldb::TypeNameSpecifierImplSP type_sp) {
256   return m_summary_cont.GetForTypeNameSpecifier(type_sp);
257 }
258 
259 TypeCategoryImpl::FilterContainer::MapValueType
GetFilterForType(lldb::TypeNameSpecifierImplSP type_sp)260 TypeCategoryImpl::GetFilterForType(lldb::TypeNameSpecifierImplSP type_sp) {
261   return m_filter_cont.GetForTypeNameSpecifier(type_sp);
262 }
263 
264 TypeCategoryImpl::SynthContainer::MapValueType
GetSyntheticForType(lldb::TypeNameSpecifierImplSP type_sp)265 TypeCategoryImpl::GetSyntheticForType(lldb::TypeNameSpecifierImplSP type_sp) {
266   return m_synth_cont.GetForTypeNameSpecifier(type_sp);
267 }
268 
269 TypeCategoryImpl::FormatContainer::MapValueType
GetFormatAtIndex(size_t index)270 TypeCategoryImpl::GetFormatAtIndex(size_t index) {
271   return m_format_cont.GetAtIndex(index);
272 }
273 
274 TypeCategoryImpl::SummaryContainer::MapValueType
GetSummaryAtIndex(size_t index)275 TypeCategoryImpl::GetSummaryAtIndex(size_t index) {
276   return m_summary_cont.GetAtIndex(index);
277 }
278 
279 TypeCategoryImpl::FilterContainer::MapValueType
GetFilterAtIndex(size_t index)280 TypeCategoryImpl::GetFilterAtIndex(size_t index) {
281   return m_filter_cont.GetAtIndex(index);
282 }
283 
284 TypeCategoryImpl::SynthContainer::MapValueType
GetSyntheticAtIndex(size_t index)285 TypeCategoryImpl::GetSyntheticAtIndex(size_t index) {
286   return m_synth_cont.GetAtIndex(index);
287 }
288 
289 lldb::TypeNameSpecifierImplSP
GetTypeNameSpecifierForFormatAtIndex(size_t index)290 TypeCategoryImpl::GetTypeNameSpecifierForFormatAtIndex(size_t index) {
291   return m_format_cont.GetTypeNameSpecifierAtIndex(index);
292 }
293 
294 lldb::TypeNameSpecifierImplSP
GetTypeNameSpecifierForSummaryAtIndex(size_t index)295 TypeCategoryImpl::GetTypeNameSpecifierForSummaryAtIndex(size_t index) {
296   return m_summary_cont.GetTypeNameSpecifierAtIndex(index);
297 }
298 
299 lldb::TypeNameSpecifierImplSP
GetTypeNameSpecifierForFilterAtIndex(size_t index)300 TypeCategoryImpl::GetTypeNameSpecifierForFilterAtIndex(size_t index) {
301   return m_filter_cont.GetTypeNameSpecifierAtIndex(index);
302 }
303 
304 lldb::TypeNameSpecifierImplSP
GetTypeNameSpecifierForSyntheticAtIndex(size_t index)305 TypeCategoryImpl::GetTypeNameSpecifierForSyntheticAtIndex(size_t index) {
306   return m_synth_cont.GetTypeNameSpecifierAtIndex(index);
307 }
308 
Enable(bool value,uint32_t position)309 void TypeCategoryImpl::Enable(bool value, uint32_t position) {
310   std::lock_guard<std::recursive_mutex> guard(m_mutex);
311   if ((m_enabled = value))
312     m_enabled_position = position;
313   if (m_change_listener)
314     m_change_listener->Changed();
315 }
316 
GetDescription()317 std::string TypeCategoryImpl::GetDescription() {
318   StreamString stream;
319   stream.Printf("%s (%s", GetName(), (IsEnabled() ? "enabled" : "disabled"));
320   StreamString lang_stream;
321   lang_stream.Printf(", applicable for language(s): ");
322   bool print_lang = false;
323   for (size_t idx = 0; idx < GetNumLanguages(); idx++) {
324     const lldb::LanguageType lang = GetLanguageAtIndex(idx);
325     if (lang != lldb::eLanguageTypeUnknown)
326       print_lang = true;
327     lang_stream.Printf("%s%s", Language::GetNameForLanguageType(lang),
328                        idx + 1 < GetNumLanguages() ? ", " : "");
329   }
330   if (print_lang)
331     stream.PutCString(lang_stream.GetString());
332   stream.PutChar(')');
333   return std::string(stream.GetString());
334 }
335