You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

自定义phpcs(phpcbf)空大括号去空格Sniff执行失败

解决PHPCBF空大括号修复循环报错问题

你的问题核心是Sniff在修复后触发了重复检测,导致PHPCBF进入无限循环直到达到最大次数限制。这通常是因为修复操作没有正确处理token指针位置,或者每次修复后又触发了同一规则的检测。

问题根源

当你移除{和}之间的空白时,文件的token流会发生变化,如果Sniff没有告诉PHPCBF跳过已处理的位置,下次扫描时会再次定位到修改后的大括号区域,重复执行修复操作,进而引发循环。

正确的Sniff实现方案

下面是能解决循环问题的Sniff代码,关键在于准确定位空大括号、一次性完成修复,并且处理后跳转指针避免重复检测:

use PHP_CodeSniffer\Files\File;
use PHP_CodeSniffer\Sniffs\Sniff;

class EmptyBraceWhitespaceSniff implements Sniff
{
    public function register()
    {
        return [T_OPEN_CURLY_BRACKET];
    }

    public function process(File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();
        $openBrace = $stackPtr;

        // 跳过无法匹配右大括号的情况
        if (!isset($tokens[$openBrace]['bracket_closer'])) {
            return;
        }

        $closeBrace = $tokens[$openBrace]['bracket_closer'];
        $hasNonWhitespace = false;

        // 检查大括号中间是否只有空白字符
        for ($i = $openBrace + 1; $i < $closeBrace; $i++) {
            if ($tokens[$i]['code'] !== T_WHITESPACE) {
                $hasNonWhitespace = true;
                break;
            }
        }

        if ($hasNonWhitespace) {
            return;
        }

        // 已经是紧凑格式,无需处理
        if (($closeBrace - $openBrace) === 1) {
            return;
        }

        // 包裹修复操作,确保单次变更完成
        $phpcsFile->fixer->beginChangeset();
        // 移除所有中间的空白token
        for ($i = $openBrace + 1; $i < $closeBrace; $i++) {
            $phpcsFile->fixer->replaceToken($i, '');
        }
        $phpcsFile->fixer->endChangeset();

        // 跳转到右大括号的下一个token,避免重复处理当前区域
        return $closeBrace + 1;
    }
}

关键修复点

  1. 准确匹配成对大括号:利用$tokens[$openBrace]['bracket_closer']获取对应的右大括号,避免定位错误。
  2. 排除非空白内容:确保只处理真正的空大括号(中间仅含空白),不会误改有注释或代码的大括号。
  3. 一次性修复:用beginChangeset()和endChangeset()包裹修复操作,让PHPCBF将所有修改视为单次变更,减少重复扫描。
  4. 指针跳转:处理完成后返回$closeBrace + 1,告诉PHPCBF从下一个token开始扫描,彻底避免重复处理当前大括号。

之前添加return $phpcsFile->numTokens没用,是因为这个操作会让PHPCBF直接跳到文件末尾,跳过后续所有内容,但如果文件中有多个需要修复的位置,第一次修复后重新扫描时还是会回到开头,再次触发当前位置的检测,导致循环。而精准跳转到下一个token才是正确的做法。

内容的提问来源于stack exchange,提问作者donatJ

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 16:42:32