Completed
Push — master ( 098f03...765465 )
by Ciaran
02:30 queued 11s
created

ClassMirrorTest   A

Complexity

Total Complexity 29

Size/Duplication

Total Lines 510
Duplicated Lines 23.14 %

Coupling/Cohesion

Components 1
Dependencies 6

Importance

Changes 0
Metric Value
wmc 29
lcom 1
cbo 6
dl 118
loc 510
rs 10
c 0
b 0
f 0

26 Methods

Rating   Name   Duplication   Size   Complexity  
A it_reflects_allowed_magic_methods() 10 10 1
A it_reflects_protected_abstract_methods() 0 15 1
A it_marks_required_args_without_types_as_not_optional() 19 19 1
A it_properly_reads_methods_arguments_with_types() 0 30 1
A it_properly_reads_methods_arguments_with_callable_types() 0 25 1
A it_properly_reads_methods_variadic_arguments() 18 18 1
A it_properly_reads_methods_typehinted_variadic_arguments() 0 22 2
A it_throws_an_exception_if_class_is_final() 0 8 1
A it_ignores_final_methods() 10 10 1
A it_marks_final_methods_as_unextendable() 0 11 1
A it_throws_an_exception_if_interface_provided_instead_of_class() 0 8 1
A it_reflects_all_interfaces_methods() 0 21 1
A it_ignores_virtually_private_methods() 0 13 1
A it_does_not_throw_exception_for_virtually_private_finals() 10 10 1
A it_reflects_return_typehints() 0 17 1
A it_throws_an_exception_if_class_provided_in_interfaces_list() 0 8 1
A it_throws_an_exception_if_not_reflection_provided_as_interface() 0 6 1
A it_doesnt_use_scalar_typehints() 12 12 1
A it_marks_passed_by_reference_args_as_passed_by_reference() 0 17 1
A it_doesnt_fail_on_array_nullable_parameter_with_not_null_default_value() 10 10 1
A it_doesnt_fail_when_method_is_extended_with_more_params() 14 14 1
A it_changes_argument_names_if_they_are_varying() 0 45 3
A it_reflects_public_static_methods() 15 15 1
A it_doesnt_fail_to_typehint_nonexistent_FQCN() 0 9 1
A it_doesnt_fail_to_typehint_nonexistent_RQCN() 0 9 1
A case_insensitive_method_names() 0 12 1

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

1
<?php
2
3
namespace Tests\Prophecy\Doubler\Generator;
4
5
use PHPUnit\Framework\TestCase;
6
use Prophecy\Doubler\Generator\ClassMirror;
7
8
class ClassMirrorTest extends TestCase
9
{
10
    /**
11
     * @test
12
     */
13 View Code Duplication
    public function it_reflects_allowed_magic_methods()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
14
    {
15
        $class = new \ReflectionClass('Fixtures\Prophecy\SpecialMethods');
16
17
        $mirror = new ClassMirror();
18
19
        $node = $mirror->reflect($class, array());
20
21
        $this->assertCount(7, $node->getMethods());
0 ignored issues
show
Documentation introduced by
$node->getMethods() is of type array<integer,object<Pro...rator\Node\MethodNode>>, but the function expects a object<Countable>|object...nit\Framework\iterable>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
22
    }
23
24
    /**
25
     * @test
26
     */
27
    public function it_reflects_protected_abstract_methods()
28
    {
29
        $class = new \ReflectionClass('Fixtures\Prophecy\WithProtectedAbstractMethod');
30
31
        $mirror = new ClassMirror();
32
33
        $classNode = $mirror->reflect($class, array());
34
35
        $this->assertEquals('Fixtures\Prophecy\WithProtectedAbstractMethod', $classNode->getParentClass());
36
37
        $methodNodes = $classNode->getMethods();
38
        $this->assertCount(1, $methodNodes);
0 ignored issues
show
Documentation introduced by
$methodNodes is of type array<integer,object<Pro...rator\Node\MethodNode>>, but the function expects a object<Countable>|object...nit\Framework\iterable>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
39
40
        $this->assertEquals('protected', $methodNodes['innerDetail']->getVisibility());
41
    }
42
43
    /**
44
     * @test
45
     */
46 View Code Duplication
    public function it_reflects_public_static_methods()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
47
    {
48
        $class = new \ReflectionClass('Fixtures\Prophecy\WithStaticMethod');
49
50
        $mirror = new ClassMirror();
51
52
        $classNode = $mirror->reflect($class, array());
53
54
        $this->assertEquals('Fixtures\Prophecy\WithStaticMethod', $classNode->getParentClass());
55
56
        $methodNodes = $classNode->getMethods();
57
        $this->assertCount(1, $methodNodes);
0 ignored issues
show
Documentation introduced by
$methodNodes is of type array<integer,object<Pro...rator\Node\MethodNode>>, but the function expects a object<Countable>|object...nit\Framework\iterable>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
58
59
        $this->assertTrue($methodNodes['innerDetail']->isStatic());
60
    }
61
62
    /**
63
     * @test
64
     */
65 View Code Duplication
    public function it_marks_required_args_without_types_as_not_optional()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
66
    {
67
        $class = new \ReflectionClass('Fixtures\Prophecy\WithArguments');
68
69
        $mirror = new ClassMirror();
70
71
        $classNode = $mirror->reflect($class, array());
72
        $methodNode = $classNode->getMethod('methodWithoutTypeHints');
73
        $argNodes = $methodNode->getArguments();
74
75
        $this->assertCount(1, $argNodes);
76
77
        $this->assertEquals('arg', $argNodes[0]->getName());
78
        $this->assertNull($argNodes[0]->getTypeHint());
79
        $this->assertFalse($argNodes[0]->isOptional());
80
        $this->assertNull($argNodes[0]->getDefault());
81
        $this->assertFalse($argNodes[0]->isPassedByReference());
82
        $this->assertFalse($argNodes[0]->isVariadic());
83
    }
84
85
    /**
86
     * @test
87
     */
88
    public function it_properly_reads_methods_arguments_with_types()
89
    {
90
        $class = new \ReflectionClass('Fixtures\Prophecy\WithArguments');
91
92
        $mirror = new ClassMirror();
93
94
        $classNode = $mirror->reflect($class, array());
95
        $methodNode = $classNode->getMethod('methodWithArgs');
96
        $argNodes = $methodNode->getArguments();
97
98
        $this->assertCount(3, $argNodes);
99
100
        $this->assertEquals('arg_1', $argNodes[0]->getName());
101
        $this->assertEquals('array', $argNodes[0]->getTypeHint());
102
        $this->assertTrue($argNodes[0]->isOptional());
103
        $this->assertEquals(array(), $argNodes[0]->getDefault());
104
        $this->assertFalse($argNodes[0]->isPassedByReference());
105
        $this->assertFalse($argNodes[0]->isVariadic());
106
107
        $this->assertEquals('arg_2', $argNodes[1]->getName());
108
        $this->assertEquals('ArrayAccess', $argNodes[1]->getTypeHint());
109
        $this->assertFalse($argNodes[1]->isOptional());
110
111
        $this->assertEquals('arg_3', $argNodes[2]->getName());
112
        $this->assertEquals('ArrayAccess', $argNodes[2]->getTypeHint());
113
        $this->assertTrue($argNodes[2]->isOptional());
114
        $this->assertNull($argNodes[2]->getDefault());
115
        $this->assertFalse($argNodes[2]->isPassedByReference());
116
        $this->assertFalse($argNodes[2]->isVariadic());
117
    }
118
119
    /**
120
     * @test
121
     * @requires PHP 5.4
122
     */
123
    public function it_properly_reads_methods_arguments_with_callable_types()
124
    {
125
        $class = new \ReflectionClass('Fixtures\Prophecy\WithCallableArgument');
126
127
        $mirror = new ClassMirror();
128
129
        $classNode = $mirror->reflect($class, array());
130
        $methodNode = $classNode->getMethod('methodWithArgs');
131
        $argNodes = $methodNode->getArguments();
132
133
        $this->assertCount(2, $argNodes);
134
135
        $this->assertEquals('arg_1', $argNodes[0]->getName());
136
        $this->assertEquals('callable', $argNodes[0]->getTypeHint());
137
        $this->assertFalse($argNodes[0]->isOptional());
138
        $this->assertFalse($argNodes[0]->isPassedByReference());
139
        $this->assertFalse($argNodes[0]->isVariadic());
140
141
        $this->assertEquals('arg_2', $argNodes[1]->getName());
142
        $this->assertEquals('callable', $argNodes[1]->getTypeHint());
143
        $this->assertTrue($argNodes[1]->isOptional());
144
        $this->assertNull($argNodes[1]->getDefault());
145
        $this->assertFalse($argNodes[1]->isPassedByReference());
146
        $this->assertFalse($argNodes[1]->isVariadic());
147
    }
148
149
    /**
150
     * @test
151
     * @requires PHP 5.6
152
     */
153 View Code Duplication
    public function it_properly_reads_methods_variadic_arguments()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
154
    {
155
        $class = new \ReflectionClass('Fixtures\Prophecy\WithVariadicArgument');
156
157
        $mirror = new ClassMirror();
158
159
        $classNode = $mirror->reflect($class, array());
160
        $methodNode = $classNode->getMethod('methodWithArgs');
161
        $argNodes = $methodNode->getArguments();
162
163
        $this->assertCount(1, $argNodes);
164
165
        $this->assertEquals('args', $argNodes[0]->getName());
166
        $this->assertNull($argNodes[0]->getTypeHint());
167
        $this->assertFalse($argNodes[0]->isOptional());
168
        $this->assertFalse($argNodes[0]->isPassedByReference());
169
        $this->assertTrue($argNodes[0]->isVariadic());
170
    }
171
172
    /**
173
     * @test
174
     * @requires PHP 5.6
175
     */
176
    public function it_properly_reads_methods_typehinted_variadic_arguments()
177
    {
178
        if (defined('HHVM_VERSION_ID')) {
179
            $this->markTestSkipped('HHVM does not support typehints on variadic arguments.');
180
        }
181
182
        $class = new \ReflectionClass('Fixtures\Prophecy\WithTypehintedVariadicArgument');
183
184
        $mirror = new ClassMirror();
185
186
        $classNode = $mirror->reflect($class, array());
187
        $methodNode = $classNode->getMethod('methodWithTypeHintedArgs');
188
        $argNodes = $methodNode->getArguments();
189
190
        $this->assertCount(1, $argNodes);
191
192
        $this->assertEquals('args', $argNodes[0]->getName());
193
        $this->assertEquals('array', $argNodes[0]->getTypeHint());
194
        $this->assertFalse($argNodes[0]->isOptional());
195
        $this->assertFalse($argNodes[0]->isPassedByReference());
196
        $this->assertTrue($argNodes[0]->isVariadic());
197
    }
198
199
    /**
200
     * @test
201
     */
202
    public function it_marks_passed_by_reference_args_as_passed_by_reference()
203
    {
204
        $class = new \ReflectionClass('Fixtures\Prophecy\WithReferences');
205
206
        $mirror = new ClassMirror();
207
208
        $classNode = $mirror->reflect($class, array());
209
210
        $this->assertTrue($classNode->hasMethod('methodWithReferenceArgument'));
211
212
        $argNodes = $classNode->getMethod('methodWithReferenceArgument')->getArguments();
213
214
        $this->assertCount(2, $argNodes);
215
216
        $this->assertTrue($argNodes[0]->isPassedByReference());
217
        $this->assertTrue($argNodes[1]->isPassedByReference());
218
    }
219
220
    /**
221
     * @test
222
     * @expectedException Prophecy\Exception\Doubler\ClassMirrorException
223
     */
224
    public function it_throws_an_exception_if_class_is_final()
225
    {
226
        $class = new \ReflectionClass('Fixtures\Prophecy\FinalClass');
227
228
        $mirror = new ClassMirror();
229
230
        $mirror->reflect($class, array());
231
    }
232
233
    /**
234
     * @test
235
     */
236 View Code Duplication
    public function it_ignores_final_methods()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
237
    {
238
        $class = new \ReflectionClass('Fixtures\Prophecy\WithFinalMethod');
239
240
        $mirror = new ClassMirror();
241
242
        $classNode = $mirror->reflect($class, array());
243
244
        $this->assertCount(0, $classNode->getMethods());
0 ignored issues
show
Documentation introduced by
$classNode->getMethods() is of type array<integer,object<Pro...rator\Node\MethodNode>>, but the function expects a object<Countable>|object...nit\Framework\iterable>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
245
    }
246
247
    /**
248
     * @test
249
     */
250
    public function it_marks_final_methods_as_unextendable()
251
    {
252
        $class = new \ReflectionClass('Fixtures\Prophecy\WithFinalMethod');
253
254
        $mirror = new ClassMirror();
255
256
        $classNode = $mirror->reflect($class, array());
257
258
        $this->assertCount(1, $classNode->getUnextendableMethods());
0 ignored issues
show
Documentation introduced by
$classNode->getUnextendableMethods() is of type array<integer,string>, but the function expects a object<Countable>|object...nit\Framework\iterable>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
259
        $this->assertFalse($classNode->isExtendable('finalImplementation'));
260
    }
261
262
    /**
263
     * @test
264
     * @expectedException Prophecy\Exception\InvalidArgumentException
265
     */
266
    public function it_throws_an_exception_if_interface_provided_instead_of_class()
267
    {
268
        $class = new \ReflectionClass('Fixtures\Prophecy\EmptyInterface');
269
270
        $mirror = new ClassMirror();
271
272
        $mirror->reflect($class, array());
273
    }
274
275
    /**
276
     * @test
277
     */
278
    public function it_reflects_all_interfaces_methods()
279
    {
280
        $mirror = new ClassMirror();
281
282
        $classNode = $mirror->reflect(null, array(
283
            new \ReflectionClass('Fixtures\Prophecy\Named'),
284
            new \ReflectionClass('Fixtures\Prophecy\ModifierInterface'),
285
        ));
286
287
        $this->assertEquals('stdClass', $classNode->getParentClass());
288
        $this->assertEquals(array(
289
            'Prophecy\Doubler\Generator\ReflectionInterface',
290
            'Fixtures\Prophecy\ModifierInterface',
291
            'Fixtures\Prophecy\Named',
292
        ), $classNode->getInterfaces());
293
294
        $this->assertCount(3, $classNode->getMethods());
0 ignored issues
show
Documentation introduced by
$classNode->getMethods() is of type array<integer,object<Pro...rator\Node\MethodNode>>, but the function expects a object<Countable>|object...nit\Framework\iterable>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
295
        $this->assertTrue($classNode->hasMethod('getName'));
296
        $this->assertTrue($classNode->hasMethod('isAbstract'));
297
        $this->assertTrue($classNode->hasMethod('getVisibility'));
298
    }
299
300
    /**
301
     * @test
302
     */
303
    public function it_ignores_virtually_private_methods()
304
    {
305
        $class = new \ReflectionClass('Fixtures\Prophecy\WithVirtuallyPrivateMethod');
306
307
        $mirror = new ClassMirror();
308
309
        $classNode = $mirror->reflect($class, array());
310
311
        $this->assertCount(2, $classNode->getMethods());
0 ignored issues
show
Documentation introduced by
$classNode->getMethods() is of type array<integer,object<Pro...rator\Node\MethodNode>>, but the function expects a object<Countable>|object...nit\Framework\iterable>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
312
        $this->assertTrue($classNode->hasMethod('isAbstract'));
313
        $this->assertTrue($classNode->hasMethod('__toString'));
314
        $this->assertFalse($classNode->hasMethod('_getName'));
315
    }
316
317
    /**
318
     * @test
319
     */
320 View Code Duplication
    public function it_does_not_throw_exception_for_virtually_private_finals()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
321
    {
322
        $class = new \ReflectionClass('Fixtures\Prophecy\WithFinalVirtuallyPrivateMethod');
323
324
        $mirror = new ClassMirror();
325
326
        $classNode = $mirror->reflect($class, array());
327
328
        $this->assertCount(0, $classNode->getMethods());
0 ignored issues
show
Documentation introduced by
$classNode->getMethods() is of type array<integer,object<Pro...rator\Node\MethodNode>>, but the function expects a object<Countable>|object...nit\Framework\iterable>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
329
    }
330
331
    /**
332
     * @test
333
     * @requires PHP 7
334
     */
335
    public function it_reflects_return_typehints()
336
    {
337
        $class = new \ReflectionClass('Fixtures\Prophecy\WithReturnTypehints');
338
339
        $mirror = new ClassMirror();
340
341
        $classNode = $mirror->reflect($class, array());
342
343
        $this->assertCount(3, $classNode->getMethods());
0 ignored issues
show
Documentation introduced by
$classNode->getMethods() is of type array<integer,object<Pro...rator\Node\MethodNode>>, but the function expects a object<Countable>|object...nit\Framework\iterable>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
344
        $this->assertTrue($classNode->hasMethod('getName'));
345
        $this->assertTrue($classNode->hasMethod('getSelf'));
346
        $this->assertTrue($classNode->hasMethod('getParent'));
347
348
        $this->assertEquals('string', $classNode->getMethod('getName')->getReturnType());
349
        $this->assertEquals('\Fixtures\Prophecy\WithReturnTypehints', $classNode->getMethod('getSelf')->getReturnType());
350
        $this->assertEquals('\Fixtures\Prophecy\EmptyClass', $classNode->getMethod('getParent')->getReturnType());
351
    }
352
353
    /**
354
     * @test
355
     * @expectedException InvalidArgumentException
356
     */
357
    public function it_throws_an_exception_if_class_provided_in_interfaces_list()
358
    {
359
        $class = new \ReflectionClass('Fixtures\Prophecy\EmptyClass');
360
361
        $mirror = new ClassMirror();
362
363
        $mirror->reflect(null, array($class));
364
    }
365
366
    /**
367
     * @test
368
     * @expectedException InvalidArgumentException
369
     */
370
    public function it_throws_an_exception_if_not_reflection_provided_as_interface()
371
    {
372
        $mirror = new ClassMirror();
373
374
        $mirror->reflect(null, array(null));
0 ignored issues
show
Documentation introduced by
array(null) is of type array<integer,null,{"0":"null"}>, but the function expects a array<integer,object<ReflectionClass>>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
375
    }
376
377
    /**
378
     * @test
379
     */
380 View Code Duplication
    public function it_doesnt_use_scalar_typehints()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
381
    {
382
        $mirror = new ClassMirror();
383
384
        $classNode = $mirror->reflect(new \ReflectionClass('ReflectionMethod'), array());
385
        $method = $classNode->getMethod('export');
386
        $arguments = $method->getArguments();
387
388
        $this->assertNull($arguments[0]->getTypeHint());
389
        $this->assertNull($arguments[1]->getTypeHint());
390
        $this->assertNull($arguments[2]->getTypeHint());
391
    }
392
393
    /**
394
     * @test
395
     */
396
    public function it_doesnt_fail_to_typehint_nonexistent_FQCN()
397
    {
398
        $mirror = new ClassMirror();
399
400
        $classNode = $mirror->reflect(new \ReflectionClass('Fixtures\Prophecy\OptionalDepsClass'), array());
401
        $method = $classNode->getMethod('iHaveAStrangeTypeHintedArg');
402
        $arguments = $method->getArguments();
403
        $this->assertEquals('I\Simply\Am\Nonexistent', $arguments[0]->getTypeHint());
404
    }
405
406
    /**
407
     * @test
408
     * @requires PHP 7.1
409
     */
410 View Code Duplication
    public function it_doesnt_fail_on_array_nullable_parameter_with_not_null_default_value()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
411
    {
412
        $mirror = new ClassMirror();
413
414
        $classNode = $mirror->reflect(new \ReflectionClass('Fixtures\Prophecy\NullableArrayParameter'), array());
415
        $method = $classNode->getMethod('iHaveNullableArrayParameterWithNotNullDefaultValue');
416
        $arguments = $method->getArguments();
417
        $this->assertSame('array', $arguments[0]->getTypeHint());
418
        $this->assertTrue($arguments[0]->isNullable());
419
    }
420
421
    /**
422
     * @test
423
     */
424
    public function it_doesnt_fail_to_typehint_nonexistent_RQCN()
425
    {
426
        $mirror = new ClassMirror();
427
428
        $classNode = $mirror->reflect(new \ReflectionClass('Fixtures\Prophecy\OptionalDepsClass'), array());
429
        $method = $classNode->getMethod('iHaveAnEvenStrangerTypeHintedArg');
430
        $arguments = $method->getArguments();
431
        $this->assertEquals('I\Simply\Am\Not', $arguments[0]->getTypeHint());
432
    }
433
434
    /**
435
     * @test
436
     * @requires PHP 7.2
437
     */
438 View Code Duplication
    function it_doesnt_fail_when_method_is_extended_with_more_params()
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
439
    {
440
        $mirror = new ClassMirror();
441
442
        $classNode = $mirror->reflect(
443
            new \ReflectionClass('Fixtures\Prophecy\MethodWithAdditionalParam'),
444
            array(new \ReflectionClass('Fixtures\Prophecy\Named'))
445
        );
446
        $method = $classNode->getMethod('getName');
447
        $this->assertCount(1, $method->getArguments());
448
449
        $method = $classNode->getMethod('methodWithoutTypeHints');
450
        $this->assertCount(2, $method->getArguments());
451
    }
452
453
    /**
454
     * @test
455
     */
456
    function it_changes_argument_names_if_they_are_varying()
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
457
    {
458
        // Use test doubles in this test, as arguments named ... in the Reflection API can only happen for internal classes
459
        $class = $this->prophesize('ReflectionClass');
460
        $method = $this->prophesize('ReflectionMethod');
461
        $parameter = $this->prophesize('ReflectionParameter');
462
463
        $class->getName()->willReturn('Custom\ClassName');
464
        $class->isInterface()->willReturn(false);
465
        $class->isFinal()->willReturn(false);
466
        $class->getMethods(\ReflectionMethod::IS_PUBLIC)->willReturn(array($method));
467
        $class->getMethods(\ReflectionMethod::IS_ABSTRACT)->willReturn(array());
468
469
        $method->getParameters()->willReturn(array($parameter));
470
        $method->getName()->willReturn('methodName');
471
        $method->isFinal()->willReturn(false);
472
        $method->isProtected()->willReturn(false);
473
        $method->isStatic()->willReturn(false);
474
        $method->returnsReference()->willReturn(false);
475
476
        if (version_compare(PHP_VERSION, '7.0', '>=')) {
477
            $method->hasReturnType()->willReturn(false);
478
        }
479
480
        $parameter->getName()->willReturn('...');
481
        $parameter->isDefaultValueAvailable()->willReturn(true);
482
        $parameter->getDefaultValue()->willReturn(null);
483
        $parameter->isPassedByReference()->willReturn(false);
484
        $parameter->allowsNull()->willReturn(true);
485
        $parameter->getClass()->willReturn($class);
486
        if (version_compare(PHP_VERSION, '5.6', '>=')) {
487
            $parameter->isVariadic()->willReturn(false);
488
        }
489
490
        $mirror = new ClassMirror();
491
492
        $classNode = $mirror->reflect($class->reveal(), array());
493
494
        $methodNodes = $classNode->getMethods();
495
496
        $argumentNodes = $methodNodes['methodName']->getArguments();
497
        $argumentNode = $argumentNodes[0];
498
499
        $this->assertEquals('__dot_dot_dot__', $argumentNode->getName());
500
    }
501
502
    /**
503
     * @test
504
     */
505
    public function case_insensitive_method_names()
506
    {
507
        $prophecy = $this->prophesize('ArrayObject');
508
        $prophecy->offsetGet(1)->willReturn(1)->shouldBeCalledTimes(1);
509
        $prophecy->offsetget(2)->willReturn(2)->shouldBeCalledTimes(1);
510
        $prophecy->OffsetGet(3)->willReturn(3)->shouldBeCalledTimes(1);
511
512
        $arrayObject = $prophecy->reveal();
513
        self::assertSame(1, $arrayObject->offsetGet(1));
514
        self::assertSame(2, $arrayObject->offsetGet(2));
515
        self::assertSame(3, $arrayObject->offsetGet(3));
516
    }
517
}
518