我让 AI 帮我改一段代码,它把方法名写错了。不是一次,是反复。后来我发现问题不在 AI,在我。

最近几个月我一直在用 AI 写代码。Claude、OpenCode 之类的,轮着试。最开始写点 Python 脚本、Java方法,体验很好。再到后来我把一个整个工程丢给它——作为一个AI 的workspace,几十个模块,接口和实现类分布在不同的包里。
大多数时候,AI可以很快很准确定位和学习我要的代码,但是如果出现上下文过长,链路过深,而且方法签名大量重载且隐式链路过多的时候,AI就会开始胡说八道了:
由于历史版本的重构,服务层的命名已发生变更。但模型并未感知到这一演变,依然基于旧有的接口契约进行推导。这导致它在逻辑构想中自动补全了‘理想化’的方法,产生了与现实架构脱节的现象。
问题不在 AI 笨,在我没给它地图
而我打开 IntelliJ,点一下类名,所有实现类、方法签名、调用链清清楚楚。AI 没有 IDE。它只有文本。
这让我想起最早写代码的工程师,上古IDE没有那么多插件,生态也不完善。找一个方法实现全靠搜,找继承关系全靠脑记。后来我觉得 IDEA 是神器——类图一点就开,实现类 Ctrl+Alt+B 一键跳转。AI 现在就是那个用 vi 的程序员。

给 AI 装一个 IDE
能不能把 IDE 里那些结构化信息提前提取出来,存成 AI 可以直接查的格式?
方案不复杂。Tree-sitter 解析 Java 文件,提取 AST,把类、接口、方法、字段、注解、继承关系全部结构化成 SQLite 数据库。AI 不擅长在乱糟糟的文本里搜方法名,但它查 SQL 是一把好手。
我问 AI「这个 Controller 注入了哪些 Service」——传统做法是把整个 Controller 文件丢给它读,读完它还要去猜每个字段的类型是什么。现在一句 SQL 就够了:
SELECT name, data_type FROM symbols WHERE type='field' AND full_name LIKE '%.OrderController'
结果直接告诉你:字段名 `orderWriteService`,类型 `OrderWriteService`。清清楚楚。AI 不用猜了。
我还把方法调用也存了进去。AI 现在可以回答「这个方法调了哪些 API」——追查调用链不需要递归读方法体。还有个我特别喜欢的特性:增量同步。每次 AI 改完代码,重新跑一遍工具,只重新解析它改过的那几个文件,耗时不到一百毫秒。代码行号更新了,数据库也跟着更新,编辑错位的问题就没了。
我用 Bun 写的。Bun 内置 SQLite,一行代码搞定数据库初始化。Tree-sitter 的 WASM 版本可以直接在 Bun 里跑,不用编译 C 扩展。最后打成一个单文件二进制,不到 20MB。丢给 AI 就能用。


ChatGPT帮我绘制的设计流程图
怎么用?几句话的事
工具叫 JCodeTree。命令就几个,不怎么需要记。
jcodetree init my-project . | 初始化,给项目起个名字 |
jcodetree gen . | 扫描解析所有 Java 文件,生成AST |
jcodetree ls | 查询有哪些项目 |
codetree query my-project "SELECT * FROM relations" | 原生 SQL,灵活查询 |
第一次 `gen` 做全量解析,之后每次只重新解析改动过的文件,毫秒级完成。AI 改完代码跑一遍,行号永远不会错位。
数据库也是版本化的。每次 gen 自动递增版本号,`v1.db` `v2.db` 按快照保存。改出问题了?切回旧版本重新查就行。
写工具的人,最后修的都是自己
写完之后我发现一件事。这工具表面上是在帮 AI 看懂代码,但实际上,我做的事情是把一堆「我脑子里知道但从来没明确写下来」的东西给显式化了。
比如我看到 `private OrderService orderService;`,我脑子里知道这个类依赖了 OrderService。但我从来没想过这个「知道」本身是需要编码的。要为 AI 把这件事做好,我必须把自己对代码的理解整理成清晰的结构:文件 -> 符号 -> 类型 -> 关系。这个过程给我的收获比给 AI 的还大。
《禅与摩托车维修艺术》里有一句话我一直记得:「真正的维修工作,有一半发生在你坐下来思考的时候。」写这个工具的过程让我重新审视了自己的项目——那些被我忽略的架构细节、那些藏在角落里的循环依赖、那个被废弃但仍然存在的接口。之前用 IDE 看项目,就像在逛自己家——每个房间都熟悉,但从来没画过户型图。这次我把户型图画出来了。
工具叫 JCodeTree。代码准备开源在 GitHub 上。如果你也在用 AI 写 Java 代码,可以试试。用法很简单——先跑 `jcodetree gen .` 建索引,然后在提示词里告诉 AI 去查 SQLite 就行了。
效果?至少我的 AI 有了一个按图索骥的IDE。这对我来说就是胜利。
“
代码不会骗人,但人会。不只是别人,也包括过去的自己。工具的意义不是让你更快,是让你别再骗自己。
电脑关了,去泡了杯茶。想了想,下次也许该给这个工具加上 Python 和 Go 的支持。但那是下后面的事了。
夜雨聆风