ResponseStatusCodeRector crashes on first-class callable of a method named assert*

未关闭 适合新手
#9,954 0 条评论 0 个 reaction 已指派 0 人 在 GitHub 查看

还没有人认领这个 Issue。

评估

难度
2/5
预计耗时
1-3 小时
新手友好度
85/100
Issue 类型
缺陷
描述清晰度
描述清楚
活跃度
活跃
技术栈
php, symfony
领域
tooling

调研方向

崩溃发生在 rules/CodeQuality/Rector/BinaryOp/ResponseStatusCodeRector.php:processMethodCall() 会将任何以 assert 开头的方法名路由到 processAssertMethodCall(),后者会对一等 callable 调用 getArgs()。首先阅读这两个方法,然后为一等 callable 添加提前返回。在 php -d zend.assertions=1 下,issue 中的复现文件被跳过且没有错误,并且有一个规则测试 fixture 覆盖该情况,即为完成。

由索引模型根据 Issue 内容生成。

描述

Bug Report

Subject Details
Rector version Rector 2.8.3 (also 2.5.7)

ResponseStatusCodeRector crashes when it visits a first-class callable whose method name starts with assert, for example $validator->assert(...). This is a common pattern with validation libraries such as PSL (Psl\Type\string()->assert(...)).

processMethodCall() sends every method call whose name starts with assert to processAssertMethodCall():

https://github.com/rectorphp/rector-symfony/blob/5e4e27ac2f9beb1ecdb268dddf5e7e5a3954cc0d/rules/CodeQuality/Rector/BinaryOp/ResponseStatusCodeRector.php#L107-L108

processAssertMethodCall() then calls getArgs() without a first-class callable check, and the php-parser assertion fails:

https://github.com/rectorphp/rector-symfony/blob/5e4e27ac2f9beb1ecdb268dddf5e7e5a3954cc0d/rules/CodeQuality/Rector/BinaryOp/ResponseStatusCodeRector.php#L179

[ERROR] Could not process "src/Example.php" file, due to:
        "System error: "assert(!$this->isPartialFunctionApplication())"

        Stack trace:
        #0 vendor/rector/rector/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/CallLike.php(50): assert()
        #1 vendor/rector/rector/vendor/rector/rector-symfony/rules/CodeQuality/Rector/BinaryOp/ResponseStatusCodeRector.php(155): PhpParser\Node\Expr\CallLike->getArgs()
        #2 vendor/rector/rector/vendor/rector/rector-symfony/rules/CodeQuality/Rector/BinaryOp/ResponseStatusCodeRector.php(105): Rector\Symfony\CodeQuality\Rector\BinaryOp\ResponseStatusCodeRector->processAssertMethodCall()
        #3 vendor/rector/rector/vendor/rector/rector-symfony/rules/CodeQuality/Rector/BinaryOp/ResponseStatusCodeRector.php(94): Rector\Symfony\CodeQuality\Rector\BinaryOp\ResponseStatusCodeRector->processMethodCall()

In Rector 2.5.7 the message is assert(!$this->isFirstClassCallable()). The crash needs zend.assertions = 1, which is the PHP CLI default in development setups.

Minimal PHP Code Causing Issue

<?php

final class Validator
{
    public function assert(mixed $value): string
    {
        return (string) $value;
    }
}

$validator = new Validator();
$values = array_map($validator->assert(...), ['a', 'b']);
<?php

use Rector\Config\RectorConfig;
use Rector\Symfony\CodeQuality\Rector\BinaryOp\ResponseStatusCodeRector;

return RectorConfig::configure()
    ->withPaths([__DIR__ . '/src'])
    ->withRules([ResponseStatusCodeRector::class]);

Run: php -d zend.assertions=1 vendor/bin/rector process --dry-run

Expected Behaviour

Rector should skip the node. A first-class callable has no arguments to inspect. A guard at the start of processMethodCall() would fix it. isPartialFunctionApplication() also covers first-class callables in the php-parser version that Rector 2.8.3 bundles:

if ($methodCall->isPartialFunctionApplication()) {
    return null;
}
主要语言
PHP
星标
10.5k
派生
742
PR 合并指标
30 天内没有已合并 PR

环境准备

  • 没有 Dockerfile 或 Docker Compose 文件
  • 没有 Pull Request 模板
  • 阅读贡献指南

从这里开始

  1. 先读完整个 Issue,再读项目的贡献指南。
  2. 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
  3. Fork 仓库,在一个分支上完成修改。
  4. 提交 Pull Request,并在描述里引用这个 Issue 编号。

rectorphp/rector 的其他 Issue

查看 rectorphp/rector 的全部 Issue

相似的 Issue

更多 PHP Issue

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。