benpoulson/phpxray

GitHub: benpoulson/phpxray

一款用 Rust 编写的高性能 PHP 静态分析器,能够推断无类型代码签名并自动修复缺失的类型标注。

Stars: 0 | Forks: 0

# phpxray 一个使用 Rust 编写的快速 PHP 静态分析器。 `phpxray` 将 PHP 解析为带类型的 AST,解析名称和项目符号,反射原生类型和 PHPDoc 类型,运行流敏感的推断,并通过 `phpxray` CLI 报告 PHPStan 风格的诊断信息。 它如今已能应用于真实项目:支持并行解析与分析、YAML 配置、`0`–`max` 级别、多种 报告器、抑制机制、基线、依赖感知的增量监听模式,以及 **300 条规则**。 有两个特点使其与普通的 PHPStan 克隆版截然不同: - **它能推断完全无类型代码的签名。** 对于那些所有内容均为 `mixed` 的遗留函数/方法,系统会根据其函数体和调用点重构出参数和返回类型,以便分析的其余部分能有实际可检查的内容——这在结构上是 PHPStan 无法做到的。 - **它能修复自身发现的问题。** `phpxray --fix` 会针对 `missingType.*` 系列,将推断出的 `@var`/`@param`/`@return` PHPDoc 写回到您的源代码中,并不断迭代直至收敛。 该分析器有意设计得较为保守:对于未知、动态、vendor 不完整以及未解析的情况, 它会回退到宽泛的类型,而不是产生嘈杂的误报。 ## 状态 - **解析器:** 对于受支持的前端已完整实现,并且在已接受的语料库测试夹具上,与 Zend 自身的 AST 保持了 100% 的结构化 AST 差异覆盖率。 - **规则:** 跨越 `0`–`max` 级别共注册了 300 条规则,使用与 PHPStan 忠实一致的标识符(`return.type`、 `method.notFound`、`argument.type` 等)。 - **类型系统:** 联合类型/交叉类型、带有模板边界的泛型、PHPDoc 类型、反射内置类型、流敏感的类型缩小、回调/闭包推断、接收者泛型、集合回调、可迭代对象/生成器精度、条件返回类型,以及用于更高级别的严格性门控。 - **产品功能:** 逐文件的并行分析、全项目结果缓存、增量监听模式、`--fix`、无类型签名推断、由配置驱动的 stub 和类型别名。 ## 安装 ### 预编译二进制文件(推荐) macOS 和 Linux(x86-64 和 ARM64)的预编译、**完全静态** 二进制文件已发布在 [Releases](https://github.com/benpoulson/phpxray/releases) 页面。Linux 构建版本为静态 musl — 单一文件,没有共享库依赖,可在任何发行版(Ubuntu、Alpine、RHEL 等)以及最小化容器中运行。 ``` # macOS + Linux — 安装至 ~/.cargo/bin curl --proto '=https' --tlsv1.2 -LsSf \ https://github.com/benpoulson/phpxray/releases/latest/download/phpxray-installer.sh | sh ``` 或通过 Homebrew(macOS + Linux): ``` brew install benpoulson/tap/phpxray ``` ### 从源码构建 该工作区基于稳定的 Rust 构建(无需 nightly 特性): ``` # 直接添加到你的 PATH cargo install --git https://github.com/benpoulson/phpxray phpxray # 或 clone 并 build git clone https://github.com/benpoulson/phpxray.git cd phpxray cargo build -p phpxray --release # -> target/release/phpxray ``` ## 快速开始 ``` # 在选定的 level 分析 explicit paths phpxray -l 6 src tests # 或使用自动发现的 config file (phpxray.yaml / .yml / .dist.yaml) phpxray # machine-readable output phpxray --error-format json # 原地修复缺失的 PHPDoc types phpxray --fix # 在 files 变更时增量 re-analyze phpxray --watch # 为一个现有的 codebase 编写 baseline,然后从 config 中 reference 它 phpxray --generate-baseline ``` ## 配置 `phpxray.yaml` 示例: ``` level: 8 paths: - src - tests scanPaths: - vendor exclude: - generated/** phpVersion: "8.4" treatPhpDocTypesAsCertain: true inferUntypedSignatures: true baseline: phpxray-baseline.yaml ignore: - identifier: method.notFound path: tests/fixtures/** - message: '#^Call to an undefined function legacy_#' ``` 常用选项: - `level`:`0` 到 `9`,或 `max`。 - `paths`:要分析的文件或目录。 - `scanPaths` / `scanFiles`:解析并反射符号,但不报告来自它们的诊断信息。 - `exclude`:从分析中排除路径(glob)。 - `excludePaths.analyse`:将路径降级为仅扫描;`excludePaths.analyseAndScan`:完全排除。 - `extensions`:要分析的文件扩展名(默认为 `["php"]`)。 - `phpVersion`:目标 PHP 版本,用于感知版本的内置签名。 - `treatPhpDocTypesAsCertain`:与 PHPStan 同名选项的行为保持一致。 - `inferUntypedSignatures`:为无类型的函数/方法重构类型(默认为 `true`)。 - `ignore`:根据消息正则表达式、标识符、path、paths 和/或 count 抑制发现的结果。 其他兼容 PHPStan 的选项: - `stubFiles`:用户提供的 `.stub`/`.php` 文件,其声明会覆盖或补充命名符号的反射(用于修复第三方签名)。 - `typeAliases`:全项目范围的 PHPDoc 类型别名(`{ UserId: 'int' }`)。 - `earlyTerminatingFunctionCalls` / `earlyTerminatingMethodCalls`:永远不会返回的调用(如 `dd`、`abort` 等),因此调用它们的分支会被视为 `throw`。 - `checkExplicitMixed`、`checkImplicitMixed`、`checkUninitializedProperties`、`checkTooWideReturnTypesInProtectedAndPublicMethods`:针对特定规则的严格性开关。 - `resultCachePath`、`editorUrl`:缓存位置以及表格输出中可点击的编辑器链接。 现有的 `phpstan-baseline.neon` 会被直接读取,因此迁移项目的基线可以原封不动地加载。 ## 修复发现的问题 `phpxray --fix` 会针对 `missingType.*` 系列插入推断出的 `@var`/`@param`/`@return` PHPDoc, 并进行迭代直至收敛(每一轮添加的类型都会为下一轮的推断提供更精确的信息),然后重新报告剩余的问题。 被基线标记和被忽略的发现结果永远不会被修复。它与 `--watch` 和 `--generate-baseline` 互斥。 ## 监听模式 `phpxray --watch` 会保持一个实时会话,并仅重新分析更改可能影响到的文件(通过 跨文件查找的依赖图),因此单文件编辑只会重新检查该文件及其依赖项。`--watch-delay MS` 用于调整防抖时间。 ## 抑制机制 内联抑制使用与 PHPStan 兼容的注释(同时也接受 `@phpxray-ignore`): ``` missingMethod(); $user->missingMethod(); // @phpstan-ignore-line method.notFound ``` ## 报告器 使用 `--error-format` 进行选择: `table`(默认)、`json`、`prettyJson`、`raw`、`github`、`checkstyle`、`gitlab`、`junit`。 退出代码: - `0`:无错误 - `1`:报告了发现结果 - `2`:用法或配置错误 ## 开发 ``` cargo test --workspace cargo clippy --workspace --all-targets -- -D warnings cargo run -p xtask -- rule-manifest # the source of truth for rule coverage ``` CI 会在每次推送到 `main` 的操作以及 PR 上运行 clippy 和测试套件。实用的 `xtask` 命令包括 `corpus`、`astdiff`、`resolve`、`index`、`reflect`、`infer`、`check` 和 `rule-timings`。某些 预测/差分任务需要本地 PHP 二进制文件和 PHP AST 扩展;普通的 Rust 测试 套件则不需要 PHP。 ## 架构 该工作区被划分为多个小 crate: - `php-lexer`、`php-parser`、`php-ast`:前端。 - `php-resolve`、`php-index`:名称和项目符号。 - `php-phpdoc`、`php-types`、`php-reflect`:PHPDoc 解析、语义类型、反射。 - `php-infer`:表达式推断、控制流、类型缩小、可赋值性、签名推断。 - `php-rules`:诊断和规则调度。 - `php-config`、`phpxray`:配置、抑制、基线、报告器、增量引擎、CLI。 - `xtask`:开发和语料库工具。 内置定义根据 JetBrains PHPStorm stubs 生成,并编译为感知版本的清单,因此该 二进制文件是完全自包含的(在 runtime 无需 PHP 或数据文件)。 ## 许可证 MIT。
标签:OpenVAS, PHP, Rust, 云安全监控, 代码质量检查, 可视化界面, 类型推断, 网络流量审计, 通知系统, 静态分析