Rajout de doctrine/orm
[zf2.biz/galerie.git] / vendor / doctrine / common / tests / Doctrine / Tests / Common / Annotations / DocParserTest.php
1 <?php
2
3 namespace Doctrine\Tests\Common\Annotations;
4
5 use Doctrine\Common\Annotations\Annotation\IgnorePhpDoc;
6 use Doctrine\Common\Annotations\Annotation\IgnoreAnnotation;
7 use Doctrine\Common\Annotations\DocParser;
8 use Doctrine\Common\Annotations\AnnotationRegistry;
9 use Doctrine\Common\Annotations\Annotation\Target;
10 use Doctrine\Tests\Common\Annotations\Fixtures\AnnotationWithConstants;
11 use Doctrine\Tests\Common\Annotations\Fixtures\ClassWithConstants;
12 use Doctrine\Tests\Common\Annotations\Fixtures\IntefaceWithConstants;
13
14 class DocParserTest extends \PHPUnit_Framework_TestCase
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         $this->assertTrue($annot instanceof Name);
25         $this->assertNull($annot->value);
26         $this->assertEquals(3, count($annot->foo));
27         $this->assertEquals(1, $annot->foo[0]);
28         $this->assertEquals(2, $annot->foo[1]);
29         $this->assertTrue(is_array($annot->foo[2]));
30
31         $nestedArray = $annot->foo[2];
32         $this->assertTrue(isset($nestedArray['key']));
33         $this->assertTrue($nestedArray['key'] instanceof Name);
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         $this->assertTrue($annot instanceof Name);
44         $this->assertNull($annot->value);
45         $this->assertNull($annot->foo);
46
47         // Associative arrays
48         $result = $parser->parse('@Name(foo={"key1" = "value1"})');
49         $annot = $result[0];
50         $this->assertNull($annot->value);
51         $this->assertTrue(is_array($annot->foo));
52         $this->assertTrue(isset($annot->foo['key1']));
53
54         // Numerical arrays
55         $result = $parser->parse('@Name({2="foo", 4="bar"})');
56         $annot = $result[0];
57         $this->assertTrue(is_array($annot->value));
58         $this->assertEquals('foo', $annot->value[2]);
59         $this->assertEquals('bar', $annot->value[4]);
60         $this->assertFalse(isset($annot->value[0]));
61         $this->assertFalse(isset($annot->value[1]));
62         $this->assertFalse(isset($annot->value[3]));
63
64         // Multiple values
65         $result = $parser->parse('@Name(@Name, @Name)');
66         $annot = $result[0];
67
68         $this->assertTrue($annot instanceof Name);
69         $this->assertTrue(is_array($annot->value));
70         $this->assertTrue($annot->value[0] instanceof Name);
71         $this->assertTrue($annot->value[1] instanceof Name);
72
73         // Multiple types as values
74         $result = $parser->parse('@Name(foo="Bar", @Name, {"key1"="value1", "key2"="value2"})');
75         $annot = $result[0];
76
77         $this->assertTrue($annot instanceof Name);
78         $this->assertTrue(is_array($annot->value));
79         $this->assertTrue($annot->value[0] instanceof Name);
80         $this->assertTrue(is_array($annot->value[1]));
81         $this->assertEquals('value1', $annot->value[1]['key1']);
82         $this->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         $this->assertEquals(1, count($result));
96         $annot = $result[0];
97         $this->assertTrue($annot instanceof Name);
98         $this->assertEquals("bar", $annot->foo);
99         $this->assertNull($annot->value);
100    }
101
102     public function testNamespacedAnnotations()
103     {
104         $parser = new DocParser;
105         $parser->setIgnoreNotImportedAnnotations(true);
106
107         $docblock = <<<DOCBLOCK
108 /**
109  * Some nifty class.
110  *
111  * @package foo
112  * @subpackage bar
113  * @author Mr.X <mr@x.com>
114  * @Doctrine\Tests\Common\Annotations\Name(foo="bar")
115  * @ignore
116  */
117 DOCBLOCK;
118
119         $result = $parser->parse($docblock);
120         $this->assertEquals(1, count($result));
121         $annot = $result[0];
122         $this->assertTrue($annot instanceof Name);
123         $this->assertEquals("bar", $annot->foo);
124     }
125
126     /**
127      * @group debug
128      */
129     public function testTypicalMethodDocBlock()
130     {
131         $parser = $this->createTestParser();
132
133         $docblock = <<<DOCBLOCK
134 /**
135  * Some nifty method.
136  *
137  * @since 2.0
138  * @Doctrine\Tests\Common\Annotations\Name(foo="bar")
139  * @param string \$foo This is foo.
140  * @param mixed \$bar This is bar.
141  * @return string Foo and bar.
142  * @This is irrelevant
143  * @Marker
144  */
145 DOCBLOCK;
146
147         $result = $parser->parse($docblock);
148         $this->assertEquals(2, count($result));
149         $this->assertTrue(isset($result[0]));
150         $this->assertTrue(isset($result[1]));
151         $annot = $result[0];
152         $this->assertTrue($annot instanceof Name);
153         $this->assertEquals("bar", $annot->foo);
154         $marker = $result[1];
155         $this->assertTrue($marker instanceof Marker);
156     }
157
158
159     public function testAnnotationWithoutConstructor()
160     {
161         $parser = $this->createTestParser();
162
163
164         $docblock = <<<DOCBLOCK
165 /**
166  * @SomeAnnotationClassNameWithoutConstructor("Some data")
167  */
168 DOCBLOCK;
169
170         $result     = $parser->parse($docblock);
171         $this->assertEquals(count($result), 1);
172         $annot      = $result[0];
173
174         $this->assertNotNull($annot);
175         $this->assertTrue($annot instanceof SomeAnnotationClassNameWithoutConstructor);
176
177         $this->assertNull($annot->name);
178         $this->assertNotNull($annot->data);
179         $this->assertEquals($annot->data, "Some data");
180
181
182
183
184 $docblock = <<<DOCBLOCK
185 /**
186  * @SomeAnnotationClassNameWithoutConstructor(name="Some Name", data = "Some data")
187  */
188 DOCBLOCK;
189
190
191         $result     = $parser->parse($docblock);
192         $this->assertEquals(count($result), 1);
193         $annot      = $result[0];
194
195         $this->assertNotNull($annot);
196         $this->assertTrue($annot instanceof SomeAnnotationClassNameWithoutConstructor);
197
198         $this->assertEquals($annot->name, "Some Name");
199         $this->assertEquals($annot->data, "Some data");
200
201
202
203
204 $docblock = <<<DOCBLOCK
205 /**
206  * @SomeAnnotationClassNameWithoutConstructor(data = "Some data")
207  */
208 DOCBLOCK;
209
210         $result     = $parser->parse($docblock);
211         $this->assertEquals(count($result), 1);
212         $annot      = $result[0];
213
214         $this->assertEquals($annot->data, "Some data");
215         $this->assertNull($annot->name);
216
217
218         $docblock = <<<DOCBLOCK
219 /**
220  * @SomeAnnotationClassNameWithoutConstructor(name = "Some name")
221  */
222 DOCBLOCK;
223
224         $result     = $parser->parse($docblock);
225         $this->assertEquals(count($result), 1);
226         $annot      = $result[0];
227
228         $this->assertEquals($annot->name, "Some name");
229         $this->assertNull($annot->data);
230
231         $docblock = <<<DOCBLOCK
232 /**
233  * @SomeAnnotationClassNameWithoutConstructor("Some data")
234  */
235 DOCBLOCK;
236
237         $result     = $parser->parse($docblock);
238         $this->assertEquals(count($result), 1);
239         $annot      = $result[0];
240
241         $this->assertEquals($annot->data, "Some data");
242         $this->assertNull($annot->name);
243
244
245
246         $docblock = <<<DOCBLOCK
247 /**
248  * @SomeAnnotationClassNameWithoutConstructor("Some data",name = "Some name")
249  */
250 DOCBLOCK;
251
252         $result     = $parser->parse($docblock);
253         $this->assertEquals(count($result), 1);
254         $annot      = $result[0];
255
256         $this->assertEquals($annot->name, "Some name");
257         $this->assertEquals($annot->data, "Some data");
258
259
260         $docblock = <<<DOCBLOCK
261 /**
262  * @SomeAnnotationWithConstructorWithoutParams(name = "Some name")
263  */
264 DOCBLOCK;
265
266         $result     = $parser->parse($docblock);
267         $this->assertEquals(count($result), 1);
268         $annot      = $result[0];
269
270         $this->assertEquals($annot->name, "Some name");
271         $this->assertEquals($annot->data, "Some data");
272
273         $docblock = <<<DOCBLOCK
274 /**
275  * @SomeAnnotationClassNameWithoutConstructorAndProperties()
276  */
277 DOCBLOCK;
278
279         $result     = $parser->parse($docblock);
280         $this->assertEquals(count($result), 1);
281         $this->assertTrue($result[0] instanceof SomeAnnotationClassNameWithoutConstructorAndProperties);
282     }
283
284     public function testAnnotationTarget()
285     {
286
287         $parser = new DocParser;
288         $parser->setImports(array(
289             '__NAMESPACE__' => 'Doctrine\Tests\Common\Annotations\Fixtures',
290         ));
291         $class  = new \ReflectionClass('Doctrine\Tests\Common\Annotations\Fixtures\ClassWithValidAnnotationTarget');
292
293
294         $context    = 'class ' . $class->getName();
295         $docComment = $class->getDocComment();
296
297         $parser->setTarget(Target::TARGET_CLASS);
298         $this->assertNotNull($parser->parse($docComment,$context));
299
300
301         $property   = $class->getProperty('foo');
302         $docComment = $property->getDocComment();
303         $context    = 'property ' . $class->getName() . "::\$" . $property->getName();
304
305         $parser->setTarget(Target::TARGET_PROPERTY);
306         $this->assertNotNull($parser->parse($docComment,$context));
307
308
309
310         $method     = $class->getMethod('someFunction');
311         $docComment = $property->getDocComment();
312         $context    = 'method ' . $class->getName() . '::' . $method->getName() . '()';
313
314         $parser->setTarget(Target::TARGET_METHOD);
315         $this->assertNotNull($parser->parse($docComment,$context));
316
317
318         try {
319             $class      = new \ReflectionClass('Doctrine\Tests\Common\Annotations\Fixtures\ClassWithInvalidAnnotationTargetAtClass');
320             $context    = 'class ' . $class->getName();
321             $docComment = $class->getDocComment();
322
323             $parser->setTarget(Target::TARGET_CLASS);
324             $parser->parse($class->getDocComment(),$context);
325
326             $this->fail();
327         } catch (\Doctrine\Common\Annotations\AnnotationException $exc) {
328             $this->assertNotNull($exc->getMessage());
329         }
330
331
332         try {
333
334             $class      = new \ReflectionClass('Doctrine\Tests\Common\Annotations\Fixtures\ClassWithInvalidAnnotationTargetAtMethod');
335             $method     = $class->getMethod('functionName');
336             $docComment = $method->getDocComment();
337             $context    = 'method ' . $class->getName() . '::' . $method->getName() . '()';
338
339             $parser->setTarget(Target::TARGET_METHOD);
340             $parser->parse($docComment,$context);
341
342             $this->fail();
343         } catch (\Doctrine\Common\Annotations\AnnotationException $exc) {
344             $this->assertNotNull($exc->getMessage());
345         }
346
347
348         try {
349             $class      = new \ReflectionClass('Doctrine\Tests\Common\Annotations\Fixtures\ClassWithInvalidAnnotationTargetAtProperty');
350             $property   = $class->getProperty('foo');
351             $docComment = $property->getDocComment();
352             $context    = 'property ' . $class->getName() . "::\$" . $property->getName();
353
354             $parser->setTarget(Target::TARGET_PROPERTY);
355             $parser->parse($docComment,$context);
356
357             $this->fail();
358         } catch (\Doctrine\Common\Annotations\AnnotationException $exc) {
359             $this->assertNotNull($exc->getMessage());
360         }
361
362     }
363
364     public function getAnnotationVarTypeProviderValid()
365     {
366         //({attribute name}, {attribute value})
367          return array(
368             // mixed type
369             array('mixed', '"String Value"'),
370             array('mixed', 'true'),
371             array('mixed', 'false'),
372             array('mixed', '1'),
373             array('mixed', '1.2'),
374             array('mixed', '@Doctrine\Tests\Common\Annotations\Fixtures\AnnotationTargetAll'),
375
376             // boolean type
377             array('boolean', 'true'),
378             array('boolean', 'false'),
379
380             // alias for internal type boolean
381             array('bool', 'true'),
382             array('bool', 'false'),
383
384             // integer type
385             array('integer', '0'),
386             array('integer', '1'),
387             array('integer', '123456789'),
388             array('integer', '9223372036854775807'),
389
390             // alias for internal type double
391             array('float', '0.1'),
392             array('float', '1.2'),
393             array('float', '123.456'),
394
395             // string type
396             array('string', '"String Value"'),
397             array('string', '"true"'),
398             array('string', '"123"'),
399
400               // array type
401             array('array', '{@AnnotationExtendsAnnotationTargetAll}'),
402             array('array', '{@AnnotationExtendsAnnotationTargetAll,@AnnotationExtendsAnnotationTargetAll}'),
403
404             array('arrayOfIntegers', '1'),
405             array('arrayOfIntegers', '{1}'),
406             array('arrayOfIntegers', '{1,2,3,4}'),
407             array('arrayOfAnnotations', '@AnnotationExtendsAnnotationTargetAll'),
408             array('arrayOfAnnotations', '{@Doctrine\Tests\Common\Annotations\Fixtures\AnnotationTargetAll}'),
409             array('arrayOfAnnotations', '{@AnnotationExtendsAnnotationTargetAll, @Doctrine\Tests\Common\Annotations\Fixtures\AnnotationTargetAll}'),
410
411             // annotation instance
412             array('annotation', '@Doctrine\Tests\Common\Annotations\Fixtures\AnnotationTargetAll'),
413             array('annotation', '@AnnotationExtendsAnnotationTargetAll'),
414         );
415     }
416
417     public function getAnnotationVarTypeProviderInvalid()
418     {
419          //({attribute name}, {type declared type}, {attribute value} , {given type or class})
420          return array(
421             // boolean type
422             array('boolean','boolean','1','integer'),
423             array('boolean','boolean','1.2','double'),
424             array('boolean','boolean','"str"','string'),
425             array('boolean','boolean','{1,2,3}','array'),
426             array('boolean','boolean','@Name', 'an instance of Doctrine\Tests\Common\Annotations\Name'),
427
428             // alias for internal type boolean
429             array('bool','bool', '1','integer'),
430             array('bool','bool', '1.2','double'),
431             array('bool','bool', '"str"','string'),
432             array('bool','bool', '{"str"}','array'),
433
434             // integer type
435             array('integer','integer', 'true','boolean'),
436             array('integer','integer', 'false','boolean'),
437             array('integer','integer', '1.2','double'),
438             array('integer','integer', '"str"','string'),
439             array('integer','integer', '{"str"}','array'),
440             array('integer','integer', '{1,2,3,4}','array'),
441
442             // alias for internal type double
443             array('float','float', 'true','boolean'),
444             array('float','float', 'false','boolean'),
445             array('float','float', '123','integer'),
446             array('float','float', '"str"','string'),
447             array('float','float', '{"str"}','array'),
448             array('float','float', '{12.34}','array'),
449             array('float','float', '{1,2,3}','array'),
450
451             // string type
452             array('string','string', 'true','boolean'),
453             array('string','string', 'false','boolean'),
454             array('string','string', '12','integer'),
455             array('string','string', '1.2','double'),
456             array('string','string', '{"str"}','array'),
457             array('string','string', '{1,2,3,4}','array'),
458
459              // annotation instance
460             array('annotation','Doctrine\Tests\Common\Annotations\Fixtures\AnnotationTargetAll', 'true','boolean'),
461             array('annotation','Doctrine\Tests\Common\Annotations\Fixtures\AnnotationTargetAll', 'false','boolean'),
462             array('annotation','Doctrine\Tests\Common\Annotations\Fixtures\AnnotationTargetAll', '12','integer'),
463             array('annotation','Doctrine\Tests\Common\Annotations\Fixtures\AnnotationTargetAll', '1.2','double'),
464             array('annotation','Doctrine\Tests\Common\Annotations\Fixtures\AnnotationTargetAll', '{"str"}','array'),
465             array('annotation','Doctrine\Tests\Common\Annotations\Fixtures\AnnotationTargetAll', '{1,2,3,4}','array'),
466             array('annotation','Doctrine\Tests\Common\Annotations\Fixtures\AnnotationTargetAll', '@Name','an instance of Doctrine\Tests\Common\Annotations\Name'),
467         );
468     }
469
470     public function getAnnotationVarTypeArrayProviderInvalid()
471     {
472          //({attribute name}, {type declared type}, {attribute value} , {given type or class})
473          return array(
474             array('arrayOfIntegers','integer', 'true','boolean'),
475             array('arrayOfIntegers','integer', 'false','boolean'),
476             array('arrayOfIntegers','integer', '{true,true}','boolean'),
477             array('arrayOfIntegers','integer', '{1,true}','boolean'),
478             array('arrayOfIntegers','integer', '{1,2,1.2}','double'),
479             array('arrayOfIntegers','integer', '{1,2,"str"}','string'),
480
481
482             array('arrayOfAnnotations','Doctrine\Tests\Common\Annotations\Fixtures\AnnotationTargetAll', 'true','boolean'),
483             array('arrayOfAnnotations','Doctrine\Tests\Common\Annotations\Fixtures\AnnotationTargetAll', 'false','boolean'),
484             array('arrayOfAnnotations','Doctrine\Tests\Common\Annotations\Fixtures\AnnotationTargetAll', '{@Doctrine\Tests\Common\Annotations\Fixtures\AnnotationTargetAll,true}','boolean'),
485             array('arrayOfAnnotations','Doctrine\Tests\Common\Annotations\Fixtures\AnnotationTargetAll', '{@Doctrine\Tests\Common\Annotations\Fixtures\AnnotationTargetAll,true}','boolean'),
486             array('arrayOfAnnotations','Doctrine\Tests\Common\Annotations\Fixtures\AnnotationTargetAll', '{@Doctrine\Tests\Common\Annotations\Fixtures\AnnotationTargetAll,1.2}','double'),
487             array('arrayOfAnnotations','Doctrine\Tests\Common\Annotations\Fixtures\AnnotationTargetAll', '{@Doctrine\Tests\Common\Annotations\Fixtures\AnnotationTargetAll,@AnnotationExtendsAnnotationTargetAll,"str"}','string'),
488         );
489     }
490
491     /**
492      * @dataProvider getAnnotationVarTypeProviderValid
493      */
494     public function testAnnotationWithVarType($attribute, $value)
495     {
496         $parser     = $this->createTestParser();
497         $context    = 'property SomeClassName::$invalidProperty.';
498         $docblock   = sprintf('@Doctrine\Tests\Common\Annotations\Fixtures\AnnotationWithVarType(%s = %s)',$attribute, $value);
499         $parser->setTarget(Target::TARGET_PROPERTY);
500
501         $result = $parser->parse($docblock, $context);
502
503         $this->assertTrue(sizeof($result) === 1);
504         $this->assertInstanceOf('Doctrine\Tests\Common\Annotations\Fixtures\AnnotationWithVarType', $result[0]);
505         $this->assertNotNull($result[0]->$attribute);
506     }
507
508     /**
509      * @dataProvider getAnnotationVarTypeProviderInvalid
510      */
511     public function testAnnotationWithVarTypeError($attribute,$type,$value,$given)
512     {
513         $parser     = $this->createTestParser();
514         $context    = 'property SomeClassName::invalidProperty.';
515         $docblock   = sprintf('@Doctrine\Tests\Common\Annotations\Fixtures\AnnotationWithVarType(%s = %s)',$attribute, $value);
516         $parser->setTarget(Target::TARGET_PROPERTY);
517
518         try {
519             $parser->parse($docblock, $context);
520             $this->fail();
521         } catch (\Doctrine\Common\Annotations\AnnotationException $exc) {
522             $this->assertContains("[Type Error] Attribute \"$attribute\" of @Doctrine\Tests\Common\Annotations\Fixtures\AnnotationWithVarType declared on property SomeClassName::invalidProperty. expects a(n) $type, but got $given.", $exc->getMessage());
523         }
524     }
525
526
527     /**
528      * @dataProvider getAnnotationVarTypeArrayProviderInvalid
529      */
530     public function testAnnotationWithVarTypeArrayError($attribute,$type,$value,$given)
531     {
532         $parser     = $this->createTestParser();
533         $context    = 'property SomeClassName::invalidProperty.';
534         $docblock   = sprintf('@Doctrine\Tests\Common\Annotations\Fixtures\AnnotationWithVarType(%s = %s)',$attribute, $value);
535         $parser->setTarget(Target::TARGET_PROPERTY);
536
537         try {
538             $parser->parse($docblock, $context);
539             $this->fail();
540         } catch (\Doctrine\Common\Annotations\AnnotationException $exc) {
541             $this->assertContains("[Type Error] Attribute \"$attribute\" of @Doctrine\Tests\Common\Annotations\Fixtures\AnnotationWithVarType declared on property SomeClassName::invalidProperty. expects either a(n) $type, or an array of {$type}s, but got $given.", $exc->getMessage());
542         }
543     }
544
545     /**
546      * @dataProvider getAnnotationVarTypeProviderValid
547      */
548     public function testAnnotationWithAttributes($attribute, $value)
549     {
550         $parser     = $this->createTestParser();
551         $context    = 'property SomeClassName::$invalidProperty.';
552         $docblock   = sprintf('@Doctrine\Tests\Common\Annotations\Fixtures\AnnotationWithAttributes(%s = %s)',$attribute, $value);
553         $parser->setTarget(Target::TARGET_PROPERTY);
554
555         $result = $parser->parse($docblock, $context);
556
557         $this->assertTrue(sizeof($result) === 1);
558         $this->assertInstanceOf('Doctrine\Tests\Common\Annotations\Fixtures\AnnotationWithAttributes', $result[0]);
559         $getter = "get".ucfirst($attribute);
560         $this->assertNotNull($result[0]->$getter());
561     }
562
563    /**
564      * @dataProvider getAnnotationVarTypeProviderInvalid
565      */
566     public function testAnnotationWithAttributesError($attribute,$type,$value,$given)
567     {
568         $parser     = $this->createTestParser();
569         $context    = 'property SomeClassName::invalidProperty.';
570         $docblock   = sprintf('@Doctrine\Tests\Common\Annotations\Fixtures\AnnotationWithAttributes(%s = %s)',$attribute, $value);
571         $parser->setTarget(Target::TARGET_PROPERTY);
572
573         try {
574             $parser->parse($docblock, $context);
575             $this->fail();
576         } catch (\Doctrine\Common\Annotations\AnnotationException $exc) {
577             $this->assertContains("[Type Error] Attribute \"$attribute\" of @Doctrine\Tests\Common\Annotations\Fixtures\AnnotationWithAttributes declared on property SomeClassName::invalidProperty. expects a(n) $type, but got $given.", $exc->getMessage());
578         }
579     }
580
581
582    /**
583      * @dataProvider getAnnotationVarTypeArrayProviderInvalid
584      */
585     public function testAnnotationWithAttributesWithVarTypeArrayError($attribute,$type,$value,$given)
586     {
587         $parser     = $this->createTestParser();
588         $context    = 'property SomeClassName::invalidProperty.';
589         $docblock   = sprintf('@Doctrine\Tests\Common\Annotations\Fixtures\AnnotationWithAttributes(%s = %s)',$attribute, $value);
590         $parser->setTarget(Target::TARGET_PROPERTY);
591
592         try {
593             $parser->parse($docblock, $context);
594             $this->fail();
595         } catch (\Doctrine\Common\Annotations\AnnotationException $exc) {
596             $this->assertContains("[Type Error] Attribute \"$attribute\" of @Doctrine\Tests\Common\Annotations\Fixtures\AnnotationWithAttributes declared on property SomeClassName::invalidProperty. expects either a(n) $type, or an array of {$type}s, but got $given.", $exc->getMessage());
597         }
598     }
599
600     public function testAnnotationWithRequiredAttributes()
601     {
602         $parser     = $this->createTestParser();
603         $context    = 'property SomeClassName::invalidProperty.';
604         $parser->setTarget(Target::TARGET_PROPERTY);
605
606
607         $docblock   = '@Doctrine\Tests\Common\Annotations\Fixtures\AnnotationWithRequiredAttributes("Some Value", annot = @Doctrine\Tests\Common\Annotations\Fixtures\AnnotationTargetAnnotation)';
608         $result     = $parser->parse($docblock);
609
610         $this->assertTrue(sizeof($result) === 1);
611         $this->assertInstanceOf('Doctrine\Tests\Common\Annotations\Fixtures\AnnotationWithRequiredAttributes', $result[0]);
612         $this->assertEquals("Some Value",$result[0]->getValue());
613         $this->assertInstanceOf('Doctrine\Tests\Common\Annotations\Fixtures\AnnotationTargetAnnotation', $result[0]->getAnnot());
614
615
616         $docblock   = '@Doctrine\Tests\Common\Annotations\Fixtures\AnnotationWithRequiredAttributes("Some Value")';
617         try {
618             $result = $parser->parse($docblock,$context);
619             $this->fail();
620         } catch (\Doctrine\Common\Annotations\AnnotationException $exc) {
621             $this->assertContains('Attribute "annot" of @Doctrine\Tests\Common\Annotations\Fixtures\AnnotationWithRequiredAttributes declared on property SomeClassName::invalidProperty. expects a(n) Doctrine\Tests\Common\Annotations\Fixtures\AnnotationTargetAnnotation. This value should not be null.', $exc->getMessage());
622         }
623
624         $docblock   = '@Doctrine\Tests\Common\Annotations\Fixtures\AnnotationWithRequiredAttributes(annot = @Doctrine\Tests\Common\Annotations\Fixtures\AnnotationTargetAnnotation)';
625         try {
626             $result = $parser->parse($docblock,$context);
627             $this->fail();
628         } catch (\Doctrine\Common\Annotations\AnnotationException $exc) {
629             $this->assertContains('Attribute "value" of @Doctrine\Tests\Common\Annotations\Fixtures\AnnotationWithRequiredAttributes declared on property SomeClassName::invalidProperty. expects a(n) string. This value should not be null.', $exc->getMessage());
630         }
631
632     }
633
634     public function testAnnotationWithRequiredAttributesWithoutContructor()
635     {
636         $parser     = $this->createTestParser();
637         $context    = 'property SomeClassName::invalidProperty.';
638         $parser->setTarget(Target::TARGET_PROPERTY);
639
640
641         $docblock   = '@Doctrine\Tests\Common\Annotations\Fixtures\AnnotationWithRequiredAttributesWithoutContructor("Some Value", annot = @Doctrine\Tests\Common\Annotations\Fixtures\AnnotationTargetAnnotation)';
642         $result     = $parser->parse($docblock);
643
644         $this->assertTrue(sizeof($result) === 1);
645         $this->assertInstanceOf('Doctrine\Tests\Common\Annotations\Fixtures\AnnotationWithRequiredAttributesWithoutContructor', $result[0]);
646         $this->assertEquals("Some Value", $result[0]->value);
647         $this->assertInstanceOf('Doctrine\Tests\Common\Annotations\Fixtures\AnnotationTargetAnnotation', $result[0]->annot);
648
649
650         $docblock   = '@Doctrine\Tests\Common\Annotations\Fixtures\AnnotationWithRequiredAttributesWithoutContructor("Some Value")';
651         try {
652             $result = $parser->parse($docblock,$context);
653             $this->fail();
654         } catch (\Doctrine\Common\Annotations\AnnotationException $exc) {
655             $this->assertContains('Attribute "annot" of @Doctrine\Tests\Common\Annotations\Fixtures\AnnotationWithRequiredAttributesWithoutContructor declared on property SomeClassName::invalidProperty. expects a(n) Doctrine\Tests\Common\Annotations\Fixtures\AnnotationTargetAnnotation. This value should not be null.', $exc->getMessage());
656         }
657
658         $docblock   = '@Doctrine\Tests\Common\Annotations\Fixtures\AnnotationWithRequiredAttributesWithoutContructor(annot = @Doctrine\Tests\Common\Annotations\Fixtures\AnnotationTargetAnnotation)';
659         try {
660             $result = $parser->parse($docblock,$context);
661             $this->fail();
662         } catch (\Doctrine\Common\Annotations\AnnotationException $exc) {
663             $this->assertContains('Attribute "value" of @Doctrine\Tests\Common\Annotations\Fixtures\AnnotationWithRequiredAttributesWithoutContructor declared on property SomeClassName::invalidProperty. expects a(n) string. This value should not be null.', $exc->getMessage());
664         }
665
666     }
667
668     public function getConstantsProvider()
669     {
670         $provider[] = array(
671             '@AnnotationWithConstants(PHP_EOL)',
672             PHP_EOL
673         );
674         $provider[] = array(
675             '@AnnotationWithConstants(AnnotationWithConstants::INTEGER)',
676             AnnotationWithConstants::INTEGER
677         );
678         $provider[] = array(
679             '@Doctrine\Tests\Common\Annotations\Fixtures\AnnotationWithConstants(AnnotationWithConstants::STRING)',
680             AnnotationWithConstants::STRING
681         );
682         $provider[] = array(
683             '@AnnotationWithConstants(Doctrine\Tests\Common\Annotations\Fixtures\AnnotationWithConstants::FLOAT)',
684             AnnotationWithConstants::FLOAT
685         );
686         $provider[] = array(
687             '@AnnotationWithConstants(ClassWithConstants::SOME_VALUE)',
688             ClassWithConstants::SOME_VALUE
689         );
690         $provider[] = array(
691             '@AnnotationWithConstants(Doctrine\Tests\Common\Annotations\Fixtures\ClassWithConstants::SOME_VALUE)',
692             ClassWithConstants::SOME_VALUE
693         );
694         $provider[] = array(
695             '@AnnotationWithConstants(IntefaceWithConstants::SOME_VALUE)',
696             IntefaceWithConstants::SOME_VALUE
697         );
698         $provider[] = array(
699             '@AnnotationWithConstants(\Doctrine\Tests\Common\Annotations\Fixtures\IntefaceWithConstants::SOME_VALUE)',
700             IntefaceWithConstants::SOME_VALUE
701         );
702         $provider[] = array(
703             '@AnnotationWithConstants({AnnotationWithConstants::STRING, AnnotationWithConstants::INTEGER, AnnotationWithConstants::FLOAT})',
704             array(AnnotationWithConstants::STRING, AnnotationWithConstants::INTEGER, AnnotationWithConstants::FLOAT)
705         );
706         $provider[] = array(
707             '@AnnotationWithConstants({
708                 AnnotationWithConstants::STRING = AnnotationWithConstants::INTEGER
709              })',
710             array(AnnotationWithConstants::STRING => AnnotationWithConstants::INTEGER)
711         );
712         $provider[] = array(
713             '@AnnotationWithConstants({
714                 Doctrine\Tests\Common\Annotations\Fixtures\IntefaceWithConstants::SOME_KEY = AnnotationWithConstants::INTEGER
715              })',
716             array(IntefaceWithConstants::SOME_KEY => AnnotationWithConstants::INTEGER)
717         );
718         $provider[] = array(
719             '@AnnotationWithConstants({
720                 \Doctrine\Tests\Common\Annotations\Fixtures\IntefaceWithConstants::SOME_KEY = AnnotationWithConstants::INTEGER
721              })',
722             array(IntefaceWithConstants::SOME_KEY => AnnotationWithConstants::INTEGER)
723         );
724         $provider[] = array(
725             '@AnnotationWithConstants({
726                 AnnotationWithConstants::STRING = AnnotationWithConstants::INTEGER,
727                 ClassWithConstants::SOME_KEY = ClassWithConstants::SOME_VALUE,
728                 Doctrine\Tests\Common\Annotations\Fixtures\ClassWithConstants::SOME_KEY = IntefaceWithConstants::SOME_VALUE
729              })',
730             array(
731                 AnnotationWithConstants::STRING => AnnotationWithConstants::INTEGER,
732                 ClassWithConstants::SOME_KEY    => ClassWithConstants::SOME_VALUE,
733                 ClassWithConstants::SOME_KEY    => IntefaceWithConstants::SOME_VALUE
734             )
735         );
736         return $provider;
737     }
738
739     /**
740      * @dataProvider getConstantsProvider
741      */
742     public function testSupportClassConstants($docblock, $expected)
743     {
744         $parser = $this->createTestParser();
745         $parser->setImports(array(
746             'classwithconstants'        => 'Doctrine\Tests\Common\Annotations\Fixtures\ClassWithConstants',
747             'intefacewithconstants'     => 'Doctrine\Tests\Common\Annotations\Fixtures\IntefaceWithConstants',
748             'annotationwithconstants'   => 'Doctrine\Tests\Common\Annotations\Fixtures\AnnotationWithConstants'
749         ));
750         
751         $result = $parser->parse($docblock);
752         $this->assertInstanceOf('\Doctrine\Tests\Common\Annotations\Fixtures\AnnotationWithConstants', $annotation = $result[0]);
753         $this->assertEquals($expected, $annotation->value);
754     }
755
756     /**
757      * @expectedException Doctrine\Common\Annotations\AnnotationException
758      * @expectedExceptionMessage The annotation @SomeAnnotationClassNameWithoutConstructorAndProperties declared on  does not accept any values, but got {"value":"Foo"}.
759      */
760     public function testWithoutConstructorWhenIsNotDefaultValue()
761     {
762         $parser     = $this->createTestParser();
763         $docblock   = <<<DOCBLOCK
764 /**
765  * @SomeAnnotationClassNameWithoutConstructorAndProperties("Foo")
766  */
767 DOCBLOCK;
768
769
770         $parser->setTarget(Target::TARGET_CLASS);
771         $parser->parse($docblock);
772     }
773
774     /**
775      * @expectedException Doctrine\Common\Annotations\AnnotationException
776      * @expectedExceptionMessage The annotation @SomeAnnotationClassNameWithoutConstructorAndProperties declared on  does not accept any values, but got {"value":"Foo"}.
777      */
778     public function testWithoutConstructorWhenHasNoProperties()
779     {
780         $parser     = $this->createTestParser();
781         $docblock   = <<<DOCBLOCK
782 /**
783  * @SomeAnnotationClassNameWithoutConstructorAndProperties(value = "Foo")
784  */
785 DOCBLOCK;
786
787         $parser->setTarget(Target::TARGET_CLASS);
788         $parser->parse($docblock);
789     }
790
791     /**
792      * @expectedException Doctrine\Common\Annotations\AnnotationException
793      * @expectedExceptionMessage Expected namespace separator or identifier, got ')' at position 24 in class @Doctrine\Tests\Common\Annotations\Fixtures\AnnotationWithTargetSyntaxError.
794      */
795     public function testAnnotationTargetSyntaxError()
796     {
797         $parser     = $this->createTestParser();
798         $context    = 'class ' . 'SomeClassName';
799         $docblock   = <<<DOCBLOCK
800 /**
801  * @Doctrine\Tests\Common\Annotations\Fixtures\AnnotationWithTargetSyntaxError()
802  */
803 DOCBLOCK;
804
805         $parser->setTarget(Target::TARGET_CLASS);
806         $parser->parse($docblock,$context);
807     }
808
809     /**
810      * @expectedException \InvalidArgumentException
811      * @expectedExceptionMessage Invalid Target "Foo". Available targets: [ALL, CLASS, METHOD, PROPERTY, ANNOTATION]
812      */
813     public function testAnnotationWithInvalidTargetDeclarationError()
814     {
815         $parser     = $this->createTestParser();
816         $context    = 'class ' . 'SomeClassName';
817         $docblock   = <<<DOCBLOCK
818 /**
819  * @AnnotationWithInvalidTargetDeclaration()
820  */
821 DOCBLOCK;
822
823         $parser->setTarget(Target::TARGET_CLASS);
824         $parser->parse($docblock,$context);
825     }
826
827     /**
828      * @expectedException \InvalidArgumentException
829      * @expectedExceptionMessage @Target expects either a string value, or an array of strings, "NULL" given.
830      */
831     public function testAnnotationWithTargetEmptyError()
832     {
833         $parser     = $this->createTestParser();
834         $context    = 'class ' . 'SomeClassName';
835         $docblock   = <<<DOCBLOCK
836 /**
837  * @AnnotationWithTargetEmpty()
838  */
839 DOCBLOCK;
840
841         $parser->setTarget(Target::TARGET_CLASS);
842         $parser->parse($docblock,$context);
843     }
844
845     /**
846      * @group DDC-575
847      */
848     public function testRegressionDDC575()
849     {
850         $parser = $this->createTestParser();
851
852         $docblock = <<<DOCBLOCK
853 /**
854  * @Name
855  *
856  * Will trigger error.
857  */
858 DOCBLOCK;
859
860         $result = $parser->parse($docblock);
861
862         $this->assertInstanceOf("Doctrine\Tests\Common\Annotations\Name", $result[0]);
863
864         $docblock = <<<DOCBLOCK
865 /**
866  * @Name
867  * @Marker
868  *
869  * Will trigger error.
870  */
871 DOCBLOCK;
872
873         $result = $parser->parse($docblock);
874
875         $this->assertInstanceOf("Doctrine\Tests\Common\Annotations\Name", $result[0]);
876     }
877
878     /**
879      * @group DDC-77
880      */
881     public function testAnnotationWithoutClassIsIgnoredWithoutWarning()
882     {
883         $parser = new DocParser();
884         $parser->setIgnoreNotImportedAnnotations(true);
885         $result = $parser->parse("@param");
886
887         $this->assertEquals(0, count($result));
888     }
889
890     /**
891      * @expectedException Doctrine\Common\Annotations\AnnotationException
892      * @expectedExceptionMessage Expected PlainValue, got ''' at position 10.
893      */
894     public function testAnnotationDontAcceptSingleQuotes()
895     {
896         $parser = $this->createTestParser();
897         $parser->parse("@Name(foo='bar')");
898     }
899
900     /**
901      * @group DCOM-41
902      */
903     public function testAnnotationDoesntThrowExceptionWhenAtSignIsNotFollowedByIdentifier()
904     {
905         $parser = new DocParser();
906         $result = $parser->parse("'@'");
907
908         $this->assertEquals(0, count($result));
909     }
910
911     /**
912      * @group DCOM-41
913      * @expectedException Doctrine\Common\Annotations\AnnotationException
914      */
915     public function testAnnotationThrowsExceptionWhenAtSignIsNotFollowedByIdentifierInNestedAnnotation()
916     {
917         $parser = new DocParser();
918         $result = $parser->parse("@Doctrine\Tests\Common\Annotations\Name(@')");
919     }
920
921     /**
922      * @group DCOM-56
923      */
924     public function testAutoloadAnnotation()
925     {
926         $this->assertFalse(class_exists('Doctrine\Tests\Common\Annotations\Fixture\Annotation\Autoload', false), 'Pre-condition: Doctrine\Tests\Common\Annotations\Fixture\Annotation\Autoload not allowed to be loaded.');
927
928         $parser = new DocParser();
929
930         AnnotationRegistry::registerAutoloadNamespace('Doctrine\Tests\Common\Annotations\Fixtures\Annotation', __DIR__ . '/../../../../');
931
932         $parser->setImports(array(
933             'autoload' => 'Doctrine\Tests\Common\Annotations\Fixtures\Annotation\Autoload',
934         ));
935         $annotations = $parser->parse('@Autoload');
936
937         $this->assertEquals(1, count($annotations));
938         $this->assertInstanceOf('Doctrine\Tests\Common\Annotations\Fixtures\Annotation\Autoload', $annotations[0]);
939     }
940
941     public function createTestParser()
942     {
943         $parser = new DocParser();
944         $parser->setIgnoreNotImportedAnnotations(true);
945         $parser->setImports(array(
946             'name' => 'Doctrine\Tests\Common\Annotations\Name',
947             '__NAMESPACE__' => 'Doctrine\Tests\Common\Annotations',
948         ));
949
950         return $parser;
951     }
952
953     /**
954      * @group DDC-78
955      * @expectedException Doctrine\Common\Annotations\AnnotationException
956      * @expectedExceptionMessage Expected PlainValue, got ''' at position 10 in class \Doctrine\Tests\Common\Annotations\Name
957      */
958     public function testSyntaxErrorWithContextDescription()
959     {
960         $parser = $this->createTestParser();
961         $parser->parse("@Name(foo='bar')", "class \Doctrine\Tests\Common\Annotations\Name");
962     }
963
964     /**
965      * @group DDC-183
966      */
967     public function testSyntaxErrorWithUnknownCharacters()
968     {
969         $docblock = <<<DOCBLOCK
970 /**
971  * @test at.
972  */
973 class A {
974 }
975 DOCBLOCK;
976
977         //$lexer = new \Doctrine\Common\Annotations\Lexer();
978         //$lexer->setInput(trim($docblock, '/ *'));
979         //var_dump($lexer);
980
981         try {
982             $parser = $this->createTestParser();
983             $result = $parser->parse($docblock);
984         } catch (Exception $e) {
985             $this->fail($e->getMessage());
986         }
987     }
988
989     /**
990      * @group DCOM-14
991      */
992     public function testIgnorePHPDocThrowTag()
993     {
994         $docblock = <<<DOCBLOCK
995 /**
996  * @throws \RuntimeException
997  */
998 class A {
999 }
1000 DOCBLOCK;
1001
1002         try {
1003             $parser = $this->createTestParser();
1004             $result = $parser->parse($docblock);
1005         } catch (Exception $e) {
1006             $this->fail($e->getMessage());
1007         }
1008     }
1009
1010     /**
1011      * @group DCOM-38
1012      */
1013     public function testCastInt()
1014     {
1015         $parser = $this->createTestParser();
1016
1017         $result = $parser->parse("@Name(foo=1234)");
1018         $annot = $result[0];
1019         $this->assertInternalType('int', $annot->foo);
1020     }
1021
1022     /**
1023      * @group DCOM-38
1024      */
1025     public function testCastNegativeInt()
1026     {
1027         $parser = $this->createTestParser();
1028
1029         $result = $parser->parse("@Name(foo=-1234)");
1030         $annot = $result[0];
1031         $this->assertInternalType('int', $annot->foo);
1032     }
1033
1034     /**
1035      * @group DCOM-38
1036      */
1037     public function testCastFloat()
1038     {
1039         $parser = $this->createTestParser();
1040
1041         $result = $parser->parse("@Name(foo=1234.345)");
1042         $annot = $result[0];
1043         $this->assertInternalType('float', $annot->foo);
1044     }
1045
1046     /**
1047      * @group DCOM-38
1048      */
1049     public function testCastNegativeFloat()
1050     {
1051         $parser = $this->createTestParser();
1052
1053         $result = $parser->parse("@Name(foo=-1234.345)");
1054         $annot = $result[0];
1055         $this->assertInternalType('float', $annot->foo);
1056
1057         $result = $parser->parse("@Marker(-1234.345)");
1058         $annot = $result[0];
1059         $this->assertInternalType('float', $annot->value);
1060     }
1061
1062     public function testReservedKeywordsInAnnotations()
1063     {
1064         $parser = $this->createTestParser();
1065
1066         $result = $parser->parse('@Doctrine\Tests\Common\Annotations\True');
1067         $this->assertTrue($result[0] instanceof True);
1068         $result = $parser->parse('@Doctrine\Tests\Common\Annotations\False');
1069         $this->assertTrue($result[0] instanceof False);
1070         $result = $parser->parse('@Doctrine\Tests\Common\Annotations\Null');
1071         $this->assertTrue($result[0] instanceof Null);
1072
1073         $result = $parser->parse('@True');
1074         $this->assertTrue($result[0] instanceof True);
1075         $result = $parser->parse('@False');
1076         $this->assertTrue($result[0] instanceof False);
1077         $result = $parser->parse('@Null');
1078         $this->assertTrue($result[0] instanceof Null);
1079     }
1080
1081      /**
1082      * @expectedException Doctrine\Common\Annotations\AnnotationException
1083      * @expectedExceptionMessage [Creation Error] The annotation @SomeAnnotationClassNameWithoutConstructor declared on some class does not have a property named "invalidaProperty". Available properties: data, name
1084      */
1085     public function testSetValuesExeption()
1086     {
1087         $docblock = <<<DOCBLOCK
1088 /**
1089  * @SomeAnnotationClassNameWithoutConstructor(invalidaProperty = "Some val")
1090  */
1091 DOCBLOCK;
1092
1093         $this->createTestParser()->parse($docblock, 'some class');
1094     }
1095
1096     /**
1097      * @expectedException Doctrine\Common\Annotations\AnnotationException
1098      * @expectedExceptionMessage [Syntax Error] Expected Doctrine\Common\Annotations\DocLexer::T_IDENTIFIER or Doctrine\Common\Annotations\DocLexer::T_TRUE or Doctrine\Common\Annotations\DocLexer::T_FALSE or Doctrine\Common\Annotations\DocLexer::T_NULL, got '3.42' at position 5.
1099      */
1100     public function testInvalidIdentifierInAnnotation()
1101     {
1102         $parser = $this->createTestParser();
1103         $parser->parse('@Foo\3.42');
1104     }
1105
1106     public function testTrailingCommaIsAllowed()
1107     {
1108         $parser = $this->createTestParser();
1109
1110         $annots = $parser->parse('@Name({
1111             "Foo",
1112             "Bar",
1113         })');
1114         $this->assertEquals(1, count($annots));
1115         $this->assertEquals(array('Foo', 'Bar'), $annots[0]->value);
1116     }
1117
1118     public function testDefaultAnnotationValueIsNotOverwritten()
1119     {
1120         $parser = $this->createTestParser();
1121
1122         $annots = $parser->parse('@Doctrine\Tests\Common\Annotations\Fixtures\Annotation\AnnotWithDefaultValue');
1123         $this->assertEquals(1, count($annots));
1124         $this->assertEquals('bar', $annots[0]->foo);
1125     }
1126
1127     public function testArrayWithColon()
1128     {
1129         $parser = $this->createTestParser();
1130
1131         $annots = $parser->parse('@Name({"foo": "bar"})');
1132         $this->assertEquals(1, count($annots));
1133         $this->assertEquals(array('foo' => 'bar'), $annots[0]->value);
1134     }
1135
1136     /**
1137      * @expectedException Doctrine\Common\Annotations\AnnotationException
1138      * @expectedExceptionMessage [Semantical Error] Couldn't find constant foo.
1139      */
1140     public function testInvalidContantName()
1141     {
1142         $parser = $this->createTestParser();
1143         $parser->parse('@Name(foo: "bar")');
1144     }
1145 }
1146
1147 /** @Annotation */
1148 class SomeAnnotationClassNameWithoutConstructor
1149 {
1150     public $data;
1151     public $name;
1152 }
1153
1154 /** @Annotation */
1155 class SomeAnnotationWithConstructorWithoutParams
1156 {
1157     function __construct()
1158     {
1159         $this->data = "Some data";
1160     }
1161     public $data;
1162     public $name;
1163 }
1164
1165 /** @Annotation */
1166 class SomeAnnotationClassNameWithoutConstructorAndProperties{}
1167
1168 /**
1169  * @Annotation
1170  * @Target("Foo")
1171  */
1172 class AnnotationWithInvalidTargetDeclaration{}
1173
1174 /**
1175  * @Annotation
1176  * @Target
1177  */
1178 class AnnotationWithTargetEmpty{}
1179
1180 /** @Annotation */
1181 class AnnotationExtendsAnnotationTargetAll extends \Doctrine\Tests\Common\Annotations\Fixtures\AnnotationTargetAll
1182 {
1183 }
1184
1185 /** @Annotation */
1186 class Name extends \Doctrine\Common\Annotations\Annotation {
1187     public $foo;
1188 }
1189
1190 /** @Annotation */
1191 class Marker {
1192     public $value;
1193 }
1194
1195 /** @Annotation */
1196 class True {}
1197
1198 /** @Annotation */
1199 class False {}
1200
1201 /** @Annotation */
1202 class Null {}
1203
1204 namespace Doctrine\Tests\Common\Annotations\FooBar;
1205
1206 /** @Annotation */
1207 class Name extends \Doctrine\Common\Annotations\Annotation {
1208 }