Move from Filesystem rules to FileNode (#4528)

* make MoveServicesBySuffixToDirectoryRector with non-filesystem rector

* [ci-review] Rector Rectify

* [ci-review] Rector Rectify

* [ci-review] Rector Rectify

* [ci-review] Apply coding standards

* fixup! make MoveServicesBySuffixToDirectoryRector with non-filesystem rector

Co-authored-by: rector-bot <tomas@getrector.org>
This commit is contained in:
Tomas Votruba 2020-10-31 22:39:09 +01:00 committed by GitHub
parent 4d2a0e731d
commit 8542a3bcbc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
76 changed files with 674 additions and 634 deletions

View File

@ -40,7 +40,7 @@ jobs:
-
name: 'PHP Linter'
run: vendor/bin/parallel-lint src tests packages --exclude packages/rector-generator/templates
run: vendor/bin/parallel-lint src bin/rector config compiler tests packages --exclude packages/rector-generator/templates --colors
name: ${{ matrix.actions.name }}
runs-on: ubuntu-latest
@ -52,7 +52,7 @@ jobs:
-
uses: shivammathur/setup-php@v1
with:
php-version: 7.4
php-version: 7.2
coverage: none
tools: composer:v2

View File

@ -186,7 +186,7 @@
"autoload-dev": {
"classmap": [
"rules/autodiscovery/tests/Rector/FileSystem/MoveInterfacesToContractNamespaceDirectoryRector/Expected",
"rules/autodiscovery/tests/Rector/FileSystem/MoveServicesBySuffixToDirectoryRector/Expected",
"rules/autodiscovery/tests/Rector/FileNode/MoveServicesBySuffixToDirectoryRector/Expected",
"rules/cakephp/tests/Rector/FileWithoutNamespace/ImplicitShortClassNameUseStatementRector/Source",
"rules/cakephp/tests/Rector/Namespace_/AppUsesStaticCallToUseStatementRector/Source",
"rules/psr4/tests/Rector/Namespace_/MultipleClassFileToPsr4ClassesRector/Source",

View File

@ -494,7 +494,7 @@ return static function (ContainerConfigurator $containerConfigurator): void {
new AddReturnTypeDeclaration(
'Nette\Application\UI\Form',
'getPresenter',
new UnionType([new ObjectType('Nette\Application\UI\Presenter'), new NullType()]),
new UnionType([new ObjectType('Nette\Application\UI\Presenter'), new NullType()])
),
new AddReturnTypeDeclaration('Nette\Application\UI\Form', 'signalReceived', new VoidType()),
new AddReturnTypeDeclaration('Nette\Application\UI\IRenderable', 'redrawControl', new VoidType()),
@ -523,7 +523,7 @@ return static function (ContainerConfigurator $containerConfigurator): void {
new AddReturnTypeDeclaration(
'Nette\Application\Routers\SimpleRouter',
'match',
new UnionType([new ObjectType('Nette\Application\Request'), new NullType()]),
new UnionType([new ObjectType('Nette\Application\Request'), new NullType()])
),
new AddReturnTypeDeclaration('Nette\Application\Routers\SimpleRouter', 'getDefaults', $arrayType),
new AddReturnTypeDeclaration('Nette\Application\Routers\SimpleRouter', 'getFlags', new IntegerType()),

View File

@ -178,7 +178,7 @@ Move interface to "Contract" namespace
### `MoveServicesBySuffixToDirectoryRector`
- class: [`Rector\Autodiscovery\Rector\FileSystem\MoveServicesBySuffixToDirectoryRector`](/rules/autodiscovery/src/Rector/FileSystem/MoveServicesBySuffixToDirectoryRector.php)
- class: [`Rector\Autodiscovery\Rector\FileNode\MoveServicesBySuffixToDirectoryRector`](/rules/autodiscovery/src/Rector/FileNode/MoveServicesBySuffixToDirectoryRector.php)
Move classes by their suffix to their own group/directory
@ -187,7 +187,7 @@ Move classes by their suffix to their own group/directory
declare(strict_types=1);
use Rector\Autodiscovery\Rector\FileSystem\MoveServicesBySuffixToDirectoryRector;
use Rector\Autodiscovery\Rector\FileNode\MoveServicesBySuffixToDirectoryRector;
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
return static function (ContainerConfigurator $containerConfigurator): void {

View File

@ -13,5 +13,5 @@ return static function (ContainerConfigurator $containerConfigurator): void {
->autoconfigure();
$services->load('Rector\FileSystemRector\\', __DIR__ . '/../src')
->exclude([__DIR__ . '/../src/Rector']);
->exclude([__DIR__ . '/../src/Rector', __DIR__ . '/../src/ValueObject']);
};

View File

@ -0,0 +1,10 @@
<?php
declare(strict_types=1);
namespace Rector\FileSystemRector\Contract;
interface AddedFileInterface
{
public function getFilePath(): string;
}

View File

@ -0,0 +1,12 @@
<?php
declare(strict_types=1);
namespace Rector\FileSystemRector\Contract;
interface MovedFileInterface
{
public function getOldPathname(): string;
public function getNewPathname(): string;
}

View File

@ -1,36 +0,0 @@
<?php
declare(strict_types=1);
namespace Rector\FileSystemRector\Rector;
use Rector\Autodiscovery\FileMover\FileMover;
use Rector\Autodiscovery\ValueObject\NodesWithFileDestination;
abstract class AbstractFileMovingFileSystemRector extends AbstractFileSystemRector
{
/**
* @var FileMover
*/
protected $fileMover;
/**
* @required
*/
public function autowireAbstractFileMovingFileSystemRector(FileMover $fileMover): void
{
$this->fileMover = $fileMover;
}
protected function processNodesWithFileDestination(NodesWithFileDestination $nodesWithFileDestination): void
{
$this->removeFile($nodesWithFileDestination->getOriginalSmartFileInfo());
$this->addClassRename(
$nodesWithFileDestination->getOldClassName(),
$nodesWithFileDestination->getNewClassName()
);
$this->printNodesWithFileDestination($nodesWithFileDestination);
}
}

View File

@ -7,7 +7,6 @@ namespace Rector\FileSystemRector\Rector;
use Nette\Utils\Strings;
use PhpParser\Lexer;
use PhpParser\Node;
use Rector\Autodiscovery\ValueObject\NodesWithFileDestination;
use Rector\Core\Application\FileProcessor;
use Rector\Core\Application\TokensByFilePathStorage;
use Rector\Core\Configuration\Configuration;
@ -15,8 +14,8 @@ use Rector\Core\PhpParser\Printer\BetterStandardPrinter;
use Rector\Core\PhpParser\Printer\FormatPerservingPrinter;
use Rector\Core\Rector\AbstractRector\AbstractRectorTrait;
use Rector\FileSystemRector\Contract\FileSystemRectorInterface;
use Rector\FileSystemRector\ValueObject\AddedFileWithContent;
use Rector\PostRector\Application\PostFileProcessor;
use Rector\PSR4\Collector\RenamedClassesCollector;
use Symplify\PackageBuilder\Parameter\ParameterProvider;
use Symplify\SmartFileSystem\SmartFileInfo;
@ -58,11 +57,6 @@ abstract class AbstractFileSystemRector implements FileSystemRectorInterface
*/
private $postFileProcessor;
/**
* @var RenamedClassesCollector
*/
private $renamedClassesCollector;
/**
* @var TokensByFilePathStorage
*/
@ -83,7 +77,6 @@ abstract class AbstractFileSystemRector implements FileSystemRectorInterface
BetterStandardPrinter $betterStandardPrinter,
ParameterProvider $parameterProvider,
PostFileProcessor $postFileProcessor,
RenamedClassesCollector $renamedClassesCollector,
TokensByFilePathStorage $tokensByFilePathStorage,
FileProcessor $fileProcessor
): void {
@ -93,16 +86,10 @@ abstract class AbstractFileSystemRector implements FileSystemRectorInterface
$this->betterStandardPrinter = $betterStandardPrinter;
$this->parameterProvider = $parameterProvider;
$this->postFileProcessor = $postFileProcessor;
$this->renamedClassesCollector = $renamedClassesCollector;
$this->tokensByFilePathStorage = $tokensByFilePathStorage;
$this->fileProcessor = $fileProcessor;
}
protected function addClassRename(string $oldClass, string $newClass): void
{
$this->renamedClassesCollector->addClassRename($oldClass, $newClass);
}
/**
* @return Node[]
*/
@ -133,7 +120,8 @@ abstract class AbstractFileSystemRector implements FileSystemRectorInterface
$this->lexer->getTokens()
);
$this->addFile($fileDestination, $fileContent);
$addedFileWithContent = new AddedFileWithContent($fileDestination, $fileContent);
$this->addFile($addedFileWithContent);
}
/**
@ -146,12 +134,8 @@ abstract class AbstractFileSystemRector implements FileSystemRectorInterface
$fileContent = $this->betterStandardPrinter->prettyPrintFile($nodes);
$fileContent = $this->resolveLastEmptyLine($fileContent);
$this->addFile($fileDestination, $fileContent);
}
protected function printNodesWithFileDestination(NodesWithFileDestination $nodesWithFileDestination): void
{
$this->addNodesWithFileDestination($nodesWithFileDestination);
$addedFileWithContent = new AddedFileWithContent($fileDestination, $fileContent);
$this->addFile($addedFileWithContent);
}
/**

View File

@ -0,0 +1,22 @@
<?php
declare(strict_types=1);
namespace Rector\FileSystemRector\Rector\Behavior;
use Rector\FileSystemRector\ValueObjectFactory\MovedFileWithNodesFactory;
trait FileSystemRectorTrait
{
/**
* @var MovedFileWithNodesFactory
*/
protected $movedFileWithNodesFactory;
/**
* @required
*/
public function autowireFileSystemRectorTrait(MovedFileWithNodesFactory $movedFileWithNodesFactory): void
{
$this->movedFileWithNodesFactory = $movedFileWithNodesFactory;
}
}

View File

@ -1,9 +1,11 @@
<?php
declare(strict_types=1);
namespace Rector\Core\ValueObject;
namespace Rector\FileSystemRector\ValueObject;
final class FilePathWithContent
use Rector\FileSystemRector\Contract\AddedFileInterface;
final class AddedFileWithContent implements AddedFileInterface
{
/**
* @var string

View File

@ -2,16 +2,17 @@
declare(strict_types=1);
namespace Rector\Core\ValueObject;
namespace Rector\FileSystemRector\ValueObject;
use Rector\FileSystemRector\Contract\MovedFileInterface;
use Symplify\SmartFileSystem\SmartFileInfo;
final class MovedFile
final class MovedFileWithContent implements MovedFileInterface
{
/**
* @var string
*/
private $newPath;
private $newPathname;
/**
* @var string
@ -23,26 +24,21 @@ final class MovedFile
*/
private $oldFileInfo;
public function __construct(SmartFileInfo $oldFileInfo, string $newPath)
public function __construct(SmartFileInfo $oldFileInfo, string $newPathname)
{
$this->oldFileInfo = $oldFileInfo;
$this->newPath = $newPath;
$this->newPathname = $newPathname;
$this->fileContent = $oldFileInfo->getContents();
}
public function getOldFileInfo(): SmartFileInfo
{
return $this->oldFileInfo;
}
public function getOldPathName(): string
public function getOldPathname(): string
{
return $this->oldFileInfo->getPathname();
}
public function getNewPath(): string
public function getNewPathname(): string
{
return $this->newPath;
return $this->newPathname;
}
public function getFileContent(): string

View File

@ -2,18 +2,19 @@
declare(strict_types=1);
namespace Rector\Autodiscovery\ValueObject;
namespace Rector\FileSystemRector\ValueObject;
use PhpParser\Node;
use Rector\Core\Exception\ShouldNotHappenException;
use Rector\FileSystemRector\Contract\MovedFileInterface;
use Symplify\SmartFileSystem\SmartFileInfo;
final class NodesWithFileDestination
final class MovedFileWithNodes implements MovedFileInterface
{
/**
* @var string
*/
private $fileDestination;
private $filePath;
/**
* @var Node[]
@ -39,10 +40,14 @@ final class NodesWithFileDestination
* @param Node[] $nodes
*/
public function __construct(
array $nodes, string $fileDestination, SmartFileInfo $originalSmartFileInfo, ?string $oldClassName = null, ?string $newClassName = null
array $nodes,
string $fileDestination,
SmartFileInfo $originalSmartFileInfo,
?string $oldClassName = null,
?string $newClassName = null
) {
$this->nodes = $nodes;
$this->fileDestination = $fileDestination;
$this->filePath = $fileDestination;
$this->oldClassName = $oldClassName;
$this->newClassName = $newClassName;
$this->originalSmartFileInfo = $originalSmartFileInfo;
@ -56,9 +61,9 @@ final class NodesWithFileDestination
return $this->nodes;
}
public function getFileDestination(): string
public function getNewPathname(): string
{
return $this->fileDestination;
return $this->filePath;
}
public function getOldClassName(): string
@ -79,8 +84,18 @@ final class NodesWithFileDestination
return $this->newClassName;
}
public function getOriginalSmartFileInfo(): SmartFileInfo
public function hasClassRename(): bool
{
return $this->newClassName !== null;
}
public function getOriginalFileInfo(): SmartFileInfo
{
return $this->originalSmartFileInfo;
}
public function getOldPathname(): string
{
return $this->originalSmartFileInfo->getPathname();
}
}

View File

@ -2,7 +2,7 @@
declare(strict_types=1);
namespace Rector\Autodiscovery\FileMover;
namespace Rector\FileSystemRector\ValueObjectFactory;
use Nette\Utils\Strings;
use PhpParser\Node;
@ -11,12 +11,12 @@ use PhpParser\Node\Name\FullyQualified;
use PhpParser\Node\Stmt\ClassLike;
use PhpParser\Node\Stmt\Namespace_;
use Rector\Autodiscovery\Configuration\CategoryNamespaceProvider;
use Rector\Autodiscovery\ValueObject\NodesWithFileDestination;
use Rector\Core\PhpParser\Node\BetterNodeFinder;
use Rector\FileSystemRector\ValueObject\MovedFileWithNodes;
use Rector\PSR4\FileRelocationResolver;
use Symplify\SmartFileSystem\SmartFileInfo;
final class FileMover
final class MovedFileWithNodesFactory
{
/**
* @var BetterNodeFinder
@ -46,11 +46,11 @@ final class FileMover
/**
* @param Node[] $nodes
*/
public function createMovedNodesAndFilePath(
SmartFileInfo $smartFileInfo,
public function create(
SmartFileInfo $oldFileInfo,
array $nodes,
string $desiredGroupName
): ?NodesWithFileDestination {
): ?MovedFileWithNodes {
/** @var Namespace_|null $currentNamespace */
$currentNamespace = $this->betterNodeFinder->findFirstInstanceOf($nodes, Namespace_::class);
@ -65,14 +65,14 @@ final class FileMover
return null;
}
$currentClassName = $currentNamespaceName . '\\' . $smartFileInfo->getBasenameWithoutSuffix();
$oldClassName = $currentNamespaceName . '\\' . $oldFileInfo->getBasenameWithoutSuffix();
// change namespace to new one
$newNamespaceName = $this->createNewNamespaceName($desiredGroupName, $currentNamespace);
$newClassName = $this->createNewClassName($smartFileInfo, $newNamespaceName);
$newClassName = $this->createNewClassName($oldFileInfo, $newNamespaceName);
// classes are identical, no rename
if ($currentClassName === $newClassName) {
if ($oldClassName === $newClassName) {
return null;
}
@ -81,7 +81,7 @@ final class FileMover
// 2. return changed nodes and new file destination
$newFileDestination = $this->fileRelocationResolver->createNewFileDestination(
$smartFileInfo,
$oldFileInfo,
$desiredGroupName,
$this->categoryNamespaceProvider->provide()
);
@ -91,9 +91,7 @@ final class FileMover
$classLike = $this->betterNodeFinder->findFirstInstanceOf($nodes, ClassLike::class);
$classLike->namespacedName = new FullyQualified($newClassName);
return new NodesWithFileDestination(
$nodes, $newFileDestination, $smartFileInfo, $currentClassName, $newClassName
);
return new MovedFileWithNodes($nodes, $newFileDestination, $oldFileInfo, $oldClassName, $newClassName);
}
private function createNewNamespaceName(string $desiredGroupName, Namespace_ $currentNamespace): string

View File

@ -9,6 +9,7 @@ use PhpParser\Lexer;
use PhpParser\Node;
use Rector\Core\Application\FileSystem\RemovedAndAddedFilesCollector;
use Rector\Core\PhpParser\Printer\BetterStandardPrinter;
use Rector\FileSystemRector\ValueObject\AddedFileWithContent;
use Rector\PostRector\Application\PostFileProcessor;
final class NodesToDestinationPrinter
@ -59,7 +60,7 @@ final class NodesToDestinationPrinter
$fileContent = $this->betterStandardPrinter->prettyPrintFile($nodes);
$fileContent = $this->resolveLastEmptyLine($fileContent);
$this->removedAndAddedFilesCollector->addFileWithContent($fileDestination, $fileContent);
$this->removedAndAddedFilesCollector->addAddedFile(new AddedFileWithContent($fileDestination, $fileContent));
}
/**

View File

@ -103,6 +103,7 @@ final class RectorsFinder
$robotLoader->acceptFiles = [$name];
$robotLoader->excludeDirectory(__DIR__ . '/../../../../packages/rector-generator/tests');
$robotLoader->refresh();
$robotLoader->rebuild();
$classNames = [];

View File

@ -10,17 +10,18 @@ use Rector\Core\Application\FileSystem\RemovedAndAddedFilesProcessor;
use Rector\Core\Configuration\Option;
use Rector\Core\Contract\Rector\PhpRectorInterface;
use Rector\Core\Exception\ShouldNotHappenException;
use Rector\Core\ValueObject\FilePathWithContent;
use Rector\Core\ValueObject\MovedFile;
use Rector\Core\ValueObject\StaticNonPhpFileSuffixes;
use Rector\FileSystemRector\Contract\MovedFileInterface;
use Rector\Testing\Contract\RunnableInterface;
use Rector\Testing\PHPUnit\Behavior\MovingFilesTrait;
use Symplify\EasyTesting\DataProvider\StaticFixtureUpdater;
use Symplify\EasyTesting\StaticFixtureSplitter;
use Symplify\SmartFileSystem\SmartFileInfo;
use Webmozart\Assert\Assert;
abstract class AbstractRectorTestCase extends AbstractGenericRectorTestCase
{
use MovingFilesTrait;
/**
* @var SmartFileInfo
*/
@ -111,36 +112,9 @@ abstract class AbstractRectorTestCase extends AbstractGenericRectorTestCase
$this->assertFileMissing($this->originalTempFileInfo->getPathname());
}
protected function matchMovedFile(): MovedFile
protected function matchMovedFile(): MovedFileInterface
{
return $this->removedAndAddedFilesCollector->getMovedFile($this->originalTempFileInfo);
}
/**
* @param FilePathWithContent[] $expectedFilePathsWithContents
*/
protected function assertFilesWereAdded(array $expectedFilePathsWithContents): void
{
Assert::allIsAOf($expectedFilePathsWithContents, FilePathWithContent::class);
$addedFilePathsWithContents = $this->removedAndAddedFilesCollector->getAddedFilePathsWithContents();
sort($addedFilePathsWithContents);
sort($expectedFilePathsWithContents);
foreach ($addedFilePathsWithContents as $key => $addedFilePathWithContent) {
$expectedFilePathWithContent = $expectedFilePathsWithContents[$key];
$this->assertSame(
$expectedFilePathWithContent->getFilePath(),
$addedFilePathWithContent->getFilePath()
);
$this->assertSame(
$expectedFilePathWithContent->getFileContent(),
$addedFilePathWithContent->getFileContent()
);
}
return $this->removedAndAddedFilesCollector->getMovedFileByFileInfo($this->originalTempFileInfo);
}
private function doTestFileMatchesExpectedContent(

View File

@ -0,0 +1,48 @@
<?php
declare(strict_types=1);
namespace Rector\Testing\PHPUnit\Behavior;
use Rector\Core\Application\FileSystem\RemovedAndAddedFilesCollector;
use Rector\FileSystemRector\ValueObject\AddedFileWithContent;
use Symplify\SmartFileSystem\SmartFileInfo;
use Webmozart\Assert\Assert;
/**
* @property-read RemovedAndAddedFilesCollector $removedAndAddedFilesCollector
*/
trait MovingFilesTrait
{
protected function assertFileWasNotChanged(SmartFileInfo $smartFileInfo): void
{
$movedFile = $this->removedAndAddedFilesCollector->getMovedFileByFileInfo($smartFileInfo);
$this->assertNull($movedFile);
}
/**
* @param AddedFileWithContent[] $expectedFilePathsWithContents
*/
protected function assertFilesWereAdded(array $expectedFilePathsWithContents): void
{
Assert::allIsAOf($expectedFilePathsWithContents, AddedFileWithContent::class);
$addedFilePathsWithContents = $this->removedAndAddedFilesCollector->getAddedFiles();
sort($addedFilePathsWithContents);
sort($expectedFilePathsWithContents);
foreach ($addedFilePathsWithContents as $key => $addedFilePathWithContent) {
$expectedFilePathWithContent = $expectedFilePathsWithContents[$key];
$this->assertSame(
$expectedFilePathWithContent->getFilePath(),
$addedFilePathWithContent->getFilePath()
);
$this->assertSame(
$expectedFilePathWithContent->getFileContent(),
$addedFilePathWithContent->getFileContent()
);
}
}
}

View File

@ -601,6 +601,7 @@ parameters:
-
message: '#Do not use trait#'
paths:
- packages/**/src/Behavior/**
- packages/better-php-doc-parser/src/Attributes/Attribute/AttributeTrait.php # 7
- packages/better-php-doc-parser/src/PartPhpDocTagPrinter/Behavior/ArrayPartPhpDocTagPrinterTrait.php # 14
- packages/better-php-doc-parser/src/PhpDocNode/PrintTagValueNodeTrait.php # 13

View File

@ -13,5 +13,5 @@ return static function (ContainerConfigurator $containerConfigurator): void {
->autoconfigure();
$services->load('Rector\Autodiscovery\\', __DIR__ . '/../src')
->exclude([__DIR__ . '/../src/Rector', __DIR__ . '/../src/ValueObject']);
->exclude([__DIR__ . '/../src/Rector']);
};

View File

@ -0,0 +1,19 @@
<?php
declare(strict_types=1);
namespace Rector\Autodiscovery\FileLocation;
final class ExpectedFileLocationResolver
{
/**
* Resolves if is suffix in the same category, e.g. "Exception/SomeException.php"
*/
public function resolve(string $escapedGroupName, string $suffixPattern): string
{
$escapedGroupName = preg_quote($escapedGroupName, '#');
$escapedSuffixPattern = preg_quote($suffixPattern, '#');
return sprintf('#\/%s\/.+%s#', $escapedGroupName, $escapedSuffixPattern);
}
}

View File

@ -2,37 +2,49 @@
declare(strict_types=1);
namespace Rector\Autodiscovery\Rector\FileSystem;
namespace Rector\Autodiscovery\Rector\FileNode;
use Nette\Utils\Strings;
use PhpParser\Node;
use PhpParser\Node\Stmt\Class_;
use Rector\Autodiscovery\FileLocation\ExpectedFileLocationResolver;
use Rector\Core\Contract\Rector\ConfigurableRectorInterface;
use Rector\Core\PhpParser\Node\CustomNode\FileNode;
use Rector\Core\Rector\AbstractRector;
use Rector\Core\RectorDefinition\ConfiguredCodeSample;
use Rector\Core\RectorDefinition\RectorDefinition;
use Rector\FileSystemRector\Rector\AbstractFileMovingFileSystemRector;
use Symplify\SmartFileSystem\SmartFileInfo;
use Webmozart\Assert\Assert;
/**
* @sponsor Thanks https://spaceflow.io/ for sponsoring this rule - visit them on https://github.com/SpaceFlow-app
*
* Inspiration @see https://github.com/rectorphp/rector/pull/1865/files#diff-0d18e660cdb626958662641b491623f8
*
* @see \Rector\Autodiscovery\Tests\Rector\FileSystem\MoveServicesBySuffixToDirectoryRector\MoveServicesBySuffixToDirectoryRectorTest
* @see \Rector\Autodiscovery\Tests\Rector\FileSystem\MoveServicesBySuffixToDirectoryRector\MutualRenameTest
* @see \Rector\Autodiscovery\Tests\Rector\FileNode\MoveServicesBySuffixToDirectoryRector\MoveServicesBySuffixToDirectoryRectorTest
* @see \Rector\Autodiscovery\Tests\Rector\FileNode\MoveServicesBySuffixToDirectoryRector\MutualRenameTest
*/
final class MoveServicesBySuffixToDirectoryRector extends AbstractFileMovingFileSystemRector implements ConfigurableRectorInterface
final class MoveServicesBySuffixToDirectoryRector extends AbstractRector implements ConfigurableRectorInterface
{
/**
* @var string
*/
public const GROUP_NAMES_BY_SUFFIX = '$groupNamesBySuffix';
public const GROUP_NAMES_BY_SUFFIX = 'group_names_by_suffix';
/**
* @var string[]
*/
private $groupNamesBySuffix = [];
/**
* @var ExpectedFileLocationResolver
*/
private $expectedFileLocationResolver;
public function __construct(ExpectedFileLocationResolver $expectedFileLocationResolver)
{
$this->expectedFileLocationResolver = $expectedFileLocationResolver;
}
public function getDefinition(): RectorDefinition
{
return new RectorDefinition('Move classes by their suffix to their own group/directory', [
@ -64,33 +76,49 @@ CODE_SAMPLE
]);
}
public function refactor(SmartFileInfo $smartFileInfo): void
/**
* @param FileNode $node
*/
public function refactor(Node $node): ?Node
{
$nodes = $this->parseFileInfoToNodes($smartFileInfo);
$class = $this->betterNodeFinder->findFirstInstanceOf($nodes, Class_::class);
if ($class === null) {
return;
$classLikes = $this->betterNodeFinder->findClassLikes($node);
if ($classLikes === []) {
return null;
}
$this->processGroupNamesBySuffix($smartFileInfo, $nodes, $this->groupNamesBySuffix);
$this->processGroupNamesBySuffix($node->getFileInfo(), $node, $this->groupNamesBySuffix);
return null;
}
public function configure(array $configuration): void
{
$this->groupNamesBySuffix = $configuration[self::GROUP_NAMES_BY_SUFFIX] ?? [];
$groupNamesBySuffix = $configuration[self::GROUP_NAMES_BY_SUFFIX] ?? [];
Assert::allString($groupNamesBySuffix);
$this->groupNamesBySuffix = $groupNamesBySuffix;
}
/**
* @return string[]
*/
public function getNodeTypes(): array
{
return [FileNode::class];
}
/**
* A. Match classes by suffix and move them to group namespace
* E.g. App\Controller\SomeException App\Exception\SomeException
*
* @param Node[] $nodes
* E.g. "App\Controller\SomeException"
*
* "App\Exception\SomeException"
*
* @param string[] $groupNamesBySuffix
*/
private function processGroupNamesBySuffix(
SmartFileInfo $smartFileInfo,
array $nodes,
FileNode $fileNode,
array $groupNamesBySuffix
): void {
foreach ($groupNamesBySuffix as $groupName) {
@ -109,7 +137,7 @@ CODE_SAMPLE
continue;
}
$this->moveFileToGroupName($smartFileInfo, $nodes, $groupName);
$this->moveFileToGroupName($smartFileInfo, $fileNode, $groupName);
return;
}
}
@ -119,33 +147,18 @@ CODE_SAMPLE
string $suffixPattern,
SmartFileInfo $smartFileInfo
): bool {
$expectedLocationFilePattern = $this->createExpectedFileLocationPattern($groupName, $suffixPattern);
$expectedLocationFilePattern = $this->expectedFileLocationResolver->resolve($groupName, $suffixPattern);
return (bool) Strings::match($smartFileInfo->getRealPath(), $expectedLocationFilePattern);
}
/**
* @param Node[] $nodes
*/
private function moveFileToGroupName(SmartFileInfo $smartFileInfo, array $nodes, string $desiredGroupName): void
private function moveFileToGroupName(SmartFileInfo $fileInfo, FileNode $fileNode, string $desiredGroupName): void
{
$nodesWithFileDestination = $this->fileMover->createMovedNodesAndFilePath(
$smartFileInfo,
$nodes,
$desiredGroupName
);
if ($nodesWithFileDestination === null) {
$movedFileWithNodes = $this->movedFileWithNodesFactory->create($fileInfo, [$fileNode], $desiredGroupName);
if ($movedFileWithNodes === null) {
return;
}
$this->processNodesWithFileDestination($nodesWithFileDestination);
}
/**
* Checks if is suffix in the same category, e.g. "Exception/SomeException.php"
*/
private function createExpectedFileLocationPattern(string $groupName, string $suffixPattern): string
{
return sprintf('#\/%s\/.+%s#', preg_quote($groupName, '#'), preg_quote($suffixPattern, '#'));
$this->addMovedFile($movedFileWithNodes);
}
}

View File

@ -10,7 +10,7 @@ use PhpParser\Node\Stmt\Class_;
use Rector\BetterPhpDocParser\ValueObject\PhpDocNode\Doctrine\Class_\EntityTagValueNode;
use Rector\Core\RectorDefinition\CodeSample;
use Rector\Core\RectorDefinition\RectorDefinition;
use Rector\FileSystemRector\Rector\AbstractFileMovingFileSystemRector;
use Rector\FileSystemRector\Rector\AbstractFileSystemRector;
use Symplify\SmartFileSystem\SmartFileInfo;
/**
@ -20,7 +20,7 @@ use Symplify\SmartFileSystem\SmartFileInfo;
*
* @see \Rector\Autodiscovery\Tests\Rector\FileSystem\MoveEntitiesToEntityDirectoryRector\MoveEntitiesToEntityDirectoryRectorTest
*/
final class MoveEntitiesToEntityDirectoryRector extends AbstractFileMovingFileSystemRector
final class MoveEntitiesToEntityDirectoryRector extends AbstractFileSystemRector
{
/**
* @var string
@ -75,12 +75,12 @@ CODE_SAMPLE
return;
}
$nodesWithFileDestination = $this->fileMover->createMovedNodesAndFilePath($smartFileInfo, $nodes, 'Entity');
if ($nodesWithFileDestination === null) {
$movedFileWithNodes = $this->movedFileWithNodesFactory->create($smartFileInfo, $nodes, 'Entity');
if ($movedFileWithNodes === null) {
return;
}
$this->processNodesWithFileDestination($nodesWithFileDestination);
$this->addMovedFile($movedFileWithNodes);
}
/**

View File

@ -8,7 +8,7 @@ use PhpParser\Node;
use PhpParser\Node\Stmt\Interface_;
use Rector\Core\RectorDefinition\CodeSample;
use Rector\Core\RectorDefinition\RectorDefinition;
use Rector\FileSystemRector\Rector\AbstractFileMovingFileSystemRector;
use Rector\FileSystemRector\Rector\AbstractFileSystemRector;
use Rector\NetteToSymfony\Analyzer\NetteControlFactoryInterfaceAnalyzer;
use Symplify\SmartFileSystem\SmartFileInfo;
@ -19,7 +19,7 @@ use Symplify\SmartFileSystem\SmartFileInfo;
*
* @see \Rector\Autodiscovery\Tests\Rector\FileSystem\MoveInterfacesToContractNamespaceDirectoryRector\MoveInterfacesToContractNamespaceDirectoryRectorTest
*/
final class MoveInterfacesToContractNamespaceDirectoryRector extends AbstractFileMovingFileSystemRector
final class MoveInterfacesToContractNamespaceDirectoryRector extends AbstractFileSystemRector
{
/**
* @var NetteControlFactoryInterfaceAnalyzer
@ -78,11 +78,11 @@ CODE_SAMPLE
return;
}
$nodesWithFileDestination = $this->fileMover->createMovedNodesAndFilePath($smartFileInfo, $nodes, 'Contract');
if ($nodesWithFileDestination === null) {
$movedFileWithNodes = $this->movedFileWithNodesFactory->create($smartFileInfo, $nodes, 'Contract');
if ($movedFileWithNodes === null) {
return;
}
$this->processNodesWithFileDestination($nodesWithFileDestination);
$this->addMovedFile($movedFileWithNodes);
}
}

View File

@ -10,7 +10,7 @@ use Rector\Autodiscovery\Analyzer\ClassAnalyzer;
use Rector\Core\Contract\Rector\ConfigurableRectorInterface;
use Rector\Core\RectorDefinition\ConfiguredCodeSample;
use Rector\Core\RectorDefinition\RectorDefinition;
use Rector\FileSystemRector\Rector\AbstractFileMovingFileSystemRector;
use Rector\FileSystemRector\Rector\AbstractFileSystemRector;
use Rector\NodeTypeResolver\Node\AttributeKey;
use Symplify\SmartFileSystem\SmartFileInfo;
@ -22,7 +22,7 @@ use Symplify\SmartFileSystem\SmartFileInfo;
*
* @see \Rector\Autodiscovery\Tests\Rector\FileSystem\MoveValueObjectsToValueObjectDirectoryRector\MoveValueObjectsToValueObjectDirectoryRectorTest
*/
final class MoveValueObjectsToValueObjectDirectoryRector extends AbstractFileMovingFileSystemRector implements ConfigurableRectorInterface
final class MoveValueObjectsToValueObjectDirectoryRector extends AbstractFileSystemRector implements ConfigurableRectorInterface
{
/**
* @var string
@ -135,17 +135,12 @@ CODE_SAMPLE
return;
}
$nodesWithFileDestination = $this->fileMover->createMovedNodesAndFilePath(
$smartFileInfo,
$nodes,
'ValueObject'
);
if ($nodesWithFileDestination === null) {
$movedFileWithNodes = $this->movedFileWithNodesFactory->create($smartFileInfo, $nodes, 'ValueObject');
if ($movedFileWithNodes === null) {
return;
}
$this->processNodesWithFileDestination($nodesWithFileDestination);
$this->addMovedFile($movedFileWithNodes);
}
public function configure(array $configuration): void

View File

@ -0,0 +1,12 @@
<?php
declare(strict_types=1);
namespace Rector\Autodiscovery\Tests\Rector\FileNode\MoveServicesBySuffixToDirectoryRector\Source\Command;
final class BananaCommand
{
public function run()
{
return new \Rector\Autodiscovery\Tests\Rector\FileNode\MoveServicesBySuffixToDirectoryRector\Source\Controller\Orange();
}
}

View File

@ -0,0 +1,12 @@
<?php
declare(strict_types=1);
namespace Rector\Autodiscovery\Tests\Rector\FileNode\MoveServicesBySuffixToDirectoryRector\Source\Controller;
final class MissPlacedController
{
public function getSelf()
{
return new \Rector\Autodiscovery\Tests\Rector\FileNode\MoveServicesBySuffixToDirectoryRector\Source\Controller\MissPlacedController();
}
}

View File

@ -0,0 +1,8 @@
<?php
declare(strict_types=1);
namespace Rector\Autodiscovery\Tests\Rector\FileNode\MoveServicesBySuffixToDirectoryRector\Source\Mapper\Nested;
abstract class AbstractBaseMapper
{
}

View File

@ -0,0 +1,8 @@
<?php
declare(strict_types=1);
namespace Rector\Autodiscovery\Tests\Rector\FileNode\MoveServicesBySuffixToDirectoryRector\Source\Mapper\Nested;
abstract class AbstractBaseWithSpaceMapper
{
}

View File

@ -0,0 +1,9 @@
<?php
declare(strict_types=1);
namespace Rector\Autodiscovery\Tests\Rector\FileNode\MoveServicesBySuffixToDirectoryRector\Source\Mapper;
use Rector\Autodiscovery\Tests\Rector\FileNode\MoveServicesBySuffixToDirectoryRector\Source\Mapper\Nested\AbstractBaseMapper;
final class UserMapper extends \Rector\Autodiscovery\Tests\Rector\FileNode\MoveServicesBySuffixToDirectoryRector\Source\Mapper\Nested\AbstractBaseMapper
{
}

View File

@ -0,0 +1,9 @@
<?php
declare(strict_types=1);
namespace Rector\Autodiscovery\Tests\Rector\FileNode\MoveServicesBySuffixToDirectoryRector\Source\Mapper;
use Rector\Autodiscovery\Tests\Rector\FileNode\MoveServicesBySuffixToDirectoryRector\Source\Mapper\Nested\AbstractBaseWithSpaceMapper;
final class UserWithSpaceMapper extends \Rector\Autodiscovery\Tests\Rector\FileNode\MoveServicesBySuffixToDirectoryRector\Source\Mapper\Nested\AbstractBaseWithSpaceMapper
{
}

View File

@ -0,0 +1,8 @@
<?php
declare(strict_types=1);
namespace Rector\Autodiscovery\Tests\Rector\FileNode\MoveServicesBySuffixToDirectoryRector\Source\Repository;
class AppleRepository
{
}

View File

@ -0,0 +1,2 @@
services:
Rector\Autodiscovery\Tests\Rector\FileNode\MoveServicesBySuffixToDirectoryRector\Source\Mapper\Nested\AbstractBaseMapper: null

View File

@ -0,0 +1,98 @@
<?php
declare(strict_types=1);
namespace Rector\Autodiscovery\Tests\Rector\FileNode\MoveServicesBySuffixToDirectoryRector;
use Iterator;
use Rector\Autodiscovery\Rector\FileNode\MoveServicesBySuffixToDirectoryRector;
use Rector\FileSystemRector\ValueObject\AddedFileWithContent;
use Rector\Testing\PHPUnit\AbstractRectorTestCase;
use Symplify\SmartFileSystem\SmartFileInfo;
use Symplify\SmartFileSystem\SmartFileSystem;
final class MoveServicesBySuffixToDirectoryRectorTest extends AbstractRectorTestCase
{
/**
* @dataProvider provideData()
*/
public function test(SmartFileInfo $originalFileInfo, ?AddedFileWithContent $expectedAddedFileWithContent): void
{
$this->doTestFileInfo($originalFileInfo);
if ($expectedAddedFileWithContent === null) {
// no change - file should have the original location
$this->assertFileWasNotChanged($this->originalTempFileInfo);
}
if ($expectedAddedFileWithContent !== null) {
$this->assertFilesWereAdded([$expectedAddedFileWithContent]);
}
}
public function provideData(): Iterator
{
$smartFileSystem = new SmartFileSystem();
yield [
new SmartFileInfo(__DIR__ . '/Source/Entity/AppleRepository.php'),
new AddedFileWithContent(
$this->getFixtureTempDirectory() . '/Source/Repository/AppleRepository.php',
$smartFileSystem->readFile(__DIR__ . '/Expected/Repository/ExpectedAppleRepository.php')
),
];
yield [
new SmartFileInfo(__DIR__ . '/Source/Controller/BananaCommand.php'),
new AddedFileWithContent(
$this->getFixtureTempDirectory() . '/Source/Command/BananaCommand.php',
$smartFileSystem->readFile(__DIR__ . '/Expected/Command/ExpectedBananaCommand.php')
),
];
yield [
new SmartFileInfo(__DIR__ . '/Source/Command/MissPlacedController.php'),
new AddedFileWithContent(
$this->getFixtureTempDirectory() . '/Source/Controller/MissPlacedController.php',
$smartFileSystem->readFile(__DIR__ . '/Expected/Controller/MissPlacedController.php')
),
];
// nothing changes
yield [new SmartFileInfo(__DIR__ . '/Source/Mapper/SkipCorrectMapper.php'), null];
yield [
new SmartFileInfo(__DIR__ . '/Source/Controller/Nested/AbstractBaseWithSpaceMapper.php'),
new AddedFileWithContent(
$this->getFixtureTempDirectory() . '/Source/Mapper/Nested/AbstractBaseWithSpaceMapper.php',
$smartFileSystem->readFile(__DIR__ . '/Expected/Mapper/Nested/AbstractBaseWithSpaceMapper.php.inc')
),
];
// inversed order, but should have the same effect
yield [
new SmartFileInfo(__DIR__ . '/Source/Entity/UserMapper.php'),
new AddedFileWithContent(
$this->getFixtureTempDirectory() . '/Source/Mapper/UserMapper.php',
$smartFileSystem->readFile(__DIR__ . '/Expected/Mapper/UserMapper.php.inc')
),
];
}
/**
* @return array<string, mixed[]>
*/
protected function getRectorsWithConfiguration(): array
{
return [
MoveServicesBySuffixToDirectoryRector::class => [
MoveServicesBySuffixToDirectoryRector::GROUP_NAMES_BY_SUFFIX => [
'Repository',
'Command',
'Mapper',
'Controller',
],
],
];
}
}

View File

@ -2,7 +2,7 @@
declare(strict_types=1);
namespace Rector\Autodiscovery\Tests\Rector\FileSystem\MoveServicesBySuffixToDirectoryRector\Source\Command;
namespace Rector\Autodiscovery\Tests\Rector\FileNode\MoveServicesBySuffixToDirectoryRector\Source\Command;
final class MissPlacedController
{

View File

@ -2,7 +2,7 @@
declare(strict_types=1);
namespace Rector\Autodiscovery\Tests\Rector\FileSystem\MoveServicesBySuffixToDirectoryRector\Source\Controller;
namespace Rector\Autodiscovery\Tests\Rector\FileNode\MoveServicesBySuffixToDirectoryRector\Source\Controller;
final class BananaCommand
{

View File

@ -0,0 +1,9 @@
<?php
declare(strict_types=1);
namespace Rector\Autodiscovery\Tests\Rector\FileNode\MoveServicesBySuffixToDirectoryRector\Source\Controller\Nested;
abstract class AbstractBaseMapper
{
}

View File

@ -0,0 +1,9 @@
<?php
declare(strict_types=1);
namespace Rector\Autodiscovery\Tests\Rector\FileNode\MoveServicesBySuffixToDirectoryRector\Source\Controller\Nested;
abstract class AbstractBaseWithSpaceMapper
{
}

View File

@ -0,0 +1,10 @@
<?php
declare(strict_types=1);
namespace Rector\Autodiscovery\Tests\Rector\FileNode\MoveServicesBySuffixToDirectoryRector\Source\Controller;
final class Orange
{
}

View File

@ -0,0 +1,10 @@
<?php
declare(strict_types=1);
namespace Rector\Autodiscovery\Tests\Rector\FileNode\MoveServicesBySuffixToDirectoryRector\Source\Entity;
class AppleRepository
{
}

View File

@ -0,0 +1,11 @@
<?php
declare(strict_types=1);
namespace Rector\Autodiscovery\Tests\Rector\FileNode\MoveServicesBySuffixToDirectoryRector\Source\Entity;
use Rector\Autodiscovery\Tests\Rector\FileNode\MoveServicesBySuffixToDirectoryRector\Source\Controller\Nested\AbstractBaseMapper;
final class UserMapper extends AbstractBaseMapper
{
}

View File

@ -0,0 +1,11 @@
<?php
declare(strict_types=1);
namespace Rector\Autodiscovery\Tests\Rector\FileNode\MoveServicesBySuffixToDirectoryRector\Source\Entity;
use Rector\Autodiscovery\Tests\Rector\FileNode\MoveServicesBySuffixToDirectoryRector\Source\Controller\Nested\AbstractBaseWithSpaceMapper;
final class UserWithSpaceMapper extends AbstractBaseWithSpaceMapper
{
}

View File

@ -0,0 +1,10 @@
<?php
declare(strict_types=1);
namespace Rector\Autodiscovery\Tests\Rector\FileNode\MoveServicesBySuffixToDirectoryRector\SkipAlreadyMoved\Source\Mapper;
final class SkipCorrectMapper
{
}

View File

@ -0,0 +1,10 @@
<?php
declare(strict_types=1);
namespace Rector\Autodiscovery\Tests\Rector\FileNode\MoveServicesBySuffixToDirectoryRector\Source\Repository;
class AppleRepository
{
}

View File

@ -0,0 +1,2 @@
services:
Rector\Autodiscovery\Tests\Rector\FileNode\MoveServicesBySuffixToDirectoryRector\Source\Controller\Nested\AbstractBaseMapper: null

View File

@ -1,12 +0,0 @@
<?php
declare(strict_types=1);
namespace Rector\Autodiscovery\Tests\Rector\FileSystem\MoveServicesBySuffixToDirectoryRector\Source\Command;
final class BananaCommand
{
public function run()
{
return new \Rector\Autodiscovery\Tests\Rector\FileSystem\MoveServicesBySuffixToDirectoryRector\Source\Controller\Orange();
}
}

View File

@ -1,12 +0,0 @@
<?php
declare(strict_types=1);
namespace Rector\Autodiscovery\Tests\Rector\FileSystem\MoveServicesBySuffixToDirectoryRector\Source\Controller;
final class MissPlacedController
{
public function getSelf()
{
return new \Rector\Autodiscovery\Tests\Rector\FileSystem\MoveServicesBySuffixToDirectoryRector\Source\Controller\MissPlacedController();
}
}

View File

@ -1,8 +0,0 @@
<?php
declare(strict_types=1);
namespace Rector\Autodiscovery\Tests\Rector\FileSystem\MoveServicesBySuffixToDirectoryRector\Source\Repository;
class AppleRepository
{
}

View File

@ -1,8 +0,0 @@
<?php
declare(strict_types=1);
namespace Rector\Autodiscovery\Tests\Rector\FileSystem\MoveServicesBySuffixToDirectoryRector\SourceMutualRename\Mapper\Nested;
abstract class AbstractBaseMapper
{
}

View File

@ -1,8 +0,0 @@
<?php
declare(strict_types=1);
namespace Rector\Autodiscovery\Tests\Rector\FileSystem\MoveServicesBySuffixToDirectoryRector\SourceMutualRename\Mapper\Nested;
abstract class AbstractBaseWithSpaceMapper
{
}

View File

@ -1,9 +0,0 @@
<?php
declare(strict_types=1);
namespace Rector\Autodiscovery\Tests\Rector\FileSystem\MoveServicesBySuffixToDirectoryRector\SourceMutualRename\Mapper;
use Rector\Autodiscovery\Tests\Rector\FileSystem\MoveServicesBySuffixToDirectoryRector\SourceMutualRename\Mapper\Nested\AbstractBaseMapper;
final class UserMapper extends \Rector\Autodiscovery\Tests\Rector\FileSystem\MoveServicesBySuffixToDirectoryRector\SourceMutualRename\Mapper\Nested\AbstractBaseMapper
{
}

View File

@ -1,9 +0,0 @@
<?php
declare(strict_types=1);
namespace Rector\Autodiscovery\Tests\Rector\FileSystem\MoveServicesBySuffixToDirectoryRector\SourceMutualRename\Mapper;
use Rector\Autodiscovery\Tests\Rector\FileSystem\MoveServicesBySuffixToDirectoryRector\SourceMutualRename\Mapper\Nested\AbstractBaseWithSpaceMapper;
final class UserWithSpaceMapper extends \Rector\Autodiscovery\Tests\Rector\FileSystem\MoveServicesBySuffixToDirectoryRector\SourceMutualRename\Mapper\Nested\AbstractBaseWithSpaceMapper
{
}

View File

@ -1,2 +0,0 @@
services:
Rector\Autodiscovery\Tests\Rector\FileSystem\MoveServicesBySuffixToDirectoryRector\SourceMutualRename\Mapper\Nested\AbstractBaseMapper: null

View File

@ -1,80 +0,0 @@
<?php
declare(strict_types=1);
namespace Rector\Autodiscovery\Tests\Rector\FileSystem\MoveServicesBySuffixToDirectoryRector;
use Iterator;
use Rector\Autodiscovery\Rector\FileSystem\MoveServicesBySuffixToDirectoryRector;
use Rector\Testing\PHPUnit\AbstractFileSystemRectorTestCase;
use Symplify\SmartFileSystem\SmartFileInfo;
final class MoveServicesBySuffixToDirectoryRectorTest extends AbstractFileSystemRectorTestCase
{
/**
* @dataProvider provideData()
*/
public function test(
SmartFileInfo $originalFileInfo,
string $expectedFileLocation,
string $expectedFileContent
): void {
$this->doTestFileInfo($originalFileInfo);
$this->assertFileExists($expectedFileLocation);
$this->assertFileEquals($expectedFileContent, $expectedFileLocation);
}
public function provideData(): Iterator
{
yield [
new SmartFileInfo(__DIR__ . '/Source/Entity/AppleRepository.php'),
$this->getFixtureTempDirectory() . '/Source/Repository/AppleRepository.php',
__DIR__ . '/Expected/Repository/ExpectedAppleRepository.php',
];
yield [
new SmartFileInfo(__DIR__ . '/Source/Controller/BananaCommand.php'),
$this->getFixtureTempDirectory() . '/Source/Command/BananaCommand.php',
__DIR__ . '/Expected/Command/ExpectedBananaCommand.php',
];
yield [
new SmartFileInfo(__DIR__ . '/Source/Mapper/CorrectMapper.php'),
$this->getFixtureTempDirectory() . '/Source/Mapper/CorrectMapper.php',
// same content, no change
__DIR__ . '/Source/Mapper/CorrectMapper.php',
];
yield [
new SmartFileInfo(__DIR__ . '/Source/Command/MissPlacedController.php'),
$this->getFixtureTempDirectory() . '/Source/Controller/MissPlacedController.php',
__DIR__ . '/Expected/Controller/MissPlacedController.php',
];
// skip interface
yield [
new SmartFileInfo(__DIR__ . '/Source/Command/MightBeController.php'),
$this->getFixtureTempDirectory() . '/Source/Command/MightBeController.php',
// same content, no change
__DIR__ . '/Source/Command/MightBeController.php',
];
}
/**
* @return array<string, mixed[]>
*/
protected function getRectorsWithConfiguration(): array
{
return [
MoveServicesBySuffixToDirectoryRector::class => [
MoveServicesBySuffixToDirectoryRector::GROUP_NAMES_BY_SUFFIX => [
'Repository',
'Command',
'Mapper',
'Controller',
],
],
];
}
}

View File

@ -1,87 +0,0 @@
<?php
declare(strict_types=1);
namespace Rector\Autodiscovery\Tests\Rector\FileSystem\MoveServicesBySuffixToDirectoryRector;
use Iterator;
use Rector\Autodiscovery\Rector\FileSystem\MoveServicesBySuffixToDirectoryRector;
use Rector\Autodiscovery\Tests\Rector\FileSystem\MoveInterfacesToContractNamespaceDirectoryRector\ValueObject\InputFilePathWithExpectedFile;
use Rector\Testing\PHPUnit\AbstractFileSystemRectorTestCase;
use Symplify\SmartFileSystem\SmartFileInfo;
final class MutualRenameTest extends AbstractFileSystemRectorTestCase
{
/**
* @dataProvider provideData()
*
* @param InputFilePathWithExpectedFile[] $extraFiles
*/
public function test(
SmartFileInfo $originalFileInfo,
string $expectedFileLocation,
string $expectedFileContent,
array $extraFiles = []
): void {
//$extraFilePaths = array_keys($extraFiles);
$this->doTestFileInfo($originalFileInfo, $extraFiles);
$this->assertFileExists($expectedFileLocation);
$this->assertFileEquals($expectedFileContent, $expectedFileLocation);
$this->doTestExtraFileInfos($extraFiles);
}
public function provideData(): Iterator
{
yield [
new SmartFileInfo(__DIR__ . '/SourceMutualRename/Controller/Nested/AbstractBaseWithSpaceMapper.php'),
$this->getFixtureTempDirectory() . '/SourceMutualRename/Mapper/Nested/AbstractBaseWithSpaceMapper.php',
__DIR__ . '/ExpectedMutualRename/Mapper/Nested/AbstractBaseWithSpaceMapper.php.inc',
// extra files
[
new InputFilePathWithExpectedFile(
__DIR__ . '/SourceMutualRename/Entity/UserWithSpaceMapper.php',
$this->getFixtureTempDirectory() . '/SourceMutualRename/Mapper/UserWithSpaceMapper.php',
__DIR__ . '/ExpectedMutualRename/Mapper/UserWithSpaceMapper.php.inc'
),
],
];
// inversed order, but should have the same effect
yield [
new SmartFileInfo(__DIR__ . '/SourceMutualRename/Entity/UserMapper.php'),
$this->getFixtureTempDirectory() . '/SourceMutualRename/Mapper/UserMapper.php',
__DIR__ . '/ExpectedMutualRename/Mapper/UserMapper.php.inc',
// extra files
[
new InputFilePathWithExpectedFile(
__DIR__ . '/SourceMutualRename/Controller/Nested/AbstractBaseMapper.php',
$this->getFixtureTempDirectory() . '/SourceMutualRename/Mapper/Nested/AbstractBaseMapper.php',
__DIR__ . '/ExpectedMutualRename/Mapper/Nested/AbstractBaseMapper.php.inc'
),
// includes NEON/YAML file renames
new InputFilePathWithExpectedFile(
__DIR__ . '/SourceMutualRename/config/some_config.neon',
$this->getFixtureTempDirectory() . '/SourceMutualRename/config/some_config.neon',
__DIR__ . '/ExpectedMutualRename/config/expected_some_config.neon'
),
],
];
}
/**
* @return array<string, mixed[]>
*/
protected function getRectorsWithConfiguration(): array
{
return [
MoveServicesBySuffixToDirectoryRector::class => [
MoveServicesBySuffixToDirectoryRector::GROUP_NAMES_BY_SUFFIX => ['Mapper'],
],
];
}
}

View File

@ -1,10 +0,0 @@
<?php
declare(strict_types=1);
namespace Rector\Autodiscovery\Tests\Rector\FileSystem\MoveServicesBySuffixToDirectoryRector\Source\Command;
interface MightBeController
{
}

View File

@ -1,10 +0,0 @@
<?php
declare(strict_types=1);
namespace Rector\Autodiscovery\Tests\Rector\FileSystem\MoveServicesBySuffixToDirectoryRector\Source\Controller;
final class Orange
{
}

View File

@ -1,10 +0,0 @@
<?php
declare(strict_types=1);
namespace Rector\Autodiscovery\Tests\Rector\FileSystem\MoveServicesBySuffixToDirectoryRector\Source\Entity;
class AppleRepository
{
}

View File

@ -1,10 +0,0 @@
<?php
declare(strict_types=1);
namespace Rector\Autodiscovery\Tests\Rector\FileSystem\MoveServicesBySuffixToDirectoryRector\SkipAlreadyMoved\Source\Mapper;
final class CorrectMapper
{
}

View File

@ -1,10 +0,0 @@
<?php
declare(strict_types=1);
namespace Rector\Autodiscovery\Tests\Rector\FileSystem\MoveServicesBySuffixToDirectoryRector\Source\Repository;
class AppleRepository
{
}

View File

@ -1,9 +0,0 @@
<?php
declare(strict_types=1);
namespace Rector\Autodiscovery\Tests\Rector\FileSystem\MoveServicesBySuffixToDirectoryRector\SourceMutualRename\Controller\Nested;
abstract class AbstractBaseMapper
{
}

View File

@ -1,9 +0,0 @@
<?php
declare(strict_types=1);
namespace Rector\Autodiscovery\Tests\Rector\FileSystem\MoveServicesBySuffixToDirectoryRector\SourceMutualRename\Controller\Nested;
abstract class AbstractBaseWithSpaceMapper
{
}

View File

@ -1,11 +0,0 @@
<?php
declare(strict_types=1);
namespace Rector\Autodiscovery\Tests\Rector\FileSystem\MoveServicesBySuffixToDirectoryRector\SourceMutualRename\Entity;
use Rector\Autodiscovery\Tests\Rector\FileSystem\MoveServicesBySuffixToDirectoryRector\SourceMutualRename\Controller\Nested\AbstractBaseMapper;
final class UserMapper extends AbstractBaseMapper
{
}

View File

@ -1,11 +0,0 @@
<?php
declare(strict_types=1);
namespace Rector\Autodiscovery\Tests\Rector\FileSystem\MoveServicesBySuffixToDirectoryRector\SourceMutualRename\Entity;
use Rector\Autodiscovery\Tests\Rector\FileSystem\MoveServicesBySuffixToDirectoryRector\SourceMutualRename\Controller\Nested\AbstractBaseWithSpaceMapper;
final class UserWithSpaceMapper extends AbstractBaseWithSpaceMapper
{
}

View File

@ -1,2 +0,0 @@
services:
Rector\Autodiscovery\Tests\Rector\FileSystem\MoveServicesBySuffixToDirectoryRector\SourceMutualRename\Controller\Nested\AbstractBaseMapper: null

View File

@ -8,6 +8,7 @@ use Nette\Utils\Strings;
use Rector\Core\RectorDefinition\CodeSample;
use Rector\Core\RectorDefinition\RectorDefinition;
use Rector\FileSystemRector\Rector\AbstractFileSystemRector;
use Rector\FileSystemRector\ValueObject\MovedFileWithContent;
use Symplify\SmartFileSystem\SmartFileInfo;
/**
@ -54,7 +55,7 @@ CODE_SAMPLE
return;
}
$this->moveFile($smartFileInfo, $newRealPath);
$this->addMovedFile(new MovedFileWithContent($smartFileInfo, $newRealPath));
}
private function createNewRealPath(string $oldRealPath): string

View File

@ -10,6 +10,7 @@ use Rector\Core\PhpParser\Node\CustomNode\FileNode;
use Rector\Core\Rector\AbstractRector;
use Rector\Core\RectorDefinition\CodeSample;
use Rector\Core\RectorDefinition\RectorDefinition;
use Rector\FileSystemRector\ValueObject\MovedFileWithContent;
/**
* @see https://gnugat.github.io/2015/09/23/phpunit-with-phpspec.html
@ -67,7 +68,7 @@ CODE_SAMPLE
}
$newPathName = $this->createPathName($oldPathname);
$this->moveFile($fileInfo, $newPathName);
$this->addMovedFile(new MovedFileWithContent($fileInfo, $newPathName));
return null;
}

View File

@ -6,7 +6,7 @@ namespace Rector\PhpSpecToPHPUnit\Tests\Rector\FileNode\RenameSpecFileToTestFile
use Iterator;
use Nette\Utils\Strings;
use Rector\Core\ValueObject\MovedFile;
use Rector\FileSystemRector\ValueObject\MovedFileWithContent;
use Rector\PhpSpecToPHPUnit\Rector\FileNode\RenameSpecFileToTestFileRector;
use Rector\Testing\PHPUnit\AbstractRectorTestCase;
use Symplify\SmartFileSystem\SmartFileInfo;
@ -22,9 +22,9 @@ final class RenameSpecFileToTestFileRectorTest extends AbstractRectorTestCase
// test file is moved
$movedFile = $this->matchMovedFile();
$this->assertInstanceOf(MovedFile::class, $movedFile);
$this->assertInstanceOf(MovedFileWithContent::class, $movedFile);
$this->assertTrue(Strings::endsWith($movedFile->getNewPath(), 'Test.php'));
$this->assertTrue(Strings::endsWith($movedFile->getNewPathname(), 'Test.php'));
}
public function provideData(): Iterator

View File

@ -6,7 +6,7 @@ namespace Rector\PSR4\Tests\Rector\Namespace_\MultipleClassFileToPsr4ClassesRect
use Iterator;
use Rector\Core\Application\FileSystem\RemovedAndAddedFilesCollector;
use Rector\Core\ValueObject\FilePathWithContent;
use Rector\FileSystemRector\ValueObject\AddedFileWithContent;
use Rector\PSR4\Rector\Namespace_\MultipleClassFileToPsr4ClassesRector;
use Rector\Testing\PHPUnit\AbstractRectorTestCase;
use Symplify\SmartFileSystem\SmartFileInfo;
@ -15,7 +15,7 @@ use Symplify\SmartFileSystem\SmartFileSystem;
final class MultipleClassFileToPsr4ClassesRectorTest extends AbstractRectorTestCase
{
/**
* @param FilePathWithContent[] $expectedFilePathsWithContents
* @param AddedFileWithContent[] $expectedFilePathsWithContents
* @dataProvider provideData()
*/
public function test(
@ -43,11 +43,11 @@ final class MultipleClassFileToPsr4ClassesRectorTest extends AbstractRectorTestC
// source: https://github.com/nette/utils/blob/798f8c1626a8e0e23116d90e588532725cce7d0e/src/Utils/exceptions.php
$filePathsWithContents = [
new FilePathWithContent(
new AddedFileWithContent(
$this->getFixtureTempDirectory() . '/RegexpException.php',
$smartFileSystem->readFile(__DIR__ . '/Expected/RegexpException.php')
),
new FilePathWithContent(
new AddedFileWithContent(
$this->getFixtureTempDirectory() . '/UnknownImageFileException.php',
$smartFileSystem->readFile(__DIR__ . '/Expected/UnknownImageFileException.php')
),
@ -55,11 +55,11 @@ final class MultipleClassFileToPsr4ClassesRectorTest extends AbstractRectorTestC
yield [new SmartFileInfo(__DIR__ . '/Source/nette-exceptions.php'), $filePathsWithContents, true];
$filePathsWithContents = [
new FilePathWithContent(
new AddedFileWithContent(
$this->getFixtureTempDirectory() . '/JustOneExceptionWithoutNamespace.php',
$smartFileSystem->readFile(__DIR__ . '/Expected/JustOneExceptionWithoutNamespace.php')
),
new FilePathWithContent(
new AddedFileWithContent(
$this->getFixtureTempDirectory() . '/JustTwoExceptionWithoutNamespace.php',
$smartFileSystem->readFile(__DIR__ . '/Expected/JustTwoExceptionWithoutNamespace.php')
),
@ -67,15 +67,15 @@ final class MultipleClassFileToPsr4ClassesRectorTest extends AbstractRectorTestC
yield [new SmartFileInfo(__DIR__ . '/Source/without-namespace.php'), $filePathsWithContents, true];
$filePathsWithContents = [
new FilePathWithContent(
new AddedFileWithContent(
$this->getFixtureTempDirectory() . '/MyTrait.php',
$smartFileSystem->readFile(__DIR__ . '/Expected/MyTrait.php')
),
new FilePathWithContent(
new AddedFileWithContent(
$this->getFixtureTempDirectory() . '/MyClass.php',
$smartFileSystem->readFile(__DIR__ . '/Expected/MyClass.php')
),
new FilePathWithContent(
new AddedFileWithContent(
$this->getFixtureTempDirectory() . '/MyInterface.php',
$smartFileSystem->readFile(__DIR__ . '/Expected/MyInterface.php')
),
@ -87,7 +87,7 @@ final class MultipleClassFileToPsr4ClassesRectorTest extends AbstractRectorTestC
new SmartFileInfo(__DIR__ . '/Source/SomeClass.php'),
// extra files
[
new FilePathWithContent(
new AddedFileWithContent(
$this->getFixtureTempDirectory() . '/SomeClass_Exception.php',
$smartFileSystem->readFile(__DIR__ . '/Expected/SomeClass_Exception.php')
),

View File

@ -10,6 +10,7 @@ use Rector\CodingStyle\Naming\ClassNaming;
use Rector\Core\Rector\AbstractRector;
use Rector\Core\RectorDefinition\CodeSample;
use Rector\Core\RectorDefinition\RectorDefinition;
use Rector\FileSystemRector\ValueObject\MovedFileWithContent;
use Symplify\SmartFileSystem\SmartFileInfo;
/**
@ -85,7 +86,7 @@ CODE_SAMPLE
// no match → rename file
$newFileLocation = $smartFileInfo->getPath() . DIRECTORY_SEPARATOR . $classShortName . '.php';
$this->moveFile($smartFileInfo, $newFileLocation);
$this->addMovedFile(new MovedFileWithContent($smartFileInfo, $newFileLocation));
return null;
}

View File

@ -4,9 +4,10 @@ declare(strict_types=1);
namespace Rector\Core\Application\FileSystem;
use Rector\Autodiscovery\ValueObject\NodesWithFileDestination;
use Rector\Core\ValueObject\FilePathWithContent;
use Rector\Core\ValueObject\MovedFile;
use Rector\FileSystemRector\Contract\AddedFileInterface;
use Rector\FileSystemRector\Contract\MovedFileInterface;
use Rector\FileSystemRector\ValueObject\AddedFileWithContent;
use Rector\FileSystemRector\ValueObject\MovedFileWithNodes;
use Symplify\SmartFileSystem\SmartFileInfo;
final class RemovedAndAddedFilesCollector
@ -17,28 +18,23 @@ final class RemovedAndAddedFilesCollector
private $removedFiles = [];
/**
* @var FilePathWithContent[]
* @var AddedFileInterface[]
*/
private $addedFilePathsWithContents = [];
private $addedFiles = [];
/**
* @var MovedFile[]
* @var MovedFileInterface[]
*/
private $movedFiles = [];
/**
* @var NodesWithFileDestination[]
*/
private $nodesWithFileDestination = [];
public function removeFile(SmartFileInfo $smartFileInfo): void
{
$this->removedFiles[$smartFileInfo->getRealPath()] = $smartFileInfo;
$this->removedFiles[] = $smartFileInfo;
}
public function addMovedFile(SmartFileInfo $oldFileInfo, string $newFileLocation): void
public function addMovedFile(MovedFileInterface $movedFile): void
{
$this->movedFiles[] = new MovedFile($oldFileInfo, $newFileLocation);
$this->movedFiles[] = $movedFile;
}
/**
@ -50,17 +46,17 @@ final class RemovedAndAddedFilesCollector
}
/**
* @return MovedFile[]
* @return MovedFileInterface[]
*/
public function getMovedFiles(): array
{
return $this->movedFiles;
}
public function getMovedFile(SmartFileInfo $smartFileInfo): ?MovedFile
public function getMovedFileByFileInfo(SmartFileInfo $smartFileInfo): ?MovedFileInterface
{
foreach ($this->movedFiles as $movedFile) {
if ($movedFile->getOldFileInfo()->getPathname() !== $smartFileInfo->getPathname()) {
if ($movedFile->getOldPathname() !== $smartFileInfo->getPathname()) {
continue;
}
@ -72,39 +68,58 @@ final class RemovedAndAddedFilesCollector
public function isFileRemoved(SmartFileInfo $smartFileInfo): bool
{
return isset($this->removedFiles[$smartFileInfo->getRealPath()]);
foreach ($this->removedFiles as $removedFile) {
if ($removedFile->getPathname() !== $smartFileInfo->getPathname()) {
continue;
}
return true;
}
return false;
}
public function addFileWithContent(string $filePath, string $content): void
public function addAddedFile(AddedFileInterface $addedFile): void
{
$this->addedFilePathsWithContents[] = new FilePathWithContent($filePath, $content);
$this->addedFiles[] = $addedFile;
}
/**
* @return FilePathWithContent[]
* @return AddedFileInterface[]
*/
public function getAddedFilePathsWithContents(): array
public function getAddedFiles(): array
{
return $this->addedFilePathsWithContents;
return $this->addedFiles;
}
/**
* For testing
* @return AddedFileWithContent[]
*/
public function reset(): void
public function getAddedFilesWithContent(): array
{
$this->addedFilePathsWithContents = [];
$this->removedFiles = [];
return array_filter($this->addedFiles, function (AddedFileInterface $addedFile): bool {
return $addedFile instanceof AddedFileWithContent;
});
}
/**
* @return MovedFileWithNodes[]
*/
public function getMovedFileWithNodes(): array
{
return array_filter($this->movedFiles, function (MovedFileInterface $movedFile): bool {
return $movedFile instanceof MovedFileWithNodes;
});
}
public function getAffectedFilesCount(): int
{
return count($this->addedFilePathsWithContents) + count($this->removedFiles);
return count($this->addedFiles) + count($this->movedFiles) + count($this->removedFiles);
}
public function getAddedFileCount(): int
{
return count($this->addedFilePathsWithContents);
return count($this->addedFiles);
}
public function getRemovedFilesCount(): int
@ -112,16 +127,13 @@ final class RemovedAndAddedFilesCollector
return count($this->removedFiles);
}
public function addNodesWithFileDestination(NodesWithFileDestination $nodesWithFileDestination): void
{
$this->nodesWithFileDestination[] = $nodesWithFileDestination;
}
/**
* @return NodesWithFileDestination[]
* For testing
*/
public function getNodesWithFileDestination(): array
public function reset(): void
{
return $this->nodesWithFileDestination;
$this->addedFiles = [];
$this->removedFiles = [];
$this->movedFiles = [];
}
}

View File

@ -5,8 +5,12 @@ declare(strict_types=1);
namespace Rector\Core\Application\FileSystem;
use Rector\Core\Configuration\Configuration;
use Rector\Core\Exception\NotImplementedYetException;
use Rector\Core\PhpParser\Printer\BetterStandardPrinter;
use Rector\Core\PhpParser\Printer\NodesWithFileDestinationPrinter;
use Rector\Core\ValueObject\MovedFile;
use Rector\FileSystemRector\Contract\MovedFileInterface;
use Rector\FileSystemRector\ValueObject\MovedFileWithContent;
use Rector\FileSystemRector\ValueObject\MovedFileWithNodes;
use Rector\Testing\PHPUnit\StaticPHPUnitEnvironment;
use Symfony\Component\Console\Style\SymfonyStyle;
use Symplify\SmartFileSystem\SmartFileSystem;
@ -41,18 +45,25 @@ final class RemovedAndAddedFilesProcessor
*/
private $smartFileSystem;
/**
* @var BetterStandardPrinter
*/
private $betterStandardPrinter;
public function __construct(
Configuration $configuration,
SmartFileSystem $smartFileSystem,
NodesWithFileDestinationPrinter $nodesWithFileDestinationPrinter,
RemovedAndAddedFilesCollector $removedAndAddedFilesCollector,
SymfonyStyle $symfonyStyle
SymfonyStyle $symfonyStyle,
BetterStandardPrinter $betterStandardPrinter
) {
$this->removedAndAddedFilesCollector = $removedAndAddedFilesCollector;
$this->configuration = $configuration;
$this->symfonyStyle = $symfonyStyle;
$this->nodesWithFileDestinationPrinter = $nodesWithFileDestinationPrinter;
$this->smartFileSystem = $smartFileSystem;
$this->betterStandardPrinter = $betterStandardPrinter;
}
public function run(): void
@ -64,40 +75,8 @@ final class RemovedAndAddedFilesProcessor
private function processAddedFiles(): void
{
foreach ($this->removedAndAddedFilesCollector->getAddedFilePathsWithContents() as $filePathWithContent) {
if ($this->configuration->isDryRun()) {
$message = sprintf('File "%s" will be added:', $filePathWithContent->getFilePath());
$this->symfonyStyle->note($message);
} else {
$this->smartFileSystem->dumpFile(
$filePathWithContent->getFilePath(),
$filePathWithContent->getFileContent()
);
$message = sprintf('File "%s" was added:', $filePathWithContent->getFilePath());
$this->symfonyStyle->note($message);
}
$this->symfonyStyle->writeln($filePathWithContent->getFileContent());
}
foreach ($this->removedAndAddedFilesCollector->getNodesWithFileDestination() as $nodesWithFileDestination) {
$fileContent = $this->nodesWithFileDestinationPrinter->printNodesWithFileDestination(
$nodesWithFileDestination
);
if ($this->configuration->isDryRun()) {
$message = sprintf('File "%s" will be added:', $nodesWithFileDestination->getFileDestination());
$this->symfonyStyle->note($message);
} else {
$this->smartFileSystem->dumpFile($nodesWithFileDestination->getFileDestination(), $fileContent);
$message = sprintf('File "%s" was added:', $nodesWithFileDestination->getFileDestination());
$this->symfonyStyle->note($message);
}
$this->symfonyStyle->writeln('----------------------------------------');
$this->symfonyStyle->writeln($fileContent);
$this->symfonyStyle->writeln('----------------------------------------');
}
$this->processAddedFilesWithContent();
$this->processAddedFilesWithNodes();
}
private function processDeletedFiles(): void
@ -111,7 +90,7 @@ final class RemovedAndAddedFilesProcessor
} else {
$message = sprintf('File "%s" was removed', $relativePath);
$this->symfonyStyle->warning($message);
$this->smartFileSystem->remove($removedFile->getRealPath());
$this->smartFileSystem->remove($removedFile->getPathname());
}
}
}
@ -124,22 +103,77 @@ final class RemovedAndAddedFilesProcessor
} else {
$this->printFileMoveWarning($movedFile, 'was');
$this->smartFileSystem->remove($movedFile->getOldPathName());
$this->smartFileSystem->remove($movedFile->getOldPathname());
$this->smartFileSystem->dumpFile($movedFile->getNewPath(), $movedFile->getFileContent());
$fileContent = $this->resolveFileContentFromMovedFile($movedFile);
$this->smartFileSystem->dumpFile($movedFile->getNewPathname(), $fileContent);
}
}
}
private function printFileMoveWarning(MovedFile $movedFile, string $verb): void
private function processAddedFilesWithContent(): void
{
foreach ($this->removedAndAddedFilesCollector->getAddedFilesWithContent() as $addedFileWithContent) {
if ($this->configuration->isDryRun()) {
$message = sprintf('File "%s" will be added:', $addedFileWithContent->getFilePath());
$this->symfonyStyle->note($message);
} else {
$this->smartFileSystem->dumpFile(
$addedFileWithContent->getFilePath(),
$addedFileWithContent->getFileContent()
);
$message = sprintf('File "%s" was added:', $addedFileWithContent->getFilePath());
$this->symfonyStyle->note($message);
}
$this->symfonyStyle->writeln($addedFileWithContent->getFileContent());
}
}
private function processAddedFilesWithNodes(): void
{
foreach ($this->removedAndAddedFilesCollector->getMovedFileWithNodes() as $addedFileWithNodes) {
$fileContent = $this->nodesWithFileDestinationPrinter->printNodesWithFileDestination(
$addedFileWithNodes
);
if ($this->configuration->isDryRun()) {
$message = sprintf('File "%s" will be added:', $addedFileWithNodes->getOldPathname());
$this->symfonyStyle->note($message);
} else {
$this->smartFileSystem->dumpFile($addedFileWithNodes->getNewPathname(), $fileContent);
$message = sprintf('File "%s" was added:', $addedFileWithNodes->getNewPathname());
$this->symfonyStyle->note($message);
}
$this->symfonyStyle->writeln('----------------------------------------');
$this->symfonyStyle->writeln($fileContent);
$this->symfonyStyle->writeln('----------------------------------------');
}
}
private function printFileMoveWarning(MovedFileInterface $movedFile, string $verb): void
{
$message = sprintf(
'File "%s" %s moved to "%s"',
$movedFile->getOldFileInfo(),
$movedFile->getOldPathname(),
$verb,
$movedFile->getNewPath()
$movedFile->getNewPathname()
);
$this->symfonyStyle->warning($message);
}
private function resolveFileContentFromMovedFile(MovedFileInterface $movedFile): string
{
if ($movedFile instanceof MovedFileWithContent) {
return $movedFile->getFileContent();
}
if ($movedFile instanceof MovedFileWithNodes) {
return $this->betterStandardPrinter->prettyPrintFile($movedFile->getNodes());
}
throw new NotImplementedYetException(get_class($movedFile));
}
}

View File

@ -189,7 +189,7 @@ final class BetterStandardPrinter extends Standard
return ltrim($content);
}
public function pFile(FileNode $fileNode): string
public function pFileNode(FileNode $fileNode): string
{
return self::pStmts((array) $fileNode->stmts);
}

View File

@ -6,7 +6,7 @@ namespace Rector\Core\PhpParser\Printer;
use Nette\Utils\Strings;
use PhpParser\Lexer;
use Rector\Autodiscovery\ValueObject\NodesWithFileDestination;
use Rector\FileSystemRector\ValueObject\MovedFileWithNodes;
use Rector\PostRector\Application\PostFileProcessor;
final class NodesWithFileDestinationPrinter
@ -36,9 +36,9 @@ final class NodesWithFileDestinationPrinter
$this->betterStandardPrinter = $betterStandardPrinter;
}
public function printNodesWithFileDestination(NodesWithFileDestination $nodesWithFileDestination): string
public function printNodesWithFileDestination(MovedFileWithNodes $movedFileWithNodes): string
{
$nodes = $this->postFileProcessor->traverse($nodesWithFileDestination->getNodes());
$nodes = $this->postFileProcessor->traverse($movedFileWithNodes->getNodes());
$prettyPrintContent = $this->betterStandardPrinter->prettyPrintFile($nodes);
return $this->resolveLastEmptyLine($prettyPrintContent);

View File

@ -9,11 +9,13 @@ use PhpParser\Node;
use PhpParser\Node\Stmt\Class_;
use Rector\ChangesReporting\Rector\AbstractRector\NotifyingRemovingNodeTrait;
use Rector\Doctrine\AbstractRector\DoctrineTrait;
use Rector\FileSystemRector\Rector\Behavior\FileSystemRectorTrait;
use Rector\PostRector\Rector\AbstractRector\NodeCommandersTrait;
use Rector\Reporting\Rector\AbstractRector\NodeReportCollectorTrait;
trait AbstractRectorTrait
{
use FileSystemRectorTrait;
use PhpDocTrait;
use RemovedAndAddedFilesTrait;
use DoctrineTrait;

View File

@ -5,9 +5,13 @@ declare(strict_types=1);
namespace Rector\Core\Rector\AbstractRector;
use PhpParser\Node;
use Rector\Autodiscovery\ValueObject\NodesWithFileDestination;
use Rector\Core\Application\FileSystem\RemovedAndAddedFilesCollector;
use Rector\Core\PhpParser\Printer\BetterStandardPrinter;
use Rector\FileSystemRector\Contract\AddedFileInterface;
use Rector\FileSystemRector\Contract\MovedFileInterface;
use Rector\FileSystemRector\ValueObject\AddedFileWithContent;
use Rector\FileSystemRector\ValueObject\MovedFileWithNodes;
use Rector\PSR4\Collector\RenamedClassesCollector;
use Symplify\SmartFileSystem\SmartFileInfo;
/**
@ -23,13 +27,20 @@ trait RemovedAndAddedFilesTrait
*/
private $removedAndAddedFilesCollector;
/**
* @var RenamedClassesCollector
*/
private $renamedClassesCollector;
/**
* @required
*/
public function autowireRemovedAndAddedFilesTrait(
RemovedAndAddedFilesCollector $removedAndAddedFilesCollector
RemovedAndAddedFilesCollector $removedAndAddedFilesCollector,
RenamedClassesCollector $renamedClassesCollector
): void {
$this->removedAndAddedFilesCollector = $removedAndAddedFilesCollector;
$this->renamedClassesCollector = $renamedClassesCollector;
}
/**
@ -39,12 +50,19 @@ trait RemovedAndAddedFilesTrait
{
$fileContent = $this->betterStandardPrinter->prettyPrintFile($nodes);
$this->removedAndAddedFilesCollector->addFileWithContent($fileLocation, $fileContent);
$this->removedAndAddedFilesCollector->addAddedFile(new AddedFileWithContent($fileLocation, $fileContent));
}
protected function moveFile(SmartFileInfo $oldFileInfo, string $newFileLocation): void
protected function addMovedFile(MovedFileInterface $movedFile): void
{
$this->removedAndAddedFilesCollector->addMovedFile($oldFileInfo, $newFileLocation);
if ($movedFile instanceof MovedFileWithNodes && $movedFile->hasClassRename()) {
$this->renamedClassesCollector->addClassRename(
$movedFile->getOldClassName(),
$movedFile->getNewClassName()
);
}
$this->removedAndAddedFilesCollector->addMovedFile($movedFile);
}
protected function removeFile(SmartFileInfo $smartFileInfo): void
@ -52,13 +70,8 @@ trait RemovedAndAddedFilesTrait
$this->removedAndAddedFilesCollector->removeFile($smartFileInfo);
}
private function addFile(string $filePath, string $content): void
private function addFile(AddedFileInterface $addedFile): void
{
$this->removedAndAddedFilesCollector->addFileWithContent($filePath, $content);
}
private function addNodesWithFileDestination(NodesWithFileDestination $nodesWithFileDestination): void
{
$this->removedAndAddedFilesCollector->addNodesWithFileDestination($nodesWithFileDestination);
$this->removedAndAddedFilesCollector->addAddedFile($addedFile);
}
}