1 /** 2 * Copyright: Copyright (c) 2011-2016 Jacob Carlborg. All rights reserved. 3 * Authors: Jacob Carlborg, Joakim Brännström (joakim.brannstrom dottli gmx.com) 4 * Version: 1.1+ 5 * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0) 6 * History: 7 * 1.0 initial release. 2012-01-29 $(BR) 8 * Jacob Carlborg 9 * 10 * 1.1+ additional features missing compared to cindex.py. 2015-03-07 $(BR) 11 * Joakim Brännström 12 * 13 * TODO split the specific C++ stuff to a dedicated cursor. 14 * TODO implement cxxMangling. 15 */ 16 module clang.Cursor; 17 18 import clang.c.Index; 19 20 import clang.Eval; 21 import clang.File; 22 import clang.SourceLocation; 23 import clang.SourceRange; 24 import clang.Token; 25 import clang.TranslationUnit; 26 import clang.Type; 27 import clang.Util; 28 import clang.Visitor; 29 30 /** The Cursor class represents a reference to an element within the AST. It 31 * acts as a kind of iterator. 32 */ 33 @safe struct Cursor { 34 mixin CX; 35 36 // for example primitive types are predefined 37 private static const CXCursorKind[string] predefined; 38 39 static this() { 40 // populate the database once 41 predefined = queryPredefined(); 42 } 43 44 /// Retrieve the NULL cursor, which represents no entity. 45 @property static Cursor empty() @trusted { 46 auto r = clang_getNullCursor(); 47 return Cursor(r); 48 } 49 50 /** Retrieve a Unified Symbol Resolution (USR) for the entity referenced by 51 * the given cursor. 52 * 53 * A Unified Symbol Resolution (USR) is a string that identifies a 54 * particular entity (function, class, variable, etc.) within a program. 55 * USRs can be compared across translation units to determine, e.g., when 56 * references in one translation refer to an entity defined in another 57 * translation unit. 58 */ 59 @property string usr() const @trusted { 60 return toD(clang_getCursorUSR(cx)); 61 } 62 63 /// Return: Retrieve a name for the entity referenced by this cursor. 64 @property string spelling() const @trusted { 65 return toD(clang_getCursorSpelling(cx)); 66 } 67 68 /** 69 * Returns the storage class for a function or variable declaration. 70 * 71 * If the passed in Cursor is not a function or variable declaration, 72 * CX_SC_Invalid is returned else the storage class. 73 */ 74 @property CX_StorageClass storageClass() const @trusted { 75 return clang_Cursor_getStorageClass(cx); 76 } 77 78 /** Determine the linkage of the entity referred to by a given cursor. 79 * 80 * This value indicates that no linkage information is available for a 81 * provided CXCursor. 82 * CXLinkage_Invalid, 83 * 84 * This is the linkage for variables, parameters, and so on that have 85 * automatic storage. This covers normal (non-extern) local variables. 86 * CXLinkage_NoLinkage, 87 * 88 * This is the linkage for static variables and static functions. 89 * CXLinkage_Internal, 90 * 91 * This is the linkage for entities with external linkage that live 92 * in C++ anonymous namespaces. 93 * CXLinkage_UniqueExternal, 94 * 95 * This is the linkage for entities with true, external linkage. 96 * CXLinkage_External 97 */ 98 @property CXLinkageKind linkage() const @trusted { 99 return clang_getCursorLinkage(cx); 100 } 101 102 /** Return the display name for the entity referenced by this cursor. 103 * 104 * The display name contains extra information that helps identify the 105 * cursor, such as the parameters of a function or template or the 106 * arguments of a class template specialization. 107 * 108 * If it is NOT a declaration then the return value is the same as 109 * spelling. 110 */ 111 @property string displayName() const @trusted { 112 return toD(clang_getCursorDisplayName(cx)); 113 } 114 115 /** Return the cursor kind of the template specialization that would be 116 * generated when instantiating the template with this cursor. 117 */ 118 @property CXCursorKind templateKind() const @trusted { 119 return clang_getTemplateCursorKind(cx); 120 } 121 122 /** Return the cursor that represents the template that given cursor 123 * specializes (or is instantiated) from. 124 * 125 * It will only work for a cursor that represent a specialization or 126 * insantiation of a template. Otherwise, NULL cursor is returned. 127 */ 128 @property CXCursor templateCursor() const @trusted { 129 return clang_getSpecializedCursorTemplate(cx); 130 } 131 132 /** Retrieve the string representing the mangled name of the cursor. 133 * 134 * Only useful for cursors that are NOT declarations. 135 */ 136 @property string mangling() const @trusted { 137 return toD(clang_Cursor_getMangling(cx)); 138 } 139 140 /** 141 * \brief Retrieve the CXStrings representing the mangled symbols of the C++ 142 * constructor or destructor at the cursor. 143 */ 144 //@property string[] cxxMangling() const @trusted { 145 // CXStringSet *clang_Cursor_getCXXManglings(CXCursor); 146 //} 147 148 /// Return: the kind of this cursor. 149 @property CXCursorKind kind() const @trusted { 150 return clang_getCursorKind(cx); 151 } 152 153 /** Retrieve the physical location of the source constructor referenced by 154 * the given cursor. 155 * 156 * The location of a declaration is typically the location of the name of 157 * that declaration, where the name of that declaration would occur if it 158 * is unnamed, or some keyword that introduces that particular declaration. 159 * The location of a reference is where that reference occurs within the 160 * source code. 161 */ 162 @property SourceLocation location() const @trusted { 163 return SourceLocation(clang_getCursorLocation(cx)); 164 } 165 166 /** Type (if any) of the entity pointed at by the cursor. 167 * 168 * The following isDeclaration cursors are handled: 169 * - TypeDecl 170 * - DeclaratorDecl (if source info exist) 171 * 172 * isReference cursors may be automatically dereferenced if they are of the 173 * following kind: 174 * - TypeRef 175 * - CXXBaseSpecifier 176 * - MemberRef 177 * - VariableRef 178 * The following are NOT handled: 179 * - TemplateRef 180 * - NamespaceRef 181 * - OverloadedDeclRef 182 */ 183 @property Type type() @trusted const { 184 auto r = clang_getCursorType(cx); 185 return Type(this, r); 186 } 187 188 /** Return the underlying type of a typedef declaration. 189 * 190 * If the current cursor is not a typedef an empty type is returned. 191 * 192 * Returns: the Type the typedef cursor is a declaration for. 193 */ 194 @property Type typedefUnderlyingType() @trusted const { 195 auto r = clang_getTypedefDeclUnderlyingType(cx); 196 return Type(this, r); 197 } 198 199 /** If the cursor is a reference to a declaration or a declaration of 200 * some entity, return a cursor that points to the definition of that 201 * entity. 202 */ 203 @property Cursor definition() const @trusted { 204 auto r = clang_getCursorDefinition(cx); 205 return Cursor(r); 206 } 207 208 /** Determine the semantic parent of the given cursor. 209 * 210 * The semantic parent of a cursor is the cursor that semantically contains 211 * the given cursor. For many declarations, the lexical and semantic 212 * parents are equivalent (the lexical parent is returned by 213 * clang_getCursorLexicalParent()). They diverge when declarations or 214 * definitions are provided out-of-line. For example: 215 * 216 * --- 217 * class C { 218 * void f(); 219 * } 220 * 221 * void C::f() { } 222 * --- 223 * 224 * In the out-of-line definition of C::f, the semantic parent is the the 225 * class C, of which this function is a member. The lexical parent is the 226 * place where the declaration actually occurs in the source code; in this 227 * case, the definition occurs in the translation unit. In general, the 228 * lexical parent for a given entity can change without affecting the 229 * semantics of the program, and the lexical parent of different 230 * declarations of the same entity may be different. Changing the semantic 231 * parent of a declaration, on the other hand, can have a major impact on 232 * semantics, and redeclarations of a particular entity should all have the 233 * same semantic context. 234 * 235 * In the example above, both declarations of C::f have C as their semantic 236 * context, while the lexical context of the first C::f is C and the 237 * lexical context of the second C::f is the translation unit. 238 * 239 * For global declarations, the semantic parent is the translation unit. 240 */ 241 @property Cursor semanticParent() const @trusted { 242 auto r = clang_getCursorSemanticParent(cx); 243 return Cursor(r); 244 } 245 246 /** Determine the lexical parent of the given cursor. 247 * 248 * The lexical parent of a cursor is the cursor in which the given cursor 249 * was actually written. For many declarations, the lexical and semantic 250 * parents are equivalent (the semantic parent is returned by 251 * clang_getCursorSemanticParent()). They diverge when declarations or 252 * definitions are provided out-of-line. For example: 253 * 254 * --- 255 * class C { 256 * void f(); 257 * } 258 * 259 * void C::f() { } 260 * --- 261 * 262 * In the out-of-line definition of C::f, the semantic parent is the the 263 * class C, of which this function is a member. The lexical parent is the 264 * place where the declaration actually occurs in the source code; in this 265 * case, the definition occurs in the translation unit. In general, the 266 * lexical parent for a given entity can change without affecting the 267 * semantics of the program, and the lexical parent of different 268 * declarations of the same entity may be different. Changing the semantic 269 * parent of a declaration, on the other hand, can have a major impact on 270 * semantics, and redeclarations of a particular entity should all have the 271 * same semantic context. 272 * 273 * In the example above, both declarations of C::f have C as their semantic 274 * context, while the lexical context of the first C::f is C and the 275 * lexical context of the second \c C::f is the translation unit. 276 * 277 * For declarations written in the global scope, the lexical parent is 278 * the translation unit. 279 */ 280 @property Cursor lexicalParent() const @trusted { 281 auto r = clang_getCursorLexicalParent(cx); 282 return Cursor(r); 283 } 284 285 /** For a cursor that is a reference, retrieve a cursor representing the 286 * entity that it references. 287 * 288 * Reference cursors refer to other entities in the AST. For example, an 289 * Objective-C superclass reference cursor refers to an Objective-C class. 290 * This function produces the cursor for the Objective-C class from the 291 * cursor for the superclass reference. If the input cursor is a 292 * declaration or definition, it returns that declaration or definition 293 * unchanged. Otherwise, returns the NULL cursor. 294 */ 295 @property Cursor referenced() const @trusted { 296 auto r = clang_getCursorReferenced(cx); 297 return Cursor(r); 298 } 299 300 @property DeclarationVisitor declarations() const @trusted { 301 return DeclarationVisitor(this); 302 } 303 304 /** Retrieve the physical extent of the source construct referenced by the 305 * given cursor. 306 * 307 * The extent of a cursor starts with the file/line/column pointing at the 308 * first character within the source construct that the cursor refers to 309 * and ends with the last character withinin that source construct. For a 310 * declaration, the extent covers the declaration itself. For a reference, 311 * the extent covers the location of the reference (e.g., where the 312 * referenced entity was actually used). 313 */ 314 @property SourceRange extent() const @trusted { 315 auto r = clang_getCursorExtent(cx); 316 return SourceRange(r); 317 } 318 319 /** If cursor is a statement declaration tries to evaluate the statement 320 * and if its variable, tries to evaluate its initializer, into its 321 * corresponding type. 322 */ 323 Eval eval() const @trusted { 324 return Eval(clang_Cursor_Evaluate(cx)); 325 } 326 327 /** Retrieve the canonical cursor corresponding to the given cursor. 328 * 329 * In the C family of languages, many kinds of entities can be declared 330 * several times within a single translation unit. For example, a structure 331 * type can be forward-declared (possibly multiple times) and later 332 * defined: 333 * 334 * --- 335 * struct X; 336 * struct X; 337 * struct X { 338 * int member; 339 * } 340 * --- 341 * 342 * The declarations and the definition of X are represented by three 343 * different cursors, all of which are declarations of the same underlying 344 * entity. One of these cursor is considered the "canonical" cursor, which 345 * is effectively the representative for the underlying entity. One can 346 * determine if two cursors are declarations of the same underlying entity 347 * by comparing their canonical cursors. 348 * 349 * Return: The canonical cursor for the entity referred to by the given cursor. 350 */ 351 @property Cursor canonical() @trusted const { 352 auto r = clang_getCanonicalCursor(cx); 353 return Cursor(r); 354 } 355 356 /// Determine the "language" of the entity referred to by a given cursor. 357 @property CXLanguageKind language() const @trusted { 358 return clang_getCursorLanguage(cx); 359 } 360 361 /// Returns: the translation unit that a cursor originated from. 362 @property TranslationUnit translationUnit() const @trusted { 363 return TranslationUnit(clang_Cursor_getTranslationUnit(cx)); 364 } 365 366 /** Obtain Token instances formulating that compose this Cursor. 367 * 368 * This is a generator for Token instances. It returns all tokens which 369 * occupy the extent this cursor occupies. 370 * 371 * Trusted: the API usage follows the LLVM manual. The potential problem 372 * would be if clang_tokenize write back invalid addresses. 373 * 374 * Returns: A range over the tokens. 375 */ 376 @property auto tokens() const @trusted { 377 import std.algorithm.mutation : stripRight; 378 379 CXToken* tokens = null; 380 uint numTokens = 0; 381 clang_tokenize(translationUnit.cx, extent.cx, &tokens, &numTokens); 382 auto result = TokenRange(translationUnit, tokens, numTokens); 383 384 // For some reason libclang returns some tokens out of cursors extent.cursor 385 return result.stripRight!(token => !intersects(extent, token.extent)); 386 } 387 388 @property ObjcCursor objc() const { 389 return ObjcCursor(this); 390 } 391 392 @property FunctionCursor func() const { 393 return FunctionCursor(this); 394 } 395 396 @property EnumCursor enum_() const { 397 return EnumCursor(this); 398 } 399 400 @property AccessCursor access() const { 401 return AccessCursor(this); 402 } 403 404 @property IncludeCursor include() const { 405 return IncludeCursor(this); 406 } 407 408 @property Visitor all() const { 409 return Visitor(this); 410 } 411 412 @property InOrderVisitor allInOrder() const { 413 return InOrderVisitor(this); 414 } 415 416 private Cursor[] childrenImpl(T)(bool ignorePredefined) const { 417 import std.array : appender; 418 419 Cursor[] result; 420 auto app = appender(result); 421 422 if (ignorePredefined && isTranslationUnit) { 423 foreach (cursor, _; T(this)) { 424 if (!cursor.isPredefined) 425 app.put(cursor); 426 } 427 } else { 428 foreach (cursor, _; T(this)) 429 app.put(cursor); 430 } 431 432 return app.data; 433 } 434 435 /** Array of all children of the cursor. 436 * 437 * Params: 438 * ignorePredefined = ignore cursors for primitive types. 439 */ 440 Cursor[] children(bool ignorePredefined = false) const { 441 return childrenImpl!Visitor(ignorePredefined); 442 } 443 444 Cursor[] childrenInOrder(bool ignorePredefined = false) const { 445 return childrenImpl!InOrderVisitor(ignorePredefined); 446 } 447 448 /// Determine whether two cursors are equivalent. 449 equals_t opEquals(const ref Cursor cursor) const @trusted { 450 return clang_equalCursors(cast(CXCursor) cursor.cx, cast(CXCursor) cx) != 0; 451 } 452 453 /// Compute a hash value for the given cursor. 454 size_t toHash() const nothrow @trusted { 455 //TODO i'm not sure this is a good solution... investigate. 456 try { 457 return clang_hashCursor(cast(CXCursor) cx); 458 } catch (Exception ex) { 459 return 0; 460 } 461 } 462 463 /// Determine whether the given cursor has any attributes. 464 @property bool hasAttributes() const @trusted { 465 return clang_Cursor_hasAttrs(cx) != 0; 466 } 467 468 /// Determine whether the given cursor kind represents a declaration. 469 @property bool isDeclaration() const @trusted { 470 return clang_isDeclaration(cx.kind) != 0; 471 } 472 473 /** Determine whether the given cursor kind represents a simple 474 * reference. 475 * 476 * Note that other kinds of cursors (such as expressions) can also refer to 477 * other cursors. Use clang_getCursorReferenced() to determine whether a 478 * particular cursor refers to another entity. 479 */ 480 @property bool isReference() const @trusted { 481 return clang_isReference(cx.kind) != 0; 482 } 483 484 /// Determine whether the given cursor kind represents an expression. 485 @property bool isExpression() const @trusted { 486 return clang_isExpression(cx.kind) != 0; 487 } 488 489 /// Determine whether the given cursor kind represents a statement. 490 @property bool isStatement() const @trusted { 491 return clang_isStatement(cx.kind) != 0; 492 } 493 494 /** Determine whether the given cursor represents an anonymous record 495 * declaration. 496 * 497 * The cursor must be a declaration and either a struct or union. 498 * 499 * Determines whether this field is a representative for an anonymous 500 * struct or union. Such fields are unnamed and are implicitly generated by 501 * the implementation to store the data for the anonymous union or struct. 502 * 503 * If the following is declared inside a struct. 504 * 505 * Example: 506 * --- 507 * union { 508 * int x; 509 * char y; 510 * }; 511 * --- 512 */ 513 @property bool isAnonymous() const @trusted { 514 return clang_Cursor_isAnonymous(cx) != 0; 515 } 516 517 /// Determine whether the given cursor kind represents an attribute. 518 @property bool isAttribute() const @trusted { 519 return clang_isAttribute(cx.kind) != 0; 520 } 521 522 int bitFieldWidth() const @trusted { 523 return clang_getFieldDeclBitWidth(cast(CXCursor) cx); 524 } 525 526 bool isBitField() const @trusted { 527 return clang_Cursor_isBitField(cast(CXCursor) cx) != 0; 528 } 529 530 /// Determine whether the given cursor kind represents an invalid cursor. 531 @property bool isValid() const @trusted { 532 // note that it checks for invalidity of the cursor, thus the inverse 533 // is the return value. 534 return !clang_isInvalid(cx.kind); 535 } 536 537 /// Determine whether the given cursor kind represents a translation unit. 538 @property bool isTranslationUnit() const @trusted { 539 return clang_isTranslationUnit(cx.kind) != 0; 540 } 541 542 /** Determine whether the given cursor represents a preprocessing 543 * element, such as a preprocessor directive or macro instantiation. 544 */ 545 @property bool isPreprocessing() const @trusted { 546 return clang_isPreprocessing(cx.kind) != 0; 547 548 // If clang_isPreprocessing isn't working out this is the 549 // implementation from DStep. 550 551 //CXCursorKind kind = clang_getCursorKind(cx); 552 //return CXCursorKind.firstPreprocessing <= kind && 553 // kind <= CXCursorKind.lastPreprocessing; 554 } 555 556 /** Determine whether the given cursor represents a currently unexposed 557 * piece of the AST (e.g., CXCursor_UnexposedStmt). 558 */ 559 @property bool isUnexposed() const @trusted { 560 return clang_isUnexposed(cx.kind) != 0; 561 } 562 563 /// Return: if the underlying type is an enum. 564 @property bool isUnderlyingTypeEnum() const @trusted { 565 auto underlying = typedefUnderlyingType; 566 if (!underlying.isValid) { 567 return false; 568 } 569 570 auto decl = underlying.declaration; 571 if (!decl.isValid) { 572 return false; 573 } 574 575 return decl.type.isEnum; 576 } 577 578 /// Return: if cursor is null/empty. 579 @property bool isEmpty() const @trusted { 580 return clang_Cursor_isNull(cx) != 0; 581 } 582 583 /** Returns true if the declaration pointed at by the cursor is also a 584 * definition of that entity. 585 */ 586 bool isDefinition() const @trusted { 587 return clang_isCursorDefinition(cast(CXCursor) cx) != 0; 588 } 589 590 /// Returns: if the base class specified by the cursor with kind CX_CXXBaseSpecifier is virtual. 591 @property bool isVirtualBase() const @trusted { 592 return clang_isVirtualBase(cx) != 0; 593 } 594 595 bool isPredefined() const @trusted { 596 auto xkind = usr in predefined; 597 return xkind !is null && *xkind == kind; 598 } 599 600 /** Determine whether a CXCursor that is a macro, is function like. 601 */ 602 bool isMacroFunctionLike() const @trusted { 603 return clang_Cursor_isMacroFunctionLike(cx) != 0; 604 } 605 606 /** Determine whether a CXCursor that is a macro, is a builtin one. 607 */ 608 bool isMacroBuiltin() const @trusted { 609 return clang_Cursor_isMacroBuiltin(cx) != 0; 610 } 611 612 /** Determine whether a CXCursor that is a function declaration, is an 613 * inline declaration. 614 */ 615 bool isFunctionInlined() const @trusted { 616 return clang_Cursor_isFunctionInlined(cx) != 0; 617 } 618 619 /// Determine if a C++ constructor is a converting constructor. 620 bool isConvertingConstructor() const @trusted { 621 return clang_CXXConstructor_isConvertingConstructor(cx) != 0; 622 } 623 624 /// Determine if a C++ constructor is a copy constructor. 625 bool isCopyConstructor() const @trusted { 626 return clang_CXXConstructor_isCopyConstructor(cx) != 0; 627 } 628 629 /// Determine if a C++ constructor is the default constructor. 630 bool isDefaultConstructor() const @trusted { 631 return clang_CXXConstructor_isDefaultConstructor(cx) != 0; 632 } 633 634 /// Determine if a C++ constructor is a move constructor. 635 bool isMoveConstructor() const @trusted { 636 return clang_CXXConstructor_isMoveConstructor(cx) != 0; 637 } 638 639 /// Determine if a C++ field is declared 'mutable'. 640 bool isMutable() const @trusted { 641 return clang_CXXField_isMutable(cx) != 0; 642 } 643 644 /// Determine if a C++ method is declared '= default'. 645 bool isDefaulted() const @trusted { 646 return clang_CXXMethod_isDefaulted(cx) != 0; 647 } 648 649 /// Determine if a C++ member function or member function template is pure virtual. 650 bool isPureVirtual() @trusted { 651 return clang_CXXMethod_isPureVirtual(cx) != 0; 652 } 653 654 /** Describe the visibility of the entity referred to by a cursor. 655 * 656 * Note: This is linker visibility. 657 * 658 * This returns the default visibility if not explicitly specified by 659 * a visibility attribute. The default visibility may be changed by 660 * commandline arguments. 661 * 662 * Params: 663 * cursor The cursor to query. 664 * 665 * Returns: The visibility of the cursor. 666 */ 667 CXVisibilityKind visibility() const @trusted { 668 return clang_getCursorVisibility(cx); 669 } 670 671 private static CXCursorKind[string] queryPredefined() @trusted { 672 import clang.Index; 673 import clang.TranslationUnit; 674 675 CXCursorKind[string] result; 676 677 Index index = Index(false, false); 678 TranslationUnit unit = TranslationUnit.parseString(index, "", []); 679 680 foreach (cursor; unit.cursor.children) 681 result[cursor.usr] = cursor.kind; 682 683 return result; 684 } 685 686 public static string predefinedToString() @trusted { 687 import std.algorithm : map, joiner; 688 import std.ascii : newline; 689 import std.conv : text; 690 import std.string : leftJustifier; 691 692 return predefined.byKeyValue().map!(a => leftJustifier(a.key, 50) 693 .text ~ a.value.text).joiner(newline).text; 694 } 695 } 696 697 struct ObjcCursor { 698 Cursor cursor; 699 alias cursor this; 700 701 @property ObjCInstanceMethodVisitor instanceMethods() { 702 return ObjCInstanceMethodVisitor(cursor); 703 } 704 705 @property ObjCClassMethodVisitor classMethods() { 706 return ObjCClassMethodVisitor(cursor); 707 } 708 709 @property ObjCPropertyVisitor properties() { 710 return ObjCPropertyVisitor(cursor); 711 } 712 713 @property Cursor superClass() { 714 foreach (cursor, parent; TypedVisitor!(CXCursorKind.objCSuperClassRef)(cursor)) 715 return cursor; 716 717 return Cursor.empty(); 718 } 719 720 @property ObjCProtocolVisitor protocols() { 721 return ObjCProtocolVisitor(cursor); 722 } 723 724 @property Cursor category() { 725 assert(cursor.kind == CXCursorKind.objCCategoryDecl); 726 727 foreach (c, _; TypedVisitor!(CXCursorKind.objCClassRef)(cursor)) 728 return c; 729 730 assert(0, "This cursor does not have a class reference."); 731 } 732 } 733 734 struct FunctionCursor { 735 Cursor cursor; 736 alias cursor this; 737 738 /// Return: Retrieve the Type of the result for this Cursor. 739 @property Type resultType() @trusted { 740 auto r = clang_getCursorResultType(cx); 741 return Type(cursor, r); 742 } 743 744 @property ParamVisitor parameters() { 745 return ParamVisitor(cursor); 746 } 747 748 /** Determine if a C++ member function or member function template is 749 * pure virtual. 750 */ 751 @property bool isPureVirtual() @trusted { 752 return clang_CXXMethod_isPureVirtual(cx) != 0; 753 } 754 755 /** Returns: True if the cursor refers to a C++ member function or member 756 * function template that is declared 'static'. 757 */ 758 @property bool isStatic() @trusted { 759 return clang_CXXMethod_isStatic(cx) != 0; 760 } 761 762 /** Determine if a C++ member function or member function template is 763 * explicitly declared 'virtual' or if it overrides a virtual method from 764 * one of the base classes. 765 */ 766 @property bool isVirtual() @trusted { 767 return clang_CXXMethod_isVirtual(cx) != 0; 768 } 769 770 /** Determine if a C++ member function or member function template is 771 * declared 'const'. 772 */ 773 @property bool isConst() @trusted { 774 return clang_CXXMethod_isConst(cx) != 0; 775 } 776 777 /** Given a cursor pointing to a C++ method call or an Objective-C 778 * message, returns non-zero if the method/message is "dynamic", meaning: 779 * 780 * For a C++ method: the call is virtual. 781 * For an Objective-C message: the receiver is an object instance, not 'super' 782 * or a specific class. 783 * 784 * If the method/message is "static" or the cursor does not point to a 785 * method/message, it will return zero. 786 */ 787 @property bool isDynamicCall() @trusted { 788 return clang_Cursor_isDynamicCall(cx) != 0; 789 } 790 } 791 792 struct AccessCursor { 793 Cursor cursor; 794 alias cursor this; 795 796 /** Returns the access control level for the C++ base specifier represented 797 * by a cursor with kind CXCursor_CXXBaseSpecifier or 798 * CXCursor_AccessSpecifier. 799 */ 800 @property auto accessSpecifier() @trusted { 801 return clang_getCXXAccessSpecifier(cx); 802 } 803 } 804 805 struct ParamCursor { 806 Cursor cursor; 807 alias cursor this; 808 } 809 810 struct IncludeCursor { 811 Cursor cursor; 812 alias cursor this; 813 814 /** Retrieve the file that is included by the given inclusion directive 815 * cursor. 816 */ 817 @property auto file() @trusted { 818 return File(clang_getIncludedFile(cx)); 819 } 820 } 821 822 struct EnumCursor { 823 import std.conv : to; 824 825 Cursor cursor; 826 alias cursor this; 827 828 @property string value() @safe { 829 import std.conv : to; 830 831 return to!string(signedValue); 832 } 833 834 /** Retrieve the integer type of an enum declaration. 835 * 836 * If the cursor does not reference an enum declaration, an invalid type is 837 * returned. 838 */ 839 @property Type type() @trusted { 840 auto r = clang_getEnumDeclIntegerType(cx); 841 return Type(cursor, r); 842 } 843 844 /** Retrieve the integer value of an enum constant declaration as a signed 845 * long. 846 * 847 * If the cursor does not reference an enum constant declaration, LLONG_MIN 848 * is returned. Since this is also potentially a valid constant value, the 849 * kind of the cursor must be verified before calling this function. 850 */ 851 @property long signedValue() @trusted { 852 return clang_getEnumConstantDeclValue(cx); 853 } 854 855 /** Retrieve the integer value of an enum constant declaration as an 856 * unsigned long. 857 * 858 * If the cursor does not reference an enum constant declaration, 859 * ULLONG_MAX is returned. Since this is also potentially a valid constant 860 * value, the kind of the cursor must be verified before calling this 861 * function. 862 */ 863 @property ulong unsignedValue() @trusted { 864 return clang_getEnumConstantDeclUnsignedValue(cx); 865 } 866 867 /// Return: if the type of the enum is signed. 868 @property bool isSigned() const @trusted { 869 Type t; 870 871 if (isUnderlyingTypeEnum) { 872 t = typedefUnderlyingType.declaration.enum_.type; 873 } else { 874 t = Type(cursor, clang_getCursorType(cx)); 875 } 876 877 return t.isSigned; 878 } 879 } 880 881 import std.array : appender, Appender; 882 883 string dump(ref const(Cursor) c) @trusted { 884 import std.conv : to; 885 import std.string; 886 887 static string stripPrefix(string x) { 888 immutable string prefix = "CXCursor_"; 889 immutable size_t prefixSize = prefix.length; 890 return x.startsWith(prefix) ? x[prefixSize .. $] : x; 891 } 892 893 static string prettyTokens(ref const(Cursor) c, size_t limit = 5) { 894 import std.algorithm.comparison : min; 895 896 TokenRange tokens = c.tokens; 897 898 string prettyToken(Token token) { 899 immutable string prefix = "CXToken_"; 900 immutable size_t prefixSize = prefix.length; 901 auto x = to!string(token.kind); 902 return "%s \"%s\"".format(x.startsWith(prefix) ? x[prefixSize .. $] : x, token.spelling); 903 } 904 905 auto result = appender!string("["); 906 907 if (tokens.length != 0) { 908 result.put(prettyToken(tokens[0])); 909 910 foreach (Token token; c.tokens[1 .. min($, limit)]) { 911 result.put(", "); 912 result.put(prettyToken(token)); 913 } 914 } 915 916 if (tokens.length > limit) 917 result.put(", ..]"); 918 else 919 result.put("]"); 920 921 return result.data; 922 } 923 924 auto text = "%s \"%s\" [%d:%d..%d:%d] %s %s".format(stripPrefix(to!string(c.kind)), 925 c.spelling, c.extent.start.line, c.extent.start.column, 926 c.extent.end.line, c.extent.end.column, prettyTokens(c), c.usr); 927 928 return text; 929 } 930 931 void dumpAST(ref const(Cursor) c, ref Appender!string result, size_t indent, File* file) @trusted { 932 import std.ascii : newline; 933 import std.format; 934 import std.array : replicate; 935 936 immutable size_t step = 4; 937 938 auto text = dump(c); 939 940 result.put(" ".replicate(indent)); 941 result.put(text); 942 result.put(newline); 943 944 if (file) { 945 foreach (cursor, _; c.all) { 946 if (!cursor.isPredefined() && cursor.location.file == *file) 947 dumpAST(cursor, result, indent + step); 948 } 949 } else { 950 foreach (cursor, _; c.all) { 951 if (!cursor.isPredefined()) 952 cursor.dumpAST(result, indent + step); 953 } 954 } 955 } 956 957 void dumpAST(ref const(Cursor) c, ref Appender!string result, size_t indent) @safe { 958 dumpAST(c, result, indent, null); 959 } 960 961 unittest { 962 // "Should output the predefined types for inspection" 963 import std.stdio; 964 965 writeln(Cursor.predefinedToString); 966 }