1 /**
2  * Contains definition of hasTemplateMixin, which checks if a class or struct
3  * defines all the members of a template mixin, and hasStringMixin, which
4  * checks if a class or struct defines all the members of a string mixin.
5  */
6 module quack.mixins;
7 import quack.extends;
8 
9 import tested;
10 
11 /**
12  * Checks if Child extends Parent by implementing a template mixin.
13  *
14  * Params:
15  *      Child =         The base class to test.
16  *      mix =           The mixin to test for.
17  *
18  * Returns:
19  *      Whether Child has all the members of mix.
20  */
21 template hasTemplateMixin( Child, alias mix )
22 {
23     static if( isExtendable!Child )
24     {
25         struct MixinImpl
26         {
27             mixin mix!();
28         }
29 
30         enum hasTemplateMixin = hasSameMembers!( Child, MixinImpl );
31     }
32     else
33     {
34         enum hasTemplateMixin = false;
35     }
36 }
37 ///
38 @name( "hasTemplateMixin" )
39 unittest
40 {
41     assert( !hasTemplateMixin!( float, TestMix ) );
42 
43     struct TestMixStruct1
44     {
45         mixin TestMix!();
46     }
47     assert( hasTemplateMixin!( TestMixStruct1, TestMix ) );
48 
49     class TestMixClass1
50     {
51         mixin TestMix!();
52     }
53     assert( hasTemplateMixin!( TestMixClass1, TestMix ) );
54 
55     class TestMixClass2
56     {
57         mixin TestMix!();
58         int getY() { return 43; }
59     }
60     assert( hasTemplateMixin!( TestMixClass2, TestMix ) );
61 
62     class TestMixClass3
63     {
64         int getZ() { return 44; }
65     }
66     assert( !hasTemplateMixin!( TestMixClass3, TestMix ) );
67 
68     class TestMixClass4
69     {
70         int getX() { return 45; }
71     }
72     assert( hasTemplateMixin!( TestMixClass4, TestMix ) );
73 }
74 version( unittest )
75 mixin template TestMix()
76 {
77     int getX() { return 42; }
78 }
79 
80 /**
81  * Checks if Child extends Parent by implementing a string mixin.
82  *
83  * Params:
84  *      Child =         The base class to test.
85  *      mix =           The mixin to test for.
86  *
87  * Returns:
88  *      Whether Child has all the members of mix.
89  */
90 template hasStringMixin( Base, string mix )
91 {
92     static if( isExtendable!Base )
93     {
94         struct MixinImpl
95         {
96             mixin( mix );
97         }
98 
99         enum hasStringMixin = hasSameMembers!( Base, MixinImpl );
100     }
101     else
102     {
103         enum hasStringMixin = false;
104     }
105 }
106 ///
107 @name( "hasStringMixin" )
108 unittest
109 {
110     enum testMix = q{ int getX() { return 42; } };
111 
112     assert( !hasStringMixin!( float, testMix ) );
113 
114     struct TestMixStruct1
115     {
116         mixin( testMix );
117     }
118     assert( hasStringMixin!( TestMixStruct1, testMix ) );
119 
120     class TestMixClass1
121     {
122         mixin( testMix );
123     }
124     assert( hasStringMixin!( TestMixClass1, testMix ) );
125 
126     class TestMixClass2
127     {
128         mixin( testMix );
129         int getY() { return 43; }
130     }
131     assert( hasStringMixin!( TestMixClass2, testMix ) );
132 
133     class TestMixClass3
134     {
135         int getZ() { return 44; }
136     }
137     assert( !hasStringMixin!( TestMixClass3, testMix ) );
138 
139     class TestMixClass4
140     {
141         int getX() { return 45; }
142     }
143     assert( hasStringMixin!( TestMixClass4, testMix ) );
144 }