From 6a6411158db0a1d11af2bf1e053e917fe133d636 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 --- .../Doubler/Generator/ClassCodeGenerator.php | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/src/Prophecy/Doubler/Generator/ClassCodeGenerator.php b/src/Prophecy/Doubler/Generator/ClassCodeGenerator.php index ddc6985c..a34ad0f4 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()); + $types = $argument->getTypeNode()->getTypes(); + if ($nullable = $argument->isOptional() && $argument->getDefault() === NULL) { + $count = \count($types); + if ($count === 1 && $types[0] === 'mixed' ) { + $nullable = FALSE; + } + elseif ($count > 1 && !isset($types['null'])) { + $argument->setTypeNode(new ArgumentTypeNode('null', ...$argument->getTypeNode()->getNonNullTypes())); + $nullable = FALSE; + } + } + $php = $this->generateTypes($argument->getTypeNode(), $nullable); $php .= ' '.($argument->isPassedByReference() ? '&' : '');