/** * Initializes method prophecy. * * @param ObjectProphecy $objectProphecy * @param string $methodName * @param null|Argument\ArgumentsWildcard|array $arguments * * @throws \Prophecy\Exception\Doubler\MethodNotFoundException If method not found */ public function __construct(ObjectProphecy $objectProphecy, $methodName, $arguments = null) { $double = $objectProphecy->reveal(); if (!method_exists($double, $methodName)) { throw new MethodNotFoundException(sprintf('Method `%s::%s()` is not defined.', get_class($double), $methodName), get_class($double), $methodName, $arguments); } $this->objectProphecy = $objectProphecy; $this->methodName = $methodName; $reflectedMethod = new \ReflectionMethod($double, $methodName); if ($reflectedMethod->isFinal()) { throw new MethodProphecyException(sprintf("Can not add prophecy for a method `%s::%s()`\n" . "as it is a final method.", get_class($double), $methodName), $this); } if (null !== $arguments) { $this->withArguments($arguments); } if (version_compare(PHP_VERSION, '7.0', '>=') && true === $reflectedMethod->hasReturnType()) { $type = (string) $reflectedMethod->getReturnType(); $this->will(function () use($type) { switch ($type) { case 'string': return ''; case 'float': return 0.0; case 'int': return 0; case 'bool': return false; case 'array': return array(); case 'callable': case 'Closure': return function () { }; case 'Traversable': case 'Generator': // Remove eval() when minimum version >=5.5 /** @var callable $generator */ $generator = eval('return function () { yield; };'); return $generator(); default: $prophet = new Prophet(); return $prophet->prophesize($type)->reveal(); } }); } }
/** * @param $methodMirror * * @return string */ protected function describeMethod(ReflectionMethod $methodMirror) : string { if ($methodMirror->isProtected() || $methodMirror->isPrivate()) { return ''; } $this->parseDocComment($methodMirror->getDocComment(), 2); $output = "\t.. php:method:: " . $methodMirror->name . " ( "; $output .= $this->buildParameterList($methodMirror->getParameters()) . " )\n\n"; $output .= $this->describeParameters($methodMirror->getParameters()); if ($methodMirror->hasReturnType()) { $output .= "\t\t:returns: \n\t\t:rtype: {$methodMirror->getReturnType()}"; } $output .= "\n\n"; $output .= $this->currentDocString . "\n\n"; return $output; }
/** * @param ReflectionMethod $method * * @return bool */ private function hasReturnType(ReflectionMethod $method) { return method_exists('ReflectionMethod', 'hasReturnType') && $method->hasReturnType(); }
protected function buildMethodSignature(\ReflectionMethod $method, bool $skipAbstract = false, bool $skipDefaultValues = false) : string { if ($method->isProtected()) { $code = 'protected '; } elseif ($method->isPrivate()) { $code = 'private '; } else { $code = 'public '; } if ($method->isAbstract()) { if (!$skipAbstract) { $code .= 'abstract '; } } elseif ($method->isFinal()) { $code .= 'final '; } if ($method->isStatic()) { $code .= 'static '; } $code .= 'function '; if ($method->returnsReference()) { $code .= '& '; } $code .= $method->getName() . '('; foreach ($method->getParameters() as $i => $param) { if ($i > 0) { $code .= ', '; } $code .= $this->buildParameterSignature($param, $skipDefaultValues); } $code .= ')'; if ($method->hasReturnType()) { $type = $method->getReturnType(); if ($type->isBuiltin) { $code .= ': ' . $type; } else { $code .= ': \\' . $type; } } return $code; }
/** * @param ReflectionMethod $method * * @return bool */ private function allowsReturnNull(ReflectionMethod $method) { return method_exists(ReflectionMethod::class, 'getReturnType') && method_exists(ReflectionType::class, 'allowsNull') && $method->hasReturnType() && $method->getReturnType()->allowsNull(); }