Skip to content

Commit fd30d11

Browse files
authored
Fix issues with parsing invokable macros (#1124)
* Fix issues with parsing invokable macros * Add macro test # Conflicts: # tests/MacroTest.php
1 parent 4f13ba8 commit fd30d11

File tree

4 files changed

+65
-2
lines changed

4 files changed

+65
-2
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ All notable changes to this project will be documented in this file.
3131
- Allow model_locations to have glob patterns [\#1059 / saackearl](https://github.com/barryvdh/laravel-ide-helper/pull/1059)
3232
- 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)
3333
- 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)
34+
- Error when generating helper for invokable classes [\#1124 / standaniels](https://github.com/barryvdh/laravel-ide-helper/pull/1124)
3435

3536
### Removed
3637
- Removed format and broken generateJsonHelper [\#1053 / mfn](https://github.com/barryvdh/laravel-ide-helper/pull/1053)

src/Macro.php

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,11 @@ protected function initPhpDoc($method)
6565

6666
protected function addLocationToPhpDoc()
6767
{
68-
$enclosingClass = $this->method->getClosureScopeClass();
68+
if ($this->method->name === '__invoke') {
69+
$enclosingClass = $this->method->getDeclaringClass();
70+
} else {
71+
$enclosingClass = $this->method->getClosureScopeClass();
72+
}
6973

7074
/** @var \ReflectionMethod $enclosingMethod */
7175
$enclosingMethod = Collection::make($enclosingClass->getMethods())

src/Method.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ public function __construct($method, $alias, $class, $methodName = null, $interf
5555
$this->initClassDefinedProperties($method, $class);
5656

5757
//Reference the 'real' function in the declaring class
58-
$this->root = '\\' . ltrim($class->getName(), '\\');
58+
$this->root = '\\' . ltrim($method->name === '__invoke' ? $method->getDeclaringClass()->getName() : $class->getName(), '\\');
5959

6060
//Create a DocBlock and serializer instance
6161
$this->initPhpDoc($method);

tests/MacroTest.php

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
use Barryvdh\Reflection\DocBlock;
99
use Barryvdh\Reflection\DocBlock\Tag;
1010
use Illuminate\Database\Eloquent\Builder as EloquentBuilder;
11+
use Illuminate\Routing\UrlGenerator;
1112
use ReflectionClass;
1213
use ReflectionFunction;
1314
use ReflectionFunctionAbstract;
@@ -200,6 +201,47 @@ function (Tag $tag) {
200201

201202
return $tags;
202203
}
204+
/**
205+
* Test that we can actually instantiate the class
206+
*/
207+
public function testCanInstantiate()
208+
{
209+
$reflectionMethod = new \ReflectionMethod(UrlGeneratorMacroClass::class, '__invoke');
210+
211+
$macro = new Macro($reflectionMethod, UrlGenerator::class, new \ReflectionClass(UrlGenerator::class), 'macroName');
212+
213+
$this->assertInstanceOf(Macro::class, $macro);
214+
}
215+
216+
/**
217+
* Test the output of a class
218+
*/
219+
public function testOutput()
220+
{
221+
$reflectionMethod = new \ReflectionMethod(UrlGeneratorMacroClass::class, '__invoke');
222+
223+
$macro = new Macro($reflectionMethod, 'URL', new \ReflectionClass(UrlGenerator::class), 'macroName');
224+
$output = <<<'DOC'
225+
/**
226+
*
227+
*
228+
* @see \Barryvdh\LaravelIdeHelper\Tests\UrlGeneratorMacroClass::__invoke()
229+
* @param string $foo
230+
* @param int $bar
231+
* @return string
232+
* @static
233+
*/
234+
DOC;
235+
$this->assertSame($output, $macro->getDocComment(''));
236+
$this->assertSame('__invoke', $macro->getRealName());
237+
$this->assertSame('\\' . UrlGenerator::class, $macro->getDeclaringClass());
238+
$this->assertSame('$foo, $bar', $macro->getParams(true));
239+
$this->assertSame(['$foo', '$bar'], $macro->getParams(false));
240+
$this->assertSame('$foo, $bar = 0', $macro->getParamsWithDefault(true));
241+
$this->assertSame(['$foo', '$bar = 0'], $macro->getParamsWithDefault(false));
242+
$this->assertTrue($macro->shouldReturn());
243+
$this->assertSame('$instance->__invoke($foo, $bar)', $macro->getRootMethodCall());
244+
}
203245
}
204246

205247
/**
@@ -218,3 +260,19 @@ public function getPhpDoc(ReflectionFunctionAbstract $method, ReflectionClass $c
218260
return (new Macro($method, '', $class ?? $method->getClosureScopeClass()))->phpdoc;
219261
}
220262
}
263+
264+
/**
265+
* Example of an invokable class to be used as a macro.
266+
*/
267+
class UrlGeneratorMacroClass
268+
{
269+
/**
270+
* @param string $foo
271+
* @param int $bar
272+
* @return string
273+
*/
274+
public function __invoke(string $foo, int $bar = 0): string
275+
{
276+
return '';
277+
}
278+
}

0 commit comments

Comments
 (0)