Total Complexity | 73 |
Total Lines | 1364 |
Duplicated Lines | 0 % |
Changes | 0 |
Complex classes like DocParserTest often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use DocParserTest, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
15 | { |
||
16 | public function testNestedArraysWithNestedAnnotation() |
||
17 | { |
||
18 | $parser = $this->createTestParser(); |
||
19 | |||
20 | // Nested arrays with nested annotations |
||
21 | $result = $parser->parse('@Name(foo={1,2, {"key"=@Name}})'); |
||
22 | $annot = $result[0]; |
||
23 | |||
24 | self::assertInstanceOf(Name::class, $annot); |
||
25 | self::assertNull($annot->value); |
||
26 | self::assertCount(3, $annot->foo); |
||
27 | self::assertEquals(1, $annot->foo[0]); |
||
28 | self::assertEquals(2, $annot->foo[1]); |
||
29 | self::assertInternalType('array', $annot->foo[2]); |
||
30 | |||
31 | $nestedArray = $annot->foo[2]; |
||
32 | self::assertTrue(isset($nestedArray['key'])); |
||
33 | self::assertInstanceOf(Name::class, $nestedArray['key']); |
||
34 | } |
||
35 | |||
36 | public function testBasicAnnotations() |
||
37 | { |
||
38 | $parser = $this->createTestParser(); |
||
39 | |||
40 | // Marker annotation |
||
41 | $result = $parser->parse('@Name'); |
||
42 | $annot = $result[0]; |
||
43 | self::assertInstanceOf(Name::class, $annot); |
||
44 | self::assertNull($annot->value); |
||
45 | self::assertNull($annot->foo); |
||
46 | |||
47 | // Associative arrays |
||
48 | $result = $parser->parse('@Name(foo={"key1" = "value1"})'); |
||
49 | $annot = $result[0]; |
||
50 | self::assertNull($annot->value); |
||
51 | self::assertInternalType('array', $annot->foo); |
||
52 | self::assertTrue(isset($annot->foo['key1'])); |
||
53 | |||
54 | // Numerical arrays |
||
55 | $result = $parser->parse('@Name({2="foo", 4="bar"})'); |
||
56 | $annot = $result[0]; |
||
57 | self::assertInternalType('array', $annot->value); |
||
58 | self::assertEquals('foo', $annot->value[2]); |
||
59 | self::assertEquals('bar', $annot->value[4]); |
||
60 | self::assertFalse(isset($annot->value[0])); |
||
61 | self::assertFalse(isset($annot->value[1])); |
||
62 | self::assertFalse(isset($annot->value[3])); |
||
63 | |||
64 | // Multiple values |
||
65 | $result = $parser->parse('@Name(@Name, @Name)'); |
||
66 | $annot = $result[0]; |
||
67 | |||
68 | self::assertInstanceOf(Name::class, $annot); |
||
69 | self::assertInternalType('array', $annot->value); |
||
70 | self::assertInstanceOf(Name::class, $annot->value[0]); |
||
71 | self::assertInstanceOf(Name::class, $annot->value[1]); |
||
72 | |||
73 | // Multiple types as values |
||
74 | $result = $parser->parse('@Name(foo="Bar", @Name, {"key1"="value1", "key2"="value2"})'); |
||
75 | $annot = $result[0]; |
||
76 | |||
77 | self::assertInstanceOf(Name::class, $annot); |
||
78 | self::assertInternalType('array', $annot->value); |
||
79 | self::assertInstanceOf(Name::class, $annot->value[0]); |
||
80 | self::assertInternalType('array', $annot->value[1]); |
||
81 | self::assertEquals('value1', $annot->value[1]['key1']); |
||
82 | self::assertEquals('value2', $annot->value[1]['key2']); |
||
83 | |||
84 | // Complete docblock |
||
85 | $docblock = <<<DOCBLOCK |
||
86 | /** |
||
87 | * Some nifty class. |
||
88 | * |
||
89 | * @author Mr.X |
||
90 | * @Name(foo="bar") |
||
91 | */ |
||
92 | DOCBLOCK; |
||
93 | |||
94 | $result = $parser->parse($docblock); |
||
95 | self::assertCount(1, $result); |
||
96 | $annot = $result[0]; |
||
97 | self::assertInstanceOf(Name::class, $annot); |
||
98 | self::assertEquals('bar', $annot->foo); |
||
99 | self::assertNull($annot->value); |
||
100 | } |
||
101 | |||
102 | public function testDefaultValueAnnotations() |
||
103 | { |
||
104 | $parser = $this->createTestParser(); |
||
105 | |||
106 | // Array as first value |
||
107 | $result = $parser->parse('@Name({"key1"="value1"})'); |
||
108 | $annot = $result[0]; |
||
109 | |||
110 | self::assertInstanceOf(Name::class, $annot); |
||
111 | self::assertInternalType('array', $annot->value); |
||
112 | self::assertEquals('value1', $annot->value['key1']); |
||
113 | |||
114 | // Array as first value and additional values |
||
115 | $result = $parser->parse('@Name({"key1"="value1"}, foo="bar")'); |
||
116 | $annot = $result[0]; |
||
117 | |||
118 | self::assertInstanceOf(Name::class, $annot); |
||
119 | self::assertInternalType('array', $annot->value); |
||
120 | self::assertEquals('value1', $annot->value['key1']); |
||
121 | self::assertEquals('bar', $annot->foo); |
||
122 | } |
||
123 | |||
124 | public function testNamespacedAnnotations() |
||
125 | { |
||
126 | $parser = new DocParser; |
||
127 | $parser->setIgnoreNotImportedAnnotations(true); |
||
128 | |||
129 | $docblock = <<<DOCBLOCK |
||
130 | /** |
||
131 | * Some nifty class. |
||
132 | * |
||
133 | * @package foo |
||
134 | * @subpackage bar |
||
135 | * @author Mr.X <[email protected]> |
||
136 | * @Doctrine\Tests\Annotations\Name(foo="bar") |
||
137 | * @ignore |
||
138 | */ |
||
139 | DOCBLOCK; |
||
140 | |||
141 | $result = $parser->parse($docblock); |
||
142 | self::assertCount(1, $result); |
||
143 | $annot = $result[0]; |
||
144 | self::assertInstanceOf(Name::class, $annot); |
||
145 | self::assertEquals('bar', $annot->foo); |
||
146 | } |
||
147 | |||
148 | /** |
||
149 | * @group debug |
||
150 | */ |
||
151 | public function testTypicalMethodDocBlock() |
||
152 | { |
||
153 | $parser = $this->createTestParser(); |
||
154 | |||
155 | $docblock = <<<DOCBLOCK |
||
156 | /** |
||
157 | * Some nifty method. |
||
158 | * |
||
159 | * @since 2.0 |
||
160 | * @Doctrine\Tests\Annotations\Name(foo="bar") |
||
161 | * @param string \$foo This is foo. |
||
162 | * @param mixed \$bar This is bar. |
||
163 | * @return string Foo and bar. |
||
164 | * @This is irrelevant |
||
165 | * @Marker |
||
166 | */ |
||
167 | DOCBLOCK; |
||
168 | |||
169 | $result = $parser->parse($docblock); |
||
170 | self::assertCount(2, $result); |
||
171 | self::assertTrue(isset($result[0])); |
||
172 | self::assertTrue(isset($result[1])); |
||
173 | $annot = $result[0]; |
||
174 | self::assertInstanceOf(Name::class, $annot); |
||
175 | self::assertEquals('bar', $annot->foo); |
||
176 | $marker = $result[1]; |
||
177 | self::assertInstanceOf(Marker::class, $marker); |
||
178 | } |
||
179 | |||
180 | |||
181 | public function testAnnotationWithoutConstructor() |
||
182 | { |
||
183 | $parser = $this->createTestParser(); |
||
184 | |||
185 | |||
186 | $docblock = <<<DOCBLOCK |
||
187 | /** |
||
188 | * @SomeAnnotationClassNameWithoutConstructor("Some data") |
||
189 | */ |
||
190 | DOCBLOCK; |
||
191 | |||
192 | $result = $parser->parse($docblock); |
||
193 | self::assertCount(1, $result); |
||
194 | $annot = $result[0]; |
||
195 | |||
196 | self::assertInstanceOf(SomeAnnotationClassNameWithoutConstructor::class, $annot); |
||
197 | |||
198 | self::assertNull($annot->name); |
||
199 | self::assertNotNull($annot->data); |
||
200 | self::assertEquals($annot->data, 'Some data'); |
||
201 | |||
202 | |||
203 | |||
204 | |||
205 | $docblock = <<<DOCBLOCK |
||
206 | /** |
||
207 | * @SomeAnnotationClassNameWithoutConstructor(name="Some Name", data = "Some data") |
||
208 | */ |
||
209 | DOCBLOCK; |
||
210 | |||
211 | |||
212 | $result = $parser->parse($docblock); |
||
213 | self::assertCount(1, $result); |
||
214 | $annot = $result[0]; |
||
215 | |||
216 | self::assertNotNull($annot); |
||
217 | self::assertInstanceOf(SomeAnnotationClassNameWithoutConstructor::class, $annot); |
||
218 | |||
219 | self::assertEquals($annot->name, 'Some Name'); |
||
220 | self::assertEquals($annot->data, 'Some data'); |
||
221 | |||
222 | |||
223 | |||
224 | |||
225 | $docblock = <<<DOCBLOCK |
||
226 | /** |
||
227 | * @SomeAnnotationClassNameWithoutConstructor(data = "Some data") |
||
228 | */ |
||
229 | DOCBLOCK; |
||
230 | |||
231 | $result = $parser->parse($docblock); |
||
232 | self::assertCount(1, $result); |
||
233 | $annot = $result[0]; |
||
234 | |||
235 | self::assertEquals($annot->data, 'Some data'); |
||
236 | self::assertNull($annot->name); |
||
237 | |||
238 | |||
239 | $docblock = <<<DOCBLOCK |
||
240 | /** |
||
241 | * @SomeAnnotationClassNameWithoutConstructor(name = "Some name") |
||
242 | */ |
||
243 | DOCBLOCK; |
||
244 | |||
245 | $result = $parser->parse($docblock); |
||
246 | self::assertCount(1, $result); |
||
247 | $annot = $result[0]; |
||
248 | |||
249 | self::assertEquals($annot->name, 'Some name'); |
||
250 | self::assertNull($annot->data); |
||
251 | |||
252 | $docblock = <<<DOCBLOCK |
||
253 | /** |
||
254 | * @SomeAnnotationClassNameWithoutConstructor("Some data") |
||
255 | */ |
||
256 | DOCBLOCK; |
||
257 | |||
258 | $result = $parser->parse($docblock); |
||
259 | self::assertCount(1, $result); |
||
260 | $annot = $result[0]; |
||
261 | |||
262 | self::assertEquals($annot->data, 'Some data'); |
||
263 | self::assertNull($annot->name); |
||
264 | |||
265 | |||
266 | |||
267 | $docblock = <<<DOCBLOCK |
||
268 | /** |
||
269 | * @SomeAnnotationClassNameWithoutConstructor("Some data",name = "Some name") |
||
270 | */ |
||
271 | DOCBLOCK; |
||
272 | |||
273 | $result = $parser->parse($docblock); |
||
274 | self::assertCount(1, $result); |
||
275 | $annot = $result[0]; |
||
276 | |||
277 | self::assertEquals($annot->name, 'Some name'); |
||
278 | self::assertEquals($annot->data, 'Some data'); |
||
279 | |||
280 | |||
281 | $docblock = <<<DOCBLOCK |
||
282 | /** |
||
283 | * @SomeAnnotationWithConstructorWithoutParams(name = "Some name") |
||
284 | */ |
||
285 | DOCBLOCK; |
||
286 | |||
287 | $result = $parser->parse($docblock); |
||
288 | self::assertCount(1, $result); |
||
289 | $annot = $result[0]; |
||
290 | |||
291 | self::assertEquals($annot->name, 'Some name'); |
||
292 | self::assertEquals($annot->data, 'Some data'); |
||
293 | |||
294 | $docblock = <<<DOCBLOCK |
||
295 | /** |
||
296 | * @SomeAnnotationClassNameWithoutConstructorAndProperties() |
||
297 | */ |
||
298 | DOCBLOCK; |
||
299 | |||
300 | $result = $parser->parse($docblock); |
||
301 | self::assertCount(1, $result); |
||
302 | self::assertInstanceOf(SomeAnnotationClassNameWithoutConstructorAndProperties::class, $result[0]); |
||
303 | } |
||
304 | |||
305 | public function testAnnotationTarget() |
||
306 | { |
||
307 | |||
308 | $parser = new DocParser; |
||
309 | $parser->setImports([ |
||
310 | '__NAMESPACE__' => 'Doctrine\Tests\Annotations\Fixtures', |
||
311 | ]); |
||
312 | $class = new \ReflectionClass(Fixtures\ClassWithValidAnnotationTarget::class); |
||
313 | |||
314 | |||
315 | $context = 'class ' . $class->getName(); |
||
316 | $docComment = $class->getDocComment(); |
||
317 | |||
318 | $parser->setTarget(Target::TARGET_CLASS); |
||
319 | self::assertNotNull($parser->parse($docComment,$context)); |
||
320 | |||
321 | |||
322 | $property = $class->getProperty('foo'); |
||
323 | $docComment = $property->getDocComment(); |
||
324 | $context = 'property ' . $class->getName() . "::\$" . $property->getName(); |
||
325 | |||
326 | $parser->setTarget(Target::TARGET_PROPERTY); |
||
327 | self::assertNotNull($parser->parse($docComment,$context)); |
||
328 | |||
329 | |||
330 | |||
331 | $method = $class->getMethod('someFunction'); |
||
332 | $docComment = $property->getDocComment(); |
||
333 | $context = 'method ' . $class->getName() . '::' . $method->getName() . '()'; |
||
334 | |||
335 | $parser->setTarget(Target::TARGET_METHOD); |
||
336 | self::assertNotNull($parser->parse($docComment,$context)); |
||
337 | |||
338 | |||
339 | try { |
||
340 | $class = new \ReflectionClass(Fixtures\ClassWithInvalidAnnotationTargetAtClass::class); |
||
341 | $context = 'class ' . $class->getName(); |
||
342 | $docComment = $class->getDocComment(); |
||
343 | |||
344 | $parser->setTarget(Target::TARGET_CLASS); |
||
345 | $parser->parse($docComment, $context); |
||
346 | |||
347 | $this->fail(); |
||
348 | } catch (AnnotationException $exc) { |
||
349 | self::assertNotNull($exc->getMessage()); |
||
350 | } |
||
351 | |||
352 | |||
353 | try { |
||
354 | |||
355 | $class = new \ReflectionClass(Fixtures\ClassWithInvalidAnnotationTargetAtMethod::class); |
||
356 | $method = $class->getMethod('functionName'); |
||
357 | $docComment = $method->getDocComment(); |
||
358 | $context = 'method ' . $class->getName() . '::' . $method->getName() . '()'; |
||
359 | |||
360 | $parser->setTarget(Target::TARGET_METHOD); |
||
361 | $parser->parse($docComment, $context); |
||
362 | |||
363 | $this->fail(); |
||
364 | } catch (AnnotationException $exc) { |
||
365 | self::assertNotNull($exc->getMessage()); |
||
366 | } |
||
367 | |||
368 | |||
369 | try { |
||
370 | $class = new \ReflectionClass(Fixtures\ClassWithInvalidAnnotationTargetAtProperty::class); |
||
371 | $property = $class->getProperty('foo'); |
||
372 | $docComment = $property->getDocComment(); |
||
373 | $context = 'property ' . $class->getName() . "::\$" . $property->getName(); |
||
374 | |||
375 | $parser->setTarget(Target::TARGET_PROPERTY); |
||
376 | $parser->parse($docComment, $context); |
||
377 | |||
378 | $this->fail(); |
||
379 | } catch (AnnotationException $exc) { |
||
380 | self::assertNotNull($exc->getMessage()); |
||
381 | } |
||
382 | |||
383 | } |
||
384 | |||
385 | public function getAnnotationVarTypeProviderValid() |
||
386 | { |
||
387 | //({attribute name}, {attribute value}) |
||
388 | return [ |
||
389 | // mixed type |
||
390 | ['mixed', '"String Value"'], |
||
391 | ['mixed', 'true'], |
||
392 | ['mixed', 'false'], |
||
393 | ['mixed', '1'], |
||
394 | ['mixed', '1.2'], |
||
395 | ['mixed', '@Doctrine\Tests\Annotations\Fixtures\AnnotationTargetAll'], |
||
396 | |||
397 | // boolean type |
||
398 | ['boolean', 'true'], |
||
399 | ['boolean', 'false'], |
||
400 | |||
401 | // alias for internal type boolean |
||
402 | ['bool', 'true'], |
||
403 | ['bool', 'false'], |
||
404 | |||
405 | // integer type |
||
406 | ['integer', '0'], |
||
407 | ['integer', '1'], |
||
408 | ['integer', '123456789'], |
||
409 | ['integer', '9223372036854775807'], |
||
410 | |||
411 | // alias for internal type double |
||
412 | ['float', '0.1'], |
||
413 | ['float', '1.2'], |
||
414 | ['float', '123.456'], |
||
415 | |||
416 | // string type |
||
417 | ['string', '"String Value"'], |
||
418 | ['string', '"true"'], |
||
419 | ['string', '"123"'], |
||
420 | |||
421 | // array type |
||
422 | ['array', '{@AnnotationExtendsAnnotationTargetAll}'], |
||
423 | ['array', '{@AnnotationExtendsAnnotationTargetAll,@AnnotationExtendsAnnotationTargetAll}'], |
||
424 | |||
425 | ['arrayOfIntegers', '1'], |
||
426 | ['arrayOfIntegers', '{1}'], |
||
427 | ['arrayOfIntegers', '{1,2,3,4}'], |
||
428 | ['arrayOfAnnotations', '@AnnotationExtendsAnnotationTargetAll'], |
||
429 | ['arrayOfAnnotations', '{@Doctrine\Tests\Annotations\Fixtures\AnnotationTargetAll}'], |
||
430 | ['arrayOfAnnotations', '{@AnnotationExtendsAnnotationTargetAll, @Doctrine\Tests\Annotations\Fixtures\AnnotationTargetAll}'], |
||
431 | |||
432 | // annotation instance |
||
433 | ['annotation', '@Doctrine\Tests\Annotations\Fixtures\AnnotationTargetAll'], |
||
434 | ['annotation', '@AnnotationExtendsAnnotationTargetAll'], |
||
435 | ]; |
||
436 | } |
||
437 | |||
438 | public function getAnnotationVarTypeProviderInvalid() |
||
439 | { |
||
440 | //({attribute name}, {type declared type}, {attribute value} , {given type or class}) |
||
441 | return [ |
||
442 | // boolean type |
||
443 | ['boolean','boolean','1','integer'], |
||
444 | ['boolean','boolean','1.2','double'], |
||
445 | ['boolean','boolean','"str"','string'], |
||
446 | ['boolean','boolean','{1,2,3}','array'], |
||
447 | ['boolean','boolean','@Name', 'an instance of Doctrine\Tests\Annotations\Name'], |
||
448 | |||
449 | // alias for internal type boolean |
||
450 | ['bool','bool', '1','integer'], |
||
451 | ['bool','bool', '1.2','double'], |
||
452 | ['bool','bool', '"str"','string'], |
||
453 | ['bool','bool', '{"str"}','array'], |
||
454 | |||
455 | // integer type |
||
456 | ['integer','integer', 'true','boolean'], |
||
457 | ['integer','integer', 'false','boolean'], |
||
458 | ['integer','integer', '1.2','double'], |
||
459 | ['integer','integer', '"str"','string'], |
||
460 | ['integer','integer', '{"str"}','array'], |
||
461 | ['integer','integer', '{1,2,3,4}','array'], |
||
462 | |||
463 | // alias for internal type double |
||
464 | ['float','float', 'true','boolean'], |
||
465 | ['float','float', 'false','boolean'], |
||
466 | ['float','float', '123','integer'], |
||
467 | ['float','float', '"str"','string'], |
||
468 | ['float','float', '{"str"}','array'], |
||
469 | ['float','float', '{12.34}','array'], |
||
470 | ['float','float', '{1,2,3}','array'], |
||
471 | |||
472 | // string type |
||
473 | ['string','string', 'true','boolean'], |
||
474 | ['string','string', 'false','boolean'], |
||
475 | ['string','string', '12','integer'], |
||
476 | ['string','string', '1.2','double'], |
||
477 | ['string','string', '{"str"}','array'], |
||
478 | ['string','string', '{1,2,3,4}','array'], |
||
479 | |||
480 | // annotation instance |
||
481 | ['annotation', AnnotationTargetAll::class, 'true','boolean'], |
||
482 | ['annotation', AnnotationTargetAll::class, 'false','boolean'], |
||
483 | ['annotation', AnnotationTargetAll::class, '12','integer'], |
||
484 | ['annotation', AnnotationTargetAll::class, '1.2','double'], |
||
485 | ['annotation', AnnotationTargetAll::class, '{"str"}','array'], |
||
486 | ['annotation', AnnotationTargetAll::class, '{1,2,3,4}','array'], |
||
487 | ['annotation', AnnotationTargetAll::class, '@Name','an instance of Doctrine\Tests\Annotations\Name'], |
||
488 | ]; |
||
489 | } |
||
490 | |||
491 | public function getAnnotationVarTypeArrayProviderInvalid() |
||
492 | { |
||
493 | //({attribute name}, {type declared type}, {attribute value} , {given type or class}) |
||
494 | return [ |
||
495 | ['arrayOfIntegers', 'integer', 'true', 'boolean'], |
||
496 | ['arrayOfIntegers', 'integer', 'false', 'boolean'], |
||
497 | ['arrayOfIntegers', 'integer', '{true,true}', 'boolean'], |
||
498 | ['arrayOfIntegers', 'integer', '{1,true}', 'boolean'], |
||
499 | ['arrayOfIntegers', 'integer', '{1,2,1.2}', 'double'], |
||
500 | ['arrayOfIntegers', 'integer', '{1,2,"str"}', 'string'], |
||
501 | |||
502 | ['arrayOfStrings', 'string', 'true', 'boolean'], |
||
503 | ['arrayOfStrings', 'string', 'false', 'boolean'], |
||
504 | ['arrayOfStrings', 'string', '{true,true}', 'boolean'], |
||
505 | ['arrayOfStrings', 'string', '{"foo",true}', 'boolean'], |
||
506 | ['arrayOfStrings', 'string', '{"foo","bar",1.2}', 'double'], |
||
507 | ['arrayOfStrings', 'string', '1', 'integer'], |
||
508 | |||
509 | ['arrayOfAnnotations', AnnotationTargetAll::class, 'true', 'boolean'], |
||
510 | ['arrayOfAnnotations', AnnotationTargetAll::class, 'false', 'boolean'], |
||
511 | ['arrayOfAnnotations', AnnotationTargetAll::class, '{@Doctrine\Tests\Annotations\Fixtures\AnnotationTargetAll,true}', 'boolean'], |
||
512 | ['arrayOfAnnotations', AnnotationTargetAll::class, '{@Doctrine\Tests\Annotations\Fixtures\AnnotationTargetAll,true}', 'boolean'], |
||
513 | ['arrayOfAnnotations', AnnotationTargetAll::class, '{@Doctrine\Tests\Annotations\Fixtures\AnnotationTargetAll,1.2}', 'double'], |
||
514 | ['arrayOfAnnotations', AnnotationTargetAll::class, '{@Doctrine\Tests\Annotations\Fixtures\AnnotationTargetAll,@AnnotationExtendsAnnotationTargetAll,"str"}', 'string'], |
||
515 | ]; |
||
516 | } |
||
517 | |||
518 | /** |
||
519 | * @dataProvider getAnnotationVarTypeProviderValid |
||
520 | */ |
||
521 | public function testAnnotationWithVarType($attribute, $value) |
||
522 | { |
||
523 | $parser = $this->createTestParser(); |
||
524 | $context = 'property SomeClassName::$invalidProperty.'; |
||
525 | $docblock = sprintf('@Doctrine\Tests\Annotations\Fixtures\AnnotationWithVarType(%s = %s)',$attribute, $value); |
||
526 | $parser->setTarget(Target::TARGET_PROPERTY); |
||
527 | |||
528 | $result = $parser->parse($docblock, $context); |
||
529 | |||
530 | self::assertCount(1, $result); |
||
531 | self::assertInstanceOf(Fixtures\AnnotationWithVarType::class, $result[0]); |
||
532 | self::assertNotNull($result[0]->$attribute); |
||
533 | } |
||
534 | |||
535 | /** |
||
536 | * @dataProvider getAnnotationVarTypeProviderInvalid |
||
537 | */ |
||
538 | public function testAnnotationWithVarTypeError($attribute,$type,$value,$given) |
||
539 | { |
||
540 | $parser = $this->createTestParser(); |
||
541 | $context = 'property SomeClassName::invalidProperty.'; |
||
542 | $docblock = sprintf('@Doctrine\Tests\Annotations\Fixtures\AnnotationWithVarType(%s = %s)',$attribute, $value); |
||
543 | $parser->setTarget(Target::TARGET_PROPERTY); |
||
544 | |||
545 | try { |
||
546 | $parser->parse($docblock, $context); |
||
547 | $this->fail(); |
||
548 | } catch (AnnotationException $exc) { |
||
549 | self::assertStringMatchesFormat( |
||
550 | '[Type Error] Attribute "' . $attribute . '" of @Doctrine\Tests\Annotations\Fixtures\AnnotationWithVarType declared on property SomeClassName::invalidProperty. expects a(n) %A' . $type . ', but got ' . $given . '.', |
||
551 | $exc->getMessage() |
||
552 | ); |
||
553 | } |
||
554 | } |
||
555 | |||
556 | |||
557 | /** |
||
558 | * @dataProvider getAnnotationVarTypeArrayProviderInvalid |
||
559 | */ |
||
560 | public function testAnnotationWithVarTypeArrayError($attribute,$type,$value,$given) |
||
561 | { |
||
562 | $parser = $this->createTestParser(); |
||
563 | $context = 'property SomeClassName::invalidProperty.'; |
||
564 | $docblock = sprintf('@Doctrine\Tests\Annotations\Fixtures\AnnotationWithVarType(%s = %s)',$attribute, $value); |
||
565 | $parser->setTarget(Target::TARGET_PROPERTY); |
||
566 | |||
567 | try { |
||
568 | $parser->parse($docblock, $context); |
||
569 | $this->fail(); |
||
570 | } catch (AnnotationException $exc) { |
||
571 | self::assertStringMatchesFormat( |
||
572 | '[Type Error] Attribute "' . $attribute . '" of @Doctrine\Tests\Annotations\Fixtures\AnnotationWithVarType declared on property SomeClassName::invalidProperty. expects either a(n) %A' . $type . ', or an array of %A' . $type . 's, but got ' . $given . '.', |
||
573 | $exc->getMessage() |
||
574 | ); |
||
575 | } |
||
576 | } |
||
577 | |||
578 | /** |
||
579 | * @dataProvider getAnnotationVarTypeProviderValid |
||
580 | */ |
||
581 | public function testAnnotationWithAttributes($attribute, $value) |
||
582 | { |
||
583 | $parser = $this->createTestParser(); |
||
584 | $context = 'property SomeClassName::$invalidProperty.'; |
||
585 | $docblock = sprintf('@Doctrine\Tests\Annotations\Fixtures\AnnotationWithAttributes(%s = %s)',$attribute, $value); |
||
586 | $parser->setTarget(Target::TARGET_PROPERTY); |
||
587 | |||
588 | $result = $parser->parse($docblock, $context); |
||
589 | |||
590 | self::assertCount(1, $result); |
||
591 | self::assertInstanceOf(Fixtures\AnnotationWithAttributes::class, $result[0]); |
||
592 | $getter = 'get' .ucfirst($attribute); |
||
593 | self::assertNotNull($result[0]->$getter()); |
||
594 | } |
||
595 | |||
596 | /** |
||
597 | * @dataProvider getAnnotationVarTypeProviderInvalid |
||
598 | */ |
||
599 | public function testAnnotationWithAttributesError($attribute,$type,$value,$given) |
||
600 | { |
||
601 | $parser = $this->createTestParser(); |
||
602 | $context = 'property SomeClassName::invalidProperty.'; |
||
603 | $docblock = sprintf('@Doctrine\Tests\Annotations\Fixtures\AnnotationWithAttributes(%s = %s)',$attribute, $value); |
||
604 | $parser->setTarget(Target::TARGET_PROPERTY); |
||
605 | |||
606 | try { |
||
607 | $parser->parse($docblock, $context); |
||
608 | $this->fail(); |
||
609 | } catch (AnnotationException $exc) { |
||
610 | self::assertContains("[Type Error] Attribute \"$attribute\" of @Doctrine\Tests\Annotations\Fixtures\AnnotationWithAttributes declared on property SomeClassName::invalidProperty. expects a(n) $type, but got $given.", $exc->getMessage()); |
||
611 | } |
||
612 | } |
||
613 | |||
614 | |||
615 | /** |
||
616 | * @dataProvider getAnnotationVarTypeArrayProviderInvalid |
||
617 | */ |
||
618 | public function testAnnotationWithAttributesWithVarTypeArrayError($attribute,$type,$value,$given) |
||
619 | { |
||
620 | $parser = $this->createTestParser(); |
||
621 | $context = 'property SomeClassName::invalidProperty.'; |
||
622 | $docblock = sprintf('@Doctrine\Tests\Annotations\Fixtures\AnnotationWithAttributes(%s = %s)',$attribute, $value); |
||
623 | $parser->setTarget(Target::TARGET_PROPERTY); |
||
624 | |||
625 | try { |
||
626 | $parser->parse($docblock, $context); |
||
627 | $this->fail(); |
||
628 | } catch (AnnotationException $exc) { |
||
629 | self::assertContains("[Type Error] Attribute \"$attribute\" of @Doctrine\Tests\Annotations\Fixtures\AnnotationWithAttributes declared on property SomeClassName::invalidProperty. expects either a(n) $type, or an array of {$type}s, but got $given.", $exc->getMessage()); |
||
630 | } |
||
631 | } |
||
632 | |||
633 | public function testAnnotationWithRequiredAttributes() |
||
634 | { |
||
635 | $parser = $this->createTestParser(); |
||
636 | $context = 'property SomeClassName::invalidProperty.'; |
||
637 | $parser->setTarget(Target::TARGET_PROPERTY); |
||
638 | |||
639 | |||
640 | $docblock = '@Doctrine\Tests\Annotations\Fixtures\AnnotationWithRequiredAttributes("Some Value", annot = @Doctrine\Tests\Annotations\Fixtures\AnnotationTargetAnnotation)'; |
||
641 | $result = $parser->parse($docblock); |
||
642 | |||
643 | self::assertCount(1, $result); |
||
644 | |||
645 | /* @var $annotation Fixtures\AnnotationWithRequiredAttributes */ |
||
646 | $annotation = $result[0]; |
||
647 | |||
648 | self::assertInstanceOf(Fixtures\AnnotationWithRequiredAttributes::class, $annotation); |
||
649 | self::assertEquals('Some Value', $annotation->getValue()); |
||
650 | self::assertInstanceOf(Fixtures\AnnotationTargetAnnotation::class, $annotation->getAnnot()); |
||
651 | |||
652 | |||
653 | $docblock = '@Doctrine\Tests\Annotations\Fixtures\AnnotationWithRequiredAttributes("Some Value")'; |
||
654 | try { |
||
655 | $parser->parse($docblock, $context); |
||
656 | $this->fail(); |
||
657 | } catch (AnnotationException $exc) { |
||
658 | self::assertContains('Attribute "annot" of @Doctrine\Tests\Annotations\Fixtures\AnnotationWithRequiredAttributes declared on property SomeClassName::invalidProperty. expects a(n) Doctrine\Tests\Annotations\Fixtures\AnnotationTargetAnnotation. This value should not be null.', $exc->getMessage()); |
||
659 | } |
||
660 | |||
661 | $docblock = '@Doctrine\Tests\Annotations\Fixtures\AnnotationWithRequiredAttributes(annot = @Doctrine\Tests\Annotations\Fixtures\AnnotationTargetAnnotation)'; |
||
662 | try { |
||
663 | $parser->parse($docblock, $context); |
||
664 | $this->fail(); |
||
665 | } catch (AnnotationException $exc) { |
||
666 | self::assertContains('Attribute "value" of @Doctrine\Tests\Annotations\Fixtures\AnnotationWithRequiredAttributes declared on property SomeClassName::invalidProperty. expects a(n) string. This value should not be null.', $exc->getMessage()); |
||
667 | } |
||
668 | |||
669 | } |
||
670 | |||
671 | public function testAnnotationWithRequiredAttributesWithoutConstructor() |
||
672 | { |
||
673 | $parser = $this->createTestParser(); |
||
674 | $context = 'property SomeClassName::invalidProperty.'; |
||
675 | $parser->setTarget(Target::TARGET_PROPERTY); |
||
676 | |||
677 | |||
678 | $docblock = '@Doctrine\Tests\Annotations\Fixtures\AnnotationWithRequiredAttributesWithoutConstructor("Some Value", annot = @Doctrine\Tests\Annotations\Fixtures\AnnotationTargetAnnotation)'; |
||
679 | $result = $parser->parse($docblock); |
||
680 | |||
681 | self::assertCount(1, $result); |
||
682 | self::assertInstanceOf(Fixtures\AnnotationWithRequiredAttributesWithoutConstructor::class, $result[0]); |
||
683 | self::assertEquals('Some Value', $result[0]->value); |
||
684 | self::assertInstanceOf(Fixtures\AnnotationTargetAnnotation::class, $result[0]->annot); |
||
685 | |||
686 | |||
687 | $docblock = '@Doctrine\Tests\Annotations\Fixtures\AnnotationWithRequiredAttributesWithoutConstructor("Some Value")'; |
||
688 | try { |
||
689 | $parser->parse($docblock, $context); |
||
690 | $this->fail(); |
||
691 | } catch (AnnotationException $exc) { |
||
692 | self::assertContains('Attribute "annot" of @Doctrine\Tests\Annotations\Fixtures\AnnotationWithRequiredAttributesWithoutConstructor declared on property SomeClassName::invalidProperty. expects a(n) \Doctrine\Tests\Annotations\Fixtures\AnnotationTargetAnnotation. This value should not be null.', $exc->getMessage()); |
||
693 | } |
||
694 | |||
695 | $docblock = '@Doctrine\Tests\Annotations\Fixtures\AnnotationWithRequiredAttributesWithoutConstructor(annot = @Doctrine\Tests\Annotations\Fixtures\AnnotationTargetAnnotation)'; |
||
696 | try { |
||
697 | $parser->parse($docblock, $context); |
||
698 | $this->fail(); |
||
699 | } catch (AnnotationException $exc) { |
||
700 | self::assertContains('Attribute "value" of @Doctrine\Tests\Annotations\Fixtures\AnnotationWithRequiredAttributesWithoutConstructor declared on property SomeClassName::invalidProperty. expects a(n) string. This value should not be null.', $exc->getMessage()); |
||
701 | } |
||
702 | |||
703 | } |
||
704 | |||
705 | /** |
||
706 | * @expectedException \Doctrine\Annotations\AnnotationException |
||
707 | * @expectedExceptionMessage Attribute "value" of @Doctrine\Tests\Annotations\Fixtures\AnnotationEnum declared on property SomeClassName::invalidProperty. accept only [ONE, TWO, THREE], but got FOUR. |
||
708 | */ |
||
709 | public function testAnnotationEnumeratorException() |
||
710 | { |
||
711 | $parser = $this->createTestParser(); |
||
712 | $context = 'property SomeClassName::invalidProperty.'; |
||
713 | $docblock = '@Doctrine\Tests\Annotations\Fixtures\AnnotationEnum("FOUR")'; |
||
714 | |||
715 | $parser->setIgnoreNotImportedAnnotations(false); |
||
716 | $parser->setTarget(Target::TARGET_PROPERTY); |
||
717 | $parser->parse($docblock, $context); |
||
718 | } |
||
719 | |||
720 | /** |
||
721 | * @expectedException \Doctrine\Annotations\AnnotationException |
||
722 | * @expectedExceptionMessage Attribute "value" of @Doctrine\Tests\Annotations\Fixtures\AnnotationEnumLiteral declared on property SomeClassName::invalidProperty. accept only [AnnotationEnumLiteral::ONE, AnnotationEnumLiteral::TWO, AnnotationEnumLiteral::THREE], but got 4. |
||
723 | */ |
||
724 | public function testAnnotationEnumeratorLiteralException() |
||
725 | { |
||
726 | $parser = $this->createTestParser(); |
||
727 | $context = 'property SomeClassName::invalidProperty.'; |
||
728 | $docblock = '@Doctrine\Tests\Annotations\Fixtures\AnnotationEnumLiteral(4)'; |
||
729 | |||
730 | $parser->setIgnoreNotImportedAnnotations(false); |
||
731 | $parser->setTarget(Target::TARGET_PROPERTY); |
||
732 | $parser->parse($docblock, $context); |
||
733 | } |
||
734 | |||
735 | /** |
||
736 | * @expectedException \InvalidArgumentException |
||
737 | * @expectedExceptionMessage @Enum supports only scalar values "array" given. |
||
738 | */ |
||
739 | public function testAnnotationEnumInvalidTypeDeclarationException() |
||
740 | { |
||
741 | $parser = $this->createTestParser(); |
||
742 | $docblock = '@Doctrine\Tests\Annotations\Fixtures\AnnotationEnumInvalid("foo")'; |
||
743 | |||
744 | $parser->setIgnoreNotImportedAnnotations(false); |
||
745 | $parser->parse($docblock); |
||
746 | } |
||
747 | |||
748 | /** |
||
749 | * @expectedException \InvalidArgumentException |
||
750 | * @expectedExceptionMessage Undefined enumerator value "3" for literal "AnnotationEnumLiteral::THREE". |
||
751 | */ |
||
752 | public function testAnnotationEnumInvalidLiteralDeclarationException() |
||
753 | { |
||
754 | $parser = $this->createTestParser(); |
||
755 | $docblock = '@Doctrine\Tests\Annotations\Fixtures\AnnotationEnumLiteralInvalid("foo")'; |
||
756 | |||
757 | $parser->setIgnoreNotImportedAnnotations(false); |
||
758 | $parser->parse($docblock); |
||
759 | } |
||
760 | |||
761 | public function getConstantsProvider() |
||
762 | { |
||
763 | $provider[] = [ |
||
764 | '@AnnotationWithConstants(PHP_EOL)', |
||
765 | PHP_EOL |
||
766 | ]; |
||
767 | $provider[] = [ |
||
768 | '@AnnotationWithConstants(AnnotationWithConstants::INTEGER)', |
||
769 | AnnotationWithConstants::INTEGER |
||
770 | ]; |
||
771 | $provider[] = [ |
||
772 | '@Doctrine\Tests\Annotations\Fixtures\AnnotationWithConstants(AnnotationWithConstants::STRING)', |
||
773 | AnnotationWithConstants::STRING |
||
774 | ]; |
||
775 | $provider[] = [ |
||
776 | '@AnnotationWithConstants(Doctrine\Tests\Annotations\Fixtures\AnnotationWithConstants::FLOAT)', |
||
777 | AnnotationWithConstants::FLOAT |
||
778 | ]; |
||
779 | $provider[] = [ |
||
780 | '@AnnotationWithConstants(ClassWithConstants::SOME_VALUE)', |
||
781 | ClassWithConstants::SOME_VALUE |
||
782 | ]; |
||
783 | $provider[] = [ |
||
784 | '@AnnotationWithConstants(ClassWithConstants::OTHER_KEY_)', |
||
785 | ClassWithConstants::OTHER_KEY_ |
||
786 | ]; |
||
787 | $provider[] = [ |
||
788 | '@AnnotationWithConstants(ClassWithConstants::OTHER_KEY_2)', |
||
789 | ClassWithConstants::OTHER_KEY_2 |
||
790 | ]; |
||
791 | $provider[] = [ |
||
792 | '@AnnotationWithConstants(Doctrine\Tests\Annotations\Fixtures\ClassWithConstants::SOME_VALUE)', |
||
793 | ClassWithConstants::SOME_VALUE |
||
794 | ]; |
||
795 | $provider[] = [ |
||
796 | '@AnnotationWithConstants(InterfaceWithConstants::SOME_VALUE)', |
||
797 | InterfaceWithConstants::SOME_VALUE |
||
798 | ]; |
||
799 | $provider[] = [ |
||
800 | '@AnnotationWithConstants(\Doctrine\Tests\Annotations\Fixtures\InterfaceWithConstants::SOME_VALUE)', |
||
801 | InterfaceWithConstants::SOME_VALUE |
||
802 | ]; |
||
803 | $provider[] = [ |
||
804 | '@AnnotationWithConstants({AnnotationWithConstants::STRING, AnnotationWithConstants::INTEGER, AnnotationWithConstants::FLOAT})', |
||
805 | [AnnotationWithConstants::STRING, AnnotationWithConstants::INTEGER, AnnotationWithConstants::FLOAT] |
||
806 | ]; |
||
807 | $provider[] = [ |
||
808 | '@AnnotationWithConstants({ |
||
809 | AnnotationWithConstants::STRING = AnnotationWithConstants::INTEGER |
||
810 | })', |
||
811 | [AnnotationWithConstants::STRING => AnnotationWithConstants::INTEGER] |
||
812 | ]; |
||
813 | $provider[] = [ |
||
814 | '@AnnotationWithConstants({ |
||
815 | Doctrine\Tests\Annotations\Fixtures\InterfaceWithConstants::SOME_KEY = AnnotationWithConstants::INTEGER |
||
816 | })', |
||
817 | [InterfaceWithConstants::SOME_KEY => AnnotationWithConstants::INTEGER] |
||
818 | ]; |
||
819 | $provider[] = [ |
||
820 | '@AnnotationWithConstants({ |
||
821 | \Doctrine\Tests\Annotations\Fixtures\InterfaceWithConstants::SOME_KEY = AnnotationWithConstants::INTEGER |
||
822 | })', |
||
823 | [InterfaceWithConstants::SOME_KEY => AnnotationWithConstants::INTEGER] |
||
824 | ]; |
||
825 | $provider[] = [ |
||
826 | '@AnnotationWithConstants({ |
||
827 | AnnotationWithConstants::STRING = AnnotationWithConstants::INTEGER, |
||
828 | ClassWithConstants::SOME_KEY = ClassWithConstants::SOME_VALUE, |
||
829 | Doctrine\Tests\Annotations\Fixtures\ClassWithConstants::SOME_KEY = InterfaceWithConstants::SOME_VALUE |
||
830 | })', |
||
831 | [ |
||
832 | AnnotationWithConstants::STRING => AnnotationWithConstants::INTEGER, |
||
833 | ClassWithConstants::SOME_KEY => ClassWithConstants::SOME_VALUE, |
||
834 | ClassWithConstants::SOME_KEY => InterfaceWithConstants::SOME_VALUE |
||
835 | ] |
||
836 | ]; |
||
837 | $provider[] = [ |
||
838 | '@AnnotationWithConstants(AnnotationWithConstants::class)', |
||
839 | AnnotationWithConstants::class |
||
840 | ]; |
||
841 | $provider[] = [ |
||
842 | '@AnnotationWithConstants({AnnotationWithConstants::class = AnnotationWithConstants::class})', |
||
843 | [AnnotationWithConstants::class => AnnotationWithConstants::class] |
||
844 | ]; |
||
845 | $provider[] = [ |
||
846 | '@AnnotationWithConstants(Doctrine\Tests\Annotations\Fixtures\AnnotationWithConstants::class)', |
||
847 | AnnotationWithConstants::class |
||
848 | ]; |
||
849 | $provider[] = [ |
||
850 | '@Doctrine\Tests\Annotations\Fixtures\AnnotationWithConstants(Doctrine\Tests\Annotations\Fixtures\AnnotationWithConstants::class)', |
||
851 | AnnotationWithConstants::class |
||
852 | ]; |
||
853 | return $provider; |
||
854 | } |
||
855 | |||
856 | /** |
||
857 | * @dataProvider getConstantsProvider |
||
858 | */ |
||
859 | public function testSupportClassConstants($docblock, $expected) |
||
860 | { |
||
861 | $parser = $this->createTestParser(); |
||
862 | $parser->setImports([ |
||
863 | 'classwithconstants' => ClassWithConstants::class, |
||
864 | 'interfacewithconstants' => InterfaceWithConstants::class, |
||
865 | 'annotationwithconstants' => AnnotationWithConstants::class |
||
866 | ]); |
||
867 | |||
868 | $result = $parser->parse($docblock); |
||
869 | self::assertInstanceOf(AnnotationWithConstants::class, $annotation = $result[0]); |
||
870 | self::assertEquals($expected, $annotation->value); |
||
871 | } |
||
872 | |||
873 | /** |
||
874 | * @expectedException \Doctrine\Annotations\AnnotationException |
||
875 | * @expectedExceptionMessage The annotation @SomeAnnotationClassNameWithoutConstructorAndProperties declared on does not accept any values, but got {"value":"Foo"}. |
||
876 | */ |
||
877 | public function testWithoutConstructorWhenIsNotDefaultValue() |
||
878 | { |
||
879 | $parser = $this->createTestParser(); |
||
880 | $docblock = <<<DOCBLOCK |
||
881 | /** |
||
882 | * @SomeAnnotationClassNameWithoutConstructorAndProperties("Foo") |
||
883 | */ |
||
884 | DOCBLOCK; |
||
885 | |||
886 | |||
887 | $parser->setTarget(Target::TARGET_CLASS); |
||
888 | $parser->parse($docblock); |
||
889 | } |
||
890 | |||
891 | /** |
||
892 | * @expectedException \Doctrine\Annotations\AnnotationException |
||
893 | * @expectedExceptionMessage The annotation @SomeAnnotationClassNameWithoutConstructorAndProperties declared on does not accept any values, but got {"value":"Foo"}. |
||
894 | */ |
||
895 | public function testWithoutConstructorWhenHasNoProperties() |
||
896 | { |
||
897 | $parser = $this->createTestParser(); |
||
898 | $docblock = <<<DOCBLOCK |
||
899 | /** |
||
900 | * @SomeAnnotationClassNameWithoutConstructorAndProperties(value = "Foo") |
||
901 | */ |
||
902 | DOCBLOCK; |
||
903 | |||
904 | $parser->setTarget(Target::TARGET_CLASS); |
||
905 | $parser->parse($docblock); |
||
906 | } |
||
907 | |||
908 | /** |
||
909 | * @expectedException \Doctrine\Annotations\AnnotationException |
||
910 | * @expectedExceptionMessage Expected namespace separator or identifier, got ')' at position 24 in class @Doctrine\Tests\Annotations\Fixtures\AnnotationWithTargetSyntaxError. |
||
911 | */ |
||
912 | public function testAnnotationTargetSyntaxError() |
||
913 | { |
||
914 | $parser = $this->createTestParser(); |
||
915 | $context = 'class ' . 'SomeClassName'; |
||
916 | $docblock = <<<DOCBLOCK |
||
917 | /** |
||
918 | * @Doctrine\Tests\Annotations\Fixtures\AnnotationWithTargetSyntaxError() |
||
919 | */ |
||
920 | DOCBLOCK; |
||
921 | |||
922 | $parser->setTarget(Target::TARGET_CLASS); |
||
923 | $parser->parse($docblock, $context); |
||
924 | } |
||
925 | |||
926 | /** |
||
927 | * @expectedException \InvalidArgumentException |
||
928 | * @expectedExceptionMessage Invalid Target "Foo". Available targets: [ALL, CLASS, METHOD, PROPERTY, ANNOTATION] |
||
929 | */ |
||
930 | public function testAnnotationWithInvalidTargetDeclarationError() |
||
931 | { |
||
932 | $parser = $this->createTestParser(); |
||
933 | $context = 'class ' . 'SomeClassName'; |
||
934 | $docblock = <<<DOCBLOCK |
||
935 | /** |
||
936 | * @AnnotationWithInvalidTargetDeclaration() |
||
937 | */ |
||
938 | DOCBLOCK; |
||
939 | |||
940 | $parser->setTarget(Target::TARGET_CLASS); |
||
941 | $parser->parse($docblock, $context); |
||
942 | } |
||
943 | |||
944 | /** |
||
945 | * @expectedException \InvalidArgumentException |
||
946 | * @expectedExceptionMessage @Target expects either a string value, or an array of strings, "NULL" given. |
||
947 | */ |
||
948 | public function testAnnotationWithTargetEmptyError() |
||
949 | { |
||
950 | $parser = $this->createTestParser(); |
||
951 | $context = 'class ' . 'SomeClassName'; |
||
952 | $docblock = <<<DOCBLOCK |
||
953 | /** |
||
954 | * @AnnotationWithTargetEmpty() |
||
955 | */ |
||
956 | DOCBLOCK; |
||
957 | |||
958 | $parser->setTarget(Target::TARGET_CLASS); |
||
959 | $parser->parse($docblock, $context); |
||
960 | } |
||
961 | |||
962 | /** |
||
963 | * @group DDC-575 |
||
964 | */ |
||
965 | public function testRegressionDDC575() |
||
966 | { |
||
967 | $parser = $this->createTestParser(); |
||
968 | |||
969 | $docblock = <<<DOCBLOCK |
||
970 | /** |
||
971 | * @Name |
||
972 | * |
||
973 | * Will trigger error. |
||
974 | */ |
||
975 | DOCBLOCK; |
||
976 | |||
977 | $result = $parser->parse($docblock); |
||
978 | |||
979 | self::assertInstanceOf(Name::class, $result[0]); |
||
980 | |||
981 | $docblock = <<<DOCBLOCK |
||
982 | /** |
||
983 | * @Name |
||
984 | * @Marker |
||
985 | * |
||
986 | * Will trigger error. |
||
987 | */ |
||
988 | DOCBLOCK; |
||
989 | |||
990 | $result = $parser->parse($docblock); |
||
991 | |||
992 | self::assertInstanceOf(Name::class, $result[0]); |
||
993 | } |
||
994 | |||
995 | /** |
||
996 | * @group DDC-77 |
||
997 | */ |
||
998 | public function testAnnotationWithoutClassIsIgnoredWithoutWarning() |
||
999 | { |
||
1000 | $parser = new DocParser(); |
||
1001 | $parser->setIgnoreNotImportedAnnotations(true); |
||
1002 | $result = $parser->parse('@param'); |
||
1003 | |||
1004 | self::assertEmpty($result); |
||
1005 | } |
||
1006 | |||
1007 | /** |
||
1008 | * Tests if it's possible to ignore whole namespaces |
||
1009 | * |
||
1010 | * @param string $ignoreAnnotationName annotation/namespace to ignore |
||
1011 | * @param string $input annotation/namespace from the docblock |
||
1012 | * |
||
1013 | * @return void |
||
1014 | * |
||
1015 | * @dataProvider provideTestIgnoreWholeNamespaces |
||
1016 | * @group 45 |
||
1017 | */ |
||
1018 | public function testIgnoreWholeNamespaces($ignoreAnnotationName, $input) |
||
1019 | { |
||
1020 | $parser = new DocParser(); |
||
1021 | $parser->setIgnoredAnnotationNamespaces([$ignoreAnnotationName => true]); |
||
1022 | $result = $parser->parse($input); |
||
1023 | |||
1024 | self::assertEmpty($result); |
||
1025 | } |
||
1026 | |||
1027 | public function provideTestIgnoreWholeNamespaces() |
||
1028 | { |
||
1029 | return [ |
||
1030 | ['Namespace', '@Namespace'], |
||
1031 | ['Namespace\\', '@Namespace'], |
||
1032 | |||
1033 | ['Namespace', '@Namespace\Subnamespace'], |
||
1034 | ['Namespace\\', '@Namespace\Subnamespace'], |
||
1035 | |||
1036 | ['Namespace', '@Namespace\Subnamespace\SubSubNamespace'], |
||
1037 | ['Namespace\\', '@Namespace\Subnamespace\SubSubNamespace'], |
||
1038 | |||
1039 | ['Namespace\Subnamespace', '@Namespace\Subnamespace'], |
||
1040 | ['Namespace\Subnamespace\\', '@Namespace\Subnamespace'], |
||
1041 | |||
1042 | ['Namespace\Subnamespace', '@Namespace\Subnamespace\SubSubNamespace'], |
||
1043 | ['Namespace\Subnamespace\\', '@Namespace\Subnamespace\SubSubNamespace'], |
||
1044 | |||
1045 | ['Namespace\Subnamespace\SubSubNamespace', '@Namespace\Subnamespace\SubSubNamespace'], |
||
1046 | ['Namespace\Subnamespace\SubSubNamespace\\', '@Namespace\Subnamespace\SubSubNamespace'], |
||
1047 | ]; |
||
1048 | } |
||
1049 | |||
1050 | /** |
||
1051 | * @group DCOM-168 |
||
1052 | */ |
||
1053 | public function testNotAnAnnotationClassIsIgnoredWithoutWarning() |
||
1054 | { |
||
1055 | $parser = new DocParser(); |
||
1056 | $parser->setIgnoreNotImportedAnnotations(true); |
||
1057 | $parser->setIgnoredAnnotationNames([\PHPUnit\Framework\TestCase::class => true]); |
||
1058 | $result = $parser->parse('@\PHPUnit\Framework\TestCase'); |
||
1059 | |||
1060 | self::assertEmpty($result); |
||
1061 | } |
||
1062 | |||
1063 | public function testNotAnAnnotationClassIsIgnoredWithoutWarningWithoutCheating() |
||
1064 | { |
||
1065 | $parser = new DocParser(); |
||
1066 | $parser->setIgnoreNotImportedAnnotations(true); |
||
1067 | $result = $parser->parse('@\PHPUnit\Framework\TestCase'); |
||
1068 | |||
1069 | self::assertEmpty($result); |
||
1070 | } |
||
1071 | |||
1072 | /** |
||
1073 | * @expectedException \Doctrine\Annotations\AnnotationException |
||
1074 | * @expectedExceptionMessage Expected PlainValue, got ''' at position 10. |
||
1075 | */ |
||
1076 | public function testAnnotationDontAcceptSingleQuotes() |
||
1077 | { |
||
1078 | $parser = $this->createTestParser(); |
||
1079 | $parser->parse("@Name(foo='bar')"); |
||
1080 | } |
||
1081 | |||
1082 | /** |
||
1083 | * @group DCOM-41 |
||
1084 | */ |
||
1085 | public function testAnnotationDoesntThrowExceptionWhenAtSignIsNotFollowedByIdentifier() |
||
1086 | { |
||
1087 | $parser = new DocParser(); |
||
1088 | $result = $parser->parse("'@'"); |
||
1089 | |||
1090 | self::assertEmpty($result); |
||
1091 | } |
||
1092 | |||
1093 | /** |
||
1094 | * @group DCOM-41 |
||
1095 | * @expectedException \Doctrine\Annotations\AnnotationException |
||
1096 | */ |
||
1097 | public function testAnnotationThrowsExceptionWhenAtSignIsNotFollowedByIdentifierInNestedAnnotation() |
||
1098 | { |
||
1099 | $parser = new DocParser(); |
||
1100 | $parser->parse("@Doctrine\Tests\Annotations\Name(@')"); |
||
1101 | } |
||
1102 | |||
1103 | /** |
||
1104 | * @group DCOM-56 |
||
1105 | */ |
||
1106 | public function testAutoloadAnnotation() |
||
1107 | { |
||
1108 | self::assertFalse(class_exists('Doctrine\Tests\Annotations\Fixture\Annotation\Autoload', false), 'Pre-condition: Doctrine\Tests\Annotations\Fixture\Annotation\Autoload not allowed to be loaded.'); |
||
1109 | |||
1110 | $parser = new DocParser(); |
||
1111 | |||
1112 | $parser->setImports([ |
||
1113 | 'autoload' => Fixtures\Annotation\Autoload::class, |
||
1114 | ]); |
||
1115 | $annotations = $parser->parse('@Autoload'); |
||
1116 | |||
1117 | self::assertCount(1, $annotations); |
||
1118 | self::assertInstanceOf(Fixtures\Annotation\Autoload::class, $annotations[0]); |
||
1119 | } |
||
1120 | |||
1121 | public function createTestParser() |
||
1122 | { |
||
1123 | $parser = new DocParser(); |
||
1124 | $parser->setIgnoreNotImportedAnnotations(true); |
||
1125 | $parser->setImports([ |
||
1126 | 'name' => Name::class, |
||
1127 | '__NAMESPACE__' => 'Doctrine\Tests\Annotations', |
||
1128 | ]); |
||
1129 | |||
1130 | return $parser; |
||
1131 | } |
||
1132 | |||
1133 | /** |
||
1134 | * @group DDC-78 |
||
1135 | * @expectedException \Doctrine\Annotations\AnnotationException |
||
1136 | * @expectedExceptionMessage Expected PlainValue, got ''' at position 10 in class \Doctrine\Tests\Annotations\Name |
||
1137 | */ |
||
1138 | public function testSyntaxErrorWithContextDescription() |
||
1139 | { |
||
1140 | $parser = $this->createTestParser(); |
||
1141 | $parser->parse("@Name(foo='bar')", "class \Doctrine\Tests\Annotations\Name"); |
||
1142 | } |
||
1143 | |||
1144 | /** |
||
1145 | * @group DDC-183 |
||
1146 | */ |
||
1147 | public function testSyntaxErrorWithUnknownCharacters() |
||
1148 | { |
||
1149 | $docblock = <<<DOCBLOCK |
||
1150 | /** |
||
1151 | * @test at. |
||
1152 | */ |
||
1153 | class A { |
||
1154 | } |
||
1155 | DOCBLOCK; |
||
1156 | |||
1157 | //$lexer = new \Doctrine\Annotations\Lexer(); |
||
1158 | //$lexer->setInput(trim($docblock, '/ *')); |
||
1159 | //var_dump($lexer); |
||
1160 | |||
1161 | try { |
||
1162 | $parser = $this->createTestParser(); |
||
1163 | self::assertEmpty($parser->parse($docblock)); |
||
1164 | } catch (AnnotationException $e) { |
||
1165 | $this->fail($e->getMessage()); |
||
1166 | } |
||
1167 | } |
||
1168 | |||
1169 | /** |
||
1170 | * @group DCOM-14 |
||
1171 | */ |
||
1172 | public function testIgnorePHPDocThrowTag() |
||
1173 | { |
||
1174 | $docblock = <<<DOCBLOCK |
||
1175 | /** |
||
1176 | * @throws \RuntimeException |
||
1177 | */ |
||
1178 | class A { |
||
1179 | } |
||
1180 | DOCBLOCK; |
||
1181 | |||
1182 | try { |
||
1183 | $parser = $this->createTestParser(); |
||
1184 | self::assertEmpty($parser->parse($docblock)); |
||
1185 | } catch (AnnotationException $e) { |
||
1186 | $this->fail($e->getMessage()); |
||
1187 | } |
||
1188 | } |
||
1189 | |||
1190 | /** |
||
1191 | * @group DCOM-38 |
||
1192 | */ |
||
1193 | public function testCastInt() |
||
1194 | { |
||
1195 | $parser = $this->createTestParser(); |
||
1196 | |||
1197 | $result = $parser->parse('@Name(foo=1234)'); |
||
1198 | $annot = $result[0]; |
||
1199 | self::assertInternalType('int', $annot->foo); |
||
1200 | } |
||
1201 | |||
1202 | /** |
||
1203 | * @group DCOM-38 |
||
1204 | */ |
||
1205 | public function testCastNegativeInt() |
||
1206 | { |
||
1207 | $parser = $this->createTestParser(); |
||
1208 | |||
1209 | $result = $parser->parse('@Name(foo=-1234)'); |
||
1210 | $annot = $result[0]; |
||
1211 | self::assertInternalType('int', $annot->foo); |
||
1212 | } |
||
1213 | |||
1214 | /** |
||
1215 | * @group DCOM-38 |
||
1216 | */ |
||
1217 | public function testCastFloat() |
||
1218 | { |
||
1219 | $parser = $this->createTestParser(); |
||
1220 | |||
1221 | $result = $parser->parse('@Name(foo=1234.345)'); |
||
1222 | $annot = $result[0]; |
||
1223 | self::assertInternalType('float', $annot->foo); |
||
1224 | } |
||
1225 | |||
1226 | /** |
||
1227 | * @group DCOM-38 |
||
1228 | */ |
||
1229 | public function testCastNegativeFloat() |
||
1230 | { |
||
1231 | $parser = $this->createTestParser(); |
||
1232 | |||
1233 | $result = $parser->parse('@Name(foo=-1234.345)'); |
||
1234 | $annot = $result[0]; |
||
1235 | self::assertInternalType('float', $annot->foo); |
||
1236 | |||
1237 | $result = $parser->parse('@Marker(-1234.345)'); |
||
1238 | $annot = $result[0]; |
||
1239 | self::assertInternalType('float', $annot->value); |
||
1240 | } |
||
1241 | |||
1242 | /** |
||
1243 | * @expectedException \Doctrine\Annotations\AnnotationException |
||
1244 | * @expectedExceptionMessage [Creation Error] The annotation @SomeAnnotationClassNameWithoutConstructor declared on some class does not have a property named "invalidaProperty". Available properties: data, name |
||
1245 | */ |
||
1246 | public function testSetValuesExeption() |
||
1247 | { |
||
1248 | $docblock = <<<DOCBLOCK |
||
1249 | /** |
||
1250 | * @SomeAnnotationClassNameWithoutConstructor(invalidaProperty = "Some val") |
||
1251 | */ |
||
1252 | DOCBLOCK; |
||
1253 | |||
1254 | $this->createTestParser()->parse($docblock, 'some class'); |
||
1255 | } |
||
1256 | |||
1257 | /** |
||
1258 | * @expectedException \Doctrine\Annotations\AnnotationException |
||
1259 | * @expectedExceptionMessage [Syntax Error] Expected Doctrine\Annotations\DocLexer::T_IDENTIFIER or Doctrine\Annotations\DocLexer::T_TRUE or Doctrine\Annotations\DocLexer::T_FALSE or Doctrine\Annotations\DocLexer::T_NULL, got '3.42' at position 5. |
||
1260 | */ |
||
1261 | public function testInvalidIdentifierInAnnotation() |
||
1262 | { |
||
1263 | $parser = $this->createTestParser(); |
||
1264 | $parser->parse('@Foo\3.42'); |
||
1265 | } |
||
1266 | |||
1267 | public function testTrailingCommaIsAllowed() |
||
1268 | { |
||
1269 | $parser = $this->createTestParser(); |
||
1270 | |||
1271 | $annots = $parser->parse('@Name({ |
||
1272 | "Foo", |
||
1273 | "Bar", |
||
1274 | })'); |
||
1275 | self::assertCount(1, $annots); |
||
1276 | self::assertEquals(['Foo', 'Bar'], $annots[0]->value); |
||
1277 | } |
||
1278 | |||
1279 | public function testTabPrefixIsAllowed() |
||
1280 | { |
||
1281 | $docblock = <<<DOCBLOCK |
||
1282 | /** |
||
1283 | * @Name |
||
1284 | */ |
||
1285 | DOCBLOCK; |
||
1286 | |||
1287 | $parser = $this->createTestParser(); |
||
1288 | $result = $parser->parse($docblock); |
||
1289 | self::assertCount(1, $result); |
||
1290 | self::assertInstanceOf(Name::class, $result[0]); |
||
1291 | } |
||
1292 | |||
1293 | public function testDefaultAnnotationValueIsNotOverwritten() |
||
1294 | { |
||
1295 | $parser = $this->createTestParser(); |
||
1296 | |||
1297 | $annots = $parser->parse('@Doctrine\Tests\Annotations\Fixtures\Annotation\AnnotWithDefaultValue'); |
||
1298 | self::assertCount(1, $annots); |
||
1299 | self::assertEquals('bar', $annots[0]->foo); |
||
1300 | } |
||
1301 | |||
1302 | public function testArrayWithColon() |
||
1303 | { |
||
1304 | $parser = $this->createTestParser(); |
||
1305 | |||
1306 | $annots = $parser->parse('@Name({"foo": "bar"})'); |
||
1307 | self::assertCount(1, $annots); |
||
1308 | self::assertEquals(['foo' => 'bar'], $annots[0]->value); |
||
1309 | } |
||
1310 | |||
1311 | /** |
||
1312 | * @expectedException \Doctrine\Annotations\AnnotationException |
||
1313 | * @expectedExceptionMessage [Semantical Error] Couldn't find constant foo. |
||
1314 | */ |
||
1315 | public function testInvalidContantName() |
||
1316 | { |
||
1317 | $parser = $this->createTestParser(); |
||
1318 | $parser->parse('@Name(foo: "bar")'); |
||
1319 | } |
||
1320 | |||
1321 | /** |
||
1322 | * Tests parsing empty arrays. |
||
1323 | */ |
||
1324 | public function testEmptyArray() |
||
1325 | { |
||
1326 | $parser = $this->createTestParser(); |
||
1327 | |||
1328 | $annots = $parser->parse('@Name({"foo": {}})'); |
||
1329 | self::assertCount(1, $annots); |
||
1330 | self::assertEquals(['foo' => []], $annots[0]->value); |
||
1331 | } |
||
1332 | |||
1333 | public function testKeyHasNumber() |
||
1334 | { |
||
1335 | $parser = $this->createTestParser(); |
||
1336 | $annots = $parser->parse('@SettingsAnnotation(foo="test", bar2="test")'); |
||
1337 | |||
1338 | self::assertCount(1, $annots); |
||
1339 | self::assertEquals(['foo' => 'test', 'bar2' => 'test'], $annots[0]->settings); |
||
1340 | } |
||
1341 | |||
1342 | /** |
||
1343 | * @group 44 |
||
1344 | */ |
||
1345 | public function testSupportsEscapedQuotedValues() |
||
1346 | { |
||
1347 | $result = $this->createTestParser()->parse('@Doctrine\Tests\Annotations\Name(foo="""bar""")'); |
||
1348 | |||
1349 | self::assertCount(1, $result); |
||
1350 | |||
1351 | self::assertInstanceOf(Name::class, $result[0]); |
||
1352 | self::assertEquals('"bar"', $result[0]->foo); |
||
1353 | } |
||
1354 | |||
1355 | /** |
||
1356 | * @see http://php.net/manual/en/mbstring.configuration.php |
||
1357 | * mbstring.func_overload can be changed only in php.ini |
||
1358 | * so for testing this case instead of skipping it you need to manually configure your php installation |
||
1359 | */ |
||
1360 | public function testMultiByteAnnotation() |
||
1361 | { |
||
1362 | $overloadStringFunctions = 2; |
||
1363 | if (!extension_loaded('mbstring') || (ini_get('mbstring.func_overload') & $overloadStringFunctions) == 0) { |
||
1364 | $this->markTestSkipped('This test requires mbstring function overloading is turned on'); |
||
1365 | } |
||
1366 | |||
1367 | $docblock = <<<DOCBLOCK |
||
1368 | /** |
||
1369 | * Мультибайтовый текст ломал парсер при оверлоадинге строковых функций |
||
1370 | * @Doctrine\Tests\Annotations\Name |
||
1371 | */ |
||
1372 | DOCBLOCK; |
||
1373 | |||
1374 | $docParser = $this->createTestParser(); |
||
1375 | $result = $docParser->parse($docblock); |
||
1376 | |||
1377 | self::assertCount(1, $result); |
||
1378 | |||
1379 | } |
||
1447 |