Alias will grab macros from \Illuminate\Database\Eloquent\Builder too (#1118)

* `Alias` will grab macros from `\Illuminate\Database\Eloquent\Builder` too.

* `@return` will contains `|static` for Eloquent Builder macros which return Eloquent Builder instance.

* `Macro` tests.

* `Alias::detectMethods()` tests.

* Mock classes rename.
This commit is contained in:
Aleksei Lebedev
2020-12-21 11:15:47 +01:00
committed by GitHub
parent 9ba2f5c557
commit 36c4406b3a
4 changed files with 194 additions and 3 deletions
+105
View File
@@ -0,0 +1,105 @@
<?php
declare(strict_types=1);
namespace Barryvdh\LaravelIdeHelper\Tests;
use Barryvdh\LaravelIdeHelper\Alias;
use Barryvdh\LaravelIdeHelper\Macro;
use Illuminate\Database\Eloquent\Builder as EloquentBuilder;
use Illuminate\Database\Query\Builder;
use Illuminate\Support\Arr;
/**
* @internal
* @coversDefaultClass \Barryvdh\LaravelIdeHelper\Alias
*/
class AliasTest extends TestCase
{
/**
* @covers ::detectMethods
*/
public function testDetectMethodsMacroableMacros(): void
{
// Mock
$macro = __FUNCTION__;
$alias = new AliasMock();
// Macros
Builder::macro(
$macro,
function () {
// empty
}
);
// Prepare
$alias->setClasses([Builder::class]);
$alias->detectMethods();
// Test
$this->assertNotNull($this->getAliasMacro($alias, Builder::class, $macro));
}
/**
* @covers ::detectMethods
*/
public function testDetectMethodsEloquentBuilderMacros(): void
{
// Mock
$macro = __FUNCTION__;
$alias = new AliasMock();
// Macros
EloquentBuilder::macro(
$macro,
function () {
// empty
}
);
// Prepare
$alias->setClasses([EloquentBuilder::class]);
$alias->detectMethods();
// Test
$this->assertNotNull($this->getAliasMacro($alias, EloquentBuilder::class, $macro));
}
protected function getAliasMacro(Alias $alias, string $class, string $method): ?Macro
{
return Arr::first(
$alias->getMethods(),
function ($macro) use ($class, $method) {
return $macro instanceof Macro
&& $macro->getDeclaringClass() === "\\{$class}"
&& $macro->getName() === $method;
}
);
}
}
/**
* @internal
* @noinspection PhpMultipleClassesDeclarationsInOneFile
*/
class AliasMock extends Alias
{
public function __construct()
{
// no need to call parent
}
/**
* @param string[] $classes
*/
public function setClasses(array $classes)
{
$this->classes = $classes;
}
public function detectMethods()
{
parent::detectMethods();
}
}
+79
View File
@@ -0,0 +1,79 @@
<?php
declare(strict_types=1);
namespace Barryvdh\LaravelIdeHelper\Tests;
use Barryvdh\LaravelIdeHelper\Macro;
use Barryvdh\Reflection\DocBlock;
use Barryvdh\Reflection\DocBlock\Tag;
use Illuminate\Database\Eloquent\Builder as EloquentBuilder;
use ReflectionClass;
use ReflectionFunction;
use ReflectionFunctionAbstract;
use function array_map;
use function implode;
use const PHP_EOL;
/**
* @internal
* @coversDefaultClass \Barryvdh\LaravelIdeHelper\Macro
*/
class MacroTest extends TestCase
{
/**
* @covers ::initPhpDoc
* @throws \ReflectionException
*/
public function testInitPhpDocEloquentBuilderHasStaticInReturnType(): void
{
$class = new ReflectionClass(EloquentBuilder::class);
$phpdoc = (new MacroMock())->getPhpDoc(
new ReflectionFunction(
function (): EloquentBuilder {
return $this;
}
),
$class
);
$this->assertNotNull($phpdoc);
$this->assertEquals(
'@return \Illuminate\Database\Eloquent\Builder|static',
$this->tagsToString($phpdoc, 'return')
);
}
protected function tagsToString(DocBlock $docBlock, string $name)
{
$tags = $docBlock->getTagsByName($name);
$tags = array_map(
function (Tag $tag) {
return trim((string)$tag);
},
$tags
);
$tags = implode(PHP_EOL, $tags);
return $tags;
}
}
/**
* @internal
* @noinspection PhpMultipleClassesDeclarationsInOneFile
*/
class MacroMock extends Macro
{
public function __construct()
{
// no need to call parent
}
public function getPhpDoc(ReflectionFunctionAbstract $method, ReflectionClass $class = null): DocBlock
{
return (new Macro($method, '', $class ?? $method->getClosureScopeClass()))->phpdoc;
}
}