aalpar/wile-goast
GitHub: aalpar/wile-goast
wile-goast 是一个通过暴露 Go 编译器内部机制并以 Scheme 驱动静态分析,解决代码库中结构重复与一致性问题的 MCP 服务器。
Stars: 5 | Forks: 0
# wile-goast
你有一个大型的 Go 代码库。几十个包中的数百个函数。
你怀疑存在重复的函数、不一致的约定,以及与实际代码运行方式不匹配的结构体边界。grep 只能找到字符串匹配。gopls 可以找到引用。golangci-lint 可以发现已知的反模式。但它们无法回答:
- 这两个函数除了类型不同,结构上是否完全相同?
- `Step` 的每个调用者都处理了返回的错误吗?
- 每个获取锁的函数是否在所有路径上都释放了锁?
- 哪些结构体边界与实际字段访问模式相矛盾?
- 这 30 个方法是否遵循相同的调用约定?哪些偏离了?
wile-goast 是一个 MCP 服务器,它将 Go 编译器的内部机制——AST、SSA、控制流图、调用图和 lint 分析——作为分析原语暴露出来。你的 AI 助手编写查询。你描述你要寻找的内容。
## 安装
安装二进制文件:
```
go install github.com/aalpar/wile-goast/cmd/wile-goast@latest
```
将其添加到你的 MCP 客户端配置中:
```
{
"mcpServers": {
"wile-goast": {
"command": "wile-goast",
"args": ["--mcp"]
}
}
}
```
该二进制文件是自包含的。所有分析库都已嵌入——运行时无需外部依赖。
## 重构会话
你正在清理一个 Go 服务。以下是一个会话的示例。
### 查找重复函数
你提问:*“扫描我的 service/... 目录,查找重复或近似重复的函数。”*
助手使用 `goast-refactor` 提示来驱动分析。背后,它会解析每个函数,按签名形状分组,并对每对函数运行结构差异分析。替换折叠会分离出真正的差异与类型传播噪声——如果 `FooStore` 和 `BarStore` 的方法体除了类型名称外完全一致,工具会将其识别为单个类型参数,而不是几十个分散的差异。
输出是一个评分列表:
```
store.CreateFoo <-> store.CreateBar
similarity: 0.94
type params: 1
?T0: FooRecord -> BarRecord
literals: 0
operators: 0
cosmetic: 12
structural: 0
```
94% 相似,仅一个类型参数,零结构差异。这是一个统一候选——提取为泛型函数并删除重复项。
相似度为 0.65 且存在两个结构差异和一个字面量差异的组合?这是压缩,而非简化。工具会标记这些差异,让你决定如何处理。
### 检查约定违规
你提问:*“raft.Step 的所有调用者都处理了返回的错误吗?”*
助手定义一个信念——一种统计一致性检查——并在你的包上运行它:
```
step-error-handling
sites: callers-of "Step"
adherence: 87% (13/15)
deviations:
processMessage (file.go:142) — missing error handling
handleRaftReady (file.go:308) — missing error handling
```
87% 的调用者处理了错误。有两个没有。这些就是需要调查的地方。
信念之所以有效,是因为约定是统计性的。你不会写一条规则说“每个调用者必须做 X”,而是写“找到调用者,检查这个属性,并报告少数例外”。代码库定义了约定,工具负责发现违反者。
同一机制也适用于锁/解锁配对、有序操作、字段协同修改、空指针解引用前的检查——任何大多数代码遵循但部分代码违反的属性。
### 检查锁纪律
你提问:*“Lock 是否总是与 Unlock 配对?检查所有路径,包括 defer。”*
两个信念,串联执行:
```
lock-unlock-pairing
sites: functions calling Lock
adherence: 91% (42/46)
deviations:
acquireLease (lease.go:87) — unpaired
startElection (raft.go:203) — unpaired
...
```
偏差表现为调用了 `Lock` 但未调用 `Unlock` 的函数。但也许它们的调用者处理了。第二个信念在第一条基础上延伸——它检查偏差函数的上层调用栈:
```
lock-unlock-callers
sites: deviations from lock-unlock-pairing
adherence: 75% (3/4)
deviations:
handleTimeout (server.go:445) — caller also missing Unlock
```
四个偏差中有三个被它们的调用者处理了。有一个没有。这就是你的 Bug。
### 查找错误的 struct 边界
你提问:*“哪些结构体边界与实际字段访问模式不一致?”*
助手从 SSA 字段存储数据构建一个概念格——哪些函数写入哪些类型的哪些字段。自然分组从数据中涌现。当一个分组跨越多个结构体类型时,意味着函数将不同类型的字段视为一个整体。这些就是错误的边界候选。
```
Cross-boundary concept:
types: MachineContext, vmState
fields: pc, sp, callStack, continuation
functions (7): step, resume, pushFrame, popFrame, ...
These 7 functions access fields from both types together.
Consider: colocate fields, extract shared type, or confirm
the coupling is intentional.
```
这是形式概念分析(Ganter & Wille, 1999)——不是启发式方法。概念格是描述所有合法字段分组的数学结构。跨边界概念是数据支持但类型系统未反映的分组。
### 验证重构结果
你已经合并了重复函数,修复了锁错误,重构了类型。现在验证:
*“再次运行相同的信念。同时在变更的包上运行 nilness、unusedresult 和 shadow 分析。”*
信念确认约定仍然成立——或捕捉到你重构引入的新偏差。Lint 检查捕获机械性问题。调用图确认旧函数的所有调用者现在都引用了统一后的替换函数。
## 我还可以问什么
MCP 服务器包含三个引导提示,用于结构化分析:
| 提示 | 用途 |
|------|------|
| `goast-analyze` | 查询代码结构:AST 形状、数据流、控制流、调用关系 |
| `goast-beliefs` | 定义并运行跨包的 consistency 检查 |
| `goast-refactor` | 查找统一候选并验证重构的正确性 |
除了上述流程,分析层级还支持:
- **调用图查询**——谁调用了这个函数?从 main 出发能到达哪里?
支持静态、CHA 和 RTA 算法。
- **控制流**——语句 A 是否支配语句 B?枚举两个块之间的所有路径。构建支配树。
- **SSA 数据流**——到达定义、活跃变量分析、常量传播、符号分析、区间分析。
基于工作列表的前向/后向分析。
- **代数等价性**——两个 SSA 表达式在交换律、恒等律和零元规则下是否等价?
- **布尔简化**——将复杂的 Go 条件归一化以检测等价或冗余逻辑。
- **路径代数**——基于耦合距离、错误传播深度等的调用图上的半环最短路算法。
- **40+ lint 分析器**——完整的 `go/analysis` 套件,可通过名称调用。
## 作为 Go 库
如果你想在自己的工具中嵌入这些分析:
```
engine, err := wile.NewEngine(ctx,
wile.WithSafeExtensions(),
wile.WithExtension(goast.Extension),
wile.WithExtension(goastssa.Extension),
wile.WithExtension(goastcfg.Extension),
wile.WithExtension(goastcg.Extension),
wile.WithExtension(goastlint.Extension),
)
defer engine.Close()
val, err := engine.Eval(ctx, `(go-parse-expr "1 + 2")`)
```
## 构建与测试
```
make build # Build to ./dist/{os}/{arch}/wile-goast
make test # Run all tests
make lint # Run golangci-lint
make ci # Full CI: lint + build + test + covercheck + verify-mod
```
## 文档
| 文档 | 内容 |
|------|------|
| [docs/PRIMITIVES.md](docs/PRIMITIVES.md) | 所有分析原语的完整参考 |
| [docs/AST-NODES.md](docs/AST-NODES.md) | 50+ 种 Go AST 节点字段参考 |
| [docs/EXAMPLES.md](docs/EXAMPLES.md) | 示例脚本的带注释逐步讲解 |
| [docs/GO-STATIC-ANALYSIS.md](docs/GO-STATIC-ANALYSIS.md) | 跨层使用指南 |
## 依赖
| 依赖 | 用途 |
|------|------|
| [github.com/aalpar/wile](https://github.com/aalpar/wile) | R7RS Scheme 解释器与扩展 API |
| golang.org/x/tools | SSA、调用图、CFG、go/analysis 框架 |
| mark3labs/mcp-go | MCP 服务器(基于 stdio 的 JSON-RPC) |
基于 [Wile](https://github.com/aalpar/wile) 构建——一个 R7RS Scheme 解释器。
Go 的 AST 本身就是一棵树——S 表达式是其自然表示。
AI 能熟练编写 Scheme;你不需要会。
标签:EVTX分析, golangci-lint, gopls, Go源码分析, Go语言, grep增强, MCP服务器, Scheme脚本, SSA, 云安全监控, 代码审查, 代码搜索, 代码重复检测, 函数结构比较, 技术债务, 控制流图, 日志审计, 模式匹配, 程序破解, 类型参数化, 结构体边界分析, 编译器内部, 自动化资产收集, 调用图, 调用约定一致性, 跨层分析, 重构辅助, 锁获取与释放, 错误处理检查, 静态分析