1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* Scabbia2 Scanners Component |
4
|
|
|
* https://github.com/eserozvataf/scabbia2 |
5
|
|
|
* |
6
|
|
|
* For the full copyright and license information, please view the LICENSE |
7
|
|
|
* file that was distributed with this source code. |
8
|
|
|
* |
9
|
|
|
* @link https://github.com/eserozvataf/scabbia2-scanners for the canonical source repository |
10
|
|
|
* @copyright 2010-2016 Eser Ozvataf. (http://eser.ozvataf.com/) |
11
|
|
|
* @license http://www.apache.org/licenses/LICENSE-2.0 - Apache License, Version 2.0 |
12
|
|
|
*/ |
13
|
|
|
|
14
|
|
|
namespace Scabbia\Scanners; |
15
|
|
|
|
16
|
|
|
use Scabbia\Scanners\ScannerInterface; |
17
|
|
|
use Scabbia\Scanners\TokenStream; |
18
|
|
|
use LogicException; |
19
|
|
|
use ReflectionClass; |
20
|
|
|
|
21
|
|
|
/** |
22
|
|
|
* canner |
23
|
|
|
* |
24
|
|
|
* @package Scabbia\Scanners |
25
|
|
|
* @author Eser Ozvataf <[email protected]> |
26
|
|
|
* @since 2.0.0 |
27
|
|
|
*/ |
28
|
|
|
class AnnotationScanner implements ScannerInterface |
29
|
|
|
{ |
30
|
|
|
/** @type array $result result of scanning task */ |
31
|
|
|
public $result = []; |
32
|
|
|
/** @type array $ignoreList annotations to be ignored */ |
33
|
|
|
public $ignoreList = [ |
34
|
|
|
"link", |
35
|
|
|
"copyright", |
36
|
|
|
"license", |
37
|
|
|
"package", |
38
|
|
|
"author", |
39
|
|
|
"since", |
40
|
|
|
"type", |
41
|
|
|
"param", |
42
|
|
|
"return", |
43
|
|
|
"throws", |
44
|
|
|
"todo", |
45
|
|
|
"see", |
46
|
|
|
"ignore" |
47
|
|
|
]; |
48
|
|
|
|
49
|
|
|
|
50
|
|
|
/** |
51
|
|
|
* Scans a file |
52
|
|
|
* |
53
|
|
|
* @param string $uFile file path |
54
|
|
|
* @param string $uFileContents contents of file |
55
|
|
|
* |
56
|
|
|
* @return void |
57
|
|
|
*/ |
58
|
|
|
public function processFile($uFile, $uFileContents) |
59
|
|
|
{ |
60
|
|
|
} |
61
|
|
|
|
62
|
|
|
/** |
63
|
|
|
* Scans a token stream |
64
|
|
|
* |
65
|
|
|
* @param TokenStream $uTokenStream extracted tokens wrapped with tokenstream |
66
|
|
|
* |
67
|
|
|
* @return void |
68
|
|
|
*/ |
69
|
|
|
public function processTokenStream(TokenStream $uTokenStream) |
70
|
|
|
{ |
71
|
|
|
} |
72
|
|
|
|
73
|
|
|
/** |
74
|
|
|
* Processes classes using reflection |
75
|
|
|
* |
76
|
|
|
* @param string $uClass class name |
77
|
|
|
* @param ReflectionClass $uReflection reflection information for the class |
78
|
|
|
* |
79
|
|
|
* @return void |
80
|
|
|
*/ |
81
|
|
|
public function processClass($uClass, ReflectionClass $uReflection) |
82
|
|
|
{ |
83
|
|
|
$tClassAnnotations = []; |
84
|
|
|
|
85
|
|
|
$tDocComment = $uReflection->getDocComment(); |
86
|
|
|
if (strlen($tDocComment) > 0) { |
87
|
|
|
$tParsedAnnotations = $this->parseAnnotations($tDocComment); |
88
|
|
|
if (count($tParsedAnnotations) > 0) { |
89
|
|
|
$tClassAnnotations["class"] = ["self" => $tParsedAnnotations]; |
90
|
|
|
} |
91
|
|
|
} |
92
|
|
|
|
93
|
|
|
// methods |
94
|
|
View Code Duplication |
foreach ($uReflection->getMethods() as $tMethodReflection) { |
|
|
|
|
95
|
|
|
// TODO check the correctness of logic |
96
|
|
|
if ($tMethodReflection->class !== $uClass) { |
97
|
|
|
continue; |
98
|
|
|
} |
99
|
|
|
|
100
|
|
|
$tDocComment = $tMethodReflection->getDocComment(); |
101
|
|
|
if (strlen($tDocComment) > 0) { |
102
|
|
|
$tParsedAnnotations = $this->parseAnnotations($tDocComment); |
103
|
|
|
|
104
|
|
|
if (count($tParsedAnnotations) === 0) { |
|
|
|
|
105
|
|
|
// nothing |
106
|
|
|
} elseif ($tMethodReflection->isStatic()) { |
107
|
|
|
if (!isset($tClassAnnotations["staticMethods"])) { |
108
|
|
|
$tClassAnnotations["staticMethods"] = []; |
109
|
|
|
} |
110
|
|
|
|
111
|
|
|
$tClassAnnotations["staticMethods"][$tMethodReflection->name] = $tParsedAnnotations; |
112
|
|
|
} else { |
113
|
|
|
if (!isset($tClassAnnotations["methods"])) { |
114
|
|
|
$tClassAnnotations["methods"] = []; |
115
|
|
|
} |
116
|
|
|
|
117
|
|
|
$tClassAnnotations["methods"][$tMethodReflection->name] = $tParsedAnnotations; |
118
|
|
|
} |
119
|
|
|
} |
120
|
|
|
} |
121
|
|
|
|
122
|
|
|
// properties |
123
|
|
View Code Duplication |
foreach ($uReflection->getProperties() as $tPropertyReflection) { |
|
|
|
|
124
|
|
|
// TODO check the correctness of logic |
125
|
|
|
if ($tPropertyReflection->class !== $uClass) { |
126
|
|
|
continue; |
127
|
|
|
} |
128
|
|
|
|
129
|
|
|
$tDocComment = $tPropertyReflection->getDocComment(); |
130
|
|
|
if (strlen($tDocComment) > 0) { |
131
|
|
|
$tParsedAnnotations = $this->parseAnnotations($tDocComment); |
132
|
|
|
|
133
|
|
|
if (count($tParsedAnnotations) === 0) { |
|
|
|
|
134
|
|
|
// nothing |
135
|
|
|
} elseif ($tPropertyReflection->isStatic()) { |
136
|
|
|
if (!isset($tClassAnnotations["staticProperties"])) { |
137
|
|
|
$tClassAnnotations["staticProperties"] = []; |
138
|
|
|
} |
139
|
|
|
|
140
|
|
|
$tClassAnnotations["staticProperties"][$tPropertyReflection->name] = $tParsedAnnotations; |
141
|
|
|
} else { |
142
|
|
|
if (!isset($tClassAnnotations["properties"])) { |
143
|
|
|
$tClassAnnotations["properties"] = []; |
144
|
|
|
} |
145
|
|
|
|
146
|
|
|
$tClassAnnotations["properties"][$tPropertyReflection->name] = $tParsedAnnotations; |
147
|
|
|
} |
148
|
|
|
} |
149
|
|
|
} |
150
|
|
|
|
151
|
|
|
if (count($tClassAnnotations) > 0) { |
152
|
|
|
$this->result[$uClass] = $tClassAnnotations; |
153
|
|
|
} else { |
154
|
|
|
$this->result[$uClass] = null; |
155
|
|
|
} |
156
|
|
|
} |
157
|
|
|
|
158
|
|
|
/** |
159
|
|
|
* Finalizes the task |
160
|
|
|
* |
161
|
|
|
* @return void |
162
|
|
|
*/ |
163
|
|
|
public function finalize() |
164
|
|
|
{ |
165
|
|
|
} |
166
|
|
|
|
167
|
|
|
/** |
168
|
|
|
* Parses the docblock and returns annotations in an array |
169
|
|
|
* |
170
|
|
|
* @param string $uDocComment docblock which contains annotations |
171
|
|
|
* |
172
|
|
|
* @return array set of annotations |
173
|
|
|
*/ |
174
|
|
|
protected function parseAnnotations($uDocComment) |
175
|
|
|
{ |
176
|
|
|
preg_match_all( |
177
|
|
|
"/\\*[\\t| ]\\@([^\\n|\\t| ]+)(?:[\\t| ]([^\\n]+))*/", |
178
|
|
|
$uDocComment, |
179
|
|
|
$tDocCommentLines, |
180
|
|
|
PREG_SET_ORDER |
181
|
|
|
); |
182
|
|
|
|
183
|
|
|
$tParsedAnnotations = []; |
184
|
|
|
|
185
|
|
|
foreach ($tDocCommentLines as $tDocCommentLine) { |
|
|
|
|
186
|
|
|
if (in_array($tDocCommentLine[1], $this->ignoreList)) { |
187
|
|
|
continue; |
188
|
|
|
} |
189
|
|
|
|
190
|
|
|
if (!isset($tParsedAnnotations[$tDocCommentLine[1]])) { |
191
|
|
|
$tParsedAnnotations[$tDocCommentLine[1]] = []; |
192
|
|
|
} |
193
|
|
|
|
194
|
|
|
if (isset($tDocCommentLine[2])) { |
195
|
|
|
$tParsedAnnotations[$tDocCommentLine[1]][] = trim($tDocCommentLine[2]); |
196
|
|
|
} |
197
|
|
|
} |
198
|
|
|
|
199
|
|
|
return $tParsedAnnotations; |
200
|
|
|
} |
201
|
|
|
} |
202
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.