mcpField
A
add-lang

add-lang

github.com/colbymchenry开发75.8k1.2k 次安装今天更新
代码仓库

关于 add-lang

此技能用于为 CodeGraph 添加 tree-sitter 语言支持,涵盖语法检查、提取器接入、测试、仓库基准评测和文档更新。它会保留改动供审阅,不会提交或发布。

主要功能

  1. 01语法健康检查
  2. 02提取器接入与测试
  3. 03选择基准仓库集
  4. 04提取与 Agent A/B 评测
  5. 05更新文档并汇报改动

适用场景

  1. 01为 CodeGraph 添加语言支持
  2. 02通过基准评测验证已有支持
  3. 03衡量不同仓库中的检索效果

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/colbymchenry/codegraph --skill add-lang

安装后在 Claude Code 中输入/add-lang确认已加载。

详细介绍

为 CodeGraph 添加一种语言

将新的 tree-sitter 语言接入 codegraph 的提取流程,证明它能从热门代码库中提取真实符号,并证明它对 Agent 的效果优于不使用 codegraph。完全自主运行——选择代码库、进行基准测试、更新文档,然后汇报。绝不提交、推送、发布或打标签(内部规定);保留所有更改,供用户审阅。

参数是 Language 联合类型中通篇使用的语言令牌,例如 lua、elixir、zig。如果未提供,请询问要添加哪种语言。所有地方都使用小写的单个令牌(csharp,而不是 c#)。

前置条件

  • 从 codegraph 仓库根目录运行。需要 node、git、gh,以及已登录的 claude CLI(基准测试会启动真实的 claude -p 运行)。
  • 基准测试使用本地开发版本——第 8 步会构建它,并将其链接到 PATH 中。

工作流程

复制此检查清单,并按顺序完成:

- [ ] 1. Resolve language; bail early if already supported (just benchmark)
- [ ] 2. Find a grammar + health-check it (ABI / heap corruption)
- [ ] 3. Discover the grammar's AST node types (dump-ast.mjs)
- [ ] 4. Wire the language (4 files; sometimes a 5th core touch)
- [ ] 5. Build + verify-extraction loop until PASS
- [ ] 6. Add extraction tests; make them green
- [ ] 7. Auto-pick 3 popular repos by size tier; add to corpus.json
- [ ] 8. Benchmark all 3: extraction + with/without A/B
- [ ] 9. Update README + CHANGELOG
- [ ] 10. Report; do NOT commit
第 1 步 — 确认语言并提前结束

检查该语言是否已接入:在 LANGUAGES 常量(src/types.ts)和 EXTRACTORS 映射(src/extraction/languages/index.ts)中查找对应令牌。如果已受支持(例如 typescript、rust),跳过第 2–6 步,直接进行基准测试(第 7–8 步)以验证和衡量效果——在报告中注明代码未作更改。

第 2 步 — 查找语法,然后进行健康检查
ls node_modules/tree-sitter-wasms/out/ | grep -i <lang>   # csharp -> c_sharp
  • 存在 → 可能可直接使用;grammars.ts 会自动从 tree-sitter-wasms 中解析它。(许多语言都可用:elixir、zig、ocaml、solidity、toml、yaml 等。)
  • 不存在 → 将 .wasm 放入 src/extraction/wasm/(如 pascal / scala / lua),并在第 4 步中将令牌添加到 vendored 分支。

编写提取器前务必进行健康检查——语法文件存在也不代表可以使用:

node scripts/add-lang/check-grammar.mjs <lang> path/to/valid-sample.<ext>

此命令会打印语法的 ABI 版本,并按照索引时的方式运行它:在子进程中使用索引的 V8 标志,在 vendored 语法文件旁边运行,多次解析有效示例代码,并在 1 MiB 文件大小限制下再解析一次。如果检查失败(对有效代码生成 ERROR 树,或后续解析得到不同的树——旧 ABI 会破坏共享 WASM 堆,导致首个文件之后的所有文件都静默丢失嵌套调用和导入;例如,tree-sitter-wasms 的 Lua 语法 ABI 为 13,检查会失败——或者运行该语法的进程崩溃或挂起,即使每次解析都已完成),请勿使用该 wasm。请改用更新的(ABI 14/15)构建:

npm pack @tree-sitter-grammars/tree-sitter-<lang>   # often ships a prebuilt *.wasm
# or build one: npx tree-sitter build --wasm   (needs Docker/emscripten)
cp <the>.wasm src/extraction/wasm/tree-sitter-<lang>.wasm

然后在第 4 步中将令牌添加到 vendored 分支,并针对 vendored 路径重新运行 check-grammar,直到检查通过。如果无法获得健康的 wasm,请停止并告知用户。

第 3 步 — 探索 AST 节点类型

获取一个有代表性的源文件(编写一个涵盖函数、类/结构体、导入、枚举的小型示例;或使用 curl 从已知代码库获取原始文件),然后:

node scripts/add-lang/dump-ast.mjs <lang> path/to/sample.<ext>
# vendored grammar: pass the wasm path instead of the token
node scripts/add-lang/dump-ast.mjs src/extraction/wasm/tree-sitter-<lang>.wasm sample.<ext>

频率表和字段名(name:、parameters:、body:、return_type:)会告诉你该映射哪些内容。以最接近该语言范式的现有提取器为参考:rust.ts / scala.ts(函数式、特征),java.ts / csharp.ts(面向对象),python.ts / ruby.ts(脚本语言),go.ts(顶层方法 + 接收者)。

步骤 4 — 接入语言(4 个文件)

这些接线改动必须精确且谨慎——严格匹配现有风格:

  1. src/types.ts — 两处修改:
    • 将 '<lang>', 添加到 LANGUAGES 常量中(放在 'unknown' 之前);
    • 将 '**/*.<ext>', 添加到 DEFAULT_CONFIG.include。不要跳过这一步——这是文件扫描的允许列表;没有这个 glob,即使检测和提取都已接入,codegraph init 仍会找到 0 个文件。
  2. src/extraction/grammars.ts — 三个映射:
    • WASM_GRAMMAR_FILES:<lang>: 'tree-sitter-<lang>.wasm',
    • EXTENSION_MAP:每个文件扩展名 → '<lang>'(例如,'.lua': 'lua',)
    • getLanguageDisplayName:<lang>: '<Display Name>',
    • 仅 vendored:将 <lang> 添加到 (lang === 'pascal' || lang === 'scala' || …) wasm 路径分支中。
  3. src/extraction/languages/<lang>.ts — 新建文件,导出 export const <lang>Extractor: LanguageExtractor = { … }。将 Step 3 中的节点类型映射到相应字段。必填字段:functionTypes、classTypes、methodTypes、interfaceTypes、structTypes、enumTypes、typeAliasTypes、importTypes、callTypes、variableTypes、nameField、bodyField、paramsField。根据语法需要添加钩子(getSignature、getVisibility、isExported、extractImport、visitNode、getReceiverType、interfaceKind、enumMemberTypes 等——参见 src/extraction/tree-sitter-types.ts)。
  4. src/extraction/languages/index.ts — import { <lang>Extractor } from './<lang>';,并将 <lang>: <lang>Extractor, 添加到 EXTRACTORS。

有时还需要第 5 处核心修改,位于 src/extraction/tree-sitter.ts — extractVariable 中有按语言划分的变量提取分支(通用回退逻辑只查找直接的 identifier/variable_declarator 子节点)。如果语法会嵌套已声明的名称(例如,Lua 的 variable_declaration → variable_list),就在该处添加一个 } else if (this.language === '<lang>') 分支,参照现有的 ts/python/go 分支。不是独立节点的导入形式(Lua/Ruby 的 require 是一次 调用)则在提取器的 visitNode 钩子中处理。

步骤 5 — 构建与验证循环
npm run build            # tsc + copy-assets (copies any vendored *.wasm into dist/)

为一个小型示例仓库建立索引并检查提取结果:

( cd <sample-repo> && codegraph init -i )
node scripts/add-lang/verify-extraction.mjs <sample-repo> <lang>

如果未检测到该语言,或只生成了 file/import 节点,verify-extraction.mjs 就会失败(退出码为 1)——这是节点类型名称错误的典型表现。如果 FAIL 或 WARN 结果不理想:针对内容更丰富的文件重新运行 dump-ast.mjs,修正 <lang>.ts 中的映射,运行 npm run build,重新建立索引并再次验证。重复此过程,直到 PASS。

步骤 6 — 测试

在 __tests__/extraction.test.ts 中添加测试,参照 Rust Extraction 代码块:

  • 在 describe('Language Detection') 中添加一个 detectLanguage 断言
  • 添加一个 describe('<Lang> Extraction') 代码块,断言能从内联源字符串中提取函数、类和导入
npx vitest run __tests__/extraction.test.ts

通过后再继续。

步骤 7 — 自动挑选 3 个仓库并构建语料库

无需询问,直接挑选。寻找候选仓库,然后筛选出 3 个真正以 <lang> 为主的仓库,每个规模层级各 1 个:

gh search repos --language=<lang> --sort=stars --limit 40 \
  --json fullName,stargazerCount,description

层级(与 corpus.json 匹配):小型 <~150 个文件 · 中型 ~150–1500 个 · 大型 >~1500 个。跳过那些虽然标记为 <lang>、但实际主要使用其他语言的仓库。为每个仓库编写一个需要跨文件追踪才能回答的架构问题。向 .claude/skills/agent-eval/corpus.json 添加一个 "<Language>" 代码块(字段:name、repo、size、files、question),以便 /agent-eval 重用这些仓库。

步骤 8 — 对全部 3 个进行基准测试(提取 + A/B)

让 dev 构建版本仅将 codegraph 添加到 PATH 一次,然后循环执行:

npm run build && ./scripts/local-install.sh
scripts/add-lang/bench.sh <lang> <name> <url> "<question>" headless   # ×3

bench.sh 会克隆(共享 /tmp/codegraph-corpus)、清理并建立索引、运行 verify-extraction.mjs,然后通过 scripts/agent-eval/run-all.sh 执行带检索和不带检索的 A/B 测试(如果提取出错,则跳过付费 A/B 测试)。 读取 run-all.sh 打印的每个 parse-run.mjs 摘要:工具调用次数、文件 Read 次数、Grep/Bash 次数、codegraph-tool 调用次数、耗时和成本——包括 with 和 without 两组。循环结束后,如果需要,恢复 dev 链接: ./scripts/local-install.sh。

步骤 9 — 文档 + CHANGELOG
  • README.md:在 “19+ Languages” 功能条目中添加 <Lang>,并在 Supported Languages 表格中添加一行: | <Lang> | \.ext` | Full support (classes, methods, …) |`。
  • CHANGELOG.md:在顶部(最新版本上方)添加一个 ## [Unreleased] 部分,其中包含 ### Added → 一条面向用户的条目,例如: "CodeGraph 现在会为 (.ext) 建立索引,包括函数、类、导入项和 调用边。" 如果 ## [Unreleased] 已存在,则在其下追加。(发布时会将其并入下一个带版本号的区块。)
步骤 10 — 报告(不要提交)

总结以下内容以供审核:

  • 变更文件:4 处接线修改 + 新提取器 + 测试 + README + CHANGELOG + corpus.json(以及任何 vendored .wasm)。
  • 提取情况:逐个仓库列出文件数 / 节点数 / 边数 / verify-extraction 结果。
  • A/B 测试:逐个仓库对比 with 与 without(工具调用次数、文件 Read 次数、成本),并给出一句结论——codegraph 是否减少了工作量,且两组是否都得出了正确答案?
  • 缺口 / 后续工作(尚未映射的节点类型、缺失的解析边、框架路由等)。

将变更交给用户。不要运行 git commit/push 或发布——发布需通过 GitHub Actions Release 工作流进行。

说明

  • A/B 测试会启动真实的付费 claude -p 运行(opus,--max-budget-usd),共 2 组 × 3 个仓库。语料库目录 /tmp/codegraph-corpus 与 /agent-eval 共享,因此多个运行会复用克隆。
  • 任何新的 *.wasm 都必须放在 src/extraction/wasm/ 中——copy-assets(由 npm run build 运行)会将其打包;否则它不会进入 dist/。
  • 索引必须由同一个二进制文件提供服务。步骤 8 会先构建并链接 dev 构建版本,因此满足此要求。
  • 如果无法获取语法,或提取无法达到 PASS,请停止并报告——不要交付只接好一半的语言支持。

评论

支持 Markdown