TypeCategory.cpp revision 360784
1//===-- TypeCategory.cpp -----------------------------------------*- C++-*-===// 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 13using namespace lldb; 14using namespace lldb_private; 15 16TypeCategoryImpl::TypeCategoryImpl(IFormatChangeListener *clist, 17 ConstString name) 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() {} 23 24static bool IsApplicable(lldb::LanguageType category_lang, 25 lldb::LanguageType valobj_lang) { 26 switch (category_lang) { 27 // Unless we know better, allow only exact equality. 28 default: 29 return category_lang == valobj_lang; 30 31 // the C family, we consider it as one 32 case eLanguageTypeC89: 33 case eLanguageTypeC: 34 case eLanguageTypeC99: 35 return valobj_lang == eLanguageTypeC89 || valobj_lang == eLanguageTypeC || 36 valobj_lang == eLanguageTypeC99; 37 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; 42 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; 48 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; 55 56 // Categories with unspecified language match everything. 57 case eLanguageTypeUnknown: 58 return true; 59 } 60} 61 62bool 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)) 66 return true; 67 } 68 return false; 69} 70 71size_t TypeCategoryImpl::GetNumLanguages() { 72 if (m_languages.empty()) 73 return 1; 74 return m_languages.size(); 75} 76 77lldb::LanguageType TypeCategoryImpl::GetLanguageAtIndex(size_t idx) { 78 if (m_languages.empty()) 79 return lldb::eLanguageTypeUnknown; 80 return m_languages[idx]; 81} 82 83void TypeCategoryImpl::AddLanguage(lldb::LanguageType lang) { 84 m_languages.push_back(lang); 85} 86 87bool TypeCategoryImpl::Get(lldb::LanguageType lang, 88 const FormattersMatchVector &candidates, 89 lldb::TypeFormatImplSP &entry, uint32_t *reason) { 90 if (!IsEnabled() || !IsApplicable(lang)) 91 return false; 92 if (GetTypeFormatsContainer()->Get(candidates, entry, reason)) 93 return true; 94 bool regex = GetRegexTypeFormatsContainer()->Get(candidates, entry, reason); 95 if (regex && reason) 96 *reason |= lldb_private::eFormatterChoiceCriterionRegularExpressionSummary; 97 return regex; 98} 99 100bool TypeCategoryImpl::Get(lldb::LanguageType lang, 101 const FormattersMatchVector &candidates, 102 lldb::TypeSummaryImplSP &entry, uint32_t *reason) { 103 if (!IsEnabled() || !IsApplicable(lang)) 104 return false; 105 if (GetTypeSummariesContainer()->Get(candidates, entry, reason)) 106 return true; 107 bool regex = GetRegexTypeSummariesContainer()->Get(candidates, entry, reason); 108 if (regex && reason) 109 *reason |= lldb_private::eFormatterChoiceCriterionRegularExpressionSummary; 110 return regex; 111} 112 113bool TypeCategoryImpl::Get(lldb::LanguageType lang, 114 const FormattersMatchVector &candidates, 115 lldb::SyntheticChildrenSP &entry, uint32_t *reason) { 116 if (!IsEnabled() || !IsApplicable(lang)) 117 return false; 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 122 123 if (!GetTypeFiltersContainer()->Get(candidates, filter_sp, &reason_filter)) 124 regex_filter = GetRegexTypeFiltersContainer()->Get(candidates, filter_sp, 125 &reason_filter); 126 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, 133 &reason_synth); 134 if (!filter_sp.get() && !synth.get()) 135 return false; 136 else if (!filter_sp.get() && synth.get()) 137 pick_synth = true; 138 139 else if (filter_sp.get() && !synth.get()) 140 pick_synth = false; 141 142 else /*if (filter_sp.get() && synth.get())*/ 143 { 144 pick_synth = filter_sp->GetRevision() <= synth->GetRevision(); 145 } 146 if (pick_synth) { 147 if (regex_synth && reason) 148 *reason |= lldb_private::eFormatterChoiceCriterionRegularExpressionFilter; 149 entry = synth; 150 return true; 151 } else { 152 if (regex_filter && reason) 153 *reason |= lldb_private::eFormatterChoiceCriterionRegularExpressionFilter; 154 entry = filter_sp; 155 return true; 156 } 157 return false; 158} 159 160void TypeCategoryImpl::Clear(FormatCategoryItems items) { 161 if ((items & eFormatCategoryItemValue) == eFormatCategoryItemValue) 162 GetTypeFormatsContainer()->Clear(); 163 if ((items & eFormatCategoryItemRegexValue) == eFormatCategoryItemRegexValue) 164 GetRegexTypeFormatsContainer()->Clear(); 165 166 if ((items & eFormatCategoryItemSummary) == eFormatCategoryItemSummary) 167 GetTypeSummariesContainer()->Clear(); 168 if ((items & eFormatCategoryItemRegexSummary) == 169 eFormatCategoryItemRegexSummary) 170 GetRegexTypeSummariesContainer()->Clear(); 171 172 if ((items & eFormatCategoryItemFilter) == eFormatCategoryItemFilter) 173 GetTypeFiltersContainer()->Clear(); 174 if ((items & eFormatCategoryItemRegexFilter) == 175 eFormatCategoryItemRegexFilter) 176 GetRegexTypeFiltersContainer()->Clear(); 177 178 if ((items & eFormatCategoryItemSynth) == eFormatCategoryItemSynth) 179 GetTypeSyntheticsContainer()->Clear(); 180 if ((items & eFormatCategoryItemRegexSynth) == eFormatCategoryItemRegexSynth) 181 GetRegexTypeSyntheticsContainer()->Clear(); 182} 183 184bool TypeCategoryImpl::Delete(ConstString name, FormatCategoryItems items) { 185 bool success = false; 186 187 if ((items & eFormatCategoryItemValue) == eFormatCategoryItemValue) 188 success = GetTypeFormatsContainer()->Delete(name) || success; 189 if ((items & eFormatCategoryItemRegexValue) == eFormatCategoryItemRegexValue) 190 success = GetRegexTypeFormatsContainer()->Delete(name) || success; 191 192 if ((items & eFormatCategoryItemSummary) == eFormatCategoryItemSummary) 193 success = GetTypeSummariesContainer()->Delete(name) || success; 194 if ((items & eFormatCategoryItemRegexSummary) == 195 eFormatCategoryItemRegexSummary) 196 success = GetRegexTypeSummariesContainer()->Delete(name) || success; 197 198 if ((items & eFormatCategoryItemFilter) == eFormatCategoryItemFilter) 199 success = GetTypeFiltersContainer()->Delete(name) || success; 200 if ((items & eFormatCategoryItemRegexFilter) == 201 eFormatCategoryItemRegexFilter) 202 success = GetRegexTypeFiltersContainer()->Delete(name) || success; 203 204 if ((items & eFormatCategoryItemSynth) == eFormatCategoryItemSynth) 205 success = GetTypeSyntheticsContainer()->Delete(name) || success; 206 if ((items & eFormatCategoryItemRegexSynth) == eFormatCategoryItemRegexSynth) 207 success = GetRegexTypeSyntheticsContainer()->Delete(name) || success; 208 209 return success; 210} 211 212uint32_t TypeCategoryImpl::GetCount(FormatCategoryItems items) { 213 uint32_t count = 0; 214 215 if ((items & eFormatCategoryItemValue) == eFormatCategoryItemValue) 216 count += GetTypeFormatsContainer()->GetCount(); 217 if ((items & eFormatCategoryItemRegexValue) == eFormatCategoryItemRegexValue) 218 count += GetRegexTypeFormatsContainer()->GetCount(); 219 220 if ((items & eFormatCategoryItemSummary) == eFormatCategoryItemSummary) 221 count += GetTypeSummariesContainer()->GetCount(); 222 if ((items & eFormatCategoryItemRegexSummary) == 223 eFormatCategoryItemRegexSummary) 224 count += GetRegexTypeSummariesContainer()->GetCount(); 225 226 if ((items & eFormatCategoryItemFilter) == eFormatCategoryItemFilter) 227 count += GetTypeFiltersContainer()->GetCount(); 228 if ((items & eFormatCategoryItemRegexFilter) == 229 eFormatCategoryItemRegexFilter) 230 count += GetRegexTypeFiltersContainer()->GetCount(); 231 232 if ((items & eFormatCategoryItemSynth) == eFormatCategoryItemSynth) 233 count += GetTypeSyntheticsContainer()->GetCount(); 234 if ((items & eFormatCategoryItemRegexSynth) == eFormatCategoryItemRegexSynth) 235 count += GetRegexTypeSyntheticsContainer()->GetCount(); 236 237 return count; 238} 239 240bool 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) 245 return false; 246 247 lldb::TypeFormatImplSP format_sp; 248 lldb::TypeSummaryImplSP summary_sp; 249 TypeFilterImpl::SharedPointer filter_sp; 250 ScriptedSyntheticChildren::SharedPointer synth_sp; 251 252 if ((items & eFormatCategoryItemValue) == eFormatCategoryItemValue) { 253 if (GetTypeFormatsContainer()->Get(type_name, format_sp)) { 254 if (matching_category) 255 *matching_category = m_name.GetCString(); 256 if (matching_type) 257 *matching_type = eFormatCategoryItemValue; 258 return true; 259 } 260 } 261 if ((items & eFormatCategoryItemRegexValue) == 262 eFormatCategoryItemRegexValue) { 263 if (GetRegexTypeFormatsContainer()->Get(type_name, format_sp)) { 264 if (matching_category) 265 *matching_category = m_name.GetCString(); 266 if (matching_type) 267 *matching_type = eFormatCategoryItemRegexValue; 268 return true; 269 } 270 } 271 272 if ((items & eFormatCategoryItemSummary) == eFormatCategoryItemSummary) { 273 if (GetTypeSummariesContainer()->Get(type_name, summary_sp)) { 274 if (matching_category) 275 *matching_category = m_name.GetCString(); 276 if (matching_type) 277 *matching_type = eFormatCategoryItemSummary; 278 return true; 279 } 280 } 281 if ((items & eFormatCategoryItemRegexSummary) == 282 eFormatCategoryItemRegexSummary) { 283 if (GetRegexTypeSummariesContainer()->Get(type_name, summary_sp)) { 284 if (matching_category) 285 *matching_category = m_name.GetCString(); 286 if (matching_type) 287 *matching_type = eFormatCategoryItemRegexSummary; 288 return true; 289 } 290 } 291 292 if ((items & eFormatCategoryItemFilter) == eFormatCategoryItemFilter) { 293 if (GetTypeFiltersContainer()->Get(type_name, filter_sp)) { 294 if (matching_category) 295 *matching_category = m_name.GetCString(); 296 if (matching_type) 297 *matching_type = eFormatCategoryItemFilter; 298 return true; 299 } 300 } 301 if ((items & eFormatCategoryItemRegexFilter) == 302 eFormatCategoryItemRegexFilter) { 303 if (GetRegexTypeFiltersContainer()->Get(type_name, filter_sp)) { 304 if (matching_category) 305 *matching_category = m_name.GetCString(); 306 if (matching_type) 307 *matching_type = eFormatCategoryItemRegexFilter; 308 return true; 309 } 310 } 311 312 if ((items & eFormatCategoryItemSynth) == eFormatCategoryItemSynth) { 313 if (GetTypeSyntheticsContainer()->Get(type_name, synth_sp)) { 314 if (matching_category) 315 *matching_category = m_name.GetCString(); 316 if (matching_type) 317 *matching_type = eFormatCategoryItemSynth; 318 return true; 319 } 320 } 321 if ((items & eFormatCategoryItemRegexSynth) == 322 eFormatCategoryItemRegexSynth) { 323 if (GetRegexTypeSyntheticsContainer()->Get(type_name, synth_sp)) { 324 if (matching_category) 325 *matching_category = m_name.GetCString(); 326 if (matching_type) 327 *matching_type = eFormatCategoryItemRegexSynth; 328 return true; 329 } 330 } 331 332 return false; 333} 334 335TypeCategoryImpl::FormatContainer::MapValueType 336TypeCategoryImpl::GetFormatForType(lldb::TypeNameSpecifierImplSP type_sp) { 337 FormatContainer::MapValueType retval; 338 339 if (type_sp) { 340 if (type_sp->IsRegex()) 341 GetRegexTypeFormatsContainer()->GetExact(ConstString(type_sp->GetName()), 342 retval); 343 else 344 GetTypeFormatsContainer()->GetExact(ConstString(type_sp->GetName()), 345 retval); 346 } 347 348 return retval; 349} 350 351TypeCategoryImpl::SummaryContainer::MapValueType 352TypeCategoryImpl::GetSummaryForType(lldb::TypeNameSpecifierImplSP type_sp) { 353 SummaryContainer::MapValueType retval; 354 355 if (type_sp) { 356 if (type_sp->IsRegex()) 357 GetRegexTypeSummariesContainer()->GetExact( 358 ConstString(type_sp->GetName()), retval); 359 else 360 GetTypeSummariesContainer()->GetExact(ConstString(type_sp->GetName()), 361 retval); 362 } 363 364 return retval; 365} 366 367TypeCategoryImpl::FilterContainer::MapValueType 368TypeCategoryImpl::GetFilterForType(lldb::TypeNameSpecifierImplSP type_sp) { 369 FilterContainer::MapValueType retval; 370 371 if (type_sp) { 372 if (type_sp->IsRegex()) 373 GetRegexTypeFiltersContainer()->GetExact(ConstString(type_sp->GetName()), 374 retval); 375 else 376 GetTypeFiltersContainer()->GetExact(ConstString(type_sp->GetName()), 377 retval); 378 } 379 380 return retval; 381} 382 383TypeCategoryImpl::SynthContainer::MapValueType 384TypeCategoryImpl::GetSyntheticForType(lldb::TypeNameSpecifierImplSP type_sp) { 385 SynthContainer::MapValueType retval; 386 387 if (type_sp) { 388 if (type_sp->IsRegex()) 389 GetRegexTypeSyntheticsContainer()->GetExact( 390 ConstString(type_sp->GetName()), retval); 391 else 392 GetTypeSyntheticsContainer()->GetExact(ConstString(type_sp->GetName()), 393 retval); 394 } 395 396 return retval; 397} 398 399lldb::TypeNameSpecifierImplSP 400TypeCategoryImpl::GetTypeNameSpecifierForSummaryAtIndex(size_t index) { 401 if (index < GetTypeSummariesContainer()->GetCount()) 402 return GetTypeSummariesContainer()->GetTypeNameSpecifierAtIndex(index); 403 else 404 return GetRegexTypeSummariesContainer()->GetTypeNameSpecifierAtIndex( 405 index - GetTypeSummariesContainer()->GetCount()); 406} 407 408TypeCategoryImpl::FormatContainer::MapValueType 409TypeCategoryImpl::GetFormatAtIndex(size_t index) { 410 if (index < GetTypeFormatsContainer()->GetCount()) 411 return GetTypeFormatsContainer()->GetAtIndex(index); 412 else 413 return GetRegexTypeFormatsContainer()->GetAtIndex( 414 index - GetTypeFormatsContainer()->GetCount()); 415} 416 417TypeCategoryImpl::SummaryContainer::MapValueType 418TypeCategoryImpl::GetSummaryAtIndex(size_t index) { 419 if (index < GetTypeSummariesContainer()->GetCount()) 420 return GetTypeSummariesContainer()->GetAtIndex(index); 421 else 422 return GetRegexTypeSummariesContainer()->GetAtIndex( 423 index - GetTypeSummariesContainer()->GetCount()); 424} 425 426TypeCategoryImpl::FilterContainer::MapValueType 427TypeCategoryImpl::GetFilterAtIndex(size_t index) { 428 if (index < GetTypeFiltersContainer()->GetCount()) 429 return GetTypeFiltersContainer()->GetAtIndex(index); 430 else 431 return GetRegexTypeFiltersContainer()->GetAtIndex( 432 index - GetTypeFiltersContainer()->GetCount()); 433} 434 435lldb::TypeNameSpecifierImplSP 436TypeCategoryImpl::GetTypeNameSpecifierForFormatAtIndex(size_t index) { 437 if (index < GetTypeFormatsContainer()->GetCount()) 438 return GetTypeFormatsContainer()->GetTypeNameSpecifierAtIndex(index); 439 else 440 return GetRegexTypeFormatsContainer()->GetTypeNameSpecifierAtIndex( 441 index - GetTypeFormatsContainer()->GetCount()); 442} 443 444lldb::TypeNameSpecifierImplSP 445TypeCategoryImpl::GetTypeNameSpecifierForFilterAtIndex(size_t index) { 446 if (index < GetTypeFiltersContainer()->GetCount()) 447 return GetTypeFiltersContainer()->GetTypeNameSpecifierAtIndex(index); 448 else 449 return GetRegexTypeFiltersContainer()->GetTypeNameSpecifierAtIndex( 450 index - GetTypeFiltersContainer()->GetCount()); 451} 452 453TypeCategoryImpl::SynthContainer::MapValueType 454TypeCategoryImpl::GetSyntheticAtIndex(size_t index) { 455 if (index < GetTypeSyntheticsContainer()->GetCount()) 456 return GetTypeSyntheticsContainer()->GetAtIndex(index); 457 else 458 return GetRegexTypeSyntheticsContainer()->GetAtIndex( 459 index - GetTypeSyntheticsContainer()->GetCount()); 460} 461 462lldb::TypeNameSpecifierImplSP 463TypeCategoryImpl::GetTypeNameSpecifierForSyntheticAtIndex(size_t index) { 464 if (index < GetTypeSyntheticsContainer()->GetCount()) 465 return GetTypeSyntheticsContainer()->GetTypeNameSpecifierAtIndex(index); 466 else 467 return GetRegexTypeSyntheticsContainer()->GetTypeNameSpecifierAtIndex( 468 index - GetTypeSyntheticsContainer()->GetCount()); 469} 470 471void 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(); 477} 478 479std::string TypeCategoryImpl::GetDescription() { 480 StreamString stream; 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) 488 print_lang = true; 489 lang_stream.Printf("%s%s", Language::GetNameForLanguageType(lang), 490 idx + 1 < GetNumLanguages() ? ", " : ""); 491 } 492 if (print_lang) 493 stream.PutCString(lang_stream.GetString()); 494 stream.PutChar(')'); 495 return stream.GetString(); 496} 497