diff --git a/config/set/strict-booleans.php b/config/set/strict-booleans.php new file mode 100644 index 00000000000..921427a90cc --- /dev/null +++ b/config/set/strict-booleans.php @@ -0,0 +1,20 @@ +rules([ + BooleanInBooleanNotRuleFixerRector::class, + DisallowedEmptyRuleFixerRector::class, + BooleanInIfConditionRuleFixerRector::class, + BooleanInTernaryOperatorRuleFixerRector::class, + DisallowedShortTernaryRuleFixerRector::class, + ]); +}; diff --git a/packages/Caching/ValueObject/Storage/FileCacheStorage.php b/packages/Caching/ValueObject/Storage/FileCacheStorage.php index a5c0787b2ab..d49f17ba998 100644 --- a/packages/Caching/ValueObject/Storage/FileCacheStorage.php +++ b/packages/Caching/ValueObject/Storage/FileCacheStorage.php @@ -19,8 +19,8 @@ final class FileCacheStorage implements CacheStorageInterface { public function __construct( - private string $directory, - private \Symfony\Component\Filesystem\Filesystem $filesystem + private readonly string $directory, + private readonly \Symfony\Component\Filesystem\Filesystem $filesystem ) { } @@ -53,7 +53,7 @@ public function save(string $key, string $variableKey, mixed $data): void $this->filesystem-> mkdir($cacheFilePaths->getFirstDirectory()); $this->filesystem->mkdir($cacheFilePaths->getSecondDirectory()); - $path = $cacheFilePaths->getFilePath(); + $filePath = $cacheFilePaths->getFilePath(); $tmpPath = \sprintf('%s/%s.tmp', $this->directory, Random::generate()); $errorBefore = \error_get_last(); @@ -70,14 +70,14 @@ public function save(string $key, string $variableKey, mixed $data): void // for performance reasons we don't use SmartFileSystem FileSystem::write($tmpPath, \sprintf("addVisitor($commentRemovingNodeVisitor); + + parent::__construct(); } } diff --git a/packages/Set/ValueObject/SetList.php b/packages/Set/ValueObject/SetList.php index 5625ff29779..04425f4f451 100644 --- a/packages/Set/ValueObject/SetList.php +++ b/packages/Set/ValueObject/SetList.php @@ -26,6 +26,11 @@ final class SetList implements SetListInterface */ public const DEAD_CODE = __DIR__ . '/../../../config/set/dead-code.php'; + /** + * @var string + */ + public const STRICT_BOOLEANS = __DIR__ . '/../../../config/set/strict-booleans.php'; + /** * @var string */ diff --git a/packages/Testing/PHPUnit/Behavior/MovingFilesTrait.php b/packages/Testing/PHPUnit/Behavior/MovingFilesTrait.php index 99021383cbd..b9c38305575 100644 --- a/packages/Testing/PHPUnit/Behavior/MovingFilesTrait.php +++ b/packages/Testing/PHPUnit/Behavior/MovingFilesTrait.php @@ -19,12 +19,12 @@ protected function assertFileWasAdded(string $expectedFilePath, string $expected $wasFound = false; - foreach ($addedFilePathsWithContents as $addedFilePathsWithContent) { - if ($addedFilePathsWithContent->getFilePath() !== $expectedFilePath) { + foreach ($addedFilePathsWithContents as $addedFilePathWithContent) { + if ($addedFilePathWithContent->getFilePath() !== $expectedFilePath) { continue; } - $this->assertSame($expectedFileContents, $addedFilePathsWithContent->getFileContent()); + $this->assertSame($expectedFileContents, $addedFilePathWithContent->getFileContent()); $wasFound = true; } @@ -46,9 +46,9 @@ private function resolveAddedFilePathsWithContents(): array return $addedFilePathsWithContents; } - foreach ($addedFilesWithNodes as $addedFileWithNodes) { - $fileContent = $nodesWithFileDestinationPrinter->printNodesWithFileDestination($addedFileWithNodes); - $addedFilePathsWithContents[] = new AddedFileWithContent($addedFileWithNodes->getFilePath(), $fileContent); + foreach ($addedFilesWithNodes as $addedFileWithNode) { + $fileContent = $nodesWithFileDestinationPrinter->printNodesWithFileDestination($addedFileWithNode); + $addedFilePathsWithContents[] = new AddedFileWithContent($addedFileWithNode->getFilePath(), $fileContent); } return $addedFilePathsWithContents; diff --git a/phpstan.neon b/phpstan.neon index 0a9162ffd06..416d1e4c2b6 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -158,7 +158,7 @@ parameters: paths: - packages/Caching/ValueObject/Storage/FileCacheStorage.php - - message: '#"@\\rename\(\$tmpPath, \$path\)" is forbidden to use#' + message: '#"@\\rename(.*?)" is forbidden to use#' paths: - packages/Caching/ValueObject/Storage/FileCacheStorage.php - @@ -731,3 +731,4 @@ parameters: # resolve before Rector 1.0 - '#Call to deprecated method findParentType#' - '#Call to deprecated method findParentByTypes#' + - '#Instantiation of deprecated class Rector\\Core\\DependencyInjection\\CompilerPass\\AutowireArrayParameterCompilerPass#' diff --git a/rector.php b/rector.php index 3157fb2986b..e814b006735 100644 --- a/rector.php +++ b/rector.php @@ -8,7 +8,6 @@ use Rector\CodingStyle\Rector\String_\UseClassKeywordForClassNameResolutionRector; use Rector\CodingStyle\ValueObject\ReturnArrayClassMethodToYield; use Rector\Config\RectorConfig; -use Rector\Naming\Rector\Foreach_\RenameForeachValueVariableToMatchExprVariableRector; use Rector\Php55\Rector\String_\StringClassNameToClassConstantRector; use Rector\PHPUnit\Set\PHPUnitSetList; use Rector\Set\ValueObject\LevelSetList; @@ -28,6 +27,7 @@ SetList::EARLY_RETURN, PHPUnitSetList::PHPUNIT_CODE_QUALITY, SetList::CODING_STYLE, + SetList::STRICT_BOOLEANS, ]); $rectorConfig->rules([DeclareStrictTypesRector::class]); @@ -71,17 +71,9 @@ '**/Source/*', '**/Expected/*', '**/Expected*', - __DIR__ . '/tests/PhpUnit/MultipleFilesChangedTrait/MultipleFilesChangedTraitTest.php', - - // to keep original API from PHPStan untouched - __DIR__ . '/packages/Caching/ValueObject/Storage/FileCacheStorage.php', // keep configs untouched, as the classes are just strings UseClassKeywordForClassNameResolutionRector::class => [__DIR__ . '/config', '*/config/*'], - RenameForeachValueVariableToMatchExprVariableRector::class => [ - // false positive on plurals - __DIR__ . '/packages/Testing/PHPUnit/Behavior/MovingFilesTrait.php', - ], // avoid simplifying itself \Rector\CodeQuality\Rector\FuncCall\SimplifyRegexPatternRector::class => [ @@ -92,6 +84,13 @@ \Rector\TypeDeclaration\Rector\ClassMethod\AddMethodCallBasedStrictParamTypeRector::class => [ __DIR__ . '/rules/DeadCode/Rector/If_/RemoveUnusedNonEmptyArrayBeforeForeachRector.php', ], + + \Rector\Strict\Rector\If_\BooleanInIfConditionRuleFixerRector::class => [ + __DIR__ . '/src/DependencyInjection', + ], + \Rector\Strict\Rector\Ternary\DisallowedShortTernaryRuleFixerRector::class => [ + __DIR__ . '/src/DependencyInjection', + ], ]); $rectorConfig->phpstanConfig(__DIR__ . '/phpstan-for-rector.neon'); diff --git a/rules-tests/Strict/Rector/BooleanNot/BooleanInBooleanNotRuleFixerRector/Fixture/skip_negated_boolean.php.inc b/rules-tests/Strict/Rector/BooleanNot/BooleanInBooleanNotRuleFixerRector/Fixture/skip_negated_boolean.php.inc new file mode 100644 index 00000000000..f2fbfc2a9f3 --- /dev/null +++ b/rules-tests/Strict/Rector/BooleanNot/BooleanInBooleanNotRuleFixerRector/Fixture/skip_negated_boolean.php.inc @@ -0,0 +1,16 @@ +getClass(), PostRectorInterface::class, true); + } +} diff --git a/rules-tests/Strict/Rector/ClassMethod/AddConstructorParentCallRector/AddConstructorParentCallRectorTest.php b/rules-tests/Strict/Rector/ClassMethod/AddConstructorParentCallRector/AddConstructorParentCallRectorTest.php deleted file mode 100644 index 32039279e0c..00000000000 --- a/rules-tests/Strict/Rector/ClassMethod/AddConstructorParentCallRector/AddConstructorParentCallRectorTest.php +++ /dev/null @@ -1,28 +0,0 @@ -doTestFile($filePath); - } - - public static function provideData(): Iterator - { - return self::yieldFilesFromDirectory(__DIR__ . '/Fixture'); - } - - public function provideConfigFilePath(): string - { - return __DIR__ . '/config/configured_rule.php'; - } -} diff --git a/rules-tests/Strict/Rector/ClassMethod/AddConstructorParentCallRector/Fixture/fixture.php.inc b/rules-tests/Strict/Rector/ClassMethod/AddConstructorParentCallRector/Fixture/fixture.php.inc deleted file mode 100644 index ed6cf12a864..00000000000 --- a/rules-tests/Strict/Rector/ClassMethod/AddConstructorParentCallRector/Fixture/fixture.php.inc +++ /dev/null @@ -1,32 +0,0 @@ - ------ - diff --git a/rules-tests/Strict/Rector/ClassMethod/AddConstructorParentCallRector/Fixture/fixture2.php.inc b/rules-tests/Strict/Rector/ClassMethod/AddConstructorParentCallRector/Fixture/fixture2.php.inc deleted file mode 100644 index e9eeaa3330d..00000000000 --- a/rules-tests/Strict/Rector/ClassMethod/AddConstructorParentCallRector/Fixture/fixture2.php.inc +++ /dev/null @@ -1,32 +0,0 @@ - ------ - diff --git a/rules-tests/Strict/Rector/ClassMethod/AddConstructorParentCallRector/Fixture/fixture3.php.inc b/rules-tests/Strict/Rector/ClassMethod/AddConstructorParentCallRector/Fixture/fixture3.php.inc deleted file mode 100644 index 1d0c43e999c..00000000000 --- a/rules-tests/Strict/Rector/ClassMethod/AddConstructorParentCallRector/Fixture/fixture3.php.inc +++ /dev/null @@ -1,32 +0,0 @@ - ------ - diff --git a/rules-tests/Strict/Rector/ClassMethod/AddConstructorParentCallRector/Fixture/skip_already_has.php.inc b/rules-tests/Strict/Rector/ClassMethod/AddConstructorParentCallRector/Fixture/skip_already_has.php.inc deleted file mode 100644 index 3a643d67269..00000000000 --- a/rules-tests/Strict/Rector/ClassMethod/AddConstructorParentCallRector/Fixture/skip_already_has.php.inc +++ /dev/null @@ -1,15 +0,0 @@ -defaultValue = 5; - } -} diff --git a/rules-tests/Strict/Rector/ClassMethod/AddConstructorParentCallRector/config/configured_rule.php b/rules-tests/Strict/Rector/ClassMethod/AddConstructorParentCallRector/config/configured_rule.php deleted file mode 100644 index 9b607786848..00000000000 --- a/rules-tests/Strict/Rector/ClassMethod/AddConstructorParentCallRector/config/configured_rule.php +++ /dev/null @@ -1,10 +0,0 @@ -rule(AddConstructorParentCallRector::class); -}; diff --git a/rules/Naming/Naming/PropertyNaming.php b/rules/Naming/Naming/PropertyNaming.php index 0b6adefb86a..3b43d92ae7e 100644 --- a/rules/Naming/Naming/PropertyNaming.php +++ b/rules/Naming/Naming/PropertyNaming.php @@ -210,12 +210,14 @@ private function fqnToShortName(string $fqn): string private function removeInterfaceSuffixPrefix(string $className, string $category): string { // suffix - if (Strings::match($className, '#' . $category . '$#i')) { + $iSuffixMatch = Strings::match($className, '#' . $category . '$#i'); + if ($iSuffixMatch !== null) { return Strings::substring($className, 0, -strlen($category)); } // prefix - if (Strings::match($className, '#^' . $category . '#i')) { + $iPrefixMatch = Strings::match($className, '#^' . $category . '#i'); + if ($iPrefixMatch !== null) { return Strings::substring($className, strlen($category)); } diff --git a/rules/Strict/Rector/BooleanNot/BooleanInBooleanNotRuleFixerRector.php b/rules/Strict/Rector/BooleanNot/BooleanInBooleanNotRuleFixerRector.php index e735fe5e4ed..02ff84eaec2 100644 --- a/rules/Strict/Rector/BooleanNot/BooleanInBooleanNotRuleFixerRector.php +++ b/rules/Strict/Rector/BooleanNot/BooleanInBooleanNotRuleFixerRector.php @@ -83,6 +83,9 @@ public function getNodeTypes(): array public function refactorWithScope(Node $node, Scope $scope): ?Expr { $exprType = $scope->getType($node->expr); + if ($exprType->isBoolean()->yes()) { + return null; + } return $this->exactCompareFactory->createIdenticalFalsyCompare($exprType, $node->expr, $this->treatAsNonEmpty); } diff --git a/rules/Strict/Rector/ClassMethod/AddConstructorParentCallRector.php b/rules/Strict/Rector/ClassMethod/AddConstructorParentCallRector.php deleted file mode 100644 index 6dca9609b19..00000000000 --- a/rules/Strict/Rector/ClassMethod/AddConstructorParentCallRector.php +++ /dev/null @@ -1,117 +0,0 @@ -> - */ - public function getNodeTypes(): array - { - return [ClassMethod::class]; - } - - /** - * @param ClassMethod $node - */ - public function refactorWithScope(Node $node, Scope $scope): ?Node - { - if (! $this->isName($node, MethodName::CONSTRUCT)) { - return null; - } - - $classLike = $this->betterNodeFinder->findParentType($node, ClassLike::class); - if (! $classLike instanceof Class_) { - return null; - } - - if ($this->hasParentCallOfMethod($node)) { - return null; - } - - $this->dependencyClassMethodDecorator->decorateConstructorWithParentDependencies($classLike, $node, $scope); - - return $node; - } - - /** - * Looks for "parent::__construct" - */ - private function hasParentCallOfMethod(ClassMethod $classMethod): bool - { - return (bool) $this->betterNodeFinder->findFirst((array) $classMethod->stmts, function (Node $node): bool { - if (! $node instanceof StaticCall) { - return false; - } - - if (! $this->isName($node->class, ObjectReference::PARENT)) { - return false; - } - - return $this->isName($node->name, MethodName::CONSTRUCT); - }); - } -} diff --git a/rules/Transform/Rector/StaticCall/StaticCallToFuncCallRector.php b/rules/Transform/Rector/StaticCall/StaticCallToFuncCallRector.php index c125f9e62f6..acf49e9474c 100644 --- a/rules/Transform/Rector/StaticCall/StaticCallToFuncCallRector.php +++ b/rules/Transform/Rector/StaticCall/StaticCallToFuncCallRector.php @@ -21,12 +21,9 @@ final class StaticCallToFuncCallRector extends AbstractRector implements ConfigurableRectorInterface { /** - * @param StaticCallToFuncCall[] $staticCallsToFunctions + * @var StaticCallToFuncCall[] */ - public function __construct( - private array $staticCallsToFunctions = [] - ) { - } + private array $staticCallsToFunctions = []; public function getRuleDefinition(): RuleDefinition { diff --git a/src/DependencyInjection/CompilerPass/AutowireArrayParameterCompilerPass.php b/src/DependencyInjection/CompilerPass/AutowireArrayParameterCompilerPass.php index 519bc3cf9aa..9fdbfeb1223 100644 --- a/src/DependencyInjection/CompilerPass/AutowireArrayParameterCompilerPass.php +++ b/src/DependencyInjection/CompilerPass/AutowireArrayParameterCompilerPass.php @@ -18,6 +18,8 @@ use Symfony\Component\DependencyInjection\Reference; /** + * @deprecated Make the required services explicit, for faster autowire + * * @inspiration https://github.com/nette/di/pull/178 * @see \Rector\Core\Tests\DependencyInjection\CompilerPass\AutowireArrayParameterCompilerPassTest */ @@ -101,7 +103,9 @@ private function shouldSkipDefinition(ContainerBuilder $containerBuilder, Defini // skip 3rd party classes, they're autowired by own config $excludedNamespacePattern = '#^(' . implode('|', self::EXCLUDED_NAMESPACES) . ')\\\\#'; - if (Strings::match($resolvedClassName, $excludedNamespacePattern)) { + $excludedNamespaceMatch = Strings::match($resolvedClassName, $excludedNamespacePattern); + + if ($excludedNamespaceMatch !== null) { return true; } @@ -128,7 +132,8 @@ private function shouldSkipDefinition(ContainerBuilder $containerBuilder, Defini /** @var ReflectionMethod $constructorReflectionMethod */ $constructorReflectionMethod = $reflectionClass->getConstructor(); - return ! $constructorReflectionMethod->getParameters(); + + return $constructorReflectionMethod->getParameters() === []; } private function processParameters( diff --git a/src/DependencyInjection/DefinitionFinder.php b/src/DependencyInjection/DefinitionFinder.php index 68f71d89c99..577958332ef 100644 --- a/src/DependencyInjection/DefinitionFinder.php +++ b/src/DependencyInjection/DefinitionFinder.php @@ -23,6 +23,7 @@ public function findAllByType(ContainerBuilder $containerBuilder, string $type): $definitions = []; $containerBuilderDefinitions = $containerBuilder->getDefinitions(); foreach ($containerBuilderDefinitions as $name => $definition) { + /** @var Definition $definition */ $class = $definition->getClass() ?: $name; if (! $this->doesClassExists($class)) { continue; diff --git a/src/PhpParser/NodeTraverser/FileWithoutNamespaceNodeTraverser.php b/src/PhpParser/NodeTraverser/FileWithoutNamespaceNodeTraverser.php index dda16f37349..78291923fa7 100644 --- a/src/PhpParser/NodeTraverser/FileWithoutNamespaceNodeTraverser.php +++ b/src/PhpParser/NodeTraverser/FileWithoutNamespaceNodeTraverser.php @@ -16,6 +16,7 @@ final class FileWithoutNamespaceNodeTraverser extends NodeTraverser public function __construct( private readonly NodeFinder $nodeFinder, ) { + parent::__construct(); } /** diff --git a/src/PhpParser/NodeTraverser/RectorNodeTraverser.php b/src/PhpParser/NodeTraverser/RectorNodeTraverser.php index 16931657948..df0d033f0db 100644 --- a/src/PhpParser/NodeTraverser/RectorNodeTraverser.php +++ b/src/PhpParser/NodeTraverser/RectorNodeTraverser.php @@ -20,6 +20,7 @@ public function __construct( private readonly array $phpRectors, private readonly PhpVersionedFilter $phpVersionedFilter ) { + parent::__construct(); } /** diff --git a/utils/Command/MissingInSetCommand.php b/utils/Command/MissingInSetCommand.php index 998f59d1bab..285a2924b06 100644 --- a/utils/Command/MissingInSetCommand.php +++ b/utils/Command/MissingInSetCommand.php @@ -46,6 +46,14 @@ final class MissingInSetCommand extends Command __DIR__ . '/../../rules/Php80/Rector' => __DIR__ . '/../../config/set/php80.php', __DIR__ . '/../../rules/Php81/Rector' => __DIR__ . '/../../config/set/php81.php', __DIR__ . '/../../rules/Php82/Rector' => __DIR__ . '/../../config/set/php82.php', + __DIR__ . '/../../rules/Strict/Rector' => __DIR__ . '/../../config/set/strict-booleans.php', + __DIR__ . '/../../vendor/rector/rector-downgrade-php/rules/DowngradePhp70' => __DIR__ . '/../../vendor/rector/rector-downgrade-php/config/set/downgrade-php70.php', + __DIR__ . '/../../vendor/rector/rector-downgrade-php/rules/DowngradePhp71' => __DIR__ . '/../../vendor/rector/rector-downgrade-php/config/set/downgrade-php71.php', + __DIR__ . '/../../vendor/rector/rector-downgrade-php/rules/DowngradePhp72' => __DIR__ . '/../../vendor/rector/rector-downgrade-php/config/set/downgrade-php72.php', + __DIR__ . '/../../vendor/rector/rector-downgrade-php/rules/DowngradePhp73' => __DIR__ . '/../../vendor/rector/rector-downgrade-php/config/set/downgrade-php73.php', + __DIR__ . '/../../vendor/rector/rector-downgrade-php/rules/DowngradePhp74' => __DIR__ . '/../../vendor/rector/rector-downgrade-php/config/set/downgrade-php74.php', + __DIR__ . '/../../vendor/rector/rector-downgrade-php/rules/DowngradePhp80' => __DIR__ . '/../../vendor/rector/rector-downgrade-php/config/set/downgrade-php80.php', + __DIR__ . '/../../vendor/rector/rector-downgrade-php/rules/DowngradePhp81' => __DIR__ . '/../../vendor/rector/rector-downgrade-php/config/set/downgrade-php81.php', ]; /**