Skip to content

Commit ed0cb99

Browse files
peterfoxGeniJaho
andauthored
Laravel App Analyzer (#328)
* Simplify getting Laravel version * Updated --------- Co-authored-by: Geni Jaho <[email protected]>
1 parent 79d3761 commit ed0cb99

11 files changed

+113
-60
lines changed

Diff for: phpstan.neon

-4
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,5 @@ parameters:
2828

2929
- '#Parameter \#1 \$className of method Rector\\Reflection\\ReflectionResolver\:\:resolveMethodReflection\(\) expects class\-string, string given#'
3030

31-
# Laravel Container not being recognized properly in some of the tests
32-
- '#Call to method needs\(\) on an unknown class Illuminate\\Contracts\\Container\\ContextualBindingBuilder#'
33-
- '#Cannot call method give\(\) on mixed.#'
34-
3531
# No easy replacement for this check, it's also ignored in core Rector
3632
- '#Doing instanceof PHPStan\\Type\\Generic\\GenericObjectType is error\-prone and deprecated#'

Diff for: src/NodeAnalyzer/ApplicationAnalyzer.php

+57
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
<?php
2+
3+
namespace RectorLaravel\NodeAnalyzer;
4+
5+
use ReflectionClassConstant;
6+
use RuntimeException;
7+
8+
class ApplicationAnalyzer
9+
{
10+
private ?string $version = null;
11+
12+
public function __construct(
13+
private string $applicationClass = 'Illuminate\Foundation\Application',
14+
) {}
15+
16+
public function setVersion(?string $version): static
17+
{
18+
$this->version = $version;
19+
20+
return $this;
21+
}
22+
23+
public function setApplicationClass(string $applicationClass): static
24+
{
25+
$this->applicationClass = $applicationClass;
26+
27+
return $this;
28+
}
29+
30+
public function getApplicationClass(): string
31+
{
32+
return $this->applicationClass;
33+
}
34+
35+
/**
36+
* @param '>='|'='|'<=' $comparison
37+
*/
38+
public function isVersion(string $comparison, string $version): bool
39+
{
40+
return version_compare($this->getVersion(), $version, $comparison);
41+
}
42+
43+
public function getVersion(): string
44+
{
45+
if ($this->version !== null) {
46+
return $this->version;
47+
}
48+
49+
$reflectionClassConstant = new ReflectionClassConstant($this->applicationClass, 'VERSION');
50+
51+
if (! is_string($version = $reflectionClassConstant->getValue())) {
52+
throw new RuntimeException('expected VERSION to be a string, got ' . gettype($version));
53+
}
54+
55+
return $version;
56+
}
57+
}

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

+10-12
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
use Rector\PHPStan\ScopeFetcher;
2727
use Rector\StaticTypeMapper\StaticTypeMapper;
2828
use RectorLaravel\AbstractRector;
29-
use ReflectionClassConstant;
29+
use RectorLaravel\NodeAnalyzer\ApplicationAnalyzer;
3030
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
3131
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
3232

@@ -60,7 +60,7 @@ public function __construct(
6060
private readonly BetterNodeFinder $betterNodeFinder,
6161
private readonly StaticTypeMapper $staticTypeMapper,
6262
private readonly ReflectionProvider $reflectionProvider,
63-
private readonly string $applicationClass = 'Illuminate\Foundation\Application',
63+
private readonly ApplicationAnalyzer $applicationAnalyzer,
6464
) {}
6565

6666
public function getRuleDefinition(): RuleDefinition
@@ -484,19 +484,17 @@ private function getGenericTypes(Node $node, string $relatedClass, ?string $chil
484484

485485
private function setShouldUseNewGenerics(): void
486486
{
487-
$reflectionClassConstant = new ReflectionClassConstant($this->applicationClass, 'VERSION');
488-
489-
if (is_string($reflectionClassConstant->getValue())) {
490-
$this->shouldUseNewGenerics = version_compare($reflectionClassConstant->getValue(), '11.15.0', '>=');
491-
}
487+
$this->shouldUseNewGenerics = $this->applicationAnalyzer->isVersion(
488+
'>=',
489+
'11.15.0'
490+
);
492491
}
493492

494493
private function setShouldUsePivotGeneric(): void
495494
{
496-
$reflectionClassConstant = new ReflectionClassConstant($this->applicationClass, 'VERSION');
497-
498-
if (is_string($reflectionClassConstant->getValue())) {
499-
$this->shouldUsePivotGeneric = version_compare($reflectionClassConstant->getValue(), '12.3.0', '>=');
500-
}
495+
$this->shouldUsePivotGeneric = $this->applicationAnalyzer->isVersion(
496+
'>=',
497+
'12.3.0'
498+
);
501499
}
502500
}

Diff for: stubs/Illuminate/Foundation/Application.php

+2
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313

1414
class Application extends Container implements ApplicationContract
1515
{
16+
const VERSION = '12.0.0';
17+
1618
public function tagged(string $tagName): iterable
1719
{
1820
return [];

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

+9-1
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,12 @@
77
use Iterator;
88
use PHPUnit\Framework\Attributes\DataProvider;
99
use Rector\Testing\PHPUnit\AbstractRectorTestCase;
10+
use RectorLaravel\Tests\Support\InteractsWithLaravelVersion;
1011

1112
final class AddGenericReturnTypeToRelationsRectorNewGenericsTest extends AbstractRectorTestCase
1213
{
14+
use InteractsWithLaravelVersion;
15+
1316
public static function provideData(): Iterator
1417
{
1518
return self::yieldFilesFromDirectory(__DIR__ . '/Fixture/NewGenerics');
@@ -26,6 +29,11 @@ public function test(string $filePath): void
2629

2730
public function provideConfigFilePath(): string
2831
{
29-
return __DIR__ . '/config/use_new_generics_configured_rule.php';
32+
return __DIR__ . '/config/configured_rule.php';
33+
}
34+
35+
public function version(): string
36+
{
37+
return '12.3.0';
3038
}
3139
}

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

+9-1
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,12 @@
77
use Iterator;
88
use PHPUnit\Framework\Attributes\DataProvider;
99
use Rector\Testing\PHPUnit\AbstractRectorTestCase;
10+
use RectorLaravel\Tests\Support\InteractsWithLaravelVersion;
1011

1112
final class AddGenericReturnTypeToRelationsRectorOldGenericsTest extends AbstractRectorTestCase
1213
{
14+
use InteractsWithLaravelVersion;
15+
1316
public static function provideData(): Iterator
1417
{
1518
return self::yieldFilesFromDirectory(__DIR__ . '/Fixture/OldGenerics');
@@ -26,6 +29,11 @@ public function test(string $filePath): void
2629

2730
public function provideConfigFilePath(): string
2831
{
29-
return __DIR__ . '/config/use_old_generics_configured_rule.php';
32+
return __DIR__ . '/config/configured_rule.php';
33+
}
34+
35+
public function version(): string
36+
{
37+
return '11.14.0';
3038
}
3139
}

Diff for: tests/Rector/ClassMethod/AddGenericReturnTypeToRelationsRector/Source/NewApplication.php

-10
This file was deleted.

Diff for: tests/Rector/ClassMethod/AddGenericReturnTypeToRelationsRector/Source/OldApplication.php

-10
This file was deleted.

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

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

55
use Rector\Config\RectorConfig;
66
use RectorLaravel\Rector\ClassMethod\AddGenericReturnTypeToRelationsRector;
7-
use RectorLaravel\Tests\Rector\ClassMethod\AddGenericReturnTypeToRelationsRector\Source\NewApplication;
87

98
return static function (RectorConfig $rectorConfig): void {
109
$rectorConfig->import(__DIR__ . '/../../../../../config/config.php');
1110

12-
$rectorConfig->when(AddGenericReturnTypeToRelationsRector::class)
13-
->needs('$applicationClass')
14-
->give(NewApplication::class);
15-
1611
$rectorConfig->rule(AddGenericReturnTypeToRelationsRector::class);
1712
};

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

-17
This file was deleted.

Diff for: tests/Support/InteractsWithLaravelVersion.php

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<?php
2+
3+
namespace RectorLaravel\Tests\Support;
4+
5+
use Rector\Testing\PHPUnit\AbstractRectorTestCase;
6+
use RectorLaravel\NodeAnalyzer\ApplicationAnalyzer;
7+
8+
/**
9+
* @mixin AbstractRectorTestCase
10+
*/
11+
trait InteractsWithLaravelVersion
12+
{
13+
/**
14+
* @before
15+
*/
16+
public function setAppVersion(): void
17+
{
18+
self::getContainer()->singleton(
19+
ApplicationAnalyzer::class,
20+
fn () => (new ApplicationAnalyzer)
21+
->setVersion($this->version())
22+
);
23+
}
24+
25+
abstract public function version(): string;
26+
}

0 commit comments

Comments
 (0)