-
Notifications
You must be signed in to change notification settings - Fork 0
/
introspect.d
70 lines (65 loc) · 2.08 KB
/
introspect.d
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
module /*std.*/introspect;
//import std.typecons;
/**
Introspection information for a module named `moduleName`. Offers an entry
point for all accessible declarations within the module.
*/
struct Module(string moduleName)
{
alias name = moduleName;
/**
Returns an array of all accessible top-level declarations in the module.
*/
static immutable(string[]) allMembers()
{
mixin("static import " ~ name ~ ";");
return mixin("[ __traits(allMembers, "~name~") ]");
}
/**
Returns an array of all accessible top-level data declarations in the
module for which static or thread-local storage gets allocated. These
consist of global variables and global constants, but not `enum`s.
*/
static immutable(Data[]) data()
{
static auto make()
{
Data[] result;
enum all = allMembers;
mixin("static import " ~ name ~ ";");
static foreach (x; all)
{{
// Can the address be taken? Then it's data or function
static if (is(typeof(mixin("&"~name~"."~x)) T))
{
// Eliminate functions
static if (!mixin("is(typeof("~name~"."~x~") == function)"))
{
enum attributes = mixin("__traits(getAttributes,"
~name~"."~x~")");
result ~= Data(x, T.stringof[0 .. $ - 1]);
static foreach (y; attributes)
result[$ - 1].attributes ~= y.stringof;
}
}
}}
return result;
}
static immutable Data[] result = make();
return result;
}
}
struct Data
{
string name;
string type;
string[] attributes;
}
unittest
{
enum data = Module!"test1".data;
static assert(data.length == 3);
static assert(data[0] == Data("a1", "int"));
static assert(data[1] == Data("a2", "immutable(string)", ["3"]));
static assert(data[2] == Data("a3", "const(float[])", [`"test"`, "42"]));
}