Skip to content

Commit

Permalink
Closure::__invoke is not in PHP reflection
Browse files Browse the repository at this point in the history
  • Loading branch information
ondrejmirtes committed Jan 22, 2017
1 parent 254def8 commit adf5a28
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 3 deletions.
15 changes: 14 additions & 1 deletion src/Reflection/Php/PhpClassReflectionExtension.php
Expand Up @@ -137,7 +137,20 @@ public function getMethod(ClassReflection $classReflection, string $methodName):
private function createMethods(ClassReflection $classReflection): array
{
$methods = [];
foreach ($classReflection->getNativeReflection()->getMethods() as $methodReflection) {
$reflectionMethods = $classReflection->getNativeReflection()->getMethods();
if ($classReflection->getName() === \Closure::class || $classReflection->isSubclassOf(\Closure::class)) {
$hasInvokeMethod = false;
foreach ($reflectionMethods as $reflectionMethod) {
if ($reflectionMethod->getName() === '__invoke') {
$hasInvokeMethod = true;
break;
}
}
if (!$hasInvokeMethod) {
$reflectionMethods[] = $classReflection->getNativeReflection()->getMethod('__invoke');
}
}
foreach ($reflectionMethods as $methodReflection) {
$declaringClass = $this->broker->getClass($methodReflection->getDeclaringClass()->getName());

$phpDocParameterTypes = [];
Expand Down
25 changes: 23 additions & 2 deletions src/Reflection/Php/PhpMethodReflection.php
Expand Up @@ -189,6 +189,19 @@ public function getParameters(): array
true
);
}
if (
$this->declaringClass->getName() === 'Closure'
&& $this->reflection->getName() === '__invoke'
&& count($this->parameters) < 1
) {
$this->parameters[] = new DummyParameter(
'args',
new MixedType(),
true,
false,
true
);
}
}

return $this->parameters;
Expand All @@ -199,8 +212,16 @@ public function isVariadic(): bool
$isNativelyVariadic = $this->reflection->isVariadic();
if (
!$isNativelyVariadic
&& $this->declaringClass->getName() === 'ReflectionMethod'
&& $this->reflection->getName() === 'invoke'
&& (
(
$this->declaringClass->getName() === 'ReflectionMethod'
&& $this->reflection->getName() === 'invoke'
)
|| (
$this->declaringClass->getName() === 'Closure'
&& $this->reflection->getName() === '__invoke'
)
)
) {
return true;
}
Expand Down
5 changes: 5 additions & 0 deletions tests/PHPStan/Rules/Methods/data/call-methods.php
Expand Up @@ -133,4 +133,9 @@ public function acceptsString(string $foo)
function () {
$foo = new ClassWithToString();
$foo->acceptsString($foo);

$closure = function () {

};
$closure->__invoke(1, 2, 3);
};

0 comments on commit adf5a28

Please sign in to comment.