From a3f0761a90b44ff75b11fd52884d952d143724a0 Mon Sep 17 00:00:00 2001 From: Andy Postnikov Date: Wed, 14 Aug 2024 03:24:36 +0200 Subject: [PATCH] Fix generator for PHP >= 8.4 #624 --- .../Generator/ClassCodeGeneratorSpec.php | 4 ++-- .../Doubler/Generator/ClassCodeGenerator.php | 18 +++++++++++++++--- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/spec/Prophecy/Doubler/Generator/ClassCodeGeneratorSpec.php b/spec/Prophecy/Doubler/Generator/ClassCodeGeneratorSpec.php index 50fb1704c..3d8cf4484 100644 --- a/spec/Prophecy/Doubler/Generator/ClassCodeGeneratorSpec.php +++ b/spec/Prophecy/Doubler/Generator/ClassCodeGeneratorSpec.php @@ -116,7 +116,7 @@ class CustomClass extends \RuntimeException implements \Prophecy\Doubler\Generat public $name; private $email; -public static function getName(array $fullname = NULL, \ReflectionClass $class, object $instance): ?string { +public static function getName(?array $fullname = NULL, \ReflectionClass $class, object $instance): ?string { return $this->name; } protected function getEmail(?string $default = 'ever.zet@gmail.com') { @@ -272,7 +272,7 @@ function it_overrides_properly_methods_with_args_passed_by_reference( namespace { class CustomClass extends \RuntimeException implements \Prophecy\Doubler\Generator\MirroredInterface { -public function getName(array &$fullname = NULL) { +public function getName(?array &$fullname = NULL) { return $this->name; } diff --git a/src/Prophecy/Doubler/Generator/ClassCodeGenerator.php b/src/Prophecy/Doubler/Generator/ClassCodeGenerator.php index ddc6985cd..70b6171bd 100644 --- a/src/Prophecy/Doubler/Generator/ClassCodeGenerator.php +++ b/src/Prophecy/Doubler/Generator/ClassCodeGenerator.php @@ -11,6 +11,7 @@ namespace Prophecy\Doubler\Generator; +use Prophecy\Doubler\Generator\Node\ArgumentTypeNode; use Prophecy\Doubler\Generator\Node\ReturnTypeNode; use Prophecy\Doubler\Generator\Node\TypeNodeAbstract; @@ -78,14 +79,14 @@ private function generateMethod(Node\MethodNode $method): string return $php.'}'; } - private function generateTypes(TypeNodeAbstract $typeNode): string + private function generateTypes(TypeNodeAbstract $typeNode, bool $nullable = FALSE): string { if (!$typeNode->getTypes()) { return ''; } // When we require PHP 8 we can stop generating ?foo nullables and remove this first block - if ($typeNode->canUseNullShorthand()) { + if ($typeNode->canUseNullShorthand() || $nullable) { return sprintf( '?%s', $typeNode->getNonNullTypes()[0]); } else { return join('|', $typeNode->getTypes()); @@ -101,7 +102,18 @@ private function generateArguments(array $arguments): array { return array_map(function (Node\ArgumentNode $argument){ - $php = $this->generateTypes($argument->getTypeNode()); + if ($nullable = $argument->isOptional() && $argument->getDefault() === NULL) { + $types = $argument->getTypeNode()->getTypes(); + $count = \count($types); + if ($count === 1 && $types[0] === 'mixed' ) { + $nullable = FALSE; + } + elseif ($count > 1 && !isset($types['null'])) { + $argument->setTypeNode(new ArgumentTypeNode('null', ...$types)); + $nullable = FALSE; + } + } + $php = $this->generateTypes($argument->getTypeNode(), $nullable); $php .= ' '.($argument->isPassedByReference() ? '&' : '');