-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathReader.hh
133 lines (112 loc) · 3.87 KB
/
Reader.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
<?hh // strict
/**
* @copyright 2010-2015, The Titon Project
* @license http://opensource.org/licenses/bsd-license.php
* @link http://titon.io
*/
namespace Titon\Annotation;
use Titon\Annotation\Exception\MissingAnnotationException;
use ReflectionClass;
/**
* The Reader class provides a straight forward approach for reading class and method annotations.
* Each annotation that is read is converted to a mapped annotation class.
*
* @package Titon\Annotation
*/
class Reader {
/**
* The class reflection to read annotations from.
*
* @var \ReflectionClass
*/
protected ReflectionClass $class;
/**
* Instantiate a new class reflection layer based on the specified class.
*
* @param mixed $class
*/
public function __construct(mixed $class) {
$this->class = new ReflectionClass($class);
}
/**
* Return a map of all methods that have annotations.
*
* @return \Titon\Annotation\MethodAnnotationMap
*/
<<__Memoize>>
public function getAnnotatedMethods(): MethodAnnotationMap {
$methods = Map {};
foreach ($this->class->getMethods() as $method) {
if ($annotations = $this->getMethodAnnotations($method->getName())) {
$methods[$method->getName()] = $annotations;
}
}
return $methods;
}
/**
* Return the annotation instance defined by name.
* If no annotation exists, throw an exception.
*
* @param string $name
* @return \Titon\Annotation\Annotation
* @throws \Titon\Annotation\Exception\MissingAnnotationException
*/
public function getClassAnnotation(string $name): Annotation {
$annotations = $this->getClassAnnotations();
if ($annotations->contains($name)) {
return $annotations[$name];
}
throw new MissingAnnotationException(sprintf('Class annotation %s does not exist', $name));
}
/**
* Return a map of all annotations defined on the current class.
*
* @return \Titon\Annotation\AnnotationMap
*/
<<__Memoize>>
public function getClassAnnotations(): AnnotationMap {
return $this->packageAnnotations($this->class->getAttributes());
}
/**
* Return the annotation instance defined by name on a specific method.
* If no annotation exists, throw an exception.
*
* @param string $method
* @param string $name
* @return \Titon\Annotation\Annotation
* @throws \Titon\Annotation\Exception\MissingAnnotationException
*/
public function getMethodAnnotation(string $method, string $name): Annotation {
$annotations = $this->getMethodAnnotations($method);
if ($annotations->contains($name)) {
return $annotations[$name];
}
throw new MissingAnnotationException(sprintf('Method %s annotation %s does not exist', $method, $name));
}
/**
* Return a map of all annotations defined on a method on the current class.
*
* @param string $method
* @return \Titon\Annotation\AnnotationMap
*/
<<__Memoize>>
public function getMethodAnnotations(string $method): AnnotationMap {
return $this->packageAnnotations($this->class->getMethod($method)->getAttributes());
}
/**
* Convert the attributes returned from the reflection layer into annotation classes.
*
* @param array<string, array<mixed>> $attributes
* @return \Titon\Annotation\AnnotationMap
*/
protected function packageAnnotations(array<string, array<mixed>> $attributes): AnnotationMap {
$annotations = Map {};
foreach ($attributes as $name => $arguments) {
if (substr($name, 0, 2) === '__') {
continue; // Ignore built-ins
}
$annotations[$name] = Registry::factory($name, $arguments);
}
return $annotations;
}
}