public function getReturnType() : Type { if ($this->returnType === null) { $this->returnType = TypehintHelper::decideType($this->reflection->getReturnType(), $this->phpDocReturnType, $this->declaringClass->getName()); } return $this->returnType; }
public function getReturnType() : Type { if ($this->returnType === null) { $returnType = $this->reflection->getReturnType(); $phpDocReturnType = $this->phpDocReturnType; if ($returnType !== null && $phpDocReturnType !== null && $returnType->allowsNull() !== $phpDocReturnType->isNullable()) { $phpDocReturnType = null; } $this->returnType = TypehintHelper::decideTypeFromReflection($returnType, $phpDocReturnType, $this->declaringClass->getName()); } return $this->returnType; }
private function updateDefinition(ContainerBuilder $container, $id, Definition $definition, array $previous = array()) { // circular reference if (isset($previous[$id])) { return; } $factory = $definition->getFactory(); if (null === $factory || null !== $definition->getClass()) { return; } $class = null; if (is_string($factory)) { try { $m = new \ReflectionFunction($factory); } catch (\ReflectionException $e) { return; } } else { if ($factory[0] instanceof Reference) { $previous[$id] = true; $factoryDefinition = $container->findDefinition((string) $factory[0]); $this->updateDefinition($container, (string) $factory[0], $factoryDefinition, $previous); $class = $factoryDefinition->getClass(); } else { $class = $factory[0]; } try { $m = new \ReflectionMethod($class, $factory[1]); } catch (\ReflectionException $e) { return; } } $returnType = $m->getReturnType(); if (null !== $returnType && !$returnType->isBuiltin()) { $returnType = (string) $returnType; if (null !== $class) { $declaringClass = $m->getDeclaringClass()->getName(); if ('self' === $returnType) { $returnType = $declaringClass; } elseif ('parent' === $returnType) { $returnType = get_parent_class($declaringClass) ?: null; } } $definition->setClass($returnType); } }
/** * 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 \ReflectionMethod $method * * @return TypeInfoMember|null */ protected function methodToTypeInfoMember(\ReflectionMethod $method) { if (substr($method->name, 0, 2) === '__') { return; } $docb = new DocBlock($method); $hint = $docb->getComment() ?: ''; $link = $docb->getTag('link', '') ?: ''; if (is_array($link)) { $link = $link[0]; } if ($docb->tagExists('param')) { // detect return from docblock $return = explode(' ', $docb->getTag('return', 'void'), 2)[0]; } else { // detect return from reflection $return = $this->canInspectReflectionReturnType ? $method->getReturnType() : ''; } if ($docb->tagExists('param')) { // detect params from docblock $params = array_map([$this, 'parseDocBlockPropOrParam'], $docb->getTag('param', [], true)); } else { // detect params from reflection $params = array_map([$this, 'parseReflectedParams'], $method->getParameters()); } $signature = sprintf('<div class="cm-signature">' . '<span class="type">%s</span> <span class="name">%s</span>' . '(<span class="args">%s</span>)</span>' . '</div>', $return, $method->name, implode(', ', array_map(function ($param) { $result = '???'; if ($param) { $result = sprintf('<span class="%s" title="%s"><span class="type">%s</span>$%s</span>', $param['hint'] ? 'arg hint' : 'arg', $param['hint'], count($param['types']) ? implode('|', $param['types']) . ' ' : '', $param['name']); } return $result; }, $params))); return new TypeInfoMember($method->name, ['method'], $signature . $hint, $link); }
<?php $f = function (stdClass $x) : stdClass { }; $r = new ReflectionMethod($f, '__invoke'); var_dump($r->getParameters()[0]->getName()); var_dump($r->getParameters()[0]->getClass()); echo $r->getParameters()[0], "\n"; echo $r->getReturnType(), "\n"; echo $r, "\n";
/** * @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; }
<?php $closure = function (Test $x) : Test2 { return new Test2($x); }; $rm = new ReflectionMethod($closure, '__invoke'); $rp = $rm->getParameters()[0]; $rt = $rp->getType(); $rrt = $rm->getReturnType(); unset($rm, $rp); var_dump((string) $rt, (string) $rrt);
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(); }