M-simplifier/formsmith
GitHub: M-simplifier/formsmith
Clojure 原生的后格式化、后 lint 代码美化工具,填补格式化器和静态检查器之间的惯用法空白。
Stars: 0 | Forks: 0
# formsmith
`formsmith` 是针对已能运行、已格式化整洁但仍略显单薄的代码的一次 Clojure 原生美化处理。
格式化工具用于规范化代码形状。Bug 检查工具用于指出正确性问题。`formsmith` 则位于两者之后。它在 form 级别重写代码,然后对结果进行格式化,因此一次处理过程不仅能让代码更整洁,还能使其更具 Clojure 风格。
## 状态
处于预测试阶段,但已在真实仓库中发挥作用。
当前 `v1` 的范围被刻意缩小:
- 默认零配置
- 优先进行保守的自动修复
- 覆盖 CLJ、CLJS 以及初始的 ClojureDart 本地风格
- 在需要时提供同一 lint 层面的 `clj-kondo` 发现
当前的里程碑问题是:
这意味着项目目前的姿态是:
- 优先考虑仓库的预测试阶段
- 版本化的 GitHub 源码发布
- 用于可合并工作的短生命周期分支与 PR
- `bb ci` 作为默认的代码变更关卡
- 当重写行为或公开声明发生变动时使用 `bb benchmark-v1`
- 当需要判断公开楔入声明是否确凿时使用 `bb validate-v1`
- 当仅限仓库的首次运行路径或新手引导文档发生变动时使用 `bb validate-cold-start`
- 在楔入声明得到证实前提供尽力而为的支持
请参阅[贡献指南](./CONTRIBUTING.md)。
当前源码发布版本:`v0.1.0-pre.7`,位于
`decbd33310ada782d9097c195284a1ad9dcd4e39`。
如果您正在通过 AI 编程代理操作该仓库,请将 [AGENTS.md](./AGENTS.md) 作为公开的 AI 操作指南,用于冷启动会话和数据包选择。
## 为什么在有了 `clj-kondo` 和格式化工具后还要使用它?
因为在常规工具链处理之后,仍然存在一段空白。
这段空白表现为:
- 能够工作但弱于惯用写法的 `if` / `when` / `cond` forms
- 想要使用 `not-empty`、`if-let` 或 `when-let`,却使用了基于 `seq` 的空值检查
- 想要使用 `blank?`,却使用了空白检查
- 诸如嵌套 `let`、冗余的 `do`、冗余的 `str` 或 `when (not ...)` 的局部包装
`formsmith` 并不想取代所有的格式化工具或代码检查工具。它只想解决这最后一公里的问题。
## 快速开始
要求:
- JDK
- Clojure CLI
维护者检查也会使用 Babashka。证明验证使用 Lean,或通过 Nix 来
运行 Lean,经由 `scripts/verify-proofs.sh` 实现。
从仓库运行:
```
clojure -M -m formsmith.main lint src test
clojure -M -m formsmith.main check .
clojure -M -m formsmith.main fix --check .
clojure -M -m formsmith.main fix --check --guarded .
clojure -M -m formsmith.main fix .
clojure -M -m formsmith.main fix --aggressive .
clojure -M -m formsmith.main baseline src test -o .formsmith-baseline.edn
clojure -M -m formsmith.main profiles src test
clojure -M -m formsmith.main contracts src test
```
对于其他仓库,请添加一个消费 GitHub 源码发布的 `:formsmith` 别名。
请参阅[安装说明](./docs/install.md)和 [CI](./docs/ci.md)。
如果您只想要 `formsmith` 的发现而不合并 `clj-kondo` 的输出:
```
clojure -M -m formsmith.main lint --no-kondo src test
```
如果您想要一个不包含任何同级基准仓库的、仅限本仓库的首次运行:
```
bash scripts/cold-start-demo.sh prepare
bash scripts/cold-start-demo.sh lint
bash scripts/cold-start-demo.sh preview
```
维护者可以从一个全新的临时工作区副本验证该仅限仓库的路径,使用:
```
bb validate-cold-start
```
感知框架的输出包括信息性配置文件、仅供报告的 LLM 契约,以及带有显式防护的狭窄局部重写。当前配置文件覆盖范围包括 re-frame、Reagent、HSX、RFX、ClojureDart、Ring、Reitit、Integrant 和 Malli。ClojureDart 支持包括 `.cljd` 文件、Flutter 字符串包依赖,以及从嵌套的 `.child` 链到 `cljd.flutter/nest` 的首个可见 Flutter UI 重写。
请参阅[框架配置文件](./docs/framework-profiles.md)。
## 推荐工作流
1. 运行 `lint` 以查看全貌。
2. 运行 `check` 以预览 CI 可以强制执行的规范安全重写。
3. 当安全预览看起来不错时,运行 `fix`。
4. 当您想要由静态事实证明的、带有局部符号防护的分析器支持重写时,运行 `fix --guarded --check`。
5. 在整个仓库应用更广泛的语义模式重写之前,运行 `fix --aggressive --check`。
6. 当将 `formsmith` 引入现有仓库,且希望 CI 仅对新的发现报错时,使用 `baseline`。
7. 当您需要目录和安全边界时,使用 `rules` 和 `explain `。
## 生产采用面
`formsmith` 在默认情况下会读取 `.formsmith.edn`(如果存在)。当前
最小的生产配置面是有意保持微小的:
```
{:ignore-paths ["target" "resources/generated"]
:rules {:exclude [:some/rule]}
:baseline ".formsmith-baseline.edn"
:suppressions [{:file "src/app/core.clj"
:rule-id :if/not-condition
:line 42}]}
```
在极少数局部惯用法是有意为之的情况下,支持内联抑制:
```
;; formsmith-disable-next-line if/not-condition
(if (not ready?) :wait :go)
```
默认的 JSON 输出省略了完整的文件源码和前后对比片段,因此 CI 产物对于私有仓库来说更加安全。仅在本地调试时使用 `--include-source`。
## 安全模型
- `syntax-safe`
`formsmith` 愿意在默认的 `fix` 中自动应用的局部重写。
- `semantic-pattern`
需要 `--aggressive` 才能自动修复的强烈建议。
- `unsafe`
仅报告。这是有用的信号,但不应由工具默认重写。
两个重要命令:
- `fix --check`
无写入预览。仅报告实际会应用的发现。
- `check`
用于 CI 的规范无写入检查。等同于默认的安全自动修复配置文件,但不执行写入。
- `fix --guarded`
仅在静态事实证明了当前支持的防护条件时,才应用由分析器防护的重写。
- `fix --rewrite-only`
跳过格式化阶段。当您想要直接检查重写局部性时非常有用。
## 基准快照
截至 `2026-05-08`,`main` 分支上的当前快照:
- 对 `nextmoon/src` 进行纯 `formsmith` lint:`files=18 changed=0 findings=12`
- 对 `dirty-clojure/src test` 进行纯 `formsmith` lint:`files=9 changed=0 findings=9`
- 对 `nextmoon/src` 的安全预览:`fix --check --rewrite-only` => `files=18 changed=1 findings=1`
- 对 `dirty-clojure/src test` 的安全预览:`fix --check --rewrite-only` => `files=9 changed=2 findings=4`
- 仅限 CLJS 的激进预览:
- `dirty-clojure/frontend/core.cljs` => `files=1 changed=1 findings=7`
- `nextmoon/ui/core.cljs` => `files=1 changed=1 findings=1`
这些数字非常重要,因为这两个基准仓库现在都在 `formsmith` 添加额外信号之前通过了其基线测试、lint 和格式检查。
当前维护者的基准数据包更具说服力:
- `dirty-clojure` 是一个干净的维护者基准仓库,包含重复的 CLJ 和 CLJS 发现
- `nextmoon` 现在也是一个干净的维护者基准仓库,同时仍作为更强的真实仓库压力面
这意味着 `formsmith` 拥有两个由维护者控制的基准仓库,它们表明
在常规工具处理之后,仍然存在有意义的局部改进空间。自包含的
公开首次运行证据路径是 `bb validate-cold-start`;
更广泛的公开外部压力证据记录在
[实地试验](./docs/field-trials.md)中。
使用以下命令刷新当前矩阵:
```
bb benchmark-v1
```
使用以下命令验证实际的楔入证据:
```
bb validate-v1
```
这两个证据数据包是维护者命令,并预期存在用于 `nextmoon` 和 `dirty-clojure` 的同级基准检入。全新的公开克隆可以通过 `bb validate-cold-start` 验证捆绑的首次运行路径。
## 命令
```
clojure -M -m formsmith.main lint
clojure -M -m formsmith.main check
clojure -M -m formsmith.main fix
clojure -M -m formsmith.main fmt
clojure -M -m formsmith.main analyze
clojure -M -m formsmith.main profiles
clojure -M -m formsmith.main contracts
clojure -M -m formsmith.main rules
clojure -M -m formsmith.main explain
```
示例:
```
clojure -M -m formsmith.main fix --check --rewrite-only src test
clojure -M -m formsmith.main check src test
clojure -M -m formsmith.main fix --check --guarded src test
clojure -M -m formsmith.main fix --aggressive src test
clojure -M -m formsmith.main explain condition/and-seq
clojure -M -m formsmith.main analyze src test
clojure -M -m formsmith.main profiles src test
clojure -M -m formsmith.main contracts src test
clojure -M -m formsmith.main baseline src test -o .formsmith-baseline.edn
```
## 当前规则面
当前的规则族包括:
- 冗余包装器:`redundant-do`、嵌套 `let`、冗余 `str`
- 条件清理:`when-not`、`if-not`、`cond -> if/when`、`cond true -> :else`
- nil 谓词:`= nil` -> `nil?`、`not= nil` -> `some?`
- 关键字查找:`(get m :k)` -> `(:k m)`
- 空值与空白:`seq`、`not-empty`、`blank?`
- 围绕前端表单和集合检查的面向 CLJS 的局部模式
请查看实时的目录:
```
clojure -M -m formsmith.main rules
clojure -M -m formsmith.main explain cond/minimal-form
```
## 项目边界
`v1` 有意避免成为:
- 格式化工具之争
- 通用 Bug 检查工具
- 仓库架构分析器
- 高度依赖配置的风格语言
当前的楔入更简单:
这正是 `formsmith v1` 试图证明的。
## 文档
- [愿景](./docs/vision.md)
- [架构](./docs/architecture.md)
- [AI 操作指南](./AGENTS.md)
- [安装说明](./docs/install.md)
- [CI](./docs/ci.md)
- [采用试验](./docs/adoption-trial.md)
- [发布说明](./docs/releases/v0.1.0-pre.7.md)
- [证明](./docs/proofs.md)
- [v1 验证](./docs/v1-validation.md)
- [快速开始](./docs/quickstart.md)
- [冷启动演示](./docs/cold-start-demo.md)
- [冷启动采用](./docs/cold-start-adoption.md)
- [基准测试](./docs/benchmarking.md)
- [语料库](./docs/corpus.md)
- [压力项目](./docs/pressure-projects.md)
- [实地试验](./docs/field-trials.md)
- [审查消除研究](./docs/review-elimination-study.md)
- [审查研究记录](./docs/review-studies/README.md)
- [L5 记分卡](./docs/l5-scorecard.md)
标签:AI辅助编程, AST重写, CLJ, clj-kondo, CLJS, Clojure, ClojureDart, DevOps工具, Lisp, 云安全监控, 代码可读性, 代码审查, 代码格式化, 代码规范, 代码重构, 代码静态检查, 函数式编程, 威胁情报, 开发者工具, 操作系统探测, 自动化重构, 静态分析