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