yangweijie/aot-rector

Rector rules for transforming PHP code to be compatible with Swoole AOT Compiler

Maintainers

Package info

github.com/yangweijie/aot-rector

Type:rector-extension

pkg:composer/yangweijie/aot-rector

Statistics

Installs: 0

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

v0.1.0 2026-05-18 02:32 UTC

This package is auto-updated.

Last update: 2026-05-18 02:34:12 UTC


README

将 vendor 目录中的第三方 PHP 代码转换为兼容 Swoole AOT Compiler 语法的自动化工具。

工作原理

composer aot:rector
    │
    ├── Step 1: Rector 转换
    │   vendor/bin/rector process vendor/ → @aot/
    │   (应用 6 条规则,83+ 个文件被转换)
    │
    ├── Step 2: 生成补丁
    │   vendor/bin/aot-patch → patches/*.patch
    │   (对比 vendor 和 @aot,生成 diff)
    │
    └── Step 3: 应用补丁
        aot-patch → 将 @aot 文件复制回 vendor/
        (修改后的 vendor 代码即可用于 AOT 编译)

规则列表

规则 针对语法 操作
DollarDollarToArrayAccessRector $$var 动态变量 转为 $_dyn_vars[$key]
ExtractToManualAssignmentRector extract() 函数 替换为参数表达式 + 注释提醒
MultiBreakContinueRector break N / continue N 添加注释提醒改用 goto
StringNullByteRector 字符串字面量中含 \0 替换为 "str".chr(0)."续"
FreeCodeToFunctionRector 游离代码(不在函数内) 标记检测结果
ClosureRefParamToRefvalRector 闭包引用参数 &$var 添加注释提醒使用 refval()

安装

composer require yangweijie/aot-rector

配置

1. rector.php

复制模板到项目根目录:

cp vendor/yangweijie/aot-rector/rector.php.dist rector.php

根据项目的 vendor 依赖,在 withSkip 中添加需要跳过的文件:

->withSkip([
    // ... 默认跳过规则 ...
    'vendor/topthink/framework/src/think/exception/Handle.php',
    'vendor/topthink/think-helper/src/helper/Arr.php',
    // 你的项目中解析报错的文件
])

2. composer.json 脚本

Composer 脚本不会自动从依赖包继承,需要在根项目的 composer.json 中添加:

"scripts": {
    "aot:rector": [
        "vendor/bin/rector process vendor/ --config rector.php",
        "vendor/bin/aot-patch"
    ],
    "aot:rector-dry": "vendor/bin/rector process vendor/ --config rector.php --dry-run || true",
    "aot:patch": "vendor/bin/aot-patch"
}

命令参考

命令 说明
composer aot:rector 完整流程:Rector 转换 → 生成补丁 → 应用到 vendor
composer aot:rector-dry 预览:只显示 Rector 会改哪些文件,不改写
vendor/bin/aot-patch 仅补丁:对比 @aot/vendor/,生成补丁并应用
composer aot:patch 同上(通过 composer 脚本)

首次运行:

# 先预览
composer aot:rector-dry

# 确认后执行
composer aot:rector

后续如果修改了 patches/ 中的补丁文件,重新执行 composer aot:rectorvendor/bin/aot-patch 即可同步到 vendor。

目录说明

项目根目录/
├── rector.php          # Rector 配置文件(需手动创建)
├── @aot/               # Rector 转换后的代码(自动生成)
│   └── vendor/         #   — 镜像 vendor 目录结构
├── patches/            # 补丁文件(自动生成,可手动修改)
│   └── .manifest.json  #   — 已补丁文件清单
└── vendor/             # 被修改的 vendor 代码

跳过规则配置

rector.phpwithSkip 的常见配置项:

->withSkip([
    // 测试文件
    '*/Tests/*', '*/tests/*', '*/Test/*', '*/test/*',

    // Composer 自动生成文件
    '*/vendor/autoload.php',
    '*/vendor/composer/*',

    // Rector 自身(避免嵌套 vendor/ 循环)
    'vendor/rector/**',

    // Rector 解析器不支持的语法
    'vendor/symfony/polyfill-*/**',
    'vendor/symfony/var-dumper/**',

    // 项目中解析报错的特定文件
    'vendor/topthink/framework/src/think/exception/Handle.php',
    'vendor/topthink/framework/src/think/view/driver/Php.php',
    'vendor/topthink/think-helper/src/helper/Arr.php',

    // 非 PHP 文件
    '*.json', '*.yml', '*.yaml', '*.xml', '*.neon', '*.md', '*.dist',
])

注意:被跳过的文件不会被 Rector 转换,但不影响 AOT 编译。AOT 编译器使用 ZendPHP 自己的解析器而非 Rector 的 nikic/php-parser

开发

运行测试

cd packages/aot-rector
composer install
composer test

测试夹具结构

tests/Rules/Fixtures/{RuleName}/
├── some_feature.php.inc      # 转换测试
├── skip_passthrough.php.inc  # 不做转换的测试(无 ----- 分隔符)
└── ...

夹具格式:

<?php
// ———— 输入(转换前) ————
$name = 'foo';
$$name = 'hello';

?>
-----
<?php
// ———— 期望输出(转换后) ————
$name = 'foo';
$_dyn_vars[$name] = 'hello';

?>

Patcher 类

  • Aot\Rector\Patcher — 补丁生成和应用
  • Aot\Rector\PatcherConfig — 路径配置常量
  • bin/aot-patch — CLI 入口(Composer bin 脚本)

路径解析使用 getcwd() 获取项目根目录,因此可以在任意目录执行。