mirror of
https://github.com/rectorphp/rector.git
synced 2024-06-26 20:53:31 +00:00
add TokensByFilePathStorage
This commit is contained in:
parent
919fafd57b
commit
48bbc835b1
|
@ -9,8 +9,9 @@ use PhpParser\Lexer;
|
|||
use PhpParser\Node;
|
||||
use PhpParser\ParserFactory;
|
||||
use Rector\Autodiscovery\ValueObject\NodesWithFileDestinationValueObject;
|
||||
use Rector\Core\Application\FileProcessor;
|
||||
use Rector\Core\Application\TokensByFilePathStorage;
|
||||
use Rector\Core\Configuration\Configuration;
|
||||
use Rector\Core\PhpParser\Parser\Parser;
|
||||
use Rector\Core\PhpParser\Printer\BetterStandardPrinter;
|
||||
use Rector\Core\PhpParser\Printer\FormatPerservingPrinter;
|
||||
use Rector\Core\Rector\AbstractRector\AbstractRectorTrait;
|
||||
|
@ -41,11 +42,6 @@ abstract class AbstractFileSystemRector implements FileSystemRectorInterface
|
|||
*/
|
||||
private $oldStmts = [];
|
||||
|
||||
/**
|
||||
* @var Parser
|
||||
*/
|
||||
private $parser;
|
||||
|
||||
/**
|
||||
* @var Lexer
|
||||
*/
|
||||
|
@ -76,11 +72,20 @@ abstract class AbstractFileSystemRector implements FileSystemRectorInterface
|
|||
*/
|
||||
private $renamedClassesCollector;
|
||||
|
||||
/**
|
||||
* @var TokensByFilePathStorage
|
||||
*/
|
||||
private $tokensByFilePathStorage;
|
||||
|
||||
/**
|
||||
* @var FileProcessor
|
||||
*/
|
||||
private $fileProcessor;
|
||||
|
||||
/**
|
||||
* @required
|
||||
*/
|
||||
public function autowireAbstractFileSystemRector(
|
||||
Parser $parser,
|
||||
ParserFactory $parserFactory,
|
||||
Lexer $lexer,
|
||||
FormatPerservingPrinter $formatPerservingPrinter,
|
||||
|
@ -89,9 +94,10 @@ abstract class AbstractFileSystemRector implements FileSystemRectorInterface
|
|||
BetterStandardPrinter $betterStandardPrinter,
|
||||
ParameterProvider $parameterProvider,
|
||||
PostFileProcessor $postFileProcessor,
|
||||
RenamedClassesCollector $renamedClassesCollector
|
||||
RenamedClassesCollector $renamedClassesCollector,
|
||||
TokensByFilePathStorage $tokensByFilePathStorage,
|
||||
FileProcessor $fileProcessor
|
||||
): void {
|
||||
$this->parser = $parser;
|
||||
$this->parserFactory = $parserFactory;
|
||||
$this->lexer = $lexer;
|
||||
$this->formatPerservingPrinter = $formatPerservingPrinter;
|
||||
|
@ -101,6 +107,8 @@ abstract class AbstractFileSystemRector implements FileSystemRectorInterface
|
|||
$this->parameterProvider = $parameterProvider;
|
||||
$this->postFileProcessor = $postFileProcessor;
|
||||
$this->renamedClassesCollector = $renamedClassesCollector;
|
||||
$this->tokensByFilePathStorage = $tokensByFilePathStorage;
|
||||
$this->fileProcessor = $fileProcessor;
|
||||
}
|
||||
|
||||
protected function addClassRename(string $oldClass, string $newClass): void
|
||||
|
@ -113,7 +121,12 @@ abstract class AbstractFileSystemRector implements FileSystemRectorInterface
|
|||
*/
|
||||
protected function parseFileInfoToNodes(SmartFileInfo $smartFileInfo): array
|
||||
{
|
||||
$oldStmts = $this->parser->parseFileInfo($smartFileInfo);
|
||||
if (! $this->tokensByFilePathStorage->hasForRealPath($smartFileInfo->getRealPath())) {
|
||||
$this->fileProcessor->parseFileInfoToLocalCache($smartFileInfo);
|
||||
}
|
||||
|
||||
[, $oldStmts] = $this->tokensByFilePathStorage->getForRealPath($smartFileInfo->getRealPath());
|
||||
|
||||
// needed for format preserving
|
||||
$this->oldStmts = $oldStmts;
|
||||
|
||||
|
@ -125,7 +138,12 @@ abstract class AbstractFileSystemRector implements FileSystemRectorInterface
|
|||
*/
|
||||
protected function parseFileInfoToNodesWithoutScope(SmartFileInfo $smartFileInfo): array
|
||||
{
|
||||
$oldStmts = $this->parser->parseFileInfo($smartFileInfo);
|
||||
if (! $this->tokensByFilePathStorage->hasForRealPath($smartFileInfo->getRealPath())) {
|
||||
$this->fileProcessor->parseFileInfoToLocalCache($smartFileInfo);
|
||||
}
|
||||
|
||||
[, $oldStmts] = $this->tokensByFilePathStorage->getForRealPath($smartFileInfo->getRealPath());
|
||||
|
||||
$this->oldStmts = $oldStmts;
|
||||
|
||||
return $oldStmts;
|
||||
|
|
|
@ -315,3 +315,4 @@ parameters:
|
|||
- '#Parameter \#1 \$oldMethod of class Rector\\PHPOffice\\ValueObject\\ConditionalSetValue constructor expects string, bool\|int\|string given#'
|
||||
- '#Parameter \#2 \$scope of method PHPStan\\Analyser\\NodeScopeResolver\:\:processNodes\(\) expects PHPStan\\Analyser\\MutatingScope, PHPStan\\Analyser\\Scope given#'
|
||||
- '#Parameter \#1 \$object of function get_class expects object, PhpParser\\Node\|null given#'
|
||||
- '#Cognitive complexity for "Rector\\Core\\Application\\RectorApplication\:\:runOnFileInfos\(\)" is 10, keep it under 9#'
|
||||
|
|
|
@ -59,13 +59,14 @@ final class FileMover
|
|||
return null;
|
||||
}
|
||||
|
||||
$currentClassName = $currentNamespace->name->toString() . '\\' . $smartFileInfo->getBasenameWithoutSuffix();
|
||||
|
||||
// is already in the right group
|
||||
if (Strings::endsWith((string) $currentNamespace->name, '\\' . $desiredGroupName)) {
|
||||
$currentNamespaceName = (string) $currentNamespace->name;
|
||||
if (Strings::endsWith($currentNamespaceName, '\\' . $desiredGroupName)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$currentClassName = $currentNamespaceName . '\\' . $smartFileInfo->getBasenameWithoutSuffix();
|
||||
|
||||
// change namespace to new one
|
||||
$newNamespaceName = $this->createNewNamespaceName($desiredGroupName, $currentNamespace);
|
||||
$newClassName = $this->createNewClassName($smartFileInfo, $newNamespaceName);
|
||||
|
@ -76,11 +77,7 @@ final class FileMover
|
|||
}
|
||||
|
||||
// 1. rename namespace
|
||||
foreach ($nodes as $node) {
|
||||
if ($node instanceof Namespace_) {
|
||||
$node->name = new Name($newNamespaceName);
|
||||
}
|
||||
}
|
||||
$this->renameNamespace($nodes, $newNamespaceName);
|
||||
|
||||
// 2. return changed nodes and new file destination
|
||||
$newFileDestination = $this->fileRelocationResolver->createNewFileDestination(
|
||||
|
@ -110,4 +107,19 @@ final class FileMover
|
|||
{
|
||||
return $newNamespaceName . '\\' . $smartFileInfo->getBasenameWithoutSuffix();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Node[] $nodes
|
||||
*/
|
||||
private function renameNamespace(array $nodes, string $newNamespaceName): void
|
||||
{
|
||||
foreach ($nodes as $node) {
|
||||
if (! $node instanceof Namespace_) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$node->name = new Name($newNamespaceName);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,11 +7,8 @@ namespace Rector\Autodiscovery\Rector\FileSystem;
|
|||
use PhpParser\Node;
|
||||
use PhpParser\Node\Stmt\ClassLike;
|
||||
use PhpParser\Node\Stmt\Interface_;
|
||||
use PHPStan\Type\ObjectType;
|
||||
use PHPStan\Type\TypeWithClassName;
|
||||
use Rector\Autodiscovery\FileMover\FileMover;
|
||||
use Rector\Autodiscovery\ValueObject\NodesWithFileDestinationValueObject;
|
||||
use Rector\Core\Exception\ShouldNotHappenException;
|
||||
use Rector\Core\RectorDefinition\CodeSample;
|
||||
use Rector\Core\RectorDefinition\RectorDefinition;
|
||||
use Rector\FileSystemRector\Rector\AbstractFileSystemRector;
|
||||
|
@ -82,15 +79,11 @@ PHP
|
|||
{
|
||||
/** @var Interface_|null $interface */
|
||||
$interface = $this->betterNodeFinder->findFirstInstanceOf($nodes, Interface_::class);
|
||||
|
||||
if ($interface === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
$oldInterfaceName = $this->getName($interface);
|
||||
if ($oldInterfaceName === null) {
|
||||
throw new ShouldNotHappenException();
|
||||
}
|
||||
|
||||
if ($this->isNetteMagicGeneratedFactory($interface)) {
|
||||
return;
|
||||
}
|
||||
|
@ -102,29 +95,14 @@ PHP
|
|||
return;
|
||||
}
|
||||
|
||||
$newInterfaceName = $this->resolveNewClassLikeName($nodesWithFileDestination);
|
||||
|
||||
$this->removeFile($smartFileInfo);
|
||||
$this->addClassRename($oldInterfaceName, $newInterfaceName);
|
||||
|
||||
$this->printNodesWithFileDestination($nodesWithFileDestination);
|
||||
}
|
||||
|
||||
private function resolveNewClassLikeName(
|
||||
NodesWithFileDestinationValueObject $nodesWithFileDestinationValueObject
|
||||
): string {
|
||||
/** @var ClassLike $classLike */
|
||||
$classLike = $this->betterNodeFinder->findFirstInstanceOf(
|
||||
$nodesWithFileDestinationValueObject->getNodes(),
|
||||
ClassLike::class
|
||||
$this->addClassRename(
|
||||
$nodesWithFileDestination->getOldClassName(),
|
||||
$nodesWithFileDestination->getNewClassName()
|
||||
);
|
||||
|
||||
$classLikeName = $this->getName($classLike);
|
||||
if ($classLikeName === null) {
|
||||
throw new ShouldNotHappenException();
|
||||
}
|
||||
|
||||
return $classLikeName;
|
||||
$this->printNodesWithFileDestination($nodesWithFileDestination);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -138,11 +116,13 @@ PHP
|
|||
continue;
|
||||
}
|
||||
|
||||
if ($returnType->isSuperTypeOf(new ObjectType('Nette\Application\UI\Control'))) {
|
||||
$className = $returnType->getClassName();
|
||||
|
||||
if (is_a($className, 'Nette\Application\UI\Control', true)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ($returnType->isSuperTypeOf(new ObjectType('Nette\Application\UI\Form'))) {
|
||||
if (is_a($className, 'Nette\Application\UI\Form', true)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@ final class MoveEntitiesToEntityDirectoryRectorTest extends AbstractFileSystemRe
|
|||
*/
|
||||
public function test(string $originalFile, string $expectedFileLocation, string $expectedFileContent): void
|
||||
{
|
||||
// @todo add extra files too, wehre the calass name will be changed
|
||||
$this->doTestFile($originalFile);
|
||||
|
||||
$this->assertFileExists($expectedFileLocation);
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\Autodiscovery\Tests\Rector\FileSystem\MoveInterfacesToContractNamespaceDirectoryRector\Source;
|
||||
|
||||
use Rector\Autodiscovery\Tests\Rector\FileSystem\MoveEntitiesToEntityDirectoryRector\Source\Contract\RandomInterface;
|
||||
|
||||
class SomeFactory
|
||||
{
|
||||
public function create(): \Rector\Autodiscovery\Tests\Rector\FileSystem\MoveEntitiesToEntityDirectoryRector\Source\Contract\RandomInterface
|
||||
{
|
||||
}
|
||||
}
|
|
@ -12,13 +12,28 @@ final class MoveInterfacesToContractNamespaceDirectoryRectorTest extends Abstrac
|
|||
{
|
||||
/**
|
||||
* @dataProvider provideData()
|
||||
* @param string[] $extraFiles
|
||||
*/
|
||||
public function test(string $originalFile, string $expectedFileLocation, string $expectedFileContent): void
|
||||
{
|
||||
$this->doTestFile($originalFile);
|
||||
public function test(
|
||||
string $originalFile,
|
||||
string $expectedFileLocation,
|
||||
string $expectedFileContent,
|
||||
array $extraFiles = [],
|
||||
?string $extraExpectedFileLocation = null,
|
||||
?string $expectedExtraFileContent = null
|
||||
): void {
|
||||
$this->doTestFile($originalFile, $extraFiles);
|
||||
|
||||
$this->assertFileExists($expectedFileLocation);
|
||||
$this->assertFileEquals($expectedFileContent, $expectedFileLocation);
|
||||
|
||||
if ($extraExpectedFileLocation !== null) {
|
||||
$this->assertFileExists($extraExpectedFileLocation);
|
||||
|
||||
if ($expectedExtraFileContent !== null) {
|
||||
$this->assertFileEquals($expectedExtraFileContent, $extraExpectedFileLocation);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function provideData(): Iterator
|
||||
|
@ -27,6 +42,10 @@ final class MoveInterfacesToContractNamespaceDirectoryRectorTest extends Abstrac
|
|||
__DIR__ . '/Source/Entity/RandomInterface.php',
|
||||
$this->getFixtureTempDirectory() . '/Source/Contract/RandomInterface.php',
|
||||
__DIR__ . '/Expected/ExpectedRandomInterface.php',
|
||||
// extra file
|
||||
[__DIR__ . '/Source/RandomInterfaceUseCase.php'],
|
||||
$this->getFixtureTempDirectory() . '/Source/RandomInterfaceUseCase.php',
|
||||
__DIR__ . '/Expected/ExpectedRandomInterfaceUseCase.php',
|
||||
];
|
||||
|
||||
// skip nette control factory
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\Autodiscovery\Tests\Rector\FileSystem\MoveInterfacesToContractNamespaceDirectoryRector\Source;
|
||||
|
||||
use Rector\Autodiscovery\Tests\Rector\FileSystem\MoveEntitiesToEntityDirectoryRector\Source\Entity\RandomInterface;
|
||||
|
||||
class SomeFactory
|
||||
{
|
||||
public function create(): RandomInterface
|
||||
{
|
||||
}
|
||||
}
|
|
@ -19,11 +19,6 @@ use Symplify\SmartFileSystem\SmartFileInfo;
|
|||
|
||||
final class FileProcessor
|
||||
{
|
||||
/**
|
||||
* @var mixed[][]
|
||||
*/
|
||||
private $tokensByFilePath = [];
|
||||
|
||||
/**
|
||||
* @var FormatPerservingPrinter
|
||||
*/
|
||||
|
@ -69,6 +64,11 @@ final class FileProcessor
|
|||
*/
|
||||
private $postFileProcessor;
|
||||
|
||||
/**
|
||||
* @var TokensByFilePathStorage
|
||||
*/
|
||||
private $tokensByFilePathStorage;
|
||||
|
||||
public function __construct(
|
||||
FormatPerservingPrinter $formatPerservingPrinter,
|
||||
Parser $parser,
|
||||
|
@ -78,7 +78,8 @@ final class FileProcessor
|
|||
CurrentFileInfoProvider $currentFileInfoProvider,
|
||||
StubLoader $stubLoader,
|
||||
AffectedFilesCollector $affectedFilesCollector,
|
||||
PostFileProcessor $postFileProcessor
|
||||
PostFileProcessor $postFileProcessor,
|
||||
TokensByFilePathStorage $tokensByFilePathStorage
|
||||
) {
|
||||
$this->formatPerservingPrinter = $formatPerservingPrinter;
|
||||
$this->parser = $parser;
|
||||
|
@ -89,12 +90,12 @@ final class FileProcessor
|
|||
$this->stubLoader = $stubLoader;
|
||||
$this->affectedFilesCollector = $affectedFilesCollector;
|
||||
$this->postFileProcessor = $postFileProcessor;
|
||||
$this->tokensByFilePathStorage = $tokensByFilePathStorage;
|
||||
}
|
||||
|
||||
public function parseFileInfoToLocalCache(SmartFileInfo $smartFileInfo): void
|
||||
{
|
||||
if (isset($this->tokensByFilePath[$smartFileInfo->getRealPath()])) {
|
||||
// already parsed
|
||||
if ($this->tokensByFilePathStorage->hasForRealPath($smartFileInfo->getRealPath())) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -109,12 +110,14 @@ final class FileProcessor
|
|||
}
|
||||
|
||||
// store tokens by absolute path, so we don't have to print them right now
|
||||
$this->tokensByFilePath[$smartFileInfo->getRealPath()] = [$newStmts, $oldStmts, $oldTokens];
|
||||
$this->tokensByFilePathStorage->addForRealPath($smartFileInfo->getRealPath(), $newStmts, $oldStmts, $oldTokens);
|
||||
}
|
||||
|
||||
public function printToFile(SmartFileInfo $smartFileInfo): string
|
||||
{
|
||||
[$newStmts, $oldStmts, $oldTokens] = $this->tokensByFilePath[$smartFileInfo->getRealPath()];
|
||||
[$newStmts, $oldStmts, $oldTokens] = $this->tokensByFilePathStorage->getForRealPath(
|
||||
$smartFileInfo->getRealPath()
|
||||
);
|
||||
return $this->formatPerservingPrinter->printToFile($smartFileInfo, $newStmts, $oldStmts, $oldTokens);
|
||||
}
|
||||
|
||||
|
@ -125,7 +128,9 @@ final class FileProcessor
|
|||
{
|
||||
$this->makeSureFileIsParsed($smartFileInfo);
|
||||
|
||||
[$newStmts, $oldStmts, $oldTokens] = $this->tokensByFilePath[$smartFileInfo->getRealPath()];
|
||||
[$newStmts, $oldStmts, $oldTokens] = $this->tokensByFilePathStorage->getForRealPath(
|
||||
$smartFileInfo->getRealPath()
|
||||
);
|
||||
return $this->formatPerservingPrinter->printToString($newStmts, $oldStmts, $oldTokens);
|
||||
}
|
||||
|
||||
|
@ -136,7 +141,9 @@ final class FileProcessor
|
|||
|
||||
$this->makeSureFileIsParsed($smartFileInfo);
|
||||
|
||||
[$newStmts, $oldStmts, $oldTokens] = $this->tokensByFilePath[$smartFileInfo->getRealPath()];
|
||||
[$newStmts, $oldStmts, $oldTokens] = $this->tokensByFilePathStorage->getForRealPath(
|
||||
$smartFileInfo->getRealPath()
|
||||
);
|
||||
|
||||
$this->currentFileInfoProvider->setCurrentStmt($newStmts);
|
||||
|
||||
|
@ -144,7 +151,7 @@ final class FileProcessor
|
|||
$newStmts = $this->postFileProcessor->traverse($newStmts);
|
||||
|
||||
// this is needed for new tokens added in "afterTraverse()"
|
||||
$this->tokensByFilePath[$smartFileInfo->getRealPath()] = [$newStmts, $oldStmts, $oldTokens];
|
||||
$this->tokensByFilePathStorage->addForRealPath($smartFileInfo->getRealPath(), $newStmts, $oldStmts, $oldTokens);
|
||||
|
||||
$this->affectedFilesCollector->removeFromList($smartFileInfo);
|
||||
while ($otherTouchedFile = $this->affectedFilesCollector->getNext()) {
|
||||
|
@ -152,6 +159,24 @@ final class FileProcessor
|
|||
}
|
||||
}
|
||||
|
||||
public function postFileRefactor(SmartFileInfo $smartFileInfo): void
|
||||
{
|
||||
if (! $this->tokensByFilePathStorage->hasForRealPath($smartFileInfo->getRealPath())) {
|
||||
$this->parseFileInfoToLocalCache($smartFileInfo);
|
||||
}
|
||||
|
||||
[$newStmts, $oldStmts, $oldTokens] = $this->tokensByFilePathStorage->getForRealPath(
|
||||
$smartFileInfo->getRealPath()
|
||||
);
|
||||
|
||||
$this->currentFileInfoProvider->setCurrentStmt($newStmts);
|
||||
|
||||
$newStmts = $this->postFileProcessor->traverse($newStmts);
|
||||
|
||||
// this is needed for new tokens added in "afterTraverse()"
|
||||
$this->tokensByFilePathStorage->addForRealPath($smartFileInfo->getRealPath(), $newStmts, $oldStmts, $oldTokens);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Node[][]|mixed[]
|
||||
*/
|
||||
|
@ -161,7 +186,7 @@ final class FileProcessor
|
|||
$oldTokens = $this->lexer->getTokens();
|
||||
|
||||
// needed for \Rector\NodeTypeResolver\PHPStan\Scope\NodeScopeResolver
|
||||
$this->tokensByFilePath[$smartFileInfo->getRealPath()] = [$oldStmts, $oldStmts, $oldTokens];
|
||||
$this->tokensByFilePathStorage->addForRealPath($smartFileInfo->getRealPath(), $oldStmts, $oldStmts, $oldTokens);
|
||||
|
||||
$newStmts = $this->nodeScopeAndMetadataDecorator->decorateNodesFromFile($oldStmts, $smartFileInfo);
|
||||
|
||||
|
@ -170,7 +195,7 @@ final class FileProcessor
|
|||
|
||||
private function makeSureFileIsParsed(SmartFileInfo $smartFileInfo): void
|
||||
{
|
||||
if (isset($this->tokensByFilePath[$smartFileInfo->getRealPath()])) {
|
||||
if ($this->tokensByFilePathStorage->hasForRealPath($smartFileInfo->getRealPath())) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -121,8 +121,8 @@ final class RectorApplication
|
|||
}
|
||||
|
||||
if (! $this->symfonyStyle->isVerbose() && $this->configuration->showProgressBar()) {
|
||||
// why 3? one for each cycle, so user sees some activity all the time
|
||||
$this->symfonyStyle->progressStart($fileCount * 3);
|
||||
// why 5? one for each cycle, so user sees some activity all the time
|
||||
$this->symfonyStyle->progressStart($fileCount * 5);
|
||||
|
||||
$this->configureStepCount($this->symfonyStyle);
|
||||
}
|
||||
|
@ -130,6 +130,12 @@ final class RectorApplication
|
|||
// PHPStan has to know about all files!
|
||||
$this->configurePHPStanNodeScopeResolver($fileInfos);
|
||||
|
||||
// active only one rule
|
||||
if ($this->configuration->getOnlyRector() !== null) {
|
||||
$onlyRector = $this->configuration->getOnlyRector();
|
||||
$this->enabledRectorsProvider->addEnabledRector($onlyRector);
|
||||
}
|
||||
|
||||
// 1. parse files to nodes
|
||||
foreach ($fileInfos as $fileInfo) {
|
||||
$this->tryCatchWrapper($fileInfo, function (SmartFileInfo $smartFileInfo): void {
|
||||
|
@ -137,12 +143,6 @@ final class RectorApplication
|
|||
}, 'parsing');
|
||||
}
|
||||
|
||||
// active only one rule
|
||||
if ($this->configuration->getOnlyRector() !== null) {
|
||||
$onlyRector = $this->configuration->getOnlyRector();
|
||||
$this->enabledRectorsProvider->addEnabledRector($onlyRector);
|
||||
}
|
||||
|
||||
// 2. change nodes with Rectors
|
||||
foreach ($fileInfos as $fileInfo) {
|
||||
$this->tryCatchWrapper($fileInfo, function (SmartFileInfo $smartFileInfo): void {
|
||||
|
@ -150,10 +150,24 @@ final class RectorApplication
|
|||
}, 'refactoring');
|
||||
}
|
||||
|
||||
// 3. print to file or string
|
||||
// 3. process file system rectors
|
||||
foreach ($fileInfos as $fileInfo) {
|
||||
$this->tryCatchWrapper($fileInfo, function (SmartFileInfo $smartFileInfo): void {
|
||||
$this->processFileInfo($smartFileInfo);
|
||||
$this->processFileSystemRectors($smartFileInfo);
|
||||
}, 'refactoring with file system');
|
||||
}
|
||||
|
||||
// 4. apply post rectors
|
||||
foreach ($fileInfos as $fileInfo) {
|
||||
$this->tryCatchWrapper($fileInfo, function (SmartFileInfo $smartFileInfo): void {
|
||||
$this->fileProcessor->postFileRefactor($smartFileInfo);
|
||||
}, 'post rectors');
|
||||
}
|
||||
|
||||
// 5. print to file or string
|
||||
foreach ($fileInfos as $fileInfo) {
|
||||
$this->tryCatchWrapper($fileInfo, function (SmartFileInfo $smartFileInfo): void {
|
||||
$this->printFileInfo($smartFileInfo);
|
||||
}, 'printing');
|
||||
}
|
||||
|
||||
|
@ -222,7 +236,7 @@ final class RectorApplication
|
|||
}
|
||||
}
|
||||
|
||||
private function processFileInfo(SmartFileInfo $fileInfo): void
|
||||
private function printFileInfo(SmartFileInfo $fileInfo): void
|
||||
{
|
||||
if ($this->removedAndAddedFilesCollector->isFileRemoved($fileInfo)) {
|
||||
// skip, because this file exists no more
|
||||
|
@ -235,8 +249,6 @@ final class RectorApplication
|
|||
: $this->fileProcessor->printToFile($fileInfo);
|
||||
|
||||
$this->errorAndDiffCollector->addFileDiff($fileInfo, $newContent, $oldContent);
|
||||
|
||||
$this->fileSystemFileProcessor->processFileInfo($fileInfo);
|
||||
}
|
||||
|
||||
private function advance(SmartFileInfo $smartFileInfo, string $phase): void
|
||||
|
@ -248,4 +260,14 @@ final class RectorApplication
|
|||
$this->symfonyStyle->progressAdvance();
|
||||
}
|
||||
}
|
||||
|
||||
private function processFileSystemRectors(SmartFileInfo $smartFileInfo): void
|
||||
{
|
||||
if ($this->removedAndAddedFilesCollector->isFileRemoved($smartFileInfo)) {
|
||||
// skip, because this file exists no more
|
||||
return;
|
||||
}
|
||||
|
||||
$this->fileSystemFileProcessor->processFileInfo($smartFileInfo);
|
||||
}
|
||||
}
|
||||
|
|
47
src/Application/TokensByFilePathStorage.php
Normal file
47
src/Application/TokensByFilePathStorage.php
Normal file
|
@ -0,0 +1,47 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\Core\Application;
|
||||
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Stmt;
|
||||
|
||||
final class TokensByFilePathStorage
|
||||
{
|
||||
/**
|
||||
* @todo use value object
|
||||
* @var Node[][][]|Stmt[][][]
|
||||
*/
|
||||
private $tokensByFilePath = [];
|
||||
|
||||
/**
|
||||
* @todo replace with SmartFileInfo $realPath
|
||||
*
|
||||
* @param Node[]|Stmt[] $newStmts
|
||||
* @param Node[]|Stmt[] $oldStmts
|
||||
* @param Node[]|Stmt[] $oldTokens
|
||||
*/
|
||||
public function addForRealPath(string $realPath, array $newStmts, array $oldStmts, array $oldTokens): void
|
||||
{
|
||||
$this->tokensByFilePath[$realPath] = [$newStmts, $oldStmts, $oldTokens];
|
||||
}
|
||||
|
||||
/**
|
||||
* @todo replace with SmartFileInfo $realPath
|
||||
*/
|
||||
public function hasForRealPath(string $realPath): bool
|
||||
{
|
||||
return isset($this->tokensByFilePath[$realPath]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @todo replace with SmartFileInfo $realPath
|
||||
*
|
||||
* @return Node[][]|Stmt[][]
|
||||
*/
|
||||
public function getForRealPath(string $realPath): array
|
||||
{
|
||||
return $this->tokensByFilePath[$realPath];
|
||||
}
|
||||
}
|
|
@ -6,6 +6,7 @@ namespace Rector\Core\Testing\PHPUnit;
|
|||
|
||||
use Nette\Utils\FileSystem;
|
||||
use Nette\Utils\Strings;
|
||||
use Rector\Core\Application\FileProcessor;
|
||||
use Rector\Core\Application\FileSystem\RemovedAndAddedFilesProcessor;
|
||||
use Rector\Core\Configuration\Configuration;
|
||||
use Rector\Core\HttpKernel\RectorKernel;
|
||||
|
@ -27,6 +28,11 @@ abstract class AbstractFileSystemRectorTestCase extends AbstractGenericRectorTes
|
|||
*/
|
||||
private $removedAndAddedFilesProcessor;
|
||||
|
||||
/**
|
||||
* @var FileProcessor
|
||||
*/
|
||||
private $fileProcessor;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->createContainerWithProvidedRector();
|
||||
|
@ -35,6 +41,7 @@ abstract class AbstractFileSystemRectorTestCase extends AbstractGenericRectorTes
|
|||
$configuration = self::$container->get(Configuration::class);
|
||||
$configuration->setIsDryRun(false);
|
||||
|
||||
$this->fileProcessor = self::$container->get(FileProcessor::class);
|
||||
$this->fileSystemFileProcessor = self::$container->get(FileSystemFileProcessor::class);
|
||||
$this->removedAndAddedFilesProcessor = self::$container->get(RemovedAndAddedFilesProcessor::class);
|
||||
}
|
||||
|
@ -49,13 +56,36 @@ abstract class AbstractFileSystemRectorTestCase extends AbstractGenericRectorTes
|
|||
return $temporaryFilePath;
|
||||
}
|
||||
|
||||
protected function doTestFile(string $file): string
|
||||
/**
|
||||
* @param string[] $extraFiles
|
||||
*/
|
||||
protected function doTestFile(string $file, array $extraFiles = []): string
|
||||
{
|
||||
$temporaryFilePath = $this->createTemporaryFilePathFromFilePath($file);
|
||||
|
||||
require_once $temporaryFilePath;
|
||||
$fileInfo = new SmartFileInfo($temporaryFilePath);
|
||||
$this->fileSystemFileProcessor->processFileInfo($fileInfo);
|
||||
|
||||
$filesInfos = [$fileInfo];
|
||||
|
||||
foreach ($extraFiles as $extraFile) {
|
||||
$temporaryExtraFilePath = $this->createTemporaryFilePathFromFilePath($extraFile);
|
||||
require_once $temporaryExtraFilePath;
|
||||
$extraFileInfo = new SmartFileInfo($temporaryExtraFilePath);
|
||||
$this->fileSystemFileProcessor->processFileInfo($extraFileInfo);
|
||||
|
||||
$filesInfos[] = $extraFileInfo;
|
||||
}
|
||||
|
||||
foreach ($filesInfos as $fileInfo) {
|
||||
if (! file_exists($fileInfo->getPathname())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$this->fileProcessor->postFileRefactor($fileInfo);
|
||||
$this->fileProcessor->printToFile($fileInfo);
|
||||
}
|
||||
|
||||
$this->fileSystemFileProcessor->processFileInfo(new SmartFileInfo($temporaryFilePath));
|
||||
$this->removedAndAddedFilesProcessor->run();
|
||||
|
||||
return $temporaryFilePath;
|
||||
|
@ -107,6 +137,7 @@ abstract class AbstractFileSystemRectorTestCase extends AbstractGenericRectorTes
|
|||
$relativeFilePath = $fileInfo->getRelativeFilePathFromDirectory($testCaseDirectory);
|
||||
$temporaryFilePath = $this->getFixtureTempDirectory() . '/' . $relativeFilePath;
|
||||
|
||||
FileSystem::delete($temporaryFilePath);
|
||||
FileSystem::copy($file, $temporaryFilePath, true);
|
||||
|
||||
return $temporaryFilePath;
|
||||
|
|
Loading…
Reference in New Issue
Block a user