Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 2 additions & 8 deletions bin/rector.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@
declare(strict_types=1);

use Nette\Utils\Json;
use Rector\Bootstrap\AutoloadFileParameterResolver;
use Rector\Bootstrap\RectorConfigsResolver;
use Rector\ChangesReporting\Output\JsonOutputFormatter;
use Rector\Configuration\Option;
use Rector\Configuration\Parameter\SimpleParameterProvider;
use Rector\Console\Style\SymfonyStyleFactory;
use Rector\DependencyInjection\LazyContainerFactory;
use Rector\DependencyInjection\RectorContainerFactory;
Expand Down Expand Up @@ -128,13 +128,7 @@ public function loadIfExistsAndNotLoadedYet(string $filePath): void
$autoloadIncluder->autoloadRectorInstalledAsGlobalDependency();
$autoloadIncluder->autoloadFromCommandLine();

// a different extra autoload changes what PHPStan can resolve, so cached results
// must not survive it: register it before the configuration hash is computed.
// ArgvInput handles both "--autoload-file path" and "--autoload-file=path"
$autoloadFileOption = (new ArgvInput())->getParameterOption(['--autoload-file', '-a'], null);
if (is_string($autoloadFileOption) && $autoloadFileOption !== '') {
SimpleParameterProvider::setParameter(Option::AUTOLOAD_FILE, realpath($autoloadFileOption) ?: $autoloadFileOption);
}
AutoloadFileParameterResolver::resolveFromArgv($_SERVER['argv']);

$rectorConfigsResolver = new RectorConfigsResolver();

Expand Down
37 changes: 37 additions & 0 deletions src/Bootstrap/AutoloadFileParameterResolver.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<?php

declare(strict_types=1);

namespace Rector\Bootstrap;

use Rector\Configuration\Option;
use Rector\Configuration\Parameter\SimpleParameterProvider;
use Symfony\Component\Console\Input\ArgvInput;

/**
* A different extra autoload changes what PHPStan can resolve, so cached results
* must not survive it. Registering the file as a parameter folds it into the
* configuration hash, which invalidates the cache like any other config change.
*
* Called from bin/rector.php before the configuration hash is computed.
*
* @see \Rector\Tests\Bootstrap\AutoloadFileParameterResolverTest
*/
final class AutoloadFileParameterResolver
{
/**
* @param array<int, mixed> $argv
*/
public static function resolveFromArgv(array $argv): void
{
// handles "--autoload-file path", "--autoload-file=path" and "-a path";
// parallel workers receive the space-separated form, so all spellings must
// normalize to the same value or main process and workers would disagree
$autoloadFile = (new ArgvInput($argv))->getParameterOption(['--autoload-file', '-a'], null);
if (! is_string($autoloadFile) || $autoloadFile === '') {
return;
}

SimpleParameterProvider::setParameter(Option::AUTOLOAD_FILE, realpath($autoloadFile) ?: $autoloadFile);
}
}
70 changes: 70 additions & 0 deletions tests/Bootstrap/AutoloadFileParameterResolverTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
<?php

declare(strict_types=1);

namespace Rector\Tests\Bootstrap;

use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\TestCase;
use Rector\Bootstrap\AutoloadFileParameterResolver;
use Rector\Caching\Config\FileHashComputer;
use Rector\Configuration\Option;
use Rector\Configuration\Parameter\SimpleParameterProvider;

final class AutoloadFileParameterResolverTest extends TestCase
{
protected function setUp(): void
{
SimpleParameterProvider::setParameter(Option::AUTOLOAD_FILE, '');
}

/**
* all spellings must resolve to the same value, or the main process and
* parallel workers, which receive the space-separated form, would compute
* different configuration hashes
*
* @param array<int, string> $argv
*/
#[DataProvider('provideArgvSpellings')]
public function testEverySpellingResolvesToSameRealPath(array $argv): void
{
AutoloadFileParameterResolver::resolveFromArgv($argv);

$this->assertSame(
(string) realpath(__FILE__),
SimpleParameterProvider::provideStringParameter(Option::AUTOLOAD_FILE)
);
}

/**
* @return iterable<string, array{array<int, string>}>
*/
public static function provideArgvSpellings(): iterable
{
$relativePath = 'tests/Bootstrap/' . basename(__FILE__);

yield 'long with space' => [['bin/rector', 'process', '--autoload-file', __FILE__]];
yield 'long with equals' => [['bin/rector', 'process', '--autoload-file=' . __FILE__]];
yield 'short with space' => [['bin/rector', 'process', '-a', __FILE__]];
yield 'relative path is normalized' => [['bin/rector', 'process', '-a', $relativePath]];
}

public function testWithoutOptionParameterStaysUntouched(): void
{
AutoloadFileParameterResolver::resolveFromArgv(['bin/rector', 'process', '--dry-run']);

$this->assertSame('', SimpleParameterProvider::provideStringParameter(Option::AUTOLOAD_FILE));
}

public function testResolvedAutoloadFileChangesConfigurationHash(): void
{
$fileHashComputer = new FileHashComputer();
$configFilePath = __DIR__ . '/config/some_config.php';

$hashWithout = $fileHashComputer->compute($configFilePath);

AutoloadFileParameterResolver::resolveFromArgv(['bin/rector', 'process', '-a', __FILE__]);

$this->assertNotSame($hashWithout, $fileHashComputer->compute($configFilePath));
}
}
8 changes: 8 additions & 0 deletions tests/Bootstrap/config/some_config.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?php

declare(strict_types=1);

use Rector\Config\RectorConfig;

return static function (RectorConfig $rectorConfig): void {
};
Loading