1 
2 module witchcraft.mixins.classes;
3 
4 mixin template WitchcraftClass()
5 {
6     import witchcraft;
7 
8     import std.meta;
9     import std.traits;
10 
11     static class ClassMixin(T) : Class
12     if(is(T == class))
13     {
14         this()
15         {
16             foreach(name; FieldNameTuple!T)
17             {
18                 _fields[name] = new FieldMixin!(T, name);
19             }
20 
21             foreach(name; __traits(derivedMembers, T))
22             {
23                 static if(is(typeof(__traits(getMember, T, name)) == function))
24                 {
25                     static if(name != "__ctor" && name != "__dtor")
26                     {
27                         foreach(index, overload; __traits(getOverloads, T, name))
28                         {
29                             _methods[name] ~= new MethodMixin!(T, name, index);
30                         }
31                     }
32                 }
33             }
34         }
35 
36         @property
37         override Object create() const
38         {
39             return T.classinfo.create;
40         }
41 
42         const(Attribute)[] getAttributes() const
43         {
44             alias attributes = AliasSeq!(__traits(getAttributes, T));
45             auto values = new Attribute[attributes.length];
46 
47             foreach(index, attribute; attributes)
48             {
49                 values[index] = new AttributeImpl!attribute;
50             }
51 
52             return values;
53         }
54 
55         override const(Constructor)[] getConstructors() const
56         {
57             static if(__traits(hasMember, T, "__ctor"))
58             {
59                 alias constructors = AliasSeq!(__traits(getOverloads, T, "__ctor"));
60                 auto values = new Constructor[constructors.length];
61 
62                 foreach(index, constructor; constructors)
63                 {
64                     values[index] = new ConstructorMixin!(T, index);
65                 }
66 
67                 return values;
68             }
69             else
70             {
71                 return [ ];
72             }
73         }
74 
75         const(Type) getDeclaringType() const
76         {
77             alias Parent = Alias!(__traits(parent, T));
78 
79             return inspect!Parent;
80         }
81 
82         const(TypeInfo) getDeclaringTypeInfo() const
83         {
84             alias Parent = Alias!(__traits(parent, T));
85 
86             static if(__traits(compiles, typeid(Parent)))
87             {
88                 return typeid(Parent);
89             }
90             else
91             {
92                 return null;
93             }
94         }
95 
96         override const(InterfaceType)[] getInterfaces() const
97         {
98             alias Interfaces = InterfacesTuple!T;
99             auto values = new InterfaceType[Interfaces.length];
100 
101             foreach(index, IFace; Interfaces)
102             {
103                 values[index] = cast(InterfaceType) inspect!IFace;
104             }
105 
106             return values;
107         }
108 
109         string getFullName() const
110         {
111             return fullyQualifiedName!T;
112         }
113 
114         string getName() const
115         {
116             return T.stringof;
117         }
118 
119         string getProtection() const
120         {
121             return __traits(getProtection, T);
122         }
123 
124         override const(Class) getSuperClass() const
125         {
126             static if(is(Unqual!T == Object))
127             {
128                 return null;
129             }
130             else
131             {
132                 alias Bases = BaseClassesTuple!T;
133 
134                 static if(Bases.length > 0)
135                 {
136                     return cast(const(Class)) inspect!(Bases[0]);
137                 }
138                 else
139                 {
140                     return null;
141                 }
142             }
143         }
144 
145         override const(TypeInfo) getSuperTypeInfo() const
146         {
147             static if(is(Unqual!T == Object))
148             {
149                 return null;
150             }
151             else
152             {
153                 alias Bases = BaseClassesTuple!T;
154 
155                 static if(Bases.length > 0)
156                 {
157                     return typeid(Bases[0]);
158                 }
159                 else
160                 {
161                     return null;
162                 }
163             }
164         }
165 
166         override const(TypeInfo) getTypeInfo() const
167         {
168             return T.classinfo;
169         }
170 
171         @property
172         override bool isAbstract() const
173         {
174             return __traits(isAbstractClass, T);
175         }
176 
177         @property
178         final bool isAccessible() const
179         {
180             return true;
181         }
182 
183         @property
184         override bool isFinal() const
185         {
186             return __traits(isFinalClass, T);
187         }
188 
189         override bool isSubClassOf(const Class other) const
190         {
191             return _d_isbaseof(T.classinfo, cast(ClassInfo) other.getTypeInfo);
192         }
193 
194         override bool isSuperClassOf(const Class other) const
195         {
196             return _d_isbaseof(cast(ClassInfo) other.getTypeInfo, T.classinfo);
197         }
198     }
199 }