1 module rpui.traits;
2
3 import std.traits : hasUDA, getUDAs, isFunction, isType, isAggregateType;
4
5 template getSymbolsNamesByUDA(alias symbol, alias attribute) {
6 import std.format : format;
7 import std.meta : AliasSeq, Filter;
8
9 // filtering inaccessible members
10 enum noInaccessibleMembers(string name) = (__traits(compiles, __traits(getMember, symbol, name)));
11 alias withoutInaccessibleMembers = Filter!(noInaccessibleMembers, __traits(allMembers, symbol));
12
13 // filtering out nested class context
14 enum noThisMember(string name) = (name != "this");
15 alias membersWithoutNestedCC = Filter!(noThisMember, withoutInaccessibleMembers);
16
17 // filtering not compiled members such as alias of basic types
18 enum hasSpecificUDA(string name) = mixin("hasUDA!(symbol." ~ name ~ ", attribute)");
19 enum noIncorrectMembers(string name) = (__traits(compiles, hasSpecificUDA!(name)));
20
21 alias withoutIncorrectMembers = Filter!(noIncorrectMembers, membersWithoutNestedCC);
22 alias membersWithUDA = Filter!(hasSpecificUDA, withoutIncorrectMembers);
23
24 // if the symbol itself has the UDA, tack it on to the front of the list
25 static if (hasUDA!(symbol, attribute))
26 alias getSymbolsNamesByUDA = AliasSeq!(symbol, membersWithUDA);
27 else
28 alias getSymbolsNamesByUDA = membersWithUDA;
29 }
30
31 template getSymbolsByUDA(alias symbol, alias attribute) {
32 import std.format : format;
33 import std.meta : AliasSeq, Filter;
34
35 // translate a list of strings into symbols. mixing in the entire alias
36 // avoids trying to access the symbol, which could cause a privacy violation
37 template toSymbols(names...) {
38 static if (names.length == 0)
39 alias toSymbols = AliasSeq!();
40 else
41 mixin("alias toSymbols = AliasSeq!(symbol.%s, toSymbols!(names[1..$]));"
42 .format(names[0]));
43 }
44
45 // filtering inaccessible members
46 enum isAccessibleMember(string name) = __traits(compiles, __traits(getMember, symbol, name));
47 alias accessibleMembers = Filter!(isAccessibleMember, __traits(allMembers, symbol));
48
49 // filtering not compiled members such as alias of basic types
50 enum hasSpecificUDA(string name) = mixin("hasUDA!(symbol." ~ name ~ ", attribute)");
51 enum isCorrectMember(string name) = __traits(compiles, hasSpecificUDA!(name));
52
53 alias correctMembers = Filter!(isCorrectMember, accessibleMembers);
54 alias membersWithUDA = toSymbols!(Filter!(hasSpecificUDA, correctMembers));
55
56 // if the symbol itself has the UDA, tack it on to the front of the list
57 static if (hasUDA!(symbol, attribute))
58 alias getSymbolsByUDA = AliasSeq!(symbol, membersWithUDA);
59 else
60 alias getSymbolsByUDA = membersWithUDA;
61 }