momiji-rs/oxidecop

GitHub: momiji-rs/oxidecop

OxideCop 是一款基于 Rust 和 Prism 解析器的 Ruby 代码检查与自动修复工具,旨在以极快的原生速度提供与 RuboCop 逐字节兼容的 lint 体验。

Stars: 0 | Forks: 0

# OxideCop 一款快速、原生且 **兼容 RuboCop** 的 Ruby linter 和 autocorrector —— 使用 Rust 编写,基于官方的 [Prism](https://github.com/ruby/prism) parser。可以把它看作 *ruff 的 Ruby 版,并且与大家已经在用的 RuboCop 保持 bug 级别的兼容。* ``` cargo install oxidecop oxidecop . # same offenses, same messages, same exit code — just fast ``` ## 为什么选择 OxideCop RuboCop 是事实上的标准 Ruby linter,但它运行在 CRuby 上,且**在解释型的 `parser` gem 中,解析时间占据了主导地位**。一个能够处理 Prism 的原生 linter 速度要快上一个数量级,同时能产生**逐字节一致的输出**,因此它可以零配置改动地直接接入现有项目。 只有当我们对 **RuboCop 的实际行为保持绝对忠诚**(而不是仅仅是“本质上的等效”)时,这个赌注才会奏效。这就是为什么保真度是对照 RuboCop *自己的* 测试套件来衡量的,而不是靠肉眼观察: | | | |---|---| | 整个 tree lint,Rails(约 3,400 个文件) | **57 ms** | | 对比 [oxicop](https://crates.io/crates/oxicop)(基于 regex,无 parser) | 快 2–5 倍 — 并且在 oxicop 误报数千个问题的地方能得出正确结果 | | 对比 [nitrocop](https://github.com/6/nitrocop)(基于 prism,915 个 cops) | 冷启动快 4–31 倍;在 RuboCop 自己的 CI-clean repo 中,它报告了 17,174 个 offenses,而 OxideCop 报告了真正的零 | | 热重跑(没有任何改动) | **~29 ms**(基于 stat 键入的结果缓存,无文件读取) | ## 可量化的保真度 RuboCop 的 spec 套件内联了确切的预期结果: ``` expect_offense(<<~RUBY) x == nil ^^ Prefer the use of the `nil?` predicate. RUBY ``` **oracle** (`oracle/oracle.rb`) 会解析这些 fixtures,在*该示例自己的* `cop_config` 下,通过 `oxidecop` 二进制文件运行去除了注释的源码,并在三个层级上进行 diff:**LOC**(正确的 line:col),**FULL**(line:col *以及* 相同的消息),和 **FIX**(对照 `expect_correction` 的 `--fix` 输出)。 当前的排行榜(`ruby oracle/leaderboard.rb`),对照 RuboCop v1.88.0: ``` 47 cops implemented — every one at 100% FULL match, 100% FIX (autocorrect). TOTAL (representable examples) 1051 108 1051/1051 100% FIX 477/477 ``` **客观解读:** 该分数仅针对*可表示的*示例计算。RuboCop 的 specs 动态编码了一些文本(RSpec 循环变量,`%{identifier}` 替换,在调用者配置下运行的 `shared_examples`);oracle 会渲染静态内容并**跳过**非静态内容,而不是将测试套件的限制计为 cop 的遗漏 —— 因此有了 `skip` 列。 在端到端测试中,`tools/parity.sh ` 会使用两个 linter 对同一个 tree 进行 lint(两者都在 `--only` 下使用已实现的 cop 列表,RuboCop 会强制启用它们),并对标准化后的 offense 列表进行 diff。在所有四个语料库上实现了逐字节一致:**Rails(12,271 行 offense),Mastodon(4,123),rubygems.org(772),以及 RuboCop 自己的 1,712 个文件的源码 tree(0 对 0)**。CI 在每次推送时都会重新验证 oracle 是否达到 100% 以及一致性。 ## 用法 ``` oxidecop lib/ spec/ # lint trees in parallel (nearest .rubocop.yml per file) oxidecop file.rb my.yml # explicit config oxidecop -a . # autocorrect in place (like rubocop -a) oxidecop file.rb --fix # autocorrect a single file -> stdout oxidecop --only Style/SymbolProc --format json . ``` 输出模仿了 RuboCop 的 simple formatter(严重性字母,`[Correctable]` 标签,遵守每个 cop 的 `Severity` 配置);`--format json` 会输出兼容 RuboCop 的 JSON。当发现 offenses 时,退出代码为 1。 配置支持涵盖了实际项目会使用的常用功能:`.rubocop.yml` 发现(每个文件查找最近的配置),`inherit_from` 链,`inherit_gem`,`AllCops: DisabledByDefault / Exclude / Include`,每个 cop 的 `Enabled` / `Exclude` / `EnforcedStyle` / `AllowedMethods` / `AllowedPatterns`(包括 `!ruby/regexp`),magic-comment `rubocop:disable` 指令(带有 `-- reason` 尾部说明),以及 `TargetRubyVersion`。**所有 606 个 cops** 的参数默认值都是从 RuboCop 自己的 `config/default.yml` 生成到一个 schema 表中的,因此新移植的 cop 的默认值已经是正确的。 结果缓存(基于 stat 键入,content-hash 后备机制)使得未更改 tree 的重新运行速度提高了约 2 倍;`--cache false` 可以禁用它。 ## Repo 布局 ``` src/main.rs the runner: argv, file/config discovery, output, --fix loop src/config.rs .rubocop.yml subset + the generated per-cop SCHEMA src/declarative.rs the DECLARATIVE pattern-cop table (node-pattern rows) src/nodepattern.rs RuboCop's node-pattern DSL, parsed and matched over Prism src/cops/ the visitor + per-department cop logic src/cops/breakable.rs Layout/LineLength autocorrection (CheckLineBreakable port) oracle/ the spec-suite oracle + leaderboard (fidelity measurement) tools/parity.sh whole-tree byte-identical diff vs reference RuboCop bench/compare.sh the speed scoreboard vs competing linters ``` ## 如何添加 / 改进 cop 1. **找到 RuboCop 的真实模式。** 从 RuboCop 的源码中*逐字*复制 `def_node_matcher` 字符串和 `MSG` —— 不要改写。(主观猜测的模式通常会过于宽泛;oracle 每次都能捕捉到这一点。) 2. **表达它。** 一个 pattern cop -> `DECLARATIVE` 表中的一行。一个 logic cop -> 一个小型的 `Visit` 方法。如果 DSL 还不能表达该模式,请扩展 `src/nodepattern.rs`。 3. **衡量。** 将 cop 映射到 `oracle/leaderboard.rb` 中的 spec,运行它 —— 遗漏列表就是你精确的 TODO,一直到具体的失败示例。 4. **端到端验证。** 针对真实 tree 的 `tools/parity.sh` 必须保持逐字节一致。 ## Roadmap - **拓宽范围**:移植下一层级的 cops(schema 和 node-pattern DSL 已经覆盖了它们的配置面)。 - **分发**:预编译二进制文件,`brew install oxidecop`。 - **缩小热重跑差距**:缓存目录遍历,将无更改的重跑时间从 ~29 ms 缩短至接近 ~5 ms。 ## License MIT — 详见 [LICENSE](https://github.com/momiji-rs/oxidecop/blob/master/LICENSE)。 OxideCop 与 RuboCop 项目无隶属关系;RuboCop 是其作者和贡献者的作品,而这个项目的存在是为了忠实于它。
标签:Apache Flink, AST解析, Ruby, Rust, SOC Prime, 云安全监控, 代码规范检查, 可视化界面, 开发工具, 知识库, 网络流量审计, 通知系统, 静态分析