1 /// Extension of std.traist used in the tagion project
2 module tagion.basic.traits;
3 import std.meta : ApplyRight, Filter, staticMap;
4 import std.range.primitives : isInputRange;
5 import std.traits : getUDAs, hasUDA;
6 
7 /**
8     Similar to .stringof but working on member functions
9     Params: 
10        member = symbol of module,struct or class
11     Returns: the name of the symbol 
12 */
13 template getName(alias member) {
14     import std.algorithm.iteration : splitter;
15     import std.range : tail;
16     import std.traits : fullyQualifiedName;
17 
18     enum getName = fullyQualifiedName!(member).splitter('.').tail(1).front;
19 }
20 
21 /**
22     Params: 
23         member = symbol of a member
24     Returns: 
25         all overloads of the member
26 */
27 template getOverloads(alias member) {
28     alias Parent = __traits(parent, member);
29     alias getOverloads = __traits(getOverloads, Parent, getName!member);
30 }
31 
32 /** 
33  * Params:
34  *     member = symbol of a member
35  *     UDA = User defined attribute of the member
36  * Returns:
37  *     all the member symbols which has this UDA
38  *     If no UDA was found a empty alias sequency will be returned 
39  */
40 template hasMemberUDA(alias member, alias UDA) {
41     alias Overloads = getOverloads!(member);
42     alias hasTheUDA = ApplyRight!(hasUDA, UDA);
43     alias hasMemberUDA = Filter!(hasTheUDA, Overloads);
44 }
45 
46 enum hasOneMemberUDA(alias member, alias UDA) = hasMemberUDA!(member, UDA).length is 1;
47 
48 /**
49  * Params:
50  *     member = symbol of a member
51  *     UDA = User defined attribute of the member
52  * Returns:
53  *     
54 */
55 template getMemberUDAs(alias member, alias UDA) {
56     alias Overloads = getOverloads!(member);
57     alias getTheUDAs = ApplyRight!(getUDAs, UDA);
58     alias getMemberUDAs = staticMap!(getTheUDAs, hasMemberUDA!(member, UDA));
59 }
60 
61 ///
62 static unittest {
63     import std.typecons : Tuple;
64 
65     enum test;
66     struct special {
67         string label;
68     }
69 
70     struct S {
71         @test
72         int func() {
73             return 0;
74         }
75 
76         @special("text")
77         int func(int x) {
78             return x;
79         }
80 
81         string func(string str) {
82             return str;
83         }
84     }
85 
86     static assert(getName!(S.func) == "func");
87     static assert(__traits(isSame, __traits(getOverloads, S, "func"), getOverloads!(S.func)));
88     /// UDA @test
89     static assert(hasMemberUDA!(S.func, test).length is 1);
90     static assert(__traits(isSame, hasMemberUDA!(S.func, test)[0], getOverloads!(S.func)[0]));
91     static assert(is(getMemberUDAs!(S.func, test)[0] == test));
92     /// UDA special
93     static assert(hasMemberUDA!(S.func, special).length is 1);
94     static assert(__traits(isSame, hasMemberUDA!(S.func, special)[0], getOverloads!(S.func)[1]));
95     enum s_special = getMemberUDAs!(S.func, special)[0];
96     static assert(s_special == special("text"));
97 }