From 21f68185190d4a851acf9b62025772116926dda4 Mon Sep 17 00:00:00 2001 From: Tomas Votruba Date: Sun, 23 Mar 2025 21:42:24 +0100 Subject: [PATCH 1/3] add native command, to test failing --- .github/workflows/code_analysis.yaml | 2 +- artisan | 0 bin/validate-rule-definitions.php | 50 ------------------- bootstrap/app.php | 3 ++ composer.json | 2 +- .../ValidateRuleDefinitionsCommand.php | 41 +++++++++++++++ src/FileSystem/RectorFinder.php | 1 - 7 files changed, 46 insertions(+), 53 deletions(-) mode change 100644 => 100755 artisan delete mode 100644 bin/validate-rule-definitions.php create mode 100644 src/Console/Commands/ValidateRuleDefinitionsCommand.php diff --git a/.github/workflows/code_analysis.yaml b/.github/workflows/code_analysis.yaml index 7f75363b2..47f13d79c 100644 --- a/.github/workflows/code_analysis.yaml +++ b/.github/workflows/code_analysis.yaml @@ -15,7 +15,7 @@ jobs: # validate rule definitions, so they can be used in /find-rule - name: 'Validate rule definitions' - run: php bin/validate-rule-definitions.php + run: php artisan app:validate-rule-definitions.php - name: 'PHPStan' diff --git a/artisan b/artisan old mode 100644 new mode 100755 diff --git a/bin/validate-rule-definitions.php b/bin/validate-rule-definitions.php deleted file mode 100644 index 88ffe96b0..000000000 --- a/bin/validate-rule-definitions.php +++ /dev/null @@ -1,50 +0,0 @@ -make(RectorFinder::class); -$ruleMetadatas = array_merge($rectorFinder->findCore(), $rectorFinder->findCommunity()); - -$symfonyStyle = $container->make(SymfonyStyle::class); -$symfonyStyle->title(sprintf('Found %d rule definitions', count($ruleMetadatas))); - -$areRulesValid = true; - -foreach ($ruleMetadatas as $ruleMetadata) { - $isValid = true; - if ($ruleMetadata->getDescription() === '') { - $isValid = false; - $symfonyStyle->error(sprintf('Rule "%s" is missing description. Fill it first to enable rule search', $ruleMetadata->getRuleShortClass())); - } - - if ($ruleMetadata->getCodeSamples() === []) { - $symfonyStyle->error(sprintf('Rule "%s" is missing code samples. Fill it first to enable rule search', $ruleMetadata->getRuleShortClass())); - $isValid = false; - } - - if ($isValid === false) { - $areRulesValid = false; - continue; - } - - $symfonyStyle->writeln(sprintf('* Rule "%s" is valid', $ruleMetadata->getRuleShortClass())); -} - - -if ($areRulesValid) { - $symfonyStyle->success(sprintf('All %d rules are valid', count($ruleMetadatas))); - exit(Command::SUCCESS); -} - -exit(Command::FAILURE); diff --git a/bootstrap/app.php b/bootstrap/app.php index 42b869c2d..ea7bfdb19 100755 --- a/bootstrap/app.php +++ b/bootstrap/app.php @@ -11,6 +11,9 @@ ->withRouting( web: __DIR__.'/../routes/web.php', ) + ->withCommands([ + __DIR__ . '/../src/Console/Commands' + ]) ->withMiddleware(function (Middleware $middleware) { }) ->withExceptions(function (Exceptions $exceptions) { diff --git a/composer.json b/composer.json index 4fb85e57e..9c8897641 100644 --- a/composer.json +++ b/composer.json @@ -6,7 +6,7 @@ "php": "^8.2", "imagine/imagine": "^1.5", "jajo/jsondb": "^3.0.1", - "laravel/framework": "^11.36", + "laravel/framework": "^12.3", "league/commonmark": "^2.6", "livewire/livewire": "^3.5", "nesbot/carbon": "^3.8", diff --git a/src/Console/Commands/ValidateRuleDefinitionsCommand.php b/src/Console/Commands/ValidateRuleDefinitionsCommand.php new file mode 100644 index 000000000..b7ff34bc2 --- /dev/null +++ b/src/Console/Commands/ValidateRuleDefinitionsCommand.php @@ -0,0 +1,41 @@ +line('Validating core Rector rule definitions'); + + $coreRuleMetadatas = $rectorFinder->findCore(); + $this->info(sprintf('Found %d valid core Rector rules', count($coreRuleMetadatas))); + + $communityRuleMetadatas = $rectorFinder->findCommunity(); + $this->info(sprintf('Found %d valid community Rector rules', count($communityRuleMetadatas))); + +// foreach ($ruleMetadatas as $ruleMetadata) { +// $isValid = true; +// if ($ruleMetadata->getDescription() === '') { +// $isValid = false; +// $symfonyStyle->error(sprintf('Rule "%s" is missing description. Fill it first to enable rule search', $ruleMetadata->getRuleShortClass())); +// } +// +// if ($ruleMetadata->getCodeSamples() === []) { +// $symfonyStyle->error(sprintf('Rule "%s" is missing code samples. Fill it first to enable rule search', $ruleMetadata->getRuleShortClass())); +// $isValid = false; +// } +// } + + return self::SUCCESS; + } +} diff --git a/src/FileSystem/RectorFinder.php b/src/FileSystem/RectorFinder.php index f2cb01311..4f5665073 100644 --- a/src/FileSystem/RectorFinder.php +++ b/src/FileSystem/RectorFinder.php @@ -151,7 +151,6 @@ private function findInDirectoriesAndCreateRuleMetadatas(array $directories, arr $rector = $rectorReflectionClass->newInstanceWithoutConstructor(); - // this is validated by bin/validate-rule-definitions.php Assert::methodExists($rector, 'getRuleDefinition'); /** @var RectorInterface $rector */ From b4c020a6fa38e8c24f2467dae0d3292b5e067945 Mon Sep 17 00:00:00 2001 From: Tomas Votruba Date: Sun, 23 Mar 2025 21:47:47 +0100 Subject: [PATCH 2/3] test job that must fail --- .github/workflows/code_analysis.yaml | 2 +- composer.json | 5 +- composer.lock | 152 +++++++++--------- ...emovedataproviderparamkeysrector-php.patch | 11 ++ .../ValidateRuleDefinitionsCommand.php | 24 +-- 5 files changed, 104 insertions(+), 90 deletions(-) create mode 100644 patches/rector-rector-vendor-rector-rector-phpunit-rules-codequality-rector-class-removedataproviderparamkeysrector-php.patch diff --git a/.github/workflows/code_analysis.yaml b/.github/workflows/code_analysis.yaml index 47f13d79c..426354a50 100644 --- a/.github/workflows/code_analysis.yaml +++ b/.github/workflows/code_analysis.yaml @@ -15,7 +15,7 @@ jobs: # validate rule definitions, so they can be used in /find-rule - name: 'Validate rule definitions' - run: php artisan app:validate-rule-definitions.php + run: php artisan app:validate-rule-definitions - name: 'PHPStan' diff --git a/composer.json b/composer.json index 9c8897641..ca5f66342 100644 --- a/composer.json +++ b/composer.json @@ -79,9 +79,12 @@ }, "extra": { "patches": { + "rector/rector": [ + "patches/rector-rector-vendor-rector-rector-phpunit-rules-codequality-rector-class-removedataproviderparamkeysrector-php.patch" + ], "illuminate/container": [ "https://raw.githubusercontent.com/rectorphp/vendor-patches/main/patches/illuminate-container-container-php.patch" ] } } -} +} \ No newline at end of file diff --git a/composer.lock b/composer.lock index 9103c768d..8843aea58 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "66757993b25bc8062b97f9f60333aa10", + "content-hash": "a044096382c20e408227f9e7d66e6d84", "packages": [ { "name": "brick/math", @@ -493,16 +493,16 @@ }, { "name": "egulias/email-validator", - "version": "4.0.3", + "version": "4.0.4", "source": { "type": "git", "url": "https://github.com/egulias/EmailValidator.git", - "reference": "b115554301161fa21467629f1e1391c1936de517" + "reference": "d42c8731f0624ad6bdc8d3e5e9a4524f68801cfa" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/egulias/EmailValidator/zipball/b115554301161fa21467629f1e1391c1936de517", - "reference": "b115554301161fa21467629f1e1391c1936de517", + "url": "https://api.github.com/repos/egulias/EmailValidator/zipball/d42c8731f0624ad6bdc8d3e5e9a4524f68801cfa", + "reference": "d42c8731f0624ad6bdc8d3e5e9a4524f68801cfa", "shasum": "" }, "require": { @@ -548,7 +548,7 @@ ], "support": { "issues": "https://github.com/egulias/EmailValidator/issues", - "source": "https://github.com/egulias/EmailValidator/tree/4.0.3" + "source": "https://github.com/egulias/EmailValidator/tree/4.0.4" }, "funding": [ { @@ -556,7 +556,7 @@ "type": "github" } ], - "time": "2024-12-27T00:36:43+00:00" + "time": "2025-03-06T22:45:56+00:00" }, { "name": "fruitcake/php-cors", @@ -1215,20 +1215,20 @@ }, { "name": "laravel/framework", - "version": "v11.44.1", + "version": "v12.3.0", "source": { "type": "git", "url": "https://github.com/laravel/framework.git", - "reference": "0883d4175f4e2b5c299e7087ad3c74f2ce195c6d" + "reference": "ca0412e978f78ecea0cafbe34dd8b18010064f73" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/framework/zipball/0883d4175f4e2b5c299e7087ad3c74f2ce195c6d", - "reference": "0883d4175f4e2b5c299e7087ad3c74f2ce195c6d", + "url": "https://api.github.com/repos/laravel/framework/zipball/ca0412e978f78ecea0cafbe34dd8b18010064f73", + "reference": "ca0412e978f78ecea0cafbe34dd8b18010064f73", "shasum": "" }, "require": { - "brick/math": "^0.9.3|^0.10.2|^0.11|^0.12", + "brick/math": "^0.11|^0.12", "composer-runtime-api": "^2.2", "doctrine/inflector": "^2.0.5", "dragonmantank/cron-expression": "^3.4", @@ -1243,32 +1243,32 @@ "fruitcake/php-cors": "^1.3", "guzzlehttp/guzzle": "^7.8.2", "guzzlehttp/uri-template": "^1.0", - "laravel/prompts": "^0.1.18|^0.2.0|^0.3.0", + "laravel/prompts": "^0.3.0", "laravel/serializable-closure": "^1.3|^2.0", "league/commonmark": "^2.6", "league/flysystem": "^3.25.1", "league/flysystem-local": "^3.25.1", "league/uri": "^7.5.1", "monolog/monolog": "^3.0", - "nesbot/carbon": "^2.72.6|^3.8.4", + "nesbot/carbon": "^3.8.4", "nunomaduro/termwind": "^2.0", "php": "^8.2", "psr/container": "^1.1.1|^2.0.1", "psr/log": "^1.0|^2.0|^3.0", "psr/simple-cache": "^1.0|^2.0|^3.0", "ramsey/uuid": "^4.7", - "symfony/console": "^7.0.3", - "symfony/error-handler": "^7.0.3", - "symfony/finder": "^7.0.3", + "symfony/console": "^7.2.0", + "symfony/error-handler": "^7.2.0", + "symfony/finder": "^7.2.0", "symfony/http-foundation": "^7.2.0", - "symfony/http-kernel": "^7.0.3", - "symfony/mailer": "^7.0.3", - "symfony/mime": "^7.0.3", + "symfony/http-kernel": "^7.2.0", + "symfony/mailer": "^7.2.0", + "symfony/mime": "^7.2.0", "symfony/polyfill-php83": "^1.31", - "symfony/process": "^7.0.3", - "symfony/routing": "^7.0.3", - "symfony/uid": "^7.0.3", - "symfony/var-dumper": "^7.0.3", + "symfony/process": "^7.2.0", + "symfony/routing": "^7.2.0", + "symfony/uid": "^7.2.0", + "symfony/var-dumper": "^7.2.0", "tijsverkoyen/css-to-inline-styles": "^2.2.5", "vlucas/phpdotenv": "^5.6.1", "voku/portable-ascii": "^2.0.2" @@ -1332,17 +1332,17 @@ "league/flysystem-read-only": "^3.25.1", "league/flysystem-sftp-v3": "^3.25.1", "mockery/mockery": "^1.6.10", - "orchestra/testbench-core": "^9.11.2", + "orchestra/testbench-core": "^10.0.0", "pda/pheanstalk": "^5.0.6", "php-http/discovery": "^1.15", "phpstan/phpstan": "^2.0", - "phpunit/phpunit": "^10.5.35|^11.3.6|^12.0.1", + "phpunit/phpunit": "^10.5.35|^11.5.3|^12.0.1", "predis/predis": "^2.3", "resend/resend-php": "^0.10.0", - "symfony/cache": "^7.0.3", - "symfony/http-client": "^7.0.3", - "symfony/psr-http-message-bridge": "^7.0.3", - "symfony/translation": "^7.0.3" + "symfony/cache": "^7.2.0", + "symfony/http-client": "^7.2.0", + "symfony/psr-http-message-bridge": "^7.2.0", + "symfony/translation": "^7.2.0" }, "suggest": { "ably/ably-php": "Required to use the Ably broadcast driver (^1.0).", @@ -1368,22 +1368,22 @@ "mockery/mockery": "Required to use mocking (^1.6).", "pda/pheanstalk": "Required to use the beanstalk queue driver (^5.0).", "php-http/discovery": "Required to use PSR-7 bridging features (^1.15).", - "phpunit/phpunit": "Required to use assertions and run tests (^10.5.35|^11.3.6|^12.0.1).", + "phpunit/phpunit": "Required to use assertions and run tests (^10.5.35|^11.5.3|^12.0.1).", "predis/predis": "Required to use the predis connector (^2.3).", "psr/http-message": "Required to allow Storage::put to accept a StreamInterface (^1.0).", "pusher/pusher-php-server": "Required to use the Pusher broadcast driver (^6.0|^7.0).", "resend/resend-php": "Required to enable support for the Resend mail transport (^0.10.0).", - "symfony/cache": "Required to PSR-6 cache bridge (^7.0).", - "symfony/filesystem": "Required to enable support for relative symbolic links (^7.0).", - "symfony/http-client": "Required to enable support for the Symfony API mail transports (^7.0).", - "symfony/mailgun-mailer": "Required to enable support for the Mailgun mail transport (^7.0).", - "symfony/postmark-mailer": "Required to enable support for the Postmark mail transport (^7.0).", - "symfony/psr-http-message-bridge": "Required to use PSR-7 bridging features (^7.0)." + "symfony/cache": "Required to PSR-6 cache bridge (^7.2).", + "symfony/filesystem": "Required to enable support for relative symbolic links (^7.2).", + "symfony/http-client": "Required to enable support for the Symfony API mail transports (^7.2).", + "symfony/mailgun-mailer": "Required to enable support for the Mailgun mail transport (^7.2).", + "symfony/postmark-mailer": "Required to enable support for the Postmark mail transport (^7.2).", + "symfony/psr-http-message-bridge": "Required to use PSR-7 bridging features (^7.2)." }, "type": "library", "extra": { "branch-alias": { - "dev-master": "11.x-dev" + "dev-master": "12.x-dev" } }, "autoload": { @@ -1426,7 +1426,7 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2025-03-05T15:34:10+00:00" + "time": "2025-03-18T13:49:19+00:00" }, { "name": "laravel/prompts", @@ -2101,16 +2101,16 @@ }, { "name": "livewire/livewire", - "version": "v3.6.1", + "version": "v3.6.2", "source": { "type": "git", "url": "https://github.com/livewire/livewire.git", - "reference": "0df0a762698176d714e42e2dfed92b6b9e24b8e4" + "reference": "8f8914731f5eb43b6bb145d87c8d5a9edfc89313" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/livewire/livewire/zipball/0df0a762698176d714e42e2dfed92b6b9e24b8e4", - "reference": "0df0a762698176d714e42e2dfed92b6b9e24b8e4", + "url": "https://api.github.com/repos/livewire/livewire/zipball/8f8914731f5eb43b6bb145d87c8d5a9edfc89313", + "reference": "8f8914731f5eb43b6bb145d87c8d5a9edfc89313", "shasum": "" }, "require": { @@ -2165,7 +2165,7 @@ "description": "A front-end framework for Laravel.", "support": { "issues": "https://github.com/livewire/livewire/issues", - "source": "https://github.com/livewire/livewire/tree/v3.6.1" + "source": "https://github.com/livewire/livewire/tree/v3.6.2" }, "funding": [ { @@ -2173,7 +2173,7 @@ "type": "github" } ], - "time": "2025-03-04T21:48:52+00:00" + "time": "2025-03-12T20:24:15+00:00" }, { "name": "monolog/monolog", @@ -3268,16 +3268,16 @@ }, { "name": "ramsey/collection", - "version": "2.1.0", + "version": "2.1.1", "source": { "type": "git", "url": "https://github.com/ramsey/collection.git", - "reference": "3c5990b8a5e0b79cd1cf11c2dc1229e58e93f109" + "reference": "344572933ad0181accbf4ba763e85a0306a8c5e2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ramsey/collection/zipball/3c5990b8a5e0b79cd1cf11c2dc1229e58e93f109", - "reference": "3c5990b8a5e0b79cd1cf11c2dc1229e58e93f109", + "url": "https://api.github.com/repos/ramsey/collection/zipball/344572933ad0181accbf4ba763e85a0306a8c5e2", + "reference": "344572933ad0181accbf4ba763e85a0306a8c5e2", "shasum": "" }, "require": { @@ -3338,9 +3338,9 @@ ], "support": { "issues": "https://github.com/ramsey/collection/issues", - "source": "https://github.com/ramsey/collection/tree/2.1.0" + "source": "https://github.com/ramsey/collection/tree/2.1.1" }, - "time": "2025-03-02T04:48:29+00:00" + "time": "2025-03-22T05:38:12+00:00" }, { "name": "ramsey/uuid", @@ -6821,21 +6821,21 @@ }, { "name": "phpecs/phpecs", - "version": "2.0.1", + "version": "2.1.1", "source": { "type": "git", "url": "https://github.com/TomasVotruba/ecs.git", - "reference": "048894c4d4bddee273ff5372acd0a4e692849874" + "reference": "14fdfbdd98b4a6769d2cd81d450e8233d7c40f89" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/TomasVotruba/ecs/zipball/048894c4d4bddee273ff5372acd0a4e692849874", - "reference": "048894c4d4bddee273ff5372acd0a4e692849874", + "url": "https://api.github.com/repos/TomasVotruba/ecs/zipball/14fdfbdd98b4a6769d2cd81d450e8233d7c40f89", + "reference": "14fdfbdd98b4a6769d2cd81d450e8233d7c40f89", "shasum": "" }, "require": { "php": "^7.2|^8.0", - "symplify/easy-coding-standard": "^12.5" + "symplify/easy-coding-standard": "^12.5.9" }, "type": "library", "notification-url": "https://packagist.org/downloads/", @@ -6845,9 +6845,9 @@ "description": "The easiest way to use Coding Standard", "support": { "issues": "https://github.com/TomasVotruba/ecs/issues", - "source": "https://github.com/TomasVotruba/ecs/tree/2.0.1" + "source": "https://github.com/TomasVotruba/ecs/tree/2.1.1" }, - "time": "2025-02-18T08:38:45+00:00" + "time": "2025-03-17T15:32:26+00:00" }, { "name": "phpstan/extension-installer", @@ -7472,16 +7472,16 @@ }, { "name": "sebastian/code-unit", - "version": "3.0.2", + "version": "3.0.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/code-unit.git", - "reference": "ee88b0cdbe74cf8dd3b54940ff17643c0d6543ca" + "reference": "54391c61e4af8078e5b276ab082b6d3c54c9ad64" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/ee88b0cdbe74cf8dd3b54940ff17643c0d6543ca", - "reference": "ee88b0cdbe74cf8dd3b54940ff17643c0d6543ca", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/54391c61e4af8078e5b276ab082b6d3c54c9ad64", + "reference": "54391c61e4af8078e5b276ab082b6d3c54c9ad64", "shasum": "" }, "require": { @@ -7517,7 +7517,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/code-unit/issues", "security": "https://github.com/sebastianbergmann/code-unit/security/policy", - "source": "https://github.com/sebastianbergmann/code-unit/tree/3.0.2" + "source": "https://github.com/sebastianbergmann/code-unit/tree/3.0.3" }, "funding": [ { @@ -7525,7 +7525,7 @@ "type": "github" } ], - "time": "2024-12-12T09:59:06+00:00" + "time": "2025-03-19T07:56:08+00:00" }, { "name": "sebastian/code-unit-reverse-lookup", @@ -8230,16 +8230,16 @@ }, { "name": "sebastian/type", - "version": "5.1.0", + "version": "5.1.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/type.git", - "reference": "461b9c5da241511a2a0e8f240814fb23ce5c0aac" + "reference": "a8a7e30534b0eb0c77cd9d07e82de1a114389f5e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/461b9c5da241511a2a0e8f240814fb23ce5c0aac", - "reference": "461b9c5da241511a2a0e8f240814fb23ce5c0aac", + "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/a8a7e30534b0eb0c77cd9d07e82de1a114389f5e", + "reference": "a8a7e30534b0eb0c77cd9d07e82de1a114389f5e", "shasum": "" }, "require": { @@ -8275,7 +8275,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/type/issues", "security": "https://github.com/sebastianbergmann/type/security/policy", - "source": "https://github.com/sebastianbergmann/type/tree/5.1.0" + "source": "https://github.com/sebastianbergmann/type/tree/5.1.2" }, "funding": [ { @@ -8283,7 +8283,7 @@ "type": "github" } ], - "time": "2024-09-17T13:12:04+00:00" + "time": "2025-03-18T13:35:50+00:00" }, { "name": "sebastian/version", @@ -8341,16 +8341,16 @@ }, { "name": "symplify/easy-coding-standard", - "version": "12.5.8", + "version": "12.5.9", "source": { "type": "git", "url": "https://github.com/easy-coding-standard/easy-coding-standard.git", - "reference": "2bf0e468dc9679f3835c835cd3fd4a25ff6e4e14" + "reference": "4b20b6fa6a1509811b91c3d931f799febb48b75a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/easy-coding-standard/easy-coding-standard/zipball/2bf0e468dc9679f3835c835cd3fd4a25ff6e4e14", - "reference": "2bf0e468dc9679f3835c835cd3fd4a25ff6e4e14", + "url": "https://api.github.com/repos/easy-coding-standard/easy-coding-standard/zipball/4b20b6fa6a1509811b91c3d931f799febb48b75a", + "reference": "4b20b6fa6a1509811b91c3d931f799febb48b75a", "shasum": "" }, "require": { @@ -8386,7 +8386,7 @@ ], "support": { "issues": "https://github.com/easy-coding-standard/easy-coding-standard/issues", - "source": "https://github.com/easy-coding-standard/easy-coding-standard/tree/12.5.8" + "source": "https://github.com/easy-coding-standard/easy-coding-standard/tree/12.5.9" }, "funding": [ { @@ -8398,7 +8398,7 @@ "type": "github" } ], - "time": "2025-01-31T13:59:38+00:00" + "time": "2025-03-17T15:30:37+00:00" }, { "name": "theseer/tokenizer", diff --git a/patches/rector-rector-vendor-rector-rector-phpunit-rules-codequality-rector-class-removedataproviderparamkeysrector-php.patch b/patches/rector-rector-vendor-rector-rector-phpunit-rules-codequality-rector-class-removedataproviderparamkeysrector-php.patch new file mode 100644 index 000000000..48046acda --- /dev/null +++ b/patches/rector-rector-vendor-rector-rector-phpunit-rules-codequality-rector-class-removedataproviderparamkeysrector-php.patch @@ -0,0 +1,11 @@ +--- /dev/null ++++ ../vendor/rector/rector-phpunit/rules/CodeQuality/Rector/Class_/RemoveDataProviderParamKeysRector.php +@@ -68,7 +68,7 @@ + public function provideData(): array + { + return [ +- ['Tom'], ++ 'name' => ['Tom'], + ]; + } + } diff --git a/src/Console/Commands/ValidateRuleDefinitionsCommand.php b/src/Console/Commands/ValidateRuleDefinitionsCommand.php index b7ff34bc2..9c3066fde 100644 --- a/src/Console/Commands/ValidateRuleDefinitionsCommand.php +++ b/src/Console/Commands/ValidateRuleDefinitionsCommand.php @@ -23,18 +23,18 @@ public function handle(RectorFinder $rectorFinder): int $communityRuleMetadatas = $rectorFinder->findCommunity(); $this->info(sprintf('Found %d valid community Rector rules', count($communityRuleMetadatas))); -// foreach ($ruleMetadatas as $ruleMetadata) { -// $isValid = true; -// if ($ruleMetadata->getDescription() === '') { -// $isValid = false; -// $symfonyStyle->error(sprintf('Rule "%s" is missing description. Fill it first to enable rule search', $ruleMetadata->getRuleShortClass())); -// } -// -// if ($ruleMetadata->getCodeSamples() === []) { -// $symfonyStyle->error(sprintf('Rule "%s" is missing code samples. Fill it first to enable rule search', $ruleMetadata->getRuleShortClass())); -// $isValid = false; -// } -// } + // foreach ($ruleMetadatas as $ruleMetadata) { + // $isValid = true; + // if ($ruleMetadata->getDescription() === '') { + // $isValid = false; + // $symfonyStyle->error(sprintf('Rule "%s" is missing description. Fill it first to enable rule search', $ruleMetadata->getRuleShortClass())); + // } + // + // if ($ruleMetadata->getCodeSamples() === []) { + // $symfonyStyle->error(sprintf('Rule "%s" is missing code samples. Fill it first to enable rule search', $ruleMetadata->getRuleShortClass())); + // $isValid = false; + // } + // } return self::SUCCESS; } From 1ce97096db6101ad5590f9ee2d4e455f31d9d232 Mon Sep 17 00:00:00 2001 From: Tomas Votruba Date: Mon, 24 Mar 2025 00:54:28 +0100 Subject: [PATCH 3/3] exact version --- composer.json | 5 +- ...emovedataproviderparamkeysrector-php.patch | 11 ---- phpstan.neon | 11 ++-- .../ValidateRuleDefinitionsCommand.php | 52 ++++++++++++++----- .../InvalidRuleDescriptionException.php | 11 ++++ src/FileSystem/RectorFinder.php | 24 +++++++-- src/Sets/RectorSetsTreeProvider.php | 30 ++--------- 7 files changed, 83 insertions(+), 61 deletions(-) delete mode 100644 patches/rector-rector-vendor-rector-rector-phpunit-rules-codequality-rector-class-removedataproviderparamkeysrector-php.patch create mode 100644 src/Exception/InvalidRuleDescriptionException.php diff --git a/composer.json b/composer.json index ca5f66342..9c8897641 100644 --- a/composer.json +++ b/composer.json @@ -79,12 +79,9 @@ }, "extra": { "patches": { - "rector/rector": [ - "patches/rector-rector-vendor-rector-rector-phpunit-rules-codequality-rector-class-removedataproviderparamkeysrector-php.patch" - ], "illuminate/container": [ "https://raw.githubusercontent.com/rectorphp/vendor-patches/main/patches/illuminate-container-container-php.patch" ] } } -} \ No newline at end of file +} diff --git a/patches/rector-rector-vendor-rector-rector-phpunit-rules-codequality-rector-class-removedataproviderparamkeysrector-php.patch b/patches/rector-rector-vendor-rector-rector-phpunit-rules-codequality-rector-class-removedataproviderparamkeysrector-php.patch deleted file mode 100644 index 48046acda..000000000 --- a/patches/rector-rector-vendor-rector-rector-phpunit-rules-codequality-rector-class-removedataproviderparamkeysrector-php.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- /dev/null -+++ ../vendor/rector/rector-phpunit/rules/CodeQuality/Rector/Class_/RemoveDataProviderParamKeysRector.php -@@ -68,7 +68,7 @@ - public function provideData(): array - { - return [ -- ['Tom'], -+ 'name' => ['Tom'], - ]; - } - } diff --git a/phpstan.neon b/phpstan.neon index 2c1bdd770..729ae9e20 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -19,7 +19,8 @@ parameters: - tests/bootstrap.php level: 8 - reportUnmatchedIgnoredErrors: false + + # reportUnmatchedIgnoredErrors: false ignoreErrors: # float allowed @@ -61,6 +62,10 @@ parameters: identifier: return.type # enforce native +# - +# path: src/FileSystem/RectorFinder.php +# identifier: varTag.nativeType + - - path: src/FileSystem/RectorFinder.php - identifier: varTag.nativeType + message: '#Parameter \#3 \$rectorClasses of class App\\RuleFilter\\ValueObject\\RectorSet constructor expects array>, array, array>|class-string> given#' + path: src/Sets/RectorSetsTreeProvider.php diff --git a/src/Console/Commands/ValidateRuleDefinitionsCommand.php b/src/Console/Commands/ValidateRuleDefinitionsCommand.php index 9c3066fde..31024ce89 100644 --- a/src/Console/Commands/ValidateRuleDefinitionsCommand.php +++ b/src/Console/Commands/ValidateRuleDefinitionsCommand.php @@ -9,6 +9,8 @@ final class ValidateRuleDefinitionsCommand extends Command { + private const MIN_RULE_LIMIT = 655; + protected $signature = 'app:validate-rule-definitions'; protected $description = 'Validate Rector rule definitions'; @@ -23,18 +25,44 @@ public function handle(RectorFinder $rectorFinder): int $communityRuleMetadatas = $rectorFinder->findCommunity(); $this->info(sprintf('Found %d valid community Rector rules', count($communityRuleMetadatas))); - // foreach ($ruleMetadatas as $ruleMetadata) { - // $isValid = true; - // if ($ruleMetadata->getDescription() === '') { - // $isValid = false; - // $symfonyStyle->error(sprintf('Rule "%s" is missing description. Fill it first to enable rule search', $ruleMetadata->getRuleShortClass())); - // } - // - // if ($ruleMetadata->getCodeSamples() === []) { - // $symfonyStyle->error(sprintf('Rule "%s" is missing code samples. Fill it first to enable rule search', $ruleMetadata->getRuleShortClass())); - // $isValid = false; - // } - // } + $ruleMetadatas = array_merge($coreRuleMetadatas, $communityRuleMetadatas); + + $isValid = true; + foreach ($ruleMetadatas as $ruleMetadata) { + if ($ruleMetadata->getDescription() === '') { + $isValid = false; + $this->error( + sprintf( + 'Rule "%s" is missing description. Fill it first to enable rule search', + $ruleMetadata->getRuleShortClass() + ) + ); + } + + if ($ruleMetadata->getCodeSamples() === []) { + $this->error( + sprintf( + 'Rule "%s" is missing code samples. Fill it first to enable rule search', + $ruleMetadata->getRuleShortClass() + ) + ); + $isValid = false; + } + } + + if ($isValid === false) { + return self::FAILURE; + } + + if (count($ruleMetadatas) < self::MIN_RULE_LIMIT) { + $this->error(sprintf( + 'Only %d rule definitions found. Make sure all are loaded and above %d', + count($ruleMetadatas), + self::MIN_RULE_LIMIT + )); + + return self::FAILURE; + } return self::SUCCESS; } diff --git a/src/Exception/InvalidRuleDescriptionException.php b/src/Exception/InvalidRuleDescriptionException.php new file mode 100644 index 000000000..2c219f52d --- /dev/null +++ b/src/Exception/InvalidRuleDescriptionException.php @@ -0,0 +1,11 @@ +newInstanceWithoutConstructor(); - - Assert::methodExists($rector, 'getRuleDefinition'); + try { + $rector = $rectorReflectionClass->newInstanceWithoutConstructor(); + + Assert::methodExists($rector, 'getRuleDefinition'); + /** @var RectorInterface $rector */ + $ruleDefinition = $rector->getRuleDefinition(); + + } catch (Throwable $throwable) { + throw new InvalidRuleDescriptionException( + sprintf( + 'Rule "%s" has invalid code samples:%s"%s"', + $rectorClass, + PHP_EOL . PHP_EOL, + $throwable->getMessage() + ) + ); + } - /** @var RectorInterface $rector */ - $ruleDefinition = $rector->getRuleDefinition(); $ruleDefinition->setRuleClass($rectorClass); $currentRuleSets = $this->findRuleUsedSets($ruleDefinition, $rectorSets); diff --git a/src/Sets/RectorSetsTreeProvider.php b/src/Sets/RectorSetsTreeProvider.php index eaa0f04f9..3266601db 100644 --- a/src/Sets/RectorSetsTreeProvider.php +++ b/src/Sets/RectorSetsTreeProvider.php @@ -6,11 +6,9 @@ use App\RuleFilter\ValueObject\RectorSet; use Rector\Bridge\SetProviderCollector; -use Rector\Config\RectorConfig; -use Rector\Contract\Rector\RectorInterface; +use Rector\Bridge\SetRectorsResolver; use Rector\Set\Contract\SetInterface; use RectorLaravel\Set\LaravelSetProvider; -use ReflectionProperty; use Webmozart\Assert\Assert; final class RectorSetsTreeProvider @@ -90,28 +88,6 @@ public function provideCommunity(): array return $communityRectorSets; } - /** - * @return array> - */ - public function resolveFromFilePath(string $configFilePath): array - { - Assert::fileExists($configFilePath); - - $rectorConfig = new RectorConfig(); - /** @var callable $configCallable */ - $configCallable = require $configFilePath; - $configCallable($rectorConfig); - - // get tagged class-names - $tagsReflectionProperty = new ReflectionProperty($rectorConfig, 'tags'); - $tags = $tagsReflectionProperty->getValue($rectorConfig); - - $rectorClasses = $tags[RectorInterface::class] ?? []; - sort($rectorClasses); - - return array_unique($rectorClasses); - } - /** * @param SetInterface[] $sets * @return RectorSet[] @@ -121,8 +97,10 @@ private function createRectorSetsFromSetProviders(array $sets): array Assert::allIsInstanceOf($sets, SetInterface::class); $rectorSets = []; + $setRectorsResolver = new SetRectorsResolver(); + foreach ($sets as $set) { - $rectorClasses = $this->resolveFromFilePath($set->getSetFilePath()); + $rectorClasses = $setRectorsResolver->resolveFromFilePathIncludingConfiguration($set->getSetFilePath()); $rectorSets[] = new RectorSet($set->getGroupName(), $set->getName(), $rectorClasses); }