diff --git a/pretranslated/14/index.d b/pretranslated/14/index.d index e3a78c3..527366f 100644 --- a/pretranslated/14/index.d +++ b/pretranslated/14/index.d @@ -69,7 +69,16 @@ alias CXIndex = void*; /** * \brief A single translation unit, which resides in an index. */ -struct CXTranslationUnitImpl; +struct CXTranslationUnitImpl { + void* CIdx; + void* TheASTUnit; + void* StringPool; + void* Diagnostics; + void* OverridenCursorsPool; + void* CommentToXML; + uint ParsingOptions; + void* Arguments; +}; alias CXTranslationUnit = CXTranslationUnitImpl*; /** diff --git a/pretranslated/15/index.d b/pretranslated/15/index.d index f02c95b..5e4a45e 100644 --- a/pretranslated/15/index.d +++ b/pretranslated/15/index.d @@ -122,7 +122,16 @@ alias CXTargetInfo = CXTargetInfoImpl*; /** * A single translation unit, which resides in an index. */ -struct CXTranslationUnitImpl; +struct CXTranslationUnitImpl { + void* CIdx; + void* TheASTUnit; + void* StringPool; + void* Diagnostics; + void* OverridenCursorsPool; + void* CommentToXML; + uint ParsingOptions; + void* Arguments; +}; alias CXTranslationUnit = CXTranslationUnitImpl*; /** diff --git a/source/clang/package.d b/source/clang/package.d index 7b983d4..8031d98 100644 --- a/source/clang/package.d +++ b/source/clang/package.d @@ -38,8 +38,7 @@ TranslationUnit parse(in string fileName, // faux booleans const excludeDeclarationsFromPCH = 0; const displayDiagnostics = 0; - auto index = clang_createIndex(excludeDeclarationsFromPCH, displayDiagnostics); - scope(exit) clang_disposeIndex(index); + CXIndex index = clang_createIndex(excludeDeclarationsFromPCH, displayDiagnostics); CXUnsavedFile[] unsavedFiles; const commandLineArgz = commandLineArgs .map!(a => a.toStringz) @@ -79,7 +78,7 @@ TranslationUnit parse(in string fileName, errorMessages.join("\n"))); - return TranslationUnit(cx); + return new TranslationUnit(index, cx); } string[] systemPaths() @safe { @@ -122,24 +121,34 @@ string[] systemPaths() @safe { mixin EnumD!("ChildVisitResult", CXChildVisitResult, "CXChildVisit_"); alias CursorVisitor = ChildVisitResult delegate(Cursor cursor, Cursor parent); -struct TranslationUnit { - +class TranslationUnit { + private CXIndex index; CXTranslationUnit cx; - Cursor cursor; - this(CXTranslationUnit cx) @safe nothrow { + this(CXIndex index, CXTranslationUnit cx) @safe nothrow { + this.index = index; this.cx = cx; - this.cursor = Cursor(clang_getTranslationUnitCursor(cx)); + + assert(cx.CommentToXML is null); + () @trusted { + cx.CommentToXML = cast(void*) this; + }(); } - // This pair of functions *should* work but crash dpp's tests intead - // A memory leak is a better than a crash, so... + ~this() @safe @nogc pure nothrow { + () @trusted { + assert(cx.CommentToXML == cast(void*) this); + }(); - // @disable this(this); + cx.CommentToXML = null; + clang_disposeTranslationUnit(cx); + clang_disposeIndex(index); + } - // ~this() @safe @nogc pure nothrow { - // clang_disposeTranslationUnit(cx); - // } + Cursor cursor() @safe nothrow + { + return Cursor(clang_getTranslationUnitCursor(cx)); + } string spelling() @safe pure nothrow const { return clang_getTranslationUnitSpelling(cx).toString; @@ -206,6 +215,7 @@ struct Cursor { alias Hash = ReturnType!clang_hashCursor; + private TranslationUnit trUnit; CXCursor cx; private Cursor[] _children; Kind kind; @@ -224,6 +234,8 @@ struct Cursor { if(kind == Cursor.Kind.TypedefDecl || kind == Cursor.Kind.TypeAliasDecl) underlyingType = Type(clang_getTypedefDeclUnderlyingType(cx)); + + trUnit = fetchTranslationUnit(); } this(in Kind kind, in string spelling) @safe @nogc pure nothrow { @@ -237,6 +249,15 @@ struct Cursor { this.type = type; } + this()(ref return Cursor s) @safe @nogc pure nothrow { + cx = s.cx; + kind = s.kind; + type = s.type; + underlyingType = s.underlyingType; + + trUnit = fetchTranslationUnit(); + } + /// Lazily return the cursor's children auto children(this This)() @property { import std.array: appender; @@ -428,8 +449,8 @@ struct Cursor { return Cursor(clang_getSpecializedCursorTemplate(cx)); } - TranslationUnit translationUnit() @safe nothrow const { - return TranslationUnit(clang_Cursor_getTranslationUnit(cx)); + TranslationUnit translationUnit() @safe nothrow { + return trUnit; } Language translationUnitLanguage() @safe pure nothrow const { @@ -618,6 +639,23 @@ struct Cursor { private SourceRange _sourceRangeCreate() @safe pure nothrow const { return SourceRange(clang_getCursorExtent(cx)); } + + private TranslationUnit fetchTranslationUnit() @safe @nogc pure nothrow const + { + assert(trUnit is null, "must be called once only from ctor"); + + CXTranslationUnitImpl* tui = clang_Cursor_getTranslationUnit(cx); + + // can be null if cursor created by cxcursor::MakeCXCursorInvalid + if(tui is null) + return null; + + return () @trusted { + TranslationUnit tu = cast(TranslationUnit) tui.CommentToXML; + assert(tu !is null); + return tu; + }(); + } }