1 /**
2  * These are core annotations for the whole framework. To avoid recursive checks,
3  * they are not annotated with constraints, but supported usage is documented 
4  * with annotations in doc comments.
5  */
6 module glued.annotations.core_annotations;
7 
8 import std.meta: Alias;
9 import std.traits: hasUDA;
10 
11 import glued.annotations.common_annotations;
12 import glued.annotations.common_impl;
13 
14 ///UDA for "magic annotations" like OnParameter, that should be filtered out
15 /// when retrieving target annotations
16 enum GluedMagic;
17 
18 ///Strictly documentational UDA; totally ignored by a framework, but defines
19 /// how the "magic" annotation would be used.
20 @GluedMagic
21 enum MagicUsage(T...) = "And this is how we do it";
22 
23 @GluedMagic
24 @MagicUsage!(OnAnnotation, Repeatable, NonImplicable)
25 struct CheckedBy(alias Checker)
26 {
27     ///bool foo(alias target, alias annotation, alias constraint)()
28     ///where target is a symbol and annotation and constraint are values (struct
29     ///instances)
30     alias Check = Checker;
31     
32     static bool check(T...)()
33     {
34         return Checker!(T)();
35     }
36 }
37 
38 /**
39  * If this annotation is present on another annotation, the annotated one cannot
40  * be subject of Implies!(...).
41  */
42  @GluedMagic
43 struct NonImplicable {}
44 
45 @GluedMagic
46 struct Implies(S) 
47     if (is(S == struct)) 
48 {
49     static assert(!hasUDA!(S, NonImplicable), "Annotation "~fullyQualifiedName!S~" is not implicable and as such cannot be used in Implies!(...)");
50     ///Annotation "brought" by the one annotated with Implies
51     const S implicated = S.init;
52     
53     template getImplicated()
54     {
55         alias getImplicated = Alias!(S.init);
56     }
57 }
58 
59 @GluedMagic
60 struct Implies(alias S) 
61     if (is(typeof(S) == struct)) 
62 {
63     static assert(!hasUDA!(typeof(S), NonImplicable), "Annotation "~fullyQualifiedName!(typeof(S))~" is not implicable and as such cannot be used in Implies!(...)");
64     
65     ///ditto
66     const typeof(S) implicated = S; 
67      
68     template getImplicated()
69     { 
70         alias getImplicated = Alias!(S); 
71     } 
72 }
73 
74 //todo actually figure out parameter annotations instead of using this weird 'pointers'
75 @GluedMagic
76 @MagicUsage!(Repeatable, Target(TargetType.FUNCTION))
77 struct OnParameter(size_t _paramIdx, alias _annotation)
78 {
79     enum paramIdx = _paramIdx;
80     alias annotation = _annotation;
81     
82     enum describesParam(string name, size_t idx) = (idx == paramIdx);
83 }
84 
85 @GluedMagic
86 @MagicUsage!(Repeatable, Target(TargetType.FUNCTION))
87 struct OnParameter(string _paramName, alias _annotation)
88 {
89     enum paramName = _paramName;
90     alias annotation = _annotation;
91     
92     enum describesParam(string name, size_t idx) = (name == paramName);
93 }