[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:
Tomas Votruba 2020-09-24 20:54:39 +02:00 committed by GitHub
parent 0ebf4df558
commit 70bf2ea830
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
29 changed files with 1424 additions and 1280 deletions

View File

@ -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",

View File

@ -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

View File

@ -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', [[

View File

@ -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();

View File

@ -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()

View File

@ -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);
}
}

View File

@ -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;

View File

@ -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;
}
}

View File

@ -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',
];
}
}

View File

@ -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]]);
};

View File

@ -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;
}
}
```

View File

@ -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]]);
};

View File

@ -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

View File

@ -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>

View File

@ -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;
}
}

View File

@ -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#'

View File

@ -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
{
/**

View File

@ -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];
}
}

View File

@ -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);
};

View File

@ -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);
}
}

View File

@ -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
));
}
}

View File

@ -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';
}

View File

@ -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;
}

View File

@ -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
));
}
}

View File

@ -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)

View File

@ -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;

View File

@ -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);
}
}

View File

@ -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');