Failed Conditions
Push — metadata ( c6c11e...d7114b )
by Michael
02:19
created

DocParserTest::testBasicAnnotations()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 64
Code Lines 47

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 47
dl 0
loc 64
rs 9.1563
c 0
b 0
f 0
cc 1
nc 1
nop 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace Doctrine\Tests\Annotations;
4
5
use Doctrine\Annotations\AnnotationException;
6
use Doctrine\Annotations\DocParser;
7
use Doctrine\Annotations\Annotation\Target;
8
use Doctrine\Tests\Annotations\Fixtures\AnnotationTargetAll;
9
use Doctrine\Tests\Annotations\Fixtures\AnnotationWithConstants;
10
use Doctrine\Tests\Annotations\Fixtures\ClassWithConstants;
11
use Doctrine\Tests\Annotations\Fixtures\InterfaceWithConstants;
12
use PHPUnit\Framework\TestCase;
13
14
class DocParserTest extends 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
        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
    }
1380
}
1381
1382
/** @Annotation */
1383
class SettingsAnnotation
1384
{
1385
    public $settings;
1386
1387
    public function __construct($settings)
1388
    {
1389
        $this->settings = $settings;
1390
    }
1391
}
1392
1393
/** @Annotation */
1394
class SomeAnnotationClassNameWithoutConstructor
1395
{
1396
    public $data;
1397
    public $name;
1398
}
1399
1400
/** @Annotation */
1401
class SomeAnnotationWithConstructorWithoutParams
1402
{
1403
    public function __construct()
1404
    {
1405
        $this->data = 'Some data';
1406
    }
1407
    public $data;
1408
    public $name;
1409
}
1410
1411
/** @Annotation */
1412
class SomeAnnotationClassNameWithoutConstructorAndProperties{}
1413
1414
/**
1415
 * @Annotation
1416
 * @Target("Foo")
1417
 */
1418
class AnnotationWithInvalidTargetDeclaration{}
1419
1420
/**
1421
 * @Annotation
1422
 * @Target
1423
 */
1424
class AnnotationWithTargetEmpty{}
1425
1426
/** @Annotation */
1427
class AnnotationExtendsAnnotationTargetAll extends AnnotationTargetAll
1428
{
1429
}
1430
1431
/** @Annotation */
1432
class Name {
1433
    public $value;
1434
    public $foo;
1435
}
1436
1437
/** @Annotation */
1438
class Marker {
1439
    public $value;
1440
}
1441
1442
namespace Doctrine\Tests\Annotations\FooBar;
1443
1444
/** @Annotation */
1445
class Name {
1446
}
1447