mirror of
https://github.com/barryvdh/laravel-ide-helper.git
synced 2026-08-18 01:57:13 +00:00
Fix broken ReflectionUnionTypes (#1132)
* Fix exceptions on ReflectionUnionTypes this commit fixes exceptions thrown on ReflectionUnionType::isBuiltIn() and ReflectionUnionType::getNme() called on php8 union types * Fix exceptions on ReflectionUnionTypes this commit fixes exceptions thrown on ReflectionUnionType::isBuiltIn() and ReflectionUnionType::getNme() called on php8 union types * add check for php8.0 * fix static analysis error * fix $types variable undefined * fix failing test * fix failing test * fixed style with php-cs-fixer * add test for union types in parameters and return type * add test for nullable union types in parameters and return type * updated CHANGELOG.md
This commit is contained in:
+1
-1
@@ -35,7 +35,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)
|
||||
|
||||
- Broken ReflectionUnionTypes [\#1132 / def-studio](https://github.com/barryvdh/laravel-ide-helper/pull/1132)
|
||||
### Removed
|
||||
- Removed format and broken generateJsonHelper [\#1053 / mfn](https://github.com/barryvdh/laravel-ide-helper/pull/1053)
|
||||
|
||||
|
||||
@@ -35,7 +35,9 @@ use Illuminate\Filesystem\Filesystem;
|
||||
use Illuminate\Support\Str;
|
||||
use phpDocumentor\Reflection\Types\ContextFactory;
|
||||
use ReflectionClass;
|
||||
use ReflectionNamedType;
|
||||
use ReflectionObject;
|
||||
use ReflectionType;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
@@ -578,7 +580,7 @@ class ModelsCommand extends Command
|
||||
$reflection = new \ReflectionMethod($model, $method);
|
||||
|
||||
if ($returnType = $reflection->getReturnType()) {
|
||||
$type = $returnType instanceof \ReflectionNamedType
|
||||
$type = $returnType instanceof ReflectionNamedType
|
||||
? $returnType->getName()
|
||||
: (string)$returnType;
|
||||
} else {
|
||||
@@ -1013,16 +1015,12 @@ class ModelsCommand extends Command
|
||||
return null;
|
||||
}
|
||||
|
||||
$type = $returnType instanceof \ReflectionNamedType
|
||||
? $returnType->getName()
|
||||
: (string)$returnType;
|
||||
$types = $this->extractReflectionTypes($returnType);
|
||||
|
||||
if (!$returnType->isBuiltin()) {
|
||||
$type = '\\' . $type;
|
||||
}
|
||||
$type = implode('|', $types);
|
||||
|
||||
if ($returnType->allowsNull()) {
|
||||
$type .= '|null';
|
||||
if($returnType->allowsNull()){
|
||||
$type .='|null';
|
||||
}
|
||||
|
||||
return $type;
|
||||
@@ -1215,17 +1213,19 @@ class ModelsCommand extends Command
|
||||
protected function getParamType(\ReflectionMethod $method, \ReflectionParameter $parameter): ?string
|
||||
{
|
||||
if ($paramType = $parameter->getType()) {
|
||||
$parameterName = $paramType->getName();
|
||||
$types = $this->extractReflectionTypes($paramType);
|
||||
|
||||
if (!$paramType->isBuiltin()) {
|
||||
$parameterName = '\\' . $parameterName;
|
||||
$type = implode('|', $types);
|
||||
|
||||
if($paramType->allowsNull()){
|
||||
if(count($types)==1){
|
||||
$type = '?' . $type;
|
||||
}else{
|
||||
$type .='|null';
|
||||
}
|
||||
}
|
||||
|
||||
if ($paramType->allowsNull()) {
|
||||
return '?' . $parameterName;
|
||||
}
|
||||
|
||||
return $parameterName;
|
||||
return $type;
|
||||
}
|
||||
|
||||
$docComment = $method->getDocComment();
|
||||
@@ -1290,4 +1290,32 @@ class ModelsCommand extends Command
|
||||
// then we have found the type of the variable if not we return null
|
||||
return $type;
|
||||
}
|
||||
|
||||
protected function extractReflectionTypes(ReflectionType $reflection_type)
|
||||
{
|
||||
if($reflection_type instanceof ReflectionNamedType){
|
||||
$types[] = $this->getReflectionNamedType($reflection_type);
|
||||
}else{
|
||||
$types = [];
|
||||
foreach ($reflection_type->getTypes() as $named_type){
|
||||
if($named_type->getName()==='null'){
|
||||
continue;
|
||||
}
|
||||
|
||||
$types[] = $this->getReflectionNamedType($named_type);
|
||||
}
|
||||
}
|
||||
|
||||
return $types;
|
||||
}
|
||||
|
||||
protected function getReflectionNamedType(ReflectionNamedType $paramType): string
|
||||
{
|
||||
$parameterName = $paramType->getName();
|
||||
if (!$paramType->isBuiltin()) {
|
||||
$parameterName = '\\' . $parameterName;
|
||||
}
|
||||
|
||||
return $parameterName;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\UnionTypes\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
use Illuminate\Database\Query\Builder;
|
||||
|
||||
class UnionTypeModel extends Model
|
||||
{
|
||||
public function scopeWithUnionTypeParameter(Builder $query, string|int $bar): Builder
|
||||
{
|
||||
return $query->where('foo', $bar);
|
||||
}
|
||||
|
||||
public function scopeWithNullableUnionTypeParameter(Builder $query, null|string|int $bar): Builder
|
||||
{
|
||||
return $query->where('foo', $bar);
|
||||
}
|
||||
|
||||
public function withUnionTypeReturn(): HasMany|UnionTypeModel
|
||||
{
|
||||
return $this->hasMany(UnionTypeModel::class);
|
||||
}
|
||||
|
||||
public function getFooAttribute(): string|int|null
|
||||
{
|
||||
return $this->getAttribute('foo');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\UnionTypes;
|
||||
|
||||
use Barryvdh\LaravelIdeHelper\Console\ModelsCommand;
|
||||
use Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\AbstractModelsCommand;
|
||||
use Illuminate\Foundation\Application;
|
||||
|
||||
class Test extends AbstractModelsCommand
|
||||
{
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
if (PHP_VERSION_ID < 80000) {
|
||||
$this->markTestSkipped('This test requires PHP 8.0 or higher');
|
||||
}
|
||||
}
|
||||
|
||||
public function test(): void
|
||||
{
|
||||
$command = $this->app->make(ModelsCommand::class);
|
||||
|
||||
$tester = $this->runCommand($command, [
|
||||
'--write' => true,
|
||||
]);
|
||||
|
||||
$this->assertSame(0, $tester->getStatusCode());
|
||||
$this->assertStringContainsString('Written new phpDocBlock to', $tester->getDisplay());
|
||||
$this->assertMatchesMockedSnapshot();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\UnionTypes\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
use Illuminate\Database\Query\Builder;
|
||||
|
||||
/**
|
||||
* Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\UnionTypes\Models\UnionTypeModel
|
||||
*
|
||||
* @property-read string|int|null $foo
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection|UnionTypeModel[] $withUnionTypeReturn
|
||||
* @property-read int|null $with_union_type_return_count
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|UnionTypeModel newModelQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|UnionTypeModel newQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|UnionTypeModel query()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|UnionTypeModel withNullableUnionTypeParameter(string|int|null $bar)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|UnionTypeModel withUnionTypeParameter(string|int $bar)
|
||||
* @mixin \Eloquent
|
||||
*/
|
||||
class UnionTypeModel extends Model
|
||||
{
|
||||
public function scopeWithUnionTypeParameter(Builder $query, string|int $bar): Builder
|
||||
{
|
||||
return $query->where('foo', $bar);
|
||||
}
|
||||
|
||||
public function scopeWithNullableUnionTypeParameter(Builder $query, null|string|int $bar): Builder
|
||||
{
|
||||
return $query->where('foo', $bar);
|
||||
}
|
||||
|
||||
public function withUnionTypeReturn(): HasMany|UnionTypeModel
|
||||
{
|
||||
return $this->hasMany(UnionTypeModel::class);
|
||||
}
|
||||
|
||||
public function getFooAttribute(): string|int|null
|
||||
{
|
||||
return $this->getAttribute('foo');
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user