-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathWiresAnnotations.hh
135 lines (113 loc) · 3.68 KB
/
WiresAnnotations.hh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
<?hh // strict
/**
* @copyright 2010-2015, The Titon Project
* @license http://opensource.org/licenses/bsd-license.php
* @link http://titon.io
*/
namespace Titon\Annotation;
/**
* The WiresAnnotations trait allows a class to wire class level and method level annotations.
* If an annotation implements the `Titon\Annotation\Wireable` interface, than any wired
* annotation will be bootstrapped.
*
* @package Titon\Annotation
*/
trait WiresAnnotations {
/**
* Annotation reader instance.
*
* @var \Titon\Annotation\Reader
*/
protected ?Reader $annotationReader;
/**
* Map of wired annotations.
*
* @var Map<string, int>
*/
protected Map<string, int> $wiredAnnotations = Map {};
/**
* Return an annotation reader instance. If one does not exist, it will be created.
*
* @return \Titon\Annotation\Reader
*/
protected function getAnnotationReader(): Reader {
if ($this->annotationReader) {
return $this->annotationReader;
}
return $this->annotationReader = new Reader($this);
}
/**
* Wire all class and method annotations.
*
* @return $this
*/
protected function wireAnnotations(): this {
$this->wireClassAnnotations();
foreach ($this->getAnnotationReader()->getAnnotatedMethods() as $method => $annotations) {
foreach ($annotations as $annotation) {
$this->wireUp($annotation, $method);
}
}
return $this;
}
/**
* Wire a single class annotation by name and return the annotation.
*
* @param string $name
* @return \Titon\Annotation\Annotation
*/
protected function wireClassAnnotation(string $name): Annotation {
return $this->wireUp($this->getAnnotationReader()->getClassAnnotation($name));
}
/**
* Wire all class annotations.
*
* @return $this;
*/
protected function wireClassAnnotations(): this {
foreach ($this->getAnnotationReader()->getClassAnnotations() as $annotation) {
$this->wireUp($annotation);
}
return $this;
}
/**
* Wire a single method annotation by name and return the annotation.
*
* @param string $name
* @return \Titon\Annotation\Annotation
*/
protected function wireMethodAnnotation(string $method, string $name): Annotation {
return $this->wireUp($this->getAnnotationReader()->getMethodAnnotation($method, $name), $method);
}
/**
* Wire all annotations for a specific method.
*
* @return $this;
*/
protected function wireMethodAnnotations(string $method): this {
foreach ($this->getAnnotationReader()->getMethodAnnotations($method) as $annotation) {
$this->wireUp($annotation);
}
return $this;
}
/**
* Wire up an annotation if it has not been previously wired.
*
* @param \Titon\Annotation\Annotation $annotation
* @param string $method
* @return \Titon\Annotation\Annotation
*/
protected function wireUp(Annotation $annotation, string $method = ''): Annotation {
$key = static::class . ':' . $method . ':' . $annotation->getName();
if ($this->wiredAnnotations->contains($key)) {
return $annotation;
}
if ($annotation instanceof Wireable) {
$annotation->wire($this, $method);
}
$this->wiredAnnotations[$key] = time();
// The type checker balks here and thinks we are `Wireable` instead of `Annotation`, so reset it.
invariant($annotation instanceof Annotation, 'Must be an annotation.');
return $annotation;
}
}