Completed
Pull Request — master (#274)
by Christophe
04:43
created

ClassMirrorTest   A

Complexity

Total Complexity 24

Size/Duplication

Total Lines 447
Duplicated Lines 0 %

Coupling/Cohesion

Components 2
Dependencies 6

Importance

Changes 0
Metric Value
wmc 24
c 0
b 0
f 0
lcom 2
cbo 6
dl 0
loc 447
rs 10

22 Methods

Rating   Name   Duplication   Size   Complexity  
A it_reflects_allowed_magic_methods() 0 10 1
A it_reflects_protected_abstract_methods() 0 15 1
A it_reflects_public_static_methods() 0 15 1
A it_marks_required_args_without_types_as_not_optional() 0 19 1
B it_properly_reads_methods_arguments_with_types() 0 30 1
B it_properly_reads_methods_arguments_with_callable_types() 0 25 1
B it_properly_reads_methods_variadic_arguments() 0 29 1
A it_marks_passed_by_reference_args_as_passed_by_reference() 0 17 1
A it_throws_an_exception_if_class_is_final() 0 10 1
A it_ignores_final_methods() 0 10 1
A it_marks_final_methods_as_unextendable() 0 11 1
A it_throws_an_exception_if_interface_provided_instead_of_class() 0 10 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() 0 10 1
A it_reflects_return_typehints() 0 17 1
A it_throws_an_exception_if_class_provided_in_interfaces_list() 0 10 1
A it_throws_an_exception_if_not_reflection_provided_as_interface() 0 8 1
A it_doesnt_use_scalar_typehints() 0 12 1
A it_doesnt_fail_to_typehint_nonexistent_FQCN() 0 9 1
A it_doesnt_fail_to_typehint_nonexistent_RQCN() 0 9 1
B it_changes_argument_names_if_they_are_varying() 0 44 3
1
<?php
2
3
namespace Tests\Prophecy\Doubler\Generator;
4
5
use Prophecy\Doubler\Generator\ClassMirror;
6
7
class ClassMirrorTest extends \PHPUnit_Framework_TestCase
8
{
9
    /**
10
     * @test
11
     */
12
    public function it_reflects_allowed_magic_methods()
13
    {
14
        $class = new \ReflectionClass('Fixtures\Prophecy\SpecialMethods');
15
16
        $mirror = new ClassMirror();
17
18
        $node = $mirror->reflect($class, array());
19
20
        $this->assertCount(7, $node->getMethods());
21
    }
22
23
    /**
24
     * @test
25
     */
26
    public function it_reflects_protected_abstract_methods()
27
    {
28
        $class = new \ReflectionClass('Fixtures\Prophecy\WithProtectedAbstractMethod');
29
30
        $mirror = new ClassMirror();
31
32
        $classNode = $mirror->reflect($class, array());
33
34
        $this->assertEquals('Fixtures\Prophecy\WithProtectedAbstractMethod', $classNode->getParentClass());
35
36
        $methodNodes = $classNode->getMethods();
37
        $this->assertCount(1, $methodNodes);
38
39
        $this->assertEquals('protected', $methodNodes['innerDetail']->getVisibility());
40
    }
41
42
    /**
43
     * @test
44
     */
45
    public function it_reflects_public_static_methods()
46
    {
47
        $class = new \ReflectionClass('Fixtures\Prophecy\WithStaticMethod');
48
49
        $mirror = new ClassMirror();
50
51
        $classNode = $mirror->reflect($class, array());
52
53
        $this->assertEquals('Fixtures\Prophecy\WithStaticMethod', $classNode->getParentClass());
54
55
        $methodNodes = $classNode->getMethods();
56
        $this->assertCount(1, $methodNodes);
57
58
        $this->assertTrue($methodNodes['innerDetail']->isStatic());
59
    }
60
61
    /**
62
     * @test
63
     */
64
    public function it_marks_required_args_without_types_as_not_optional()
65
    {
66
        $class = new \ReflectionClass('Fixtures\Prophecy\WithArguments');
67
68
        $mirror = new ClassMirror();
69
70
        $classNode = $mirror->reflect($class, array());
71
        $methodNode = $classNode->getMethod('methodWithoutTypeHints');
72
        $argNodes = $methodNode->getArguments();
73
74
        $this->assertCount(1, $argNodes);
75
76
        $this->assertEquals('arg', $argNodes[0]->getName());
77
        $this->assertNull($argNodes[0]->getTypeHint());
78
        $this->assertFalse($argNodes[0]->isOptional());
79
        $this->assertNull($argNodes[0]->getDefault());
80
        $this->assertFalse($argNodes[0]->isPassedByReference());
81
        $this->assertFalse($argNodes[0]->isVariadic());
82
    }
83
84
    /**
85
     * @test
86
     */
87
    public function it_properly_reads_methods_arguments_with_types()
88
    {
89
        $class = new \ReflectionClass('Fixtures\Prophecy\WithArguments');
90
91
        $mirror = new ClassMirror();
92
93
        $classNode = $mirror->reflect($class, array());
94
        $methodNode = $classNode->getMethod('methodWithArgs');
95
        $argNodes = $methodNode->getArguments();
96
97
        $this->assertCount(3, $argNodes);
98
99
        $this->assertEquals('arg_1', $argNodes[0]->getName());
100
        $this->assertEquals('array', $argNodes[0]->getTypeHint());
101
        $this->assertTrue($argNodes[0]->isOptional());
102
        $this->assertEquals(array(), $argNodes[0]->getDefault());
103
        $this->assertFalse($argNodes[0]->isPassedByReference());
104
        $this->assertFalse($argNodes[0]->isVariadic());
105
106
        $this->assertEquals('arg_2', $argNodes[1]->getName());
107
        $this->assertEquals('ArrayAccess', $argNodes[1]->getTypeHint());
108
        $this->assertFalse($argNodes[1]->isOptional());
109
110
        $this->assertEquals('arg_3', $argNodes[2]->getName());
111
        $this->assertEquals('ArrayAccess', $argNodes[2]->getTypeHint());
112
        $this->assertTrue($argNodes[2]->isOptional());
113
        $this->assertNull($argNodes[2]->getDefault());
114
        $this->assertFalse($argNodes[2]->isPassedByReference());
115
        $this->assertFalse($argNodes[2]->isVariadic());
116
    }
117
118
    /**
119
     * @test
120
     * @requires PHP 5.4
121
     */
122
    public function it_properly_reads_methods_arguments_with_callable_types()
123
    {
124
        $class = new \ReflectionClass('Fixtures\Prophecy\WithCallableArgument');
125
126
        $mirror = new ClassMirror();
127
128
        $classNode = $mirror->reflect($class, array());
129
        $methodNode = $classNode->getMethod('methodWithArgs');
130
        $argNodes = $methodNode->getArguments();
131
132
        $this->assertCount(2, $argNodes);
133
134
        $this->assertEquals('arg_1', $argNodes[0]->getName());
135
        $this->assertEquals('callable', $argNodes[0]->getTypeHint());
136
        $this->assertFalse($argNodes[0]->isOptional());
137
        $this->assertFalse($argNodes[0]->isPassedByReference());
138
        $this->assertFalse($argNodes[0]->isVariadic());
139
140
        $this->assertEquals('arg_2', $argNodes[1]->getName());
141
        $this->assertEquals('callable', $argNodes[1]->getTypeHint());
142
        $this->assertTrue($argNodes[1]->isOptional());
143
        $this->assertNull($argNodes[1]->getDefault());
144
        $this->assertFalse($argNodes[1]->isPassedByReference());
145
        $this->assertFalse($argNodes[1]->isVariadic());
146
    }
147
148
    /**
149
     * @test
150
     * @requires PHP 5.6
151
     */
152
    public function it_properly_reads_methods_variadic_arguments()
153
    {
154
        $class = new \ReflectionClass('Fixtures\Prophecy\WithVariadicArgument');
155
156
        $mirror = new ClassMirror();
157
158
        $classNode = $mirror->reflect($class, array());
159
        $methodNode = $classNode->getMethod('methodWithArgs');
160
        $argNodes = $methodNode->getArguments();
161
162
        $this->assertCount(1, $argNodes);
163
164
        $this->assertEquals('args', $argNodes[0]->getName());
165
        $this->assertNull($argNodes[0]->getTypeHint());
166
        $this->assertFalse($argNodes[0]->isOptional());
167
        $this->assertFalse($argNodes[0]->isPassedByReference());
168
        $this->assertTrue($argNodes[0]->isVariadic());
169
170
        $methodNode = $classNode->getMethod('methodWithTypeHintedArgs');
171
        $argNodes = $methodNode->getArguments();
172
173
        $this->assertCount(1, $argNodes);
174
175
        $this->assertEquals('args', $argNodes[0]->getName());
176
        $this->assertEquals('array', $argNodes[0]->getTypeHint());
177
        $this->assertFalse($argNodes[0]->isOptional());
178
        $this->assertFalse($argNodes[0]->isPassedByReference());
179
        $this->assertTrue($argNodes[0]->isVariadic());
180
    }
181
182
    /**
183
     * @test
184
     */
185
    public function it_marks_passed_by_reference_args_as_passed_by_reference()
186
    {
187
        $class = new \ReflectionClass('Fixtures\Prophecy\WithReferences');
188
189
        $mirror = new ClassMirror();
190
191
        $classNode = $mirror->reflect($class, array());
192
193
        $this->assertTrue($classNode->hasMethod('methodWithReferenceArgument'));
194
195
        $argNodes = $classNode->getMethod('methodWithReferenceArgument')->getArguments();
196
197
        $this->assertCount(2, $argNodes);
198
199
        $this->assertTrue($argNodes[0]->isPassedByReference());
200
        $this->assertTrue($argNodes[1]->isPassedByReference());
201
    }
202
203
    /**
204
     * @test
205
     */
206
    public function it_throws_an_exception_if_class_is_final()
207
    {
208
        $class = new \ReflectionClass('Fixtures\Prophecy\FinalClass');
209
210
        $mirror = new ClassMirror();
211
212
        $this->setExpectedException('Prophecy\Exception\Doubler\ClassMirrorException');
0 ignored issues
show
Deprecated Code introduced by
The method PHPUnit_Framework_TestCase::setExpectedException() has been deprecated with message: Method deprecated since Release 5.2.0

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

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

Loading history...
213
214
        $mirror->reflect($class, array());
215
    }
216
217
    /**
218
     * @test
219
     */
220
    public function it_ignores_final_methods()
221
    {
222
        $class = new \ReflectionClass('Fixtures\Prophecy\WithFinalMethod');
223
224
        $mirror = new ClassMirror();
225
226
        $classNode = $mirror->reflect($class, array());
227
228
        $this->assertCount(0, $classNode->getMethods());
229
    }
230
231
    /**
232
     * @test
233
     */
234
    public function it_marks_final_methods_as_unextendable()
235
    {
236
        $class = new \ReflectionClass('Fixtures\Prophecy\WithFinalMethod');
237
238
        $mirror = new ClassMirror();
239
240
        $classNode = $mirror->reflect($class, array());
241
242
        $this->assertCount(1, $classNode->getUnextendableMethods());
243
        $this->assertFalse($classNode->isExtendable('finalImplementation'));
244
    }
245
246
    /**
247
     * @test
248
     */
249
    public function it_throws_an_exception_if_interface_provided_instead_of_class()
250
    {
251
        $class = new \ReflectionClass('Fixtures\Prophecy\EmptyInterface');
252
253
        $mirror = new ClassMirror();
254
255
        $this->setExpectedException('Prophecy\Exception\InvalidArgumentException');
0 ignored issues
show
Deprecated Code introduced by
The method PHPUnit_Framework_TestCase::setExpectedException() has been deprecated with message: Method deprecated since Release 5.2.0

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

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

Loading history...
256
257
        $mirror->reflect($class, array());
258
    }
259
260
    /**
261
     * @test
262
     */
263
    public function it_reflects_all_interfaces_methods()
264
    {
265
        $mirror = new ClassMirror();
266
267
        $classNode = $mirror->reflect(null, array(
268
            new \ReflectionClass('Fixtures\Prophecy\Named'),
269
            new \ReflectionClass('Fixtures\Prophecy\ModifierInterface'),
270
        ));
271
272
        $this->assertEquals('stdClass', $classNode->getParentClass());
273
        $this->assertEquals(array(
274
            'Prophecy\Doubler\Generator\ReflectionInterface',
275
            'Fixtures\Prophecy\ModifierInterface',
276
            'Fixtures\Prophecy\Named',
277
        ), $classNode->getInterfaces());
278
279
        $this->assertCount(3, $classNode->getMethods());
280
        $this->assertTrue($classNode->hasMethod('getName'));
281
        $this->assertTrue($classNode->hasMethod('isAbstract'));
282
        $this->assertTrue($classNode->hasMethod('getVisibility'));
283
    }
284
285
    /**
286
     * @test
287
     */
288
    public function it_ignores_virtually_private_methods()
289
    {
290
        $class = new \ReflectionClass('Fixtures\Prophecy\WithVirtuallyPrivateMethod');
291
292
        $mirror = new ClassMirror();
293
294
        $classNode = $mirror->reflect($class, array());
295
296
        $this->assertCount(2, $classNode->getMethods());
297
        $this->assertTrue($classNode->hasMethod('isAbstract'));
298
        $this->assertTrue($classNode->hasMethod('__toString'));
299
        $this->assertFalse($classNode->hasMethod('_getName'));
300
    }
301
302
    /**
303
     * @test
304
     */
305
    public function it_does_not_throw_exception_for_virtually_private_finals()
306
    {
307
        $class = new \ReflectionClass('Fixtures\Prophecy\WithFinalVirtuallyPrivateMethod');
308
309
        $mirror = new ClassMirror();
310
311
        $classNode = $mirror->reflect($class, array());
312
313
        $this->assertCount(0, $classNode->getMethods());
314
    }
315
316
    /**
317
     * @test
318
     * @requires PHP 7
319
     */
320
    public function it_reflects_return_typehints()
321
    {
322
        $class = new \ReflectionClass('Fixtures\Prophecy\WithReturnTypehints');
323
324
        $mirror = new ClassMirror();
325
326
        $classNode = $mirror->reflect($class, array());
327
328
        $this->assertCount(3, $classNode->getMethods());
329
        $this->assertTrue($classNode->hasMethod('getName'));
330
        $this->assertTrue($classNode->hasMethod('getSelf'));
331
        $this->assertTrue($classNode->hasMethod('getParent'));
332
333
        $this->assertEquals('string', $classNode->getMethod('getName')->getReturnType());
334
        $this->assertEquals('\Fixtures\Prophecy\WithReturnTypehints', $classNode->getMethod('getSelf')->getReturnType());
335
        $this->assertEquals('\Fixtures\Prophecy\EmptyClass', $classNode->getMethod('getParent')->getReturnType());
336
    }
337
338
    /**
339
     * @test
340
     */
341
    public function it_throws_an_exception_if_class_provided_in_interfaces_list()
342
    {
343
        $class = new \ReflectionClass('Fixtures\Prophecy\EmptyClass');
344
345
        $mirror = new ClassMirror();
346
347
        $this->setExpectedException('InvalidArgumentException');
0 ignored issues
show
Deprecated Code introduced by
The method PHPUnit_Framework_TestCase::setExpectedException() has been deprecated with message: Method deprecated since Release 5.2.0

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

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

Loading history...
348
349
        $mirror->reflect(null, array($class));
350
    }
351
352
    /**
353
     * @test
354
     */
355
    public function it_throws_an_exception_if_not_reflection_provided_as_interface()
356
    {
357
        $mirror = new ClassMirror();
358
359
        $this->setExpectedException('InvalidArgumentException');
0 ignored issues
show
Deprecated Code introduced by
The method PHPUnit_Framework_TestCase::setExpectedException() has been deprecated with message: Method deprecated since Release 5.2.0

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

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

Loading history...
360
361
        $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...
362
    }
363
364
    /**
365
     * @test
366
     */
367
    public function it_doesnt_use_scalar_typehints()
368
    {
369
        $mirror = new ClassMirror();
370
371
        $classNode = $mirror->reflect(new \ReflectionClass('ReflectionMethod'), array());
372
        $method = $classNode->getMethod('export');
373
        $arguments = $method->getArguments();
374
375
        $this->assertNull($arguments[0]->getTypeHint());
376
        $this->assertNull($arguments[1]->getTypeHint());
377
        $this->assertNull($arguments[2]->getTypeHint());
378
    }
379
380
    /**
381
     * @test
382
     */
383
    public function it_doesnt_fail_to_typehint_nonexistent_FQCN()
384
    {
385
        $mirror = new ClassMirror();
386
387
        $classNode = $mirror->reflect(new \ReflectionClass('Fixtures\Prophecy\OptionalDepsClass'), array());
388
        $method = $classNode->getMethod('iHaveAStrangeTypeHintedArg');
389
        $arguments = $method->getArguments();
390
        $this->assertEquals('I\Simply\Am\Nonexistent', $arguments[0]->getTypeHint());
391
    }
392
393
    /**
394
     * @test
395
     */
396
    public function it_doesnt_fail_to_typehint_nonexistent_RQCN()
397
    {
398
        $mirror = new ClassMirror();
399
400
        $classNode = $mirror->reflect(new \ReflectionClass('Fixtures\Prophecy\OptionalDepsClass'), array());
401
        $method = $classNode->getMethod('iHaveAnEvenStrangerTypeHintedArg');
402
        $arguments = $method->getArguments();
403
        $this->assertEquals('I\Simply\Am\Not', $arguments[0]->getTypeHint());
404
    }
405
406
    /**
407
     * @test
408
     */
409
    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...
410
    {
411
        // Use test doubles in this test, as arguments named ... in the Reflection API can only happen for internal classes
412
        $class = $this->prophesize('ReflectionClass');
413
        $method = $this->prophesize('ReflectionMethod');
414
        $parameter = $this->prophesize('ReflectionParameter');
415
416
        $class->getName()->willReturn('Custom\ClassName');
1 ignored issue
show
Documentation Bug introduced by
The method getName does not exist on object<Prophecy\Prophecy\ObjectProphecy>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
417
        $class->isInterface()->willReturn(false);
1 ignored issue
show
Documentation Bug introduced by
The method isInterface does not exist on object<Prophecy\Prophecy\ObjectProphecy>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
418
        $class->isFinal()->willReturn(false);
1 ignored issue
show
Documentation Bug introduced by
The method isFinal does not exist on object<Prophecy\Prophecy\ObjectProphecy>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
419
        $class->getMethods(\ReflectionMethod::IS_PUBLIC)->willReturn(array($method));
1 ignored issue
show
Documentation Bug introduced by
The method getMethods does not exist on object<Prophecy\Prophecy\ObjectProphecy>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
420
        $class->getMethods(\ReflectionMethod::IS_ABSTRACT)->willReturn(array());
1 ignored issue
show
Documentation Bug introduced by
The method getMethods does not exist on object<Prophecy\Prophecy\ObjectProphecy>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
421
422
        $method->getParameters()->willReturn(array($parameter));
1 ignored issue
show
Documentation Bug introduced by
The method getParameters does not exist on object<Prophecy\Prophecy\ObjectProphecy>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
423
        $method->getName()->willReturn('methodName');
1 ignored issue
show
Documentation Bug introduced by
The method getName does not exist on object<Prophecy\Prophecy\ObjectProphecy>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
424
        $method->isFinal()->willReturn(false);
1 ignored issue
show
Documentation Bug introduced by
The method isFinal does not exist on object<Prophecy\Prophecy\ObjectProphecy>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
425
        $method->isProtected()->willReturn(false);
1 ignored issue
show
Documentation Bug introduced by
The method isProtected does not exist on object<Prophecy\Prophecy\ObjectProphecy>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
426
        $method->isStatic()->willReturn(false);
1 ignored issue
show
Documentation Bug introduced by
The method isStatic does not exist on object<Prophecy\Prophecy\ObjectProphecy>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
427
        $method->returnsReference()->willReturn(false);
1 ignored issue
show
Documentation Bug introduced by
The method returnsReference does not exist on object<Prophecy\Prophecy\ObjectProphecy>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
428
429
        if (version_compare(PHP_VERSION, '7.0', '>=')) {
430
            $method->hasReturnType()->willReturn(false);
1 ignored issue
show
Documentation Bug introduced by
The method hasReturnType does not exist on object<Prophecy\Prophecy\ObjectProphecy>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
431
        }
432
433
        $parameter->getName()->willReturn('...');
1 ignored issue
show
Documentation Bug introduced by
The method getName does not exist on object<Prophecy\Prophecy\ObjectProphecy>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
434
        $parameter->isDefaultValueAvailable()->willReturn(true);
1 ignored issue
show
Documentation Bug introduced by
The method isDefaultValueAvailable does not exist on object<Prophecy\Prophecy\ObjectProphecy>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
435
        $parameter->getDefaultValue()->willReturn(null);
1 ignored issue
show
Documentation Bug introduced by
The method getDefaultValue does not exist on object<Prophecy\Prophecy\ObjectProphecy>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
436
        $parameter->isPassedByReference()->willReturn(false);
1 ignored issue
show
Documentation Bug introduced by
The method isPassedByReference does not exist on object<Prophecy\Prophecy\ObjectProphecy>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
437
        $parameter->getClass()->willReturn($class);
1 ignored issue
show
Documentation Bug introduced by
The method getClass does not exist on object<Prophecy\Prophecy\ObjectProphecy>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
438
        if (version_compare(PHP_VERSION, '5.6', '>=')) {
439
            $parameter->isVariadic()->willReturn(false);
1 ignored issue
show
Documentation Bug introduced by
The method isVariadic does not exist on object<Prophecy\Prophecy\ObjectProphecy>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
440
        }
441
442
        $mirror = new ClassMirror();
443
444
        $classNode = $mirror->reflect($class->reveal(), array());
445
446
        $methodNodes = $classNode->getMethods();
447
448
        $argumentNodes = $methodNodes['methodName']->getArguments();
449
        $argumentNode = $argumentNodes[0];
450
451
        $this->assertEquals('__dot_dot_dot__', $argumentNode->getName());
452
    }
453
}
454