mirror of
https://github.com/rectorphp/rector.git
synced 2024-05-28 23:10:51 +00:00
[DOCS] Switch DumpRectorCommand from console to string printer (#4281)
* monorepob-builder: add v prefix * monorepob-builder: add v prefix * bump symplify * decouple SymfonyConsole from DumpRectorCommand * moving to migrify php-config-printer * regenerate docs * include rules oerview
This commit is contained in:
parent
0ebf4df558
commit
70bf2ea830
|
@ -15,7 +15,8 @@
|
|||
"composer/xdebug-handler": "^1.4",
|
||||
"doctrine/annotations": "^1.10.4",
|
||||
"doctrine/inflector": "^1.4|^2.0",
|
||||
"migrify/php-config-printer": "^0.3.31",
|
||||
"jean85/pretty-package-versions": "^1.5.1",
|
||||
"migrify/php-config-printer": "^0.3.44",
|
||||
"nette/robot-loader": "^3.2",
|
||||
"nette/utils": "^3.1",
|
||||
"nikic/php-parser": "4.10.1",
|
||||
|
@ -37,8 +38,7 @@
|
|||
"symplify/set-config-resolver": "^8.3.17",
|
||||
"symplify/smart-file-system": "^8.3.17",
|
||||
"tracy/tracy": "^2.7",
|
||||
"webmozart/assert": "^1.8",
|
||||
"jean85/pretty-package-versions": "^1.5.1"
|
||||
"webmozart/assert": "^1.8"
|
||||
},
|
||||
"require-dev": {
|
||||
"friendsofphp/php-cs-fixer": "^2.16",
|
||||
|
@ -285,11 +285,11 @@
|
|||
],
|
||||
"check-cs": [
|
||||
"vendor/bin/ecs check --ansi",
|
||||
"vendor/bin/ecs check-markdown README.md --ansi"
|
||||
"vendor/bin/ecs check-markdown README.md docs/rector_rules_overview.md --ansi"
|
||||
],
|
||||
"fix-cs": [
|
||||
"vendor/bin/ecs check --fix --ansi",
|
||||
"vendor/bin/ecs check-markdown README.md --fix --ansi"
|
||||
"vendor/bin/ecs check-markdown README.md docs/rector_rules_overview.md --fix --ansi"
|
||||
],
|
||||
"phpstan": [
|
||||
"vendor/bin/phpstan analyse --ansi --error-format symplify",
|
||||
|
@ -304,7 +304,7 @@
|
|||
"vendor/bin/changelog-linker cleanup --ansi"
|
||||
],
|
||||
"docs": [
|
||||
"bin/rector dump-rectors > docs/rector_rules_overview.md",
|
||||
"bin/rector dump-rectors --output-file docs/rector_rules_overview.md --ansi",
|
||||
"bin/rector dump-nodes > docs/nodes_overview.md"
|
||||
],
|
||||
"rector-ci": "bin/rector process --config rector-ci.php --dry-run --ansi",
|
||||
|
|
|
@ -215,6 +215,7 @@ fn() => 1
|
|||
* `$params` - `/** @var Node\Param[] */`
|
||||
* `$returnType` - `/** @var null|Node\Identifier|Node\Name|Node\NullableType|Node\UnionType */`
|
||||
* `$expr` - `/** @var Expr */`
|
||||
* `$attrGroups` - `/** @var Node\AttributeGroup[] */`
|
||||
|
||||
<br>
|
||||
|
||||
|
@ -2219,13 +2220,13 @@ use PhpParser\Node\Expr\Variable;
|
|||
|
||||
$variable = new Variable('variableName');
|
||||
|
||||
return new Include_($variable, Include_::TYPE_REQUIRE_ONCE);
|
||||
return new Include_($variable, Include_::TYPE_INCLUDE);
|
||||
```
|
||||
|
||||
↓
|
||||
|
||||
```php
|
||||
require_once $variableName
|
||||
include $variableName
|
||||
```
|
||||
|
||||
<br>
|
||||
|
@ -2240,13 +2241,13 @@ use PhpParser\Node\Expr\Variable;
|
|||
|
||||
$variable = new Variable('variableName');
|
||||
|
||||
return new Include_($variable, Include_::TYPE_INCLUDE);
|
||||
return new Include_($variable, Include_::TYPE_REQUIRE_ONCE);
|
||||
```
|
||||
|
||||
↓
|
||||
|
||||
```php
|
||||
include $variableName
|
||||
require_once $variableName
|
||||
```
|
||||
|
||||
<br>
|
||||
|
@ -2480,27 +2481,6 @@ $someObject->methodName('yes', 'maybe')
|
|||
|
||||
declare(strict_types=1);
|
||||
|
||||
use PhpParser\Node\Expr\New_;
|
||||
use PhpParser\Node\Name;
|
||||
|
||||
$class = new Name('SomeClass');
|
||||
|
||||
return new New_($class);
|
||||
```
|
||||
|
||||
↓
|
||||
|
||||
```php
|
||||
new SomeClass()
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
// anonymous class
|
||||
|
||||
use PhpParser\Node\Expr\New_;
|
||||
|
@ -2521,6 +2501,27 @@ new class
|
|||
|
||||
<br>
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use PhpParser\Node\Expr\New_;
|
||||
use PhpParser\Node\Name;
|
||||
|
||||
$class = new Name('SomeClass');
|
||||
|
||||
return new New_($class);
|
||||
```
|
||||
|
||||
↓
|
||||
|
||||
```php
|
||||
new SomeClass()
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
|
||||
### Public Properties
|
||||
|
||||
|
@ -3324,6 +3325,7 @@ $variableName
|
|||
* `$var` - `/** @var Expr\Variable|Expr\Error Parameter variable */`
|
||||
* `$default` - `/** @var null|Expr Default value */`
|
||||
* `$flags` - `/** @var int */`
|
||||
* `$attrGroups` - `/** @var AttributeGroup[] PHP attribute groups */`
|
||||
|
||||
<br>
|
||||
|
||||
|
@ -3586,6 +3588,7 @@ public const SOME_CLASS_CONSTANT = 'default value';
|
|||
|
||||
* `$flags` - `/** @var int Modifiers */`
|
||||
* `$consts` - `/** @var Node\Const_[] Constant declarations */`
|
||||
* `$attrGroups` - `/** @var Node\AttributeGroup[] */`
|
||||
|
||||
<br>
|
||||
|
||||
|
@ -3658,6 +3661,7 @@ private function methodName($paramName): string
|
|||
* `$params` - `/** @var Node\Param[] Parameters */`
|
||||
* `$returnType` - `/** @var null|Node\Identifier|Node\Name|Node\NullableType|Node\UnionType Return type */`
|
||||
* `$stmts` - `/** @var Node\Stmt[]|null Statements */`
|
||||
* `$attrGroups` - `/** @var Node\AttributeGroup[] PHP attribute groups */`
|
||||
* `$magicNames` - ``
|
||||
|
||||
<br>
|
||||
|
@ -3672,6 +3676,26 @@ private function methodName($paramName): string
|
|||
|
||||
declare(strict_types=1);
|
||||
|
||||
use PhpParser\Node\Stmt\Class_;
|
||||
|
||||
return new Class_('ClassName');
|
||||
```
|
||||
|
||||
↓
|
||||
|
||||
```php
|
||||
class ClassName
|
||||
{
|
||||
}
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use PhpParser\Node\Name\FullyQualified;
|
||||
use PhpParser\Node\Stmt\Class_;
|
||||
|
||||
|
@ -3693,26 +3717,6 @@ final class ClassName extends \ParentClass
|
|||
|
||||
<br>
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use PhpParser\Node\Stmt\Class_;
|
||||
|
||||
return new Class_('ClassName');
|
||||
```
|
||||
|
||||
↓
|
||||
|
||||
```php
|
||||
class ClassName
|
||||
{
|
||||
}
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
|
||||
### Public Properties
|
||||
|
||||
|
@ -3721,6 +3725,7 @@ class ClassName
|
|||
* `$implements` - `/** @var Node\Name[] Names of implemented interfaces */`
|
||||
* `$name` - `/** @var Node\Identifier|null Name */`
|
||||
* `$stmts` - `/** @var Node\Stmt[] Statements */`
|
||||
* `$attrGroups` - `/** @var Node\AttributeGroup[] PHP attribute groups */`
|
||||
|
||||
<br>
|
||||
|
||||
|
@ -4005,6 +4010,7 @@ function some_function()
|
|||
* `$params` - `/** @var Node\Param[] Parameters */`
|
||||
* `$returnType` - `/** @var null|Node\Identifier|Node\Name|Node\NullableType|Node\UnionType Return type */`
|
||||
* `$stmts` - `/** @var Node\Stmt[] Statements */`
|
||||
* `$attrGroups` - `/** @var Node\AttributeGroup[] PHP attribute groups */`
|
||||
|
||||
<br>
|
||||
|
||||
|
@ -4238,6 +4244,7 @@ interface InterfaceName
|
|||
* `$extends` - `/** @var Node\Name[] Extended interfaces */`
|
||||
* `$name` - `/** @var Node\Identifier|null Name */`
|
||||
* `$stmts` - `/** @var Node\Stmt[] Statements */`
|
||||
* `$attrGroups` - `/** @var Node\AttributeGroup[] PHP attribute groups */`
|
||||
|
||||
<br>
|
||||
|
||||
|
@ -4350,6 +4357,7 @@ public static $firstProperty, $secondProperty;
|
|||
* `$flags` - `/** @var int Modifiers */`
|
||||
* `$props` - `/** @var PropertyProperty[] Properties */`
|
||||
* `$type` - `/** @var null|Identifier|Name|NullableType|UnionType Type declaration */`
|
||||
* `$attrGroups` - `/** @var Node\AttributeGroup[] PHP attribute groups */`
|
||||
|
||||
<br>
|
||||
|
||||
|
@ -4659,6 +4667,7 @@ trait TraitName
|
|||
|
||||
* `$name` - `/** @var Node\Identifier|null Name */`
|
||||
* `$stmts` - `/** @var Node\Stmt[] Statements */`
|
||||
* `$attrGroups` - `/** @var Node\AttributeGroup[] PHP attribute groups */`
|
||||
|
||||
<br>
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
5
ecs.php
5
ecs.php
|
@ -13,16 +13,17 @@ use PhpCsFixer\Fixer\ReturnNotation\ReturnAssignmentFixer;
|
|||
use PhpCsFixer\Fixer\Strict\StrictComparisonFixer;
|
||||
use SlevomatCodingStandard\Sniffs\Variables\UnusedVariableSniff;
|
||||
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
|
||||
use Symplify\CodingStandard\Fixer\ArrayNotation\ArrayOpenerAndCloserNewlineFixer;
|
||||
use Symplify\CodingStandard\Fixer\ArrayNotation\StandaloneLineInMultilineArrayFixer;
|
||||
use Symplify\CodingStandard\Fixer\LineLength\LineLengthFixer;
|
||||
use Symplify\CodingStandard\Sniffs\Debug\CommentedOutCodeSniff;
|
||||
use Symplify\EasyCodingStandard\Configuration\Option;
|
||||
use Symplify\EasyCodingStandard\ValueObject\Option;
|
||||
use Symplify\EasyCodingStandard\ValueObject\Set\SetList;
|
||||
|
||||
return static function (ContainerConfigurator $containerConfigurator): void {
|
||||
$services = $containerConfigurator->services();
|
||||
$services->set(StandaloneLineInMultilineArrayFixer::class);
|
||||
$services->set(LineLengthFixer::class);
|
||||
$services->set(ArrayOpenerAndCloserNewlineFixer::class);
|
||||
|
||||
$services->set(GeneralPhpdocAnnotationRemoveFixer::class)
|
||||
->call('configure', [[
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
declare(strict_types=1);
|
||||
|
||||
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
|
||||
use Symplify\MonorepoBuilder\ValueObject\Option;
|
||||
|
||||
return static function (ContainerConfigurator $containerConfigurator): void {
|
||||
$services = $containerConfigurator->services();
|
||||
|
|
|
@ -2,9 +2,14 @@
|
|||
|
||||
declare(strict_types=1);
|
||||
|
||||
use Migrify\PhpConfigPrinter\ValueObject\Option;
|
||||
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
|
||||
|
||||
return static function (ContainerConfigurator $containerConfigurator): void {
|
||||
$parameters = $containerConfigurator->parameters();
|
||||
$parameters->set(Option::INLINE_VALUE_OBJECT_FUNC_CALL_NAME, 'Rector\SymfonyPhpConfig\inline_value_object');
|
||||
$parameters->set(Option::INLINE_VALUE_OBJECTS_FUNC_CALL_NAME, 'Rector\SymfonyPhpConfig\inline_value_objects');
|
||||
|
||||
$services = $containerConfigurator->services();
|
||||
|
||||
$services->defaults()
|
||||
|
|
|
@ -6,34 +6,58 @@ namespace Rector\DocumentationGenerator\Command;
|
|||
|
||||
use Rector\Core\Configuration\Option;
|
||||
use Rector\Core\Console\Command\AbstractCommand;
|
||||
use Rector\Core\Contract\Rector\RectorInterface;
|
||||
use Rector\Core\Testing\Finder\RectorsFinder;
|
||||
use Rector\DocumentationGenerator\OutputFormatter\MarkdownDumpRectorsOutputFormatter;
|
||||
use Rector\DocumentationGenerator\Printer\RectorsDocumentationPrinter;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Style\SymfonyStyle;
|
||||
use Symplify\PackageBuilder\Console\Command\CommandNaming;
|
||||
use Symplify\PackageBuilder\Console\ShellCode;
|
||||
use Symplify\SmartFileSystem\SmartFileInfo;
|
||||
use Symplify\SmartFileSystem\SmartFileSystem;
|
||||
|
||||
final class DumpRectorsCommand extends AbstractCommand
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private const OUTPUT_FILE = 'output-file';
|
||||
|
||||
/**
|
||||
* @var RectorsFinder
|
||||
*/
|
||||
private $rectorsFinder;
|
||||
|
||||
/**
|
||||
* @var MarkdownDumpRectorsOutputFormatter
|
||||
* @var RectorsDocumentationPrinter
|
||||
*/
|
||||
private $markdownDumpRectorsOutputFormatter;
|
||||
private $rectorsDocumentationPrinter;
|
||||
|
||||
/**
|
||||
* @var SymfonyStyle
|
||||
*/
|
||||
private $symfonyStyle;
|
||||
|
||||
/**
|
||||
* @var SmartFileSystem
|
||||
*/
|
||||
private $smartFileSystem;
|
||||
|
||||
public function __construct(
|
||||
MarkdownDumpRectorsOutputFormatter $markdownDumpRectorsOutputFormatter,
|
||||
RectorsFinder $rectorsFinder
|
||||
RectorsDocumentationPrinter $rectorsDocumentationPrinter,
|
||||
RectorsFinder $rectorsFinder,
|
||||
SymfonyStyle $symfonyStyle,
|
||||
SmartFileSystem $smartFileSystem
|
||||
) {
|
||||
parent::__construct();
|
||||
|
||||
$this->rectorsFinder = $rectorsFinder;
|
||||
$this->markdownDumpRectorsOutputFormatter = $markdownDumpRectorsOutputFormatter;
|
||||
$this->rectorsDocumentationPrinter = $rectorsDocumentationPrinter;
|
||||
$this->symfonyStyle = $symfonyStyle;
|
||||
$this->smartFileSystem = $smartFileSystem;
|
||||
}
|
||||
|
||||
protected function configure(): void
|
||||
|
@ -46,27 +70,53 @@ final class DumpRectorsCommand extends AbstractCommand
|
|||
InputArgument::OPTIONAL | InputArgument::IS_ARRAY,
|
||||
'Directories with Rector rules'
|
||||
);
|
||||
|
||||
$this->addOption(
|
||||
self::OUTPUT_FILE,
|
||||
null,
|
||||
InputOption::VALUE_REQUIRED,
|
||||
'Where to output the file',
|
||||
getcwd() . '/docs/rector_rules_overview.md'
|
||||
);
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output): int
|
||||
{
|
||||
$source = (array) $input->getArgument(Option::SOURCE);
|
||||
|
||||
$isRectorProject = $source === [];
|
||||
|
||||
if ($isRectorProject) {
|
||||
// fallback to core Rectors
|
||||
$rulesRectors = $this->rectorsFinder->findInDirectories([
|
||||
__DIR__ . '/../../../../rules',
|
||||
__DIR__ . '/../../../../packages',
|
||||
]);
|
||||
} else {
|
||||
// custom directory
|
||||
$rulesRectors = $this->rectorsFinder->findInDirectories($source);
|
||||
}
|
||||
$rectors = $this->findRectorClassesInDirectoriesAndCreateRectorObjects($isRectorProject, $source);
|
||||
|
||||
$this->markdownDumpRectorsOutputFormatter->format($rulesRectors, $isRectorProject);
|
||||
$outputFile = (string) $input->getOption(self::OUTPUT_FILE);
|
||||
$printedContent = $this->rectorsDocumentationPrinter->print($rectors, $isRectorProject);
|
||||
$this->smartFileSystem->dumpFile($outputFile, $printedContent);
|
||||
|
||||
$outputFileFileInfo = new SmartFileInfo($outputFile);
|
||||
$message = sprintf(
|
||||
'Documentation for "%d" Rector rules was generated to "%s"',
|
||||
count($rectors),
|
||||
$outputFileFileInfo->getRelativeFilePathFromCwd()
|
||||
);
|
||||
$this->symfonyStyle->success($message);
|
||||
|
||||
return ShellCode::SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string[] $source
|
||||
* @return RectorInterface[]
|
||||
*/
|
||||
private function findRectorClassesInDirectoriesAndCreateRectorObjects(bool $isRectorProject, array $source): array
|
||||
{
|
||||
if ($isRectorProject) {
|
||||
// fallback to core Rectors
|
||||
return $this->rectorsFinder->findInDirectoriesAndCreate([
|
||||
__DIR__ . '/../../../../rules',
|
||||
__DIR__ . '/../../../../packages',
|
||||
]);
|
||||
}
|
||||
|
||||
// custom directory
|
||||
return $this->rectorsFinder->findInDirectoriesAndCreate($source);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,13 +4,13 @@ declare(strict_types=1);
|
|||
|
||||
namespace Rector\DocumentationGenerator\Printer;
|
||||
|
||||
use Migrify\PhpConfigPrinter\Printer\SmartPhpConfigPrinter;
|
||||
use Rector\ConsoleDiffer\MarkdownDifferAndFormatter;
|
||||
use Rector\Core\Contract\Rector\RectorInterface;
|
||||
use Rector\Core\Contract\RectorDefinition\CodeSampleInterface;
|
||||
use Rector\Core\RectorDefinition\ComposerJsonAwareCodeSample;
|
||||
use Rector\Core\RectorDefinition\ConfiguredCodeSample;
|
||||
use Rector\Core\RectorDefinition\RectorDefinition;
|
||||
use Rector\SymfonyPhpConfig\Printer\ReturnClosurePrinter;
|
||||
|
||||
/**
|
||||
* @see \Rector\DocumentationGenerator\Tests\Printer\CodeSamplePrinter\CodeSamplePrinterTest
|
||||
|
@ -23,16 +23,16 @@ final class CodeSamplePrinter
|
|||
private $markdownDifferAndFormatter;
|
||||
|
||||
/**
|
||||
* @var ReturnClosurePrinter
|
||||
* @var SmartPhpConfigPrinter
|
||||
*/
|
||||
private $returnClosurePrinter;
|
||||
private $smartPhpConfigPrinter;
|
||||
|
||||
public function __construct(
|
||||
MarkdownDifferAndFormatter $markdownDifferAndFormatter,
|
||||
ReturnClosurePrinter $returnClosurePrinter
|
||||
SmartPhpConfigPrinter $smartPhpConfigPrinter
|
||||
) {
|
||||
$this->markdownDifferAndFormatter = $markdownDifferAndFormatter;
|
||||
$this->returnClosurePrinter = $returnClosurePrinter;
|
||||
$this->smartPhpConfigPrinter = $smartPhpConfigPrinter;
|
||||
}
|
||||
|
||||
public function printCodeSamples(RectorDefinition $rectorDefinition, RectorInterface $rector): string
|
||||
|
@ -57,7 +57,7 @@ final class CodeSamplePrinter
|
|||
get_class($rector) => $codeSample->getConfiguration(),
|
||||
];
|
||||
|
||||
$phpConfigContent = $this->returnClosurePrinter->printServices($configuration);
|
||||
$phpConfigContent = $this->smartPhpConfigPrinter->printConfiguredServices($configuration);
|
||||
$wrappedPhpConfigContent = $this->printCodeWrapped($phpConfigContent, 'php');
|
||||
|
||||
return $wrappedPhpConfigContent . PHP_EOL . '↓' . PHP_EOL . PHP_EOL;
|
||||
|
|
|
@ -2,21 +2,18 @@
|
|||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\DocumentationGenerator\OutputFormatter;
|
||||
namespace Rector\DocumentationGenerator\Printer;
|
||||
|
||||
use Nette\Utils\Strings;
|
||||
use Rector\Core\Contract\Rector\RectorInterface;
|
||||
use Rector\DocumentationGenerator\Printer\RectorPrinter;
|
||||
use Rector\DocumentationGenerator\RectorMetadataResolver;
|
||||
use Symfony\Component\Console\Style\SymfonyStyle;
|
||||
use Webmozart\Assert\Assert;
|
||||
|
||||
final class MarkdownDumpRectorsOutputFormatter
|
||||
/**
|
||||
* @see \Rector\DocumentationGenerator\Tests\Printer\RectorsDocumentationPrinter\RectorsDocumentationPrinterTest
|
||||
*/
|
||||
final class RectorsDocumentationPrinter
|
||||
{
|
||||
/**
|
||||
* @var SymfonyStyle
|
||||
*/
|
||||
private $symfonyStyle;
|
||||
|
||||
/**
|
||||
* @var RectorMetadataResolver
|
||||
*/
|
||||
|
@ -27,74 +24,78 @@ final class MarkdownDumpRectorsOutputFormatter
|
|||
*/
|
||||
private $rectorPrinter;
|
||||
|
||||
public function __construct(
|
||||
RectorMetadataResolver $rectorMetadataResolver,
|
||||
SymfonyStyle $symfonyStyle,
|
||||
RectorPrinter $rectorPrinter
|
||||
) {
|
||||
$this->symfonyStyle = $symfonyStyle;
|
||||
public function __construct(RectorMetadataResolver $rectorMetadataResolver, RectorPrinter $rectorPrinter)
|
||||
{
|
||||
$this->rectorMetadataResolver = $rectorMetadataResolver;
|
||||
$this->rectorPrinter = $rectorPrinter;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param RectorInterface[] $packageRectors
|
||||
* @param RectorInterface[] $rectors
|
||||
*/
|
||||
public function format(array $packageRectors, bool $isRectorProject): void
|
||||
public function print(array $rectors, bool $isRectorProject): string
|
||||
{
|
||||
$totalRectorCount = count($packageRectors);
|
||||
$message = sprintf('# All %d Rectors Overview', $totalRectorCount);
|
||||
Assert::allIsInstanceOf($rectors, RectorInterface::class);
|
||||
|
||||
$this->symfonyStyle->writeln($message);
|
||||
$this->symfonyStyle->newLine();
|
||||
$totalRectorCount = count($rectors);
|
||||
$message = sprintf('# All %d Rectors Overview', $totalRectorCount) . PHP_EOL;
|
||||
|
||||
$content = $message;
|
||||
$content .= PHP_EOL;
|
||||
|
||||
if ($isRectorProject) {
|
||||
$this->symfonyStyle->writeln('- [Projects](#projects)');
|
||||
$this->printRectorsWithHeadline($packageRectors, 'Projects');
|
||||
$content .= '- [Projects](#projects)';
|
||||
$content .= PHP_EOL;
|
||||
|
||||
$content .= $this->printRectorsWithHeadline($rectors, 'Projects');
|
||||
} else {
|
||||
$this->printRectors($packageRectors, $isRectorProject);
|
||||
$content .= $this->printRectors($rectors, $isRectorProject);
|
||||
}
|
||||
|
||||
return $content;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param RectorInterface[] $rectors
|
||||
*/
|
||||
private function printRectorsWithHeadline(array $rectors, string $headline): void
|
||||
{
|
||||
if (count($rectors) === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->symfonyStyle->writeln('---');
|
||||
$this->symfonyStyle->newLine();
|
||||
|
||||
$this->symfonyStyle->writeln('## ' . $headline);
|
||||
$this->symfonyStyle->newLine();
|
||||
|
||||
$this->printRectors($rectors, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param RectorInterface[] $rectors
|
||||
*/
|
||||
private function printRectors(array $rectors, bool $isRectorProject): void
|
||||
public function printRectors(array $rectors, bool $isRectorProject): string
|
||||
{
|
||||
$groupedRectors = $this->groupRectorsByPackage($rectors);
|
||||
|
||||
$content = '';
|
||||
if ($isRectorProject) {
|
||||
$this->printGroupsMenu($groupedRectors);
|
||||
$content .= $this->printGroupsMenu($groupedRectors);
|
||||
}
|
||||
|
||||
foreach ($groupedRectors as $group => $rectors) {
|
||||
if ($isRectorProject) {
|
||||
$this->symfonyStyle->writeln('## ' . $group);
|
||||
$this->symfonyStyle->newLine();
|
||||
$content .= '## ' . $group . PHP_EOL . PHP_EOL;
|
||||
}
|
||||
|
||||
foreach ($rectors as $rector) {
|
||||
$this->rectorPrinter->printRector($rector, $isRectorProject);
|
||||
$rectorContent = $this->rectorPrinter->printRector($rector, $isRectorProject);
|
||||
$content .= $rectorContent . PHP_EOL;
|
||||
}
|
||||
}
|
||||
|
||||
return $content;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param RectorInterface[] $rectors
|
||||
*/
|
||||
private function printRectorsWithHeadline(array $rectors, string $headline): string
|
||||
{
|
||||
if (count($rectors) === 0) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$content = '---' . PHP_EOL . PHP_EOL;
|
||||
$content .= '## ' . $headline . PHP_EOL . PHP_EOL;
|
||||
|
||||
$content .= $this->printRectors($rectors, true);
|
||||
|
||||
return $content;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -119,16 +120,16 @@ final class MarkdownDumpRectorsOutputFormatter
|
|||
/**
|
||||
* @param RectorInterface[][] $rectorsByGroup
|
||||
*/
|
||||
private function printGroupsMenu(array $rectorsByGroup): void
|
||||
private function printGroupsMenu(array $rectorsByGroup): string
|
||||
{
|
||||
$content = '';
|
||||
foreach ($rectorsByGroup as $group => $rectors) {
|
||||
$escapedGroup = str_replace('\\', '', $group);
|
||||
$escapedGroup = Strings::webalize($escapedGroup, '_');
|
||||
$message = sprintf('- [%s](#%s) (%d)', $group, $escapedGroup, count($rectors));
|
||||
|
||||
$this->symfonyStyle->writeln($message);
|
||||
$content .= $message . PHP_EOL;
|
||||
}
|
||||
|
||||
$this->symfonyStyle->newLine();
|
||||
return $content . PHP_EOL;
|
||||
}
|
||||
}
|
|
@ -5,12 +5,14 @@ declare(strict_types=1);
|
|||
namespace Rector\DocumentationGenerator\Tests\Printer\CodeSamplePrinter;
|
||||
|
||||
use Iterator;
|
||||
use Rector\Autodiscovery\Rector\FileSystem\MoveValueObjectsToValueObjectDirectoryRector;
|
||||
use Rector\Core\Contract\Rector\RectorInterface;
|
||||
use Rector\Core\HttpKernel\RectorKernel;
|
||||
use Rector\DocumentationGenerator\Printer\CodeSamplePrinter;
|
||||
use Rector\Php74\Rector\Property\TypedPropertyRector;
|
||||
use ReflectionClass;
|
||||
use Symplify\PackageBuilder\Tests\AbstractKernelTestCase;
|
||||
use Symplify\SmartFileSystem\SmartFileInfo;
|
||||
|
||||
final class CodeSamplePrinterTest extends AbstractKernelTestCase
|
||||
{
|
||||
|
@ -37,11 +39,21 @@ final class CodeSamplePrinterTest extends AbstractKernelTestCase
|
|||
$this->assertInstanceOf(RectorInterface::class, $rector);
|
||||
|
||||
$printedCodeSamples = $this->codeSamplePrinter->printCodeSamples($rector->getDefinition(), $rector);
|
||||
$this->assertStringEqualsFile($expectedPrintedCodeSampleFilePath, $printedCodeSamples);
|
||||
|
||||
$expectedFileInfo = new SmartFileInfo($expectedPrintedCodeSampleFilePath);
|
||||
$this->assertStringEqualsFile(
|
||||
$expectedPrintedCodeSampleFilePath,
|
||||
$printedCodeSamples,
|
||||
$expectedFileInfo->getRelativeFilePathFromCwd()
|
||||
);
|
||||
}
|
||||
|
||||
public function provideData(): Iterator
|
||||
{
|
||||
yield [TypedPropertyRector::class, __DIR__ . '/Fixture/expected_typed_property_code_sample.txt'];
|
||||
yield [
|
||||
MoveValueObjectsToValueObjectDirectoryRector::class,
|
||||
__DIR__ . '/Fixture/expected_value_object_rector.txt',
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,11 +1,14 @@
|
|||
```php
|
||||
<?php
|
||||
|
||||
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
|
||||
use Rector\Php74\Rector\Property\TypedPropertyRector;
|
||||
declare(strict_types=1);
|
||||
|
||||
return function (ContainerConfigurator $containerConfigurator) : void {
|
||||
use Rector\Php74\Rector\Property\TypedPropertyRector;
|
||||
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
|
||||
|
||||
return static function (ContainerConfigurator $containerConfigurator): void {
|
||||
$services = $containerConfigurator->services();
|
||||
|
||||
$services->set(TypedPropertyRector::class)
|
||||
->call('configure', [[TypedPropertyRector::CLASS_LIKE_TYPE_ONLY => false]]);
|
||||
};
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
```php
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use Rector\Autodiscovery\Rector\FileSystem\MoveValueObjectsToValueObjectDirectoryRector;
|
||||
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
|
||||
|
||||
return static function (ContainerConfigurator $containerConfigurator): void {
|
||||
$services = $containerConfigurator->services();
|
||||
|
||||
$services->set(MoveValueObjectsToValueObjectDirectoryRector::class)
|
||||
->call('configure', [[MoveValueObjectsToValueObjectDirectoryRector::TYPES => ['ValueObjectInterfaceClassName'], MoveValueObjectsToValueObjectDirectoryRector::SUFFIXES => ['Search'], MoveValueObjectsToValueObjectDirectoryRector::ENABLE_VALUE_OBJECT_GUESSING => true]]);
|
||||
};
|
||||
```
|
||||
|
||||
↓
|
||||
|
||||
```diff
|
||||
-// app/Exception/Name.php
|
||||
+// app/ValueObject/Name.php
|
||||
class Name
|
||||
{
|
||||
private $name;
|
||||
|
||||
public function __construct(string $name)
|
||||
{
|
||||
$this->name = $name;
|
||||
}
|
||||
|
||||
public function getName()
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
}
|
||||
```
|
|
@ -8,11 +8,14 @@ Changes property `@var` annotations from annotation to type.
|
|||
```php
|
||||
<?php
|
||||
|
||||
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
|
||||
use Rector\Php74\Rector\Property\TypedPropertyRector;
|
||||
declare(strict_types=1);
|
||||
|
||||
return function (ContainerConfigurator $containerConfigurator) : void {
|
||||
use Rector\Php74\Rector\Property\TypedPropertyRector;
|
||||
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
|
||||
|
||||
return static function (ContainerConfigurator $containerConfigurator): void {
|
||||
$services = $containerConfigurator->services();
|
||||
|
||||
$services->set(TypedPropertyRector::class)
|
||||
->call('configure', [[TypedPropertyRector::CLASS_LIKE_TYPE_ONLY => false]]);
|
||||
};
|
||||
|
|
|
@ -35,8 +35,8 @@ final class RectorPrinterTest extends AbstractKernelTestCase
|
|||
/** @var RectorInterface $rector */
|
||||
$rector = $reflectionClass->newInstanceWithoutConstructor();
|
||||
|
||||
$printedRector = $this->rectorPrinter->printRector($rector, false);
|
||||
$this->assertStringEqualsFile($expectedContentFilePath, $printedRector);
|
||||
$printedContent = $this->rectorPrinter->printRector($rector, false);
|
||||
$this->assertStringEqualsFile($expectedContentFilePath, $printedContent);
|
||||
}
|
||||
|
||||
public function provideData(): Iterator
|
||||
|
|
|
@ -0,0 +1,74 @@
|
|||
# All 2 Rectors Overview
|
||||
|
||||
## `RenamePropertyRector`
|
||||
|
||||
- class: [`Rector\Generic\Rector\PropertyFetch\RenamePropertyRector`](/rules/generic/src/Rector/PropertyFetch/RenamePropertyRector.php)
|
||||
- [test fixtures](/rules/generic/tests/Rector/PropertyFetch/RenamePropertyRector/Fixture)
|
||||
|
||||
Replaces defined old properties by new ones.
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use Rector\Generic\Rector\PropertyFetch\RenamePropertyRector;
|
||||
use Rector\Generic\ValueObject\RenameProperty;
|
||||
use function Rector\SymfonyPhpConfig\inline_value_objects;
|
||||
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
|
||||
|
||||
return static function (ContainerConfigurator $containerConfigurator): void {
|
||||
$services = $containerConfigurator->services();
|
||||
|
||||
$services->set(RenamePropertyRector::class)
|
||||
->call('configure', [[RenamePropertyRector::RENAMED_PROPERTIES => inline_value_objects([new RenameProperty('SomeClass', 'someOldProperty', 'someNewProperty')])]]);
|
||||
};
|
||||
```
|
||||
|
||||
↓
|
||||
|
||||
```diff
|
||||
-$someObject->someOldProperty;
|
||||
+$someObject->someNewProperty;
|
||||
```
|
||||
|
||||
<br><br>
|
||||
|
||||
## `TypedPropertyRector`
|
||||
|
||||
- class: [`Rector\Php74\Rector\Property\TypedPropertyRector`](/rules/php74/src/Rector/Property/TypedPropertyRector.php)
|
||||
- [test fixtures](/rules/php74/tests/Rector/Property/TypedPropertyRector/Fixture)
|
||||
|
||||
Changes property `@var` annotations from annotation to type.
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use Rector\Php74\Rector\Property\TypedPropertyRector;
|
||||
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
|
||||
|
||||
return static function (ContainerConfigurator $containerConfigurator): void {
|
||||
$services = $containerConfigurator->services();
|
||||
|
||||
$services->set(TypedPropertyRector::class)
|
||||
->call('configure', [[TypedPropertyRector::CLASS_LIKE_TYPE_ONLY => false]]);
|
||||
};
|
||||
```
|
||||
|
||||
↓
|
||||
|
||||
```diff
|
||||
final class SomeClass
|
||||
{
|
||||
- /**
|
||||
- * @var int
|
||||
- */
|
||||
- private count;
|
||||
+ private int count;
|
||||
}
|
||||
```
|
||||
|
||||
<br><br>
|
||||
|
|
@ -0,0 +1,77 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\DocumentationGenerator\Tests\Printer\RectorsDocumentationPrinter;
|
||||
|
||||
use Iterator;
|
||||
use Rector\Core\Contract\Rector\RectorInterface;
|
||||
use Rector\Core\Exception\ShouldNotHappenException;
|
||||
use Rector\Core\HttpKernel\RectorKernel;
|
||||
use Rector\DocumentationGenerator\Printer\RectorsDocumentationPrinter;
|
||||
use Rector\Generic\Rector\PropertyFetch\RenamePropertyRector;
|
||||
use Rector\Php74\Rector\Property\TypedPropertyRector;
|
||||
use ReflectionClass;
|
||||
use Symplify\PackageBuilder\Tests\AbstractKernelTestCase;
|
||||
use Symplify\SmartFileSystem\SmartFileInfo;
|
||||
|
||||
final class RectorsDocumentationPrinterTest extends AbstractKernelTestCase
|
||||
{
|
||||
/**
|
||||
* @var RectorsDocumentationPrinter
|
||||
*/
|
||||
private $rectorsDocumentationPrinter;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->bootKernel(RectorKernel::class);
|
||||
$this->rectorsDocumentationPrinter = self::$container->get(RectorsDocumentationPrinter::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider provideData()
|
||||
*/
|
||||
public function test(array $rectorClasses, bool $isRectorProject, string $expectedContentFilePath): void
|
||||
{
|
||||
$rectors = $this->createRectorsFromRectorClasses($rectorClasses);
|
||||
|
||||
$printedContent = $this->rectorsDocumentationPrinter->print($rectors, $isRectorProject);
|
||||
$expectedFileInfo = new SmartFileInfo($expectedContentFilePath);
|
||||
|
||||
$this->assertStringEqualsFile(
|
||||
$expectedContentFilePath,
|
||||
$printedContent,
|
||||
$expectedFileInfo->getRelativeFilePathFromCwd()
|
||||
);
|
||||
}
|
||||
|
||||
public function provideData(): Iterator
|
||||
{
|
||||
yield [
|
||||
[TypedPropertyRector::class, RenamePropertyRector::class],
|
||||
false,
|
||||
__DIR__ . '/Fixture/expected_rectors.txt',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param class-string[] $rectorClasses
|
||||
* @return RectorInterface[]
|
||||
*/
|
||||
private function createRectorsFromRectorClasses(array $rectorClasses): array
|
||||
{
|
||||
$rectors = [];
|
||||
|
||||
foreach ($rectorClasses as $rectorClass) {
|
||||
$reflectionClass = new ReflectionClass($rectorClass);
|
||||
$rector = $reflectionClass->newInstanceWithoutConstructor();
|
||||
if (! $rector instanceof RectorInterface) {
|
||||
throw new ShouldNotHappenException();
|
||||
}
|
||||
|
||||
$rectors[] = $rector;
|
||||
}
|
||||
|
||||
return $rectors;
|
||||
}
|
||||
}
|
25
phpstan.neon
25
phpstan.neon
|
@ -9,6 +9,22 @@ includes:
|
|||
- vendor/symplify/coding-standard/config/symplify-rules.neon
|
||||
|
||||
services:
|
||||
# require constant in argument position
|
||||
-
|
||||
class: Symplify\CodingStandard\Rules\ForceMethodCallArgumentConstantRule
|
||||
tags: [phpstan.rules.rule]
|
||||
arguments:
|
||||
constantArgByMethodByType:
|
||||
Symfony\Component\Console\Command\Command:
|
||||
addArgument: [0]
|
||||
addOption: [0]
|
||||
Symfony\Component\Console\Input\InputInterface:
|
||||
getOption: [0]
|
||||
getArgument: [0]
|
||||
PhpParser\Node:
|
||||
getAttribute: [0]
|
||||
setAttribute: [0]
|
||||
|
||||
-
|
||||
class: Symplify\CodingStandard\Rules\SeeAnnotationToTestRule
|
||||
tags: [phpstan.rules.rule]
|
||||
|
@ -495,3 +511,12 @@ parameters:
|
|||
message: '#Instead of "Symfony\\Component\\Finder\\SplFileInfo" class/interface use "Symplify\\SmartFileSystem\\SmartFileInfo"#'
|
||||
paths:
|
||||
- src/FileSystem/FilesFinder.php
|
||||
|
||||
# @todo fix in symplify
|
||||
-
|
||||
message: '#Method call argument on position 0 must use constant over value#'
|
||||
path: 'src/Rector/AbstractRector.php'
|
||||
|
||||
- '#Method Rector\\DocumentationGenerator\\Tests\\Printer\\RectorsDocumentationPrinter\\RectorsDocumentationPrinterTest\:\:createRectorsFromRectorClasses\(\) should return array<Rector\\Core\\Contract\\Rector\\RectorInterface\> but returns array<int, object\>#'
|
||||
|
||||
- '#Parameter \#1 \$rectors of method Rector\\DocumentationGenerator\\Printer\\RectorsDocumentationPrinter\:\:print\(\) expects array<Rector\\Core\\Contract\\Rector\\RectorInterface\>, array<object\> given#'
|
||||
|
|
|
@ -8,6 +8,9 @@ use Nette\Utils\Strings;
|
|||
use PhpParser\Node\Stmt\Class_;
|
||||
use Rector\NodeNameResolver\NodeNameResolver;
|
||||
|
||||
/**
|
||||
* @see \Rector\PHPUnit\Tests\TestClassResolver\TestClassResolverTest
|
||||
*/
|
||||
final class TestClassResolver
|
||||
{
|
||||
/**
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\PHPUnit\Tests\TestClassResolver;
|
||||
|
||||
use Iterator;
|
||||
use Rector\Core\HttpKernel\RectorKernel;
|
||||
use Rector\DowngradePhp74\Rector\Property\DowngradeTypedPropertyRector;
|
||||
use Rector\DowngradePhp74\Tests\Rector\Property\DowngradeTypedPropertyRector\DowngradeTypedPropertyRectorTest;
|
||||
use Rector\Php74\Rector\Property\TypedPropertyRector;
|
||||
use Rector\Php74\Tests\Rector\Property\TypedPropertyRector\TypedPropertyRectorTest;
|
||||
use Rector\PHPUnit\TestClassResolver\TestClassResolver;
|
||||
use Symplify\PackageBuilder\Tests\AbstractKernelTestCase;
|
||||
|
||||
final class TestClassResolverTest extends AbstractKernelTestCase
|
||||
{
|
||||
/**
|
||||
* @var TestClassResolver
|
||||
*/
|
||||
private $testClassResolver;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->bootKernel(RectorKernel::class);
|
||||
$this->testClassResolver = self::$container->get(TestClassResolver::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider provideData()
|
||||
*/
|
||||
public function test(string $rectorClass, string $expectedTestClass): void
|
||||
{
|
||||
$testClass = $this->testClassResolver->resolveFromClassName($rectorClass);
|
||||
$this->assertSame($expectedTestClass, $testClass);
|
||||
}
|
||||
|
||||
public function provideData(): Iterator
|
||||
{
|
||||
yield [TypedPropertyRector::class, TypedPropertyRectorTest::class];
|
||||
yield [DowngradeTypedPropertyRector::class, DowngradeTypedPropertyRectorTest::class];
|
||||
}
|
||||
}
|
|
@ -2,7 +2,10 @@
|
|||
|
||||
declare(strict_types=1);
|
||||
|
||||
use Migrify\PhpConfigPrinter\Printer\PhpParserPhpConfigPrinter;
|
||||
use Migrify\PhpConfigPrinter\YamlToPhpConverter;
|
||||
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
|
||||
use Symfony\Component\Yaml\Parser;
|
||||
|
||||
return static function (ContainerConfigurator $containerConfigurator): void {
|
||||
$services = $containerConfigurator->services();
|
||||
|
@ -13,4 +16,8 @@ return static function (ContainerConfigurator $containerConfigurator): void {
|
|||
|
||||
$services->load('Rector\SymfonyPhpConfig\\', __DIR__ . '/../src')
|
||||
->exclude([__DIR__ . '/../src/Rector']);
|
||||
|
||||
$services->set(YamlToPhpConverter::class);
|
||||
$services->set(Parser::class);
|
||||
$services->set(PhpParserPhpConfigPrinter::class);
|
||||
};
|
||||
|
|
|
@ -1,207 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\SymfonyPhpConfig\Printer;
|
||||
|
||||
use Nette\Utils\Strings;
|
||||
use PhpParser\BuilderHelpers;
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Arg;
|
||||
use PhpParser\Node\Expr\ArrayItem;
|
||||
use PhpParser\Node\Expr\Assign;
|
||||
use PhpParser\Node\Expr\ClassConstFetch;
|
||||
use PhpParser\Node\Expr\Closure;
|
||||
use PhpParser\Node\Expr\FuncCall;
|
||||
use PhpParser\Node\Expr\MethodCall;
|
||||
use PhpParser\Node\Expr\Variable;
|
||||
use PhpParser\Node\Identifier;
|
||||
use PhpParser\Node\Name;
|
||||
use PhpParser\Node\Name\FullyQualified;
|
||||
use PhpParser\Node\Param;
|
||||
use PhpParser\Node\Stmt\Expression;
|
||||
use PhpParser\Node\Stmt\Nop;
|
||||
use PhpParser\Node\Stmt\Return_;
|
||||
use Rector\CodingStyle\Naming\ClassNaming;
|
||||
use Rector\Core\Exception\ShouldNotHappenException;
|
||||
use Rector\Core\PhpParser\Builder\ParamBuilder;
|
||||
use Rector\Core\PhpParser\Builder\UseBuilder;
|
||||
use Rector\Core\PhpParser\Node\NodeFactory;
|
||||
use Rector\Core\PhpParser\Printer\BetterStandardPrinter;
|
||||
use Rector\Core\Reflection\ConstantNameFromValueResolver;
|
||||
use Rector\SymfonyPhpConfig\NodeFactory\NewValueObjectFactory;
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
* @todo use migrify package https://github.com/migrify/php-config-printer
|
||||
*/
|
||||
final class ReturnClosurePrinter
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private const CONTAINER_CONFIGURATOR = 'containerConfigurator';
|
||||
|
||||
/**
|
||||
* @var Node[]
|
||||
*/
|
||||
private $useStmts = [];
|
||||
|
||||
/**
|
||||
* @var BetterStandardPrinter
|
||||
*/
|
||||
private $betterStandardPrinter;
|
||||
|
||||
/**
|
||||
* @var NodeFactory
|
||||
*/
|
||||
private $nodeFactory;
|
||||
|
||||
/**
|
||||
* @var ClassNaming
|
||||
*/
|
||||
private $classNaming;
|
||||
|
||||
/**
|
||||
* @var ConstantNameFromValueResolver
|
||||
*/
|
||||
private $constantNameFromValueResolver;
|
||||
|
||||
/**
|
||||
* @var NewValueObjectFactory
|
||||
*/
|
||||
private $newValueObjectFactory;
|
||||
|
||||
public function __construct(
|
||||
BetterStandardPrinter $betterStandardPrinter,
|
||||
ClassNaming $classNaming,
|
||||
NodeFactory $nodeFactory,
|
||||
ConstantNameFromValueResolver $constantNameFromValueResolver,
|
||||
NewValueObjectFactory $newValueObjectFactory
|
||||
) {
|
||||
$this->betterStandardPrinter = $betterStandardPrinter;
|
||||
$this->nodeFactory = $nodeFactory;
|
||||
$this->classNaming = $classNaming;
|
||||
$this->constantNameFromValueResolver = $constantNameFromValueResolver;
|
||||
$this->newValueObjectFactory = $newValueObjectFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* @todo use migrify package
|
||||
*/
|
||||
public function printServices(array $services): string
|
||||
{
|
||||
// reset for each services
|
||||
$this->useStmts = [];
|
||||
$this->addUseStmts('Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator');
|
||||
|
||||
$closure = new Closure([
|
||||
'params' => [$this->createClosureParam()],
|
||||
'returnType' => new Identifier('void'),
|
||||
'stmts' => $this->createClosureStmts($services),
|
||||
]);
|
||||
|
||||
$return = new Return_($closure);
|
||||
|
||||
$rootStmts = array_merge($this->useStmts, [new Nop(), $return]);
|
||||
$printedContent = $this->betterStandardPrinter->prettyPrintFile($rootStmts);
|
||||
|
||||
return $this->indentFluentCallToNewline($printedContent);
|
||||
}
|
||||
|
||||
private function addUseStmts(string $useImport): void
|
||||
{
|
||||
$useBuilder = new UseBuilder($useImport);
|
||||
$this->useStmts[] = $useBuilder->getNode();
|
||||
}
|
||||
|
||||
private function createClosureParam(): Param
|
||||
{
|
||||
$paramBuilder = new ParamBuilder(self::CONTAINER_CONFIGURATOR);
|
||||
$paramBuilder->setType('ContainerConfigurator');
|
||||
return $paramBuilder->getNode();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed[] $services
|
||||
* @return Expression[]
|
||||
*/
|
||||
private function createClosureStmts(array $services): array
|
||||
{
|
||||
$stmts = [];
|
||||
|
||||
$servicesVariable = new Variable('services');
|
||||
|
||||
$servicesMethodCall = new MethodCall(new Variable(self::CONTAINER_CONFIGURATOR), 'services');
|
||||
$assign = new Assign($servicesVariable, $servicesMethodCall);
|
||||
$stmts[] = new Expression($assign);
|
||||
|
||||
foreach ($services as $serviceName => $serviceParameters) {
|
||||
$this->addUseStmts($serviceName);
|
||||
$methodCall = $this->createServicesSetMethodCall($serviceName, $servicesVariable, $serviceParameters);
|
||||
$stmts[] = new Expression($methodCall);
|
||||
}
|
||||
|
||||
return $stmts;
|
||||
}
|
||||
|
||||
private function indentFluentCallToNewline(string $content): string
|
||||
{
|
||||
$nextCallIndentReplacement = ')' . PHP_EOL . Strings::indent('->', 8, ' ');
|
||||
return Strings::replace($content, '#\)->#', $nextCallIndentReplacement);
|
||||
}
|
||||
|
||||
private function createServicesSetMethodCall(
|
||||
string $serviceName,
|
||||
Variable $servicesVariable,
|
||||
array $serviceParameters
|
||||
): MethodCall {
|
||||
$shortClassName = $this->classNaming->getShortName($serviceName);
|
||||
$classConstFetch = new ClassConstFetch(new Name($shortClassName), new Identifier('class'));
|
||||
$args = [new Arg($classConstFetch)];
|
||||
|
||||
$methodCall = new MethodCall($servicesVariable, 'set', $args);
|
||||
|
||||
foreach ($serviceParameters as $argument => $value) {
|
||||
if (! is_string($argument)) {
|
||||
$message = sprintf('Invalid configuration for code sample in "%s" class', $serviceName);
|
||||
throw new ShouldNotHappenException($message);
|
||||
}
|
||||
|
||||
$constantName = $this->constantNameFromValueResolver->resolveFromValueAndClass($argument, $serviceName);
|
||||
$classConstFetch = new ClassConstFetch(new Name($shortClassName), $constantName);
|
||||
|
||||
$args = $this->nodeFactory->createArgs(
|
||||
['configure', [[$this->createConfigureArgs($value, $classConstFetch)]]]
|
||||
);
|
||||
|
||||
$methodCall = new MethodCall($methodCall, 'call', $args);
|
||||
}
|
||||
|
||||
return $methodCall;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed|mixed[] $value
|
||||
*/
|
||||
private function createConfigureArgs($value, ClassConstFetch $classConstFetch): ArrayItem
|
||||
{
|
||||
if (is_array($value)) {
|
||||
foreach ($value as $key => $subValue) {
|
||||
// PHP object configuration
|
||||
if (is_object($subValue)) {
|
||||
$new = $this->newValueObjectFactory->create($subValue);
|
||||
$args = [new Arg($new)];
|
||||
|
||||
// create arguments from object properties
|
||||
$inlineObjectFuncCall = new FuncCall(new FullyQualified(
|
||||
'Rector\SymfonyPhpConfig\inline_value_object'
|
||||
), $args);
|
||||
$value[$key] = $inlineObjectFuncCall;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new ArrayItem(BuilderHelpers::normalizeValue($value), $classConstFetch);
|
||||
}
|
||||
}
|
|
@ -4,9 +4,12 @@ declare(strict_types=1);
|
|||
|
||||
namespace Rector\Core\Application;
|
||||
|
||||
use Rector\Core\Configuration\Option;
|
||||
use Rector\Core\Contract\Rector\RectorInterface;
|
||||
use Rector\Core\Exception\ShouldNotHappenException;
|
||||
use Rector\PostRector\Contract\Rector\PostRectorInterface;
|
||||
use Rector\RectorGenerator\Contract\InternalRectorInterface;
|
||||
use Symplify\PackageBuilder\Parameter\ParameterProvider;
|
||||
|
||||
/**
|
||||
* Provides list of Rector rules, that are not internal → only those registered by user
|
||||
|
@ -21,11 +24,31 @@ final class ActiveRectorsProvider
|
|||
/**
|
||||
* @param RectorInterface[] $rectors
|
||||
*/
|
||||
public function __construct(array $rectors)
|
||||
public function __construct(array $rectors, ParameterProvider $parameterProvider)
|
||||
{
|
||||
$excludeRectors = $parameterProvider->provideArrayParameter(Option::EXCLUDE_RECTORS);
|
||||
$this->ensureClassesExistsAndAreRectors($excludeRectors);
|
||||
|
||||
foreach ($rectors as $key => $rector) {
|
||||
$rectorClass = get_class($rector);
|
||||
if (in_array($rectorClass, $excludeRectors, true)) {
|
||||
unset($rectors[$key]);
|
||||
}
|
||||
}
|
||||
|
||||
$this->rectors = $rectors;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return RectorInterface[]
|
||||
*/
|
||||
public function provideByType(string $type): array
|
||||
{
|
||||
return array_filter($this->rectors, function (RectorInterface $rector) use ($type): bool {
|
||||
return is_a($rector, $type, true);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @return RectorInterface[]
|
||||
*/
|
||||
|
@ -34,6 +57,17 @@ final class ActiveRectorsProvider
|
|||
return $this->filterOutInternalRectorsAndSort($this->rectors);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string[] $excludedRectors
|
||||
*/
|
||||
private function ensureClassesExistsAndAreRectors(array $excludedRectors): void
|
||||
{
|
||||
foreach ($excludedRectors as $excludedRector) {
|
||||
$this->ensureClassExists($excludedRector);
|
||||
$this->ensureIsRectorClass($excludedRector);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param RectorInterface[] $rectors
|
||||
* @return RectorInterface[]
|
||||
|
@ -52,4 +86,31 @@ final class ActiveRectorsProvider
|
|||
return ! $rector instanceof PostRectorInterface;
|
||||
});
|
||||
}
|
||||
|
||||
private function ensureClassExists(string $excludedRector): void
|
||||
{
|
||||
if (class_exists($excludedRector)) {
|
||||
return;
|
||||
}
|
||||
|
||||
throw new ShouldNotHappenException(sprintf(
|
||||
'Class "%s" defined in "parameters > %s" was not found ',
|
||||
$excludedRector,
|
||||
Option::EXCLUDE_RECTORS
|
||||
));
|
||||
}
|
||||
|
||||
private function ensureIsRectorClass(string $excludedRector): void
|
||||
{
|
||||
if (is_a($excludedRector, RectorInterface::class, true)) {
|
||||
return;
|
||||
}
|
||||
|
||||
throw new ShouldNotHappenException(sprintf(
|
||||
'Class "%s" defined in "parameters > %s" is not a Rector rule = does not implement "%s" ',
|
||||
$excludedRector,
|
||||
Option::EXCLUDE_RECTORS,
|
||||
RectorInterface::class
|
||||
));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -141,11 +141,6 @@ final class Option
|
|||
*/
|
||||
public const FILE_EXTENSIONS = 'file_extensions';
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public const RECTOR_RECIPE = 'rector_recipe';
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
|
@ -155,4 +150,9 @@ final class Option
|
|||
* @var string
|
||||
*/
|
||||
public const CACHE_DIR = 'cache_dir';
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public const OPTION_DEBUG = 'debug';
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ declare(strict_types=1);
|
|||
namespace Rector\Core\Console\Command;
|
||||
|
||||
use Nette\Utils\Strings;
|
||||
use Rector\Core\Configuration\Option;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Descriptor\TextDescriptor;
|
||||
use Symfony\Component\Console\Exception\RuntimeException;
|
||||
|
@ -53,7 +54,7 @@ abstract class AbstractCommand extends Command
|
|||
|
||||
protected function initialize(InputInterface $input, OutputInterface $output): void
|
||||
{
|
||||
if ($input->getOption('debug')) {
|
||||
if ($input->getOption(Option::OPTION_DEBUG)) {
|
||||
if ($this->getApplication() === null) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -1,81 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\Core\DependencyInjection\CompilerPass;
|
||||
|
||||
use Rector\Core\Configuration\Option;
|
||||
use Rector\Core\Contract\Rector\RectorInterface;
|
||||
use Rector\Core\Exception\ShouldNotHappenException;
|
||||
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
|
||||
final class RemoveExcludedRectorsCompilerPass implements CompilerPassInterface
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private const EXCLUDE_RECTORS_KEY = 'exclude_rectors';
|
||||
|
||||
public function process(ContainerBuilder $containerBuilder): void
|
||||
{
|
||||
$parameterBag = $containerBuilder->getParameterBag();
|
||||
if (! $parameterBag->has(self::EXCLUDE_RECTORS_KEY)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$excludedRectors = (array) $parameterBag->get(self::EXCLUDE_RECTORS_KEY);
|
||||
|
||||
$this->ensureClassesExistsAndAreRectors($excludedRectors);
|
||||
|
||||
foreach ($containerBuilder->getDefinitions() as $id => $definition) {
|
||||
if ($definition->getClass() === null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (! in_array($definition->getClass(), $excludedRectors, true)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$containerBuilder->removeDefinition($id);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string[] $excludedRectors
|
||||
*/
|
||||
private function ensureClassesExistsAndAreRectors(array $excludedRectors): void
|
||||
{
|
||||
foreach ($excludedRectors as $excludedRector) {
|
||||
$this->ensureClassExists($excludedRector);
|
||||
$this->ensureIsRectorClass($excludedRector);
|
||||
}
|
||||
}
|
||||
|
||||
private function ensureClassExists(string $excludedRector): void
|
||||
{
|
||||
if (class_exists($excludedRector)) {
|
||||
return;
|
||||
}
|
||||
|
||||
throw new ShouldNotHappenException(sprintf(
|
||||
'Class "%s" defined in "parameters > %s" was not found ',
|
||||
$excludedRector,
|
||||
Option::EXCLUDE_RECTORS
|
||||
));
|
||||
}
|
||||
|
||||
private function ensureIsRectorClass(string $excludedRector): void
|
||||
{
|
||||
if (is_a($excludedRector, RectorInterface::class, true)) {
|
||||
return;
|
||||
}
|
||||
|
||||
throw new ShouldNotHappenException(sprintf(
|
||||
'Class "%s" defined in "parameters > %s" is not a Rector rule = does not implement "%s" ',
|
||||
$excludedRector,
|
||||
Option::EXCLUDE_RECTORS,
|
||||
RectorInterface::class
|
||||
));
|
||||
}
|
||||
}
|
|
@ -4,11 +4,11 @@ declare(strict_types=1);
|
|||
|
||||
namespace Rector\Core\HttpKernel;
|
||||
|
||||
use Migrify\PhpConfigPrinter\Bundle\PhpConfigPrinterBundle;
|
||||
use Rector\Core\Contract\Rector\RectorInterface;
|
||||
use Rector\Core\DependencyInjection\Collector\ConfigureCallValuesCollector;
|
||||
use Rector\Core\DependencyInjection\CompilerPass\MakeRectorsPublicCompilerPass;
|
||||
use Rector\Core\DependencyInjection\CompilerPass\MergeImportedRectorConfigureCallValuesCompilerPass;
|
||||
use Rector\Core\DependencyInjection\CompilerPass\RemoveExcludedRectorsCompilerPass;
|
||||
use Rector\Core\DependencyInjection\Loader\ConfigurableCallValuesCollectingPhpFileLoader;
|
||||
use Symfony\Component\Config\Loader\DelegatingLoader;
|
||||
use Symfony\Component\Config\Loader\GlobFileLoader;
|
||||
|
@ -77,13 +77,11 @@ final class RectorKernel extends Kernel implements ExtraConfigAwareKernelInterfa
|
|||
*/
|
||||
public function registerBundles(): array
|
||||
{
|
||||
return [new ConsoleColorDiffBundle()];
|
||||
return [new ConsoleColorDiffBundle(), new PhpConfigPrinterBundle()];
|
||||
}
|
||||
|
||||
protected function build(ContainerBuilder $containerBuilder): void
|
||||
{
|
||||
$containerBuilder->addCompilerPass(new RemoveExcludedRectorsCompilerPass());
|
||||
|
||||
$containerBuilder->addCompilerPass(new AutowireArrayParameterCompilerPass());
|
||||
|
||||
// autowire Rectors by default (mainly for 3rd party code)
|
||||
|
|
|
@ -7,6 +7,7 @@ namespace Rector\Core\PhpParser\NodeTraverser;
|
|||
use PhpParser\Node;
|
||||
use PhpParser\NodeTraverser;
|
||||
use Rector\Caching\Contract\Rector\ZeroCacheRectorInterface;
|
||||
use Rector\Core\Application\ActiveRectorsProvider;
|
||||
use Rector\Core\Configuration\Configuration;
|
||||
use Rector\Core\Contract\Rector\ConfigurableRectorInterface;
|
||||
use Rector\Core\Contract\Rector\PhpRectorInterface;
|
||||
|
@ -26,14 +27,14 @@ final class RectorNodeTraverser extends NodeTraverser
|
|||
*/
|
||||
private $enabledRectorsProvider;
|
||||
|
||||
/**
|
||||
* @param PhpRectorInterface[] $phpRectors
|
||||
*/
|
||||
public function __construct(
|
||||
EnabledRectorsProvider $enabledRectorsProvider,
|
||||
Configuration $configuration,
|
||||
array $phpRectors = []
|
||||
ActiveRectorsProvider $activeRectorsProvider
|
||||
) {
|
||||
/** @var PhpRectorInterface[] $phpRectors */
|
||||
$phpRectors = $activeRectorsProvider->provideByType(PhpRectorInterface::class);
|
||||
|
||||
$this->allPhpRectors = $phpRectors;
|
||||
$this->enabledRectorsProvider = $enabledRectorsProvider;
|
||||
|
||||
|
|
|
@ -1,28 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\Core\Reflection;
|
||||
|
||||
use Rector\Core\Exception\ShouldNotHappenException;
|
||||
use ReflectionClass;
|
||||
|
||||
final class ConstantNameFromValueResolver
|
||||
{
|
||||
public function resolveFromValueAndClass(string $constantValue, string $class): string
|
||||
{
|
||||
$reflectionClass = new ReflectionClass($class);
|
||||
foreach ($reflectionClass->getConstants() as $name => $value) {
|
||||
if ($value === $constantValue) {
|
||||
return $name;
|
||||
}
|
||||
}
|
||||
|
||||
$message = sprintf(
|
||||
'Constant value "%s" for class "%s" could not be resolved. Make sure you use constants references there, not string values',
|
||||
$constantValue,
|
||||
$class
|
||||
);
|
||||
throw new ShouldNotHappenException($message);
|
||||
}
|
||||
}
|
|
@ -28,7 +28,7 @@ final class RectorsFinder
|
|||
*/
|
||||
public function findCoreRectorClasses(): array
|
||||
{
|
||||
$allRectors = $this->findInDirectories(self::RECTOR_PATHS);
|
||||
$allRectors = $this->findInDirectoriesAndCreate(self::RECTOR_PATHS);
|
||||
|
||||
$rectorClasses = array_map(function (RectorInterface $rector): string {
|
||||
return get_class($rector);
|
||||
|
@ -44,7 +44,7 @@ final class RectorsFinder
|
|||
* @param string[] $directories
|
||||
* @return RectorInterface[]
|
||||
*/
|
||||
public function findInDirectories(array $directories): array
|
||||
public function findInDirectoriesAndCreate(array $directories): array
|
||||
{
|
||||
$foundClasses = $this->findClassesInDirectoriesByName($directories, '*Rector.php');
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user