Failed Conditions
Push — travis-php7.4 ( 6887c5 )
by Michael
13:05
created

getAnnotationVarTypeProviderInvalid()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 50
Code Lines 36

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 36
dl 0
loc 50
rs 9.344
c 0
b 0
f 0
cc 1
nc 1
nop 0
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]);
0 ignored issues
show
Deprecated Code introduced by
The function PHPUnit\Framework\Assert::assertInternalType() has been deprecated: https://github.com/sebastianbergmann/phpunit/issues/3369 ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

30
        /** @scrutinizer ignore-deprecated */ self::assertInternalType('array', $annot->foo[2]);

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
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);
0 ignored issues
show
Deprecated Code introduced by
The function PHPUnit\Framework\Assert::assertInternalType() has been deprecated: https://github.com/sebastianbergmann/phpunit/issues/3369 ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

52
        /** @scrutinizer ignore-deprecated */ self::assertInternalType('array', $annot->foo);

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
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);
0 ignored issues
show
Deprecated Code introduced by
The function PHPUnit\Framework\Assert::assertInternalType() has been deprecated: https://github.com/sebastianbergmann/phpunit/issues/3369 ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

58
        /** @scrutinizer ignore-deprecated */ self::assertInternalType('array', $annot->value);

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
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);
0 ignored issues
show
Deprecated Code introduced by
The function PHPUnit\Framework\Assert::assertInternalType() has been deprecated: https://github.com/sebastianbergmann/phpunit/issues/3369 ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

70
        /** @scrutinizer ignore-deprecated */ self::assertInternalType('array', $annot->value);

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
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);
0 ignored issues
show
Deprecated Code introduced by
The function PHPUnit\Framework\Assert::assertInternalType() has been deprecated: https://github.com/sebastianbergmann/phpunit/issues/3369 ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

79
        /** @scrutinizer ignore-deprecated */ self::assertInternalType('array', $annot->value);

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
80
        self::assertInstanceOf(Name::class, $annot->value[0]);
81
        self::assertInternalType('array', $annot->value[1]);
0 ignored issues
show
Deprecated Code introduced by
The function PHPUnit\Framework\Assert::assertInternalType() has been deprecated: https://github.com/sebastianbergmann/phpunit/issues/3369 ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

81
        /** @scrutinizer ignore-deprecated */ self::assertInternalType('array', $annot->value[1]);

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
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);
0 ignored issues
show
Deprecated Code introduced by
The function PHPUnit\Framework\Assert::assertInternalType() has been deprecated: https://github.com/sebastianbergmann/phpunit/issues/3369 ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

112
        /** @scrutinizer ignore-deprecated */ self::assertInternalType('array', $annot->value);

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
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);
0 ignored issues
show
Deprecated Code introduced by
The function PHPUnit\Framework\Assert::assertInternalType() has been deprecated: https://github.com/sebastianbergmann/phpunit/issues/3369 ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

120
        /** @scrutinizer ignore-deprecated */ self::assertInternalType('array', $annot->value);

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
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);
0 ignored issues
show
Deprecated Code introduced by
The function PHPUnit\Framework\Assert::assertInternalType() has been deprecated: https://github.com/sebastianbergmann/phpunit/issues/3369 ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

1200
        /** @scrutinizer ignore-deprecated */ self::assertInternalType('int', $annot->foo);

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
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);
0 ignored issues
show
Deprecated Code introduced by
The function PHPUnit\Framework\Assert::assertInternalType() has been deprecated: https://github.com/sebastianbergmann/phpunit/issues/3369 ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

1212
        /** @scrutinizer ignore-deprecated */ self::assertInternalType('int', $annot->foo);

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
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);
0 ignored issues
show
Deprecated Code introduced by
The function PHPUnit\Framework\Assert::assertInternalType() has been deprecated: https://github.com/sebastianbergmann/phpunit/issues/3369 ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

1224
        /** @scrutinizer ignore-deprecated */ self::assertInternalType('float', $annot->foo);

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
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);
0 ignored issues
show
Deprecated Code introduced by
The function PHPUnit\Framework\Assert::assertInternalType() has been deprecated: https://github.com/sebastianbergmann/phpunit/issues/3369 ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

1236
        /** @scrutinizer ignore-deprecated */ self::assertInternalType('float', $annot->foo);

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
1237
1238
        $result = $parser->parse('@Marker(-1234.345)');
1239
        $annot = $result[0];
1240
        self::assertInternalType('float', $annot->value);
0 ignored issues
show
Deprecated Code introduced by
The function PHPUnit\Framework\Assert::assertInternalType() has been deprecated: https://github.com/sebastianbergmann/phpunit/issues/3369 ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

1240
        /** @scrutinizer ignore-deprecated */ self::assertInternalType('float', $annot->value);

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
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