1 /** 2 libclang utility code 3 */ 4 module dpp.clang; 5 6 7 import dpp.from; 8 9 10 from!"clang".Cursor namespace(in from!"clang".Cursor cursor) @safe { 11 import clang: Cursor; 12 13 auto ret = Cursor(cursor.cx); 14 15 while(!ret.isInvalid && ret.kind != Cursor.Kind.Namespace) 16 ret = ret.semanticParent; 17 18 return ret; 19 } 20 21 22 /** 23 Returns the type name without namespaces. 24 */ 25 string typeNameNoNs(in from!"clang".Cursor cursor) @safe { 26 import clang: Cursor; 27 import std.array: join; 28 import std.algorithm: reverse; 29 30 string[] parts; 31 32 auto c = Cursor(cursor.cx); 33 34 bool isWanted(in Cursor c) { 35 return 36 !c.isInvalid 37 && c.kind != Cursor.Kind.Namespace 38 && c.kind != Cursor.Kind.TranslationUnit 39 ; 40 } 41 42 while(isWanted(c.semanticParent)) { 43 c = c.semanticParent; 44 parts ~= c.spelling.idup; 45 } 46 47 parts = parts.reverse ~ cursor.spelling; 48 49 return parts.join("::"); 50 } 51 52 53 /** 54 If the cursor is a virtual function that overrides 55 another virtual function. 56 */ 57 bool isOverride(in from!"clang".Cursor cursor) @safe { 58 import clang: Cursor; 59 import std.algorithm: any, map, filter, joiner; 60 61 bool hasOverrideAttr(in Cursor cursor) { 62 return cursor 63 .children 64 .any!(a => a.kind == Cursor.Kind.CXXOverrideAttr) 65 ; 66 } 67 68 if(hasOverrideAttr(cursor)) return true; 69 70 auto parents = baseClasses(cursor.semanticParent); 71 const virtualWithSameName = parents 72 .map!(a => a.children) 73 .joiner 74 .filter!(a => a.spelling == cursor.spelling) 75 .any!(a => a.isVirtual) 76 ; 77 78 return virtualWithSameName; 79 } 80 81 82 /** 83 If the cursor is a `final` member function. 84 */ 85 bool isFinal(in from!"clang".Cursor cursor) @safe nothrow { 86 import clang: Cursor; 87 import std.algorithm: any; 88 89 return cursor 90 .children 91 .any!(a => a.kind == Cursor.Kind.CXXFinalAttr) 92 ; 93 } 94 95 96 /** 97 All base classes this cursor derives from 98 */ 99 from!"clang".Cursor[] baseClasses(in from!"clang".Cursor cursor) @safe nothrow { 100 import clang: Cursor; 101 import std.algorithm: map, filter, joiner; 102 import std.array: array; 103 import std.range: chain; 104 105 auto baseSpecifiers = cursor 106 .children 107 .filter!(a => a.kind == Cursor.Kind.CXXBaseSpecifier); 108 if(baseSpecifiers.empty) return []; 109 110 auto baseCursors = baseSpecifiers.map!(a => a.children[0].referencedCursor); 111 return chain( 112 baseCursors, 113 baseCursors.map!baseClasses.joiner, 114 ).array; 115 }