Skip to content

Commit 65c14c5

Browse files
authored
Laravel 11 new generic types (#266)
* Detect Laravel version within the AddGenericReturnTypeToRelationsRector rule * Update docs and run Rector, Duster, and PHPStan
1 parent a54acd5 commit 65c14c5

8 files changed

+58
-36
lines changed

Diff for: docs/rector_rules_overview.md

+1-3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# 70 Rules Overview
1+
# 71 Rules Overview
22

33
## AbortIfRector
44

@@ -63,8 +63,6 @@ Adds the `@extends` annotation to Factories.
6363

6464
Add generic return type to relations in child of `Illuminate\Database\Eloquent\Model`
6565

66-
:wrench: **configure it!**
67-
6866
- class: [`RectorLaravel\Rector\ClassMethod\AddGenericReturnTypeToRelationsRector`](../src/Rector/ClassMethod/AddGenericReturnTypeToRelationsRector.php)
6967

7068
```diff

Diff for: phpstan.neon

+3
Original file line numberDiff line numberDiff line change
@@ -29,3 +29,6 @@ parameters:
2929
- '#Parameter \#1 \$node (.*?) of method RectorLaravel\\(.*?)\:\:(refactor|refactorWithScope)\(\) should be contravariant with parameter \$node \(PhpParser\\Node\) of method Rector\\Contract\\Rector\\RectorInterface\:\:refactor\(\)#'
3030

3131
- '#Parameter \#1 \$className of method Rector\\Reflection\\ReflectionResolver\:\:resolveMethodReflection\(\) expects class\-string, string given#'
32+
33+
# Laravel Container not being recognized properly in some of the tests
34+
- '#Call to method needs\(\) on an unknown class Illuminate\\Contracts\\Container\\ContextualBindingBuilder#'

Diff for: src/Rector/ClassMethod/AddGenericReturnTypeToRelationsRector.php

+22-28
Original file line numberDiff line numberDiff line change
@@ -22,20 +22,19 @@
2222
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfoFactory;
2323
use Rector\BetterPhpDocParser\ValueObject\Type\FullyQualifiedIdentifierTypeNode;
2424
use Rector\Comments\NodeDocBlock\DocBlockUpdater;
25-
use Rector\Contract\Rector\ConfigurableRectorInterface;
2625
use Rector\NodeTypeResolver\TypeComparator\TypeComparator;
2726
use Rector\PhpParser\Node\BetterNodeFinder;
2827
use Rector\Rector\AbstractScopeAwareRector;
2928
use Rector\StaticTypeMapper\StaticTypeMapper;
30-
use Symplify\RuleDocGenerator\ValueObject\CodeSample\ConfiguredCodeSample;
29+
use ReflectionClassConstant;
30+
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
3131
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
32-
use Webmozart\Assert\Assert;
3332

3433
/**
3534
* @see \RectorLaravel\Tests\Rector\ClassMethod\AddGenericReturnTypeToRelationsRector\AddGenericReturnTypeToRelationsRectorNewGenericsTest
3635
* @see \RectorLaravel\Tests\Rector\ClassMethod\AddGenericReturnTypeToRelationsRector\AddGenericReturnTypeToRelationsRectorOldGenericsTest
3736
*/
38-
class AddGenericReturnTypeToRelationsRector extends AbstractScopeAwareRector implements ConfigurableRectorInterface
37+
class AddGenericReturnTypeToRelationsRector extends AbstractScopeAwareRector
3938
{
4039
// Relation methods which are supported by this Rector.
4140
private const RELATION_METHODS = [
@@ -59,6 +58,7 @@ public function __construct(
5958
private readonly PhpDocInfoFactory $phpDocInfoFactory,
6059
private readonly BetterNodeFinder $betterNodeFinder,
6160
private readonly StaticTypeMapper $staticTypeMapper,
61+
private readonly string $applicationClass = 'Illuminate\Foundation\Application',
6262
) {
6363
}
6464

@@ -67,7 +67,7 @@ public function getRuleDefinition(): RuleDefinition
6767
return new RuleDefinition(
6868
'Add generic return type to relations in child of Illuminate\Database\Eloquent\Model',
6969
[
70-
new ConfiguredCodeSample(
70+
new CodeSample(
7171
<<<'CODE_SAMPLE'
7272
use App\Account;
7373
use Illuminate\Database\Eloquent\Model;
@@ -96,9 +96,9 @@ public function accounts(): HasMany
9696
return $this->hasMany(Account::class);
9797
}
9898
}
99-
CODE_SAMPLE,
100-
['shouldUseNewGenerics' => false]),
101-
new ConfiguredCodeSample(
99+
CODE_SAMPLE
100+
),
101+
new CodeSample(
102102
<<<'CODE_SAMPLE'
103103
use App\Account;
104104
use Illuminate\Database\Eloquent\Model;
@@ -127,8 +127,8 @@ public function accounts(): HasMany
127127
return $this->hasMany(Account::class);
128128
}
129129
}
130-
CODE_SAMPLE,
131-
['shouldUseNewGenerics' => true]),
130+
CODE_SAMPLE
131+
),
132132
]
133133
);
134134
}
@@ -196,6 +196,9 @@ public function refactorWithScope(Node $node, Scope $scope): ?Node
196196
return null;
197197
}
198198

199+
// Put here to make the check as late as possible
200+
$this->setShouldUseNewGenerics();
201+
199202
$classForChildGeneric = $this->getClassForChildGeneric($scope, $relationMethodCall);
200203
$classForIntermediateGeneric = $this->getClassForIntermediateGeneric($relationMethodCall);
201204

@@ -232,24 +235,6 @@ public function refactorWithScope(Node $node, Scope $scope): ?Node
232235
return $node;
233236
}
234237

235-
/**
236-
* {@inheritDoc}
237-
*/
238-
public function configure(array $configuration): void
239-
{
240-
if ($configuration === []) {
241-
$this->shouldUseNewGenerics = false;
242-
243-
return;
244-
}
245-
246-
Assert::count($configuration, 1);
247-
Assert::keyExists($configuration, 'shouldUseNewGenerics');
248-
Assert::boolean($configuration['shouldUseNewGenerics']);
249-
250-
$this->shouldUseNewGenerics = $configuration['shouldUseNewGenerics'];
251-
}
252-
253238
private function getRelatedModelClassFromMethodCall(MethodCall $methodCall): ?string
254239
{
255240
$argType = $this->getType($methodCall->getArgs()[0]->value);
@@ -489,4 +474,13 @@ private function getGenericTypes(string $relatedClass, ?string $childClass, ?str
489474

490475
return $generics;
491476
}
477+
478+
private function setShouldUseNewGenerics(): void
479+
{
480+
$reflectionClassConstant = new ReflectionClassConstant($this->applicationClass, 'VERSION');
481+
482+
if (is_string($reflectionClassConstant->getValue())) {
483+
$this->shouldUseNewGenerics = version_compare($reflectionClassConstant->getValue(), '11.15.0', '>=');
484+
}
485+
}
492486
}

Diff for: tests/Rector/ClassMethod/AddGenericReturnTypeToRelationsRector/AddGenericReturnTypeToRelationsRectorNewGenericsTest.php

-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ final class AddGenericReturnTypeToRelationsRectorNewGenericsTest extends Abstrac
1212
{
1313
public static function provideData(): Iterator
1414
{
15-
// yield [__DIR__ . '/Fixture/NewGenerics/has-one-through.php.inc'];
1615
return self::yieldFilesFromDirectory(__DIR__ . '/Fixture/NewGenerics');
1716
}
1817

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<?php
2+
3+
namespace RectorLaravel\Tests\Rector\ClassMethod\AddGenericReturnTypeToRelationsRector\Source;
4+
5+
use Illuminate\Foundation\Application;
6+
7+
class NewApplication extends Application
8+
{
9+
const VERSION = '11.15.0';
10+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<?php
2+
3+
namespace RectorLaravel\Tests\Rector\ClassMethod\AddGenericReturnTypeToRelationsRector\Source;
4+
5+
use Illuminate\Foundation\Application;
6+
7+
class OldApplication extends Application
8+
{
9+
const VERSION = '11.14.0';
10+
}

Diff for: tests/Rector/ClassMethod/AddGenericReturnTypeToRelationsRector/config/use_new_generics_configured_rule.php

+6-3
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,14 @@
44

55
use Rector\Config\RectorConfig;
66
use RectorLaravel\Rector\ClassMethod\AddGenericReturnTypeToRelationsRector;
7+
use RectorLaravel\Tests\Rector\ClassMethod\AddGenericReturnTypeToRelationsRector\Source\NewApplication;
78

89
return static function (RectorConfig $rectorConfig): void {
910
$rectorConfig->import(__DIR__ . '/../../../../../config/config.php');
1011

11-
$rectorConfig->ruleWithConfiguration(AddGenericReturnTypeToRelationsRector::class, [
12-
'shouldUseNewGenerics' => true,
13-
]);
12+
$rectorConfig->when(AddGenericReturnTypeToRelationsRector::class)
13+
->needs('$applicationClass')
14+
->give(NewApplication::class);
15+
16+
$rectorConfig->rule(AddGenericReturnTypeToRelationsRector::class);
1417
};

Diff for: tests/Rector/ClassMethod/AddGenericReturnTypeToRelationsRector/config/use_old_generics_configured_rule.php

+6-1
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,14 @@
44

55
use Rector\Config\RectorConfig;
66
use RectorLaravel\Rector\ClassMethod\AddGenericReturnTypeToRelationsRector;
7+
use RectorLaravel\Tests\Rector\ClassMethod\AddGenericReturnTypeToRelationsRector\Source\OldApplication;
78

89
return static function (RectorConfig $rectorConfig): void {
910
$rectorConfig->import(__DIR__ . '/../../../../../config/config.php');
1011

11-
$rectorConfig->ruleWithConfiguration(AddGenericReturnTypeToRelationsRector::class, []);
12+
$rectorConfig->when(AddGenericReturnTypeToRelationsRector::class)
13+
->needs('$applicationClass')
14+
->give(OldApplication::class);
15+
16+
$rectorConfig->rule(AddGenericReturnTypeToRelationsRector::class);
1217
};

0 commit comments

Comments
 (0)