1 //===-- TypeSynthetic.h -------------------------------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #ifndef lldb_TypeSynthetic_h_ 11 #define lldb_TypeSynthetic_h_ 12 13 // C Includes 14 #include <stdint.h> 15 #include <unistd.h> 16 17 // C++ Includes 18 #include <string> 19 #include <vector> 20 21 // Other libraries and framework includes 22 23 // Project includes 24 #include "lldb/lldb-public.h" 25 #include "lldb/lldb-enumerations.h" 26 27 #include "lldb/Core/ValueObject.h" 28 #include "lldb/Interpreter/ScriptInterpreterPython.h" 29 #include "lldb/Symbol/Type.h" 30 31 namespace lldb_private { 32 class SyntheticChildrenFrontEnd 33 { 34 protected: 35 ValueObject &m_backend; 36 public: 37 SyntheticChildrenFrontEnd(ValueObject & backend)38 SyntheticChildrenFrontEnd (ValueObject &backend) : 39 m_backend(backend) 40 {} 41 42 virtual ~SyntheticChildrenFrontEnd()43 ~SyntheticChildrenFrontEnd () 44 { 45 } 46 47 virtual size_t 48 CalculateNumChildren () = 0; 49 50 virtual lldb::ValueObjectSP 51 GetChildAtIndex (size_t idx) = 0; 52 53 virtual size_t 54 GetIndexOfChildWithName (const ConstString &name) = 0; 55 56 // this function is assumed to always succeed and it if fails, the front-end should know to deal 57 // with it in the correct way (most probably, by refusing to return any children) 58 // the return value of Update() should actually be interpreted as "ValueObjectSyntheticFilter cache is good/bad" 59 // if =true, ValueObjectSyntheticFilter is allowed to use the children it fetched previously and cached 60 // if =false, ValueObjectSyntheticFilter must throw away its cache, and query again for children 61 virtual bool 62 Update () = 0; 63 64 // if this function returns false, then CalculateNumChildren() MUST return 0 since UI frontends 65 // might validly decide not to inquire for children given a false return value from this call 66 // if it returns true, then CalculateNumChildren() can return any number >= 0 (0 being valid) 67 // it should if at all possible be more efficient than CalculateNumChildren() 68 virtual bool 69 MightHaveChildren () = 0; 70 71 typedef std::shared_ptr<SyntheticChildrenFrontEnd> SharedPointer; 72 typedef std::unique_ptr<SyntheticChildrenFrontEnd> AutoPointer; 73 74 private: 75 DISALLOW_COPY_AND_ASSIGN(SyntheticChildrenFrontEnd); 76 }; 77 78 class SyntheticChildren 79 { 80 public: 81 82 class Flags 83 { 84 public: 85 Flags()86 Flags () : 87 m_flags (lldb::eTypeOptionCascade) 88 {} 89 Flags(const Flags & other)90 Flags (const Flags& other) : 91 m_flags (other.m_flags) 92 {} 93 Flags(uint32_t value)94 Flags (uint32_t value) : 95 m_flags (value) 96 {} 97 98 Flags& 99 operator = (const Flags& rhs) 100 { 101 if (&rhs != this) 102 m_flags = rhs.m_flags; 103 104 return *this; 105 } 106 107 Flags& 108 operator = (const uint32_t& rhs) 109 { 110 m_flags = rhs; 111 return *this; 112 } 113 114 Flags& Clear()115 Clear() 116 { 117 m_flags = 0; 118 return *this; 119 } 120 121 bool GetCascades()122 GetCascades () const 123 { 124 return (m_flags & lldb::eTypeOptionCascade) == lldb::eTypeOptionCascade; 125 } 126 127 Flags& 128 SetCascades (bool value = true) 129 { 130 if (value) 131 m_flags |= lldb::eTypeOptionCascade; 132 else 133 m_flags &= ~lldb::eTypeOptionCascade; 134 return *this; 135 } 136 137 bool GetSkipPointers()138 GetSkipPointers () const 139 { 140 return (m_flags & lldb::eTypeOptionSkipPointers) == lldb::eTypeOptionSkipPointers; 141 } 142 143 Flags& 144 SetSkipPointers (bool value = true) 145 { 146 if (value) 147 m_flags |= lldb::eTypeOptionSkipPointers; 148 else 149 m_flags &= ~lldb::eTypeOptionSkipPointers; 150 return *this; 151 } 152 153 bool GetSkipReferences()154 GetSkipReferences () const 155 { 156 return (m_flags & lldb::eTypeOptionSkipReferences) == lldb::eTypeOptionSkipReferences; 157 } 158 159 Flags& 160 SetSkipReferences (bool value = true) 161 { 162 if (value) 163 m_flags |= lldb::eTypeOptionSkipReferences; 164 else 165 m_flags &= ~lldb::eTypeOptionSkipReferences; 166 return *this; 167 } 168 169 uint32_t GetValue()170 GetValue () 171 { 172 return m_flags; 173 } 174 175 void SetValue(uint32_t value)176 SetValue (uint32_t value) 177 { 178 m_flags = value; 179 } 180 181 private: 182 uint32_t m_flags; 183 }; 184 SyntheticChildren(const Flags & flags)185 SyntheticChildren (const Flags& flags) : 186 m_flags(flags) 187 { 188 } 189 190 virtual ~SyntheticChildren()191 ~SyntheticChildren () 192 { 193 } 194 195 bool Cascades()196 Cascades () const 197 { 198 return m_flags.GetCascades(); 199 } 200 bool SkipsPointers()201 SkipsPointers () const 202 { 203 return m_flags.GetSkipPointers(); 204 } 205 bool SkipsReferences()206 SkipsReferences () const 207 { 208 return m_flags.GetSkipReferences(); 209 } 210 211 void SetCascades(bool value)212 SetCascades (bool value) 213 { 214 m_flags.SetCascades(value); 215 } 216 217 void SetSkipsPointers(bool value)218 SetSkipsPointers (bool value) 219 { 220 m_flags.SetSkipPointers(value); 221 } 222 223 void SetSkipsReferences(bool value)224 SetSkipsReferences (bool value) 225 { 226 m_flags.SetSkipReferences(value); 227 } 228 229 uint32_t GetOptions()230 GetOptions () 231 { 232 return m_flags.GetValue(); 233 } 234 235 void SetOptions(uint32_t value)236 SetOptions (uint32_t value) 237 { 238 m_flags.SetValue(value); 239 } 240 241 virtual bool 242 IsScripted () = 0; 243 244 virtual std::string 245 GetDescription () = 0; 246 247 virtual SyntheticChildrenFrontEnd::AutoPointer 248 GetFrontEnd (ValueObject &backend) = 0; 249 250 typedef std::shared_ptr<SyntheticChildren> SharedPointer; 251 typedef bool(*SyntheticChildrenCallback)(void*, ConstString, const SyntheticChildren::SharedPointer&); 252 253 uint32_t& GetRevision()254 GetRevision () 255 { 256 return m_my_revision; 257 } 258 259 protected: 260 uint32_t m_my_revision; 261 Flags m_flags; 262 263 private: 264 DISALLOW_COPY_AND_ASSIGN(SyntheticChildren); 265 }; 266 267 class TypeFilterImpl : public SyntheticChildren 268 { 269 std::vector<std::string> m_expression_paths; 270 public: TypeFilterImpl(const SyntheticChildren::Flags & flags)271 TypeFilterImpl(const SyntheticChildren::Flags& flags) : 272 SyntheticChildren(flags), 273 m_expression_paths() 274 { 275 } 276 TypeFilterImpl(const SyntheticChildren::Flags & flags,const std::initializer_list<const char * > items)277 TypeFilterImpl(const SyntheticChildren::Flags& flags, 278 const std::initializer_list<const char*> items) : 279 SyntheticChildren(flags), 280 m_expression_paths() 281 { 282 for (auto path : items) 283 AddExpressionPath (path); 284 } 285 286 void AddExpressionPath(const char * path)287 AddExpressionPath (const char* path) 288 { 289 AddExpressionPath(std::string(path)); 290 } 291 292 void Clear()293 Clear() 294 { 295 m_expression_paths.clear(); 296 } 297 298 size_t GetCount()299 GetCount() const 300 { 301 return m_expression_paths.size(); 302 } 303 304 const char* GetExpressionPathAtIndex(size_t i)305 GetExpressionPathAtIndex(size_t i) const 306 { 307 return m_expression_paths[i].c_str(); 308 } 309 310 bool SetExpressionPathAtIndex(size_t i,const char * path)311 SetExpressionPathAtIndex (size_t i, const char* path) 312 { 313 return SetExpressionPathAtIndex(i, std::string(path)); 314 } 315 316 void AddExpressionPath(const std::string & path)317 AddExpressionPath (const std::string& path) 318 { 319 bool need_add_dot = true; 320 if (path[0] == '.' || 321 (path[0] == '-' && path[1] == '>') || 322 path[0] == '[') 323 need_add_dot = false; 324 // add a '.' symbol to help forgetful users 325 if(!need_add_dot) 326 m_expression_paths.push_back(path); 327 else 328 m_expression_paths.push_back(std::string(".") + path); 329 } 330 331 bool SetExpressionPathAtIndex(size_t i,const std::string & path)332 SetExpressionPathAtIndex (size_t i, const std::string& path) 333 { 334 if (i >= GetCount()) 335 return false; 336 bool need_add_dot = true; 337 if (path[0] == '.' || 338 (path[0] == '-' && path[1] == '>') || 339 path[0] == '[') 340 need_add_dot = false; 341 // add a '.' symbol to help forgetful users 342 if(!need_add_dot) 343 m_expression_paths[i] = path; 344 else 345 m_expression_paths[i] = std::string(".") + path; 346 return true; 347 } 348 349 bool IsScripted()350 IsScripted () 351 { 352 return false; 353 } 354 355 std::string 356 GetDescription (); 357 358 class FrontEnd : public SyntheticChildrenFrontEnd 359 { 360 private: 361 TypeFilterImpl* filter; 362 public: 363 FrontEnd(TypeFilterImpl * flt,ValueObject & backend)364 FrontEnd(TypeFilterImpl* flt, 365 ValueObject &backend) : 366 SyntheticChildrenFrontEnd(backend), 367 filter(flt) 368 {} 369 370 virtual ~FrontEnd()371 ~FrontEnd () 372 { 373 } 374 375 virtual size_t CalculateNumChildren()376 CalculateNumChildren () 377 { 378 return filter->GetCount(); 379 } 380 381 virtual lldb::ValueObjectSP GetChildAtIndex(size_t idx)382 GetChildAtIndex (size_t idx) 383 { 384 if (idx >= filter->GetCount()) 385 return lldb::ValueObjectSP(); 386 return m_backend.GetSyntheticExpressionPathChild(filter->GetExpressionPathAtIndex(idx), true); 387 } 388 389 virtual bool Update()390 Update() { return false; } 391 392 virtual bool MightHaveChildren()393 MightHaveChildren () 394 { 395 return filter->GetCount() > 0; 396 } 397 398 virtual size_t GetIndexOfChildWithName(const ConstString & name)399 GetIndexOfChildWithName (const ConstString &name) 400 { 401 const char* name_cstr = name.GetCString(); 402 for (size_t i = 0; i < filter->GetCount(); i++) 403 { 404 const char* expr_cstr = filter->GetExpressionPathAtIndex(i); 405 if (expr_cstr) 406 { 407 if (*expr_cstr == '.') 408 expr_cstr++; 409 else if (*expr_cstr == '-' && *(expr_cstr+1) == '>') 410 expr_cstr += 2; 411 } 412 if (!::strcmp(name_cstr, expr_cstr)) 413 return i; 414 } 415 return UINT32_MAX; 416 } 417 418 typedef std::shared_ptr<SyntheticChildrenFrontEnd> SharedPointer; 419 420 private: 421 DISALLOW_COPY_AND_ASSIGN(FrontEnd); 422 }; 423 424 virtual SyntheticChildrenFrontEnd::AutoPointer GetFrontEnd(ValueObject & backend)425 GetFrontEnd(ValueObject &backend) 426 { 427 return SyntheticChildrenFrontEnd::AutoPointer(new FrontEnd(this, backend)); 428 } 429 430 private: 431 DISALLOW_COPY_AND_ASSIGN(TypeFilterImpl); 432 }; 433 434 class CXXSyntheticChildren : public SyntheticChildren 435 { 436 public: 437 typedef SyntheticChildrenFrontEnd* (*CreateFrontEndCallback) (CXXSyntheticChildren*, lldb::ValueObjectSP); 438 protected: 439 CreateFrontEndCallback m_create_callback; 440 std::string m_description; 441 public: CXXSyntheticChildren(const SyntheticChildren::Flags & flags,const char * description,CreateFrontEndCallback callback)442 CXXSyntheticChildren (const SyntheticChildren::Flags& flags, 443 const char* description, 444 CreateFrontEndCallback callback) : 445 SyntheticChildren(flags), 446 m_create_callback(callback), 447 m_description(description ? description : "") 448 { 449 } 450 451 bool IsScripted()452 IsScripted () 453 { 454 return false; 455 } 456 457 std::string 458 GetDescription (); 459 460 virtual SyntheticChildrenFrontEnd::AutoPointer GetFrontEnd(ValueObject & backend)461 GetFrontEnd (ValueObject &backend) 462 { 463 return SyntheticChildrenFrontEnd::AutoPointer(m_create_callback(this, backend.GetSP())); 464 } 465 466 private: 467 DISALLOW_COPY_AND_ASSIGN(CXXSyntheticChildren); 468 }; 469 470 #ifndef LLDB_DISABLE_PYTHON 471 472 class ScriptedSyntheticChildren : public SyntheticChildren 473 { 474 std::string m_python_class; 475 std::string m_python_code; 476 public: 477 478 ScriptedSyntheticChildren (const SyntheticChildren::Flags& flags, 479 const char* pclass, 480 const char* pcode = NULL) : SyntheticChildren(flags)481 SyntheticChildren(flags), 482 m_python_class(), 483 m_python_code() 484 { 485 if (pclass) 486 m_python_class = pclass; 487 if (pcode) 488 m_python_code = pcode; 489 } 490 491 const char* GetPythonClassName()492 GetPythonClassName () 493 { 494 return m_python_class.c_str(); 495 } 496 497 const char* GetPythonCode()498 GetPythonCode () 499 { 500 return m_python_code.c_str(); 501 } 502 503 void SetPythonClassName(const char * fname)504 SetPythonClassName (const char* fname) 505 { 506 m_python_class.assign(fname); 507 m_python_code.clear(); 508 } 509 510 void SetPythonCode(const char * script)511 SetPythonCode (const char* script) 512 { 513 m_python_code.assign(script); 514 } 515 516 std::string 517 GetDescription (); 518 519 bool IsScripted()520 IsScripted () 521 { 522 return true; 523 } 524 525 class FrontEnd : public SyntheticChildrenFrontEnd 526 { 527 private: 528 std::string m_python_class; 529 lldb::ScriptInterpreterObjectSP m_wrapper_sp; 530 ScriptInterpreter *m_interpreter; 531 public: 532 533 FrontEnd (std::string pclass, 534 ValueObject &backend); 535 536 virtual 537 ~FrontEnd (); 538 539 virtual size_t CalculateNumChildren()540 CalculateNumChildren () 541 { 542 if (!m_wrapper_sp || m_interpreter == NULL) 543 return 0; 544 return m_interpreter->CalculateNumChildren(m_wrapper_sp); 545 } 546 547 virtual lldb::ValueObjectSP 548 GetChildAtIndex (size_t idx); 549 550 virtual bool Update()551 Update () 552 { 553 if (!m_wrapper_sp || m_interpreter == NULL) 554 return false; 555 556 return m_interpreter->UpdateSynthProviderInstance(m_wrapper_sp); 557 } 558 559 virtual bool MightHaveChildren()560 MightHaveChildren () 561 { 562 if (!m_wrapper_sp || m_interpreter == NULL) 563 return false; 564 565 return m_interpreter->MightHaveChildrenSynthProviderInstance(m_wrapper_sp); 566 } 567 568 virtual size_t GetIndexOfChildWithName(const ConstString & name)569 GetIndexOfChildWithName (const ConstString &name) 570 { 571 if (!m_wrapper_sp || m_interpreter == NULL) 572 return UINT32_MAX; 573 return m_interpreter->GetIndexOfChildWithName(m_wrapper_sp, name.GetCString()); 574 } 575 576 typedef std::shared_ptr<SyntheticChildrenFrontEnd> SharedPointer; 577 578 private: 579 DISALLOW_COPY_AND_ASSIGN(FrontEnd); 580 }; 581 582 virtual SyntheticChildrenFrontEnd::AutoPointer GetFrontEnd(ValueObject & backend)583 GetFrontEnd(ValueObject &backend) 584 { 585 return SyntheticChildrenFrontEnd::AutoPointer(new FrontEnd(m_python_class, backend)); 586 } 587 588 private: 589 DISALLOW_COPY_AND_ASSIGN(ScriptedSyntheticChildren); 590 }; 591 #endif 592 } // namespace lldb_private 593 594 #endif // lldb_TypeSynthetic_h_ 595