Allow for PhpDoc for macros with union types (#1148)

* Allow for PhpDoc for macros with union types

* Replace null coalescing operator

* Test init PhpDoc for macros with parameter union types

* Allow for PhpDoc for macros with union return types

* Add helper method to Macro class

* Add changelog entry

* Format

* Complement changelog with PR link

* Add missing return

* Fix test for PHP < 8

* Rewrite PHP 8 test using eval()

* Remove obsolete test class

* Suppress Psalm errors for undefined ReflectionUnionType class

* Remove unreachable return statement
This commit is contained in:
Richard van Baarsen
2021-07-30 08:54:59 +02:00
committed by GitHub
parent af84c78dec
commit f4e0fc3695
3 changed files with 54 additions and 5 deletions
+1
View File
@@ -40,6 +40,7 @@ All notable changes to this project will be documented in this file.
- Generate PHPDoc for Laravel 8.x factories [\#1074 / ahmed-aliraqi](https://github.com/barryvdh/laravel-ide-helper/pull/1074) - Generate PHPDoc for Laravel 8.x factories [\#1074 / ahmed-aliraqi](https://github.com/barryvdh/laravel-ide-helper/pull/1074)
- Add a comment to a property like table columns [\#1168 / biiiiiigmonster](https://github.com/barryvdh/laravel-ide-helper/pull/1168) - Add a comment to a property like table columns [\#1168 / biiiiiigmonster](https://github.com/barryvdh/laravel-ide-helper/pull/1168)
- Added `post_migrate` hook to run commands after a migration [\#1163 / netpok](https://github.com/barryvdh/laravel-ide-helper/pull/1163) - Added `post_migrate` hook to run commands after a migration [\#1163 / netpok](https://github.com/barryvdh/laravel-ide-helper/pull/1163)
- Allow for PhpDoc for macros with union types [\#1148 / riesjart](https://github.com/barryvdh/laravel-ide-helper/pull/1148)
### Fixed ### Fixed
- Error when generating helper for invokable classes [\#1124 / standaniels](https://github.com/barryvdh/laravel-ide-helper/pull/1124) - Error when generating helper for invokable classes [\#1124 / standaniels](https://github.com/barryvdh/laravel-ide-helper/pull/1124)
+28 -3
View File
@@ -42,8 +42,16 @@ class Macro extends Method
// Add macro parameters if they are missed in original docblock // Add macro parameters if they are missed in original docblock
if (!$this->phpdoc->hasTag('param')) { if (!$this->phpdoc->hasTag('param')) {
foreach ($method->getParameters() as $parameter) { foreach ($method->getParameters() as $parameter) {
$type = $parameter->hasType() ? $parameter->getType()->getName() : 'mixed'; $reflectionType = $parameter->getType();
$type .= $parameter->hasType() && $parameter->getType()->allowsNull() ? '|null' : '';
$type = $this->concatReflectionTypes($reflectionType);
/** @psalm-suppress UndefinedClass */
if ($reflectionType && !$reflectionType instanceof \ReflectionUnionType && $reflectionType->allowsNull()) {
$type .= '|null';
}
$type = $type ?: 'mixed';
$name = $parameter->isVariadic() ? '...' : ''; $name = $parameter->isVariadic() ? '...' : '';
$name .= '$' . $parameter->getName(); $name .= '$' . $parameter->getName();
@@ -57,14 +65,31 @@ class Macro extends Method
$builder = EloquentBuilder::class; $builder = EloquentBuilder::class;
$return = $method->getReturnType(); $return = $method->getReturnType();
$type = $return->getName(); $type = $this->concatReflectionTypes($return);
/** @psalm-suppress UndefinedClass */
if (!$return instanceof \ReflectionUnionType) {
$type .= $this->root === "\\{$builder}" && $return->getName() === $builder ? '|static' : ''; $type .= $this->root === "\\{$builder}" && $return->getName() === $builder ? '|static' : '';
$type .= $return->allowsNull() ? '|null' : ''; $type .= $return->allowsNull() ? '|null' : '';
}
$this->phpdoc->appendTag(Tag::createInstance("@return {$type}")); $this->phpdoc->appendTag(Tag::createInstance("@return {$type}"));
} }
} }
protected function concatReflectionTypes(?\ReflectionType $type): string
{
/** @psalm-suppress UndefinedClass */
$returnTypes = $type instanceof \ReflectionUnionType
? $type->getTypes()
: [$type];
return Collection::make($returnTypes)
->filter()
->map->getName()
->implode('|');
}
protected function addLocationToPhpDoc() protected function addLocationToPhpDoc()
{ {
if ($this->method->name === '__invoke') { if ($this->method->name === '__invoke') {
+23
View File
@@ -188,6 +188,29 @@ class MacroTest extends TestCase
$this->assertEquals('@return \stdClass|null rrrrrrr', $this->tagsToString($phpdoc, 'return')); $this->assertEquals('@return \stdClass|null rrrrrrr', $this->tagsToString($phpdoc, 'return'));
} }
public function testInitPhpDocParamsWithUnionTypes(): void
{
if (PHP_VERSION_ID < 80000) {
$this->markTestSkipped('This test requires PHP 8.0 or higher');
}
$phpdoc = (new MacroMock())->getPhpDoc(eval(<<<'PHP'
return new ReflectionFunction(
/**
* Test docblock.
*/
function (\Stringable|string $a = null): \Stringable|string|null {
return $a;
}
);
PHP));
$this->assertNotNull($phpdoc);
$this->assertStringContainsString('Test docblock', $phpdoc->getText());
$this->assertEquals('@param \Stringable|string|null $a', $this->tagsToString($phpdoc, 'param'));
$this->assertEquals('@return \Stringable|string|null', $this->tagsToString($phpdoc, 'return'));
}
protected function tagsToString(DocBlock $docBlock, string $name) protected function tagsToString(DocBlock $docBlock, string $name)
{ {
$tags = $docBlock->getTagsByName($name); $tags = $docBlock->getTagsByName($name);