尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

CodeGraph Rust 内核移植实战:Lua 与 Luau 的 bug-for-bug 等价迁移全解

CodeGraph Rust 内核移植实战:Lua 与 Luau 的 bug-for-bug 等价迁移全解 CodeGraph Rust 内核移植实战Lua 与 Luau 的 bug-for-bug 等价迁移全解【免费下载链接】codegraphPre-indexed code knowledge graph, auto syncs on code changes, for Claude Code, Codex, Gemini, Cursor, OpenCode, AntiGravity, Kiro, CoPilot, and Hermes Agent — fewer tokens, fewer tool calls, 100% local项目地址: https://gitcode.com/GitHub_Trending/co0degr/codegraphCodeGraph 的 Rust 提取内核要把 TS 侧基于 WebAssembly 的 tree-sitter 提取器逐语言移植成原生 Rust walkerdocs/design/lua-luau-kernel-port-checklist.md是其中 Lua LuauR7b batch 4合并移植的bug-for-bug 清单它记录了每个 TS 分支会命中什么、哪些怪癖必须原样保留、哪些机制必须保持静默以及如何用语法版本校验与全仓扫描验证两臂输出的字节级一致。读完本文你将理解一个提取器移植清单从语法准备、钩子语义、死机制识别到等价性门禁的完整方法论并能在当前仓库中看到这份清单已被落地的对应实现。为什么 Lua 和 Luau 可以合并成一份清单Lua 和 LuauRoblox 的渐进式类型化超集的 TS 侧提取器本身就是共享关系src/extraction/languages/luau.ts只有 36 行通过{ ...luaExtractor, 4 个覆盖项 }扩展src/extraction/languages/lua.ts两种语法的节点名词汇表一致function_declaration、variable_declaration、function_call、dot_index_expression/method_index_expression等。因此移植结论是内核侧只写一个 walker 模块codegraph-kernel/src/lua.rs用 ccpp 先例的语言参数化方式分发lua | luau lua::extract(file_path, content, language)方言差异被压缩到恰好四项差异项lualuautypeAliasTypes[][type_definition]isExported无钩子wire 上 absent对节点自身前 7 字符做 UTF-16 切片判断是否以export开头getSignatureparameters字段文本参数文本 : parameters 之后的命名子节点若该子节点是block则不加语法句柄内联编译的 v0.4.1 语法cratetree-sitter-luau 1.2.0其余全部——require 钩子、receiver 方法、变量分支、调用形状、docstring、function-ref 捕获——两方言字节共享。当前仓库中 codegraph-kernel/src/lua.rs 的模块头注释明确写道One walker, two dialects (ccpp precedent): the differences are exactly four并用is_luau: bool字段驱动这四处分支langs.rs 的LANGUAGES数组已包含lua, luau现为 20 种语言。文档同时选定go.rs作为最近的参照模板receiver-QN 方法、extract_type_alias → bool、node_idsvec、按node_ids[from]去重的 fn-ref flush。清单中所有语法形状论断都用生产环境 vendored wasm 做了 CST dump 与childForFieldName真值表探测所有提取行为论断都对照真实dist/提取器的 ground-truth dump 固定下来——不是靠读代码推断。这是这份清单可信度的来源也是移植工作的第一原则先钉住现有行为再谈重写。语法准备内联编译 C 与 crate 钉版两条路线两个语言的 wasm 早已在VENDORED_WASM_LANGS中grammars.ts 第 291 行附近文件映射lua: tree-sitter-lua.wasm/luau: tree-sitter-luau.wasm且 vendored 版本恰好就是移植目标修订版因此本次移植完全不需要动 wasm 侧也没有传统的 bump 门禁。但内核是原生 Rust语法来源要分两条路线lua — vendored-grammar-C 路线沿用 kotlin 机制。探测确认 vendored wasm 与tree-sitter-lua v0.4.1tag 表格逐位一致ABI 15STATE_COUNT 262SYMBOL_COUNT 137FIELD_COUNT 22而v0.4.1 不在 crates.io 上只有 0.1/0.2/0.5所以必须把 tag 中 CHECK-IN 的生成产物parser.c、scanner.c 及 tree_sitter 头文件文档逐一列出了各文件 sha放进codegraph-kernel/grammars/lua/由 build.rs 用cc::Build编译——includegrammars/lua、编译 parser.c 与 scanner.c、参考 tag 自带 build.rs 的 flags.std(c11)、msvc-utf-8、cargo:rerun-if-changedgrammars/lua。当前仓库 codegraph-kernel/build.rs 第 32-41 行正是这个块codegraph-kernel/grammars/lua 目录已存在。langs.rs 侧则声明extern C { fn tree_sitter_lua() - *const (); }并用LanguageFn::from_raw包装见 langs.rs 第 21-25 与 80-82 行。注意 lua 有外部 scanner注释与长字符串vendor 时必须带上 scanner.c。luau — 普通 crate 钉版csharp 风格。vendored wasm 与tree-sitter-luau v1.2.0≡ crates.io 1.2.0 三方一致且 swift 移植中tag≠crate的教训在这里被复查并排除tag 与 crate tarball 的 parser.c8f25bc17…与 scanner.ca157bb52…sha 逐位相同ABI 14STATE_COUNT 585SYMBOL_COUNT 197FIELD_COUNT 21。因此 Cargo.toml 中直接写tree-sitter-luau 1.2.0crate 依赖只有tree-sitter-language 0.1cc构建依赖、tree-sitter仅 dev-dep0.26.3与内核的 tree-sitter 0.25 无版本冲突。语法等价门禁取代 bump 门禁。由于 wasm 侧零改动不存在新旧对比 dump改由tests/kernel-grammar-parity.test.ts 的GRAMMAR_LANGUAGES数组追加lua, luau当前第 39 行已包含两者来断言C 编译/ crate 版本与 vendored wasm 是同一修订版逐 id 对比 kindfield 表、lua 走 ABI 15 / luau 走 ABI 14。错误发生率lua 近乎为零luau 是语法的固有形状清单对七个真实仓库做了全文件错误扫描error-sweep.cjs文件均 ≤1MiB这张表决定了移植后的预期延迟deferral行为仓库语言文件数hasError首个错误类别Kong/konglua1,30910.08%spec/fixtures/invalid-module.lua— 故意写坏folke/lazy.nvimlua650—openresty/lua-resty-corelua380—lune-org/luneluau22131.36%.d.luau类型包/typeof 声明dphfox/Fusionluau11387.08%泛型类型包(A...) - T默认类型参数type ScopeC Fusionluau-lang/luau tests/luau2033919.21%仅压测 — 故意测试未来语法JohnnyMorganz/StyLua tests/lua41911828.16%仅压测 — cfxlua 方言、C 注释关键结论有三全部 2,368 个文件中零 phantom-hasError有 hasError 但没有 ERROR 节点的文件所以与 kotlin 不同lua/luau 的延迟信号永远伴随真实 ERROR 节点出现但策略上仍只看has_error()标志不去扫 ERROR 节点。lua 侧任何一次延迟都是 walker 自身的 bug 信号ruby 式预期0-1 次延迟出现即可疑luau 的 1.4–7.1% 是两臂共有同一语法修订版两边行为一致由两种语法固有形状驱动——泛型类型包(A...) - T与默认类型参数T D——扫描阈值定为--max-deferral 0.1scripts/kernel-parity.mjs 第 38 行默认值luau 超过 ~10% 才是 bug 信号。方言交叉污染也会被延迟luau 拒绝native/checked1.2.0 语法早于 2024 语法与 lua-only 语法goto、位运算lua 拒绝 luau 特性type X …、continue、、反引号插值。所有错误文件整体让给 wasm 臂wasm 错误时也会做 best-effort 部分提取两臂表格相同因此行为一致。require 钩子最大的 bug-for-bug 风险面Lua 没有 import 语句模块加载靠调用全局require这被实现为一个visitNode钩子lua.ts 第 105-151 行 requireModule第 28-60 行。清单把这套机制列为单个最大的 bug-for-bug 面因为它包含多处刻意的不对称requireModule(callNode)的判定顺序必须逐字移植name:字段子节点必须是identifier且文本恰为require点号/冒号调用者是 dot/method_index 节点天然不匹配arguments:字段必须存在。字符串优先、广度优先findDescendant(args, string_content)BFS 遍历 namedChildrenlua.ts 第 9-17 行取 trim 后文本。这抓住require(a.b)、单引号、[[...]]长字符串string_content 位于 string 节点内部也抓住任何参数里随便哪里有字符串的 require——被固定pinned的怪行为require(script:WaitForChild(Kid))→ importKid字符串赢过方法索引路径require(a .. b)→ importaBFS 序第一个 string_content——确定性的垃圾照原样保留。兜底findDescendant(args, string)加手工剥[[ ]]/引号只在 string 节点无 content 子节点时到达require()→ mod 为假值 → null。Roblox 实例路径第一个dot_index_expression否则method_index_expression后代的field:或method:子节点文本——require(script.Parent.Signal)→Signal末段。其余情况返回 nullrequire(dynName)、require()。钩子分发lua.ts 第 129-150 行的不对称语义节点为function_call是 require →emit(node)返回 true被认领绝不会被二次计为 call不是 → 返回 false → 落到 extractCall 发出calls require边pinned顶层require(dynamicTop)→ FILE 节点发 calls require。节点为variable_declaration找assignment_statement子 → 其expression_list→ 对每个function_call子emit(val)多 requirelocal a, b require(x), require(y)→ 两个 import——pinned总是返回 false→ extractVariable 照常执行。从此处不发的更深层嵌套的 require{ mod require(t) }表值——pinned 无 import、require(m).fieldexprList 子节点是 dot_index——pinned 无 import但accessed变量照常铸出。emit在调用节点位置创建 import 节点ctx.createNode(import, mod, callNode, { signature: 调用文本 trim 后截 100 字符 })qualifiedName 模块字符串若栈非空则addUnresolvedReferencefromNodeId 栈顶恒为 FILE 节点referenceKind importsline 调用 startRow1不带 filePath——真实 dump 中零条 ref 携带过 filePath所以 wire v2 的 REF_FLAG_FILE_PATH 不需要。最关键的一条钩子从不在函数体内运行visitFunctionBody 没有钩子调用。于是顶层local lazy require(app.lazy)包括顶层if/for/while块内——pinnedextract-condreqif ok then local m require(in.if) end→ import in.if variable m都归属于 FILE产出 import 节点而函数体内同一条语句产出calls require引用且无 importpinnedextract-bodies-lua.txtL8-9——neovim lazy-loading 惯用法就落在这一侧。把这几条任何一条移植错扫描第一天就会亮灯。变量节点位置在标识符上初始值子树永不遍历variable_declaration分支tree-sitter.ts 提取器 lua 分支的行为同样被逐字节固定kind 恒为variable无isConst钩子constant永不出现docstring 取自声明节点isExported 钩子 ?? false→ 两语言都是 falseluau 的切片看到的是local …。解析assign 第一个assignment_statement命名子节点 ?? 节点本身覆盖无的裸local xvarList assign 的variable_list子exprList assign 的expression_list子names varList 中仅identifier子attribute节点const/close被跳过且不打乱位置values exprList 的命名子节点。每个 name位置配对创建节点位置在标识符上pinnedvariable http L2 C6-10signature ${valueText 截 100}${≥100 时加 ...}该索引无值 → 连 signature 键都不存在pinnedlocal ok, err pcall(...)→ok有 signatureerr没有。签名保留原始字节内嵌\n [[long\nstring]]、CRLF\r\n、完整匿名函数文本。docstring 与 isExported 复制到声明的每个name 上。分支随后scanFnRefSubtree(node, 0) skipChildren →初始值子树永不被遍历local fromCall topFn(3, 4)不发出任何 calls 引用local anon function(v) return hidden(v) end不铸函数节点、不发 callspinned。与之对比会遍历的形状顶层x topFn(10)赋值无分支 → 递归→ 发 calls topFnM.assigned function(z) return topFn(z) end→ calls topFn归属于 FILE 节点pinned L68。函数体内则两种声明形式都遍历局部变量不铸节点——反转只发生在顶层顶层 local 声明的调用不可见、顶层全局赋值可见体内则相反。同 id 重复行是合法输出local x 1; local x 2一行内 → 两行同 id 的variable:xpinnedsameLineTwoLocals。压缩成单行的 lua 包会经常撞上walker 按node_idsvec 模式原样发两行store upsert 负责折叠——parity 比较的是入 store 前的输出。调用提取原始文本调用者世界与换行粘连陷阱extractCall 的 lua 路径有一个结构性事实function字段在本语法中为 NULL真值表固定所以调用者恒取namedChild(0)即name:子identifier / dot_index / method_index / parenthesized / 链式中的 function_call。成员分支:4364永不触发——dot_index_expression/method_index_expression不在其接受的类型列表里LITERAL_RECEIVER_TYPES、SKIP_RECEIVERS与所有 re-encode 都不可达。一切落入 ELSE 分支calleeName 调用者节点的原始源码文本UTF-16 子串。被 pinned 的形状裸topFn(5)→topFn糖调用require x/f {t}无括号参数同一路由点号M.create(2)→M.create深层core.util.log(x)→core.util.log冒号方法保留冒号M:render({})→M:renderM.sub.deep:chained(13)→M.sub.deep:chained体内self:helperMethod(o)→self:helperMethod、self.field.deep(1)→self.field.deep——self永不被剥掉此路径无 SKIP_RECEIVERS。解析层依赖这些精确字节见解析侧消费者一节括号调用原样保留M.registrykey→M.registry[key]t2k2→t2[k2]括号逐字调用结果作调用者f2()(15)→ 外层引用f2() 内层引用f2无 skipChildren子节点递归链上每一环都发引用换行粘连陷阱lua 语句歧义的固有产物调用语句后紧跟以(开头的行被解析为一条粘连链——obj:foo():bar()\n\t(helper)(4)发出四条引用obj:foo():bar()\n\t(helper)原始文本含内嵌换行/制表符字节逐字、obj:foo():bar()、obj:foo():bar、obj:foopinnedextract-bodies-lua.txtL19string.format(%d, 9)\n(literal):upper()同理三条。必须逐字节复现包括调用者是整条内层 function_call 文本的粘连中间环括号转换正则:4529-4532/^\(\s*\*?\s*([A-Za-z_][\w.]*)\s*\)$/命中时把(handler)(16)分号分隔或体内首句、未粘连的调用者文本(handler)改写为handler两次 pinned粘连/带引号的括号调用者(x):upper不命中保持原文。移植时正则要用 JS\s语义会匹配\r。Luau 额外形状全部 pinned插值调用在体内发出point {p.x} of {Config.total()}→ callsConfig.total位置在内层调用处if 表达式两臂if p.x 0 then bump() else drop()两臂都发v grow()→ calls growupdate_statement 被递归且无 fn-ref 捕获——分发里根本没有 update_statement 键。引用行统一为fromNodeId 栈顶、referenceKind calls、line 调用 startRow1、column UTF-16 startColumn。Luau 类型别名、函数签名与 docstring 怪癖类型别名luautype_definition简单别名 name 子节点是identifier泛型别名的 name 子是generic_type节点名即其逐字文本——GenericT、MapK, V空格保留pinned。export type的节点从export关键字开始CST 探测确认isExported 切片钩子给出 true。:2973的TYPE_ANNOTATION_LANGUAGES.has(luau)为 FALSE → 别名值不发任何引用双重死亡value字段在此语法中也是 NULL。extractTypeAlias 返回 false → 别名子节点被重新访问typeof(require(...))别名内的 function_call 命中钩子 →type_alias 节点 import 节点 imports 引用三样齐发pinnedFromTypeof→ type_alias L11 C0-55 import Config L11 C25-54 FILE 的 imports 引用别名节点先创建。体内局部type X …luau 合法铸出什么都没——visitFunctionBody 没有 typeAlias 分支pinned。lua 侧 typeAliasTypes 为空.lua文件里混入type X 本来就会解析报错而被整体延迟。函数与方法function_declaration覆盖全局、local、表函数function t.f、方法function t:m四种形态——同一种节点类型靠name:子节点区分形态匿名function() endfunction_definition不在类型列表中靠外层变量捕获。getReceiverTypelua.ts 第 92-99 行name:子是dot_index_expression/method_index_expression→ 返回其table:字段文本逐字点号源码function M.sub.deep:chained()→ receiverM.sub.deeppinned否则 undefined。接收者 QN 覆盖function M.attached()即使嵌套在函数体内也是M::attached而非render::attachedpinnedfunction _G.installed()铸出 method_G::installed。嵌套裸函数用节点名拼栈 QNM:render体内的local function inner→render::inner用方法名而非其 QN体内声明的全局function leakedGlobal()仍受栈作用域约束 →render::leakedGlobalpinned 怪癖保留。owner-contains 逻辑:1799-1813永不触发——它要求文件内存在 kind ∈ {struct, class, enum, trait} 的节点lua 从不铸这些 kind点号 receiver 也匹配不到任何节点名。唯一的包含边就是栈顶 contains 边。extractMethod不传 isExported——luau 方法 isExported 为 undefined 而 luau 函数为 falsepinnedmethod make 无标志、function typedTop isExportedfalse这是 lua↔luau 在节点载荷上除签名/类型别名外的唯一分歧。docstring 怪癖tree-sitter-helpers.ts第 95-127 行两语法各只有一种注释 kindcomment覆盖--行注释、--[[ ]]块注释、LuaDoc---、指令--!strict块注释剥--[[ … ]]/--[[ … ]]的开闭行注释逐行剥^--\s?LuaDoc---保留一个前导---- Summary→- Summary两语言 pinned--!strict变成 docstring 文本!strict且并入注释链——pinnedtorture.luau 的coredocstring 是!strict\nheader comment for torture.luau注释链跨空行延续兄弟跳过空白被任何非注释命名兄弟打断——包括第 1 行的hash_bang_lineshebang 注释链 → 注释链保留pinnedCRLF 字节 pinned行注释 docstring 与 LF 完全相同每条注释各自 trim 后以\n连接块注释 docstring 保留内部\r\n只 trim 两端。签名同样保留原始\r\n。相关剥离规则lua_open/lua_close/dashes已存在于内核共享的 docstring.rs#1329 的多行剥离工具移植时直接调用共享模块。Function-as-value 捕获与必须保持静默的死机制fn-ref 捕获#756LUA_SPEC 中 idTypes {identifier}仅裸标识符——点号值永不命中{ on_make M.make }捕获无物pinneddispatch 键为arguments→ 参数、assignment_statement→ RHS无字段RHS 末个命名子 expression_list参数存储跳过逻辑比较 namedChild(0) 的尾标识符与整个 RHS 文本M.cb cb跳过pinned、field→value:字段值键控与位置表字段都带value:真值表确认。捕获点在顶层 call 参数 赋值 每个 ladder 递归经过的field节点、体内逐节点、以及 scanFnRefSubtree其 halt 列表不含function_definition所以扫描会深入匿名函数初始值体深度上限 12。flush 时 definedHere 同文件函数/方法名importedNames 中点号模块路径只贡献末段app.core→coreRoblox 叶子名Signal整体通过——pinned(helper)粘连候选因存在 importhelper而被 flush。按${fromNodeId}|${name}去重首次出现位置胜出三个topFn表值候选 → 一条 function_ref 位于首个位置。pinned 总量torture.luapcall(topFn, 7, 8)→ topFn表注册含位置键[1]、嵌套表、去重、missing门控、M.cb cb跳过各形态luau{ plain typedTop }→ typedTopM:update(…, print)→ print 门控掉未定义/未导入。死机制——walker 必须把这些复现为静默清单以专节列出这是绝不发明行为的边界值引用边VALUE_REF_LANGS无 lua/luau → flushValueRefs 丢弃全部收集物赋值影子修剪的assignmentcase 是 Python 的节点 kind不是 lua 的assignment_statement即便将来加入也空转。references边带 valueRef 元数据的零静态成员引用STATIC_MEMBER_LANGS 排除 lua/luauextractStaticMemberRef 入口即返回类型标注引用TYPE_ANNOTATION_LANGUAGES 排除 → luau 参数类型与返回类型只活在签名字符串里returnType 字段永不设置instantiates / 继承无 lua 节点 kind 命中 INSTANTIATION_KINDSclass/interface/enum 类型列表全空 → extractInheritance 永不运行。setmetatable元表类模式只发出 calls 引用——无类合成、无 extendspinneddecoratesextractDecoratorsFor对每个函数/方法都会运行但 decorator/annotation/attribute 节点不会出现在它扫描的位置lua 的attributeconst/close在 variable_list 内部pinnedlocal x const 99→ variable x、signature 99、无引用。decorates引用零。等价性机械字节序、wire 标志与延迟策略移植验收的曾经咬过人清单发射顺序file 节点 → 源码序遍历。每个 require 声明钩子内 import 节点 → imports 引用先于 extractVariable 的变量节点钩子循环先完成contains 边随 createNode 交错源码位置交错的 imports calls 引用function_ref 引用最后 flush。store/harness 对 rowid 顺序敏感必须逐条复现。wire 标志bit pairslua 世界唯一会被设置的标志是变量的isExportedfalsepresent1, value0luau 额外在函数false与类型别名export type为 true上设置 present 位——但方法不设extractMethod 不传。lua 函数 present 位为 0undefined。present-vs-value 的区分必须字节精确。visibility 字节处处为 0returnType/decorators/typeParameters 处处缺失。UTF-16 列号/切片所有位置与 getNodeText调用者原文、签名、docstring 源、import 签名 trim都按 UTF-16 码元计内核侧对应textutil::col16。pinnedlocal préfixe→ C6-137 个 UTF-16 单位。节点 ID 的 hash 输入行号变量 hash标识符的行import hash调用的行函数/方法 hash 声明行luau type_alias hash type_definition 行export 时从export起。同 id 重复行照发不去重。延迟策略按文件has_error()→defer:消息约定同 ruby.rs。codegraph-kernel/src/lua.rs 第 96-98 行即此实现if tree.root_node().has_error() { return Err(defer: parse tree contains errors — wasm recovery is canonical) }。解析侧消费者walker 输出的字节被下游固定移植不需要动解析层但解析层反向固定了 walker 必须发出的字节resolveLuaRequireimport-resolver.ts 第 1688 行起分发 :1485把 imports 引用的 referenceName 当点号路径处理telescope.config→telescope/config.lua或 Roblox 叶子Signal→Signal.luau依次尝试后缀p.lua | .luau | /init.lua | /init.luau以与请求文件共享前缀最长者胜命中 file 节点、置信度 0.9代码注释说明 ≥0.9 是为了压过 name-matching 的同名自匹配。walker 的义务referenceName 模块字符串/叶子逐字点号完整不做任何归一化。Lua 冒号方法解析提取发出lg:log形状的调用name-matcher 的luaColonMatchname-matcher.ts 第 1758 行正则/^([\w.]):(\w)$/把它们拆开做局部变量 receiver 类型推断#1108其中含#1124 lookahead——第三个模式用负向前瞻拒绝 PascalCase方法调用lg:Log()Roblox 惯例被误认为类型标注因为 Lua 调用语法恰是同样的receiver:Name形状。预过滤保留单冒号引用在任一侧或大写 receiver命名已知符号时存活。walker 的义务单冒号字节形状receiver 限[\w.]——括号/粘连垃圾本来就不会被解析。除此之外没有框架 resolver 或 synthesizer 消费 lua/luauCC_LANGUAGES {swift, kotlin}、NATIVE {java, kotlin, objc, cpp}均不含也没有.lua内容嗅探——语言纯按扩展名判定grammars.ts 的detectLanguage1MiB MAX_FILE_SIZE 与生成文件跳过是编排器侧共享逻辑。验证门禁从语法表到全仓扫描按迁移计划的分层门禁lua/luau 的验收链条当前仓库已全部落地Stage 0与 walker 同批或之前内核 C vendorgrammars/luasha 见上 build.rs 块 langs.rs 条目 luau crate 钉版 GRAMMAR_LANGUAGES lua, luau—— 证明 C/crate ≡ vendored wasm 修订版lua ABI 15 / luau ABI 14kindfield 表逐 id 比对。无需 dump 对比wasm 臂原封未动。对应tests/kernel-grammar-parity.test.ts。Torture 夹具新建的tests/kernel-lua-parity.test.ts文件头注释逐条列举了夹具覆盖面配合 torture.lua 与 torture.luau 夹具加上内存派生的 CRLF 变体固定块注释\r\ndocstring 字节与 CRLF 签名与粘连链/延迟 pin。torture.lua 清单99 行、parse-cleanshebang 注释链 docstring、require 全形态双引号、Roblox 实例路径、单引号、[[ ]]、script:WaitForChild字符串优先、.field与动态参数的静默、双 require 顺序、pcall-require 无产出、LuaDoc-怪癖、receiver QNt.f/t:m/a.b.c:m/_G.f、体内 require→calls-require、self 冒号/点号调用、括号调用者、嵌套 local/receiver/global 函数的 QN 怪癖、表 fn-ref 注册位置键 嵌套 去重 missing 门控 M.cb cb跳过、全局赋值可见 vs local 声明不可见的反转、(handler)转换重写、裸local x无 signature 键、单行多语句、]]长字符串、const属性、非 ASCII 行UTF-16 列、goto/label、一行local x 1; local x 2同 id。torture.luau62 行--!strictdocstring 并入、普通/export type/泛型GenericT逐字名/typeof(require(...))别名四形态、带返回后缀的类型化签名、类型化方法无 isExported、体内 type无产出、插值调用、if-表达式两臂、RHS 调用、cast、continue。延迟夹具各一一个含 luau 语法x 1的 lua 文件、一个含默认类型参数type ST U {}的 luau 文件——内核defer:wasm 臂输出原样断言。Parity 扫描scripts/kernel-parity.mjs dir默认--max-deferral 0.1kong大仓 lua1,309 文件预期 ≤1 次延迟、lazy.nvim65预期 0、lua-resty-core38LuaJIT/OpenResty 惯用法预期 0、luneluau 221预期 ~3、Fusionluau 113 重度类型化预期 ~8luau-lang/luau tests/ 与 StyLua tests/ 仅作可选压测臂--max-deferral 0.3/0.5只判非延迟部分的 parity。随后 kong lazy.nvim lune Fusion 上做全量初始化 dump 字节对比内核臂 vsCODEGRAPH_KERNEL0的 scripts/dump-graph.mjscmp 逐字节一致。路由开启以上全部通过后把lua, luau加入 src/extraction/kernel/index.ts 的DEFAULT_ROUTED第 95-96 行注释即引用了上述扫描预期与延迟含义。当前仓库中这一步已完成CODEGRAPH_KERNEL_LANGS环境变量可按语言覆盖、CODEGRAPH_KERNEL0全关。方法论小结这份清单示范了一套可复用的移植前调查范式先对生产 wasm 做 CST/字段真值表探测钉住语法形状再对真实提取器做 ground-truth dump 钉住行为含刻意保留的确定性垃圾如 BFS 字符串优先与换行粘连链把移植义务分成三类——必须逐字保留的怪癖require 不对称、raw-text 调用者、isExported wire 分歧、必须保持静默的死机制value-refs/static-member/type-annotation refs/instantiates/decorates、以及用真实仓库错误率表推导出的延迟预期最后以语法版本表等价测试 torture 夹具 CRLF 变体 全仓 dump 字节对比 分级路由开启作为不可跳过的验收阶梯。文档末尾的 Probe artifacts 一节列出了全部可再生的探测脚本与夹具清单CST dump、字段真值表、31 条 snippet 探针、错误分类文件、门控仓浅克隆并声明这些临时目录可丢弃——从这份文档本身即可完整重新推导。这也是它作为设计文档的核心价值移植完成后它仍是 lua.rs 中每一处看起来不合理代码的权威出处——lua.rs 的模块头注释直接写明 The authoritative quirk list is docs/design/lua-luau-kernel-port-checklist.md。【免费下载链接】codegraphPre-indexed code knowledge graph, auto syncs on code changes, for Claude Code, Codex, Gemini, Cursor, OpenCode, AntiGravity, Kiro, CoPilot, and Hermes Agent — fewer tokens, fewer tool calls, 100% local项目地址: https://gitcode.com/GitHub_Trending/co0degr/codegraph创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表