diff --git a/composer-dependency-analyser.php b/composer-dependency-analyser.php index 9b360269026..f0044011a89 100644 --- a/composer-dependency-analyser.php +++ b/composer-dependency-analyser.php @@ -12,8 +12,6 @@ ->addPathToScan('bin', false) // prepared test tooling ->ignoreErrorsOnPackage('phpunit/phpunit', [ErrorType::DEV_DEPENDENCY_IN_PROD]) - // pinned v3.x version - ->ignoreErrorsOnPackage('react/promise', [ErrorType::UNUSED_DEPENDENCY]) // ensure use version ^3.2.0 ->ignoreErrorsOnPackage('composer/pcre', [ErrorType::UNUSED_DEPENDENCY]) diff --git a/composer.json b/composer.json index aa60d6f9044..c7451cac3b9 100644 --- a/composer.json +++ b/composer.json @@ -27,7 +27,6 @@ "phpstan/phpstan": "^2.2.6", "react/child-process": "^0.6.5", "react/event-loop": "^1.6", - "react/promise": "^3.3", "react/socket": "^1.17", "rector/extension-installer": "^0.11.2", "rector/rector-doctrine": "dev-main", @@ -38,12 +37,12 @@ "symfony/console": "^6.4.24", "symfony/filesystem": "^8.1", "symfony/finder": "^8.1", - "symfony/process": "^8.1", "symplify/rule-doc-generator-contracts": "^11.2", "webmozart/assert": "^2.4" }, "require-dev": { "nette/robot-loader": "^4.1", + "symfony/process": "^8.1", "php-parallel-lint/php-parallel-lint": "^1.4", "phpstan/extension-installer": "^1.4", "phpstan/phpstan-deprecation-rules": "^2.0", diff --git a/phpstan.neon b/phpstan.neon index 975d5b858cc..f237e79a3ab 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -4,7 +4,6 @@ includes: rules: - Rector\Utils\PHPStan\Rule\CheaperGuardFirstRule - - Rector\Utils\PHPStan\Rule\SingleServiceRegistrationRule - Rector\Utils\PHPStan\Rule\RegisterRelatedPolyfillRectorRule parameters: diff --git a/src/Parallel/CpuCoreCountProvider.php b/src/Parallel/CpuCoreCountProvider.php index 49923cfb46f..c23aebf3dde 100644 --- a/src/Parallel/CpuCoreCountProvider.php +++ b/src/Parallel/CpuCoreCountProvider.php @@ -14,7 +14,8 @@ final class CpuCoreCountProvider public function provide(): int { try { - return new CpuCoreCounter()->getCount(); + return new CpuCoreCounter() + ->getCount(); } catch (NumberOfCpuCoreNotFound) { return self::DEFAULT_CORE_COUNT; } diff --git a/src/VendorLocker/ParentClassMethodTypeOverrideGuard.php b/src/VendorLocker/ParentClassMethodTypeOverrideGuard.php index c11b762200f..0d66dbbeacc 100644 --- a/src/VendorLocker/ParentClassMethodTypeOverrideGuard.php +++ b/src/VendorLocker/ParentClassMethodTypeOverrideGuard.php @@ -4,10 +4,10 @@ namespace Rector\VendorLocker; -use PhpParser\Node\Stmt\Class_; -use PhpParser\Node\Stmt\Interface_; use PhpParser\Node; +use PhpParser\Node\Stmt\Class_; use PhpParser\Node\Stmt\ClassMethod; +use PhpParser\Node\Stmt\Interface_; use PHPStan\Reflection\ClassReflection; use PHPStan\Reflection\MethodReflection; use PHPStan\Type\Type; diff --git a/utils/phpstan/src/Rule/SingleServiceRegistrationRule.php b/utils/phpstan/src/Rule/SingleServiceRegistrationRule.php deleted file mode 100644 index 508074b426f..00000000000 --- a/utils/phpstan/src/Rule/SingleServiceRegistrationRule.php +++ /dev/null @@ -1,222 +0,0 @@ - - * @see \Rector\Utils\PHPStan\Tests\Rule\SingleServiceRegistrationRule\SingleServiceRegistrationRuleTest - */ -final class SingleServiceRegistrationRule implements Rule -{ - private const string DUPLICATE_ERROR_MESSAGE = '"%s(%s)" is already called on line %d; register the service exactly once.'; - - private const string AUTOTAGGED_ERROR_MESSAGE = 'Service "%s" is registered as singleton and "%s" is autotagged, so this tag() call registers it twice.'; - - /** - * Interfaces RectorConfig tags on its own, see RectorConfig::$autotagInterfaces - * - * @var string[] - */ - private const array AUTOTAG_INTERFACES = [ - 'Symfony\Component\Console\Command\Command', - 'Rector\Contract\DependencyInjection\ResettableInterface', - ]; - - /** - * Registration calls on the container, and the arguments that identify what gets registered. - * The container itself is never part of the identity, so registerTagged() skips its first argument. - * - * @var array - */ - private const array REGISTRATION_METHOD_TO_ARG_POSITIONS = [ - 'singleton' => [0], - 'tag' => [0, 1], - 'registerTagged' => [1, 2], - ]; - - public function getNodeType(): string - { - return ClassMethod::class; - } - - /** - * @param ClassMethod $node - * @return list - */ - public function processNode(Node $node, Scope $scope): array - { - if ($node->stmts === null) { - return []; - } - - $ruleErrors = []; - $firstLineByRegistration = []; - $singletonClasses = []; - - $nodeFinder = new NodeFinder(); - - /** @var MethodCall[] $methodCalls */ - $methodCalls = $nodeFinder->findInstanceOf($node->stmts, MethodCall::class); - - foreach ($methodCalls as $methodCall) { - $methodName = $this->resolveRegistrationMethodName($methodCall); - if ($methodName === null) { - continue; - } - - $argumentKeys = $this->resolveArgumentKeys( - $methodCall, - self::REGISTRATION_METHOD_TO_ARG_POSITIONS[$methodName] - ); - - if ($argumentKeys === null) { - continue; - } - - if ($methodName === 'singleton') { - $singletonClasses[] = $argumentKeys[0]; - } - - $registration = $methodName . '(' . implode(', ', $argumentKeys) . ')'; - - if (isset($firstLineByRegistration[$registration])) { - $ruleErrors[] = RuleErrorBuilder::message(sprintf( - self::DUPLICATE_ERROR_MESSAGE, - $methodName, - implode(', ', $argumentKeys), - $firstLineByRegistration[$registration] - )) - ->identifier('rector.singleServiceRegistration') - ->line($methodCall->getStartLine()) - ->build(); - - continue; - } - - $firstLineByRegistration[$registration] = $methodCall->getStartLine(); - - if ($methodName !== 'tag') { - continue; - } - - if (! in_array($argumentKeys[1], self::AUTOTAG_INTERFACES, true)) { - continue; - } - - if (! in_array($argumentKeys[0], $singletonClasses, true)) { - continue; - } - - $ruleErrors[] = RuleErrorBuilder::message( - sprintf(self::AUTOTAGGED_ERROR_MESSAGE, $argumentKeys[0], $argumentKeys[1]) - ) - ->identifier('rector.singleServiceRegistration') - ->line($methodCall->getStartLine()) - ->build(); - } - - return $ruleErrors; - } - - /** - * The scope of a ClassMethod node is the method entry, where body variables are still mixed, - * so the container is matched on call shape instead of on its resolved type. - */ - private function resolveRegistrationMethodName(MethodCall $methodCall): ?string - { - if (! $methodCall->name instanceof Identifier) { - return null; - } - - $methodName = $methodCall->name->toString(); - if (! isset(self::REGISTRATION_METHOD_TO_ARG_POSITIONS[$methodName])) { - return null; - } - - // registerTagged() takes the container as its first argument, the rest are called on it - if ($methodName === 'registerTagged') { - $firstArg = $methodCall->getArgs()[0] ?? null; - if (! $firstArg instanceof Arg || ! $firstArg->value instanceof Variable) { - return null; - } - - return $methodName; - } - - if (! $methodCall->var instanceof Variable) { - return null; - } - - return $methodName; - } - - /** - * @param int[] $argPositions - * @return string[]|null - */ - private function resolveArgumentKeys(MethodCall $methodCall, array $argPositions): ?array - { - $args = $methodCall->getArgs(); - - $argumentKeys = []; - foreach ($argPositions as $argPosition) { - $arg = $args[$argPosition] ?? null; - if (! $arg instanceof Arg) { - return null; - } - - $argumentKey = $this->resolveArgumentKey($arg); - if ($argumentKey === null) { - return null; - } - - $argumentKeys[] = $argumentKey; - } - - return $argumentKeys; - } - - private function resolveArgumentKey(Arg $arg): ?string - { - if ($arg->value instanceof String_) { - return $arg->value->value; - } - - if (! $arg->value instanceof ClassConstFetch) { - return null; - } - - $classConstFetch = $arg->value; - if (! $classConstFetch->class instanceof Name || ! $classConstFetch->name instanceof Identifier) { - return null; - } - - $constantName = $classConstFetch->name->toString(); - if ($constantName === 'class') { - return $classConstFetch->class->toString(); - } - - return $classConstFetch->class->toString() . '::' . $constantName; - } -} diff --git a/utils/phpstan/tests/Rule/SingleServiceRegistrationRule/SingleServiceRegistrationRuleTest.php b/utils/phpstan/tests/Rule/SingleServiceRegistrationRule/SingleServiceRegistrationRuleTest.php deleted file mode 100644 index 1c0a7846a97..00000000000 --- a/utils/phpstan/tests/Rule/SingleServiceRegistrationRule/SingleServiceRegistrationRuleTest.php +++ /dev/null @@ -1,43 +0,0 @@ - - */ -final class SingleServiceRegistrationRuleTest extends RuleTestCase -{ - public function testDuplicateRegistration(): void - { - $this->analyse([__DIR__ . '/Source/DuplicateRegistrationFactory.php'], [ - [ - '"registerTagged(self::SOME_VISITOR_CLASSES, Rector\Utils\PHPStan\Tests\Rule\SingleServiceRegistrationRule\Source\SomeTagInterface)" is already called on line 22; register the service exactly once.', - 27, - ], - [ - '"tag(Rector\Utils\PHPStan\Tests\Rule\SingleServiceRegistrationRule\Source\SomeOtherService, Rector\Utils\PHPStan\Tests\Rule\SingleServiceRegistrationRule\Source\SomeTagInterface)" is already called on line 25; register the service exactly once.', - 29, - ], - [ - 'Service "Rector\Utils\PHPStan\Tests\Rule\SingleServiceRegistrationRule\Source\SomeResettableService" is registered as singleton and "Rector\Contract\DependencyInjection\ResettableInterface" is autotagged, so this tag() call registers it twice.', - 31, - ], - ]); - } - - public function testSingleRegistration(): void - { - $this->analyse([__DIR__ . '/Source/SingleRegistrationFactory.php'], []); - } - - protected function getRule(): Rule - { - return new SingleServiceRegistrationRule(); - } -} diff --git a/utils/phpstan/tests/Rule/SingleServiceRegistrationRule/Source/DuplicateRegistrationFactory.php b/utils/phpstan/tests/Rule/SingleServiceRegistrationRule/Source/DuplicateRegistrationFactory.php deleted file mode 100644 index 9cfa2014c63..00000000000 --- a/utils/phpstan/tests/Rule/SingleServiceRegistrationRule/Source/DuplicateRegistrationFactory.php +++ /dev/null @@ -1,47 +0,0 @@ - - */ - private const array SOME_VISITOR_CLASSES = []; - - public function create(): RectorConfig - { - $rectorConfig = new RectorConfig(); - - $this->registerTagged($rectorConfig, self::SOME_VISITOR_CLASSES, SomeTagInterface::class); - - $rectorConfig->singleton(SomeResettableService::class); - $rectorConfig->tag(SomeOtherService::class, SomeTagInterface::class); - - $this->registerTagged($rectorConfig, self::SOME_VISITOR_CLASSES, SomeTagInterface::class); - - $rectorConfig->tag(SomeOtherService::class, SomeTagInterface::class); - - $rectorConfig->tag(SomeResettableService::class, ResettableInterface::class); - - return $rectorConfig; - } - - /** - * @param array $classes - * @param class-string $tagInterface - */ - private function registerTagged(Container $container, array $classes, string $tagInterface): void - { - foreach ($classes as $class) { - $container->singleton($class); - $container->tag($class, $tagInterface); - } - } -} diff --git a/utils/phpstan/tests/Rule/SingleServiceRegistrationRule/Source/SingleRegistrationFactory.php b/utils/phpstan/tests/Rule/SingleServiceRegistrationRule/Source/SingleRegistrationFactory.php deleted file mode 100644 index 3f320fa7317..00000000000 --- a/utils/phpstan/tests/Rule/SingleServiceRegistrationRule/Source/SingleRegistrationFactory.php +++ /dev/null @@ -1,50 +0,0 @@ - - */ - private const array SOME_VISITOR_CLASSES = []; - - /** - * @var array - */ - private const array SOME_OTHER_CLASSES = []; - - public function create(): RectorConfig - { - $rectorConfig = new RectorConfig(); - - $this->registerTagged($rectorConfig, self::SOME_VISITOR_CLASSES, SomeTagInterface::class); - $this->registerTagged($rectorConfig, self::SOME_OTHER_CLASSES, SomeTagInterface::class); - - $rectorConfig->singleton(SomeOtherService::class); - $rectorConfig->tag(SomeOtherService::class, SomeTagInterface::class); - - // not a singleton here, so the autotagging never fires and this tag is what registers it - $rectorConfig->tag(SomeResettableService::class, ResettableInterface::class); - - return $rectorConfig; - } - - /** - * @param array $classes - * @param class-string $tagInterface - */ - private function registerTagged(Container $container, array $classes, string $tagInterface): void - { - foreach ($classes as $class) { - $container->singleton($class); - $container->tag($class, $tagInterface); - } - } -} diff --git a/utils/phpstan/tests/Rule/SingleServiceRegistrationRule/Source/SomeOtherService.php b/utils/phpstan/tests/Rule/SingleServiceRegistrationRule/Source/SomeOtherService.php deleted file mode 100644 index c432665f693..00000000000 --- a/utils/phpstan/tests/Rule/SingleServiceRegistrationRule/Source/SomeOtherService.php +++ /dev/null @@ -1,9 +0,0 @@ -