8000 Updated Rector to commit 2dda748541be13dac8ef328011bc50233f2030bc · rectorphp/rector@856c640 · GitHub
[go: up one dir, main page]

Skip to content

Commit 856c640

Browse files
committed
Updated Rector to commit 2dda748541be13dac8ef328011bc50233f2030bc
rectorphp/rector-src@2dda748 [DX] Introduce set providers, to enable package + version based set registration (#5976)
1 parent 9d08250 commit 856c640

19 files changed

+348
-27
lines changed

src/Application/VersionResolver.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,12 @@ final class VersionResolver
1919
* @api
2020
* @var string
2121
*/
22-
public const PACKAGE_VERSION = 'f366a7e66228f35dc877e816b553c4f38332f801';
22+
public const PACKAGE_VERSION = '2dda748541be13dac8ef328011bc50233f2030bc';
2323
/**
2424
* @api
2525
* @var string
2626
*/
27-
public const RELEASE_DATE = '2024-06-20 13:21:54';
27+
public const RELEASE_DATE = '2024-06-20 14:52:05';
2828
/**
2929
* @var int
3030
*/
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
<?php
2+
3+
declare (strict_types=1);
4+
namespace Rector\Composer;
5+
6+
use RectorPrefix202406\Nette\Utils\FileSystem;
7+
use RectorPrefix202406\Nette\Utils\Json;
8+
use Rector\Composer\ValueObject\InstalledPackage;
9+
use Rector\Exception\ShouldNotHappenException;
10+
use RectorPrefix202406\Webmozart\Assert\Assert;
11+
/**
12+
* @see \Rector\Tests\Composer\InstalledPackageResolverTest
13+
*/
14+
final class InstalledPackageResolver
15+
{
16+
/**
17+
* @var array<string, InstalledPackage[]>
18+
*/
19+
private $resolvedInstalledPackages = [];
20+
/**
21+
* @return InstalledPackage[]
22+
*/
23+
public function resolve(string $projectDirectory) : array
24+
{
25+
// cache
26+
if (isset($this->resolvedInstalledPackages[$projectDirectory])) {
27+
return $this->resolvedInstalledPackages[$projectDirectory];
28+
}
29+
Assert::directory($projectDirectory);
30+
$installedPackagesFilePath = $projectDirectory . '/vendor/composer/installed.json';
31+
if (!\file_exists($installedPackagesFilePath)) {
32+
throw new ShouldNotHappenException('The installed package json not found. Make sure you run `composer update` and "vendor/composer/installed.json" file exists');
33+
}
34+
$installedPackageFileContents = FileSystem::read($installedPackagesFilePath);
35+
$installedPackagesFilePath = Json::decode($installedPackageFileContents, \true);
36+
$installedPackages = [];
37+
foreach ($installedPackagesFilePath['packages'] as $installedPackage) {
38+
$installedPackages[] = new InstalledPackage($installedPackage['name'], $installedPackage['version_normalized']);
39+
}
40+
$this->resolvedInstalledPackages[$projectDirectory] = $installedPackages;
41+
return $installedPackages;
42+
}
43+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<?php
2+
3+
declare (strict_types=1);
4+
namespace Rector\Composer\ValueObject;
5+
6+
final class InstalledPackage
7+
{
8+
/**
9+
* @readonly
10+
* @var string
11+
*/
12+
private $name;
13+
/**
14+
* @readonly
15+
* @var string
16+
*/
17+
private $version;
18+
public function __construct(string $name, string $version)
19+
{
20+
$this->name = $name;
21+
$this->version = $version;
22+
}
23+
public function getName() : string
24+
{
25+
return $this->name;
26+
}
27+
public function getVersion() : string
28+
{
29+
return $this->version;
30+
}
31+
}

src/Config/RectorConfig.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
use Rector\Contract\Rector\RectorInterface;
1414
use Rector\DependencyInjection\Laravel\ContainerMemento;
1515
use Rector\Exception\ShouldNotHappenException;
16+
use Rector\Set\SetProvider\TwigSetProvider;
1617
use Rector\Skipper\SkipCriteriaResolver\SkippedClassResolver;
1718
use Rector\Validation\RectorConfigValidator;
1819
use Rector\ValueObject\PhpVersion;
@@ -37,7 +38,9 @@ final class RectorConfig extends Container
3738
private $autotagInterfaces = [Command::class];
3839
public static function configure() : RectorConfigBuilder
3940
{
40-
return new RectorConfigBuilder();
41+
$rectorConfigBuilder = new RectorConfigBuilder();
42+
$rectorConfigBuilder->withSetProviders([new TwigSetProvider()]);
43+
return $rectorConfigBuilder;
4144
}
4245
/**
4346
* @param string[] $paths

src/Configuration/RectorConfigBuilder.php

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,12 @@
1515
use Rector\Contract\Rector\RectorInterface;
1616
use Rector\Doctrine\Set\DoctrineSetList;
1717
use Rector\Exception\Configuration\InvalidConfigurationException;
18+
use Rector\Exception\ShouldNotHappenException;
1819
use Rector\Php\PhpVersionResolver\ProjectComposerJsonPhpVersionResolver;
1920
use Rector\PHPUnit\Set\PHPUnitSetList;
21+
use Rector\Set\Contract\SetProviderInterface;
22+
use Rector\Set\Enum\SetGroup;
23+
use Rector\Set\SetManager;
2024
use Rector\Set\ValueObject\LevelSetList;
2125
use Rector\Set\ValueObject\SetList;
2226
use Rector\Symfony\Set\FOSRestSetList;
@@ -161,8 +165,30 @@ final class RectorConfigBuilder
161165
* @var RegisteredService[]
162166
*/
163167
private $registerServices = [];
168+
/**
169+
* @var SetProviderInterface[]
170+
*/
171+
private $setProviders = [];
172+
/**
173+
* @var array<SetGroup::*>
174+
*/
175+
private $setGroups = [];
176+
/**
177+
* @var string[]
178+
*/
179+
private $groupLoadedSets = [];
164180
public function __invoke(RectorConfig $rectorConfig) : void
165181
{
182+
// @experimental 2024-06
183+
if ($this->setGroups !== []) {
184+
if ($this->setProviders === []) {
185+
throw new ShouldNotHappenException(\sprintf('Register set providers first, as they are required for dynamic sets: "%s"', \implode('", "', $this->setGroups)));
186+
}
187+
$setManager = new SetManager($this->setProviders);
188+
$this->groupLoadedSets = $setManager->matchBySetGroups($this->setGroups);
189+
}
190+
// merge sets together
191+
$this->sets = \array_merge($this->sets, $this->groupLoadedSets);
166192
$uniqueSets = \array_unique($this->sets);
167193
if (\in_array(SetList::TYPE_DECLARATION, $uniqueSets, \true) && $this->isTypeCoverageLevelUsed === \true) {
168194
throw new InvalidConfigurationException(\sprintf('Your config already enables type declarations set.%sRemove "->withTypeCoverageLevel()" as it only duplicates it, or remove type declaration set.', \PHP_EOL));
@@ -452,6 +478,14 @@ public function withPhp74Sets() : self
452478
1CF5 }
453479
// there is no withPhp80Sets() and above,
454480
// as we already use PHP 8.0 and should go with withPhpSets() instead
481+
/**
482+
* @param SetProviderInterface[] $setProviders
483+
*/
484+
public function withSetProviders(array $setProviders) : self
485+
{
486+
$this->setProviders = \array_merge($this->setProviders, $setProviders);
487+
return $this;
488+
}
455489
public function withPreparedSets(
456490
bool $deadCode = \false,
457491
bool $codeQuality = \false,
@@ -502,9 +536,9 @@ public function withPreparedSets(
502536
if ($rectorPreset) {
503537
$this->sets[] = SetList::RECTOR_PRESET;
504538
}
539+
// @experimental 2024-06
505540
if ($twig) {
506-
// resolve sets based on composer.json versions
507-
// @todo
541+
$this->setGroups[] = SetGroup::TWIG;
508542
}
509543
return $this;
510544
}

src/Set/Contract/SetInterface.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<?php
2+
3+
declare (strict_types=1);
4+
namespace Rector\Set\Contract;
5+
6+
interface SetInterface
7+
{
8+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?php
2+
3+
declare (strict_types=1);
4+
namespace Rector\Set\Contract;
5+
6+
interface SetProviderInterface
7+
{
8+
/**
9+
* @return SetInterface[]
10+
*/
11+
public function provide() : array;
12+
}

src/Set/Enum/SetGroup.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<?php
2+
3+
declare (strict_types=1);
4+
namespace Rector\Set\Enum;
5+
6+
final class SetGroup
7+
{
8+
public const TWIG = 'twig';
9+
}

src/Set/SetManager.php

Lines changed: 68 additions & 0 deletions
< 10000 tr class="diff-line-row">
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
<?php
2+
3+
declare (strict_types=1);
4+
namespace Rector\Set;
5+
6+
use Rector\Composer\InstalledPackageResolver;
7+
use Rector\Set\Contract\SetProviderInterface;
8+
use Rector\Set\ValueObject\ComposerTriggeredSet;
9+
use RectorPrefix202406\Webmozart\Assert\Assert;
10+
/**
11+
* @see \Rector\Tests\Set\SetCollector\SetCollectorTest
12+
*/
13+
final class SetManager
14+
{
15+
/**
16+
* @var SetProviderInterface[]
17+
* @readonly
18+
*/
19+
private $setProviders;
20+
/**
21+
* @param SetProviderInterface[] $setProviders
22+
*/
23+
public function __construct(array $setProviders)
24+
{
25+
$this->setProviders = $setProviders;
26+
Assert::allIsInstanceOf($setProviders, SetProviderInterface::class);
27+
}
28+
/**
29+
* @return ComposerTriggeredSet[]
30+
*/
31+
public function matchComposerTriggered(string $groupName) : array
32+
{
33+
$matchedSets = [];
34+
foreach ($this->setProviders as $setProvider) {
35+
foreach ($setProvider->provide() as $set) {
36+
if (!$set instanceof ComposerTriggeredSet) {
37+
continue;
38+
}
39+
if ($set->getGroupName() === $groupName) {
40+
$matchedSets[] = $set;
41+
}
42+
}
43+
}
44+
return $matchedSets;
45+
}
46+
/**
47+
* @param string[] $setGroups
48+
* @return string[]
49+
*/
50+
public function matchBySetGroups(array $setGroups) : array
51+
{
52+
$installedPackageResolver = new InstalledPackageResolver();
53+
$installedComposerPackages = $installedPackageResolver->resolve(\getcwd());
54+
$groupLoadedSets = [];
55+
foreach ($setGroups as $setGroup) {
56+
$composerTriggeredSets = $this->matchComposerTriggered($setGroup);
57+
foreach ($composerTriggeredSets as $composerTriggeredSet) {
58+
if ($composerTriggeredSet->matchInstalledPackages($installedComposerPackages)) {
59+
// @todo add debug note somewhere
60+
// echo sprintf('Loaded "%s" set as it meets the conditions', $composerTriggeredSet->getSetFilePath());
61+
// it matched composer package + version requirements → load set
62+
$groupLoadedSets[] = $composerTriggeredSet->getSetFilePath();
63+
}
64+
}
65+
}
66+
return $groupLoadedSets;
67+
}
68+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?php
2+
3+
declare (strict_types=1);
4+
namespace Rector\Set\SetProvider;
5+
6+
use Rector\Set\Contract\SetInterface;
7+
use Rector\Set\Contract\SetProviderInterface;
8+
use Rector\Set\Enum\SetGroup;
9+
use Rector\Set\ValueObject\ComposerTriggeredSet;
10+
use Rector\Symfony\Set\TwigSetList;
11+
/**
12+
* Temporary location, move to rector-symfony package once this is merged
13+
* @experimental 2024-06
14+
*/
15+
final class TwigSetProvider implements SetProviderInterface
16+
{
17+
/**
18+
* @return SetInterface[]
19+
*/
20+
public function provide() : array
21+
{
22+
// @todo temporary name to test, these will be located in rector-symfony, rector-doctrine, rector-phpunit packages
23+
return [new ComposerTriggeredSet(SetGroup::TWIG, 'twig/twig', '1.12', TwigSetList::TWIG_112)];
24+
}
25+
}

0 commit comments

Comments
 (0)
0