Failed Conditions
Pull Request — new-parser-ast-metadata (#5)
by
unknown
02:14
created

testGetMethodAnnotations()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 3
dl 0
loc 7
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 3
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Doctrine\Tests\Annotations;
6
7
use Doctrine\Annotations\Annotation\IgnoreAnnotation;
8
use Doctrine\Annotations\Assembler\Constant\ReflectionConstantResolver;
9
use Doctrine\Annotations\Assembler\Validator\Exception\InvalidTarget;
10
use Doctrine\Annotations\Assembler\Validator\Exception\InvalidValue;
11
use Doctrine\Annotations\Metadata\MetadataCollection;
12
use Doctrine\Annotations\Metadata\Reflection\DefaultReflectionProvider;
13
use Doctrine\Annotations\NewAnnotationReader;
14
use Hoa\Compiler\Exception\UnrecognizedToken;
15
use PHPUnit\Framework\TestCase;
16
use ReflectionClass;
17
use ReflectionException;
18
use ReflectionMethod;
19
use ReflectionProperty;
20
use TopLevelAnnotation;
21
22
class NewAnnotationReaderTest extends TestCase
23
{
24
    /** @var MetadataCollection */
25
    private $collection;
26
27
    /** @var NewAnnotationReader */
28
    private $reader;
29
30
    public function setUp() : void
31
    {
32
        $this->collection = new MetadataCollection();
33
        $this->reader     = new NewAnnotationReader(
34
            $this->collection,
35
            new DefaultReflectionProvider(),
36
            new ReflectionConstantResolver(new DefaultReflectionProvider())
37
        );
38
    }
39
40
    /**
41
     * @dataProvider classAnnotationExamples
42
     */
43
    public function testGetClassAnnotations(string $className, callable $expectedFactory) : void
44
    {
45
        $class = new ReflectionClass($className);
46
47
        $annotations = $this->reader->getClassAnnotations($class);
48
49
        $this->assertEquals($expectedFactory(), $annotations);
50
    }
51
52
    /**
53
     * @return mixed[]
54
     */
55
    public function classAnnotationExamples() : iterable
56
    {
57
        yield 'ClassWithAnnotationTargetAll' => [
0 ignored issues
show
Bug Best Practice introduced by
The expression yield 'ClassWithAnnotati...ion(...) { /* ... */ }) returns the type Generator which is incompatible with the documented return type array<mixed,mixed>.
Loading history...
58
            Fixtures\ClassWithAnnotationTargetAll::class,
59
            static function () : array {
60
                $annotation       = new Fixtures\AnnotationTargetAll();
61
                $annotation->name = '123';
62
63
                return [$annotation];
64
            },
65
        ];
66
67
        yield 'ClassWithValidAnnotationTarget' => [
68
            Fixtures\ClassWithValidAnnotationTarget::class,
69
            static function () : array {
70
                $annotation       = new Fixtures\AnnotationTargetClass();
71
                $annotation->data = 'Some data';
72
73
                return [$annotation];
74
            },
75
        ];
76
77
        yield 'DummyClassWithDanglingComma' => [
78
            DummyClassWithDanglingComma::class,
79
            static function () : array {
80
                return [new DummyAnnotation(['dummyValue' => 'bar'])];
81
            },
82
        ];
83
84
        yield 'ClassWithRequire' => [
85
            Fixtures\ClassWithRequire::class,
86
            static function () : array {
87
                return [new DummyAnnotationWithIgnoredAnnotation(['dummyValue' => 'hello'])];
88
            },
89
        ];
90
91
        yield 'TestIgnoresNonAnnotationsClass' => [
92
            TestIgnoresNonAnnotationsClass::class,
93
            static function () : array {
94
                return [new Name([])];
95
            },
96
        ];
97
98
        yield 'InvalidAnnotationUsageButIgnoredClass' => [
99
            Fixtures\InvalidAnnotationUsageButIgnoredClass::class,
100
            static function () : array {
101
                $routeAnnotation       = new Fixtures\Annotation\Route();
102
                $routeAnnotation->name = 'foo';
103
104
                return [
105
                    new IgnoreAnnotation(['NoAnnotation']),
106
                    $routeAnnotation,
107
                ];
108
            },
109
        ];
110
111
        yield 'InvalidAnnotationButIgnored - DDC-1660' => [
112
            Fixtures\ClassDDC1660::class,
113
            static function () : array {
114
                return [];
115
            },
116
        ];
117
118
        yield 'ignore case insensitivity - DCOM-106' => [
119
            DCOM106::class,
120
            static function () : array {
121
                return [];
122
            },
123
        ];
124
    }
125
126
    /**
127
     * @dataProvider invalidClassAnnotationExamples
128
     */
129
    public function testGetInvalidClassAnnotations(string $className, string $expectedException) : void
130
    {
131
        $class = new ReflectionClass($className);
132
133
        $this->expectException($expectedException);
134
135
        $this->reader->getClassAnnotations($class);
136
    }
137
138
    /**
139
     * @return mixed[]
140
     */
141
    public function invalidClassAnnotationExamples() : iterable
142
    {
143
        yield 'ClassWithAnnotationTargetAll' => [
0 ignored issues
show
Bug Best Practice introduced by
The expression yield 'ClassWithAnnotati...n\InvalidTarget::class) returns the type Generator which is incompatible with the documented return type array<mixed,mixed>.
Loading history...
144
            Fixtures\ClassWithInvalidAnnotationTargetAtClass::class,
145
            InvalidTarget::class,
146
        ];
147
148
        yield 'ClassWithAnnotationWithTargetSyntaxError' => [
149
            Fixtures\ClassWithAnnotationWithTargetSyntaxError::class,
150
            UnrecognizedToken::class,
151
        ];
152
153
        yield 'DummyClassSyntaxError' => [
154
            DummyClassSyntaxError::class,
155
            UnrecognizedToken::class,
156
        ];
157
158
        yield 'InvalidAnnotationUsageClass' => [
159
            Fixtures\InvalidAnnotationUsageClass::class,
160
            UnrecognizedToken::class,
161
        ];
162
    }
163
164
    /**
165
     * @dataProvider methodAnnotationExamples
166
     */
167
    public function testGetMethodAnnotations(string $className, string $methodName, callable $expectedFactory) : void
168
    {
169
        $method = new ReflectionMethod($className, $methodName);
170
171
        $annotations = $this->reader->getMethodAnnotations($method);
172
173
        $this->assertEquals($expectedFactory(), $annotations);
174
    }
175
176
    /**
177
     * @return mixed[]
178
     */
179
    public function methodAnnotationExamples() : iterable
180
    {
181
        yield 'ClassWithAnnotationWithVarType - bar' => [
0 ignored issues
show
Bug Best Practice introduced by
The expression yield 'ClassWithAnnotati...ion(...) { /* ... */ }) returns the type Generator which is incompatible with the documented return type array<mixed,mixed>.
Loading history...
182
            Fixtures\ClassWithAnnotationWithVarType::class,
183
            'bar',
184
            static function () : array {
185
                $annotation             = new Fixtures\AnnotationWithVarType();
186
                $annotation->annotation = new Fixtures\AnnotationTargetAll();
187
188
                return [$annotation];
189
            },
190
        ];
191
192
        yield 'InvalidAnnotationButIgnored - DDC-1660 - bar' => [
193
            Fixtures\ClassDDC1660::class,
194
            'bar',
195
            static function () : array {
196
                return [];
197
            },
198
        ];
199
    }
200
201
    /**
202
     * @dataProvider invalidMethodAnnotationExamples
203
     */
204
    public function testGetInvalidMethodAnnotations(string $className, string $methodName, string $expectedException) : void
205
    {
206
        $method = new ReflectionMethod($className, $methodName);
207
208
        $this->expectException($expectedException);
209
210
        $this->reader->getMethodAnnotations($method);
211
    }
212
213
    /**
214
     * @return mixed[]
215
     */
216
    public function invalidMethodAnnotationExamples() : iterable
217
    {
218
        yield 'ClassWithInvalidAnnotationTargetAtMethod - functionName' => [
0 ignored issues
show
Bug Best Practice introduced by
The expression yield 'ClassWithInvalidA...n\InvalidTarget::class) returns the type Generator which is incompatible with the documented return type array<mixed,mixed>.
Loading history...
219
            Fixtures\ClassWithInvalidAnnotationTargetAtMethod::class,
220
            'functionName',
221
            InvalidTarget::class,
222
        ];
223
224
        yield 'ClassWithAnnotationWithTargetSyntaxError - bar' => [
225
            Fixtures\ClassWithAnnotationWithTargetSyntaxError::class,
226
            'bar',
227
            UnrecognizedToken::class,
228
        ];
229
230
        yield 'ClassWithAnnotationWithVarType - invalidMethod' => [
231
            Fixtures\ClassWithAnnotationWithVarType::class,
232
            'invalidMethod',
233
            InvalidValue::class,
234
        ];
235
236
        yield 'DummyClassMethodSyntaxError - foo' => [
237
            DummyClassMethodSyntaxError::class,
238
            'foo',
239
            UnrecognizedToken::class,
240
        ];
241
242
        yield 'ClassWithAnnotationEnum - invalid value - bar' => [
243
            Fixtures\ClassWithAnnotationEnum::class,
244
            'bar',
245
            InvalidValue::class,
246
        ];
247
    }
248
249
    /**
250
     * @dataProvider propertyAnnotationExamples
251
     */
252
    public function testGetPropertyAnnotations(string $className, string $propertyName, callable $expectedFactory) : void
253
    {
254
        $property = new ReflectionProperty($className, $propertyName);
255
256
        $annotations = $this->reader->getPropertyAnnotations($property);
257
258
        $this->assertEquals($expectedFactory(), $annotations);
259
    }
260
261
    /**
262
     * @return mixed[]
263
     */
264
    public function propertyAnnotationExamples() : iterable
265
    {
266
        yield 'ClassWithValidAnnotationTarget - foo' => [
0 ignored issues
show
Bug Best Practice introduced by
The expression yield 'ClassWithValidAnn...ion(...) { /* ... */ }) returns the type Generator which is incompatible with the documented return type array<mixed,mixed>.
Loading history...
267
            Fixtures\ClassWithValidAnnotationTarget::class,
268
            'foo',
269
            static function () : array {
270
                $annotation       = new Fixtures\AnnotationTargetPropertyMethod();
271
                $annotation->data = 'Some data';
272
273
                return [$annotation];
274
            },
275
        ];
276
277
        yield 'ClassWithValidAnnotationTarget - name' => [
278
            Fixtures\ClassWithValidAnnotationTarget::class,
279
            'name',
280
            static function () : array {
281
                $annotation       = new Fixtures\AnnotationTargetAll();
282
                $annotation->data = 'Some data';
283
                $annotation->name = 'Some name';
284
285
                return [$annotation];
286
            },
287
        ];
288
289
        yield 'ClassWithAnnotationWithVarType - bar' => [
290
            Fixtures\ClassWithAnnotationWithVarType::class,
291
            'foo',
292
            static function () : array {
293
                $annotation         = new Fixtures\AnnotationWithVarType();
294
                $annotation->string = 'String Value';
295
296
                return [$annotation];
297
            },
298
        ];
299
300
        yield 'ClassWithAtInDescriptionAndAnnotation - foo' => [
301
            Fixtures\ClassWithAtInDescriptionAndAnnotation::class,
302
            'foo',
303
            static function () : array {
304
                $annotation       = new Fixtures\AnnotationTargetPropertyMethod();
305
                $annotation->data = 'Bar';
306
307
                return [$annotation];
308
            },
309
        ];
310
311
        yield 'ClassWithAtInDescriptionAndAnnotation - bar' => [
312
            Fixtures\ClassWithAtInDescriptionAndAnnotation::class,
313
            'bar',
314
            static function () : array {
315
                $annotation       = new Fixtures\AnnotationTargetPropertyMethod();
316
                $annotation->data = 'Bar';
317
318
                return [$annotation];
319
            },
320
        ];
321
322
        yield 'DummyClass2 - id - multiple annotations on the same line' => [
323
            DummyClass2::class,
324
            'id',
325
            static function () : array {
326
                return [
327
                    new DummyId([]),
328
                    new DummyColumn(['type' => 'integer']),
329
                    new DummyGeneratedValue([]),
330
                ];
331
            },
332
        ];
333
334
        yield 'DummyClassNonAnnotationProblem - foo' => [
335
            DummyClassNonAnnotationProblem::class,
336
            'foo',
337
            static function () : array {
338
                return [new DummyAnnotation([])];
339
            },
340
        ];
341
342
        yield 'TestParentClass - child' => [
343
            TestParentClass::class,
344
            'child',
345
            static function () : array {
346
                return [new Foo\Name(['name' => 'foo']),
347
                ];
348
            },
349
        ];
350
351
        yield 'TestParentClass - parent' => [
352
            TestParentClass::class,
353
            'parent',
354
            static function () : array {
355
                return [new Bar\Name(['name' => 'bar']),
356
                ];
357
            },
358
        ];
359
360
        yield 'TestTopLevelAnnotationClass - field' => [
361
            TestTopLevelAnnotationClass::class,
362
            'field',
363
            static function () : array {
364
                return [new TopLevelAnnotation([])];
365
            },
366
        ];
367
368
        yield 'InvalidAnnotationButIgnored - DDC-1660 - foo' => [
369
            Fixtures\ClassDDC1660::class,
370
            'foo',
371
            static function () : array {
372
                return [];
373
            },
374
        ];
375
    }
376
377
    /**
378
     * @dataProvider invalidPropertyAnnotationExamples
379
     */
380
    public function testGetInvalidPropertyAnnotations(string $className, string $methodName, string $expectedException) : void
381
    {
382
        $property = new ReflectionProperty($className, $methodName);
383
384
        $this->expectException($expectedException);
385
386
        $this->reader->getPropertyAnnotations($property);
387
    }
388
389
    /**
390
     * @return mixed[]
391
     */
392
    public function invalidPropertyAnnotationExamples() : iterable
393
    {
394
        yield 'ClassWithInvalidAnnotationTargetAtProperty - foo' => [
0 ignored issues
show
Bug Best Practice introduced by
The expression yield 'ClassWithInvalidA...n\InvalidTarget::class) returns the type Generator which is incompatible with the documented return type array<mixed,mixed>.
Loading history...
395
            Fixtures\ClassWithInvalidAnnotationTargetAtProperty::class,
396
            'foo',
397
            InvalidTarget::class,
398
        ];
399
400
        yield 'ClassWithInvalidAnnotationTargetAtProperty - bar' => [
401
            Fixtures\ClassWithInvalidAnnotationTargetAtProperty::class,
402
            'bar',
403
            InvalidTarget::class,
404
        ];
405
406
        yield 'ClassWithAnnotationWithTargetSyntaxError - foo' => [
407
            Fixtures\ClassWithAnnotationWithTargetSyntaxError::class,
408
            'foo',
409
            UnrecognizedToken::class,
410
        ];
411
412
        yield 'ClassWithAnnotationWithVarType - invalidProperty' => [
413
            Fixtures\ClassWithAnnotationWithVarType::class,
414
            'invalidProperty',
415
            InvalidValue::class,
416
        ];
417
418
        yield 'DummyClassPropertySyntaxError - foo' => [
419
            DummyClassPropertySyntaxError::class,
420
            'foo',
421
            UnrecognizedToken::class,
422
        ];
423
424
        yield 'TestAnnotationNotImportedClass - field' => [
425
            TestAnnotationNotImportedClass::class,
426
            'field',
427
            ReflectionException::class,
428
        ];
429
430
        yield 'TestNonExistentAnnotationClass - field' => [
431
            TestNonExistentAnnotationClass::class,
432
            'field',
433
            ReflectionException::class,
434
        ];
435
436
        yield 'ClassWithAnnotationEnum - invalid value - foo' => [
437
            Fixtures\ClassWithAnnotationEnum::class,
438
            'foo',
439
            InvalidValue::class,
440
        ];
441
    }
442
}
443