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