PHP-CS-Fixer 规则详解:no_whitespace_in_empty_array 清理空数组中的空白
2026/9/23 2:32:59 网站建设 项目流程

PHP-CS-Fixer 规则详解:no_whitespace_in_empty_array 清理空数组中的空白

【免费下载链接】PHP-CS-FixerA tool to automatically fix PHP Coding Standards issues项目地址: https://gitcode.com/gh_mirrors/ph/PHP-CS-Fixer

导读

no_whitespace_in_empty_array是 PHP-CS-Fixer(PHP Coding Standards Fixer)中ArrayNotation(数组记法)类别下的一条轻量级代码风格规则,用于把"只包含空白符的空数组"(如$foo = [\n];)自动压缩为紧凑形式$foo = [];。本文基于本仓库的官方规则文档,结合规则源码、单元测试与规则集配置,完整讲解该规则的行为边界、启用方式、底层实现原理及其与其他规则的协作关系,读完即可在项目中安全落地这条规则。

规则概述

规则全名:no_whitespace_in_empty_array

官方定义(FixerDefinition,见 NoWhitespaceInEmptyArrayFixer.php):

Empty arrays should not contain only whitespace.

即:空数组内不应仅包含空白字符。当数组字面量[]中没有任何元素、只有空格、换行等空白时,规则会将其折叠为单行紧凑形式[]

该规则属于"非 Risky"规则——它只做纯格式层面的空白移除,不涉及任何语义转换,因此可以安全地加入默认规则集。

修复示例

官方文档给出的标准示例(CodeSample):

--- Original +++ New <?php -$foo = [ -]; +$foo = [];

修复前,空数组占用了三行,括号间仅有一个换行符;修复后压缩为一行$foo = [];

结合 NoWhitespaceInEmptyArrayFixerTest.php 中的测试用例,可以确认该规则覆盖的更多形态:

输入(修复前)输出(修复后)说明
$foo = [\n];$foo = [];括号间仅一个换行
$foo = [ ];$foo = [];括号间仅水平空格
$foo = [\n\n];$foo = [];括号间多个空行
$foo = [\n \n];$foo = [];括号间仅含空白行
private const Foo = [\n];private const Foo = [];类常量场景
$foo = [ ];(方法体内)$foo = [];方法体赋值场景
public array $ignore = [\n];public array $ignore = [];类型化属性默认值场景

注意:括号之间由空白(空格、制表符、换行)组成时才会被压缩。若括号间存在注释或其他有效内容,规则会跳过。

行为边界:注释与内容会被保留

该规则不会删除"看似空白"的注释,也不会删除任何真实元素。测试用例明确验证了以下两种场景不会被修复

// 场景一:括号间只有一行注释(含 `// foo`) $foo = [ // foo ]; // 场景二:括号间有块注释 $foo = [ /* test */ ];

这两类输入在测试中作为expected(期望输出)出现,即原样保留。原理很简单:实现只清空"括号之间唯一的那一个空白 token",一旦中间存在注释 token,getPrevNonWhitespace($index) !== $index - 2的判断就不成立,直接跳过。

此外,混合场景也能一次修复多处:

// 修复前 $a = [ ]; $b = [ ]; $c = []; $d = [ /**/ ]; $e = [ ]; $f = [ ]; // 修复后 $a = []; $b = []; $c = []; $d = [ /**/ ]; // 含块注释,保持原样 $e = []; $f = [];

启用方式

方式一:命令行临时指定

只针对单条规则执行修复:

vendor/bin/php-cs-fixer fix /path/to/project \ --rules='{"no_whitespace_in_empty_array": true}'

--rules接受 JSON 格式的规则配置,true表示启用该规则(默认参数为空,无需额外配置项)。

方式二:配置文件.php-cs-fixer.php

在项目根目录的配置文件(或--config指定的文件)中启用:

<?php // .php-cs-fixer.php $finder = PhpCsFixer\Finder::create() ->in(__DIR__ . '/src') ->in(__DIR__ . '/tests'); return (new PhpCsFixer\Config()) ->setRules([ 'no_whitespace_in_empty_array' => true, ]) ->setFinder($finder);

方式三:随官方规则集一键开启

该规则是@PhpCsFixer规则集的成员,见 PhpCsFixerSet.php 中的'no_whitespace_in_empty_array' => true@PhpCsFixer是 PHP CS Fixer 团队推荐的、高度主观(highly opinionated)的规则集,扩展自@PER-CS@Symfony。启用方式:

vendor/bin/php-cs-fixer fix --rules=@PhpCsFixer

或在配置文件中使用:

->setRules(['@PhpCsFixer' => true])

该规则集的完整说明见 doc/ruleSets/PhpCsFixer.rst,其中第 45 行列出了指向本规则文档的索引链接。

源码实现原理

候选检测(isCandidate)

public function isCandidate(Tokens $tokens): bool { return $tokens->isTokenKindFound(CT::T_ARRAY_BRACKET_OPEN); }

规则会先扫描整个 token 流,只有当文件里存在"数组方括号开括号"的 CT token 时才进入修复流程,否则直接跳过,保证性能。该常量定义于 CT.php:CT::T_ARRAY_BRACKET_OPEN = 10_004,对应的CT::T_ARRAY_BRACKET_CLOSE = 10_003

为什么用自定义的CT::T_ARRAY_BRACKET_OPEN而不是原生的T_ARRAY?因为 PHP 原生 tokenizer 对[]短数组语法不会产生独立的括号 token(它们被吞并进T_ARRAY附近的空白处理中),PHP-CS-Fixer 在 Tokenizer/Transformer 阶段会把方括号统一改写成这些带语义的 CT 常量,从而让各规则能精确、稳定地定位数组括号。这是整个ArrayNotation家族规则的共同基础。

修复逻辑(applyFix)

protected function applyFix(\SplFileInfo $file, Tokens $tokens): void { for ($index = \count($tokens) - 1; $index > 0; --$index) { if (!$tokens[$index]->isGivenKind(CT::T_ARRAY_BRACKET_CLOSE)) { continue; } if ($tokens->getPrevNonWhitespace($index) !== $index - 2) { continue; } if (!$tokens[$index - 2]->isGivenKind(CT::T_ARRAY_BRACKET_OPEN)) { continue; } $tokens->clearAt($index - 1); } }

核心思路可以拆成四步:

  1. 从后向前遍历token 流,先找到每一个"数组方括号闭括号"(CT::T_ARRAY_BRACKET_CLOSE)。从尾部开始遍历是 PHP-CS-Fixer 的通用惯例,因为清除 token 会改变索引,倒序遍历可以安全地在同一轮内处理多个候选;
  2. 验证括号位置相邻getPrevNonWhitespace($index)返回闭括号前最近的非空白 token 索引,只有当它等于$index - 2时,才说明"开括号与闭括号之间只有一个 token"——这个 token 就是空白;
  3. 验证开括号存在:确认$index - 2位置确实是CT::T_ARRAY_BRACKET_OPEN,避免误伤其它括号配对;
  4. 清除空白 token$tokens->clearAt($index - 1)把夹在括号之间的唯一空白 token 标记为清除,最终得到[]

优先级与执行顺序(getPriority)

/** * {@inheritdoc} * * Must run after ArraySyntaxFixer, NoEmptyCommentFixer. */ public function getPriority(): int { return 0; }

getPriority()返回0(默认优先级),但源码注释明确要求必须在ArraySyntaxFixerNoEmptyCommentFixer之后运行。原因可以通过仓库中的集成测试(tests/Fixtures/Integration/priority)得到印证:

  • array_syntax,no_whitespace_in_empty_array.test:输入array(\n\n );需先由array_syntax转成短数组[,随后本规则才能识别并压缩;
  • no_empty_comment,no_whitespace_in_empty_array.test:输入[\n //\n]中括号间是一个空注释,先由no_empty_comment删除空注释,剩下来的纯空白再由本规则折叠。

这两条集成测试以--RULESET--+--INPUT--+--EXPECT--三段式断言了"多规则串联"的最终输出,是理解 fixer 协作关系的直观材料。

官方测试与向后兼容承诺

官方文档特别强调(见 no_whitespace_in_empty_array.rst):

The test class defines officially supported behaviour. Each test case is a part of our backward compatibility promise.

即 NoWhitespaceInEmptyArrayFixerTest.php 中的每个用例都属于 PHP-CS-Fixer 的向后兼容承诺——测试里定义的行为(包括"修复什么"和"不修复什么")在后续版本中都会保持稳定,不会随意改变。这也是官方文档为每条规则都附上 Fixer 类与测试类链接的原因:

  • Fixer 类:PhpCsFixer\Fixer\ArrayNotation\NoWhitespaceInEmptyArrayFixer
  • 测试类:PhpCsFixer\Tests\Fixer\ArrayNotation\NoWhitespaceInEmptyArrayFixerTest

测试类继承自AbstractFixerTestCase,通过@dataProvider provideFixCases批量驱动testFix($expected, $input),每个yield都是一组"输入 → 期望输出"对;当inputnull时表示"已符合规范,不应被修改"。如果读者想本地复现,可运行:

vendor/bin/phpunit tests/Fixer/ArrayNotation/NoWhitespaceInEmptyArrayFixerTest.php

实际使用建议

  1. 放心纳入 CI 与 pre-commit:该规则不涉及 Risky 操作,也不会改动注释与真实元素,适合作为@PhpCsFixer或显式规则集的一部分在提交前/CI 中执行。
  2. 结合配套规则array_syntax(把array()转为[])与no_empty_comment(清除空注释)与本规则存在执行顺序依赖,三者同时开启时 PHP-CS-Fixer 会依据优先级自动编排,无需手动干预,最终效果是"空数组彻底干净"。
  3. 理解"非空即不动"原则:只要括号间有任何非空白 token(注释、元素),本规则一律跳过,因此不需要担心它误删注释或代码。
  4. 查阅更多数组类规则:本规则位于ArrayNotation类别,同类规则还包括array_syntaxno_trailing_comma_in_singleline_arraytrim_array_spaceswhitespace_after_comma_in_array等,完整清单见 doc/rules/array_notation 目录;命令行工具的整体用法可参考 doc/usage.rst 与 doc/config.rst。

小结

no_whitespace_in_empty_array虽然只解决一个很小的格式问题,但其实现体现了 PHP-CS-Fixer 的典型工程范式:通过 Tokenizer 的 CT 常量统一数组括号语义、以getPrevNonWhitespace做精确的相邻性判定、用clearAt最小化改动,再以"规则集 + 优先级注释 + 集成测试 + 单元测试"四层机制保障多规则协作下的行为稳定。理解了这条规则的实现与测试,也就掌握了阅读 PHP-CS-Fixer 任意一条空白类 fixer 源码的通用方法论。

【免费下载链接】PHP-CS-FixerA tool to automatically fix PHP Coding Standards issues项目地址: https://gitcode.com/gh_mirrors/ph/PHP-CS-Fixer

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询