资讯详情

资讯详情

Psalm 的 MissingThrowsDocblock 检查:用 checkForThrowsDocblock 强制异常文档化

开发工具代码质量质量保障【免费下载链接】psalmA PHP static analysis tool for finding errors and security vulnerabilities in PHP applications项目地址https://gitcode.com/gh_mirrors/ps/psalm点击查看免费下载Psalm 是 PHP 静态分析工具其MissingThrowsDocblock问题用于在启用checkForThrowsDocblock配置后强制要求函数与方法在抛出或未处理异常时提供throws注解从而让异常契约成为代码库中可被静态检查的显式声明。本文围绕该问题类型的触发条件、配置方式、底层检测原理、忽略规则与自动修复能力展开帮助你将其接入现有工程并理解其工作细节。什么是 MissingThrowsDocblock官方文档对它的定义非常简洁当checkForThrowsDocblock配置项被启用时Psalm 会在「函数抛出了异常或未能处理某个异常却没有throws注解」时发出该问题。最典型的一个触发示例来自 MissingThrowsDocblock.md?php function foo(int $x, int $y) : int { if ($y 0) { throw new \InvalidArgumentException(Cannot divide by zero); } return intdiv($x, $y); }函数foo在$y 0时主动抛出InvalidArgumentException但由于函数体内部没有try/catch处理它这个异常会沿调用链向上传播。在开启checkForThrowsDocblock的前提下Psalm 会在此处报告MissingThrowsDocblock并给出类似提示InvalidArgumentException is thrown but not caught - please either catch or add a throws annotation也就是说Psalm 要求开发者二者择一要么在函数内部捕获异常要么在 docblock 中明确声明它可能抛出什么。开启与配置MissingThrowsDocblock默认不启用必须先开启配置项才会检测。对应配置在 configuration.md 中描述psalm checkForThrowsDocblock[bool] 当值为true时Psalm 会检查开发者是否为函数或方法抛出的每一个异常提供了throwsdocblock默认值为false。从源码看配置解析在 Config.php 中完成第 354 行定义了public bool $check_for_throws_docblock false;第 985 行将 XML 属性名checkForThrowsDocblock映射到该属性。因此以下两种写法等价psalm checkForThrowsDocblocktruepsalm checkForThrowsDocblockfalse开启后上面的foo函数会立即收到MissingThrowsDocblock报告。修复方式是为其补充throws注解?php /** * throws \InvalidArgumentException */ function foo(int $x, int $y) : int { if ($y 0) { throw new \InvalidArgumentException(Cannot divide by zero); } return intdiv($x, $y); }检测规则与底层原理MissingThrowsDocblock的判定逻辑位于 FunctionLikeAnalyzer.php核心步骤如下调用$statements_analyzer-getUncaughtThrows($context)获取函数体内所有「可能被抛出且未被捕获」的异常集合返回格式为exception 名 CodeLocation 列表见 StatementsAnalyzer.php。将该集合与函数存储$storage-throws中已经通过throws声明的异常逐一比对。比对时不仅要求类名完全相同还支持继承关系匹配如果实际抛出的异常是已声明异常的子类或实现了已声明的接口也视为「已覆盖」。对应代码为 FunctionLikeAnalyzer.phpif ($expected_exception $possibly_thrown_exception || ( $codebase-classOrInterfaceExists($possibly_thrown_exception, null, $context) ( $codebase-interfaceExtends($possibly_thrown_exception, $expected_exception) || $codebase-classExtendsOrImplements($possibly_thrown_exception, $expected_exception) ) ) ) { $is_expected true; break; }不在期望集合中的异常会通过IssueBuffer::maybeAdd上报为MissingThrowsDocblock。该问题类型定义在 MissingThrowsDocblock.php继承自ClassIssueSHORTCODE 169属于类级别的静态分析问题。子类覆盖规则举例基于上述继承匹配逻辑下面这种写法是合法的函数声明抛Exception实际抛出其子类RuntimeException不会触发MissingThrowsDocblock?php /** * throws Exception */ function foo(): void { if (rand(0, 1)) { throw new RuntimeException(boom); } }反过来如果throws声明的是子类而实际抛出父类则无法匹配会照常报错。如何忽略特定异常ignoreExceptions并非所有异常都值得强制文档化。Psalm 提供了ignoreExceptions配置用于豁免特定异常或其全部子类的MissingThrowsDocblock以及checkForThrowsInGlobalScope报告见 configuration.mdignoreExceptions class namefully\qualified\path\Exc onlyGlobalScopetrue / classAndDescendants namefully\qualified\path\OtherExc / /ignoreExceptions各标签语义class只忽略指定类本身。若设置onlyGlobalScopetrue则仅对全局作用域的checkForThrowsInGlobalScope生效函数与方法内的MissingThrowsDocblock检查不受影响。classAndDescendants忽略指定类及其所有子类。在实现上getUncaughtThrows会读取配置中的ignored_exceptions、ignored_exceptions_and_descendants并区分全局作用域与非全局作用域两组集合见 StatementsAnalyzer.php。被豁免的异常会直接跳过不会进入后续的throws比对流程。如何单点压制psalm-suppress对于个别确实需要容忍的位置不必全局关闭配置可以使用标准的问题压制注解。测试 ThrowsAnnotationTest.php 中出现了如下写法/** psalm-suppress MissingThrowsDocblock */将其置于函数或方法上方即可跳过该位置的检查其余位置的强制文档化依然生效。自动修复让 Psalter 补全throwsMissingThrowsDocblock不只是报告问题Psalm 还支持通过代码修改工具自动补全缺失的throws注解。相关逻辑位于 FunctionLikeAnalyzer.phpif ($codebase-alter_code isset($project_analyzer-getIssuesToFix()[MissingThrowsDocblock]) !$this-function instanceof VirtualNode ) { $manipulator FunctionDocblockManipulator::getForFunction( $project_analyzer, $this-source-getFilePath(), $this-function, ); $manipulator-addThrowsDocblock($missingThrowsDocblockErrors); }当以代码修改模式运行如psalter或--alter且MissingThrowsDocblock被列入待修复问题清单时Psalm 会收集所有缺失的异常类型通过FunctionDocblockManipulator::addThrowsDocblock自动将其写入函数的 docblock。这意味着开启该检查后你可以放心地一次性修复存量代码Psalm 负责把缺失的throws精确补到对应函数上而不是全部靠手工处理。测试用例与行为验证仓库的 ThrowsAnnotationTest.php 为该问题提供了大量回归测试可帮助理解边界行为例如testUndocumentedThrow函数抛出多个未声明异常如RangeException、InvalidArgumentException预期产生MissingThrowsDocblockL172-L200。testDocumentedThrow同一函数在补全所有throws后不再报错L202 起。testUndocumentedThrowOfGenericClass即使throws中使用了泛型语法如MyExceptionint实际抛出的异常不在声明范围内时仍会触发L147-L170。这些测试通过Config::getInstance()-check_for_throws_docblock true;开启检查后调用analyzeFile验证确认了「声明必须与实际抛出匹配」的核心行为。小结MissingThrowsDocblock是 Psalm 将异常契约纳入静态检查的开关式能力适合对库代码、接口层或公共服务要求严格异常文档化的团队。使用它只需三步在psalm.xml中设置checkForThrowsDocblocktrue用throws补齐函数与方法的异常声明必要时借助ignoreExceptions与psalm-suppress处理豁免场景最后可用psalter自动修复存量代码。它解决的问题本质上是「异常是接口的一部分应当被显式声明」从而让调用者从 docblock 中即可获知函数可能抛出的风险。赞分享开发工具代码质量质量保障【免费下载链接】psalmA PHP static analysis tool for finding errors and security vulnerabilities in PHP applications项目地址https://gitcode.com/gh_mirrors/ps/psalm点击查看免费下载相关推荐Psalm 的 MissingOverrideAttribute 检查用 [\Override] 强制标注重写方法Psalm 的 MissingOverrideAttribute 检查用 \Override 强制标注重写方法 导读 本文围绕 Psalm 的 Missin开发工具代码质量质量保障Psalm InvalidThrow 完全指南从异常类型检查到实战排查Psalm InvalidThrow 完全指南从异常类型检查到实战排查 摘要导读 本文围绕 Psalm 静态分析器中的 InvalidThrow 问题类型展开开发工具代码质量质量保障一段10秒视频克隆你的脸和声音开源数字人 Duix.Avatar 本地部署完整教程一段10秒视频克隆你的脸和声音开源数字人 Duix.Avatar 本地部署完整教程 如果你做过数字人视频多半有过这样的顾虑要克隆自己的形象和声音就得把视人工智能AI 应用数字人媒体生成桌面应用上一篇aiogram 获取 Bot 默认管理员权限getMyDefaultAdministratorRights 方法完整指南下一篇Strata 实战指南Unsloth UD-Q4_K_XL 4-bit 量化模型的 in-place 专家加载、RAM 预算与质量验证创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
觉得有用,分享给同行:

为您的企业打造数字门面

稳重轻奢商务风格,端正雅致视觉,长效耐看不易过时。

立即咨询 →