[Reporting] Move missing rector services to single class (#5881)

This commit is contained in:
Tomas Votruba 2021-03-17 19:59:47 +01:00 committed by GitHub
parent ea19540a73
commit 2be6607854
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
24 changed files with 131 additions and 215 deletions

View File

@ -11,6 +11,7 @@ use Symplify\PackageBuilder\Console\ShellCode;
use Symplify\PackageBuilder\Reflection\PrivatesCaller;
use Symplify\SetConfigResolver\Bootstrap\InvalidSetReporter;
use Symplify\SetConfigResolver\Exception\SetNotFoundException;
use Tracy\Debugger;
// @ intentionally: continue anyway
@ini_set('memory_limit', '-1');
@ -36,6 +37,11 @@ $symfonyStyle = $symfonyStyleFactory->create();
$rectorConfigsResolver = new RectorConfigsResolver();
// for simpler debugging output
if (class_exists(Debugger::class)) {
Debugger::$maxDepth = 2;
}
try {
$bootstrapConfigs = $rectorConfigsResolver->provide();
@ -50,6 +56,7 @@ try {
exit(ShellCode::ERROR);
}
/** @var ConsoleApplication $application */
$application = $container->get(ConsoleApplication::class);
exit($application->run());

View File

@ -9,5 +9,4 @@ return static function (ContainerConfigurator $containerConfigurator): void {
$containerConfigurator->import(__DIR__ . '/services-rules.php');
$containerConfigurator->import(__DIR__ . '/services-packages.php');
$containerConfigurator->import(__DIR__ . '/parameters.php');
$containerConfigurator->import(__DIR__ . '/../utils/*/config/config.php', null, true);
};

View File

@ -24,7 +24,6 @@ use Psr\Cache\CacheItemPoolInterface;
use Psr\SimpleCache\CacheInterface;
use Rector\BetterPhpDocParser\PhpDocParser\BetterPhpDocParser;
use Rector\Caching\Cache\Adapter\FilesystemAdapterFactory;
use Rector\Core\Bootstrap\NoRectorsLoadedReporter;
use Rector\Core\Console\ConsoleApplication;
use Rector\Core\PhpParser\Parser\NikicPhpParserFactory;
use Rector\Core\PhpParser\Parser\PhpParserLexerFactory;
@ -78,7 +77,6 @@ return static function (ContainerConfigurator $containerConfigurator): void {
$services->set(FileSystemGuard::class);
$services->set(NoRectorsLoadedReporter::class);
$services->set(SimpleCallableNodeTraverser::class);
$services->set(ParserFactory::class);

View File

@ -10,7 +10,6 @@ use PhpParser\NodeTraverser;
use PhpParser\NodeVisitor\CloningVisitor;
use PhpParser\NodeVisitor\NameResolver;
use PhpParser\NodeVisitor\NodeConnectingVisitor;
use Rector\Core\Configuration\Configuration;
use Rector\NodeCollector\NodeVisitor\NodeCollectorNodeVisitor;
use Rector\NodeTypeResolver\NodeVisitor\FileInfoNodeVisitor;
use Rector\NodeTypeResolver\NodeVisitor\FirstLevelNodeVisitor;
@ -58,11 +57,6 @@ final class NodeScopeAndMetadataDecorator
*/
private $nodeCollectorNodeVisitor;
/**
* @var Configuration
*/
private $configuration;
/**
* @var NodeConnectingVisitor
*/
@ -80,7 +74,6 @@ final class NodeScopeAndMetadataDecorator
public function __construct(
CloningVisitor $cloningVisitor,
Configuration $configuration,
FileInfoNodeVisitor $fileInfoNodeVisitor,
FunctionMethodAndClassNodeVisitor $functionMethodAndClassNodeVisitor,
NamespaceNodeVisitor $namespaceNodeVisitor,
@ -98,7 +91,6 @@ final class NodeScopeAndMetadataDecorator
$this->statementNodeVisitor = $statementNodeVisitor;
$this->fileInfoNodeVisitor = $fileInfoNodeVisitor;
$this->nodeCollectorNodeVisitor = $nodeCollectorNodeVisitor;
$this->configuration = $configuration;
$this->nodeConnectingVisitor = $nodeConnectingVisitor;
$this->functionLikeParamArgPositionNodeVisitor = $functionLikeParamArgPositionNodeVisitor;
$this->firstLevelNodeVisitor = $firstLevelNodeVisitor;
@ -116,12 +108,9 @@ final class NodeScopeAndMetadataDecorator
// required by PHPStan
'replaceNodes' => true,
]));
$nodes = $nodeTraverser->traverse($nodes);
// node scoping is needed only for Scope
if ($needsScope || $this->configuration->areAnyPhpRectorsLoaded()) {
$nodes = $this->phpStanNodeScopeResolver->processNodes($nodes, $smartFileInfo);
}
$nodes = $nodeTraverser->traverse($nodes);
$nodes = $this->phpStanNodeScopeResolver->processNodes($nodes, $smartFileInfo);
$nodeTraverser = new NodeTraverser();

View File

@ -85,9 +85,7 @@ parameters:
# mixed
- '#Offset int\|string\|null does not exist on array<PhpParser\\Node\\Stmt>\|null#'
- '#class-string<T of object>\|T of object#'
- '#Method Rector\\Php80\\Rector\\NotIdentical\\StrContainsRector\:\:matchNotIdenticalToFalse\(\) should return PhpParser\\Node\\Expr\\FuncCall\|null but returns PhpParser\\Node\\Expr#'
# broken
- '#Parameter \#2 \$name of method Rector\\NodeNameResolver\\NodeNameResolver\:\:isName\(\) expects string, string\|null given#'
@ -156,12 +154,8 @@ parameters:
-
message: '#Array (with keys|destruct) is not allowed\. Use value object to pass data instead#'
paths:
# working with cvs file
# 3rd party package
- rules/Php70/EregToPcreTransformer.php
# template variables
# output format to json
- rules/Doctrine/Collector/UuidMigrationDataCollector.php
-
message: '#Use explicit return value over magic &reference#'
@ -208,8 +202,6 @@ parameters:
paths:
- packages/DoctrineAnnotationGenerated/PhpDocNode/ConstantReferenceIdentifierRestorer.php # 61
- '#Method Rector\\BetterPhpDocParser\\Tests\\PhpDocInfo\\PhpDocInfo\\PhpDocInfoTest\:\:createPhpDocInfoFromFile\(\) should return Rector\\BetterPhpDocParser\\PhpDocInfo\\PhpDocInfo but returns Rector\\BetterPhpDocParser\\PhpDocInfo\\PhpDocInfo\|null#'
-
message: '#"(getComments|getDocComment|setDocComment)\(\)" call on "PhpParser\\Node" type is not allowed#'
paths:
@ -249,9 +241,6 @@ parameters:
# prevent circular dependnecy
- packages/StaticTypeMapper/Naming/NameScopeFactory.php
# class-string vs string
- '#Parameter \#1 \$expected of method PHPUnit\\Framework\\Assert\:\:assertInstanceOf\(\) expects class\-string<object\>, string given#'
-
message: '#Cannot cast array<string\>\|bool\|string\|null to string#'
paths:
@ -329,7 +318,6 @@ parameters:
message: '#Property with protected modifier is not allowed\. Use interface contract method instead#'
paths:
- rules/Defluent/ValueObject/*
- src/Rector/AbstractRector.php
- '#Parameter \#1 \$keyName of method Rector\\AttributeAwarePhpDoc\\Ast\\Type\\AttributeAwareArrayShapeItemNode\:\:createKeyWithSpacePattern\(\) expects PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstExprIntegerNode\|PHPStan\\PhpDocParser\\Ast\\Type\\IdentifierTypeNode\|null, PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstExprIntegerNode\|PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstExprStringNode\|PHPStan\\PhpDocParser\\Ast\\Type\\IdentifierTypeNode\|null given#'
- '#AttributeAwarePhpDocNode#'
@ -352,13 +340,16 @@ parameters:
- bin/rector.php
- rules/Php70/Rector/FuncCall/MultiDirnameRector.php
# @todo fix later
-
message: '#Property with protected modifier is not allowed\. Use interface contract method instead#'
message: '#Function "class_exists\(\)" cannot be used/left in the code#'
paths:
- rules/Naming/Guard/PropertyConflictingNameGuard/AbstractPropertyConflictingNameGuard.php
- rules/Naming/PropertyRenamer/AbstractPropertyRenamer.php
- bin/rector.php
-
message: '#Do not use static property#'
path: 'bin/rector.php'
# @todo fix later
-
message: '#There should be no empty class#'
paths:
@ -378,7 +369,6 @@ parameters:
# fixed in php-parser master
- '#Method Rector\\Symfony\\NodeFactory\\RouteNameClassFactory\:\:create\(\) should return PhpParser\\Node\\Stmt\\Namespace_ but returns PhpParser\\Node#'
- '#Parameter \#4 \$classWithConstants of class Rector\\Privatization\\ValueObject\\ReplaceStringWithClassConstant constructor expects class\-string, string given#'
- '#Method Rector\\BetterPhpDocParser\\Tests\\PhpDocParser\\AbstractPhpDocInfoTest\:\:parseFileAndGetFirstNodeOfType\(\) should return T of PhpParser\\Node but returns PhpParser\\Node#'
-
message: '#new <class\> is limited to 3 "new <class\>\(new <class\>\)\)" nesting to each other\.#'
@ -387,11 +377,6 @@ parameters:
- '#Class with base "FileNode" name is already used in "PHPStan\\Node\\FileNode", "Rector\\Core\\PhpParser\\Node\\CustomNode\\FileNode"\. Use unique name to make classes easy to recognize#'
-
message: '#Class Rector\\RemovingStatic\\Tests\\Rector\\Property\\DesiredPropertyClassMethodTypeToDynamicRector\\Fixture\\StaticProperty not found#'
paths:
- rules/removing-static/tests/Rector/Property/DesiredPropertyClassMethodTypeToDynamicRector/config/some_config.php
# buggy phpstan clas-string
- '#Method (.*?) should return class\-string but returns string#'
@ -459,7 +444,6 @@ parameters:
- packages/AttributeAwarePhpDoc/Ast/PhpDoc/AttributeAwareParamTagValueNode.php
- '#Property Rector\\Core\\PhpParser\\Node\\AssignAndBinaryMap\:\:\$binaryOpToAssignClasses \(array<class\-string<PhpParser\\Node\\Expr\\BinaryOp\>, class\-string<PhpParser\\Node\\Expr\\BinaryOp\>\>\) does not accept array#'
- '#Content of method "configure\(\)" is duplicated with method "configure\(\)" in "Rector\\RemovingStatic\\Rector\\Class_\\PassFactoryToUniqueObjectRector" class\. Use unique content or abstract service instead#'
-
message: '#Function "class_exists\(\)" cannot be used/left in the code#'
@ -527,30 +511,10 @@ parameters:
- '#Cognitive complexity for "Rector\\NetteCodeQuality\\FormControlTypeResolver\\MagicNetteFactoryInterfaceFormControlTypeResolver\:\:resolve\(\)" is 12, keep it under 9#'
- '#Content of method "matchAssignExprToPropertyName\(\)" is duplicated with method "matchAssignExprToPropertyName\(\)" in "Rector\\TypeDeclaration\\AlreadyAssignDetector\\ConstructorAssignDetector" class\. Use unique content or abstract service instead#'
# make more tolerand, e.g. at least 2-3 lines
- '#Content of method "isConflicting\(\)" is duplicated with method "isConflicting\(\)" in "Rector\\Naming\\Guard\\PropertyConflictingNameGuard\\UnderscoreCamelCaseConflictingNameGuard" class\. Use unique content or abstract service instead#'
- '#Content of method "configure\(\)" is duplicated with method "configure\(\)" in (.*?) Use unique content or service instead#'
-
message: '#Offset 0 does not exist on array<PhpParser\\Node\\Stmt\>\|null#'
paths:
- rules/Naming/Naming/PropertyNaming.php
-
message: '#Use quoted string in constructor "new PHPStan\\Type\\ObjectType\(\)" argument on position 0 instead of "\:\:class\. It prevent scoping of the class in building prefixed package#'
paths:
- packages-tests/NodeTypeResolver
- '#Content of method "configure\(\)" is duplicated with method "configure\(\)" in "Rector\\Composer\\Rector\\AddPackageToRequireComposerRector" class\. Use unique content or service instead#'
- '#Content of method "getFunctionLikePhpDocInfo\(\)" is duplicated with method "getFunctionLikePhpDocInfo\(\)" in "Rector\\TypeDeclaration\\TypeInferer\\ParamTypeInferer\\PHPUnitDataProviderParamTypeInferer" class\. Use unique content or service instead#'
- '#PHPDoc tag @return with type PhpParser\\Node\\Stmt\\ClassMethod\|PhpParser\\Node\\Stmt\\Function_\|Rector\\Naming\\Matcher\\Closure\|null is not subtype of native type PhpParser\\Node\\FunctionLike\|null#'
-
message: '#Do not use "array_filter" function with complex content, make it more readable with extracted method or single\-line statement#'
paths:
- src/Application/ActiveRectorsProvider.php
- '#Content of method "getIfNextReturn\(\)" is duplicated with method "getIfNextReturn\(\)" in "Rector\\EarlyReturn\\NodeFactory\\InvertedIfFactory" class\. Use unique content or service instead#'
- '#Content of method "matchReturnMethodCall\(\)" is duplicated with method "matchReturnMethodCall\(\)" in "Rector\\Defluent\\Rector\\Return_\\ReturnFluentChainMethodCallToNormalMethodCallRector" class\. Use unique content or service instead#'
- '#Content of method "matchReturnMethodCall\(\)" is duplicated with method "matchReturnMethodCall\(\)" in "Rector\\Defluent\\Rector\\Return_\\ReturnNewFluentChainMethodCallToNonFluentRector" class\. Use unique content or service instead#'
@ -565,9 +529,6 @@ parameters:
- '#Content of method "getNextExpression\(\)" is duplicated with method "getNextExpression\(\)" in "Rector\\CodingStyle\\Rector\\Assign\\ManualJsonStringToJsonEncodeArrayRector" class\. Use unique content or service instead#'
- '#Content of method "getFunctionLikePhpDocInfo\(\)" is duplicated with method "getFunctionLikePhpDocInfo\(\)" in "Rector\\NodeTypeResolver\\NodeTypeResolver\\ParamTypeResolver" class\. Use unique content or service instead#'
# faking phpstan reflection in tests
- '#Parameter \#1 \$classReflection of class PHPStan\\Type\\ThisType constructor expects PHPStan\\Reflection\\ClassReflection\|string, ReflectionClass<Rector\\NodeTypeResolver\\Tests\\PerNodeTypeResolver\\VariableTypeResolver\\Fixture\\ThisClass\> given#'
- '#Cognitive complexity for "Rector\\EarlyReturn\\Rector\\If_\\ChangeAndIfToEarlyReturnRector\:\:refactor\(\)" is 10, keep it under 9#'
- '#Parameter \#2 \$returnedStrictTypeNode of method Rector\\TypeDeclaration\\Rector\\ClassMethod\\ReturnTypeFromStrictTypedCallRector\:\:refactorSingleReturnType\(\) expects PhpParser\\Node\\Name\|PhpParser\\Node\\NullableType\|PhpParser\\Node\\UnionType, PhpParser\\Node\\Name\|PhpParser\\Node\\NullableType\|PHPStan\\Type\\UnionType given#'
- '#Method Rector\\DowngradePhp80\\Rector\\ClassMethod\\DowngradeTrailingCommasInParamUseRector\:\:processUses\(\) should return PhpParser\\Node\\Expr\\Closure but returns PhpParser\\Node#'
@ -580,11 +541,6 @@ parameters:
- '#(.*?) class\-string, string given#'
-
message: '#Strict comparison using \=\=\= between PHPStan\\Type\\Type and null will always evaluate to false#'
paths:
- packages/NodeTypeResolver/PHPStan/Type/TypeFactory.php
-
message: '#Do not use trait, extract to a service and dependency injection instead#'
paths:
@ -607,8 +563,3 @@ parameters:
- '*NodeVisitor.php'
- '#Class with base "NodeComparator" name is already used in "Symplify\\PHPStanRules\\Printer\\NodeComparator", "Rector\\Core\\PhpParser\\Comparing\\NodeComparator"\. Use unique name to make classes easy to recognize#'
-
message: '#Property with protected modifier is not allowed\. Use interface contract method instead#'
paths:
- packages/BetterPhpDocParser/PhpDocNodeFactory/AbstractPhpDocNodeFactory.php

View File

@ -69,6 +69,7 @@ return static function (ContainerConfigurator $containerConfigurator): void {
$parameters->set(Option::SKIP, [
StringClassNameToClassConstantRector::class,
// some classes in config might not exist without dev dependencies
SplitStringClassConstantToClassConstFetchRector::class,
PrivatizeLocalPropertyToPrivatePropertyRector::class => [__DIR__ . '/src/Rector/AbstractRector.php'],

View File

@ -31,6 +31,9 @@ final class MoveInterfacesToContractNamespaceDirectoryRectorTest extends Abstrac
}
}
/**
* @return Iterator<mixed>
*/
public function provideData(): Iterator
{
$smartFileSystem = new SmartFileSystem();

View File

@ -27,6 +27,9 @@ final class MoveServicesBySuffixToDirectoryRectorTest extends AbstractRectorTest
}
}
/**
* @return Iterator<mixed>
*/
public function provideData(): Iterator
{
$smartFileSystem = new SmartFileSystem();

View File

@ -26,6 +26,9 @@ final class MoveValueObjectsToValueObjectDirectoryRectorTest extends AbstractRec
}
}
/**
* @return Iterator<mixed>
*/
public function provideData(): Iterator
{
$smartFileSystem = new SmartFileSystem();

View File

@ -38,6 +38,9 @@ final class PropertyNamingTest extends AbstractKernelTestCase
}
}
/**
* @return Iterator<mixed>
*/
public function getExpectedNameFromMethodNameDataProvider(): Iterator
{
yield ['getMethods', 'method'];

View File

@ -30,6 +30,9 @@ final class ReplaceMagicPropertyEventWithEventClassRectorTest extends AbstractRe
$this->doTestExtraFile($expectedRelativeFilePath, $expectedContentFilePath);
}
/**
* @return Iterator<mixed>
*/
public function provideData(): Iterator
{
yield [

View File

@ -37,6 +37,9 @@ final class TestClassResolverTest extends AbstractKernelTestCase
$this->assertSame($expectedTestClass, $testClass);
}
/**
* @return Iterator<mixed>
*/
public function provideData(): Iterator
{
yield [SeeSomeClass::class, SeeSomeClassTest::class];

View File

@ -41,6 +41,9 @@ final class FileRelocationResolverTest extends AbstractKernelTestCase
$this->assertSame($expectedNewFileLocation, $newFileLocation);
}
/**
* @return Iterator<mixed>
*/
public function provideData(): Iterator
{
yield [

View File

@ -28,6 +28,9 @@ final class MultipleClassFileToPsr4ClassesRectorTest extends AbstractRectorTestC
$this->assertFilesWereAdded($expectedFilePathsWithContents);
}
/**
* @return Iterator<mixed>
*/
public function provideData(): Iterator
{
$smartFileSystem = new SmartFileSystem();

View File

@ -55,6 +55,9 @@ final class EregToPcreTransformerTest extends TestCase
yield ['hi', '#hi#mi'];
}
/**
* @return Iterator<mixed>
*/
public function provideDataDropping(): Iterator
{
yield ['mearie\.org', '#mearie\.org#m'];

View File

@ -50,6 +50,9 @@ final class TypeNormalizerTest extends AbstractKernelTestCase
$this->assertSame($expectedDocString, $unionDocString);
}
/**
* @return Iterator<mixed>
*/
public function provideDataNormalizeArrayOfUnionToUnionArray(): Iterator
{
$unionType = new UnionType([new StringType(), new IntegerType()]);

View File

@ -1,42 +0,0 @@
<?php
declare(strict_types=1);
namespace Rector\Core\Bootstrap;
use Symfony\Component\Console\Style\SymfonyStyle;
final class NoRectorsLoadedReporter
{
/**
* @var SymfonyStyle
*/
private $symfonyStyle;
public function __construct(SymfonyStyle $symfonyStyle)
{
$this->symfonyStyle = $symfonyStyle;
}
public function report(): void
{
$this->symfonyStyle->error('We could not find any Rector rules to run');
$this->symfonyStyle->writeln('You have few options to add them:');
$this->symfonyStyle->newLine();
$this->symfonyStyle->title('Add single rule to "rector.php"');
$this->symfonyStyle->writeln(' $services = $containerConfigurator->services();');
$this->symfonyStyle->writeln(' $services->set(...);');
$this->symfonyStyle->newLine(2);
$this->symfonyStyle->title('Add set of rules to "rector.php"');
$this->symfonyStyle->writeln(' $parameters = $containerConfigurator->parameters();');
$this->symfonyStyle->writeln(' $parameters->set(Option::SETS, [...]);');
$this->symfonyStyle->newLine(2);
$this->symfonyStyle->title('Missing "rector.php" in your project? Let Rector create it for you');
$this->symfonyStyle->writeln(' vendor/bin/rector init');
$this->symfonyStyle->newLine();
}
}

View File

@ -77,6 +77,13 @@ final class RectorConfigsResolver
}
}
// load config only if "sync" command is used to avoid useless rules traversing
if ($argvInput->getFirstArgument() === 'sync-annotation-parser') {
$configFileInfos[] = new SmartFileInfo(
__DIR__ . '/../../utils/doctrine-annotation-parser-syncer/config/config.php'
);
}
return new BootstrapConfigs($mainConfigFileInfo, $configFileInfos);
}
}

View File

@ -8,7 +8,6 @@ use Jean85\PrettyVersions;
use Rector\ChangesReporting\Output\ConsoleOutputFormatter;
use Rector\Core\Exception\Configuration\InvalidConfigurationException;
use Rector\Core\ValueObject\Bootstrap\BootstrapConfigs;
use Rector\Testing\PHPUnit\StaticPHPUnitEnvironment;
use Symfony\Component\Console\Input\InputInterface;
use Symplify\PackageBuilder\Parameter\ParameterProvider;
use Symplify\SmartFileSystem\SmartFileInfo;
@ -25,11 +24,6 @@ final class Configuration
*/
private $showProgressBar = true;
/**
* @var bool
*/
private $areAnyPhpRectorsLoaded = false;
/**
* @var bool
*/
@ -146,20 +140,6 @@ final class Configuration
return $this->showProgressBar;
}
public function areAnyPhpRectorsLoaded(): bool
{
if (StaticPHPUnitEnvironment::isPHPUnitRun()) {
return true;
}
return $this->areAnyPhpRectorsLoaded;
}
public function setAreAnyPhpRectorsLoaded(bool $areAnyPhpRectorsLoaded): void
{
$this->areAnyPhpRectorsLoaded = $areAnyPhpRectorsLoaded;
}
public function getOutputFile(): ?string
{
return $this->outputFile;

View File

@ -16,9 +16,9 @@ use Rector\Core\Console\Output\OutputFormatterCollector;
use Rector\Core\Exception\ShouldNotHappenException;
use Rector\Core\FileSystem\FilesFinder;
use Rector\Core\FileSystem\PhpFilesFinder;
use Rector\Core\Guard\RectorGuard;
use Rector\Core\NonPhpFile\NonPhpFileProcessor;
use Rector\Core\PhpParser\NodeTraverser\RectorNodeTraverser;
use Rector\Core\Reporting\MissingRectorRulesReporter;
use Rector\Core\ValueObject\StaticNonPhpFileSuffixes;
use Symfony\Component\Console\Application;
use Symfony\Component\Console\Command\Command;
@ -41,11 +41,6 @@ final class ProcessCommand extends Command
*/
private $additionalAutoloader;
/**
* @var RectorGuard
*/
private $rectorGuard;
/**
* @var ErrorAndDiffCollector
*/
@ -96,6 +91,11 @@ final class ProcessCommand extends Command
*/
private $changedFilesDetector;
/**
* @var MissingRectorRulesReporter
*/
private $missingRectorRulesReporter;
public function __construct(
AdditionalAutoloader $additionalAutoloader,
ChangedFilesDetector $changedFilesDetector,
@ -105,15 +105,14 @@ final class ProcessCommand extends Command
NonPhpFileProcessor $nonPhpFileProcessor,
OutputFormatterCollector $outputFormatterCollector,
RectorApplication $rectorApplication,
RectorGuard $rectorGuard,
RectorNodeTraverser $rectorNodeTraverser,
SymfonyStyle $symfonyStyle,
ComposerProcessor $composerProcessor,
PhpFilesFinder $phpFilesFinder
PhpFilesFinder $phpFilesFinder,
MissingRectorRulesReporter $missingRectorRulesReporter
) {
$this->filesFinder = $filesFinder;
$this->additionalAutoloader = $additionalAutoloader;
$this->rectorGuard = $rectorGuard;
$this->errorAndDiffCollector = $errorAndDiffCollector;
$this->configuration = $configuration;
$this->rectorApplication = $rectorApplication;
@ -124,6 +123,7 @@ final class ProcessCommand extends Command
$this->symfonyStyle = $symfonyStyle;
$this->composerProcessor = $composerProcessor;
$this->phpFilesFinder = $phpFilesFinder;
$this->missingRectorRulesReporter = $missingRectorRulesReporter;
parent::__construct();
}
@ -190,11 +190,13 @@ final class ProcessCommand extends Command
protected function execute(InputInterface $input, OutputInterface $output): int
{
$exitCode = $this->missingRectorRulesReporter->reportIfMissing();
if ($exitCode !== null) {
return $exitCode;
}
$this->configuration->resolveFromInput($input);
$this->configuration->validateConfigParameters();
$this->configuration->setAreAnyPhpRectorsLoaded((bool) $this->rectorNodeTraverser->getPhpRectorCount());
$this->rectorGuard->ensureSomeRectorsAreRegistered();
$paths = $this->configuration->getPaths();

View File

@ -7,11 +7,10 @@ namespace Rector\Core\Console;
use Composer\XdebugHandler\XdebugHandler;
use OutOfBoundsException;
use Rector\ChangesReporting\Output\ConsoleOutputFormatter;
use Rector\Core\Bootstrap\NoRectorsLoadedReporter;
use Rector\Core\Configuration\Configuration;
use Rector\Core\Configuration\Option;
use Rector\Core\Console\Command\ProcessCommand;
use Rector\Core\Exception\Configuration\InvalidConfigurationException;
use Rector\Core\Exception\NoRectorsLoadedException;
use Symfony\Component\Console\Application;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputDefinition;
@ -19,7 +18,6 @@ use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symplify\PackageBuilder\Console\Command\CommandNaming;
use Throwable;
final class ConsoleApplication extends Application
{
@ -28,20 +26,11 @@ final class ConsoleApplication extends Application
*/
private const NAME = 'Rector';
/**
* @var NoRectorsLoadedReporter
*/
private $noRectorsLoadedReporter;
/**
* @param Command[] $commands
*/
public function __construct(
Configuration $configuration,
NoRectorsLoadedReporter $noRectorsLoadedReporter,
CommandNaming $commandNaming,
array $commands = []
) {
public function __construct(Configuration $configuration, CommandNaming $commandNaming, array $commands = [])
{
try {
$version = $configuration->getPrettyVersion();
} catch (OutOfBoundsException $outOfBoundsException) {
@ -56,9 +45,7 @@ final class ConsoleApplication extends Application
}
$this->addCommands($commands);
$this->noRectorsLoadedReporter = $noRectorsLoadedReporter;
$this->setDefaultCommand('process');
$this->setDefaultCommand(CommandNaming::classToName(ProcessCommand::class));
}
public function doRun(InputInterface $input, OutputInterface $output): int
@ -94,16 +81,6 @@ final class ConsoleApplication extends Application
return parent::doRun($input, $output);
}
public function renderThrowable(Throwable $throwable, OutputInterface $output): void
{
if (is_a($throwable, NoRectorsLoadedException::class)) {
$this->noRectorsLoadedReporter->report();
return;
}
parent::renderThrowable($throwable, $output);
}
protected function getDefaultInputDefinition(): InputDefinition
{
$defaultInputDefinition = parent::getDefaultInputDefinition();

View File

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

View File

@ -1,30 +0,0 @@
<?php
declare(strict_types=1);
namespace Rector\Core\Guard;
use Rector\Core\Application\ActiveRectorsProvider;
use Rector\Core\Exception\NoRectorsLoadedException;
final class RectorGuard
{
/**
* @var ActiveRectorsProvider
*/
private $activeRectorsProvider;
public function __construct(ActiveRectorsProvider $activeRectorsProvider)
{
$this->activeRectorsProvider = $activeRectorsProvider;
}
public function ensureSomeRectorsAreRegistered(): void
{
if ($this->activeRectorsProvider->provide() !== []) {
return;
}
throw new NoRectorsLoadedException();
}
}

View File

@ -0,0 +1,58 @@
<?php
declare(strict_types=1);
namespace Rector\Core\Reporting;
use Rector\Core\PhpParser\NodeTraverser\RectorNodeTraverser;
use Symfony\Component\Console\Style\SymfonyStyle;
use Symplify\PackageBuilder\Console\ShellCode;
final class MissingRectorRulesReporter
{
/**
* @var RectorNodeTraverser
*/
private $rectorNodeTraverser;
/**
* @var SymfonyStyle
*/
private $symfonyStyle;
public function __construct(RectorNodeTraverser $rectorNodeTraverser, SymfonyStyle $symfonyStyle)
{
$this->rectorNodeTraverser = $rectorNodeTraverser;
$this->symfonyStyle = $symfonyStyle;
}
public function reportIfMissing(): ?int
{
if ($this->rectorNodeTraverser->getPhpRectorCount() !== 0) {
return null;
}
$this->report();
return ShellCode::ERROR;
}
public function report(): void
{
$this->symfonyStyle->warning('We could not find any Rector rules to run. You have 2 options to add them:');
$this->symfonyStyle->title('1. Add single rule to "rector.php"');
$this->symfonyStyle->writeln(' $services = $containerConfigurator->services();');
$this->symfonyStyle->writeln(' $services->set(...);');
$this->symfonyStyle->newLine(1);
$this->symfonyStyle->title('2. Add set of rules to "rector.php"');
$this->symfonyStyle->writeln(' $parameters = $containerConfigurator->parameters();');
$this->symfonyStyle->writeln(' $parameters->set(Option::SETS, [...]);');
$this->symfonyStyle->newLine(1);
$this->symfonyStyle->title('Missing "rector.php" in your project? Let Rector create it for you');
$this->symfonyStyle->writeln(' vendor/bin/rector init');
$this->symfonyStyle->newLine();
}
}