diff --git a/CHANGELOG.md b/CHANGELOG.md index 7bd1f98..98cc090 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,6 +31,7 @@ All notable changes to this project will be documented in this file. - Allow model_locations to have glob patterns [\#1059 / saackearl](https://github.com/barryvdh/laravel-ide-helper/pull/1059) - Error when generating helper for macroable classes which are not facades and contain a "fake" method [\#1066 / domkrm] (https://github.com/barryvdh/laravel-ide-helper/pull/1066) - Casts with a return type of `static` or `$this` now resolve to an instance of the cast [\#1103 / riesjart](https://github.com/barryvdh/laravel-ide-helper/pull/1103) +- Error when generating helper for invokable classes [\#1124 / standaniels](https://github.com/barryvdh/laravel-ide-helper/pull/1124) ### Removed - Removed format and broken generateJsonHelper [\#1053 / mfn](https://github.com/barryvdh/laravel-ide-helper/pull/1053) diff --git a/src/Macro.php b/src/Macro.php index 069770d..34f94df 100644 --- a/src/Macro.php +++ b/src/Macro.php @@ -65,7 +65,11 @@ class Macro extends Method protected function addLocationToPhpDoc() { - $enclosingClass = $this->method->getClosureScopeClass(); + if ($this->method->name === '__invoke') { + $enclosingClass = $this->method->getDeclaringClass(); + } else { + $enclosingClass = $this->method->getClosureScopeClass(); + } /** @var \ReflectionMethod $enclosingMethod */ $enclosingMethod = Collection::make($enclosingClass->getMethods()) diff --git a/src/Method.php b/src/Method.php index ea090c6..c1b6b6d 100644 --- a/src/Method.php +++ b/src/Method.php @@ -55,7 +55,7 @@ class Method $this->initClassDefinedProperties($method, $class); //Reference the 'real' function in the declaring class - $this->root = '\\' . ltrim($class->getName(), '\\'); + $this->root = '\\' . ltrim($method->name === '__invoke' ? $method->getDeclaringClass()->getName() : $class->getName(), '\\'); //Create a DocBlock and serializer instance $this->initPhpDoc($method); diff --git a/tests/MacroTest.php b/tests/MacroTest.php index ea9dd0b..6f9456f 100644 --- a/tests/MacroTest.php +++ b/tests/MacroTest.php @@ -8,6 +8,7 @@ use Barryvdh\LaravelIdeHelper\Macro; use Barryvdh\Reflection\DocBlock; use Barryvdh\Reflection\DocBlock\Tag; use Illuminate\Database\Eloquent\Builder as EloquentBuilder; +use Illuminate\Routing\UrlGenerator; use ReflectionClass; use ReflectionFunction; use ReflectionFunctionAbstract; @@ -200,6 +201,47 @@ class MacroTest extends TestCase return $tags; } + /** + * Test that we can actually instantiate the class + */ + public function testCanInstantiate() + { + $reflectionMethod = new \ReflectionMethod(UrlGeneratorMacroClass::class, '__invoke'); + + $macro = new Macro($reflectionMethod, UrlGenerator::class, new \ReflectionClass(UrlGenerator::class), 'macroName'); + + $this->assertInstanceOf(Macro::class, $macro); + } + + /** + * Test the output of a class + */ + public function testOutput() + { + $reflectionMethod = new \ReflectionMethod(UrlGeneratorMacroClass::class, '__invoke'); + + $macro = new Macro($reflectionMethod, 'URL', new \ReflectionClass(UrlGenerator::class), 'macroName'); + $output = <<<'DOC' +/** + * + * + * @see \Barryvdh\LaravelIdeHelper\Tests\UrlGeneratorMacroClass::__invoke() + * @param string $foo + * @param int $bar + * @return string + * @static + */ +DOC; + $this->assertSame($output, $macro->getDocComment('')); + $this->assertSame('__invoke', $macro->getRealName()); + $this->assertSame('\\' . UrlGenerator::class, $macro->getDeclaringClass()); + $this->assertSame('$foo, $bar', $macro->getParams(true)); + $this->assertSame(['$foo', '$bar'], $macro->getParams(false)); + $this->assertSame('$foo, $bar = 0', $macro->getParamsWithDefault(true)); + $this->assertSame(['$foo', '$bar = 0'], $macro->getParamsWithDefault(false)); + $this->assertTrue($macro->shouldReturn()); + $this->assertSame('$instance->__invoke($foo, $bar)', $macro->getRootMethodCall()); + } } /** @@ -218,3 +260,19 @@ class MacroMock extends Macro return (new Macro($method, '', $class ?? $method->getClosureScopeClass()))->phpdoc; } } + +/** + * Example of an invokable class to be used as a macro. + */ +class UrlGeneratorMacroClass +{ + /** + * @param string $foo + * @param int $bar + * @return string + */ + public function __invoke(string $foo, int $bar = 0): string + { + return ''; + } +}