muglug/pzoom

GitHub: muglug/pzoom

pzoom 是 Psalm 的 Rust 移植版,为 PHP 项目提供快速的静态类型分析能力。

Stars: 0 | Forks: 0

# pzoom 一个使用 Rust 编写的快速 PHP 静态分析器 —— [Psalm](https://github.com/vimeo/psalm) 的移植版。 阅读背景故事:[从 Psalm 到 Pzoom](https://mattbrown.dev/articles/from-psalm-to-pzoom)。 ## 通过 Composer 安装 PHP 项目可以将 pzoom 作为开发依赖进行安装,并与 `composer.json` 中的其他内容一起进行版本管理: ``` composer require --dev muglug/pzoom ``` 你无需在本地安装 Rust 工具链。Composer 插件会在 `composer install` / `composer update` 期间,从对应的 GitHub release 中下载与你的平台匹配的预编译原生二进制文件,并将其暴露在 `vendor/bin/pzoom`: ``` vendor/bin/pzoom path/to/php/project ``` 每个 Composer 版本都映射到一个 `vX.Y.Z` 的 GitHub release,因此锁定版本约束(`"muglug/pzoom": "^0.1"`)也会同时锁定对应的二进制文件。 由于该包附带了一个 Composer 插件,在首次安装时,Composer 会要求你允许执行它。若要非交互式地允许执行(例如在 CI 中),请将其添加到你的 `composer.json` 中: ``` { "config": { "allow-plugins": { "muglug/pzoom": true } } } ``` 目前为 Linux(`x86_64`、`aarch64`)和 macOS(Apple Silicon)发布了预编译的二进制文件。在任何其他平台上,请按照以下说明从源码构建。 ## Stub provider pzoom 的分析器是原生二进制文件,无法执行 PHP。因此,对于需要*运行* PHP 才能获取类型信息的框架集成——例如启动应用并反射 Eloquent 模型、容器绑定、facades 等(就像 [psalm-plugin-laravel](https://github.com/psalm/psalm-plugin-laravel) 所做的那样)——无法在分析过程中运行。相反,它作为 **stub provider** 运行:这是一个小型的 PHP 类,(可选地)在分析前生成 stub 文件。`vendor/bin/pzoom` 会运行每个已注册的 provider,然后通过 `--stubs` 将它们的 stub 传递给二进制程序;二进制程序只会扫描它们以获取类型信息(绝不会对其进行分析或报告错误)。 这是特意设计为仅使用 stub 的方式 —— provider 只负责添加类型定义,不会介入分析过程。Psalm 插件通过 return-type provider 表达的大部分内容,都可以使用 stub 注解(`@method`、`@property`、generics)来表示,因此 stub 无需在分析中途执行用户代码即可覆盖常见的框架场景。 通过实现 `Pzoom\StubProvider` 来编写一个 provider: ``` use Pzoom\StubProvider; final class MyStubProvider implements StubProvider { public function getStubFiles(string $cacheDir): array { // Ship fixed stubs, or generate them here (boot the app, reflect, …) // and write into $cacheDir. Return the file/directory paths to scan. file_put_contents($cacheDir . '/models.phpstub', $generatedStub); return [$cacheDir . '/models.phpstub']; } } ``` 并在包的 `composer.json` 中注册它 —— pzoom 会以这种方式从每个已安装的包(以及根项目)中发现 provider: ``` { "extra": { "pzoom": { "stub-providers": ["Vendor\\Package\\MyStubProvider"] } } } ``` Provider 会将文件生成到项目的 `.pzoom/` 目录中(请将其添加到 `.gitignore`);pzoom 绝不会分析该目录。你也可以直接传递 stub,从而绕过 provider 机制: ``` vendor/bin/pzoom --stubs path/to/stubs path/to/php/project ``` [`examples/pzoom-laravel`](examples/pzoom-laravel) 是一个完整的参考 provider,它会启动 Laravel 应用并从 `$casts` 生成 Eloquent 模型 stub。 ## 构建 需要最新稳定的 [Rust 工具链](https://rustup.rs/)。 ``` git clone https://github.com/muglug/pzoom cd pzoom cargo build --release ``` 构建好的二进制文件位于 `target/release/pzoom`。 ## 运行 在有 `psalm.xml` 的项目中运行(或指向)它: ``` target/release/pzoom path/to/php/project ``` pzoom 会读取 Psalm 的 XML 配置格式(项目根目录下的 `psalm.xml`、`psalm.xml.dist` 或 `psalm.dist.xml`),因此现有的 Psalm 配置可以直接使用 —— 参阅 [Psalm 配置文档](https://psalm.dev/docs/running_psalm/configuration/)。 `pzoom --help` 列出了一些 CLI 选项(输出格式、线程数、配置路径)。 ## 测试 ``` # Inference 测试 (tests/inference/**) cargo run --release -p pzoom-test-runner # Unit 测试 cargo test ``` ## 与 Psalm 的差异 pzoom 的目标是广泛地与 Psalm 的分析能力保持一致,但存在一些刻意的设计分歧: - **区分大小写的名称解析。** PHP 和 Psalm 在解析类、函数和方法名称时不区分大小写。pzoom 解析它们时区分大小写:如果引用的大小写错误,将会报告为 `UndefinedClass` / `UndefinedDocblockClass` / `UndefinedFunction` / `UndefinedMethod`,并在消息中建议正确大小写的名称(例如 ``Class foo does not exist (incorrect casing of Foo)``)。运行时的真实性检查仍然遵循 PHP 语义:`method_exists()` 进行不区分大小写的匹配,并且方法*声明*在覆盖父类方法时也不区分大小写。 - **ComplexMethod 计算** Pzoom 的 ComplexMethod 指标是通过函数内赋值操作之间的连接图谱计算得出的。Pzoom 的图比 Psalm 的更大(它追踪了更多的连接),因此我们在 Psalm 中对 ComplexMethod 问题进行了近似处理。 ## 许可证 [MIT](LICENSE)
标签:OpenVAS, PHP, Rust, SOC Prime, 云安全监控, 代码审查, 可视化界面, 开发工具, 网络流量审计, 通知系统, 静态分析