testAnnotationWithAttributesWithVarTypeArrayError()   A
last analyzed

Complexity

Conditions 2
Paths 3

Size

Total Lines 12
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

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