Skip to content

Commit ad30cfb

Browse files
authored
[Config] Improve ComposerJsonPhpVersionResolver API, make use of explicit php set files (#6273)
* improve ComposreJsonPhpVersoinResolver * resolve php sets in explicit way, to avoid magic levels * add PhpLevelSetResolverTest * remove level sets
1 parent 96b585b commit ad30cfb

File tree

11 files changed

+158
-71
lines changed

11 files changed

+158
-71
lines changed

phpstan.neon

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -299,3 +299,6 @@ parameters:
299299
# deprecated
300300
- '#Register "Rector\\Php71\\Rector\\ClassConst\\PublicConstantVisibilityRector" service to "php71\.php" config set#'
301301
- '#Public method "Rector\\ValueObject\\Error\\SystemError\:\:getFile\(\)" is never used#'
302+
303+
# known values
304+
- '#Method Rector\\Util\\PhpVersionFactory\:\:createIntVersion\(\) should return 50200\|50300\|50400\|50500\|50600\|70000\|70100\|70200\|70300\|70400\|80000\|80100\|80200\|80300\|80400\|100000 but returns int#'

src/Configuration/PhpLevelSetResolver.php

Lines changed: 43 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -4,33 +4,53 @@
44

55
namespace Rector\Configuration;
66

7-
use Rector\Exception\Configuration\InvalidConfigurationException;
8-
use Rector\Set\ValueObject\LevelSetList;
7+
use Rector\Set\ValueObject\SetList;
8+
use Rector\Tests\Configuration\PhpLevelSetResolverTest;
99
use Rector\ValueObject\PhpVersion;
10+
use Webmozart\Assert\Assert;
1011

12+
/**
13+
* @see PhpLevelSetResolverTest
14+
*/
1115
final class PhpLevelSetResolver
1216
{
13-
public static function resolveFromPhpVersion(int $phpVersion): string
17+
/**
18+
* @var array<PhpVersion::*, SetList::PHP_*>
19+
*/
20+
private const VERSION_LOWER_BOUND_CONFIGS = [
21+
PhpVersion::PHP_52 => SetList::PHP_52,
22+
PhpVersion::PHP_53 => SetList::PHP_53,
23+
PhpVersion::PHP_54 => SetList::PHP_54,
24+
PhpVersion::PHP_55 => SetList::PHP_55,
25+
PhpVersion::PHP_56 => SetList::PHP_56,
26+
PhpVersion::PHP_70 => SetList::PHP_70,
27+
PhpVersion::PHP_71 => SetList::PHP_71,
28+
PhpVersion::PHP_72 => SetList::PHP_72,
29+
PhpVersion::PHP_73 => SetList::PHP_73,
30+
PhpVersion::PHP_74 => SetList::PHP_74,
31+
PhpVersion::PHP_80 => SetList::PHP_80,
32+
PhpVersion::PHP_81 => SetList::PHP_81,
33+
PhpVersion::PHP_82 => SetList::PHP_82,
34+
PhpVersion::PHP_83 => SetList::PHP_83,
35+
PhpVersion::PHP_84 => SetList::PHP_84,
36+
];
37+
38+
/**
39+
* @param PhpVersion::* $phpVersion
40+
* @return string[]
41+
*/
42+
public static function resolveFromPhpVersion(int $phpVersion): array
1443
{
15-
return match ($phpVersion) {
16-
PhpVersion::PHP_53 => LevelSetList::UP_TO_PHP_53,
17-
PhpVersion::PHP_54 => LevelSetList::UP_TO_PHP_54,
18-
PhpVersion::PHP_55 => LevelSetList::UP_TO_PHP_55,
19-
PhpVersion::PHP_56 => LevelSetList::UP_TO_PHP_56,
20-
PhpVersion::PHP_70 => LevelSetList::UP_TO_PHP_70,
21-
PhpVersion::PHP_71 => LevelSetList::UP_TO_PHP_71,
22-
PhpVersion::PHP_72 => LevelSetList::UP_TO_PHP_72,
23-
PhpVersion::PHP_73 => LevelSetList::UP_TO_PHP_73,
24-
PhpVersion::PHP_74 => LevelSetList::UP_TO_PHP_74,
25-
PhpVersion::PHP_80 => LevelSetList::UP_TO_PHP_80,
26-
PhpVersion::PHP_81 => LevelSetList::UP_TO_PHP_81,
27-
PhpVersion::PHP_82 => LevelSetList::UP_TO_PHP_82,
28-
PhpVersion::PHP_83 => LevelSetList::UP_TO_PHP_83,
29-
PhpVersion::PHP_84 => LevelSetList::UP_TO_PHP_84,
30-
default => throw new InvalidConfigurationException(sprintf(
31-
'Could not resolve PHP level set list for "%s"',
32-
$phpVersion
33-
)),
34-
};
44+
$configFilePaths = [];
45+
46+
foreach (self::VERSION_LOWER_BOUND_CONFIGS as $versionLowerBound => $phpSetFilePath) {
47+
if ($versionLowerBound <= $phpVersion) {
48+
$configFilePaths[] = $phpSetFilePath;
49+
}
50+
}
51+
52+
Assert::allFileExists($configFilePaths);
53+
54+
return $configFilePaths;
3555
}
3656
}

src/Configuration/RectorConfigBuilder.php

Lines changed: 43 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,11 @@
1818
use Rector\Contract\Rector\RectorInterface;
1919
use Rector\Doctrine\Set\DoctrineSetList;
2020
use Rector\Exception\Configuration\InvalidConfigurationException;
21-
use Rector\Php\PhpVersionResolver\ProjectComposerJsonPhpVersionResolver;
21+
use Rector\Php\PhpVersionResolver\ComposerJsonPhpVersionResolver;
2222
use Rector\PHPUnit\Set\PHPUnitSetList;
2323
use Rector\Set\Enum\SetGroup;
2424
use Rector\Set\SetManager;
2525
use Rector\Set\ValueObject\DowngradeLevelSetList;
26-
use Rector\Set\ValueObject\LevelSetList;
2726
use Rector\Set\ValueObject\SetList;
2827
use Rector\Symfony\Set\FOSRestSetList;
2928
use Rector\Symfony\Set\JMSSetList;
@@ -505,53 +504,49 @@ public function withPhpSets(
505504
}
506505

507506
if ($pickedArguments === []) {
508-
// use composer.json PHP version
509-
$projectComposerJsonFilePath = getcwd() . '/composer.json';
510-
if (file_exists($projectComposerJsonFilePath)) {
511-
$projectPhpVersion = ProjectComposerJsonPhpVersionResolver::resolve($projectComposerJsonFilePath);
512-
if (is_int($projectPhpVersion)) {
513-
$this->sets[] = PhpLevelSetResolver::resolveFromPhpVersion($projectPhpVersion);
514-
515-
return $this;
516-
}
517-
}
507+
$projectPhpVersion = ComposerJsonPhpVersionResolver::resolveFromCwdOrFail();
508+
$phpLevelSets = PhpLevelSetResolver::resolveFromPhpVersion($projectPhpVersion);
518509

519-
throw new InvalidConfigurationException(sprintf(
520-
'We could not find local "composer.json" to determine your PHP version.%sPlease, fill the PHP version set in withPhpSets() manually.',
521-
PHP_EOL
522-
));
510+
$this->sets = array_merge($this->sets, $phpLevelSets);
511+
512+
return $this;
523513
}
524514

525515
if ($php53) {
526-
$this->sets[] = LevelSetList::UP_TO_PHP_53;
516+
$targetPhpVersion = PhpVersion::PHP_53;
527517
} elseif ($php54) {
528-
$this->sets[] = LevelSetList::UP_TO_PHP_54;
518+
$targetPhpVersion = PhpVersion::PHP_54;
529519
} elseif ($php55) {
530-
$this->sets[] = LevelSetList::UP_TO_PHP_55;
520+
$targetPhpVersion = PhpVersion::PHP_55;
531521
} elseif ($php56) {
532-
$this->sets[] = LevelSetList::UP_TO_PHP_56;
522+
$targetPhpVersion = PhpVersion::PHP_56;
533523
} elseif ($php70) {
534-
$this->sets[] = LevelSetList::UP_TO_PHP_70;
524+
$targetPhpVersion = PhpVersion::PHP_70;
535525
} elseif ($php71) {
536-
$this->sets[] = LevelSetList::UP_TO_PHP_71;
526+
$targetPhpVersion = PhpVersion::PHP_71;
537527
} elseif ($php72) {
538-
$this->sets[] = LevelSetList::UP_TO_PHP_72;
528+
$targetPhpVersion = PhpVersion::PHP_72;
539529
} elseif ($php73) {
540-
$this->sets[] = LevelSetList::UP_TO_PHP_73;
530+
$targetPhpVersion = PhpVersion::PHP_73;
541531
} elseif ($php74) {
542-
$this->sets[] = LevelSetList::UP_TO_PHP_74;
532+
$targetPhpVersion = PhpVersion::PHP_74;
543533
} elseif ($php80) {
544-
$this->sets[] = LevelSetList::UP_TO_PHP_80;
534+
$targetPhpVersion = PhpVersion::PHP_80;
545535
} elseif ($php81) {
546-
$this->sets[] = LevelSetList::UP_TO_PHP_81;
536+
$targetPhpVersion = PhpVersion::PHP_81;
547537
} elseif ($php82) {
548-
$this->sets[] = LevelSetList::UP_TO_PHP_82;
538+
$targetPhpVersion = PhpVersion::PHP_82;
549539
} elseif ($php83) {
550-
$this->sets[] = LevelSetList::UP_TO_PHP_83;
540+
$targetPhpVersion = PhpVersion::PHP_83;
551541
} elseif ($php84) {
552-
$this->sets[] = LevelSetList::UP_TO_PHP_84;
542+
$targetPhpVersion = PhpVersion::PHP_84;
543+
} else {
544+
throw new InvalidConfigurationException('Invalid PHP version set');
553545
}
554546

547+
$phpLevelSets = PhpLevelSetResolver::resolveFromPhpVersion($targetPhpVersion);
548+
$this->sets = array_merge($this->sets, $phpLevelSets);
549+
555550
return $this;
556551
}
557552

@@ -561,55 +556,64 @@ public function withPhpSets(
561556
*/
562557
public function withPhp53Sets(): self
563558
{
564-
$this->sets[] = LevelSetList::UP_TO_PHP_53;
559+
$this->sets = array_merge($this->sets, PhpLevelSetResolver::resolveFromPhpVersion(PhpVersion::PHP_53));
560+
565561
return $this;
566562
}
567563

568564
public function withPhp54Sets(): self
569565
{
570-
$this->sets[] = LevelSetList::UP_TO_PHP_54;
566+
$this->sets = array_merge($this->sets, PhpLevelSetResolver::resolveFromPhpVersion(PhpVersion::PHP_54));
567+
571568
return $this;
572569
}
573570

574571
public function withPhp55Sets(): self
575572
{
576-
$this->sets[] = LevelSetList::UP_TO_PHP_55;
573+
$this->sets = array_merge($this->sets, PhpLevelSetResolver::resolveFromPhpVersion(PhpVersion::PHP_55));
574+
577575
return $this;
578576
}
579577

580578
public function withPhp56Sets(): self
581579
{
582-
$this->sets[] = LevelSetList::UP_TO_PHP_56;
580+
$this->sets = array_merge($this->sets, PhpLevelSetResolver::resolveFromPhpVersion(PhpVersion::PHP_56));
581+
583582
return $this;
584583
}
585584

586585
public function withPhp70Sets(): self
587586
{
588-
$this->sets[] = LevelSetList::UP_TO_PHP_70;
587+
$this->sets = array_merge($this->sets, PhpLevelSetResolver::resolveFromPhpVersion(PhpVersion::PHP_70));
588+
589589
return $this;
590590
}
591591

592592
public function withPhp71Sets(): self
593593
{
594-
$this->sets[] = LevelSetList::UP_TO_PHP_71;
594+
$this->sets = array_merge($this->sets, PhpLevelSetResolver::resolveFromPhpVersion(PhpVersion::PHP_71));
595+
595596
return $this;
596597
}
597598

598599
public function withPhp72Sets(): self
599600
{
600-
$this->sets[] = LevelSetList::UP_TO_PHP_72;
601+
$this->sets = array_merge($this->sets, PhpLevelSetResolver::resolveFromPhpVersion(PhpVersion::PHP_72));
602+
601603
return $this;
602604
}
603605

604606
public function withPhp73Sets(): self
605607
{
606-
$this->sets[] = LevelSetList::UP_TO_PHP_73;
608+
$this->sets = array_merge($this->sets, PhpLevelSetResolver::resolveFromPhpVersion(PhpVersion::PHP_73));
609+
607610
return $this;
608611
}
609612

610613
public function withPhp74Sets(): self
611614
{
612-
$this->sets[] = LevelSetList::UP_TO_PHP_74;
615+
$this->sets = array_merge($this->sets, PhpLevelSetResolver::resolveFromPhpVersion(PhpVersion::PHP_74));
616+
613617
return $this;
614618
}
615619

src/Php/PhpVersionProvider.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
use Rector\Configuration\Option;
88
use Rector\Configuration\Parameter\SimpleParameterProvider;
99
use Rector\Exception\Configuration\InvalidConfigurationException;
10-
use Rector\Php\PhpVersionResolver\ProjectComposerJsonPhpVersionResolver;
10+
use Rector\Php\PhpVersionResolver\ComposerJsonPhpVersionResolver;
1111
use Rector\Testing\PHPUnit\StaticPHPUnitEnvironment;
1212
use Rector\Util\StringUtils;
1313
use Rector\ValueObject\PhpVersion;
@@ -48,7 +48,7 @@ public function provide(): int
4848

4949
$projectComposerJson = getcwd() . '/composer.json';
5050
if (file_exists($projectComposerJson)) {
51-
$phpVersion = ProjectComposerJsonPhpVersionResolver::resolve($projectComposerJson);
51+
$phpVersion = ComposerJsonPhpVersionResolver::resolve($projectComposerJson);
5252
if ($phpVersion !== null) {
5353
return $this->phpVersionFeatures = $phpVersion;
5454
}

src/Php/PhpVersionResolver/ProjectComposerJsonPhpVersionResolver.php renamed to src/Php/PhpVersionResolver/ComposerJsonPhpVersionResolver.php

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,44 @@
55
namespace Rector\Php\PhpVersionResolver;
66

77
use Composer\Semver\VersionParser;
8+
use Rector\Exception\Configuration\InvalidConfigurationException;
89
use Rector\FileSystem\JsonFileSystem;
910
use Rector\Util\PhpVersionFactory;
11+
use Rector\ValueObject\PhpVersion;
1012

1113
/**
12-
* @see \Rector\Tests\Php\PhpVersionResolver\ProjectComposerJsonPhpVersionResolver\ProjectComposerJsonPhpVersionResolverTest
14+
* @see \Rector\Tests\Php\PhpVersionResolver\ComposerJsonPhpVersionResolver\ComposerJsonPhpVersionResolverTest
1315
*/
14-
final class ProjectComposerJsonPhpVersionResolver
16+
final class ComposerJsonPhpVersionResolver
1517
{
1618
/**
17-
* @var array<string, int|null>
19+
* @var array<string, PhpVersion::*|null>
1820
*/
1921
private static array $cachedPhpVersions = [];
2022

23+
/**
24+
* @return PhpVersion::*
25+
*/
26+
public static function resolveFromCwdOrFail(): int
27+
{
28+
// use composer.json PHP version
29+
$projectComposerJsonFilePath = getcwd() . '/composer.json';
30+
if (file_exists($projectComposerJsonFilePath)) {
31+
$projectPhpVersion = self::resolve($projectComposerJsonFilePath);
32+
if (is_int($projectPhpVersion)) {
33+
return $projectPhpVersion;
34+
}
35+
}
36+
37+
throw new InvalidConfigurationException(sprintf(
38+
'We could not find local "composer.json" to determine your PHP version.%sPlease, fill the PHP version set in withPhpSets() manually.',
39+
PHP_EOL
40+
));
41+
}
42+
43+
/**
44+
* @return PhpVersion::*|null
45+
*/
2146
public static function resolve(string $composerJson): ?int
2247
{
2348
if (array_key_exists($composerJson, self::$cachedPhpVersions)) {
@@ -43,6 +68,9 @@ public static function resolve(string $composerJson): ?int
4368
return self::$cachedPhpVersions[$composerJson] = null;
4469
}
4570

71+
/**
72+
* @return PhpVersion::*
73+
*/
4674
private static function createIntVersionFromComposerVersion(string $projectPhpVersion): int
4775
{
4876
$versionParser = new VersionParser();

src/Util/PhpVersionFactory.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,13 @@
44

55
namespace Rector\Util;
66

7+
use Rector\ValueObject\PhpVersion;
8+
79
final class PhpVersionFactory
810
{
11+
/**
12+
* @return PhpVersion::*
13+
*/
914
public static function createIntVersion(string $version): int
1015
{
1116
$explodeDash = explode('-', $version);
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+
namespace Rector\Tests\Configuration;
6+
7+
use PHPUnit\Framework\TestCase;
8+
use Rector\Configuration\PhpLevelSetResolver;
9+
use Rector\Set\ValueObject\SetList;
10+
use Rector\ValueObject\PhpVersion;
11+
12+
final class PhpLevelSetResolverTest extends TestCase
13+
{
14+
public function test(): void
15+
{
16+
$phpSetFiles = PhpLevelSetResolver::resolveFromPhpVersion(PhpVersion::PHP_56);
17+
$this->assertCount(5, $phpSetFiles);
18+
19+
$this->assertSame([
20+
SetList::PHP_52,
21+
SetList::PHP_53,
22+
SetList::PHP_54,
23+
SetList::PHP_55,
24+
SetList::PHP_56,
25+
], $phpSetFiles);
26+
}
27+
}

tests/Php/PhpVersionResolver/ProjectComposerJsonPhpVersionResolver/ProjectComposerJsonPhpVersionResolverTest.php renamed to tests/Php/PhpVersionResolver/ComposerJsonPhpVersionResolver/ComposerJsonPhpVersionResolverTest.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,19 @@
22

33
declare(strict_types=1);
44

5-
namespace Rector\Tests\Php\PhpVersionResolver\ProjectComposerJsonPhpVersionResolver;
5+
namespace Rector\Tests\Php\PhpVersionResolver\ComposerJsonPhpVersionResolver;
66

77
use Iterator;
88
use PHPUnit\Framework\Attributes\DataProvider;
9-
use Rector\Php\PhpVersionResolver\ProjectComposerJsonPhpVersionResolver;
9+
use Rector\Php\PhpVersionResolver\ComposerJsonPhpVersionResolver;
1010
use Rector\Testing\PHPUnit\AbstractLazyTestCase;
1111

12-
final class ProjectComposerJsonPhpVersionResolverTest extends AbstractLazyTestCase
12+
final class ComposerJsonPhpVersionResolverTest extends AbstractLazyTestCase
1313
{
1414
#[DataProvider('provideData')]
1515
public function test(string $composerJsonFilePath, int|null $expectedPhpVersion): void
1616
{
17-
$resolvePhpVersion = ProjectComposerJsonPhpVersionResolver::resolve($composerJsonFilePath);
17+
$resolvePhpVersion = ComposerJsonPhpVersionResolver::resolve($composerJsonFilePath);
1818
$this->assertSame($expectedPhpVersion, $resolvePhpVersion);
1919
}
2020

tests/Php/PhpVersionResolver/ProjectComposerJsonPhpVersionResolver/Fixture/no_php_definition_composer_json.json renamed to tests/Php/PhpVersionResolver/ComposerJsonPhpVersionResolver/Fixture/no_php_definition_composer_json.json

File renamed without changes.

tests/Php/PhpVersionResolver/ProjectComposerJsonPhpVersionResolver/Fixture/some_composer.json renamed to tests/Php/PhpVersionResolver/ComposerJsonPhpVersionResolver/Fixture/some_composer.json

File renamed without changes.

0 commit comments

Comments
 (0)