1 module graphql.uda;
2 
3 import std.traits : isBuiltinType;
4 
5 @safe:
6 
7 enum TypeKind {
8 	UNDEFINED,
9 	SCALAR,
10 	OBJECT,
11 	INTERFACE,
12 	UNION,
13 	ENUM,
14 	INPUT_OBJECT,
15 	LIST,
16 	NON_NULL
17 }
18 
19 struct GQLDUdaData {
20 	TypeKind typeKind;
21 	GQLDDeprecatedData deprecationInfo;
22 	GQLDDescription description;
23 }
24 
25 enum IsDeprecated {
26 	undefined,
27 	yes,
28 	no
29 }
30 
31 struct GQLDDeprecatedData {
32 	IsDeprecated isDeprecated;
33 	string deprecationReason;
34 }
35 
36 struct GQLDDescription {
37 	string text;
38 }
39 
40 GQLDDeprecatedData GQLDDeprecated(IsDeprecated isDeprecated) {
41 	return GQLDDeprecatedData(isDeprecated, "");
42 }
43 
44 GQLDDeprecatedData GQLDDeprecated(IsDeprecated isDeprecated,
45 		string deprecationReason)
46 {
47 	return GQLDDeprecatedData(isDeprecated, deprecationReason);
48 }
49 
50 GQLDUdaData GQLDUda(Args...)(Args args) {
51 	GQLDUdaData ret;
52 	static foreach(mem; __traits(allMembers, GQLDUdaData)) {
53 		static foreach(arg; args) {
54 			static if(is(typeof(__traits(getMember, ret, mem)) ==
55 						typeof(arg)))
56 			{
57 				__traits(getMember, ret, mem) = arg;
58 			}
59 		}
60 	}
61 	return ret;
62 }
63 
64 template isGQLDUdaData(alias Type) {
65 	enum isGQLDUdaData = is(typeof(Type) == GQLDUdaData);
66 }
67 
68 template getGQLDUdaData(Type, string mem) {
69 	import std.meta : Filter;
70 	alias getGQLDUdaData =
71 		Filter!(isGQLDUdaData,
72 				__traits(getAttributes, __traits(getMember, Type, mem)));
73 }
74 
75 template getGQLDUdaData(Type) {
76 	import std.meta : Filter;
77 	alias getGQLDUdaData =
78 		Filter!(isGQLDUdaData, __traits(getAttributes, Type));
79 }
80 
81 template getUdaData(Type) {
82 	static if(isBuiltinType!Type) {
83 		enum getUdaData = GQLDUdaData.init;
84 	} else {
85 		alias GQLDUdaDataAS = getGQLDUdaData!Type;
86 		static if(GQLDUdaDataAS.length > 0) {
87 			enum getUdaData = GQLDUdaDataAS[0];
88 		} else {
89 			enum getUdaData = GQLDUdaData.init;
90 		}
91 	}
92 }
93 
94 template getUdaData(Type, string mem) {
95 	//static if(isBuiltinType!(typeof(__traits(getMember, Type, mem)))) {
96 	//	enum  getUdaData = GQLDUdaData.init;
97 	//} else {
98 		alias GQLDUdaDataAS = getGQLDUdaData!(Type, mem);
99 		static if(GQLDUdaDataAS.length > 0) {
100 			enum  getUdaData = GQLDUdaDataAS[0];
101 		} else {
102 			enum  getUdaData = GQLDUdaData.init;
103 		}
104 	//}
105 }
106 
107 unittest {
108 	@GQLDUda(
109 		GQLDDeprecated(IsDeprecated.yes, "Stupid name"),
110 		GQLDDescription("You normal test struct")
111 	)
112 	struct Foo {
113 		@GQLDUda(
114 			GQLDDeprecated(IsDeprecated.no, "Very good name"),
115 			GQLDDescription("Contains something")
116 		)
117 		int bar;
118 
119 		int args;
120 	}
121 
122 	enum GQLDUdaData fd = getUdaData!Foo;
123 	static assert(fd.deprecationInfo.isDeprecated == IsDeprecated.yes);
124 	static assert(fd.deprecationInfo.deprecationReason == "Stupid name");
125 	static assert(fd.description.text == "You normal test struct");
126 
127 	enum GQLDUdaData bd = getUdaData!(Foo, "bar");
128 	static assert(bd.deprecationInfo.isDeprecated == IsDeprecated.no);
129 	static assert(bd.deprecationInfo.deprecationReason == "Very good name");
130 	static assert(bd.description.text == "Contains something");
131 
132 	enum GQLDUdaData ad = getUdaData!(Foo, "args");
133 	static assert(ad.deprecationInfo.isDeprecated == IsDeprecated.undefined);
134 	static assert(ad.deprecationInfo.deprecationReason == "");
135 	static assert(ad.description.text == "");
136 }