1 module clang; 2 3 import clang.c.index; 4 import clang.c.util: EnumD; 5 6 mixin EnumD!("TranslationUnitFlags", CXTranslationUnit_Flags, "CXTranslationUnit_"); 7 8 9 TranslationUnit parse(in string fileName, in TranslationUnitFlags translUnitflags) 10 @safe 11 { 12 return parse(fileName, [], translUnitflags); 13 } 14 15 16 TranslationUnit parse(in string fileName, in string[] commandLineArgs, in TranslationUnitFlags translUnitflags) 17 @trusted 18 { 19 20 import std.string: toStringz; 21 import std.algorithm: map; 22 import std.array: array; 23 24 auto index = clang_createIndex(0, 0); 25 CXUnsavedFile[] unsavedFiles; 26 const commandLineArgz = commandLineArgs.map!(a => a.toStringz).array; 27 28 auto cx = clang_parseTranslationUnit( 29 index, 30 fileName.toStringz, 31 commandLineArgz.ptr, 32 cast(int)commandLineArgz.length, 33 unsavedFiles.ptr, 34 cast(uint)unsavedFiles.length, 35 CXTranslationUnit_None, 36 ); 37 38 return TranslationUnit(cx); 39 } 40 41 mixin EnumD!("ChildVisitResult", CXChildVisitResult, "CXChildVisit_"); 42 43 alias CursorVisitor = ChildVisitResult delegate(Cursor cursor, Cursor parent); 44 45 struct TranslationUnit { 46 47 CXTranslationUnit _cx; 48 49 Cursor cursor() @trusted { 50 return Cursor(clang_getTranslationUnitCursor(_cx)); 51 } 52 53 void visitChildren(CursorVisitor visitor) @safe { 54 cursor.visitChildren(visitor); 55 } 56 57 int opApply(scope int delegate(Cursor cursor, Cursor parent) block) @safe { 58 return cursor.opApply(block); 59 } 60 61 int opApply(scope int delegate(Cursor cursor) block) @safe { 62 return cursor.opApply(block); 63 } 64 } 65 66 string toString(CXString cxString) @trusted { 67 import std.conv: to; 68 auto cstr = clang_getCString(cxString); 69 auto str = cstr.to!string; 70 clang_disposeString(cxString); 71 return str; 72 } 73 74 struct Cursor { 75 76 mixin EnumD!("Kind", CXCursorKind, "CXCursor_"); 77 78 private CXCursor _cx; 79 Kind kind; 80 string spelling; 81 82 this(CXCursor cx) @trusted { 83 _cx = cx; 84 kind = cast(Kind)clang_getCursorKind(_cx); 85 spelling = clang_getCursorSpelling(_cx).toString; 86 } 87 88 void visitChildren(CursorVisitor visitor) @trusted { 89 clang_visitChildren(_cx, &cvisitor, new ClientData(visitor)); 90 } 91 92 SourceRange sourceRange() @safe nothrow const { 93 return typeof(return).init; 94 } 95 96 bool isPredefined() @safe @nogc pure nothrow const { 97 return false; 98 } 99 100 int opApply(scope int delegate(Cursor cursor, Cursor parent) block) @safe { 101 return opApplyN(block); 102 } 103 104 int opApply(scope int delegate(Cursor cursor) block) @safe { 105 return opApplyN(block); 106 } 107 108 private int opApplyN(T...)(int delegate(T args) block) { 109 int stop = 0; 110 111 visitChildren((cursor, parent) { 112 113 static if(T.length == 2) 114 stop = block(cursor, parent); 115 else static if(T.length == 1) 116 stop = block(cursor); 117 else 118 static assert(false); 119 120 return stop 121 ? ChildVisitResult.Break 122 : ChildVisitResult.Recurse; 123 }); 124 125 return stop; 126 } 127 } 128 129 struct SourceRange { 130 string path; 131 SourceLocation start; 132 SourceLocation end; 133 } 134 135 struct SourceLocation { 136 uint offset; 137 } 138 139 private struct ClientData { 140 CursorVisitor dvisitor; 141 } 142 143 private extern(C) CXChildVisitResult cvisitor(CXCursor cursor, CXCursor parent, void* clientData_) { 144 auto clientData = cast(ClientData*)clientData_; 145 return cast(CXChildVisitResult)clientData.dvisitor(Cursor(cursor), Cursor(parent)); 146 }