diff --git a/composer.json b/composer.json index 26f65778..e0a31069 100644 --- a/composer.json +++ b/composer.json @@ -13,6 +13,8 @@ "phpunit/phpunit": "^11.5", "rector/rector-src": "dev-main", "symplify/easy-coding-standard": "^12.3", + "symplify/phpstan-extensions": "^12.0", + "symplify/phpstan-rules": "^14.9", "symplify/rule-doc-generator": "^12.2", "symplify/vendor-patches": "^11.5", "tomasvotruba/class-leak": "^1.0", diff --git a/phpstan.neon b/phpstan.neon index 58f926a2..306b1226 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -1,10 +1,10 @@ -# to be enabled later once rector upgraded to use phpstan v2 -# includes: -# - vendor/symplify/phpstan-rules/config/symplify-rules.neon -# - vendor/symplify/phpstan-rules/config/rector-rules.neon +includes: + - vendor/symplify/phpstan-rules/config/symplify-rules.neon + - vendor/symplify/phpstan-rules/config/rector-rules.neon parameters: level: 8 + errorFormat: symplify reportUnmatchedIgnoredErrors: false @@ -57,16 +57,16 @@ parameters: - '#Doing instanceof PHPStan\\Type\\.+ is error\-prone and deprecated#' # phpstan instanceof - - - identifier: phpstanApi.instanceofAssumption - - - - identifier: phpstanApi.varTagAssumption + - identifier: phpstanApi.instanceofAssumption + - identifier: phpstanApi.varTagAssumption + - '#Asking about instanceof PHPStan\\.* is not covered by backward compatibility promise#' - identifier: argument.type - - - '#Asking about instanceof PHPStan\\.* is not covered by backward compatibility promise#' + paths: + - rules/DowngradePhp85/Rector/StmtsAwareInterface/DowngradePipeOperatorRector.php + - rules/DowngradePhp85/Rector/Class_/DowngradeFinalPropertyPromotionRector.php + - rules/DowngradePhp80/Rector/New_/DowngradeArbitraryExpressionsSupportRector.php # false positive intanceof in OR usage - @@ -76,3 +76,30 @@ parameters: - identifier: deadCode.unreachable path: rules/DowngradePhp80/Rector/NullsafeMethodCall/DowngradeNullsafeToTernaryOperatorRector.php + + # cached printed nodes + - + identifier: rector.noPropertyNodeAssign + paths: + - rules/DowngradePhp83/Rector/FuncCall/DowngradeJsonValidateRector.php + - rules/DowngradePhp81/Rector/FuncCall/DowngradeArrayIsListRector.php + - rules/DowngradePhp72/Rector/FuncCall/DowngradeStreamIsattyRector.php + + # already registered in PHP 8.1 set + - + identifier: rector.upgradeDowngradeRegisteredInSet + path: rules/DowngradePhp74/Rector/Array_/DowngradeArraySpreadRector.php + + # valid stmts property check + - + identifier: symplify.forbiddenFuncCall + path: rules/DowngradePhp73/Rector/FuncCall/DowngradeArrayKeyFirstLastRector.php + + # false positive + - + identifier: symplify.seeAnnotationToTest + path: rules/DowngradePhp85/Rector/StmtsAwareInterface/DowngradePipeOperatorRector.php + + - + identifier: rector.noIntegerRefactorReturn + path: rules/DowngradePhp82/Rector/FuncCall/DowngradeIteratorCountToArrayRector.php diff --git a/rules-tests/DowngradePhp81/Rector/FuncCall/DowngradeHashAlgorithmXxHash/Fixture/fixture_constant.php.inc b/rules-tests/DowngradePhp81/Rector/FuncCall/DowngradeHashAlgorithmXxHash/Fixture/fixture_constant.php.inc index 8cc6c094..609214a1 100644 --- a/rules-tests/DowngradePhp81/Rector/FuncCall/DowngradeHashAlgorithmXxHash/Fixture/fixture_constant.php.inc +++ b/rules-tests/DowngradePhp81/Rector/FuncCall/DowngradeHashAlgorithmXxHash/Fixture/fixture_constant.php.inc @@ -2,7 +2,7 @@ namespace Rector\Tests\DowngradePhp81\Rector\FuncCall\DowngradeHashAlgorithmXxHash\Fixture; -class Fixture +final class FixtureConstant { public function run() { @@ -16,7 +16,7 @@ class Fixture namespace Rector\Tests\DowngradePhp81\Rector\FuncCall\DowngradeHashAlgorithmXxHash\Fixture; -class Fixture +final class FixtureConstant { public function run() { diff --git a/rules-tests/DowngradePhp81/Rector/FuncCall/DowngradeHashAlgorithmXxHash/Fixture/fixture_named_arguments.php.inc b/rules-tests/DowngradePhp81/Rector/FuncCall/DowngradeHashAlgorithmXxHash/Fixture/fixture_named_arguments.php.inc index ca6b1440..f8a78c1d 100644 --- a/rules-tests/DowngradePhp81/Rector/FuncCall/DowngradeHashAlgorithmXxHash/Fixture/fixture_named_arguments.php.inc +++ b/rules-tests/DowngradePhp81/Rector/FuncCall/DowngradeHashAlgorithmXxHash/Fixture/fixture_named_arguments.php.inc @@ -2,7 +2,7 @@ namespace Rector\Tests\DowngradePhp81\Rector\FuncCall\DowngradeHashAlgorithmXxHash\Fixture; -class Fixture +final class FixtureNamedArguments { public function run() { @@ -16,7 +16,7 @@ class Fixture namespace Rector\Tests\DowngradePhp81\Rector\FuncCall\DowngradeHashAlgorithmXxHash\Fixture; -class Fixture +final class FixtureNamedArguments { public function run() { diff --git a/rules-tests/DowngradePhp81/Rector/FuncCall/DowngradeHashAlgorithmXxHash/Fixture/fixture_named_arguments_false_order.php.inc b/rules-tests/DowngradePhp81/Rector/FuncCall/DowngradeHashAlgorithmXxHash/Fixture/fixture_named_arguments_false_order.php.inc deleted file mode 100644 index 9cbbaba3..00000000 --- a/rules-tests/DowngradePhp81/Rector/FuncCall/DowngradeHashAlgorithmXxHash/Fixture/fixture_named_arguments_false_order.php.inc +++ /dev/null @@ -1,27 +0,0 @@ - ------ - diff --git a/rules-tests/DowngradePhp81/Rector/FuncCall/DowngradeHashAlgorithmXxHash/Fixture/fixture_xxh128.php.inc b/rules-tests/DowngradePhp81/Rector/FuncCall/DowngradeHashAlgorithmXxHash/Fixture/fixture_xxh128.php.inc deleted file mode 100644 index e4c0e887..00000000 --- a/rules-tests/DowngradePhp81/Rector/FuncCall/DowngradeHashAlgorithmXxHash/Fixture/fixture_xxh128.php.inc +++ /dev/null @@ -1,27 +0,0 @@ - ------ - diff --git a/rules-tests/DowngradePhp81/Rector/FuncCall/DowngradeHashAlgorithmXxHash/Fixture/fixture_xxh32.php.inc b/rules-tests/DowngradePhp81/Rector/FuncCall/DowngradeHashAlgorithmXxHash/Fixture/fixture_xxh32.php.inc index d7e39dd2..ead2e890 100644 --- a/rules-tests/DowngradePhp81/Rector/FuncCall/DowngradeHashAlgorithmXxHash/Fixture/fixture_xxh32.php.inc +++ b/rules-tests/DowngradePhp81/Rector/FuncCall/DowngradeHashAlgorithmXxHash/Fixture/fixture_xxh32.php.inc @@ -2,11 +2,15 @@ namespace Rector\Tests\DowngradePhp81\Rector\FuncCall\DowngradeHashAlgorithmXxHash\Fixture; -class Fixture +final class FixtureXxh32 { public function run() { - return hash('xxh32', 'some-data-to-hash'); + $value = hash('xxh32', 'some-data-to-hash'); + + $value = hash('xxh64', 'some-data-to-hash'); + + $value = hash('xxh128', 'some-data-to-hash'); } } @@ -16,11 +20,15 @@ class Fixture namespace Rector\Tests\DowngradePhp81\Rector\FuncCall\DowngradeHashAlgorithmXxHash\Fixture; -class Fixture +final class FixtureXxh32 { public function run() { - return hash('md5', 'some-data-to-hash'); + $value = hash('md5', 'some-data-to-hash'); + + $value = hash('md5', 'some-data-to-hash'); + + $value = hash('md5', 'some-data-to-hash'); } } diff --git a/rules-tests/DowngradePhp81/Rector/FuncCall/DowngradeHashAlgorithmXxHash/Fixture/fixture_xxh64.php.inc b/rules-tests/DowngradePhp81/Rector/FuncCall/DowngradeHashAlgorithmXxHash/Fixture/fixture_xxh64.php.inc deleted file mode 100644 index a9937f95..00000000 --- a/rules-tests/DowngradePhp81/Rector/FuncCall/DowngradeHashAlgorithmXxHash/Fixture/fixture_xxh64.php.inc +++ /dev/null @@ -1,27 +0,0 @@ - ------ - diff --git a/rules-tests/DowngradePhp81/Rector/FuncCall/DowngradeHashAlgorithmXxHash/Fixture/skip_check_version_compare_ternary.php.inc b/rules-tests/DowngradePhp81/Rector/FuncCall/DowngradeHashAlgorithmXxHash/Fixture/skip_check_version_compare_ternary.php.inc index 3d665ea4..9b5f8d2d 100644 --- a/rules-tests/DowngradePhp81/Rector/FuncCall/DowngradeHashAlgorithmXxHash/Fixture/skip_check_version_compare_ternary.php.inc +++ b/rules-tests/DowngradePhp81/Rector/FuncCall/DowngradeHashAlgorithmXxHash/Fixture/skip_check_version_compare_ternary.php.inc @@ -6,8 +6,12 @@ final class SkipCheckVersionCompareTernary { public function run_v() { - return version_compare(PHP_VERSION, '8.1','>=') + $value = version_compare(PHP_VERSION, '8.1','>=') ? hash( 'xxh128', $value ) : hash( 'md4', $value ); + + $value = version_compare(PHP_VERSION, '8.1','<') + ? hash( 'md4', $value ) + : hash( 'xxh128', $value ); } } diff --git a/rules-tests/DowngradePhp81/Rector/FuncCall/DowngradeHashAlgorithmXxHash/Fixture/skip_check_version_compare_ternary2.php.inc b/rules-tests/DowngradePhp81/Rector/FuncCall/DowngradeHashAlgorithmXxHash/Fixture/skip_check_version_compare_ternary2.php.inc deleted file mode 100644 index 692024df..00000000 --- a/rules-tests/DowngradePhp81/Rector/FuncCall/DowngradeHashAlgorithmXxHash/Fixture/skip_check_version_compare_ternary2.php.inc +++ /dev/null @@ -1,13 +0,0 @@ - + */ private const HASH_ALGORITHMS_TO_DOWNGRADE = [ 'xxh32' => MHASH_XXH32, 'xxh64' => MHASH_XXH64, @@ -45,7 +40,6 @@ final class DowngradeHashAlgorithmXxHashRector extends AbstractRector public function __construct( private readonly ArgsAnalyzer $argsAnalyzer, private readonly ValueResolver $valueResolver, - private readonly ConditionResolver $conditionResolver ) { } @@ -84,32 +78,19 @@ public function run() */ public function getNodeTypes(): array { - return [If_::class, Ternary::class, FuncCall::class]; + return [FuncCall::class]; } /** - * @param If_|Ternary|FuncCall $node - * @return null|NodeVisitor::DONT_TRAVERSE_CHILDREN|Node + * @param FuncCall $node */ - public function refactor(Node $node): null|int|Node + public function refactor(Node $node): ?FuncCall { - if ($node instanceof If_) { - if ($this->isVersionCompareIf($node)) { - return NodeVisitor::DONT_TRAVERSE_CHILDREN; - } - - return null; - } - - if ($node instanceof Ternary) { - if ($this->isVersionCompareTernary($node)) { - return NodeVisitor::DONT_TRAVERSE_CHILDREN; - } - + if ($this->shouldSkip($node)) { return null; } - if ($this->shouldSkip($node)) { + if ($node->getAttribute(AttributeKey::PHP_VERSION_CONDITIONED)) { return null; } @@ -131,54 +112,6 @@ public function refactor(Node $node): null|int|Node return $node; } - private function isVersionCompareIf(If_ $if): bool - { - if ($if->cond instanceof FuncCall) { - // per use case reported only - if (count($if->stmts) !== 1) { - return false; - } - - $versionCompare = $this->conditionResolver->resolveFromExpr($if->cond); - - if (! $versionCompare instanceof VersionCompareCondition || $versionCompare->getSecondVersion() !== 80100) { - return false; - } - - if ($versionCompare->getCompareSign() !== '>=') { - return false; - } - - if ($if->stmts[0] instanceof Expression && $if->stmts[0]->expr instanceof Assign && $if->stmts[0]->expr->expr instanceof FuncCall) { - return $this->isName($if->stmts[0]->expr->expr, 'hash'); - } - - if ($if->stmts[0] instanceof Return_ && $if->stmts[0]->expr instanceof FuncCall) { - return $this->isName($if->stmts[0]->expr, 'hash'); - } - } - - return false; - } - - private function isVersionCompareTernary(Ternary $ternary): bool - { - if ($ternary->if instanceof Expr && $ternary->cond instanceof FuncCall) { - $versionCompare = $this->conditionResolver->resolveFromExpr($ternary->cond); - if ($versionCompare instanceof VersionCompareCondition && $versionCompare->getSecondVersion() === 80100) { - if ($versionCompare->getCompareSign() === '>=') { - return $ternary->if instanceof FuncCall && $this->isName($ternary->if, 'hash'); - } - - if ($versionCompare->getCompareSign() === '<') { - return $ternary->else instanceof FuncCall && $this->isName($ternary->else, 'hash'); - } - } - } - - return false; - } - private function shouldSkip(FuncCall $funcCall): bool { if ($funcCall->isFirstClassCallable()) { diff --git a/rules/DowngradePhp82/Rector/FuncCall/DowngradeIteratorCountToArrayRector.php b/rules/DowngradePhp82/Rector/FuncCall/DowngradeIteratorCountToArrayRector.php index 86be906f..262cd753 100644 --- a/rules/DowngradePhp82/Rector/FuncCall/DowngradeIteratorCountToArrayRector.php +++ b/rules/DowngradePhp82/Rector/FuncCall/DowngradeIteratorCountToArrayRector.php @@ -78,6 +78,8 @@ public function refactor(Node $node): null|FuncCall|int fn (Node $subNode): bool => $subNode instanceof FuncCall && $this->isName($subNode, 'is_array') ); + // get tgype... + if ($hasIsArrayCheck) { return NodeVisitor::DONT_TRAVERSE_CHILDREN; } diff --git a/rules/DowngradePhp83/Rector/FuncCall/DowngradeJsonValidateRector.php b/rules/DowngradePhp83/Rector/FuncCall/DowngradeJsonValidateRector.php index 90236959..a75e064d 100644 --- a/rules/DowngradePhp83/Rector/FuncCall/DowngradeJsonValidateRector.php +++ b/rules/DowngradePhp83/Rector/FuncCall/DowngradeJsonValidateRector.php @@ -84,8 +84,7 @@ public function getRuleDefinition(): RuleDefinition */ public function getNodeTypes(): array { - $stmtsAware = NodeGroup::STMTS_AWARE; - return [...$stmtsAware, Switch_::class, Return_::class, Expression::class, Echo_::class]; + return [...NodeGroup::STMTS_AWARE, Switch_::class, Return_::class, Expression::class, Echo_::class]; } /** diff --git a/rules/DowngradePhp85/Rector/StmtsAwareInterface/DowngradePipeOperatorRector.php b/rules/DowngradePhp85/Rector/StmtsAwareInterface/DowngradePipeOperatorRector.php index b7686004..56f04303 100644 --- a/rules/DowngradePhp85/Rector/StmtsAwareInterface/DowngradePipeOperatorRector.php +++ b/rules/DowngradePhp85/Rector/StmtsAwareInterface/DowngradePipeOperatorRector.php @@ -21,8 +21,8 @@ use Symplify\RuleDocGenerator\ValueObject\RuleDefinition; /** - * @see https://wiki.php.net/rfc/pipe-operator-v3 * @see \Rector\Tests\DowngradePhp85\Rector\StmtsAwareInterface\DowngradePipeOperatorRector\DowngradePipeOperatorRectorTest + * @see https://wiki.php.net/rfc/pipe-operator-v3 */ final class DowngradePipeOperatorRector extends AbstractRector {