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