PHP-CS-Fixer 规则详解:phpdoc_single_line_var_spacing 让单行 @var 注释间距规范统一
2026/9/23 14:41:45 网站建设 项目流程
  • 开发工具
  • 代码质量
  • 静态分析
  • Lint
  • 格式化

【免费下载链接】PHP-CS-Fixer

A tool to automatically fix PHP Coding Standards issues

项目地址:https://gitcode.com/gh_mirrors/ph/PHP-CS-Fixer
点击查看免费下载

导读

phpdoc_single_line_var_spacing是 PHP-CS-Fixer 提供的 PHPDoc 规范化规则,用于修正单行@var注释中多余或缺失的空格,将其统一为/** @var Type $variable */的标准形态。本文以 规则文档 为主体,结合 Fixer 源码 与 单元测试,完整讲解该规则的行为边界、底层实现、与其他规则的协作顺序,以及如何在项目中使用与验证。读完本文,你将掌握该规则的精确作用范围、正则匹配逻辑与规则集启用方式,可直接落地到实际项目的代码风格配置中。

规则概述:修复什么

该规则的目标非常聚焦:单行@varPHPDoc 应当具有合适的间距(proper spacing)。官方FixerDefinition描述为 "Single line@varPHPDoc should have proper spacing."(见 PhpdocSingleLineVarSpacingFixer.php)。

在源码注释中,该 Fixer 的实现定位为 "Fixer for part of rule defined in PSR5 ¶7.22"(见 源码第 26 行),即其行为与 PSR-5 草案中关于 PHPDoc 格式的 7.22 节精神一致,属于 PHPDoc 规范化的一个组成部分。

需要特别强调边界:本规则只处理"单行"形式的@var注释,即整个注释在一行内以/**开头、以*/结束。对于多行@var注释(例如属性注释跨越多行),该规则不会插手。

核心示例:一条规则的典型修复

规则文档给出了唯一的官方示例:

--- Original +++ New -<?php /**@var MyClass $a */ +<?php /** @var MyClass $a */ $a = test();

可以看到,这一条修复同时完成了三件事:

  1. /**@var之间补上缺失的空格(/**@var/** @var);
  2. @var后多余的空格压缩为单个空格(@var MyClass@var MyClass);
  3. 将注释结尾*/前的多余空格清除($a */$a */)。

源码解析:修复是怎么发生的

候选检查(isCandidate)

Fixer 只对包含注释的文件生效。isCandidate()通过$tokens->isAnyTokenKindsFound([\T_COMMENT, \T_DOC_COMMENT])检查 Token 流中是否存在普通注释或文档注释(源码第 51-54 行)。只要文件里没有任何注释,该 Fixer 会直接跳过,不产生任何开销。

核心正则与替换逻辑

applyFix()遍历所有 Token,对每个注释 Token 调用fixTokenContent(),核心是一个Preg::replaceCallback(源码第 72-89 行):

'#^/\*\*\h*@var\h+(\S+)\h*(\$\S+)?\h*([^\n]*)\*/$#'

逐段解读这个正则:

  • ^/\*\*:注释必须严格以/**开头;
  • \h*/**@var之间允许任意数量的水平空白(含空格与 Tab,但不含换行),会被压缩;
  • @var:标签本体;
  • \h+(\S+)@var后至少一个水平空白,随后捕获第一个非空白片段——即类型(如MyClass);
  • (\$\S+)?:可选的变量名捕获组,以$开头(如$a);
  • \h*([^\n]*)\*/$:变量名之后可以跟任意数量的水平空白以及剩余描述文本([^\n]*,不含换行,说明描述必须与类型同行),最后以*/结束。$锚定确保整个注释恰好匹配这一单行形态。

替换时,Fixer 以/** @var为前缀重建内容,将捕获到的"类型"、"变量名"、"描述"各组以单个空格拼接,最后用rtrim去掉尾部空白再补上*/。由于正则锚定了整行,任何不满足单行@var形态的注释(多行注释、含换行的注释、其他标签)都不会被改动

输出 Token 类型

替换后的内容以[\T_DOC_COMMENT, $fixedContent]写回 Token 流(源码第 66-68 行),保证注释仍被识别为文档注释,不影响后续其他 PHPDoc 类规则的 Token 解析。

与其他规则的协作:优先级与依赖

Fixer 通过getPriority()声明执行顺序,返回-10,并明确注释了约束(源码第 40-49 行):

Must run before PhpdocAlignFixer. Must run after AlignMultilineCommentFixer, CommentToPhpdocFixer, PhpdocIndentFixer, PhpdocNoAliasTagFixer, PhpdocScalarFixer, PhpdocToCommentFixer, PhpdocTypesFixer.

含义如下:

  • 必须在 PhpdocAlignFixer 之前运行phpdoc_align负责把@var@param等标签的类型与描述做垂直对齐(见 PhpdocAlignFixer.php)。先由本规则把单行@var的多余空格收敛为标准间距,phpdoc_align再基于干净的内容做列对齐,避免两次修复互相干扰;
  • 必须在 AlignMultilineCommentFixer、CommentToPhpdocFixer、PhpdocIndentFixer、PhpdocNoAliasTagFixer、PhpdocScalarFixer、PhpdocToCommentFixer、PhpdocTypesFixer 之后运行:这些规则会改变注释的形态、缩进、别名标签或标量类型写法,本规则必须在它们产出的"最终形态"上再做间距统一,否则会被后续改动再次打破。

这条依赖链说明,PHP-CS-Fixer 中 Fixer 之间并非独立执行,而是通过优先级组成确定的流水线,phpdoc_single_line_var_spacing处于 PHPDoc 规范化流水线的中后段。

测试验证:官方承诺的行为边界

测试类 PhpdocSingleLineVarSpacingFixerTest.php 中的每个用例都属于官方向后兼容承诺(backward compatibility promise)的一部分。从数据提供器provideFixCases()可以归纳出规则的实际行为边界:

用例 1:缺失空格的两种情况

/**@var MyCass6 $a */ → /** @var MyCass6 $a */ /**@var MyCass6*/ → /** @var MyCass6 */

/**后缺空格、*/前缺空格都会被补齐,类型名被保留。

用例 2:类型、变量、描述之间的多余空白

/** @var MyCass1 $test1 description and more.*/ → /** @var MyCass1 $test1 description and more. */ /** @var MyCass3 description. */ → /** @var MyCass3 description. */
  • 注释内部(含 Tab 与多个空格混用)的空白被统一为单个空格;
  • 描述文本内部的单词间距不会被打散——description and more.中"and"前的多余空格会被压成单个空格,但描述内单词间的正常分隔保留;
  • 变量名可省略:/** @var MyCass2 description and such. */这种无$var的形态同样受支持。

用例 3:不越界的场景(单输入无输出)

第三个用例只有expected没有input,表示该输入不做任何修改,包括:

  • 多行@param array $options { ... }块内缩进的@var bool $required ...行(属于@param的嵌套结构,不被触碰);
  • 多行@var注释块中逐行书写的@var bool $required ...@var string $label ...
  • /** @var MyCass3开头但*/换行到下一行的多行注释。

这正是"单行"限定词的含义:只要注释不是单行/** ... */形态,本规则一律不动,从而避免误伤多行 PHPDoc 块与对齐排版结构。该用例同时暗示:垂直对齐任务交由phpdoc_align处理,本规则无需也不应代劳。

所属规则集与如何启用

规则文档明确该规则属于以下两个规则集(规则集文档 Symfony.rst):

  • @PhpCsFixer(见 PhpCsFixer.rst)
  • @Symfony(见 Symfony.rst)

在源码层面,@Symfony规则集在 SymfonySet.php 中显式声明'phpdoc_single_line_var_spacing' => true;而@PhpCsFixer规则集通过'@Symfony' => true继承启用(见 PhpCsFixerSet.php)。因此,只要你的配置使用了这两个规则集之一,该规则就会默认生效,无需额外声明。

在命令行中单独运行

不依赖规则集,针对单个文件单独验证该规则:

# 仅运行此规则并输出修复结果 php php-cs-fixer fix path/to/File.php --rules=phpdoc_single_line_var_spacing # 只查看差异,不实际修改文件 php php-cs-fixer fix path/to/File.php --rules=phpdoc_single_line_var_spacing --dry-run --diff

--dry-run--diff组合可以安全预览该规则会改动的每一处注释,适合先评估影响面再决定是否落地。

在配置文件中启用

在项目根目录的.php-cs-fixer.php配置文件中显式开启:

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

由于该规则默认已随@Symfony/@PhpCsFixer启用,上述显式声明通常用于只开启少量规则的轻量配置,或用于自定义规则集时精确控制。

使用建议与注意事项

  • 聚焦单行,配合 phpdoc_align 使用:如果项目中同时存在多行@var块并希望对齐,应同时启用phpdoc_align,其优先级机制(本规则先于phpdoc_align执行)能保证间距归一后再对齐,结果稳定;
  • 该规则无配置项:与可配置规则不同,phpdoc_single_line_var_spacing是确定性行为、不接受参数,开与不开只有两种状态,配置成本为零;
  • 向后兼容承诺:官方测试用例定义了受支持的行为,升级 PHP-CS-Fixer 版本时,这些用例所覆盖的场景不会发生破坏性变化(见 规则文档),可放心纳入 CI 流程。

小结

phpdoc_single_line_var_spacing是一条小而精准的 PHPDoc 规则:它以一条锚定单行@var的正则为核心,将注释内部的多余水平空白统一为单空格,同时严格不越界处理多行注释与其他标签;它位于 PHPDoc 处理流水线的中后段,先于phpdoc_align执行,并随@Symfony@PhpCsFixer规则集默认启用。理解它的正则形态与优先级约束,有助于你在排查 PHPDoc 相关修复差异时快速定位问题来源。

  • 开发工具
  • 代码质量
  • 静态分析
  • Lint
  • 格式化

【免费下载链接】PHP-CS-Fixer

A tool to automatically fix PHP Coding Standards issues

项目地址:https://gitcode.com/gh_mirrors/ph/PHP-CS-Fixer
点击查看免费下载

相关推荐

上一篇:Hunyuan-MT API接口开发实战:构建多语言翻译服务的5个关键步骤
下一篇:Metabase Cypress E2E 测试评审方法论:从评审 Skill 到 Lint 规则与 e2e/单测分层决策

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

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

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

立即咨询