Skip to content

Latest commit

 

History

History
259 lines (196 loc) · 12.8 KB

File metadata and controls

259 lines (196 loc) · 12.8 KB

项目结构与贡献指南

本文档描述 Metamorphosis 项目的仓库布局、crate 依赖关系、规则开发流程、测试策略以及提交规范。请在阅读下方的强制编码规则前先熟悉本节内容。


Workspace 布局

metamorphosis/
├── crates/
│   ├── core/        # 引擎 + 抽象(types, traits, context, registry, engine, extractor)
│   ├── rules/       # 4 个内置重写规则 + eq_analyzer 共享模块
│   ├── cli/         # CLI 入口(5 个子命令:rewrite/suggest/show-rules/verify/mcp)
│   ├── qed/         # QED 离线验证(嵌入式 Z3,rich schema)
│   ├── verieql/     # 有界等价验证(独立,零 metamorphosis 依赖)
│   └── mcp-server/  # MCP 服务器(5 个工具,stdio 传输)
├── docs/            # 设计文档、贡献指南、最佳实践、实现计划
├── scripts/         # 安装脚本(install-qed-prover.sh, run-qed-verify.sh)
├── testcases/       # 手动测试用例
└── Cargo.toml       # Workspace 根配置

依赖关系(禁止反向依赖)

cli ──► rules ──► core ──► ogsql-parser
  └──► qed ──► core
  └──► mcp-server ──► rules, qed, verieql, core

verieql ──► ogsql-parser (独立,不依赖任何 metamorphosis crate)

关键约束:

  • core 零外部 IO 依赖。
  • verieql 完全独立,仅依赖 ogsql-parserz3
  • mcp-server 依赖所有其他业务 crate。
  • 禁止任何反向依赖

如何添加新规则

  1. crates/rules/src/ 创建新文件,实现 RewriteRule trait。
  2. 必须实现的方法:id()description()category()safety_level()matches() -> MatchResultapply() -> Option<RewriteAction>
  3. 可选覆盖:default_enabled() -> bool
  4. crates/rules/src/lib.rs 中注册。
  5. crates/rules/tests/ 添加测试。
  6. 如果规则产生 Replace 动作,建议添加 QED 等价性验证测试。

最小规则骨架:

use metamorphosis_core::{RewriteRule, RewriteContext, RewriteAction, SafetyLevel, RuleCategory, MatchResult};

#[derive(Debug)]
pub struct MyRule;

impl RewriteRule for MyRule {
    fn id(&self) -> &'static str { "my-rule" }
    fn description(&self) -> &'static str { "描述" }
    fn category(&self) -> RuleCategory { RuleCategory::Semantic }
    fn safety_level(&self) -> SafetyLevel { SafetyLevel::Safe }
    fn matches(&self, _ctx: &RewriteContext, stmt: &Statement) -> MatchResult {
        // 匹配逻辑
        MatchResult::Matched
    }
    fn apply(&self, ctx: &RewriteContext, stmt: &Statement) -> Option<RewriteAction> {
        // 重写逻辑
        None
    }
}

测试策略

  • 测试金字塔:50% 规则单元测试,30% 引擎单元测试,20% 集成测试。
  • 每个规则必须有独立的测试文件 crates/rules/tests/
  • Safe / Conditional 规则建议配合 QED E2E 测试验证语义等价性。
  • 使用 cargo test --workspace 运行全部测试。
  • QED E2E 测试运行:scripts/run-qed-verify.sh

提交规范

  • 采用 Conventional Commits:feat:fix:docs:test:refactor:chore:style:
  • 示例:feat(rules): add eliminate-join-elimination rule
  • cargo fmt 必须通过。
  • cargo clippy -- -D warnings 必须通过。
  • Cargo.lock 必须提交。

文档一:必须遵循的规则(Mandatory)

底线要求。不遵守这些规则将直接影响代码安全、可维护性、团队协作效率或生产稳定性。必须在 Code Review 和 CI 中强制检查。


1. 项目架构与模块化

规则 要求 来源/依据
M-ARCH-01 使用 Cargo Workspace 组织项目,按职责分层(core / application / adapters / api),禁止反向依赖。 工程实践
M-ARCH-02 core 层必须零外部 IO 依赖,保证业务逻辑的平台无关性与可测试性。 工程实践
M-ARCH-03 单个 .rs 文件不得超过 600 行,理想控制在 400 行以内。超过必须拆分模块。 工程实践
M-ARCH-04 入口文件(main.rslib.rs)尽量不超过 200 行,仅做模块聚合与初始化。 工程实践
M-MOD-01 一个项目中禁止混用不同的模块布局风格(统一使用 mod.rs 或统一使用 module.rs)。 G.MOD.04
M-MOD-02 不要在私有模块中将内部类型设为 pub(crate),可见性必须逐层精确控制。 G.MOD.05
M-MOD-03 作为库对外提供时,lib.rs 中必须重新导出对外公开的 API。 G.MOD.02

2. 代码风格与格式化(CI 强制门禁)

规则 要求 来源/依据
M-FMT-01 强制使用 rustfmt 自动格式化代码,不接受人工风格争论。 P.FMT.01
M-FMT-02 缩进使用空格而非制表符。 P.FMT.02
M-FMT-03 extern 外部函数必须显式指定 "C" ABI(extern "C")。 P.FMT.14
M-FMT-04 具名结构体字段初始化时不得省略字段名(除非变量名与字段名完全一致)。 P.FMT.13
M-FMT-05 导入模块分组必须具有良好的可读性,禁止随便使用通配符 * P.FMT.11 / G.MOD.03

3. 命名规范

规则 要求 来源/依据
M-NAM-01 同一个 crate 中标识符命名必须使用统一的词序(如全用 verb_noun 或全用 noun_verb)。 P.NAM.01
M-NAM-02 getter 类方法禁止使用 get_ 前缀(用 name() 而非 get_name())。 P.NAM.05
M-NAM-03 类型转换函数命名遵循所有权语义:as_(借用)、to_(可能分配)、into_(消耗所有权)。 G.NAM.02
M-NAM-04 全局静态变量必须加前缀 G_ 以便和常量区分。 P.NAM.09
M-NAM-05 作用域越大命名越精确,反之应简短。 P.NAM.04

4. 类型系统与数据安全

规则 要求 来源/依据
M-TYP-01 类型转换禁止使用裸 as,必须使用安全的转换函数(try_frominto 等)。 G.TYP.01
M-TYP-02 数字字面量必须明确标注类型(如 42u64)。 G.TYP.02
M-TYP-03 对外导出的公开 Struct 和 Enum 必须添加 #[non_exhaustive] G.TYP.SCT.01 / G.TYP.ENM.05
M-TYP-04 结构体中超过 3 个布尔字段时,必须将其独立为新的枚举类型。 G.TYP.SCT.02
M-TYP-05 禁止将数字类型转换为布尔值,禁止用数字代替布尔值。 G.TYP.BOL.03 / G.TYP.BOL.06
M-TYP-06 使用数组索引时必须确保不越界,禁止依赖数组边界检查来 Panic。 G.TYP.ARR.02 / G.EXP.03
M-TYP-07 元组元素不宜超过 3 个,超过应使用结构体。 G.TYP.TUP.01

5. 错误处理(强制底线)

规则 要求 来源/依据
M-ERR-01 库代码(lib)禁止返回 anyhow 等不透明错误,必须定义具体的错误类型(使用 thiserror)。 工程实践
M-ERR-02 禁止在库代码中使用 unwrap()。应用代码(bin)也须极度克制。 G.ERR.01
M-ERR-03 确定不可能为 None/Err 时,可使用 expect(),但信息必须说明"为什么不会失败"。 P.ERR.02
M-ERR-04 当传入参数超出限制可能导致函数失败时,必须使用断言(assert! P.ERR.01
M-ERR-05 公开的返回 Result 的函数文档中必须增加 Error 注释;可能 Panic 的必须增加 Panic 注释。 G.CMT.01 / G.CMT.02
M-ERR-06 实现 From 而非 Into(因为 Into 有默认实现)。 G.TRA.BLN.08

6. 并发与异步(安全底线)

规则 要求 来源/依据
M-ASY-01 禁止在异步块/函数中持有同步互斥锁(MutexGuard)跨越 await G.ASY.02
M-ASY-02 禁止在异步块/函数中持有 RefCell 引用跨越 await G.ASY.03
M-ASY-03 异步函数中禁止包含阻塞操作(文件 IO、密集计算必须使用 spawn_blocking)。 G.ASY.05
M-ASY-04 异步运行时(tokio/async-std)一旦选定,全局统一,禁止混用 工程实践
M-MTH-01 对布尔或引用的并发访问必须使用原子类型,禁止用互斥锁。 G.MTH.LCK.01
M-MTH-02 多线程下必须识别锁争用情况,避免死锁。 P.MTH.LCK.01

7. Unsafe Rust(绝对红线)

规则 要求 来源/依据
M-UNS-01 禁止为了逃避编译器检查而滥用 Unsafe P.UNS.01
M-UNS-02 任何 unsafe 块之前必须加 SAFETY 注释,说明为什么此处是安全的。 P.UNS.SAS.09
M-UNS-03 公开的 unsafe 函数文档中必须增加 Safety 注释 G.UNS.SAS.01
M-UNS-04 Unsafe 函数中校验边界条件必须使用 assert!禁止使用 debug_assert! G.UNS.SAS.02
M-UNS-05 禁止在公开 API 中暴露未初始化内存和裸指针。 P.UNS.SAS.03 / P.UNS.SAS.06
M-UNS-06 禁止将不可变指针手工转换为可变指针。 G.UNS.PTR.02
M-UNS-07 禁止将裸指针在多线程间共享。 P.UNS.PTR.01

8. FFI(如涉及 C 互操作)

规则 要求 来源/依据
M-FFI-01 跨越 FFI 边界的函数必须处理 Panic(使用 catch_unwind)。 P.UNS.FFI.04
M-FFI-02 使用 libc 或标准库提供的可移植类型别名,禁止直接使用平台特定类型。 P.UNS.FFI.05
M-FFI-03 禁止为传出外部的类型实现 Drop P.UNS.FFI.07
M-FFI-04 依赖 C 端传入的参数时,文档中必须声明不变性,并进行合法性检查。 P.UNS.FFI.12 / P.UNS.FFI.15
M-FFI-05 自定义数据类型必须保证与 C 端一致的数据布局(#[repr(C)])。 P.UNS.FFI.13

9. 日志与可观测性(底线)

规则 要求 来源/依据
M-LOG-01 统一使用 tracing,禁止使用 log 工程实践
M-LOG-02 生产环境日志必须输出结构化 JSON,禁止纯文本格式。 工程实践
M-LOG-03 日志级别语义必须统一:ERROR(需告警)、WARN(可自愈异常)、INFO(关键生命周期)、DEBUG/TRACE(开发调试)。 工程实践
M-LOG-04 严禁在日志中记录敏感信息(密码、Token、PII),必须使用脱敏或 [REDACTED] 工程实践
M-LOG-05 每个外部请求入口必须创建 Span,包含 trace_id / request_id 工程实践
M-LOG-06 ERROR 级别日志必须包含可行动的上下文(哪里、为什么、影响范围),禁止仅记录 ?err 工程实践

10. 依赖与构建

规则 要求 来源/依据
M-DEP-01 Cargo.toml 中依赖版本禁止使用通配符 * G.CAR.04
M-DEP-02 应用项目必须将 Cargo.lock 提交到版本控制。 工程实践
M-DEP-03 必须声明 rust-version(MSRV)并在 CI 中验证。 工程实践
M-DEP-04 使用 cargo-deny 在 CI 中检查许可证、安全漏洞(RUSTSEC)和禁止的依赖。 工程实践
M-DEP-05 使用 cargo features 进行条件编译,禁止使用 --cfg P.CAR.03

11. 文档与注释

规则 要求 来源/依据
M-DOC-01 所有 pub API 必须有文档注释,cargo doc 无警告。 工程实践
M-DOC-02 文档注释中使用空格代替 tab G.CMT.03
M-DOC-03 优先使用行注释 //,避免使用块注释 /* */ P.CMT.03
M-DOC-04 代码中保留的 FIXME / TODO 必须通过任务系统跟踪,禁止无跟踪长期遗留。 P.CMT.05

12. 信息安全

规则 要求 来源/依据
M-SEC-01 引入第三方库前必须评估维护活跃度、下载量、依赖树深度,防范供应链攻击。 P.SEC.01
M-SEC-02 代码中禁止出现非法 Unicode 字符(如双向覆盖字符)。 G.SEC.01

使用建议

  1. **文档一(必须遵循)**应直接写入团队的 CONTRIBUTING.md,并在 CI 中配置对应的检查工具(rustfmtclippycargo-denycargo-semver-checks 等)。
  2. 文档应每半年评审一次,根据项目演进和 Rust 生态发展进行更新。

相关文档

  • 设计文档:docs/metamorphosis_design_doc.md
  • 最佳实践:docs/BEST-PRATICE.md
  • 用户手册:docs/UserGuide.md
  • 开发者指南:docs/DeveloperGuide.md
  • QED 理论:docs/QED.md