1 2 module dquery.element; 3 4 import std.traits; 5 import std.typetuple; 6 7 import dquery.attribute; 8 import dquery.attributes; 9 import dquery.helper; 10 11 struct DQueryElement(QueryType, string Name, alias Overload = null) 12 { 13 14 /++ 15 + Returns the type being queried. 16 ++/ 17 @property 18 alias type = QueryType; 19 20 /++ 21 + Returns the name of the element. 22 ++/ 23 @property 24 enum name = Name; 25 26 // Check if the element is accessible. 27 static if(__traits(compiles, GetMember!(QueryType, Name))) 28 { 29 /++ 30 + Returns true if the element is accessible. 31 ++/ 32 @property 33 enum isAccessible = true; 34 35 /++ 36 + Returns the value of the element. 37 ++/ 38 @property 39 alias value = Alias!( 40 GetMember!(QueryType, Name) 41 ); 42 } 43 else 44 { 45 /++ 46 + Returns true if the element is accessible. 47 ++/ 48 @property 49 enum isAccessible = false; 50 51 /++ 52 + Returns void for inaccessible elements. 53 ++/ 54 @property 55 alias value = Alias!(void); 56 } 57 58 /++ 59 + Returns true if the name matches. 60 ++/ 61 @property 62 enum isName(string Name) = name == Name; 63 64 /++ 65 + Returns true if the element has an attribute of the given type. 66 ++/ 67 @property 68 enum hasAttribute(Type) = attributes.anyOf!Type.length > 0; 69 70 /++ 71 + Returns true if the element has all of the given attributes. 72 ++/ 73 @property 74 enum hasAllOf(TList...) = attributes.hasAllOf!TList; 75 76 /++ 77 + Returns true if the element has any of the given attributes. 78 ++/ 79 @property 80 enum hasAnyOf(TList...) = attributes.hasAnyOf!TList; 81 82 /++ 83 + Returns true if the element has none of the given attributes. 84 ++/ 85 @property 86 enum hasNoneOf(TList...) = attributes.hasNoneOf!TList; 87 88 /++ 89 + Returns the element's access protection. 90 ++/ 91 @property 92 enum protection = GetProtection!(QueryType, Name); 93 94 /++ 95 + Returns true if the element refers to a field. 96 ++/ 97 @property 98 alias isField = Alias!( 99 is(typeof(GetMember!(QueryType, Name))) && !isFunction 100 ); 101 102 /++ 103 + Returns true if a given type matches the element's type exactly. 104 ++/ 105 @property 106 enum isTypeOf(Type) = is(typeof(GetMember!(QueryType, Name)) == Type); 107 108 /++ 109 + Returns true if a given type can be assigned to a variable 110 + of the element's type. 111 ++/ 112 @property 113 enum isTypeAssignableTo(Type) = __traits(compiles, { 114 typeof(GetMember!(QueryType, Name)) t1 = void; 115 Type t2 = t1; 116 }); 117 118 /++ 119 + Returns true if a given type can be assigned from a variable 120 + of the element's type. 121 ++/ 122 @property 123 enum isTypeAssignableFrom(Type) = __traits(compiles, { 124 Type t1 = void; 125 typeof(GetMember!(QueryType, Name)) t2 = t1; 126 }); 127 128 /++ 129 + Returns true if the element refers to a function. 130 ++/ 131 @property 132 enum isFunction = 133 is(typeof(GetMember!(QueryType, Name)) == function) && 134 !is(typeof(Overload) == typeof(null)); 135 136 /++ 137 + Returns true if the element refers to a constructor. 138 ++/ 139 @property 140 enum isConstructor = isFunction && isName!"__ctor"; 141 142 /++ 143 + Returns true if the element refers to a destructor. 144 ++/ 145 @property 146 enum isDestructor = isFunction && isName!"__dtor"; 147 148 /++ 149 + Return true if the element's arity matches the given number of parameters. 150 ++/ 151 @property 152 enum isArity(int Count) = isFunction && __traits(compiles, { 153 static assert(Overload.arity == Count); 154 }); 155 156 /++ 157 + Returns true if a given type matches the element's return type exactly. 158 ++/ 159 @property 160 enum isReturnTypeOf(Type) = isFunction && is(Overload.returnType == Type); 161 162 /++ 163 + Returns true if a given type can be assigned to a variable of the 164 + element's return type. 165 ++/ 166 @property 167 enum isReturnAssignableTo(Type) = isFunction && __traits(compiles, { 168 Overload.returnType t1 = void; 169 Type t2 = t1; 170 }); 171 172 /++ 173 + Returns true if a given type can be assigned from a variable 174 + of the element's return type. 175 ++/ 176 @property 177 enum isReturnAssignableFrom(Type) = isFunction && __traits(compiles, { 178 Type t1 = void; 179 Overload.returnType t2 = t1; 180 }); 181 182 /++ 183 + Returns true if the element's parameter types match the given type list. 184 ++/ 185 @property 186 enum isParameterTypesOf(TList...) = isFunction && __traits(compiles, { 187 static assert(Compare!(Overload.parameters).With!(TList)); 188 }); 189 190 /++ 191 + Returns true if the element refers to an aggregate type. 192 ++/ 193 @property 194 enum isAggregate = __traits(compiles, { 195 static assert(isAggregateType!(GetMember!(QueryType, Name))); 196 }); 197 198 /++ 199 + Returns true if a given type matches the element's aggregate type exactly. 200 ++/ 201 @property 202 enum isAggregateTypeOf(Type) = isAggregate && is(GetMember!(QueryType, Name) == Type); 203 204 /++ 205 + Returns true if a given type can be assigned to a variable of the 206 + element's aggregate type. 207 ++/ 208 @property 209 enum isAggregateAssignableTo(Type) = isAggregate && __traits(compiles, { 210 GetMember!(QueryType, Name) t1 = void; 211 Type t2 = t1; 212 }); 213 214 /++ 215 + Returns true if a given type can be assigned from a variable of the 216 + element's aggregate type. 217 ++/ 218 @property 219 enum isAggregateAssignableFrom(Type) = isAggregate && __traits(compiles, { 220 Type t1 = void; 221 GetMember!(QueryType, Name) t2 = t1; 222 }); 223 224 /++ 225 + Returns true if the element refers to a class. 226 ++/ 227 @property 228 enum isClass = isAggregate && __traits(compiles, { 229 alias Element = Alias!(GetMember!(QueryType, Name)); 230 static assert(is(Element == class)); 231 }); 232 233 /++ 234 + Returns true if the element refers to a struct. 235 ++/ 236 @property 237 enum isStruct = isAggregate && __traits(compiles, { 238 alias Element = Alias!(GetMember!(QueryType, Name)); 239 static assert(is(Element == struct)); 240 }); 241 242 /++ 243 + Returns true if the element refers to an enum. 244 ++/ 245 @property 246 enum isEnum = isAggregate && __traits(compiles, { 247 alias Element = Alias!(GetMember!(QueryType, Name)); 248 static assert(is(Element == enum)); 249 250 }); 251 252 /++ 253 + Returns true is the element is a template of the given type. 254 ++/ 255 @property 256 enum isTemplateOf(alias Template) = __traits(compiles, { 257 alias Element = Alias!(GetMember!(QueryType, Name)); 258 static assert(is(TemplateOf!Element == Template)); 259 }); 260 261 /++ 262 + Returns true if the element's template arguments match. 263 ++/ 264 @property 265 enum isTemplateArgsOf(TemplateArgs...) = __traits(compiles, { 266 alias Element = Alias!(GetMember!(QueryType, Name)); 267 static assert(Compare!(TemplateArgsOf!Element).With!TemplateArgs); 268 }); 269 270 /++ 271 + Returns an uninitialized value of the element's type. 272 ++/ 273 @property 274 static auto opCall() 275 { 276 DQueryElement!(QueryType, Name, Overload) element = void; 277 return element; 278 } 279 280 /++ 281 + Returns a query for the type the element refers to. 282 ++/ 283 @property 284 static auto query()() 285 if(isAggregate) 286 { 287 import dquery.d; 288 return query!(GetMember!(QueryType, Name)); 289 } 290 291 /++ 292 + Returns a query for the parent type of the element. 293 ++/ 294 @property 295 static auto parent()() 296 { 297 import dquery.d; 298 return query!QueryType; 299 } 300 301 /++ 302 + Returns the element's attributes. 303 ++/ 304 @property 305 static auto attributes()() 306 { 307 static if(isAccessible) 308 { 309 alias MapToAttribute(alias Attribute) = Alias!( 310 DQueryAttribute!Attribute() 311 ); 312 313 return DQueryAttributes!( 314 QueryType, 315 staticMap!( 316 MapToAttribute, 317 GetAttributes!(QueryType, Name) 318 ) 319 )(); 320 } 321 else 322 { 323 return DQueryAttributes!( 324 QueryType, TypeTuple!() 325 )(); 326 } 327 } 328 329 /++ 330 + Returns the element's allowed attributes. 331 ++/ 332 @property 333 static auto attributes(Allow...)() 334 if(Allow.length > 0) 335 { 336 return attributes.allow!Allow; 337 } 338 339 /++ 340 + Returns the name of element. 341 ++/ 342 static string toString() 343 { 344 return Name; 345 } 346 347 }