Updated Rector to commit a6dfb049d7100c6bb5aa93735199f8434381d210

a6dfb049d7 [DX] Make generator only part of core (#2849)
This commit is contained in:
Tomas Votruba 2022-08-29 18:19:15 +00:00
parent 583eacb780
commit 3ad817dad5
47 changed files with 34 additions and 1870 deletions

View File

@ -47,7 +47,7 @@ By [buying a book](https://leanpub.com/rector-the-power-of-automated-refactoring
- [How Does Rector Work?](/docs/how_it_works.md)
- [PHP Parser Nodes](https://github.com/rectorphp/php-parser-nodes-docs/)
- [How to Work with Doc Block and Comments](/docs/how_to_work_with_doc_block_and_comments.md)
- [How to Generate New Rector Rule](/docs/create_own_rule.md)
- [How to Create Own Rector Rule](/docs/create_own_rule.md)
See [the full documentation](/docs).

View File

@ -4,13 +4,11 @@ You can have custom `SetList` class that has constants that pointed to your own
```php
<?php
namespace App\Set\ValueObject;
use Rector\Set\Contract\SetListInterface;
class SetList implements SetListInterface
final class SetList implements SetListInterface
{
public const MY_FRAMEWORK_20 = __DIR__ . '/../../../config/set/my-framework-20.php';
}

View File

@ -4,10 +4,10 @@ declare (strict_types=1);
namespace Rector\ChangesReporting\ValueObjectFactory;
use Rector\Core\Differ\DefaultDiffer;
use Rector\Core\FileSystem\FilePathHelper;
use Rector\Core\ValueObject\Application\File;
use Rector\Core\ValueObject\Reporting\FileDiff;
use RectorPrefix202208\Symplify\PackageBuilder\Console\Output\ConsoleDiffer;
use RectorPrefix202208\Symplify\SmartFileSystem\SmartFileSystem;
final class FileDiffFactory
{
/**
@ -22,19 +22,18 @@ final class FileDiffFactory
private $consoleDiffer;
/**
* @readonly
* @var \Symplify\SmartFileSystem\SmartFileSystem
* @var \Rector\Core\FileSystem\FilePathHelper
*/
private $smartFileSystem;
public function __construct(DefaultDiffer $defaultDiffer, ConsoleDiffer $consoleDiffer, SmartFileSystem $smartFileSystem)
private $filePathHelper;
public function __construct(DefaultDiffer $defaultDiffer, ConsoleDiffer $consoleDiffer, FilePathHelper $filePathHelper)
{
$this->defaultDiffer = $defaultDiffer;
$this->consoleDiffer = $consoleDiffer;
$this->smartFileSystem = $smartFileSystem;
$this->filePathHelper = $filePathHelper;
}
public function createFileDiff(File $file, string $oldContent, string $newContent) : FileDiff
{
$relativeFilePath = $this->smartFileSystem->makePathRelative($file->getFilePath(), (string) \realpath(\getcwd()));
$relativeFilePath = \rtrim($relativeFilePath, '/');
$relativeFilePath = $this->filePathHelper->relativePath($file->getFilePath());
// always keep the most recent diff
return new FileDiff($relativeFilePath, $this->defaultDiffer->diff($oldContent, $newContent), $this->consoleDiffer->diff($oldContent, $newContent), $file->getRectorWithLineChanges());
}

View File

@ -17,12 +17,12 @@ final class VersionResolver
* @api
* @var string
*/
public const PACKAGE_VERSION = 'bd6c02a3f8154152f879106c8e77731eb3f4e69c';
public const PACKAGE_VERSION = 'a6dfb049d7100c6bb5aa93735199f8434381d210';
/**
* @api
* @var string
*/
public const RELEASE_DATE = '2022-08-29 19:47:40';
public const RELEASE_DATE = '2022-08-29 20:14:24';
/**
* @var int
*/

2
vendor/autoload.php vendored
View File

@ -9,4 +9,4 @@ if (PHP_VERSION_ID < 50600) {
require_once __DIR__ . '/composer/autoload_real.php';
return ComposerAutoloaderInit83716a21ad55eb60ab18d8cb830f08a9::getLoader();
return ComposerAutoloaderInitcd1f1758a12d59a8465f8d671b277097::getLoader();

View File

@ -2479,29 +2479,6 @@ return array(
'Rector\\ReadWrite\\ReadNodeAnalyzer\\JustReadExprAnalyzer' => $baseDir . '/packages/ReadWrite/ReadNodeAnalyzer/JustReadExprAnalyzer.php',
'Rector\\ReadWrite\\ReadNodeAnalyzer\\LocalPropertyFetchReadNodeAnalyzer' => $baseDir . '/packages/ReadWrite/ReadNodeAnalyzer/LocalPropertyFetchReadNodeAnalyzer.php',
'Rector\\ReadWrite\\ReadNodeAnalyzer\\VariableReadNodeAnalyzer' => $baseDir . '/packages/ReadWrite/ReadNodeAnalyzer/VariableReadNodeAnalyzer.php',
'Rector\\RectorGenerator\\Command\\GenerateCommand' => $vendorDir . '/rector/rector-generator/src/Command/GenerateCommand.php',
'Rector\\RectorGenerator\\Command\\InitRecipeCommand' => $vendorDir . '/rector/rector-generator/src/Command/InitRecipeCommand.php',
'Rector\\RectorGenerator\\Enum\\Packages' => $vendorDir . '/rector/rector-generator/src/Enum/Packages.php',
'Rector\\RectorGenerator\\Exception\\ConfigurationException' => $vendorDir . '/rector/rector-generator/src/Exception/ConfigurationException.php',
'Rector\\RectorGenerator\\Exception\\ShouldNotHappenException' => $vendorDir . '/rector/rector-generator/src/Exception/ShouldNotHappenException.php',
'Rector\\RectorGenerator\\FileSystem\\ConfigFilesystem' => $vendorDir . '/rector/rector-generator/src/FileSystem/ConfigFilesystem.php',
'Rector\\RectorGenerator\\FileSystem\\TemplateFileSystem' => $vendorDir . '/rector/rector-generator/src/FileSystem/TemplateFileSystem.php',
'Rector\\RectorGenerator\\Finder\\TemplateFinder' => $vendorDir . '/rector/rector-generator/src/Finder/TemplateFinder.php',
'Rector\\RectorGenerator\\Generator\\FileGenerator' => $vendorDir . '/rector/rector-generator/src/Generator/FileGenerator.php',
'Rector\\RectorGenerator\\Generator\\RectorGenerator' => $vendorDir . '/rector/rector-generator/src/Generator/RectorGenerator.php',
'Rector\\RectorGenerator\\Guard\\OverrideGuard' => $vendorDir . '/rector/rector-generator/src/Guard/OverrideGuard.php',
'Rector\\RectorGenerator\\NodeFactory\\ConfigurationNodeFactory' => $vendorDir . '/rector/rector-generator/src/NodeFactory/ConfigurationNodeFactory.php',
'Rector\\RectorGenerator\\NodeFactory\\ConfigureClassMethodFactory' => $vendorDir . '/rector/rector-generator/src/NodeFactory/ConfigureClassMethodFactory.php',
'Rector\\RectorGenerator\\NodeFactory\\NodeFactory' => $vendorDir . '/rector/rector-generator/src/NodeFactory/NodeFactory.php',
'Rector\\RectorGenerator\\Provider\\RectorRecipeProvider' => $vendorDir . '/rector/rector-generator/src/Provider/RectorRecipeProvider.php',
'Rector\\RectorGenerator\\TemplateFactory' => $vendorDir . '/rector/rector-generator/src/TemplateFactory.php',
'Rector\\RectorGenerator\\TemplateInitializer' => $vendorDir . '/rector/rector-generator/src/TemplateInitializer.php',
'Rector\\RectorGenerator\\TemplateVariablesFactory' => $vendorDir . '/rector/rector-generator/src/TemplateVariablesFactory.php',
'Rector\\RectorGenerator\\ValueObject\\NamePattern' => $vendorDir . '/rector/rector-generator/src/ValueObject/NamePattern.php',
'Rector\\RectorGenerator\\ValueObject\\Option' => $vendorDir . '/rector/rector-generator/src/ValueObject/Option.php',
'Rector\\RectorGenerator\\ValueObject\\Placeholder' => $vendorDir . '/rector/rector-generator/src/ValueObject/Placeholder.php',
'Rector\\RectorGenerator\\ValueObject\\RectorGeneratorConfig' => $vendorDir . '/rector/rector-generator/src/ValueObject/RectorGeneratorConfig.php',
'Rector\\RectorGenerator\\ValueObject\\RectorRecipe' => $vendorDir . '/rector/rector-generator/src/ValueObject/RectorRecipe.php',
'Rector\\RectorInstaller\\Filesystem' => $vendorDir . '/rector/extension-installer/src/Filesystem.php',
'Rector\\RectorInstaller\\GeneratedConfig' => $vendorDir . '/rector/extension-installer/src/GeneratedConfig.php',
'Rector\\RectorInstaller\\LocalFilesystem' => $vendorDir . '/rector/extension-installer/src/LocalFilesystem.php',

View File

@ -12,7 +12,6 @@ return array(
'Rector\\Utils\\' => array($baseDir . '/utils'),
'Rector\\Symfony\\' => array($vendorDir . '/rector/rector-symfony/src'),
'Rector\\RectorInstaller\\' => array($vendorDir . '/rector/extension-installer/src'),
'Rector\\RectorGenerator\\' => array($vendorDir . '/rector/rector-generator/src'),
'Rector\\PHPUnit\\' => array($vendorDir . '/rector/rector-phpunit/src'),
'Rector\\PHPOffice\\' => array($vendorDir . '/rector/rector-phpoffice/src'),
'Rector\\Laravel\\' => array($vendorDir . '/rector/rector-laravel/src'),

View File

@ -2,7 +2,7 @@
// autoload_real.php @generated by Composer
class ComposerAutoloaderInit83716a21ad55eb60ab18d8cb830f08a9
class ComposerAutoloaderInitcd1f1758a12d59a8465f8d671b277097
{
private static $loader;
@ -22,19 +22,19 @@ class ComposerAutoloaderInit83716a21ad55eb60ab18d8cb830f08a9
return self::$loader;
}
spl_autoload_register(array('ComposerAutoloaderInit83716a21ad55eb60ab18d8cb830f08a9', 'loadClassLoader'), true, true);
spl_autoload_register(array('ComposerAutoloaderInitcd1f1758a12d59a8465f8d671b277097', 'loadClassLoader'), true, true);
self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__));
spl_autoload_unregister(array('ComposerAutoloaderInit83716a21ad55eb60ab18d8cb830f08a9', 'loadClassLoader'));
spl_autoload_unregister(array('ComposerAutoloaderInitcd1f1758a12d59a8465f8d671b277097', 'loadClassLoader'));
require __DIR__ . '/autoload_static.php';
call_user_func(\Composer\Autoload\ComposerStaticInit83716a21ad55eb60ab18d8cb830f08a9::getInitializer($loader));
call_user_func(\Composer\Autoload\ComposerStaticInitcd1f1758a12d59a8465f8d671b277097::getInitializer($loader));
$loader->setClassMapAuthoritative(true);
$loader->register(true);
$includeFiles = \Composer\Autoload\ComposerStaticInit83716a21ad55eb60ab18d8cb830f08a9::$files;
$includeFiles = \Composer\Autoload\ComposerStaticInitcd1f1758a12d59a8465f8d671b277097::$files;
foreach ($includeFiles as $fileIdentifier => $file) {
composerRequire83716a21ad55eb60ab18d8cb830f08a9($fileIdentifier, $file);
composerRequirecd1f1758a12d59a8465f8d671b277097($fileIdentifier, $file);
}
return $loader;
@ -46,7 +46,7 @@ class ComposerAutoloaderInit83716a21ad55eb60ab18d8cb830f08a9
* @param string $file
* @return void
*/
function composerRequire83716a21ad55eb60ab18d8cb830f08a9($fileIdentifier, $file)
function composerRequirecd1f1758a12d59a8465f8d671b277097($fileIdentifier, $file)
{
if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
$GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;

View File

@ -4,7 +4,7 @@
namespace Composer\Autoload;
class ComposerStaticInit83716a21ad55eb60ab18d8cb830f08a9
class ComposerStaticInitcd1f1758a12d59a8465f8d671b277097
{
public static $files = array (
'0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php',
@ -29,7 +29,6 @@ class ComposerStaticInit83716a21ad55eb60ab18d8cb830f08a9
'Rector\\Utils\\' => 13,
'Rector\\Symfony\\' => 15,
'Rector\\RectorInstaller\\' => 23,
'Rector\\RectorGenerator\\' => 23,
'Rector\\PHPUnit\\' => 15,
'Rector\\PHPOffice\\' => 17,
'Rector\\Laravel\\' => 15,
@ -107,10 +106,6 @@ class ComposerStaticInit83716a21ad55eb60ab18d8cb830f08a9
array (
0 => __DIR__ . '/..' . '/rector/extension-installer/src',
),
'Rector\\RectorGenerator\\' =>
array (
0 => __DIR__ . '/..' . '/rector/rector-generator/src',
),
'Rector\\PHPUnit\\' =>
array (
0 => __DIR__ . '/..' . '/rector/rector-phpunit/src',
@ -2774,29 +2769,6 @@ class ComposerStaticInit83716a21ad55eb60ab18d8cb830f08a9
'Rector\\ReadWrite\\ReadNodeAnalyzer\\JustReadExprAnalyzer' => __DIR__ . '/../..' . '/packages/ReadWrite/ReadNodeAnalyzer/JustReadExprAnalyzer.php',
'Rector\\ReadWrite\\ReadNodeAnalyzer\\LocalPropertyFetchReadNodeAnalyzer' => __DIR__ . '/../..' . '/packages/ReadWrite/ReadNodeAnalyzer/LocalPropertyFetchReadNodeAnalyzer.php',
'Rector\\ReadWrite\\ReadNodeAnalyzer\\VariableReadNodeAnalyzer' => __DIR__ . '/../..' . '/packages/ReadWrite/ReadNodeAnalyzer/VariableReadNodeAnalyzer.php',
'Rector\\RectorGenerator\\Command\\GenerateCommand' => __DIR__ . '/..' . '/rector/rector-generator/src/Command/GenerateCommand.php',
'Rector\\RectorGenerator\\Command\\InitRecipeCommand' => __DIR__ . '/..' . '/rector/rector-generator/src/Command/InitRecipeCommand.php',
'Rector\\RectorGenerator\\Enum\\Packages' => __DIR__ . '/..' . '/rector/rector-generator/src/Enum/Packages.php',
'Rector\\RectorGenerator\\Exception\\ConfigurationException' => __DIR__ . '/..' . '/rector/rector-generator/src/Exception/ConfigurationException.php',
'Rector\\RectorGenerator\\Exception\\ShouldNotHappenException' => __DIR__ . '/..' . '/rector/rector-generator/src/Exception/ShouldNotHappenException.php',
'Rector\\RectorGenerator\\FileSystem\\ConfigFilesystem' => __DIR__ . '/..' . '/rector/rector-generator/src/FileSystem/ConfigFilesystem.php',
'Rector\\RectorGenerator\\FileSystem\\TemplateFileSystem' => __DIR__ . '/..' . '/rector/rector-generator/src/FileSystem/TemplateFileSystem.php',
'Rector\\RectorGenerator\\Finder\\TemplateFinder' => __DIR__ . '/..' . '/rector/rector-generator/src/Finder/TemplateFinder.php',
'Rector\\RectorGenerator\\Generator\\FileGenerator' => __DIR__ . '/..' . '/rector/rector-generator/src/Generator/FileGenerator.php',
'Rector\\RectorGenerator\\Generator\\RectorGenerator' => __DIR__ . '/..' . '/rector/rector-generator/src/Generator/RectorGenerator.php',
'Rector\\RectorGenerator\\Guard\\OverrideGuard' => __DIR__ . '/..' . '/rector/rector-generator/src/Guard/OverrideGuard.php',
'Rector\\RectorGenerator\\NodeFactory\\ConfigurationNodeFactory' => __DIR__ . '/..' . '/rector/rector-generator/src/NodeFactory/ConfigurationNodeFactory.php',
'Rector\\RectorGenerator\\NodeFactory\\ConfigureClassMethodFactory' => __DIR__ . '/..' . '/rector/rector-generator/src/NodeFactory/ConfigureClassMethodFactory.php',
'Rector\\RectorGenerator\\NodeFactory\\NodeFactory' => __DIR__ . '/..' . '/rector/rector-generator/src/NodeFactory/NodeFactory.php',
'Rector\\RectorGenerator\\Provider\\RectorRecipeProvider' => __DIR__ . '/..' . '/rector/rector-generator/src/Provider/RectorRecipeProvider.php',
'Rector\\RectorGenerator\\TemplateFactory' => __DIR__ . '/..' . '/rector/rector-generator/src/TemplateFactory.php',
'Rector\\RectorGenerator\\TemplateInitializer' => __DIR__ . '/..' . '/rector/rector-generator/src/TemplateInitializer.php',
'Rector\\RectorGenerator\\TemplateVariablesFactory' => __DIR__ . '/..' . '/rector/rector-generator/src/TemplateVariablesFactory.php',
'Rector\\RectorGenerator\\ValueObject\\NamePattern' => __DIR__ . '/..' . '/rector/rector-generator/src/ValueObject/NamePattern.php',
'Rector\\RectorGenerator\\ValueObject\\Option' => __DIR__ . '/..' . '/rector/rector-generator/src/ValueObject/Option.php',
'Rector\\RectorGenerator\\ValueObject\\Placeholder' => __DIR__ . '/..' . '/rector/rector-generator/src/ValueObject/Placeholder.php',
'Rector\\RectorGenerator\\ValueObject\\RectorGeneratorConfig' => __DIR__ . '/..' . '/rector/rector-generator/src/ValueObject/RectorGeneratorConfig.php',
'Rector\\RectorGenerator\\ValueObject\\RectorRecipe' => __DIR__ . '/..' . '/rector/rector-generator/src/ValueObject/RectorRecipe.php',
'Rector\\RectorInstaller\\Filesystem' => __DIR__ . '/..' . '/rector/extension-installer/src/Filesystem.php',
'Rector\\RectorInstaller\\GeneratedConfig' => __DIR__ . '/..' . '/rector/extension-installer/src/GeneratedConfig.php',
'Rector\\RectorInstaller\\LocalFilesystem' => __DIR__ . '/..' . '/rector/extension-installer/src/LocalFilesystem.php',
@ -3240,9 +3212,9 @@ class ComposerStaticInit83716a21ad55eb60ab18d8cb830f08a9
public static function getInitializer(ClassLoader $loader)
{
return \Closure::bind(function () use ($loader) {
$loader->prefixLengthsPsr4 = ComposerStaticInit83716a21ad55eb60ab18d8cb830f08a9::$prefixLengthsPsr4;
$loader->prefixDirsPsr4 = ComposerStaticInit83716a21ad55eb60ab18d8cb830f08a9::$prefixDirsPsr4;
$loader->classMap = ComposerStaticInit83716a21ad55eb60ab18d8cb830f08a9::$classMap;
$loader->prefixLengthsPsr4 = ComposerStaticInitcd1f1758a12d59a8465f8d671b277097::$prefixLengthsPsr4;
$loader->prefixDirsPsr4 = ComposerStaticInitcd1f1758a12d59a8465f8d671b277097::$prefixDirsPsr4;
$loader->classMap = ComposerStaticInitcd1f1758a12d59a8465f8d671b277097::$classMap;
}, null, ClassLoader::class);
}

View File

@ -1984,81 +1984,6 @@
},
"install-path": "..\/rector\/rector-downgrade-php"
},
{
"name": "rector\/rector-generator",
"version": "dev-main",
"version_normalized": "dev-main",
"source": {
"type": "git",
"url": "https:\/\/github.com\/rectorphp\/rector-generator.git",
"reference": "38440b9580b6b1d8859bfb72849753b241a1e39a"
},
"dist": {
"type": "zip",
"url": "https:\/\/api.github.com\/repos\/rectorphp\/rector-generator\/zipball\/38440b9580b6b1d8859bfb72849753b241a1e39a",
"reference": "38440b9580b6b1d8859bfb72849753b241a1e39a",
"shasum": ""
},
"require": {
"nette\/utils": "^3.2",
"nikic\/php-parser": "^4.14",
"php": ">=8.1",
"symfony\/console": "^6.0",
"symfony\/dependency-injection": "^6.0",
"symfony\/finder": "^6.0",
"symplify\/package-builder": "^11.0"
},
"require-dev": {
"php-parallel-lint\/php-parallel-lint": "^1.3",
"phpstan\/extension-installer": "^1.1",
"phpstan\/phpdoc-parser": "^1.6.4",
"phpstan\/phpstan-strict-rules": "^1.3",
"phpstan\/phpstan-webmozart-assert": "^1.0",
"phpunit\/phpunit": "^9.5",
"rector\/rector-src": "dev-main",
"symplify\/coding-standard": "^11.0",
"symplify\/easy-coding-standard": "^11.0",
"symplify\/easy-testing": "^11.0",
"symplify\/monorepo-builder": "^11.0",
"symplify\/phpstan-extensions": "^11.0",
"symplify\/phpstan-rules": "^11.0",
"symplify\/vendor-patches": "^11.0"
},
"time": "2022-08-09T10:09:42+00:00",
"default-branch": true,
"type": "rector-extension",
"extra": {
"enable-patching": true,
"rector": {
"includes": [
"config\/config.php"
]
}
},
"installation-source": "dist",
"autoload": {
"psr-4": {
"Rector\\RectorGenerator\\": "src"
}
},
"notification-url": "https:\/\/packagist.org\/downloads\/",
"license": [
"MIT"
],
"description": "Generate Rector rules from command line",
"homepage": "https:\/\/getrector.org",
"support": {
"issues": "https:\/\/github.com\/rectorphp\/rector-generator\/issues",
"source": "https:\/\/github.com\/rectorphp\/rector-generator\/tree\/0.6.10"
},
"funding": [
{
"url": "https:\/\/github.com\/tomasvotruba",
"type": "github"
}
],
"install-path": "..\/rector\/rector-generator"
},
{
"name": "rector\/rector-laravel",
"version": "dev-main",
@ -2200,12 +2125,12 @@
"source": {
"type": "git",
"url": "https:\/\/github.com\/rectorphp\/rector-phpunit.git",
"reference": "26e1dcbc5fa3d214af34f627d0d7013b8eba8eb5"
"reference": "24eb4fe75f34c096c29d3ad915e1d25b4770e6ba"
},
"dist": {
"type": "zip",
"url": "https:\/\/api.github.com\/repos\/rectorphp\/rector-phpunit\/zipball\/26e1dcbc5fa3d214af34f627d0d7013b8eba8eb5",
"reference": "26e1dcbc5fa3d214af34f627d0d7013b8eba8eb5",
"url": "https:\/\/api.github.com\/repos\/rectorphp\/rector-phpunit\/zipball\/24eb4fe75f34c096c29d3ad915e1d25b4770e6ba",
"reference": "24eb4fe75f34c096c29d3ad915e1d25b4770e6ba",
"shasum": ""
},
"require": {
@ -2230,7 +2155,7 @@
"symplify\/rule-doc-generator": "^11.0",
"symplify\/vendor-patches": "^11.0"
},
"time": "2022-08-26T08:56:19+00:00",
"time": "2022-08-29T18:12:57+00:00",
"default-branch": true,
"type": "rector-extension",
"extra": {

File diff suppressed because one or more lines are too long

View File

@ -9,7 +9,7 @@ namespace Rector\RectorInstaller;
*/
final class GeneratedConfig
{
public const EXTENSIONS = array('rector/rector-cakephp' => array('install_path' => '/home/runner/work/rector-src/rector-src/vendor/rector/rector-cakephp', 'relative_install_path' => '../../rector-cakephp', 'extra' => array('includes' => array(0 => 'config/config.php')), 'version' => 'dev-main c2ec06c'), 'rector/rector-doctrine' => array('install_path' => '/home/runner/work/rector-src/rector-src/vendor/rector/rector-doctrine', 'relative_install_path' => '../../rector-doctrine', 'extra' => array('includes' => array(0 => 'config/config.php')), 'version' => 'dev-main 2eddc31'), 'rector/rector-downgrade-php' => array('install_path' => '/home/runner/work/rector-src/rector-src/vendor/rector/rector-downgrade-php', 'relative_install_path' => '../../rector-downgrade-php', 'extra' => array('includes' => array(0 => 'config/config.php')), 'version' => 'dev-main efc7ddf'), 'rector/rector-generator' => array('install_path' => '/home/runner/work/rector-src/rector-src/vendor/rector/rector-generator', 'relative_install_path' => '../../rector-generator', 'extra' => array('includes' => array(0 => 'config/config.php')), 'version' => 'dev-main 38440b9'), 'rector/rector-laravel' => array('install_path' => '/home/runner/work/rector-src/rector-src/vendor/rector/rector-laravel', 'relative_install_path' => '../../rector-laravel', 'extra' => array('includes' => array(0 => 'config/config.php')), 'version' => 'dev-main 20edb95'), 'rector/rector-phpoffice' => array('install_path' => '/home/runner/work/rector-src/rector-src/vendor/rector/rector-phpoffice', 'relative_install_path' => '../../rector-phpoffice', 'extra' => array('includes' => array(0 => 'config/config.php')), 'version' => 'dev-main 3638a66'), 'rector/rector-phpunit' => array('install_path' => '/home/runner/work/rector-src/rector-src/vendor/rector/rector-phpunit', 'relative_install_path' => '../../rector-phpunit', 'extra' => array('includes' => array(0 => 'config/config.php')), 'version' => 'dev-main 26e1dcb'), 'rector/rector-symfony' => array('install_path' => '/home/runner/work/rector-src/rector-src/vendor/rector/rector-symfony', 'relative_install_path' => '../../rector-symfony', 'extra' => array('includes' => array(0 => 'config/config.php')), 'version' => 'dev-main 66ecf4c'));
public const EXTENSIONS = array('rector/rector-cakephp' => array('install_path' => '/home/runner/work/rector-src/rector-src/vendor/rector/rector-cakephp', 'relative_install_path' => '../../rector-cakephp', 'extra' => array('includes' => array(0 => 'config/config.php')), 'version' => 'dev-main c2ec06c'), 'rector/rector-doctrine' => array('install_path' => '/home/runner/work/rector-src/rector-src/vendor/rector/rector-doctrine', 'relative_install_path' => '../../rector-doctrine', 'extra' => array('includes' => array(0 => 'config/config.php')), 'version' => 'dev-main 2eddc31'), 'rector/rector-downgrade-php' => array('install_path' => '/home/runner/work/rector-src/rector-src/vendor/rector/rector-downgrade-php', 'relative_install_path' => '../../rector-downgrade-php', 'extra' => array('includes' => array(0 => 'config/config.php')), 'version' => 'dev-main efc7ddf'), 'rector/rector-laravel' => array('install_path' => '/home/runner/work/rector-src/rector-src/vendor/rector/rector-laravel', 'relative_install_path' => '../../rector-laravel', 'extra' => array('includes' => array(0 => 'config/config.php')), 'version' => 'dev-main 20edb95'), 'rector/rector-phpoffice' => array('install_path' => '/home/runner/work/rector-src/rector-src/vendor/rector/rector-phpoffice', 'relative_install_path' => '../../rector-phpoffice', 'extra' => array('includes' => array(0 => 'config/config.php')), 'version' => 'dev-main 3638a66'), 'rector/rector-phpunit' => array('install_path' => '/home/runner/work/rector-src/rector-src/vendor/rector/rector-phpunit', 'relative_install_path' => '../../rector-phpunit', 'extra' => array('includes' => array(0 => 'config/config.php')), 'version' => 'dev-main 24eb4fe'), 'rector/rector-symfony' => array('install_path' => '/home/runner/work/rector-src/rector-src/vendor/rector/rector-symfony', 'relative_install_path' => '../../rector-symfony', 'extra' => array('includes' => array(0 => 'config/config.php')), 'version' => 'dev-main 66ecf4c'));
private function __construct()
{
}

View File

@ -1,25 +0,0 @@
The MIT License
---------------
Copyright (c) 2017-present Tomáš Votruba (https://tomasvotruba.cz)
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.

View File

@ -1,65 +0,0 @@
{
"name": "rector\/rector-generator",
"type": "rector-extension",
"description": "Generate Rector rules from command line",
"homepage": "https:\/\/getrector.org",
"license": "MIT",
"require": {
"php": ">=8.1",
"nette\/utils": "^3.2",
"nikic\/php-parser": "^4.14",
"symfony\/console": "^6.0",
"symfony\/dependency-injection": "^6.0",
"symfony\/finder": "^6.0",
"symplify\/package-builder": "^11.0"
},
"require-dev": {
"rector\/rector-src": "dev-main",
"php-parallel-lint\/php-parallel-lint": "^1.3",
"phpunit\/phpunit": "^9.5",
"phpstan\/phpdoc-parser": "^1.6.4",
"symplify\/coding-standard": "^11.0",
"symplify\/easy-coding-standard": "^11.0",
"symplify\/phpstan-extensions": "^11.0",
"symplify\/phpstan-rules": "^11.0",
"symplify\/easy-testing": "^11.0",
"phpstan\/extension-installer": "^1.1",
"symplify\/monorepo-builder": "^11.0",
"symplify\/vendor-patches": "^11.0",
"phpstan\/phpstan-strict-rules": "^1.3",
"phpstan\/phpstan-webmozart-assert": "^1.0"
},
"autoload": {
"psr-4": {
"Rector\\RectorGenerator\\": "src"
}
},
"autoload-dev": {
"psr-4": {
"Rector\\RectorGenerator\\Tests\\": "tests"
}
},
"scripts": {
"release": "vendor\/bin\/monorepo-builder release patch --ansi",
"check-cs": "vendor\/bin\/ecs check --ansi",
"fix-cs": "vendor\/bin\/ecs check --fix --ansi",
"phpstan": "vendor\/bin\/phpstan analyse --ansi --error-format symplify"
},
"extra": {
"enable-patching": true,
"rector": {
"includes": [
"config\/config.php"
]
}
},
"minimum-stability": "dev",
"prefer-stable": true,
"config": {
"allow-plugins": {
"cweagans\/composer-patches": true,
"rector\/extension-installer": true,
"phpstan\/extension-installer": true
}
}
}

View File

@ -1,38 +0,0 @@
<?php
declare (strict_types=1);
namespace RectorPrefix202208;
use PhpParser\Parser;
use PhpParser\ParserFactory;
use PhpParser\PrettyPrinter\Standard;
use RectorPrefix202208\Symfony\Component\Console\Style\SymfonyStyle;
use RectorPrefix202208\Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
use function RectorPrefix202208\Symfony\Component\DependencyInjection\Loader\Configurator\service;
use RectorPrefix202208\Symplify\PackageBuilder\Console\Style\SymfonyStyleFactory;
use RectorPrefix202208\Symplify\PackageBuilder\Reflection\PrivatesAccessor;
use RectorPrefix202208\Symplify\PackageBuilder\Reflection\PrivatesCaller;
use RectorPrefix202208\Symplify\SmartFileSystem\FileSystemGuard;
use RectorPrefix202208\Symplify\SmartFileSystem\Finder\FinderSanitizer;
use RectorPrefix202208\Symplify\SmartFileSystem\Json\JsonFileSystem;
use RectorPrefix202208\Symplify\SmartFileSystem\SmartFileSystem;
return static function (ContainerConfigurator $containerConfigurator) : void {
$services = $containerConfigurator->services();
$services->defaults()->public()->autowire()->autoconfigure();
$services->load('Rector\\RectorGenerator\\', __DIR__ . '/../src')->exclude([__DIR__ . '/../src/ValueObject', __DIR__ . '/../src/Enum']);
// console
$services->set(SymfonyStyleFactory::class);
$services->set(SymfonyStyle::class)->factory([service(SymfonyStyleFactory::class), 'create']);
// filesystem
$services->set(JsonFileSystem::class);
$services->set(SmartFileSystem::class);
$services->set(FinderSanitizer::class);
$services->set(FileSystemGuard::class);
// privates
$services->set(PrivatesCaller::class);
$services->set(PrivatesAccessor::class);
// php-parser
$services->set(Standard::class)->arg('$options', ['shortArraySyntax' => \true]);
$services->set(ParserFactory::class);
$services->set(Parser::class)->factory([service(ParserFactory::class), 'create'])->arg('$kind', ParserFactory::PREFER_PHP7);
};

View File

@ -1,15 +0,0 @@
<?php
declare (strict_types=1);
namespace RectorPrefix202208;
use RectorPrefix202208\Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
use RectorPrefix202208\Symplify\MonorepoBuilder\Release\ReleaseWorker\PushTagReleaseWorker;
use RectorPrefix202208\Symplify\MonorepoBuilder\Release\ReleaseWorker\TagVersionReleaseWorker;
return static function (ContainerConfigurator $containerConfigurator) : void {
$services = $containerConfigurator->services();
$services->defaults()->autowire();
// @see https://github.com/symplify/monorepo-builder#6-release-flow
$services->set(TagVersionReleaseWorker::class);
$services->set(PushTagReleaseWorker::class);
};

View File

@ -1,119 +0,0 @@
<?php
declare (strict_types=1);
namespace Rector\RectorGenerator\Command;
use Rector\RectorGenerator\Exception\ShouldNotHappenException;
use Rector\RectorGenerator\FileSystem\ConfigFilesystem;
use Rector\RectorGenerator\Generator\RectorGenerator;
use Rector\RectorGenerator\Provider\RectorRecipeProvider;
use Rector\RectorGenerator\TemplateVariablesFactory;
use Rector\RectorGenerator\ValueObject\NamePattern;
use RectorPrefix202208\Symfony\Component\Console\Command\Command;
use RectorPrefix202208\Symfony\Component\Console\Input\InputInterface;
use RectorPrefix202208\Symfony\Component\Console\Output\OutputInterface;
use RectorPrefix202208\Symfony\Component\Console\Style\SymfonyStyle;
use Symplify\SmartFileSystem\SmartFileInfo;
/**
* @see \Rector\RectorGenerator\Tests\RectorGenerator\GenerateCommandInteractiveModeTest
*/
final class GenerateCommand extends Command
{
/**
* @readonly
* @var \Rector\RectorGenerator\FileSystem\ConfigFilesystem
*/
private $configFilesystem;
/**
* @readonly
* @var \Symfony\Component\Console\Style\SymfonyStyle
*/
private $symfonyStyle;
/**
* @readonly
* @var \Rector\RectorGenerator\TemplateVariablesFactory
*/
private $templateVariablesFactory;
/**
* @readonly
* @var \Rector\RectorGenerator\Provider\RectorRecipeProvider
*/
private $rectorRecipeProvider;
/**
* @readonly
* @var \Rector\RectorGenerator\Generator\RectorGenerator
*/
private $rectorGenerator;
public function __construct(ConfigFilesystem $configFilesystem, SymfonyStyle $symfonyStyle, TemplateVariablesFactory $templateVariablesFactory, RectorRecipeProvider $rectorRecipeProvider, RectorGenerator $rectorGenerator)
{
$this->configFilesystem = $configFilesystem;
$this->symfonyStyle = $symfonyStyle;
$this->templateVariablesFactory = $templateVariablesFactory;
$this->rectorRecipeProvider = $rectorRecipeProvider;
$this->rectorGenerator = $rectorGenerator;
parent::__construct();
}
protected function configure() : void
{
$this->setName('generate');
$this->setDescription('[DEV] Create a new Rector, in a proper location, with new tests');
}
protected function execute(InputInterface $input, OutputInterface $output) : int
{
$rectorRecipe = $this->rectorRecipeProvider->provide();
$targetDirectory = \getcwd();
$generatedFilePaths = $this->rectorGenerator->generate($rectorRecipe, $targetDirectory);
// nothing new
if ($generatedFilePaths === []) {
return self::SUCCESS;
}
$setFilePath = $rectorRecipe->getSetFilePath();
if ($setFilePath !== null) {
$templateVariables = $this->templateVariablesFactory->createFromRectorRecipe($rectorRecipe);
$this->configFilesystem->appendRectorServiceToSet($setFilePath, $templateVariables, NamePattern::RECTOR_FQN_NAME_PATTERN);
}
$testCaseDirectoryPath = $this->resolveTestCaseDirectoryPath($generatedFilePaths);
$this->printSuccess($rectorRecipe->getName(), $generatedFilePaths, $testCaseDirectoryPath);
return self::SUCCESS;
}
/**
* @param string[] $generatedFilePaths
*/
private function resolveTestCaseDirectoryPath(array $generatedFilePaths) : string
{
foreach ($generatedFilePaths as $generatedFilePath) {
if (!$this->isGeneratedFilePathTestCase($generatedFilePath)) {
continue;
}
$generatedFileInfo = new SmartFileInfo($generatedFilePath);
return \dirname($generatedFileInfo->getRelativeFilePathFromCwd());
}
throw new ShouldNotHappenException();
}
/**
* @param string[] $generatedFilePaths
*/
private function printSuccess(string $name, array $generatedFilePaths, string $testCaseFilePath) : void
{
$message = \sprintf('New files generated for "%s":', $name);
$this->symfonyStyle->title($message);
\sort($generatedFilePaths);
foreach ($generatedFilePaths as $generatedFilePath) {
$fileInfo = new SmartFileInfo($generatedFilePath);
$relativeFilePath = $fileInfo->getRelativeFilePathFromCwd();
$this->symfonyStyle->writeln(' * ' . $relativeFilePath);
}
$message = \sprintf('Make tests green again:%svendor/bin/phpunit %s', \PHP_EOL . \PHP_EOL, $testCaseFilePath);
$this->symfonyStyle->success($message);
}
private function isGeneratedFilePathTestCase(string $generatedFilePath) : bool
{
if (\substr_compare($generatedFilePath, 'Test.php', -\strlen('Test.php')) === 0) {
return \true;
}
if (\substr_compare($generatedFilePath, 'Test.php.inc', -\strlen('Test.php.inc')) !== 0) {
return \false;
}
return \defined('PHPUNIT_COMPOSER_INSTALL');
}
}

View File

@ -1,32 +0,0 @@
<?php
declare (strict_types=1);
namespace Rector\RectorGenerator\Command;
use Rector\RectorGenerator\TemplateInitializer;
use RectorPrefix202208\Symfony\Component\Console\Command\Command;
use RectorPrefix202208\Symfony\Component\Console\Input\InputInterface;
use RectorPrefix202208\Symfony\Component\Console\Output\OutputInterface;
final class InitRecipeCommand extends Command
{
/**
* @readonly
* @var \Rector\RectorGenerator\TemplateInitializer
*/
private $templateInitializer;
public function __construct(TemplateInitializer $templateInitializer)
{
$this->templateInitializer = $templateInitializer;
parent::__construct();
}
protected function configure() : void
{
$this->setName('init-recipe');
$this->setDescription('[DEV] Initialize "rector-recipe.php" config');
}
protected function execute(InputInterface $input, OutputInterface $output) : int
{
$this->templateInitializer->initialize(__DIR__ . '/../../templates/rector-recipe.php', 'rector-recipe.php');
return self::SUCCESS;
}
}

View File

@ -1,12 +0,0 @@
<?php
declare (strict_types=1);
namespace Rector\RectorGenerator\Enum;
final class Packages
{
/**
* @var string[]
*/
public const RECTOR_CORE = ['Symfony', 'Nette', 'Doctrine', 'Laravel', 'PHPUnit', 'CakePHP', 'PHPOffice'];
}

View File

@ -1,9 +0,0 @@
<?php
declare (strict_types=1);
namespace Rector\RectorGenerator\Exception;
use Exception;
final class ConfigurationException extends Exception
{
}

View File

@ -1,9 +0,0 @@
<?php
declare (strict_types=1);
namespace Rector\RectorGenerator\Exception;
use Exception;
final class ShouldNotHappenException extends Exception
{
}

View File

@ -1,65 +0,0 @@
<?php
declare (strict_types=1);
namespace Rector\RectorGenerator\FileSystem;
use RectorPrefix202208\Nette\Utils\Strings;
use Rector\RectorGenerator\Exception\ShouldNotHappenException;
use Rector\RectorGenerator\TemplateFactory;
use RectorPrefix202208\Symplify\SmartFileSystem\SmartFileSystem;
final class ConfigFilesystem
{
/**
* @var string[]
*/
private const REQUIRED_KEYS = ['__Package__', '__Category__', '__Name__'];
/**
* @see https://regex101.com/r/gJ0bHJ/1
* @var string
*/
private const LAST_ITEM_REGEX = '#;\\n};#';
/**
* @readonly
* @var \Symplify\SmartFileSystem\SmartFileSystem
*/
private $smartFileSystem;
/**
* @readonly
* @var \Rector\RectorGenerator\TemplateFactory
*/
private $templateFactory;
public function __construct(SmartFileSystem $smartFileSystem, TemplateFactory $templateFactory)
{
$this->smartFileSystem = $smartFileSystem;
$this->templateFactory = $templateFactory;
}
/**
* @param array<string, string> $templateVariables
*/
public function appendRectorServiceToSet(string $setFilePath, array $templateVariables, string $rectorFqnNamePattern) : void
{
$setFileContents = $this->smartFileSystem->readFile($setFilePath);
$this->ensureRequiredKeysAreSet($templateVariables);
// already added?
$servicesFullyQualifiedName = $this->templateFactory->create($rectorFqnNamePattern, $templateVariables);
if (\strpos($setFileContents, $servicesFullyQualifiedName) !== \false) {
return;
}
$registerServiceLine = \sprintf(';' . \PHP_EOL . ' $rectorConfig->rule(\\%s::class);' . \PHP_EOL . '};', $servicesFullyQualifiedName);
$setFileContents = Strings::replace($setFileContents, self::LAST_ITEM_REGEX, $registerServiceLine);
// 3. print the content back to file
$this->smartFileSystem->dumpFile($setFilePath, $setFileContents);
}
/**
* @param array<string, string> $templateVariables
*/
private function ensureRequiredKeysAreSet(array $templateVariables) : void
{
$missingKeys = \array_diff(self::REQUIRED_KEYS, \array_keys($templateVariables));
if ($missingKeys === []) {
return;
}
$message = \sprintf('Template variables for "%s" keys are missing', \implode('", "', $missingKeys));
throw new ShouldNotHappenException($message);
}
}

View File

@ -1,86 +0,0 @@
<?php
declare (strict_types=1);
namespace Rector\RectorGenerator\FileSystem;
use RectorPrefix202208\Nette\Utils\Strings;
use Rector\RectorGenerator\Enum\Packages;
use Rector\RectorGenerator\Finder\TemplateFinder;
use Rector\RectorGenerator\TemplateFactory;
use Rector\RectorGenerator\ValueObject\RectorRecipe;
use Symplify\SmartFileSystem\SmartFileInfo;
final class TemplateFileSystem
{
/**
* @var string
* @see https://regex101.com/r/fw3jBe/1
*/
private const FIXTURE_SHORT_REGEX = '#/Fixture/#';
/**
* @var string
* @see https://regex101.com/r/HBcfXd/1
*/
private const PACKAGE_RULES_PATH_REGEX = '#(rules)\\/__Package__#i';
/**
* @var string
* @see https://regex101.com/r/HBcfXd/1
*/
private const PACKAGE_RULES_TESTS_PATH_REGEX = '#(rules-tests)\\/__Package__#i';
/**
* @var string
* @see https://regex101.com/r/tOidWU/1
*/
private const CONFIGURED_OR_EXTRA_REGEX = '#(__Configured|__Extra)#';
/**
* @readonly
* @var \Rector\RectorGenerator\TemplateFactory
*/
private $templateFactory;
public function __construct(TemplateFactory $templateFactory)
{
$this->templateFactory = $templateFactory;
}
/**
* @param array<string, string> $templateVariables
*/
public function resolveDestination(SmartFileInfo $smartFileInfo, array $templateVariables, RectorRecipe $rectorRecipe, string $targetDirectory) : string
{
$destination = $smartFileInfo->getRelativeFilePathFromDirectory(TemplateFinder::TEMPLATES_DIRECTORY);
$destination = $this->changeRootPathForRootPackage($rectorRecipe, $destination);
// normalize core package
if (!$rectorRecipe->isRectorRepository()) {
// special keyword for 3rd party Rectors, not for core Github contribution
$destination = Strings::replace($destination, self::PACKAGE_RULES_PATH_REGEX, 'utils/rector/src');
$destination = Strings::replace($destination, self::PACKAGE_RULES_TESTS_PATH_REGEX, 'utils/rector/tests');
}
// remove _Configured|_Extra prefix
$destination = $this->templateFactory->create($destination, $templateVariables);
$destination = Strings::replace($destination, self::CONFIGURED_OR_EXTRA_REGEX, '');
// remove ".inc" protection from PHPUnit if not a test case
if ($this->isNonFixtureFileWithIncSuffix($destination)) {
$destination = Strings::before($destination, '.inc');
}
// special hack for tests, so PHPUnit doesn't load the generated file as a test case
/** @var string $destination */
if (\substr_compare($destination, 'Test.php', -\strlen('Test.php')) === 0 && \defined('PHPUNIT_COMPOSER_INSTALL')) {
$destination .= '.inc';
}
return $targetDirectory . \DIRECTORY_SEPARATOR . $destination;
}
private function isNonFixtureFileWithIncSuffix(string $filePath) : bool
{
if (Strings::match($filePath, self::FIXTURE_SHORT_REGEX) !== null) {
return \false;
}
return \substr_compare($filePath, '.inc', -\strlen('.inc')) === 0;
}
private function changeRootPathForRootPackage(RectorRecipe $rectorRecipe, string $destination) : string
{
// rector split package? path are in the root directory
if (!\in_array($rectorRecipe->getPackage(), Packages::RECTOR_CORE, \true)) {
return $destination;
}
$destination = \str_replace('rules/__Package__', 'src', $destination);
return \str_replace('rules-tests/__Package__', 'tests', $destination);
}
}

View File

@ -1,72 +0,0 @@
<?php
declare (strict_types=1);
namespace Rector\RectorGenerator\Finder;
use Rector\RectorGenerator\ValueObject\RectorRecipe;
use RectorPrefix202208\Symplify\SmartFileSystem\FileSystemGuard;
use RectorPrefix202208\Symplify\SmartFileSystem\Finder\FinderSanitizer;
use Symplify\SmartFileSystem\SmartFileInfo;
final class TemplateFinder
{
/**
* @var string
*/
public const TEMPLATES_DIRECTORY = __DIR__ . '/../../templates';
/**
* @readonly
* @var \Symplify\SmartFileSystem\Finder\FinderSanitizer
*/
private $finderSanitizer;
/**
* @readonly
* @var \Symplify\SmartFileSystem\FileSystemGuard
*/
private $fileSystemGuard;
public function __construct(FinderSanitizer $finderSanitizer, FileSystemGuard $fileSystemGuard)
{
$this->finderSanitizer = $finderSanitizer;
$this->fileSystemGuard = $fileSystemGuard;
}
/**
* @return SmartFileInfo[]
*/
public function find(RectorRecipe $rectorRecipe) : array
{
$filePaths = [];
$filePaths = $this->addRuleAndTestCase($rectorRecipe, $filePaths);
$filePaths[] = __DIR__ . '/../../templates/rules-tests/__Package__/Rector/__Category__/__Name__/Fixture/some_class.php.inc';
$this->ensureFilePathsExists($filePaths);
return $this->finderSanitizer->sanitize($filePaths);
}
/**
* @param string[] $filePaths
* @return string[]
*
* @note the ".inc" suffix is needed, so PHPUnit doens't load it as a test case
*/
private function addRuleAndTestCase(RectorRecipe $rectorRecipe, array $filePaths) : array
{
if ($rectorRecipe->getConfiguration() !== []) {
$filePaths[] = __DIR__ . '/../../templates/rules-tests/__Package__/Rector/__Category__/__Name__/config/__Configuredconfigured_rule.php';
} else {
$filePaths[] = __DIR__ . '/../../templates/rules-tests/__Package__/Rector/__Category__/__Name__/config/configured_rule.php';
}
$filePaths[] = __DIR__ . '/../../templates/rules-tests/__Package__/Rector/__Category__/__Name__/__Name__Test.php.inc';
if ($rectorRecipe->getConfiguration() !== []) {
$filePaths[] = __DIR__ . '/../../templates/rules/__Package__/Rector/__Category__/__Configured__Name__.php';
} else {
$filePaths[] = __DIR__ . '/../../templates/rules/__Package__/Rector/__Category__/__Name__.php';
}
return $filePaths;
}
/**
* @param string[] $filePaths
*/
private function ensureFilePathsExists(array $filePaths) : void
{
foreach ($filePaths as $filePath) {
$this->fileSystemGuard->ensureFileExists($filePath, __METHOD__);
}
}
}

View File

@ -1,83 +0,0 @@
<?php
declare (strict_types=1);
namespace Rector\RectorGenerator\Generator;
use RectorPrefix202208\Nette\Utils\Strings;
use Rector\RectorGenerator\Enum\Packages;
use Rector\RectorGenerator\FileSystem\TemplateFileSystem;
use Rector\RectorGenerator\TemplateFactory;
use Rector\RectorGenerator\ValueObject\RectorRecipe;
use Symplify\SmartFileSystem\SmartFileInfo;
use RectorPrefix202208\Symplify\SmartFileSystem\SmartFileSystem;
final class FileGenerator
{
/**
* @var string
* @see https://regex101.com/r/RVbPEX/1
*/
public const RECTOR_UTILS_REGEX = '#Rector\\\\Utils#';
/**
* @var string
* @see https://regex101.com/r/RVbPEX/1
*/
public const RECTOR_UTILS_TESTS_REGEX = '#Rector\\\\Tests\\\\Utils#';
/**
* @readonly
* @var \Symplify\SmartFileSystem\SmartFileSystem
*/
private $smartFileSystem;
/**
* @readonly
* @var \Rector\RectorGenerator\TemplateFactory
*/
private $templateFactory;
/**
* @readonly
* @var \Rector\RectorGenerator\FileSystem\TemplateFileSystem
*/
private $templateFileSystem;
public function __construct(SmartFileSystem $smartFileSystem, TemplateFactory $templateFactory, TemplateFileSystem $templateFileSystem)
{
$this->smartFileSystem = $smartFileSystem;
$this->templateFactory = $templateFactory;
$this->templateFileSystem = $templateFileSystem;
}
/**
* @param SmartFileInfo[] $templateFileInfos
* @param array<string, string> $templateVariables
* @return string[]
*/
public function generateFiles(array $templateFileInfos, array $templateVariables, RectorRecipe $rectorRecipe, string $destinationDirectory) : array
{
$generatedFilePaths = [];
foreach ($templateFileInfos as $templateFileInfo) {
$generatedFilePaths[] = $this->generateFileInfoWithTemplateVariables($templateFileInfo, $templateVariables, $rectorRecipe, $destinationDirectory);
}
return $generatedFilePaths;
}
/**
* @param array<string, string> $templateVariables
*/
private function generateFileInfoWithTemplateVariables(SmartFileInfo $smartFileInfo, array $templateVariables, RectorRecipe $rectorRecipe, string $targetDirectory) : string
{
$targetFilePath = $this->templateFileSystem->resolveDestination($smartFileInfo, $templateVariables, $rectorRecipe, $targetDirectory);
$content = $this->templateFactory->create($smartFileInfo->getContents(), $templateVariables);
// replace "Rector\Utils\" with "Utils\Rector\" for 3rd party packages
if (!$rectorRecipe->isRectorRepository()) {
$content = Strings::replace($content, self::RECTOR_UTILS_REGEX, 'Utils\\Rector');
$content = Strings::replace($content, self::RECTOR_UTILS_TESTS_REGEX, 'Utils\\Rector\\Tests');
}
// correct tests PSR-4 namespace for core rector packages
if (\in_array($rectorRecipe->getPackage(), Packages::RECTOR_CORE, \true)) {
$content = Strings::replace($content, '#namespace Rector\\\\Tests\\\\' . $rectorRecipe->getPackage() . '#', 'namespace Rector\\' . $rectorRecipe->getPackage() . '\\Tests');
// add core package main config
if (\substr_compare($targetFilePath, 'configured_rule.php', -\strlen('configured_rule.php')) === 0) {
$rectorConfigLine = 'return static function (RectorConfig $rectorConfig): void {';
$content = \str_replace($rectorConfigLine, $rectorConfigLine . \PHP_EOL . ' $rectorConfig->import(__DIR__ . \'/../../../../../config/config.php\');' . \PHP_EOL, $content);
}
}
$this->smartFileSystem->dumpFile($targetFilePath, $content);
return $targetFilePath;
}
}

View File

@ -1,64 +0,0 @@
<?php
declare (strict_types=1);
namespace Rector\RectorGenerator\Generator;
use Rector\RectorGenerator\Finder\TemplateFinder;
use Rector\RectorGenerator\Guard\OverrideGuard;
use Rector\RectorGenerator\TemplateVariablesFactory;
use Rector\RectorGenerator\ValueObject\RectorRecipe;
use RectorPrefix202208\Symfony\Component\Console\Style\SymfonyStyle;
/**
* @see \Rector\RectorGenerator\Tests\RectorGenerator\RectorGeneratorTest
*/
final class RectorGenerator
{
/**
* @readonly
* @var \Rector\RectorGenerator\Finder\TemplateFinder
*/
private $templateFinder;
/**
* @readonly
* @var \Rector\RectorGenerator\TemplateVariablesFactory
*/
private $templateVariablesFactory;
/**
* @readonly
* @var \Rector\RectorGenerator\Generator\FileGenerator
*/
private $fileGenerator;
/**
* @readonly
* @var \Rector\RectorGenerator\Guard\OverrideGuard
*/
private $overrideGuard;
/**
* @readonly
* @var \Symfony\Component\Console\Style\SymfonyStyle
*/
private $symfonyStyle;
public function __construct(TemplateFinder $templateFinder, TemplateVariablesFactory $templateVariablesFactory, \Rector\RectorGenerator\Generator\FileGenerator $fileGenerator, OverrideGuard $overrideGuard, SymfonyStyle $symfonyStyle)
{
$this->templateFinder = $templateFinder;
$this->templateVariablesFactory = $templateVariablesFactory;
$this->fileGenerator = $fileGenerator;
$this->overrideGuard = $overrideGuard;
$this->symfonyStyle = $symfonyStyle;
}
/**
* @return string[]
*/
public function generate(RectorRecipe $rectorRecipe, string $destinationDirectory) : array
{
// generate and compare
$templateFileInfos = $this->templateFinder->find($rectorRecipe);
$templateVariables = $this->templateVariablesFactory->createFromRectorRecipe($rectorRecipe);
$isUnwantedOverride = $this->overrideGuard->isUnwantedOverride($templateFileInfos, $templateVariables, $rectorRecipe, $destinationDirectory);
if ($isUnwantedOverride) {
$this->symfonyStyle->warning('No files were changed');
return [];
}
return $this->fileGenerator->generateFiles($templateFileInfos, $templateVariables, $rectorRecipe, $destinationDirectory);
}
}

View File

@ -1,50 +0,0 @@
<?php
declare (strict_types=1);
namespace Rector\RectorGenerator\Guard;
use Rector\RectorGenerator\FileSystem\TemplateFileSystem;
use Rector\RectorGenerator\ValueObject\RectorRecipe;
use RectorPrefix202208\Symfony\Component\Console\Style\SymfonyStyle;
use Symplify\SmartFileSystem\SmartFileInfo;
final class OverrideGuard
{
/**
* @readonly
* @var \Symfony\Component\Console\Style\SymfonyStyle
*/
private $symfonyStyle;
/**
* @readonly
* @var \Rector\RectorGenerator\FileSystem\TemplateFileSystem
*/
private $templateFileSystem;
public function __construct(SymfonyStyle $symfonyStyle, TemplateFileSystem $templateFileSystem)
{
$this->symfonyStyle = $symfonyStyle;
$this->templateFileSystem = $templateFileSystem;
}
/**
* @param array<string, mixed> $templateVariables
* @param SmartFileInfo[] $templateFileInfos
*/
public function isUnwantedOverride(array $templateFileInfos, array $templateVariables, RectorRecipe $rectorRecipe, string $targetDirectory) : bool
{
$message = \sprintf('Files for "%s" rule already exist. Should we override them?', $rectorRecipe->getName());
foreach ($templateFileInfos as $templateFileInfo) {
if (!$this->doesFileInfoAlreadyExist($templateVariables, $rectorRecipe, $templateFileInfo, $targetDirectory)) {
continue;
}
return !$this->symfonyStyle->confirm($message);
}
return \false;
}
/**
* @param array<string, string> $templateVariables
*/
private function doesFileInfoAlreadyExist(array $templateVariables, RectorRecipe $rectorRecipe, SmartFileInfo $templateFileInfo, string $targetDirectory) : bool
{
$destination = $this->templateFileSystem->resolveDestination($templateFileInfo, $templateVariables, $rectorRecipe, $targetDirectory);
return \file_exists($destination);
}
}

View File

@ -1,33 +0,0 @@
<?php
declare (strict_types=1);
namespace Rector\RectorGenerator\NodeFactory;
use PhpParser\Node\Expr\Array_;
use PhpParser\Node\Stmt\Property;
final class ConfigurationNodeFactory
{
/**
* @readonly
* @var \Rector\RectorGenerator\NodeFactory\NodeFactory
*/
private $nodeFactory;
public function __construct(\Rector\RectorGenerator\NodeFactory\NodeFactory $nodeFactory)
{
$this->nodeFactory = $nodeFactory;
}
/**
* @param array<string, mixed> $ruleConfiguration
* @return Property[]
*/
public function createProperties(array $ruleConfiguration) : array
{
$properties = [];
foreach (\array_keys($ruleConfiguration) as $privatePropertyName) {
$property = $this->nodeFactory->createPrivateArrayProperty($privatePropertyName);
$property->props[0]->default = new Array_([]);
$properties[] = $property;
}
return $properties;
}
}

View File

@ -1,48 +0,0 @@
<?php
declare (strict_types=1);
namespace Rector\RectorGenerator\NodeFactory;
use PhpParser\Comment\Doc;
use PhpParser\Node\Expr\Variable;
use PhpParser\Node\Identifier;
use PhpParser\Node\Param;
use PhpParser\Node\Stmt\ClassMethod;
use PhpParser\Node\Stmt\Expression;
final class ConfigureClassMethodFactory
{
/**
* @readonly
* @var \Rector\RectorGenerator\NodeFactory\NodeFactory
*/
private $nodeFactory;
public function __construct(\Rector\RectorGenerator\NodeFactory\NodeFactory $nodeFactory)
{
$this->nodeFactory = $nodeFactory;
}
/**
* @param array<string, mixed> $ruleConfiguration
*/
public function create(array $ruleConfiguration) : ClassMethod
{
$classMethod = $this->nodeFactory->createPublicMethod('configure');
$classMethod->returnType = new Identifier('void');
$configurationVariable = new Variable('configuration');
$configurationParam = new Param($configurationVariable);
$configurationParam->type = new Identifier('array');
$classMethod->params[] = $configurationParam;
$assigns = [];
foreach (\array_keys($ruleConfiguration) as $propertyName) {
$assign = $this->nodeFactory->createPropertyAssign($propertyName, $configurationVariable);
$assigns[] = new Expression($assign);
}
$classMethod->stmts = $assigns;
$paramDoc = <<<'CODE_SAMPLE'
/**
* @param mixed[] $configuration
*/
CODE_SAMPLE;
$classMethod->setDocComment(new Doc($paramDoc));
return $classMethod;
}
}

View File

@ -1,64 +0,0 @@
<?php
declare (strict_types=1);
namespace Rector\RectorGenerator\NodeFactory;
use PhpParser\Builder\Method;
use PhpParser\BuilderHelpers;
use PhpParser\Node\Expr;
use PhpParser\Node\Expr\Array_;
use PhpParser\Node\Expr\ArrayItem;
use PhpParser\Node\Expr\Assign;
use PhpParser\Node\Expr\ClassConstFetch;
use PhpParser\Node\Expr\PropertyFetch;
use PhpParser\Node\Expr\Variable;
use PhpParser\Node\Name\FullyQualified;
use PhpParser\Node\Stmt\ClassMethod;
use PhpParser\Node\Stmt\Property;
final class NodeFactory
{
/**
* @param array<string|int, mixed> $values
*/
public function createArray(array $values) : Array_
{
$arrayItems = [];
foreach ($values as $key => $value) {
// natural key, no need for value
if (\is_int($key)) {
$arrayItems[] = new ArrayItem(BuilderHelpers::normalizeValue($value));
} else {
$arrayItems[] = new ArrayItem(BuilderHelpers::normalizeValue($value), BuilderHelpers::normalizeValue($key));
}
}
return new Array_($arrayItems);
}
public function createClassConstReference(string $class) : ClassConstFetch
{
$fullyQualified = new FullyQualified($class);
return new ClassConstFetch($fullyQualified, 'class');
}
public function createPropertyAssign(string $propertyName, Expr $expr) : Assign
{
$propertyFetch = new PropertyFetch(new Variable('this'), $propertyName);
return new Assign($propertyFetch, $expr);
}
public function createPublicMethod(string $methodName) : ClassMethod
{
$methodBuilder = new Method($methodName);
$methodBuilder->makePublic();
return $methodBuilder->getNode();
}
public function createPrivateArrayProperty(string $propertyName) : Property
{
$propertyBuilder = new \PhpParser\Builder\Property($propertyName);
$propertyBuilder->makePrivate();
$docContent = <<<'CODE_SAMPLE'
/**
* @var mixed[]
*/
CODE_SAMPLE;
$propertyBuilder->setDocComment($docContent);
return $propertyBuilder->getNode();
}
}

View File

@ -1,46 +0,0 @@
<?php
declare (strict_types=1);
namespace Rector\RectorGenerator\Provider;
use Rector\RectorGenerator\Exception\ConfigurationException;
use Rector\RectorGenerator\ValueObject\Option;
use Rector\RectorGenerator\ValueObject\RectorRecipe;
final class RectorRecipeProvider
{
/**
* @var \Rector\RectorGenerator\ValueObject\RectorRecipe|null
*/
private $rectorRecipe = null;
/**
* Configure in the rector-recipe.php config
*
* @param array<Option::*, mixed> $rectorRecipeConfiguration
*/
public function __construct(array $rectorRecipeConfiguration = [])
{
// no configuration provided - due to autowiring
if ($rectorRecipeConfiguration === []) {
return;
}
$rectorRecipe = new RectorRecipe($rectorRecipeConfiguration[Option::PACKAGE], $rectorRecipeConfiguration[Option::NAME], $rectorRecipeConfiguration[Option::NODE_TYPES], $rectorRecipeConfiguration[Option::DESCRIPTION], $rectorRecipeConfiguration[Option::CODE_BEFORE], $rectorRecipeConfiguration[Option::CODE_AFTER]);
// optional parameters
if (isset($rectorRecipeConfiguration[Option::CONFIGURATION])) {
$rectorRecipe->setConfiguration($rectorRecipeConfiguration[Option::CONFIGURATION]);
}
if (isset($rectorRecipeConfiguration[Option::RESOURCES])) {
$rectorRecipe->setResources($rectorRecipeConfiguration[Option::RESOURCES]);
}
if (isset($rectorRecipeConfiguration[Option::SET_FILE_PATH])) {
$rectorRecipe->setSetFilePath($rectorRecipeConfiguration[Option::SET_FILE_PATH]);
}
$this->rectorRecipe = $rectorRecipe;
}
public function provide() : RectorRecipe
{
if (!$this->rectorRecipe instanceof RectorRecipe) {
throw new ConfigurationException('Make sure the "rector-recipe.php" config file is imported and parameter set. Are you sure its in your main config?');
}
return $this->rectorRecipe;
}
}

View File

@ -1,17 +0,0 @@
<?php
declare (strict_types=1);
namespace Rector\RectorGenerator;
final class TemplateFactory
{
/**
* @param array<string, string> $variables
*/
public function create(string $content, array $variables) : string
{
$variableKeys = \array_keys($variables);
$variableValues = \array_values($variables);
return \str_replace($variableKeys, $variableValues, $content);
}
}

View File

@ -1,46 +0,0 @@
<?php
declare (strict_types=1);
namespace Rector\RectorGenerator;
use RectorPrefix202208\Symfony\Component\Console\Style\SymfonyStyle;
use RectorPrefix202208\Symplify\SmartFileSystem\FileSystemGuard;
use RectorPrefix202208\Symplify\SmartFileSystem\SmartFileSystem;
final class TemplateInitializer
{
/**
* @readonly
* @var \Symfony\Component\Console\Style\SymfonyStyle
*/
private $symfonyStyle;
/**
* @readonly
* @var \Symplify\SmartFileSystem\SmartFileSystem
*/
private $smartFileSystem;
/**
* @readonly
* @var \Symplify\SmartFileSystem\FileSystemGuard
*/
private $fileSystemGuard;
public function __construct(SymfonyStyle $symfonyStyle, SmartFileSystem $smartFileSystem, FileSystemGuard $fileSystemGuard)
{
$this->symfonyStyle = $symfonyStyle;
$this->smartFileSystem = $smartFileSystem;
$this->fileSystemGuard = $fileSystemGuard;
}
public function initialize(string $templateFilePath, string $rootFileName) : void
{
$this->fileSystemGuard->ensureFileExists($templateFilePath, __METHOD__);
$targetFilePath = \getcwd() . '/' . $rootFileName;
$doesFileExist = $this->smartFileSystem->exists($targetFilePath);
if ($doesFileExist) {
$message = \sprintf('Config file "%s" already exists', $rootFileName);
$this->symfonyStyle->warning($message);
} else {
$this->smartFileSystem->copy($templateFilePath, $targetFilePath);
$message = \sprintf('"%s" config file was added', $rootFileName);
$this->symfonyStyle->success($message);
}
}
}

View File

@ -1,142 +0,0 @@
<?php
declare (strict_types=1);
namespace Rector\RectorGenerator;
use PhpParser\BuilderHelpers;
use PhpParser\Node\Expr\Array_;
use PhpParser\Node\Expr\ArrayItem;
use PhpParser\PrettyPrinter\Standard;
use Rector\RectorGenerator\NodeFactory\ConfigurationNodeFactory;
use Rector\RectorGenerator\NodeFactory\ConfigureClassMethodFactory;
use Rector\RectorGenerator\NodeFactory\NodeFactory;
use Rector\RectorGenerator\ValueObject\Placeholder;
use Rector\RectorGenerator\ValueObject\RectorRecipe;
final class TemplateVariablesFactory
{
/**
* @readonly
* @var \PhpParser\PrettyPrinter\Standard
*/
private $standard;
/**
* @readonly
* @var \Rector\RectorGenerator\NodeFactory\ConfigurationNodeFactory
*/
private $configurationNodeFactory;
/**
* @readonly
* @var \Rector\RectorGenerator\NodeFactory\ConfigureClassMethodFactory
*/
private $configureClassMethodFactory;
/**
* @readonly
* @var \Rector\RectorGenerator\NodeFactory\NodeFactory
*/
private $nodeFactory;
public function __construct(Standard $standard, ConfigurationNodeFactory $configurationNodeFactory, ConfigureClassMethodFactory $configureClassMethodFactory, NodeFactory $nodeFactory)
{
$this->standard = $standard;
$this->configurationNodeFactory = $configurationNodeFactory;
$this->configureClassMethodFactory = $configureClassMethodFactory;
$this->nodeFactory = $nodeFactory;
}
/**
* @return array<string, mixed>
*/
public function createFromRectorRecipe(RectorRecipe $rectorRecipe) : array
{
$data = [Placeholder::PACKAGE => $rectorRecipe->getPackage(), Placeholder::CATEGORY => $rectorRecipe->getCategory(), Placeholder::DESCRIPTION => $rectorRecipe->getDescription(), Placeholder::NAME => $rectorRecipe->getName(), Placeholder::CODE_BEFORE => \trim($rectorRecipe->getCodeBefore()) . \PHP_EOL, Placeholder::CODE_BEFORE_EXAMPLE => $this->createCodeForDefinition($rectorRecipe->getCodeBefore()), Placeholder::CODE_AFTER => \trim($rectorRecipe->getCodeAfter()) . \PHP_EOL, Placeholder::CODE_AFTER_EXAMPLE => $this->createCodeForDefinition($rectorRecipe->getCodeAfter()), Placeholder::RESOURCES => $this->createSourceDocBlock($rectorRecipe->getResources())];
if ($rectorRecipe->getConfiguration() !== []) {
$configurationData = $this->createConfigurationData($rectorRecipe);
$data = \array_merge($data, $configurationData);
}
$data['__NodeTypesPhp__'] = $this->createNodeTypePhp($rectorRecipe);
$data['__NodeTypesDoc__'] = '\\' . \implode('|\\', $rectorRecipe->getNodeTypes());
return $data;
}
private function createCodeForDefinition(string $code) : string
{
if (\strpos($code, \PHP_EOL) !== \false) {
// multi lines
return \sprintf("<<<'CODE_SAMPLE'%s%s%sCODE_SAMPLE%s", \PHP_EOL, $code, \PHP_EOL, \PHP_EOL);
}
// single line
return "'" . \str_replace("'", '"', $code) . "'";
}
/**
* @param string[] $source
*/
private function createSourceDocBlock(array $source) : string
{
if ($source === []) {
return '';
}
$sourceAsString = '';
foreach ($source as $singleSource) {
$sourceAsString .= ' * @changelog ' . $singleSource . \PHP_EOL;
}
$sourceAsString .= ' *';
return \rtrim($sourceAsString);
}
/**
* @param array<string, mixed> $configuration
*/
private function createRuleConfiguration(array $configuration) : string
{
$arrayItems = [];
foreach ($configuration as $singleConfiguration) {
$singleConfiguration = BuilderHelpers::normalizeValue($singleConfiguration);
$arrayItems[] = new ArrayItem($singleConfiguration);
}
$array = new Array_($arrayItems);
return $this->standard->prettyPrintExpr($array);
}
/**
* @param array<string, mixed> $ruleConfiguration
*/
private function createConfigurationProperty(array $ruleConfiguration) : string
{
$properties = $this->configurationNodeFactory->createProperties($ruleConfiguration);
return $this->standard->prettyPrint($properties);
}
/**
* @param array<string, mixed> $ruleConfiguration
*/
private function createConfigureClassMethod(array $ruleConfiguration) : string
{
$classMethod = $this->configureClassMethodFactory->create($ruleConfiguration);
return $this->standard->prettyPrint([$classMethod]);
}
private function createNodeTypePhp(RectorRecipe $rectorRecipe) : string
{
$referencingClassConsts = [];
foreach ($rectorRecipe->getNodeTypes() as $nodeType) {
$referencingClassConsts[] = $this->nodeFactory->createClassConstReference($nodeType);
}
$array = $this->nodeFactory->createArray($referencingClassConsts);
return $this->standard->prettyPrintExpr($array);
}
/**
* @return array<string, mixed>
*/
private function createConfigurationData(RectorRecipe $rectorRecipe) : array
{
$configurationData = [];
$configurationData['__TestRuleConfiguration__'] = $this->createRuleConfiguration($rectorRecipe->getConfiguration());
$configurationData['__RuleConfiguration__'] = $this->createRuleConfiguration($rectorRecipe->getConfiguration());
$configurationData['__ConfigurationProperties__'] = $this->createConfigurationProperty($rectorRecipe->getConfiguration());
$configurationData['__ConfigureClassMethod__'] = $this->createConfigureClassMethod($rectorRecipe->getConfiguration());
$configurationData['__MainConfiguration__'] = $this->createMainConfiguration($rectorRecipe->getConfiguration());
return $configurationData;
}
/**
* @param array<string, mixed> $ruleConfiguration
*/
private function createMainConfiguration(array $ruleConfiguration) : string
{
$firstItem = \array_pop($ruleConfiguration);
$valueExpr = BuilderHelpers::normalizeValue($firstItem);
return $this->standard->prettyPrintExpr($valueExpr);
}
}

View File

@ -1,12 +0,0 @@
<?php
declare (strict_types=1);
namespace Rector\RectorGenerator\ValueObject;
final class NamePattern
{
/**
* @var string
*/
public const RECTOR_FQN_NAME_PATTERN = 'Rector\\__Package__\\Rector\\__Category__\\__Name__';
}

View File

@ -1,47 +0,0 @@
<?php
declare (strict_types=1);
namespace Rector\RectorGenerator\ValueObject;
/**
* @api
*/
final class Option
{
/**
* @var string
*/
public const PACKAGE = 'package';
/**
* @var string
*/
public const NAME = 'name';
/**
* @var string
*/
public const NODE_TYPES = 'node_types';
/**
* @var string
*/
public const DESCRIPTION = 'description';
/**
* @var string
*/
public const CODE_BEFORE = 'code_before';
/**
* @var string
*/
public const CODE_AFTER = 'code_after';
/**
* @var string
*/
public const CONFIGURATION = 'configuration';
/**
* @var string
*/
public const RESOURCES = 'resources';
/**
* @var string
*/
public const SET_FILE_PATH = 'set_file_path';
}

View File

@ -1,44 +0,0 @@
<?php
declare (strict_types=1);
namespace Rector\RectorGenerator\ValueObject;
final class Placeholder
{
/**
* @var string
*/
public const PACKAGE = '__Package__';
/**
* @var string
*/
public const CATEGORY = '__Category__';
/**
* @var string
*/
public const DESCRIPTION = '__Description__';
/**
* @var string
*/
public const NAME = '__Name__';
/**
* @var string
*/
public const CODE_BEFORE = '__CodeBefore__';
/**
* @var string
*/
public const CODE_BEFORE_EXAMPLE = '__CodeBeforeExample__';
/**
* @var string
*/
public const CODE_AFTER = '__CodeAfter__';
/**
* @var string
*/
public const CODE_AFTER_EXAMPLE = '__CodeAfterExample__';
/**
* @var string
*/
public const RESOURCES = '__Resources__';
}

View File

@ -1,15 +0,0 @@
<?php
declare (strict_types=1);
namespace Rector\RectorGenerator\ValueObject;
/**
* @api
*/
final class RectorGeneratorConfig
{
/**
* @var string
*/
public const FILE_PATH = __DIR__ . '/../../config/config.php';
}

View File

@ -1,250 +0,0 @@
<?php
declare (strict_types=1);
namespace Rector\RectorGenerator\ValueObject;
use RectorPrefix202208\Nette\Utils\Json;
use RectorPrefix202208\Nette\Utils\Strings;
use PhpParser\Node;
use PhpParser\Node\Expr\FuncCall;
use PHPStan\Node\ClassMethod;
use Rector\RectorGenerator\Exception\ConfigurationException;
use Rector\RectorGenerator\Exception\ShouldNotHappenException;
use RectorPrefix202208\Webmozart\Assert\Assert;
final class RectorRecipe
{
/**
* @var string
*/
private const PACKAGE_UTILS = 'Utils';
/**
* @var string|null
*/
private $name;
/**
* @var string|null
*/
private $codeBefore;
/**
* @var string|null
*/
private $codeAfter;
/**
* @var bool
*/
private $isRectorRepository = \false;
/**
* @var string|null
*/
private $category;
/**
* @var class-string[]
*/
private $nodeTypes = [];
/**
* @var string[]
*/
private $resources = [];
/**
* The key is a private property name that holds the configuration value (can be multiple properties)
*
* @var array<string, mixed[]>
*/
private $configuration = [];
/**
* Use default package name, if not overriden manually
* @var string
*/
private $package = self::PACKAGE_UTILS;
/**
* @var string|null
*/
private $setFilePath;
/**
* @var string
*/
private $description;
/**
* @param array<class-string<Node>> $nodeTypes
*/
public function __construct(string $package, string $name, array $nodeTypes, string $description, string $codeBefore, string $codeAfter)
{
$this->description = $description;
$this->isRectorRepository = $this->detectRectorRepository();
$this->setPackage($package);
$this->setName($name);
$this->setNodeTypes($nodeTypes);
if ($codeBefore === $codeAfter) {
throw new ConfigurationException('Code before and after are identical. They have to be different');
}
$this->setCodeBefore($codeBefore);
$this->setCodeAfter($codeAfter);
$this->resolveCategory($nodeTypes);
}
public function getPackage() : string
{
return $this->package;
}
public function getName() : string
{
return $this->name;
}
/**
* @return class-string[]
*/
public function getNodeTypes() : array
{
return $this->nodeTypes;
}
public function getDescription() : string
{
return $this->description;
}
public function getCodeBefore() : string
{
return $this->codeBefore;
}
public function getCodeAfter() : string
{
return $this->codeAfter;
}
/**
* @return string[]
*/
public function getResources() : array
{
return $this->resources;
}
public function setSetFilePath(string $setFilePath) : void
{
$this->setFilePath = $setFilePath;
}
public function getSetFilePath() : ?string
{
return $this->setFilePath;
}
/**
* @return array<string, mixed[]>
*/
public function getConfiguration() : array
{
return $this->configuration;
}
public function isRectorRepository() : bool
{
return $this->isRectorRepository;
}
public function getCategory() : string
{
return $this->category;
}
/**
* @api
* @param array<string, mixed[]> $configuration
*/
public function setConfiguration(array $configuration) : void
{
$this->configuration = $configuration;
}
/**
* @api
* @param string[] $resources
*/
public function setResources(array $resources) : void
{
$this->resources = \array_filter($resources);
}
/**
* For testing purposes
*
* @api
*/
public function setIsRectorRepository(bool $isRectorRepository) : void
{
$this->isRectorRepository = $isRectorRepository;
}
/**
* For tests
*
* @api
*/
public function setPackage(string $package) : void
{
if (\is_file($package)) {
$message = \sprintf('The "%s()" method only accepts package name, file path "%s" given', __METHOD__, $package);
throw new ShouldNotHappenException($message);
}
$this->package = $package;
}
private function setName(string $name) : void
{
if (\substr_compare($name, 'Rector', -\strlen('Rector')) !== 0) {
$message = \sprintf('Rector name "%s" must end with "Rector"', $name);
throw new ConfigurationException($message);
}
$this->name = $name;
}
/**
* @param class-string[] $nodeTypes
*/
private function setNodeTypes(array $nodeTypes) : void
{
foreach ($nodeTypes as $nodeType) {
// avoid phpstan class method that is never traversed
Assert::isNotA($nodeType, ClassMethod::class);
if (\is_a($nodeType, Node::class, \true)) {
continue;
}
$message = \sprintf('Node type "%s" does not exist, implement "%s" interface or is not imported in "rector-recipe.php"', $nodeType, Node::class);
throw new ShouldNotHappenException($message);
}
if (\count($nodeTypes) < 1) {
$message = \sprintf('"$nodeTypes" argument requires at least one item, e.g. "%s"', FuncCall::class);
throw new ConfigurationException($message);
}
$this->nodeTypes = $nodeTypes;
}
private function setCodeBefore(string $codeBefore) : void
{
$this->codeBefore = $this->normalizeCode($codeBefore);
}
private function setCodeAfter(string $codeAfter) : void
{
$this->codeAfter = $this->normalizeCode($codeAfter);
}
/**
* @param string[] $nodeTypes
*/
private function resolveCategory(array $nodeTypes) : void
{
$this->category = (string) Strings::after($nodeTypes[0], '\\', -1);
}
private function normalizeCode(string $code) : string
{
if (\strncmp($code, '<?php', \strlen('<?php')) === 0) {
$code = \ltrim($code, '<?php');
}
return \trim($code);
}
private function detectRectorRepository() : bool
{
$possibleComposerJsonFilePaths = [__DIR__ . '/../../../../../composer.json', __DIR__ . '/../../composer.json'];
foreach ($possibleComposerJsonFilePaths as $possibleComposerJsonFilePath) {
if (!\file_exists($possibleComposerJsonFilePath)) {
continue;
}
$composerJsonContent = \file_get_contents($possibleComposerJsonFilePath);
if ($composerJsonContent === \false) {
continue;
}
$composerJson = Json::decode($composerJsonContent, Json::FORCE_ARRAY);
if (!isset($composerJson['name'])) {
continue;
}
if (\strncmp((string) $composerJson['name'], 'rector/', \strlen('rector/')) === 0) {
return \true;
}
}
return \false;
}
}

View File

@ -1,50 +0,0 @@
<?php
declare (strict_types=1);
namespace RectorPrefix202208;
use PhpParser\Node\Expr\MethodCall;
use Rector\RectorGenerator\Provider\RectorRecipeProvider;
use Rector\RectorGenerator\ValueObject\Option;
use RectorPrefix202208\Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
// run "bin/rector generate" to a new Rector basic schema + tests from this config
return static function (ContainerConfigurator $containerConfigurator) : void {
$services = $containerConfigurator->services();
// [REQUIRED]
$rectorRecipeConfiguration = [
// [RECTOR CORE CONTRIBUTION - REQUIRED]
// package name, basically namespace part in `rules/<package>/src`, use PascalCase
Option::PACKAGE => 'Naming',
// name, basically short class name; use PascalCase
Option::NAME => 'RenameMethodCallRector',
// 1+ node types to change, pick from classes here https://github.com/nikic/PHP-Parser/tree/master/lib/PhpParser/Node
// the best practise is to have just 1 type here if possible, and make separated rule for other node types
Option::NODE_TYPES => [MethodCall::class],
// describe what the rule does
Option::DESCRIPTION => '"something()" will be renamed to "somethingElse()"',
// code before change
// this is used for documentation and first test fixture
Option::CODE_BEFORE => <<<'CODE_SAMPLE'
class SomeClass
{
public function run()
{
$this->something();
}
}
CODE_SAMPLE
,
// code after change
Option::CODE_AFTER => <<<'CODE_SAMPLE'
class SomeClass
{
public function run()
{
$this->somethingElse();
}
}
CODE_SAMPLE
,
];
$services->set(RectorRecipeProvider::class)->arg('$rectorRecipeConfiguration', $rectorRecipeConfiguration);
};

View File

@ -1,13 +0,0 @@
<?php
namespace Rector\Tests\__Package__\Rector\__Category__\__Name__\Fixture;
__CodeBefore__
?>
-----
<?php
namespace Rector\Tests\__Package__\Rector\__Category__\__Name__\Fixture;
__CodeAfter__
?>

View File

@ -1,31 +0,0 @@
<?php
declare(strict_types=1);
namespace Rector\Tests\__Package__\Rector\__Category__\__Name__;
use Rector\Testing\PHPUnit\AbstractRectorTestCase;
final class __Name__Test extends AbstractRectorTestCase
{
/**
* @dataProvider provideData()
*/
public function test(\Symplify\SmartFileSystem\SmartFileInfo $fileInfo): void
{
$this->doTestFileInfo($fileInfo);
}
/**
* @return \Iterator<\Symplify\SmartFileSystem\SmartFileInfo>
*/
public function provideData(): \Iterator
{
return $this->yieldFilesFromDirectory(__DIR__ . '/Fixture');
}
public function provideConfigFilePath(): string
{
return __DIR__ . '/config/configured_rule.php';
}
}

View File

@ -1,9 +0,0 @@
<?php
declare (strict_types=1);
namespace RectorPrefix202208;
use Rector\Config\RectorConfig;
return static function (RectorConfig $rectorConfig) : void {
$rectorConfig->ruleWithConfiguration(\Rector\__Package__\Rector\__Category__\__Name__::class, \RectorPrefix202208\__MainConfiguration__);
};

View File

@ -1,9 +0,0 @@
<?php
declare (strict_types=1);
namespace RectorPrefix202208;
use Rector\Config\RectorConfig;
return static function (RectorConfig $rectorConfig) : void {
$rectorConfig->rule(\Rector\__Package__\Rector\__Category__\__Name__::class);
};

View File

@ -1,51 +0,0 @@
<?php
declare(strict_types=1);
namespace Rector\__Package__\Rector\__Category__;
use PhpParser\Node;
use Rector\Core\Contract\Rector\ConfigurableRectorInterface;
use Rector\Core\Rector\AbstractRector;
use Symplify\RuleDocGenerator\ValueObject\CodeSample\ConfiguredCodeSample;
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
/**
__Resources__
* @see \Rector\Tests\__Package__\Rector\__Category__\__Name__\__Name__Test
*/
final class __Name__ extends AbstractRector implements ConfigurableRectorInterface
{
__ConfigurationProperties__
public function getRuleDefinition(): RuleDefinition
{
return new RuleDefinition('__Description__', [
new ConfiguredCodeSample(
__CodeBeforeExample__,
__CodeAfterExample__,
__RuleConfiguration__
)
]);
}
/**
* @return array<class-string<Node>>
*/
public function getNodeTypes(): array
{
return __NodeTypesPhp__;
}
/**
* @param __NodeTypesDoc__ $node
*/
public function refactor(Node $node): ?Node
{
// change the node
return $node;
}
__ConfigureClassMethod__
}

View File

@ -1,35 +0,0 @@
<?php
declare (strict_types=1);
namespace Rector\__Package__\Rector\__Category__;
use PhpParser\Node;
use Rector\Core\Rector\AbstractRector;
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
/**
__Resources__
* @see \Rector\Tests\__Package__\Rector\__Category__\__Name__\__Name__Test
*/
final class __Name__ extends AbstractRector
{
public function getRuleDefinition() : RuleDefinition
{
return new RuleDefinition('__Description__', [new CodeSample(__CodeBeforeExample__, __CodeAfterExample__)]);
}
/**
* @return array<class-string<Node>>
*/
public function getNodeTypes() : array
{
return __NodeTypesPhp__;
}
/**
* @param __NodeTypesDoc__ $node
*/
public function refactor(Node $node) : ?Node
{
// change the node
return $node;
}
}

View File

@ -7,8 +7,8 @@ use PhpParser\Node;
use PhpParser\Node\Expr\MethodCall;
use PhpParser\Node\Expr\StaticCall;
use PhpParser\Node\Stmt\ClassMethod;
use PhpParser\PrettyPrinter\Standard;
use PHPStan\Type\TypeWithClassName;
use Rector\Core\Contract\PhpParser\NodePrinterInterface;
use Rector\Core\PhpParser\AstResolver;
use Rector\Core\PhpParser\Node\BetterNodeFinder;
use Rector\NodeNameResolver\NodeNameResolver;
@ -36,9 +36,9 @@ final class AssertCallAnalyzer
private $astResolver;
/**
* @readonly
* @var \PhpParser\PrettyPrinter\Standard
* @var \Rector\Core\Contract\PhpParser\NodePrinterInterface
*/
private $printerStandard;
private $nodePrinter;
/**
* @readonly
* @var \Rector\Core\PhpParser\Node\BetterNodeFinder
@ -54,10 +54,10 @@ final class AssertCallAnalyzer
* @var \Rector\NodeTypeResolver\NodeTypeResolver
*/
private $nodeTypeResolver;
public function __construct(AstResolver $astResolver, Standard $printerStandard, BetterNodeFinder $betterNodeFinder, NodeNameResolver $nodeNameResolver, NodeTypeResolver $nodeTypeResolver)
public function __construct(AstResolver $astResolver, NodePrinterInterface $nodePrinter, BetterNodeFinder $betterNodeFinder, NodeNameResolver $nodeNameResolver, NodeTypeResolver $nodeTypeResolver)
{
$this->astResolver = $astResolver;
$this->printerStandard = $printerStandard;
$this->nodePrinter = $nodePrinter;
$this->betterNodeFinder = $betterNodeFinder;
$this->nodeNameResolver = $nodeNameResolver;
$this->nodeTypeResolver = $nodeTypeResolver;
@ -73,7 +73,7 @@ final class AssertCallAnalyzer
if ($this->classMethodNestingLevel > self::MAX_NESTED_METHOD_CALL_LEVEL) {
return \false;
}
$cacheHash = \md5($this->printerStandard->prettyPrint([$classMethod]));
$cacheHash = \md5($this->nodePrinter->prettyPrint([$classMethod]));
if (isset($this->containsAssertCallByClassMethod[$cacheHash])) {
return $this->containsAssertCallByClassMethod[$cacheHash];
}