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 }