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