Skip to content

Commit c237109

Browse files
committed
Type fake() as a fabricated record of the model's return type
1 parent eb763b2 commit c237109

3 files changed

Lines changed: 96 additions & 0 deletions

File tree

extension.neon

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,11 @@ services:
121121
tags:
122122
- phpstan.broker.dynamicFunctionReturnTypeExtension
123123

124+
-
125+
class: CodeIgniter\PHPStan\Type\FakeFunctionReturnTypeExtension
126+
tags:
127+
- phpstan.broker.dynamicFunctionReturnTypeExtension
128+
124129
-
125130
class: CodeIgniter\PHPStan\Type\SuperglobalsMethodDynamicReturnTypeExtension
126131
tags:
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/**
6+
* This file is part of CodeIgniter 4 framework.
7+
*
8+
* (c) 2023 CodeIgniter Foundation <admin@codeigniter.com>
9+
*
10+
* For the full copyright and license information, please view
11+
* the LICENSE file that was distributed with this source code.
12+
*/
13+
14+
namespace CodeIgniter\PHPStan\Type;
15+
16+
use CodeIgniter\Model;
17+
use CodeIgniter\PHPStan\Helpers\FactoriesReturnTypeHelper;
18+
use PhpParser\Node\Expr\FuncCall;
19+
use PHPStan\Analyser\Scope;
20+
use PHPStan\Reflection\FunctionReflection;
21+
use PHPStan\Type\DynamicFunctionReturnTypeExtension;
22+
use PHPStan\Type\Type;
23+
24+
/**
25+
* Types `fake()` as a single fabricated record of the given model's return type.
26+
*/
27+
final class FakeFunctionReturnTypeExtension implements DynamicFunctionReturnTypeExtension
28+
{
29+
public function __construct(
30+
private readonly ModelFetchedReturnTypeHelper $modelFetchedReturnTypeHelper,
31+
private readonly FactoriesReturnTypeHelper $factoriesReturnTypeHelper,
32+
) {}
33+
34+
public function isFunctionSupported(FunctionReflection $functionReflection): bool
35+
{
36+
return $functionReflection->getName() === 'fake';
37+
}
38+
39+
public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope): ?Type
40+
{
41+
$args = $functionCall->getArgs();
42+
43+
if (! isset($args[0])) {
44+
return null;
45+
}
46+
47+
$argType = $scope->getType($args[0]->value);
48+
$modelType = $argType->isObject()->yes() ? $argType : $this->factoriesReturnTypeHelper->check($argType, 'model');
49+
50+
$classReflections = $modelType->getObjectClassReflections();
51+
52+
if (count($classReflections) !== 1) {
53+
return null;
54+
}
55+
56+
$classReflection = current($classReflections);
57+
58+
if (! $classReflection->is(Model::class)) {
59+
return null;
60+
}
61+
62+
return $this->modelFetchedReturnTypeHelper->getFetchedReturnType($classReflection, null, $scope);
63+
}
64+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/**
6+
* This file is part of CodeIgniter 4 framework.
7+
*
8+
* (c) 2023 CodeIgniter Foundation <admin@codeigniter.com>
9+
*
10+
* For the full copyright and license information, please view
11+
* the LICENSE file that was distributed with this source code.
12+
*/
13+
14+
namespace CodeIgniter\PHPStan\Tests\Type;
15+
16+
use CodeIgniter\PHPStan\Tests\Fixtures\Models\BlogCommentModel;
17+
use CodeIgniter\PHPStan\Tests\Fixtures\Models\BlogPostModel;
18+
19+
use function PHPStan\Testing\assertType;
20+
21+
assertType('CodeIgniter\PHPStan\Tests\Fixtures\Entity\BlogComment', \fake(BlogCommentModel::class));
22+
assertType('array{id: int, user_id: CodeIgniter\PHPStan\Tests\Fixtures\Entity\Money, title: CodeIgniter\I18n\Time}', \fake(BlogPostModel::class));
23+
24+
function fakeFromInstance(BlogCommentModel $model): void
25+
{
26+
assertType('CodeIgniter\PHPStan\Tests\Fixtures\Entity\BlogComment', \fake($model));
27+
}

0 commit comments

Comments
 (0)