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