diff --git a/src/DocBlock/Tags/Factory/MethodFactory.php b/src/DocBlock/Tags/Factory/MethodFactory.php index 920be84..51dc042 100644 --- a/src/DocBlock/Tags/Factory/MethodFactory.php +++ b/src/DocBlock/Tags/Factory/MethodFactory.php @@ -57,7 +57,7 @@ final class MethodFactory implements PHPStanFactory ), $param->isReference, $param->isVariadic, - (string) $param->defaultValue + $param->defaultValue ); }, $tagValue->parameters diff --git a/src/DocBlock/Tags/Factory/MethodParameterFactory.php b/src/DocBlock/Tags/Factory/MethodParameterFactory.php new file mode 100644 index 0000000..8fd16f2 --- /dev/null +++ b/src/DocBlock/Tags/Factory/MethodParameterFactory.php @@ -0,0 +1,81 @@ +{$method}($defaultValue); + } + return ''; + } + + protected function formatDouble(float $defaultValue): string + { + return var_export($defaultValue, true); + } + + protected function formatNull($defaultValue): string + { + return 'null'; + } + + protected function formatInteger(int $defaultValue): string + { + return var_export($defaultValue, true); + } + + protected function formatString(string $defaultValue): string + { + return var_export($defaultValue, true); + } + + protected function formatBoolean(bool $defaultValue): string + { + return var_export($defaultValue, true); + } + + protected function formatArray(array $defaultValue): string + { + $formatedValue = '['; + + foreach ($defaultValue as $key => $value) { + if (method_exists($this, $method = 'format'.ucfirst(gettype($value)))) { + $formatedValue .= $this->{$method}($value); + + if ($key !== array_key_last($defaultValue)) { + $formatedValue .= ','; + } + } + } + + $formatedValue .= ']'; + + return $formatedValue; + } + + protected function formatObject(object $defaultValue): string + { + return 'new '. get_class($defaultValue). '()'; + } +} diff --git a/src/DocBlock/Tags/Method.php b/src/DocBlock/Tags/Method.php index 5fad2f3..41e0eed 100644 --- a/src/DocBlock/Tags/Method.php +++ b/src/DocBlock/Tags/Method.php @@ -261,18 +261,7 @@ final class Method extends BaseTag implements Factory\StaticMethod { $arguments = []; foreach ($this->parameters as $parameter) { - $parameterDefaultValueStr = null; - if ($parameter->getDefaultValue() !== null) { - $parameterDefaultValueStr = $parameter->getDefaultValue(); - settype($parameterDefaultValueStr, (string)$parameter->getType()); - $parameterDefaultValueStr = sprintf(' = %s', var_export($parameterDefaultValueStr, true)); - } - - $arguments[] = $parameter->getType() . ' ' . - ($parameter->isReference() ? '&' : '') . - ($parameter->isVariadic() ? '...' : '') . - '$' . $parameter->getName() . - ($parameterDefaultValueStr ?? ''); + $arguments[] = (string) $parameter; } $argumentStr = '(' . implode(', ', $arguments) . ')'; diff --git a/src/DocBlock/Tags/MethodParameter.php b/src/DocBlock/Tags/MethodParameter.php index 0c85d41..72d2c4a 100644 --- a/src/DocBlock/Tags/MethodParameter.php +++ b/src/DocBlock/Tags/MethodParameter.php @@ -12,6 +12,7 @@ declare(strict_types=1); namespace phpDocumentor\Reflection\DocBlock\Tags; +use phpDocumentor\Reflection\DocBlock\Tags\Factory\MethodParameterFactory; use phpDocumentor\Reflection\Type; final class MethodParameter @@ -24,14 +25,16 @@ final class MethodParameter private string $name; - private ?string $defaultValue = null; + private mixed $defaultValue; + + private const NO_DEFAULT_VALUE = '__NO_VALUE__'; public function __construct( string $name, Type $type, bool $isReference = false, bool $isVariadic = false, - ?string $defaultValue = null + $defaultValue = self::NO_DEFAULT_VALUE ) { $this->type = $type; $this->isReference = $isReference; @@ -60,8 +63,17 @@ final class MethodParameter return $this->isVariadic; } - public function getDefaultValue(): ?string + public function getDefaultValue(): mixed { return $this->defaultValue; } + + public function __toString(): string + { + return $this->getType() . ' ' . + ($this->isReference() ? '&' : '') . + ($this->isVariadic() ? '...' : '') . + '$' . $this->getName() . + ($this->getDefaultValue() !== self::NO_DEFAULT_VALUE ? (new MethodParameterFactory)->format($this->getDefaultValue()) : ''); + } } diff --git a/tests/unit/DocBlock/Tags/MethodParameterTest.php b/tests/unit/DocBlock/Tags/MethodParameterTest.php new file mode 100644 index 0000000..08d4f0e --- /dev/null +++ b/tests/unit/DocBlock/Tags/MethodParameterTest.php @@ -0,0 +1,104 @@ + + */ +class MethodParameterTest extends TestCase +{ + /** + * Call Mockery::close after each test. + */ + public function tearDown(): void + { + m::close(); + } + + public function collectionDefaultValuesProvider(): array + { + return [ + [new String_(), '1', '\'1\''], + [new Integer(), 1, '1'], + [new Boolean(), true, 'true'], + [new Float_(), 1.23, '1.23'], + [new Array_(), [1, '2', true], '[1,\'2\',true]'], + [new Array_(), [[1, 2], '2', true], '[[1,2],\'2\',true]'], + [new Nullable(new Float_()), null, 'null'], + [new Nullable(new Float_()), 1.23, '1.23'], + [new Object_(new Fqsen('\\stdClass')), new \stdClass(), 'new stdClass()'], + ]; + } + + /** + * @uses \phpDocumentor\Reflection\DocBlock\Tags\MethodParameter::__construct + * @uses \phpDocumentor\Reflection\DocBlock\Tags\MethodParameter::getDefaultValue() + * @uses \phpDocumentor\Reflection\DocBlock\Tags\MethodParameter::__toString + * @uses \phpDocumentor\Reflection\DocBlock\Tags\Formatter\PassthroughFormatter + * + * @dataProvider collectionDefaultValuesProvider + * @covers \phpDocumentor\Reflection\DocBlock\Tags\BaseTag::render + * @covers \phpDocumentor\Reflection\DocBlock\Tags\BaseTag::getName + */ + public function testIfTagCanBeRenderedUsingMethodParameterWithDefaultValue(Type $type, $defaultValue, string $defaultValueStr): void + { + $fixture = new MethodParameter('argument', $type, false, false, $defaultValue); + + $this->assertSame( + sprintf('%s $argument = %s', $type, $defaultValueStr), + (string) $fixture + ); + } + + /** + * @uses \phpDocumentor\Reflection\DocBlock\Tags\MethodParameter::__construct + * @uses \phpDocumentor\Reflection\DocBlock\Tags\MethodParameter::getDefaultValue() + * @uses \phpDocumentor\Reflection\DocBlock\Tags\MethodParameter::__toString + * @uses \phpDocumentor\Reflection\DocBlock\Tags\Formatter\PassthroughFormatter + * + * @covers \phpDocumentor\Reflection\DocBlock\Tags\BaseTag::render + * @covers \phpDocumentor\Reflection\DocBlock\Tags\BaseTag::getName + */ + public function testIfTagCanBeRenderedUsingMethodParameterWithNoDefaultValue(): void + { + $fixture = new MethodParameter('argument', new Float_()); + + $this->assertSame( + 'float $argument', + (string) $fixture + ); + } +} diff --git a/tests/unit/DocBlock/Tags/MethodTest.php b/tests/unit/DocBlock/Tags/MethodTest.php index ab33d3f..77196bb 100644 --- a/tests/unit/DocBlock/Tags/MethodTest.php +++ b/tests/unit/DocBlock/Tags/MethodTest.php @@ -17,6 +17,7 @@ use Mockery as m; use phpDocumentor\Reflection\DocBlock\Description; use phpDocumentor\Reflection\DocBlock\DescriptionFactory; use phpDocumentor\Reflection\Fqsen; +use phpDocumentor\Reflection\Type; use phpDocumentor\Reflection\TypeResolver; use phpDocumentor\Reflection\Types\Array_; use phpDocumentor\Reflection\Types\Boolean; @@ -700,41 +701,4 @@ class MethodTest extends TestCase $this->assertSame($description, $fixture->getDescription()); $this->assertTrue($fixture->returnsReference()); } - - /** - * @uses \phpDocumentor\Reflection\DocBlock\Tags\MethodParameter::__construct - * @uses \phpDocumentor\Reflection\DocBlock\Tags\MethodParameter::getDefaultValue() - * @uses \phpDocumentor\Reflection\DocBlock\Tags\MethodParameter::__toString - * @uses \phpDocumentor\Reflection\DocBlock\Tags\Formatter\PassthroughFormatter - * - * @covers \phpDocumentor\Reflection\DocBlock\Tags\BaseTag::render - * @covers \phpDocumentor\Reflection\DocBlock\Tags\BaseTag::getName - */ - public function testIfTagCanBeRenderedUsingMethodParameterWithDefaultValue(): void - { - $arguments = [ - ['name' => 'argument1', 'type' => new String_()], - ['name' => 'argument2', 'type' => new Object_()], - ]; - - $fixture = new Method( - 'myMethod', - $arguments, - new Void_(), - false, - null, - false, - [ - new MethodParameter('argument1', new String_(), false, false, '1'), - new MethodParameter('argument2', new Integer(), false, false, '1'), - new MethodParameter('argument3', new Boolean(), false, false, 'true'), - new MethodParameter('argument4', new Float_(), false, false, '1.23'), - ] - ); - - $this->assertSame( - '@method void myMethod(string $argument1 = \'1\', int $argument2 = 1, bool $argument3 = true, float $argument4 = 1.23)', - $fixture->render() - ); - } }