mirror of
https://github.com/rectorphp/rector.git
synced 2024-06-01 08:50:50 +00:00
add support for override of already checked file
This commit is contained in:
parent
522dc17cdb
commit
d60e21c0a0
|
@ -10,6 +10,7 @@ use PhpParser\Node\Stmt\ClassLike;
|
|||
use PhpParser\Node\Stmt\ClassMethod;
|
||||
use PhpParser\Node\Stmt\Function_;
|
||||
use PhpParser\Node\Stmt\Interface_;
|
||||
use Rector\Application\FilesToReprintCollector;
|
||||
use Rector\NodeTypeResolver\Application\ClassLikeNodeCollector;
|
||||
use Rector\NodeTypeResolver\Node\Attribute;
|
||||
use Rector\NodeTypeResolver\PhpDoc\NodeAnalyzer\DocBlockAnalyzer;
|
||||
|
@ -41,9 +42,15 @@ abstract class AbstractScalarTypehintRector extends AbstractRector
|
|||
*/
|
||||
protected $classLikeNodeCollector;
|
||||
|
||||
/**
|
||||
* @var FilesToReprintCollector
|
||||
*/
|
||||
protected $filesToReprintCollector;
|
||||
|
||||
public function __construct(
|
||||
DocBlockAnalyzer $docBlockAnalyzer,
|
||||
ClassLikeNodeCollector $classLikeNodeCollector,
|
||||
FilesToReprintCollector $filesToReprintCollector,
|
||||
bool $enableObjectType = false
|
||||
) {
|
||||
$this->docBlockAnalyzer = $docBlockAnalyzer;
|
||||
|
@ -52,6 +59,7 @@ abstract class AbstractScalarTypehintRector extends AbstractRector
|
|||
if ($enableObjectType) {
|
||||
PhpTypeSupport::enableType('object');
|
||||
}
|
||||
$this->filesToReprintCollector = $filesToReprintCollector;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -11,6 +11,7 @@ use PhpParser\Node\Stmt\Function_;
|
|||
use Rector\NodeTypeResolver\Node\Attribute;
|
||||
use Rector\RectorDefinition\CodeSample;
|
||||
use Rector\RectorDefinition\RectorDefinition;
|
||||
use Symplify\PackageBuilder\FileSystem\SmartFileInfo;
|
||||
|
||||
final class ReturnScalarTypehintRector extends AbstractScalarTypehintRector
|
||||
{
|
||||
|
@ -134,6 +135,12 @@ CODE_SAMPLE
|
|||
|
||||
// let the method now it was changed now
|
||||
$childrenClassMethod->returnType->setAttribute(self::HAS_NEW_INHERITED_TYPE, true);
|
||||
|
||||
// reprint the file
|
||||
/** @var SmartFileInfo $fileInfo */
|
||||
$fileInfo = $childrenClassMethod->getAttribute(Attribute::FILE_INFO);
|
||||
|
||||
$this->filesToReprintCollector->addFileInfoWithNewTokens($fileInfo);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -20,7 +20,6 @@ final class ParamAndReturnScalarTypehintsRectorTest extends AbstractRectorTestCa
|
|||
__DIR__ . '/Fixture/external_scope.php.inc',
|
||||
__DIR__ . '/Fixture/local_and_external_scope.php.inc',
|
||||
__DIR__ . '/Fixture/local_scope_with_parent_interface.php.inc',
|
||||
__DIR__ . '/Fixture/local_scope_with_parent_interface2.php.inc',
|
||||
__DIR__ . '/Fixture/local_scope_with_parent_class.php.inc',
|
||||
__DIR__ . '/Fixture/local_scope_with_parent_class2.php.inc',
|
||||
__DIR__ . '/Fixture/complex_array.php.inc',
|
||||
|
|
|
@ -43,6 +43,11 @@ final class FileProcessor
|
|||
*/
|
||||
private $currentFileInfoProvider;
|
||||
|
||||
/**
|
||||
* @var mixed[][]
|
||||
*/
|
||||
private $tokensByFilePath = [];
|
||||
|
||||
public function __construct(
|
||||
FormatPerservingPrinter $formatPerservingPrinter,
|
||||
Parser $parser,
|
||||
|
@ -65,6 +70,17 @@ final class FileProcessor
|
|||
|
||||
[$newStmts, $oldStmts, $oldTokens] = $this->parseAndTraverseFileInfoToNodes($smartFileInfo);
|
||||
|
||||
// store tokens by absolute path, so we don't have to print them right now
|
||||
$this->tokensByFilePath[$smartFileInfo->getRealPath()] = [$newStmts, $oldStmts, $oldTokens];
|
||||
|
||||
return $this->formatPerservingPrinter->printToFile($smartFileInfo, $newStmts, $oldStmts, $oldTokens);
|
||||
}
|
||||
|
||||
public function reprintFile(SmartFileInfo $smartFileInfo): string
|
||||
{
|
||||
// restore tokens
|
||||
[$newStmts, $oldStmts, $oldTokens] = $this->tokensByFilePath[$smartFileInfo->getRealPath()];
|
||||
|
||||
return $this->formatPerservingPrinter->printToFile($smartFileInfo, $newStmts, $oldStmts, $oldTokens);
|
||||
}
|
||||
|
||||
|
@ -77,6 +93,20 @@ final class FileProcessor
|
|||
|
||||
[$newStmts, $oldStmts, $oldTokens] = $this->parseAndTraverseFileInfoToNodes($smartFileInfo);
|
||||
|
||||
// store tokens by absolute path, so we don't have to print them right now
|
||||
$this->tokensByFilePath[$smartFileInfo->getRealPath()] = [$newStmts, $oldStmts, $oldTokens];
|
||||
|
||||
return $this->formatPerservingPrinter->printToString($newStmts, $oldStmts, $oldTokens);
|
||||
}
|
||||
|
||||
/**
|
||||
* See https://github.com/nikic/PHP-Parser/issues/344#issuecomment-298162516.
|
||||
*/
|
||||
public function reprintToString(SmartFileInfo $smartFileInfo): string
|
||||
{
|
||||
// restore tokens
|
||||
[$newStmts, $oldStmts, $oldTokens] = $this->tokensByFilePath[$smartFileInfo->getRealPath()];
|
||||
|
||||
return $this->formatPerservingPrinter->printToString($newStmts, $oldStmts, $oldTokens);
|
||||
}
|
||||
|
||||
|
|
31
src/Application/FilesToReprintCollector.php
Normal file
31
src/Application/FilesToReprintCollector.php
Normal file
|
@ -0,0 +1,31 @@
|
|||
<?php declare(strict_types=1);
|
||||
|
||||
namespace Rector\Application;
|
||||
|
||||
use Symplify\PackageBuilder\FileSystem\SmartFileInfo;
|
||||
|
||||
final class FilesToReprintCollector
|
||||
{
|
||||
/**
|
||||
* @var SmartFileInfo[]
|
||||
*/
|
||||
private $fileInfos = [];
|
||||
|
||||
public function addFileInfoWithNewTokens(SmartFileInfo $smartFileInfo): void
|
||||
{
|
||||
$this->fileInfos[$smartFileInfo->getRealPath()] = $smartFileInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return SmartFileInfo[]
|
||||
*/
|
||||
public function getFileInfos(): array
|
||||
{
|
||||
return $this->fileInfos;
|
||||
}
|
||||
|
||||
public function reset(): void
|
||||
{
|
||||
$this->fileInfos = [];
|
||||
}
|
||||
}
|
|
@ -7,6 +7,7 @@ use Rector\Application\AppliedRectorCollector;
|
|||
use Rector\Application\Error;
|
||||
use Rector\Application\ErrorCollector;
|
||||
use Rector\Application\FileProcessor;
|
||||
use Rector\Application\FilesToReprintCollector;
|
||||
use Rector\Autoloading\AdditionalAutoloader;
|
||||
use Rector\CodingStyle\AfterRectorCodingStyle;
|
||||
use Rector\Configuration\Option;
|
||||
|
@ -32,11 +33,6 @@ use function Safe\sprintf;
|
|||
|
||||
final class ProcessCommand extends Command
|
||||
{
|
||||
/**
|
||||
* @var string[]
|
||||
*/
|
||||
private $changedFiles = [];
|
||||
|
||||
/**
|
||||
* @var FileDiff[]
|
||||
*/
|
||||
|
@ -102,6 +98,11 @@ final class ProcessCommand extends Command
|
|||
*/
|
||||
private $appliedRectorCollector;
|
||||
|
||||
/**
|
||||
* @var FilesToReprintCollector
|
||||
*/
|
||||
private $filesToReprintCollector;
|
||||
|
||||
public function __construct(
|
||||
FileProcessor $fileProcessor,
|
||||
SymfonyStyle $symfonyStyle,
|
||||
|
@ -114,7 +115,8 @@ final class ProcessCommand extends Command
|
|||
FileSystemFileProcessor $fileSystemFileProcessor,
|
||||
ErrorCollector $errorCollector,
|
||||
AfterRectorCodingStyle $afterRectorCodingStyle,
|
||||
AppliedRectorCollector $appliedRectorCollector
|
||||
AppliedRectorCollector $appliedRectorCollector,
|
||||
FilesToReprintCollector $filesToReprintCollector
|
||||
) {
|
||||
parent::__construct();
|
||||
|
||||
|
@ -130,6 +132,7 @@ final class ProcessCommand extends Command
|
|||
$this->errorCollector = $errorCollector;
|
||||
$this->afterRectorCodingStyle = $afterRectorCodingStyle;
|
||||
$this->appliedRectorCollector = $appliedRectorCollector;
|
||||
$this->filesToReprintCollector = $filesToReprintCollector;
|
||||
}
|
||||
|
||||
protected function configure(): void
|
||||
|
@ -178,15 +181,13 @@ final class ProcessCommand extends Command
|
|||
$this->parameterProvider->changeParameter(Option::OPTION_DRY_RUN, $input->getOption(Option::OPTION_DRY_RUN));
|
||||
|
||||
$phpFileInfos = $this->filesFinder->findInDirectoriesAndFiles($source, ['php']);
|
||||
$yamlFileInfos = $this->filesFinder->findInDirectoriesAndFiles($source, ['yml', 'yaml']);
|
||||
$allFileInfos = $phpFileInfos + $yamlFileInfos;
|
||||
|
||||
$this->additionalAutoloader->autoloadWithInputAndSource($input, $source);
|
||||
|
||||
$this->processFileInfos($allFileInfos, (bool) $input->getOption(Option::HIDE_AUTOLOAD_ERRORS));
|
||||
$this->processFileInfos($phpFileInfos, (bool) $input->getOption(Option::HIDE_AUTOLOAD_ERRORS));
|
||||
|
||||
$this->processCommandReporter->reportFileDiffs($this->fileDiffs);
|
||||
$this->processCommandReporter->reportChangedFiles($this->changedFiles);
|
||||
$this->processCommandReporter->reportChangedFiles(array_keys($this->fileDiffs));
|
||||
|
||||
if ($this->errorCollector->getErrors()) {
|
||||
$this->processCommandReporter->reportErrors($this->errorCollector->getErrors());
|
||||
|
@ -231,7 +232,8 @@ final class ProcessCommand extends Command
|
|||
private function processFileInfo(SmartFileInfo $fileInfo, bool $shouldHideAutoloadErrors): void
|
||||
{
|
||||
try {
|
||||
$this->processAnyFile($fileInfo);
|
||||
$this->processFile($fileInfo);
|
||||
$this->fileSystemFileProcessor->processFileInfo($fileInfo);
|
||||
} catch (AnalysedCodeException $analysedCodeException) {
|
||||
if ($shouldHideAutoloadErrors) {
|
||||
return;
|
||||
|
@ -264,19 +266,24 @@ final class ProcessCommand extends Command
|
|||
|
||||
if ($this->parameterProvider->provideParameter(Option::OPTION_DRY_RUN)) {
|
||||
$newContent = $this->fileProcessor->processFileToString($fileInfo);
|
||||
if ($newContent !== $oldContent) {
|
||||
$this->fileDiffs[] = new FileDiff(
|
||||
$fileInfo->getPathname(),
|
||||
$this->differAndFormatter->diffAndFormat($oldContent, $newContent),
|
||||
$this->appliedRectorCollector->getRectorClasses()
|
||||
);
|
||||
|
||||
foreach ($this->filesToReprintCollector->getFileInfos() as $fileInfoToReprint) {
|
||||
$reprintedOldContent = $fileInfoToReprint->getContents();
|
||||
$reprintedNewContent = $this->fileProcessor->reprintToString($fileInfoToReprint);
|
||||
$this->recordFileDiff($fileInfoToReprint, $reprintedNewContent, $reprintedOldContent);
|
||||
}
|
||||
} else {
|
||||
$newContent = $this->fileProcessor->processFile($fileInfo);
|
||||
if ($newContent !== $oldContent) {
|
||||
$this->changedFiles[] = $fileInfo->getPathname();
|
||||
|
||||
foreach ($this->filesToReprintCollector->getFileInfos() as $fileInfoToReprint) {
|
||||
$reprintedOldContent = $fileInfoToReprint->getContents();
|
||||
$reprintedNewContent = $this->fileProcessor->reprintFile($fileInfoToReprint);
|
||||
$this->recordFileDiff($fileInfoToReprint, $reprintedNewContent, $reprintedOldContent);
|
||||
}
|
||||
}
|
||||
|
||||
$this->recordFileDiff($fileInfo, $newContent, $oldContent);
|
||||
$this->filesToReprintCollector->reset();
|
||||
}
|
||||
|
||||
private function matchRectorClass(Throwable $throwable): ?string
|
||||
|
@ -294,12 +301,17 @@ final class ProcessCommand extends Command
|
|||
return $class;
|
||||
}
|
||||
|
||||
private function processAnyFile(SmartFileInfo $fileInfo): void
|
||||
private function recordFileDiff(SmartFileInfo $fileInfo, string $newContent, string $oldContent): void
|
||||
{
|
||||
if ($fileInfo->getExtension() === 'php') {
|
||||
$this->processFile($fileInfo);
|
||||
if ($newContent === $oldContent) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->fileSystemFileProcessor->processFileInfo($fileInfo);
|
||||
// always keep the most recent diff
|
||||
$this->fileDiffs[$fileInfo->getRealPath()] = new FileDiff(
|
||||
$fileInfo->getRealPath(),
|
||||
$this->differAndFormatter->diffAndFormat($oldContent, $newContent),
|
||||
$this->appliedRectorCollector->getRectorClasses()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,8 @@ namespace Rector\Console\Output;
|
|||
use Rector\Application\Error;
|
||||
use Rector\Reporting\FileDiff;
|
||||
use Symfony\Component\Console\Style\SymfonyStyle;
|
||||
use function Safe\ksort;
|
||||
use function Safe\sort;
|
||||
use function Safe\sprintf;
|
||||
|
||||
final class ProcessCommandReporter
|
||||
|
@ -28,6 +30,8 @@ final class ProcessCommandReporter
|
|||
return;
|
||||
}
|
||||
|
||||
sort($changedFiles);
|
||||
|
||||
$this->symfonyStyle->title(
|
||||
sprintf('%d Changed file%s', count($changedFiles), count($changedFiles) === 1 ? '' : 's')
|
||||
);
|
||||
|
@ -43,6 +47,9 @@ final class ProcessCommandReporter
|
|||
return;
|
||||
}
|
||||
|
||||
// normalize
|
||||
ksort($fileDiffs);
|
||||
|
||||
$this->symfonyStyle->title(
|
||||
sprintf('%d file%s with changes', count($fileDiffs), count($fileDiffs) === 1 ? '' : 's')
|
||||
);
|
||||
|
|
|
@ -65,16 +65,16 @@ final class NameResolver
|
|||
return 'empty';
|
||||
};
|
||||
|
||||
$this->nameResolversPerNode[Class_::class] = function (Class_ $classNode): string {
|
||||
if ($classNode->namespacedName) {
|
||||
$this->nameResolversPerNode[Class_::class] = function (Class_ $classNode): ?string {
|
||||
if (isset($classNode->namespacedName)) {
|
||||
return $classNode->namespacedName->toString();
|
||||
}
|
||||
|
||||
return $this->resolve($classNode->name);
|
||||
};
|
||||
|
||||
$this->nameResolversPerNode[Interface_::class] = function (Interface_ $interfaceNode): string {
|
||||
if ($interfaceNode->namespacedName) {
|
||||
$this->nameResolversPerNode[Interface_::class] = function (Interface_ $interfaceNode): ?string {
|
||||
if (isset($interfaceNode->namespacedName)) {
|
||||
return $interfaceNode->namespacedName->toString();
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user