mirror of
https://github.com/rectorphp/rector.git
synced 2024-06-04 18:30:50 +00:00
[DX] Add init-recipe command to create recipe config in root (#4789)
* [DX] Add init-recipe command to initlaize recipe * update docs
This commit is contained in:
parent
e627304df9
commit
f672eace0e
2
.github/workflows/code_analysis_no_dev.yaml
vendored
2
.github/workflows/code_analysis_no_dev.yaml
vendored
|
@ -12,7 +12,7 @@ jobs:
|
||||||
-
|
-
|
||||||
name: 'Rector Recipe'
|
name: 'Rector Recipe'
|
||||||
run: |
|
run: |
|
||||||
cp rector-recipe.php.dist rector-recipe.php
|
bin/rector init-recipe --ansi
|
||||||
bin/rector generate --ansi
|
bin/rector generate --ansi
|
||||||
|
|
||||||
name: ${{ matrix.actions.name }}
|
name: ${{ matrix.actions.name }}
|
||||||
|
|
|
@ -11,8 +11,14 @@ Don't worry, also generates a test case, which is required to contribute.
|
||||||
|
|
||||||
## How to Generate Rector rule in 3 steps?
|
## How to Generate Rector rule in 3 steps?
|
||||||
|
|
||||||
1. Copy [`rector-recipe.php.dist`](/rector-recipe.php.dist) to `rector-recipe.php`
|
1. Initialize `rector-recipe.php` config
|
||||||
2. Change parameters in `rector-recipe.php` to meet you need
|
|
||||||
|
```bash
|
||||||
|
vendor/bin/rector init-recipe
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Complete parameters in `rector-recipe.php` to design your new rule
|
||||||
|
|
||||||
3. Run command
|
3. Run command
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
|
41
packages/rector-generator/src/Command/InitRecipeCommand.php
Normal file
41
packages/rector-generator/src/Command/InitRecipeCommand.php
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Rector\RectorGenerator\Command;
|
||||||
|
|
||||||
|
use Rector\RectorGenerator\TemplateInitializer;
|
||||||
|
use Symfony\Component\Console\Command\Command;
|
||||||
|
use Symfony\Component\Console\Input\InputInterface;
|
||||||
|
use Symfony\Component\Console\Output\OutputInterface;
|
||||||
|
use Symplify\PackageBuilder\Console\ShellCode;
|
||||||
|
|
||||||
|
final class InitRecipeCommand extends Command
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var TemplateInitializer
|
||||||
|
*/
|
||||||
|
private $templateInitializer;
|
||||||
|
|
||||||
|
public function __construct(TemplateInitializer $templateInitializer)
|
||||||
|
{
|
||||||
|
parent::__construct();
|
||||||
|
|
||||||
|
$this->templateInitializer = $templateInitializer;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function configure(): void
|
||||||
|
{
|
||||||
|
$this->setDescription('[DEV] Initialize "rector-recipe.php" config');
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function execute(InputInterface $input, OutputInterface $output): int
|
||||||
|
{
|
||||||
|
$this->templateInitializer->initialize(
|
||||||
|
__DIR__ . '/../../../../templates/rector-recipe.php.dist',
|
||||||
|
'rector-recipe.php'
|
||||||
|
);
|
||||||
|
|
||||||
|
return ShellCode::SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
54
packages/rector-generator/src/TemplateInitializer.php
Normal file
54
packages/rector-generator/src/TemplateInitializer.php
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Rector\RectorGenerator;
|
||||||
|
|
||||||
|
use Symfony\Component\Console\Style\SymfonyStyle;
|
||||||
|
use Symplify\SmartFileSystem\FileSystemGuard;
|
||||||
|
use Symplify\SmartFileSystem\SmartFileSystem;
|
||||||
|
|
||||||
|
final class TemplateInitializer
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var SymfonyStyle
|
||||||
|
*/
|
||||||
|
private $symfonyStyle;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var SmartFileSystem
|
||||||
|
*/
|
||||||
|
private $smartFileSystem;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -12,7 +12,6 @@ use PhpParser\Node\Expr\Variable;
|
||||||
use PhpParser\Node\Name;
|
use PhpParser\Node\Name;
|
||||||
use PhpParser\Node\Param;
|
use PhpParser\Node\Param;
|
||||||
use Rector\Core\Rector\AbstractRector;
|
use Rector\Core\Rector\AbstractRector;
|
||||||
use Rector\Core\ValueObject\PhpVersionFeature;
|
|
||||||
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
|
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
|
||||||
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
|
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
|
||||||
|
|
||||||
|
|
|
@ -4,30 +4,23 @@ declare(strict_types=1);
|
||||||
|
|
||||||
namespace Rector\Core\Console\Command;
|
namespace Rector\Core\Console\Command;
|
||||||
|
|
||||||
|
use Rector\RectorGenerator\TemplateInitializer;
|
||||||
use Symfony\Component\Console\Input\InputInterface;
|
use Symfony\Component\Console\Input\InputInterface;
|
||||||
use Symfony\Component\Console\Output\OutputInterface;
|
use Symfony\Component\Console\Output\OutputInterface;
|
||||||
use Symfony\Component\Console\Style\SymfonyStyle;
|
|
||||||
use Symplify\PackageBuilder\Console\ShellCode;
|
use Symplify\PackageBuilder\Console\ShellCode;
|
||||||
use Symplify\SmartFileSystem\SmartFileSystem;
|
|
||||||
|
|
||||||
final class InitCommand extends AbstractCommand
|
final class InitCommand extends AbstractCommand
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @var SmartFileSystem
|
* @var TemplateInitializer
|
||||||
*/
|
*/
|
||||||
private $smartFileSystem;
|
private $templateInitializer;
|
||||||
|
|
||||||
/**
|
public function __construct(TemplateInitializer $templateInitializer)
|
||||||
* @var SymfonyStyle
|
|
||||||
*/
|
|
||||||
private $symfonyStyle;
|
|
||||||
|
|
||||||
public function __construct(SmartFileSystem $smartFileSystem, SymfonyStyle $symfonyStyle)
|
|
||||||
{
|
{
|
||||||
parent::__construct();
|
parent::__construct();
|
||||||
|
|
||||||
$this->smartFileSystem = $smartFileSystem;
|
$this->templateInitializer = $templateInitializer;
|
||||||
$this->symfonyStyle = $symfonyStyle;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function configure(): void
|
protected function configure(): void
|
||||||
|
@ -37,14 +30,7 @@ final class InitCommand extends AbstractCommand
|
||||||
|
|
||||||
protected function execute(InputInterface $input, OutputInterface $output): int
|
protected function execute(InputInterface $input, OutputInterface $output): int
|
||||||
{
|
{
|
||||||
$rectorConfigFiles = $this->smartFileSystem->exists(getcwd() . '/rector.php');
|
$this->templateInitializer->initialize(__DIR__ . '/../../../templates/rector.php.dist', 'rector.php');
|
||||||
|
|
||||||
if (! $rectorConfigFiles) {
|
|
||||||
$this->smartFileSystem->copy(__DIR__ . '/../../../templates/rector.php.dist', getcwd() . '/rector.php');
|
|
||||||
$this->symfonyStyle->success('"rector.php" config file has been generated successfully!');
|
|
||||||
} else {
|
|
||||||
$this->symfonyStyle->error('Config file not generated. A "rector.php" configuration file already exists');
|
|
||||||
}
|
|
||||||
|
|
||||||
return ShellCode::SUCCESS;
|
return ShellCode::SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace Rector\RuleDocGenerator\Category;
|
namespace Rector\RuleDocGenerator\Category;
|
||||||
|
@ -14,16 +15,21 @@ final class RectorCategoryInferer implements CategoryInfererInterface
|
||||||
* @see https://regex101.com/r/wyW01F/1
|
* @see https://regex101.com/r/wyW01F/1
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
private const RECTOR_CATEGORY_REGEX = '#Rector\\\\(?<category>\w+)\\\\#';
|
private const RECTOR_CATEGORY_REGEX = '#Rector\\\\(?<' . self::CATEGORY . '>\w+)\\\\#';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private const CATEGORY = 'category';
|
||||||
|
|
||||||
public function infer(RuleDefinition $ruleDefinition): ?string
|
public function infer(RuleDefinition $ruleDefinition): ?string
|
||||||
{
|
{
|
||||||
$matches = Strings::match($ruleDefinition->getRuleClass(), self::RECTOR_CATEGORY_REGEX);
|
$matches = Strings::match($ruleDefinition->getRuleClass(), self::RECTOR_CATEGORY_REGEX);
|
||||||
if (! isset($matches['category'])) {
|
if (! isset($matches[self::CATEGORY])) {
|
||||||
$message = sprintf('Category for "%s" could not be resolved', $ruleDefinition->getRuleClass());
|
$message = sprintf('Category for "%s" could not be resolved', $ruleDefinition->getRuleClass());
|
||||||
throw new ShouldNotHappenException($message);
|
throw new ShouldNotHappenException($message);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $matches['category'];
|
return $matches[self::CATEGORY];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user