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