PHPStan 在 2021 年 11 月初获得了具有里程碑意义的版本,其中包含新功能、额外规则和许多性能优化。这意味着领先的 PHP 静态分析器现在被认为是稳定的,并且为未来的更新提供了向后兼容性承诺。
由于这是一个主要的semver 碰撞,PHPStan 1.0 还带来了一些可能会影响您现有扫描的重大更改。这些包括额外的规则和一些替换或删除的配置参数。
新的 9 级
PHPStan 扫描您的 PHP 源代码以查找潜在问题,而无需实际运行代码。除了单元测试和端到端测试外,这还可以通过在用户遇到问题之前将问题暴露出来,让您了解代码的质量。
PHPStan 级别用于配置分析器的严格程度。v0.x 版本系列提供了八个级别,其中 0 级最宽松,8 级最严格。虽然最好使用尽可能严格的级别以获得最佳覆盖率,但不太严格的级别可以帮助您将 PHPStan 引入不完美的代码库。
PHPStan 1.0 添加了级别 9 作为新选项。它包括 8 级及更低级别的所有规则,以及一项额外检查:严格mixed
类型比较。
该mixed
类型在PHP 8.0 中作为显式类型提示“任何”值的一种方式出现。由于mixed
本质上等同于无类型值,因此对mixed
-type 值的外观做出任何假设都是不安全的。
如果您尝试mixed
在代码中主动使用某个值,PHPStan 的第 9 级将通过报告错误来严格执行此操作。不允许访问属性或调用方法,因为您无法知道它们是否存在。mixed
当此规则处于活动状态时,您只能通过其他类型的类型提示传递值。
要选择加入新行为,您需要在配置文件中更改level: 8
为。PHPStan 还支持作为最高级别的别名。如果您已经在使用,当您升级到 PHPStan 1.0 时,您将自动获得 9 级。level: 9
phpstan.neon
level: max
max
Try-Catch-Finally 块中更好的意识
PHPStan 现在对 try-catch-finally 块有更好的类型推断和变量感知。它将使用@throws
docblock 标记来检查代码库中每个函数抛出的异常类型。这种理解用于通知 try-catch 块内的变量可用性检查。
这是一个示例,说明为什么这很重要:
/** * @throws 演示异常 */ function first ( ) { throw DemoException ( ) ; } /** * @throws 其他异常 */ function second ( ) { throw OtherException ( ) ; } 尝试{ $first = first ( ) ; $second =秒( ) ; } catch ( DemoException $ex ) { error_log ( $second ) ; } catch ( \Exception $ex ) { error_log ( "一般异常" ) ; }
第一个catch
博客访问,$second
但DemoException
被捕获时将不存在。PHPStan v1.0 使用该@throws
语句来实现这一点,因此当您的catch
块引用可能未定义的变量时,您会收到通知。没有@throws
注释的函数通常会以与以前相同的方式运行。
由于此更改,可选polluteCatchScopeWithTryAssignments
参数已被删除。这用于让您访问try
以下块中设置的变量catch
;不再需要它,因为 PHPStan 现在可以确定哪些变量可用。
未使用代码检测
PHPStan 在查找和报告项目中某些形式的未使用代码方面做得更好。它将突出显示从未调用或访问的私有类属性、方法和常量。
他们的出现几乎总是无意的。如果您确实希望将死代码保留更长时间,您可以尝试将其@phpstan-ignore-next-line
注释掉或添加注释以绕过检查。
记忆值的改进
v1.0 增强了 PHPStan 对函数返回值的内存一致性。它更擅长理解函数何时被第二次调用,从而更好地预测相同的返回值。
当条件重复数次时,这会导致改进的死代码检测。PHPStan 会在块变得多余时发出警告,因为执行被具有相同条件的较早分支终止:
if ( $demo -> isActive ( ) ) { return ; } if ( $demo -> isActive ( ) ) { recordDemoActivity ( ) ; }
第二个块永远不会运行,因为第一个总是终止。但是有一个假设在起作用:isActive()
必须在 的整个生命周期中始终返回相同的值$demo
。更具体地说,isActive()
需要是一个纯函数,其中重复输入总是产生相同的输出。
PHPStan 假设函数默认是纯函数。如果不是,您可以@phpstan-impure
在函数定义上方的文档块中添加注释。这将禁用该函数的返回值内存。如果isActive()
可以为每个调用返回不同的值,则您需要在上面的示例中使用它,这意味着第一个检查可以等同于false
并允许第二个分支运行。
/** @phpstan-impure */ public function isActive ( ) : bool { return ( date ( "Y" ) === "2021" ) ; }
其他规则改进
一些新的规则已被添加到现有的水平1到6,其中包括用于覆盖检查常数和性质,试图扩展一个final
类,并且总是真,总是假检测while
循环条件。
现在以递归方式检查类型是否缺少类型提示。这意味着 PHPDoc 定义array<array>
不会被接受,因为它们缺少内部类型定义。您还需要对二级数组元素的预期值进行类型提示,例如array<array<string>>
.
除了检查源内容外,PHPStan 1.0 还会检查.php
文件的整体有效性。级别 0 会检查前导和尾随文件空格和 BOM,因为在<?php ... ?>
标签对之前或之后放错位置的字符可能会导致运行时出现意外输出。
性能和稳定性
通过优化特定操作和解决一些内存泄漏问题,性能在多个方面得到了改进。这些应该有助于更快、更可靠地扫描更大的代码库。
由于 v1.0 被认为是正式的稳定版本,因此它保证未来的次要版本(1.1、1.2、1.3 等)将向后兼容。虽然从 v0.x 到 v1.0 可能需要一些配置调整,但您将来会有更简单的迁移路径。
PHPStan 扩展和自定义规则集的开发人员也可以从更稳定的代码库中受益,并且不太可能改变。开发人员文档也得到了扩展,包括更易于访问的自定义规则创建。在 PHPStan 分析中实施团队自己的规则时应该更容易上手。
虽然这预示着未来的支持是个好兆头,但用户和扩展开发人员都面临着迁移到 v1.0 的重大变化。几个扫描配置参数已被重命名或更改,bootstrap
变为bootstrapFiles
并excludes_analyse
替换为excludePaths
.
在内部,扩展 API 已被广泛修改,因此许多类和方法已被更改或删除。v1.0 更改日志中提供了向后不兼容更改的完整列表。
概括
PHPStan v1.0 通过优化性能、添加新规则和解决一些检测违规问题使项目成熟。PHPStan 在过去几年中的发展为 PHP 社区更广泛地转向接受类型化语言概念做出了贡献。类型属性和联合类型等特性的添加产生了一种能够支持高级外部检查以及通过反射进行详细内部自省的语言。
推广到 semver 稳定版本应该有助于鼓励在整个社区中进一步采用 PHPStan。对于已经使用严格的 PHPStan 规则级别的现代项目,迁移到新版本应该是相当轻松的。
您现在可以通过composer require phpstan/phpstan
在您的项目中运行来升级到 PHPStan v1.0 。建议先通读发行说明,以确定您需要解决的重大更改。每个现有级别中存在的额外规则可能会导致您的代码库开始失败的测试,即使它通过 PHPStan v0.x。您可以通过将新规则添加到基线来暂时禁用新规则,以便将它们从扫描结果中排除。
原创文章,作者:校长,如若转载,请注明出处:https://www.yundongfang.com/Yun84339.html