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 }