1 /**
2  * Copyright: Copyright (c) 2016 Wojciech Szęszoł. All rights reserved.
3  * Authors: Wojciech Szęszoł
4  * Version: Initial created: May 26, 2016
5  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0)
6  */
7 module dstep.translator.TypedefIndex;
8 
9 import clang.c.Index;
10 import clang.Cursor;
11 import clang.TranslationUnit;
12 
13 
14 class TypedefIndex
15 {
16     import std.typecons: Flag, No;
17 
18     private Cursor[Cursor] typedefs;
19 
20     this(TranslationUnit translUnit)
21     {
22         this(translUnit, (ref const(Cursor)) => false);
23     }
24 
25     this(TranslationUnit translUnit, bool function(ref const(Cursor)) isWantedCursor)
26     {
27         import std.functional: toDelegate;
28         this(translUnit, isWantedCursor.toDelegate);
29     }
30 
31     this(TranslationUnit translUnit, bool delegate(ref const(Cursor)) isWantedCursor)
32     {
33         bool[Cursor] visited;
34 
35         auto file = translUnit.file;
36 
37         foreach (cursor; translUnit.cursor.all)
38         {
39             if (cursor.file == file || (isWantedCursor !is null && isWantedCursor(cursor)))
40             {
41                 visited[cursor] = true;
42                 inspect(cursor, visited);
43             }
44         }
45     }
46 
47     private void inspect(Cursor cursor, bool[Cursor] visited)
48     {
49         if (cursor.kind == CXCursorKind.typedefDecl)
50         {
51             foreach (child; cursor.all)
52             {
53                 if (child.kind == CXCursorKind.typeRef
54                     || child.isDeclaration)
55                 {
56                     if (child.referenced !in typedefs)
57                     {
58                         typedefs[child.referenced] = cursor;
59                         typedefs[child.referenced.canonical] = cursor;
60                     }
61                 }
62             }
63         }
64         else if ((cursor in visited) is null)
65         {
66             foreach (child; cursor.all)
67             {
68                 visited[cursor] = true;
69                 inspect(cursor, visited);
70             }
71         }
72     }
73 
74     Cursor typedefParent(in Cursor cursor)
75     {
76         auto result = cursor in typedefs;
77 
78         if (result is null)
79             return cursor.empty;
80         else
81             return *result;
82     }
83 }