Viewing file: MockMethod.php (10.73 KB) -rw-r--r-- Select action/file-type: (+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
<?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\MockObject;
use const DIRECTORY_SEPARATOR; use function explode; use function implode; use function is_object; use function is_string; use function preg_match; use function preg_replace; use function sprintf; use function strlen; use function strpos; use function substr; use function substr_count; use function trim; use function var_export; use ReflectionMethod; use ReflectionParameter; use SebastianBergmann\Template\Exception as TemplateException; use SebastianBergmann\Template\Template; use SebastianBergmann\Type\ReflectionMapper; use SebastianBergmann\Type\Type; use SebastianBergmann\Type\UnknownType;
/** * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class MockMethod { /** * @var Template[] */ private static $templates = [];
/** * @var string */ private $className;
/** * @var string */ private $methodName;
/** * @var bool */ private $cloneArguments;
/** * @var string string */ private $modifier;
/** * @var string */ private $argumentsForDeclaration;
/** * @var string */ private $argumentsForCall;
/** * @var Type */ private $returnType;
/** * @var string */ private $reference;
/** * @var bool */ private $callOriginalMethod;
/** * @var bool */ private $static;
/** * @var ?string */ private $deprecation;
/** * @throws ReflectionException * @throws RuntimeException */ public static function fromReflection(ReflectionMethod $method, bool $callOriginalMethod, bool $cloneArguments): self { if ($method->isPrivate()) { $modifier = 'private'; } elseif ($method->isProtected()) { $modifier = 'protected'; } else { $modifier = 'public'; }
if ($method->isStatic()) { $modifier .= ' static'; }
if ($method->returnsReference()) { $reference = '&'; } else { $reference = ''; }
$docComment = $method->getDocComment();
if (is_string($docComment) && preg_match('#\*[ \t]*+@deprecated[ \t]*+(.*?)\r?+\n[ \t]*+\*(?:[ \t]*+@|/$)#s', $docComment, $deprecation)) { $deprecation = trim(preg_replace('#[ \t]*\r?\n[ \t]*+\*[ \t]*+#', ' ', $deprecation[1])); } else { $deprecation = null; }
return new self( $method->getDeclaringClass()->getName(), $method->getName(), $cloneArguments, $modifier, self::getMethodParametersForDeclaration($method), self::getMethodParametersForCall($method), (new ReflectionMapper)->fromReturnType($method), $reference, $callOriginalMethod, $method->isStatic(), $deprecation, ); }
public static function fromName(string $fullClassName, string $methodName, bool $cloneArguments): self { return new self( $fullClassName, $methodName, $cloneArguments, 'public', '', '', new UnknownType, '', false, false, null, ); }
public function __construct(string $className, string $methodName, bool $cloneArguments, string $modifier, string $argumentsForDeclaration, string $argumentsForCall, Type $returnType, string $reference, bool $callOriginalMethod, bool $static, ?string $deprecation) { $this->className = $className; $this->methodName = $methodName; $this->cloneArguments = $cloneArguments; $this->modifier = $modifier; $this->argumentsForDeclaration = $argumentsForDeclaration; $this->argumentsForCall = $argumentsForCall; $this->returnType = $returnType; $this->reference = $reference; $this->callOriginalMethod = $callOriginalMethod; $this->static = $static; $this->deprecation = $deprecation; }
public function getName(): string { return $this->methodName; }
/** * @throws RuntimeException */ public function generateCode(): string { if ($this->static) { $templateFile = 'mocked_static_method.tpl'; } elseif ($this->returnType->isNever() || $this->returnType->isVoid()) { $templateFile = sprintf( '%s_method_never_or_void.tpl', $this->callOriginalMethod ? 'proxied' : 'mocked', ); } else { $templateFile = sprintf( '%s_method.tpl', $this->callOriginalMethod ? 'proxied' : 'mocked', ); }
$deprecation = $this->deprecation;
if (null !== $this->deprecation) { $deprecation = "The {$this->className}::{$this->methodName} method is deprecated ({$this->deprecation})."; $deprecationTemplate = $this->getTemplate('deprecation.tpl');
$deprecationTemplate->setVar( [ 'deprecation' => var_export($deprecation, true), ], );
$deprecation = $deprecationTemplate->render(); }
$template = $this->getTemplate($templateFile);
$template->setVar( [ 'arguments_decl' => $this->argumentsForDeclaration, 'arguments_call' => $this->argumentsForCall, 'return_declaration' => !empty($this->returnType->asString()) ? (': ' . $this->returnType->asString()) : '', 'return_type' => $this->returnType->asString(), 'arguments_count' => !empty($this->argumentsForCall) ? substr_count($this->argumentsForCall, ',') + 1 : 0, 'class_name' => $this->className, 'method_name' => $this->methodName, 'modifier' => $this->modifier, 'reference' => $this->reference, 'clone_arguments' => $this->cloneArguments ? 'true' : 'false', 'deprecation' => $deprecation, ], );
return $template->render(); }
public function getReturnType(): Type { return $this->returnType; }
/** * @throws RuntimeException */ private function getTemplate(string $template): Template { $filename = __DIR__ . DIRECTORY_SEPARATOR . 'Generator' . DIRECTORY_SEPARATOR . $template;
if (!isset(self::$templates[$filename])) { try { self::$templates[$filename] = new Template($filename); } catch (TemplateException $e) { throw new RuntimeException( $e->getMessage(), $e->getCode(), $e, ); } }
return self::$templates[$filename]; }
/** * Returns the parameters of a function or method. * * @throws RuntimeException */ private static function getMethodParametersForDeclaration(ReflectionMethod $method): string { $parameters = []; $types = (new ReflectionMapper)->fromParameterTypes($method);
foreach ($method->getParameters() as $i => $parameter) { $name = '$' . $parameter->getName();
/* Note: PHP extensions may use empty names for reference arguments * or "..." for methods taking a variable number of arguments. */ if ($name === '$' || $name === '$...') { $name = '$arg' . $i; }
$default = ''; $reference = ''; $typeDeclaration = '';
if (!$types[$i]->type()->isUnknown()) { $typeDeclaration = $types[$i]->type()->asString() . ' '; }
if ($parameter->isPassedByReference()) { $reference = '&'; }
if ($parameter->isVariadic()) { $name = '...' . $name; } elseif ($parameter->isDefaultValueAvailable()) { $default = ' = ' . self::exportDefaultValue($parameter); } elseif ($parameter->isOptional()) { $default = ' = null'; }
$parameters[] = $typeDeclaration . $reference . $name . $default; }
return implode(', ', $parameters); }
/** * Returns the parameters of a function or method. * * @throws ReflectionException */ private static function getMethodParametersForCall(ReflectionMethod $method): string { $parameters = [];
foreach ($method->getParameters() as $i => $parameter) { $name = '$' . $parameter->getName();
/* Note: PHP extensions may use empty names for reference arguments * or "..." for methods taking a variable number of arguments. */ if ($name === '$' || $name === '$...') { $name = '$arg' . $i; }
if ($parameter->isVariadic()) { continue; }
if ($parameter->isPassedByReference()) { $parameters[] = '&' . $name; } else { $parameters[] = $name; } }
return implode(', ', $parameters); }
/** * @throws ReflectionException */ private static function exportDefaultValue(ReflectionParameter $parameter): string { try { $defaultValue = $parameter->getDefaultValue();
if (!is_object($defaultValue)) { return (string) var_export($defaultValue, true); }
$parameterAsString = $parameter->__toString();
return (string) explode( ' = ', substr( substr( $parameterAsString, strpos($parameterAsString, '<optional> ') + strlen('<optional> '), ), 0, -2, ), )[1]; // @codeCoverageIgnoreStart } catch (\ReflectionException $e) { throw new ReflectionException( $e->getMessage(), $e->getCode(), $e, ); } // @codeCoverageIgnoreEnd } }
|