diff --git a/src/DocBlock/Tags/Factory/MethodFactory.php b/src/DocBlock/Tags/Factory/MethodFactory.php index 920be845..5d90759f 100644 --- a/src/DocBlock/Tags/Factory/MethodFactory.php +++ b/src/DocBlock/Tags/Factory/MethodFactory.php @@ -57,7 +57,7 @@ function (MethodTagValueParameterNode $param) use ($context) { ), $param->isReference, $param->isVariadic, - (string) $param->defaultValue + $param->defaultValue === null ? MethodParameter::NO_DEFAULT_VALUE : (string) $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 00000000..92ff69d2 --- /dev/null +++ b/src/DocBlock/Tags/Factory/MethodParameterFactory.php @@ -0,0 +1,95 @@ +{$method}($defaultValue); + } + return ''; + } + + private function formatDouble(float $defaultValue): string + { + return var_export($defaultValue, true); + } + + /** + * @param mixed $defaultValue + * @return string + */ + private function formatNull($defaultValue): string + { + return 'null'; + } + + private function formatInteger(int $defaultValue): string + { + return var_export($defaultValue, true); + } + + private function formatString(string $defaultValue): string + { + return var_export($defaultValue, true); + } + + private function formatBoolean(bool $defaultValue): string + { + return var_export($defaultValue, true); + } + + /** + * @param array $defaultValue + * @return string + */ + private 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; + } + + private 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 471ebe95..41e0eed1 100644 --- a/src/DocBlock/Tags/Method.php +++ b/src/DocBlock/Tags/Method.php @@ -261,10 +261,7 @@ public function __toString(): string { $arguments = []; foreach ($this->parameters as $parameter) { - $arguments[] = $parameter->getType() . ' ' . - ($parameter->isReference() ? '&' : '') . - ($parameter->isVariadic() ? '...' : '') . - '$' . $parameter->getName(); + $arguments[] = (string) $parameter; } $argumentStr = '(' . implode(', ', $arguments) . ')'; diff --git a/src/DocBlock/Tags/MethodParameter.php b/src/DocBlock/Tags/MethodParameter.php index 0c85d41d..06fc054d 100644 --- a/src/DocBlock/Tags/MethodParameter.php +++ b/src/DocBlock/Tags/MethodParameter.php @@ -12,6 +12,7 @@ namespace phpDocumentor\Reflection\DocBlock\Tags; +use phpDocumentor\Reflection\DocBlock\Tags\Factory\MethodParameterFactory; use phpDocumentor\Reflection\Type; final class MethodParameter @@ -24,14 +25,22 @@ final class MethodParameter private string $name; - private ?string $defaultValue = null; + /** + * @var mixed + */ + private $defaultValue; + public const NO_DEFAULT_VALUE = '__NO_VALUE__'; + + /** + * @param mixed $defaultValue + */ 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; @@ -62,6 +71,21 @@ public function isVariadic(): bool public function getDefaultValue(): ?string { - return $this->defaultValue; + if ($this->defaultValue === static::NO_DEFAULT_VALUE) { + return null; + } + if (is_array($this->defaultValue)) { + return implode(',', $this->defaultValue); + } + return (string) $this->defaultValue; + } + + public function __toString(): string + { + return $this->getType() . ' ' . + ($this->isReference() ? '&' : '') . + ($this->isVariadic() ? '...' : '') . + '$' . $this->getName() . + ($this->defaultValue !== self::NO_DEFAULT_VALUE ? (new MethodParameterFactory)->format($this->defaultValue) : ''); } } diff --git a/tests/unit/DocBlock/Tags/MethodParameterTest.php b/tests/unit/DocBlock/Tags/MethodParameterTest.php new file mode 100644 index 00000000..ef64f6e0 --- /dev/null +++ b/tests/unit/DocBlock/Tags/MethodParameterTest.php @@ -0,0 +1,95 @@ + + */ +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 + ); + } +}