📝 docs(code-reader): 规格补上链式调用卡片,tauri / axum 的链换成库自己的叫法、Router 列出全部路由

This commit is contained in:
cruldra committed 2026-10-15 21:14:59 +11:00
1 parent aaa695eae4
commit 1d7e2eaee9
1 file changed
+88 -12
+88 -12
View File
@@ -373,7 +373,7 @@
原型画板「调用 · 构造」(`code.js` 的「调用与构造」一节,嵌套见 `nestedArgRow`、`NESTED_CALL_SAMPLE`)。实参多的调用一般跨几行写,挤成一行译文读不下去;把实参摊成一张表,实参的值又是这样的调用时在格子里接着摊。 原型画板「调用 · 构造」(`code.js` 的「调用与构造」一节,嵌套见 `nestedArgRow`、`NESTED_CALL_SAMPLE`)。实参多的调用一般跨几行写,挤成一行译文读不下去;把实参摊成一张表,实参的值又是这样的调用时在格子里接着摊。
- 哪些调用:实参列表(括号连同里面,`CallFacts.argumentList`)跨了几行的调用,而且整个落在要翻的这一段里(块头部;TypeScript `describe('x', () => { … })` 这种主体是子块的调用不算)。一行写完的调用照旧一行译文,不问定义。链式调用跨了几行、每段的括号都写在一行里的(`items\n .filter(…)\n .map(…)`)也不算;式子跨了几行、里面的调用各自写在一行里的(`bool(x)\n and Path(x).is_file()`)是式子,也不算。拆开的列表里整项是调用的例外,写成一行也排(见「字典 / 对象字面量、跨几行写的列表」)。 - 哪些调用:实参列表(括号连同里面,`CallFacts.argumentList`)跨了几行的调用,而且整个落在要翻的这一段里(块头部;TypeScript `describe('x', () => { … })` 这种主体是子块的调用不算)。一行写完的调用照旧一行译文,不问定义。链式调用跨了几行、每段的括号都写在一行里的(`items\n .filter(…)\n .map(…)`)也不算(两步以上的这种链排成链式调用卡片,见下一节);式子跨了几行、里面的调用各自写在一行里的(`bool(x)\n and Path(x).is_file()`)是式子,也不算。拆开的列表里整项是调用的例外,写成一行也排(见「字典 / 对象字面量、跨几行写的列表」)。
- 一段排一个:一行译文的块、常量 / 变量的值、实参表里每个值各是一段,各自排自己里面遇到的第一个(先外后里)这样的调用或跨几行写的字典 / 列表(见「字典 / 对象字面量、跨几行写的列表」);同一段里后面再有的照常一行译文(挤成一行时圆括号贴着里面的内容:`f(\n x\n)` 写成 `f(x)`,方括号、花括号照旧空一格)。被调用的表达式里的调用(`get_driver(\n m\n).query(\n …\n)` 排的是外面的 query)照常一行。 - 一段排一个:一行译文的块、常量 / 变量的值、实参表里每个值各是一段,各自排自己里面遇到的第一个(先外后里)这样的调用或跨几行写的字典 / 列表(见「字典 / 对象字面量、跨几行写的列表」);同一段里后面再有的照常一行译文(挤成一行时圆括号贴着里面的内容:`f(\n x\n)` 写成 `f(x)`,方括号、花括号照旧空一格)。被调用的表达式里的调用(`get_driver(\n m\n).query(\n …\n)` 排的是外面的 query)照常一行。
- 一行:`[等待 ]新建 / 调用 被调用的名字 · N 个参数`。「等待」就是 `await` 照常的译法(在调用前面),「新建」「调用」按声明关键字着色;被调用的名字照常翻、带源码下标(⌘ / Ctrl + 点击、单击高亮、中文名都照旧),前面几节(对象、模块)按变量着色,最后那个名字新建时按类型着色、调用时按函数着色;「· N 个参数」按说明词着色,N 数的是表里的行。 - 一行:`[等待 ]新建 / 调用 被调用的名字 · N 个参数`。「等待」就是 `await` 照常的译法(在调用前面),「新建」「调用」按声明关键字着色;被调用的名字照常翻、带源码下标(⌘ / Ctrl + 点击、单击高亮、中文名都照旧),前面几节(对象、模块)按变量着色,最后那个名字新建时按类型着色、调用时按函数着色;「· N 个参数」按说明词着色,N 数的是表里的行。
- 埋在式子里:调用后面还紧跟着同一个式子的别的部分(`.model_dump()`、`[0]`、`or x`;后面是右括号、逗号、分号、冒号或什么都没有的不算),这一行整个括起来:「(新建 X · 3 个参数).model_dump()」「(调用 make · 1 个参数) 或者 fallback」,表照样排在这一段下面。前面有东西的(`fallback or make(\n…\n)`)不括。 - 埋在式子里:调用后面还紧跟着同一个式子的别的部分(`.model_dump()`、`[0]`、`or x`;后面是右括号、逗号、分号、冒号或什么都没有的不算),这一行整个括起来:「(新建 X · 3 个参数).model_dump()」「(调用 make · 1 个参数) 或者 fallback」,表照样排在这一段下面。前面有东西的(`fallback or make(\n…\n)`)不括。
@@ -400,6 +400,25 @@
| `result = await config.get_payment_driver(\n order.payment_method\n).query_refund_status(\n out_trade_no=…,\n out_request_no=…,\n)` | 初始值 `等待 调用 config.get_payment_driver(order.payment_method).query_refund_status · 2 个参数` | | `result = await config.get_payment_driver(\n order.payment_method\n).query_refund_status(\n out_trade_no=…,\n out_request_no=…,\n)` | 初始值 `等待 调用 config.get_payment_driver(order.payment_method).query_refund_status · 2 个参数` |
| `context.subscriptions.push(\n treeView,\n commands.registerCommand('…', () => {\n …\n }),\n …\n)` | 一行 `调用 context.subscriptions.push · 4 个参数`;第 2 ~ 4 个那一格 `调用 commands.registerCommand · 2 个参数`,下面套它的 2 行表 | | `context.subscriptions.push(\n treeView,\n commands.registerCommand('…', () => {\n …\n }),\n …\n)` | 一行 `调用 context.subscriptions.push · 4 个参数`;第 2 ~ 4 个那一格 `调用 commands.registerCommand · 2 个参数`,下面套它的 2 行表 |
### 链式调用卡片
原型:`docs/prototype/code-reader/openpencil/exports/` 的 `rust-chain-a.png`(步骤轨道)、`rust-chain-b.png`(按方法分组)、`rust-chain-a-setup.png`(展开 setup 的闭包)、`rust-chain-short.png`(短链在变量初始值里),绘制脚本同目录 `rust-chain.js`。定下来的是 A、B 合并:所有链都排成 A 的步骤轨道;B 里「连着几次调用同一个方法合成一步」是通用的,按库起的叫法归库规则。样例是 luffy `apps/desktop/src-tauri/src/lib.rs` 那条 `tauri::Builder` 链(精简版 `fixtures/rustChain.rs`)。builder、迭代器这类链挤成一行译文读不下去,闭包体也被压扁;排成一步一行的竖轨道,闭包收起来、点开才看。
- 什么算链(语言插件读,`LanguageAdapter.chain` → `ChainFacts`,这次只有 Rust 给,TypeScript、Python 不给就照旧):两步以上的 `.方法(实参)` 接着写(`a.b(…).c(…)`,方法名后面可以带 `::<…>`)。套在调用外面的 `.await`、`?` 归它前面那一步,不单独成步;从外往里剥到不是方法调用的式子就是起点(连同套在它外面的 `?`:`foo()?.bar().baz()` 的起点是 `foo()?`)。宏调用、取字段(`x.a().b.c()` 的 `.b`)不算一步,链从那里断开。写在 `.` 前面的注释归这一步,和上一步结尾同一行的归上一步(行尾注释)。实参是闭包、async 块的标出来(`ChainArgument.closure`),主体是 `{}`、闭包主体直接是 match(`{}` 里只有一个 match 也算)的收起来(`DeferredFacts`:参数、主体有几句、match 的值和几支)。
- 什么时候排成卡片(翻译插件定,`zhTemplate.ts`):某一步的 `.` 另起一行写(跨行写的链),或实参里有闭包(写在一行里的 `rows.iter().filter(|r| r.active).map(|r| r.name.clone()).collect()` 也排);单行写又没有闭包的(`app.path().app_data_dir()?.join("x")`)照旧一行译文。整句(表达式语句的式子、`return` 的值、末尾不带分号的返回值;块的节点往下只有一个具名子节点的那几层)是这样的链时这一块排成卡片,常量、变量的值是这样的链时值那一行排成卡片;链埋在别的式子里(赋值右边、实参里)照旧一行。
- 排在哪:
- 整句是链的块(语句、返回):译文只剩链外面的词(返回块是「返回」;语句什么都不剩,不画这一行),下面「起点」一行照抄起点,「步骤」一行写「N 个」(合成以后的步数),链的各步排成竖轨道接在「步骤」的值下面(`TextTranslation.rows` → 视图数据的 `rows`,宿主把「注释」一行插在第一行后面)。
- 常量、变量:「值 / 初始值」那一行的值是起点,链接在值下面(`PropertyRow.chain`),没有「步骤」一行。
- 轨道(webview 的 `ChainRail`,在 `PropertyGrid.tsx`):一步一个实心点(函数色),点与点之间上下两截线(函数色淡到 35%,第一步上面、最后一步下面不画);方法一列按最长的那个定宽、各步对齐,值一列照抄实参(`Translator.verbatim` 的压成一行:名字各自带源码下标、按词着色,能悬停、⌘ + 点击跳到定义),几个实参逗号隔开,`.await`、`?` 照常翻(「等待」)跟在实参后面。
- 方法名写 `.名字`(带下标);标准库常见方法有中文名的写中文名(翻译插件的词表 `ZhTable.methods`,Rust 的在 `rustZh.ts`:iter 遍历、filter 筛选、map 映射、collect 收集、for_each 逐个执行、map_err 转换错误……;unwrap、expect 照写方法名),悬停看原名(`tooltip`),⌘ / Ctrl + 点击跳到方法名(`refers`)。
- 实参本身是值得排成卡片的链、这一步只有这一个实参时,在值下面缩进成一条小链(空心点、细一点的说明色线):第一行是它的起点,后面一步一行 `.名字(实参)`。
- 写在某一步上面的 `//` 注释是这一步下面的「注释」一行(方法那一列写「注释」,值按 Markdown 显示)。
- 收起来的闭包、async 块是一个能点的小框(框的样式 `fold`):「闭包 |参数| · N 句」,async 块是「异步块 · N 句」,主体只有一个 match 时是「闭包 |参数| · match 值 · N 支」,参数、match 照抄。默认收着,点框展开 / 收起。闭包体里的各句是这一块的子块(同函数体拆块那一套,块的位置记号、问 AI、编辑、注释照常),宿主按位置把它们挂到所在那一步下面(`ChainStep.range` → `BlockView.step`:属性表第几行那条链的第几步),展开时画在这一步下面,不排在卡片后面那一层;一步里几个闭包一起展开、一起收起。折叠 id 是 `<属性行 id>/s<步序号>`(`chainStepId`),默认收着,标了改动的子块所在的那一步默认展开。
- 连着几次调用同一个方法(不连着的不合)合成一步:值写「N 次」,下面一张表一行一次,列是各个实参(每次最多一个实参时只有一列「实参」,多的是「第 1 个」「第 2 个」……),合成的几次各自上面的注释都挂在这一步下面;顺序始终按源码。
- 库规则给链起叫法(`ChainGroup`):规则按起点、方法名认出是哪个库的链,用 `RuleContext.chain(node, groups)` 让翻译插件排(`Translator.chain`,不管值不值得排成卡片都给),把第 from 到第 to 步合成一步、起叫法(方法那一列写叫法;几步是同一个方法时悬停看原名、⌘ 点击跳到第一步的方法名),可以换掉值、换成表;没换的一步照常,几步不同方法的每步一行排成小链。认领的方式同别的 Rust 库卡片(`valueCard`),卡片的「起点」「步骤」两行同翻译插件排的(`rules/rustRows.ts` 的 `chainRows`),闭包的子块照常挂在各自那一步下面。tauri、axum 的叫法见「内置:Rust 的库」。
- 跳到定义、单击高亮、键盘跳到一处出现、查找、中文名都算上链里的字(起点、方法、值、小链、注释、表;扩展端 `renderedNames`,webview `reveal.ts` 的 `cardTexts`),高度估算算上各步。差异只标到整块:链里改了,卡片标成修改,不逐步标;删掉的块的旧链照画,闭包框不能点。「只看改动」不折挂在步骤下面的子块,只往里看改动。
- 和原型不一样的:轨道接在「步骤」那一行的值下面(原型从属性名那一列起画);变量的起点写在「初始值」那一行的值里,不并进第一步(原型写「遍历 rows」);规则合成的「构建并运行」三步用小链的空心点连着(原型 B 用箭头)。
### Shell 脚本 ### Shell 脚本
原型画板「Shell 脚本」(`code.js` 的「Shell 脚本」一节:`SHELL_KINDS`、`SHELL_BLOCKS`、`shellBlock`;README「Shell 脚本」)。样例是 luffy 桌面端的 `apps/desktop/scripts/fetch-runtime.sh`(复制成 `fixtures/fetchRuntime.sh`)。原型里的中文是手写的目标,插件读出来的逐行和它对得上;原型略去的 95–100、116–121 行也照样读。 原型画板「Shell 脚本」(`code.js` 的「Shell 脚本」一节:`SHELL_KINDS`、`SHELL_BLOCKS`、`shellBlock`;README「Shell 脚本」)。样例是 luffy 桌面端的 `apps/desktop/scripts/fetch-runtime.sh`(复制成 `fixtures/fetchRuntime.sh`)。原型里的中文是手写的目标,插件读出来的逐行和它对得上;原型略去的 95–100、116–121 行也照样读。
@@ -872,6 +891,35 @@ export interface CallFacts {
arguments: CallArgument[] arguments: CallArgument[]
} }
/** 链式调用里收起来的一个实参(见「链式调用卡片」):主体是 `{}`(或只有一个 match)的闭包、async 块;主体里的各句是这条语句的子块。 */
export interface DeferredFacts {
kind: 'closure' | 'async'
parameters?: Node // 闭包的参数表(`|app, event|`);async 块没有
statements: number // 主体里写了几句,注释不算
match?: { node: Node, value: Node, arms: number } // 主体只有一个 match 时:整个 match、匹配的值、几支
}
export interface ChainArgument {
node: Node
closure: boolean // 实参是闭包、async 块:实参里有它的链写在一行里也排成卡片
deferred?: DeferredFacts // 收起来的闭包、async 块
}
/** 链式调用的一步:`.方法(实参)`,连同紧跟在调用后面的 `.await`、`?`。 */
export interface ChainStepFacts {
dot: Node // 方法名前面的 `.`:和上一步的结尾(第一步是起点)不在同一行就是跨行写的链
method: Node
typeArguments?: Node // `::<Vec<_>>` 的 `<Vec<_>>`
call: Node // 这一步的调用,从链的开头算起
argumentList: Node
arguments: ChainArgument[]
after: Node[] // 套在调用外面的 `.await`、`?` 各一层,从里往外
comments: Node[] // 写在 `.` 前面的注释(和上一步结尾同一行的归上一步)
}
/** 两步以上的链式调用:起点(链最前面的接收者或起始表达式)和各步,照源码顺序。 */
export interface ChainFacts { start: Node, steps: ChainStepFacts[] }
export interface DeclaratorFacts { export interface DeclaratorFacts {
name: Node name: Node
type?: Node type?: Node
@@ -963,9 +1011,10 @@ export interface Segment { text: string, role: TokenRole, offset?: number, refer
* 框的样式,决定框头图标和框的颜色:iteration 写在表达式里的遍历(渲染大纲的「对 … 的每一项」也是),图标、颜色同「循环」块; * 框的样式,决定框头图标和框的颜色:iteration 写在表达式里的遍历(渲染大纲的「对 … 的每一项」也是),图标、颜色同「循环」块;
* condition 按条件(「当 … 时」「如果 …」),图标、颜色同「条件」块;branch 条件的一支(三元的「是」「否」),同「条件」块的颜色、不带图标; * condition 按条件(「当 … 时」「如果 …」),图标、颜色同「条件」块;branch 条件的一支(三元的「是」「否」),同「条件」块的颜色、不带图标;
* tag 小标签(「具名导出」「回调」),只有框头的字、颜色是 color; * tag 小标签(「具名导出」「回调」),只有框头的字、颜色是 color;
* classes 收起来的一串类名(「样式 N 个类」),中性色,点开、悬停看 detail。 * classes 收起来的一串类名(「样式 N 个类」),中性色,点开、悬停看 detail;
* fold 链式调用卡片里收起来的闭包、async 块(「闭包 |app| · 37 句」),中性色,点它展开、收起这一步下面挂着的子块。
*/ */
export type GroupStyle = 'iteration' | 'condition' | 'branch' | 'tag' | 'classes' export type GroupStyle = 'iteration' | 'condition' | 'branch' | 'tag' | 'classes' | 'fold'
/** /**
* 框起来的一组词:预览画成嵌在前后文字里的小框,框头是图标和 label(翻译插件、库规则给;只有图标时是空的);框里的词照样带下标,还能再套框。 * 框起来的一组词:预览画成嵌在前后文字里的小框,框头是图标和 label(翻译插件、库规则给;只有图标时是空的);框里的词照样带下标,还能再套框。
@@ -1019,14 +1068,30 @@ export interface PropertyItem extends Defines {
* 属性表的一行:属性名、着色的值或 Markdown 说明(函数、类的「说明」)、展开在下面的子行(输入参数、导入项、字典 / 对象、列表的各项)。 * 属性表的一行:属性名、着色的值或 Markdown 说明(函数、类的「说明」)、展开在下面的子行(输入参数、导入项、字典 / 对象、列表的各项)。
* columns 是子行各列的列名(输入参数的名称 / 类型 / 默认值):给了的子行排成带表头的表格,没给的排成列表;两种子行都能再带下一层。 * columns 是子行各列的列名(输入参数的名称 / 类型 / 默认值):给了的子行排成带表头的表格,没给的排成列表;两种子行都能再带下一层。
* note 是跟在值后面的一段说明(Markdown,注释色):输出参数那一行,返回类型后面是说明里的 `@return`。 * note 是跟在值后面的一段说明(Markdown,注释色):输出参数那一行,返回类型后面是说明里的 `@return`。
* chain 是值(链的起点)后面接着的链式调用各步,排成竖轨道(见「链式调用卡片」)。
*/ */
export interface PropertyRow extends Defines { label: string, value: PreviewText, note?: Markdown, items?: PropertyItem[], columns?: string[] } export interface PropertyRow extends Defines { label: string, value: PreviewText, note?: Markdown, items?: PropertyItem[], columns?: string[], chain?: ChainStep[] }
/** 一张带表头和边框的表:列名,每行几列对齐的格子,同 PropertyRow 给了 columns 的子行。 */ /** 一张带表头和边框的表:列名,每行几列对齐的格子,同 PropertyRow 给了 columns 的子行。 */
export interface PreviewTable { columns: string[], items: PropertyItem[] } export interface PreviewTable { columns: string[], items: PropertyItem[] }
/** 一行译文的块翻出来的:一行译文(注释块——文件开头的说明、挂在块上的注释——是 Markdown 原文);预览排在这一行下面的,跨几行写的字面量是拆开的各项(items),跨几行写的调用是摊开各个实参的表(table)。 */ /**
export interface TextTranslation { text: PreviewText, items?: PropertyItem[], table?: PreviewTable } * 链式调用卡片的一步:方法那一列(`.名字`,或翻译插件、库规则起的叫法,叫法带 refers / tooltip 指回方法名)、值那一列(实参照抄、
* 收起来的闭包是 fold 框、合成的一步是「N 次」),下面依次是小链(一节一行)、几行属性(注释)、表;range 是这一步在源码里的范围,宿主按它挂子块。
*/
export interface ChainStep { name: Inline[], value: Inline[], lines?: Inline[][], rows?: PropertyRow[], table?: PreviewTable, range: SourceRange }
/** 一条链排成的样子(Translator.chain):起点照抄成一行,各步。 */
export interface ChainView { start: Inline[], steps: ChainStep[] }
/** 库规则给链的读法:第 from 到第 to 步(ChainFacts.steps 的下标)合成一步、起叫法,可以换掉值(value)、换成表(table)。 */
export interface ChainGroup { from: number, to: number, label: string, value?: Inline[], table?: PreviewTable }
/**
* 一行译文的块翻出来的:一行译文(注释块——文件开头的说明、挂在块上的注释——是 Markdown 原文);预览排在这一行下面的,跨几行写的字面量是拆开的各项(items),
* 跨几行写的调用是摊开各个实参的表(table),整句是链式调用时是「起点」「步骤」两行(rows,链在「步骤」那一行上,text 只剩链外面的词)。
*/
export interface TextTranslation { text: PreviewText, items?: PropertyItem[], table?: PreviewTable, rows?: PropertyRow[] }
/** 语言插件:语法树 → 代码块树,外加只有它懂、翻译插件翻表达式时要用的信息(叶子的词性、写在表达式里的遍历的结构)。 */ /** 语言插件:语法树 → 代码块树,外加只有它懂、翻译插件翻表达式时要用的信息(叶子的词性、写在表达式里的遍历的结构)。 */
export interface LanguageAdapter { export interface LanguageAdapter {
@@ -1049,6 +1114,8 @@ export interface LanguageAdapter {
call?: (node: Node) => CallFacts | undefined call?: (node: Node) => CallFacts | undefined
/** node 是写出各项的字面量(字典、列表……)时给出它的各项,别的节点没有;没给的语言不拆字面量,照常一行译文。 */ /** node 是写出各项的字面量(字典、列表……)时给出它的各项,别的节点没有;没给的语言不拆字面量,照常一行译文。 */
collection?: (node: Node) => CollectionFacts | undefined collection?: (node: Node) => CollectionFacts | undefined
/** node 是两步以上的链式调用时给出它的结构,别的节点没有;没给的语言不排链式调用卡片。排不排成卡片归翻译插件(见「链式调用卡片」)。 */
chain?: (node: Node) => ChainFacts | undefined
/** node 是执行一条命令(shell)时给出它的结构,交给命令规则读;没有命令的语言不填。 */ /** node 是执行一条命令(shell)时给出它的结构,交给命令规则读;没有命令的语言不填。 */
command?: (node: Node) => CommandFacts | undefined command?: (node: Node) => CommandFacts | undefined
/** 一份源码里自己认得出的名字(LocalSymbol);VS Code 有这种语言的定义、高亮提供者时用不上,不填。 */ /** 一份源码里自己认得出的名字(LocalSymbol);VS Code 有这种语言的定义、高亮提供者时用不上,不填。 */
@@ -1113,8 +1180,9 @@ export interface Translator {
translate: (block: TextBlock, document: SourceDocument) => TextTranslation // 只翻 header 那一段;注释块(文件开头的说明、挂在块上的注释)给 Markdown 原文;跨几行写的字面量带拆开的各项、调用带实参表 translate: (block: TextBlock, document: SourceDocument) => TextTranslation // 只翻 header 那一段;注释块(文件开头的说明、挂在块上的注释)给 Markdown 原文;跨几行写的字面量带拆开的各项、调用带实参表
describe: (block: FactBlock, document: SourceDocument) => PropertyRow[] // 函数、类、枚举、异常、导入、常量、变量块 → 属性表 describe: (block: FactBlock, document: SourceDocument) => PropertyRow[] // 函数、类、枚举、异常、导入、常量、变量块 → 属性表
expression: (node: Node, document: SourceDocument) => Inline[] // 一个表达式 / 类型节点整个翻成一行译文,译法同属性表的值;库规则借它 expression: (node: Node, document: SourceDocument) => Inline[] // 一个表达式 / 类型节点整个翻成一行译文,译法同属性表的值;库规则借它
verbatim: (node: Node, document: SourceDocument, role?: TokenRole) => Inline[] // 一个类型 / 签名节点照抄成一行原文,不翻关键字:叶子按源码着色(给了 role 就都按它),名字各自带下标,跨几行写的压成一行、连着的空白收成一个空格;库规则借它 verbatim: (node: Node, document: SourceDocument, role?: TokenRole) => Inline[] // 一个类型 / 签名节点照抄成一行原文,不翻关键字:叶子按源码着色(给了 role 就都按它),名字各自带下标,跨几行写的压成一行、连着的空白收成一个空格(换行处圆括号贴着里面的内容、另起一行的 `.` 贴着前面,同译文;注释不抄,右括号前的尾逗号去掉);库规则借它
doc: (node: Node, document: SourceDocument) => Doc | undefined // 说明文字(注释、docstring、当说明用的字符串)→ 正文和块标签(Doc);正文同属性表的「说明」;连着几行的行文档注释(Rust 的 `///`)node 是第一条,翻译插件自己往下连 doc: (node: Node, document: SourceDocument) => Doc | undefined // 说明文字(注释、docstring、当说明用的字符串)→ 正文和块标签(Doc);正文同属性表的「说明」;连着几行的行文档注释(Rust 的 `///`)node 是第一条,翻译插件自己往下连
chain?: (node: Node, document: SourceDocument, groups?: readonly ChainGroup[]) => ChainView | undefined // 语言插件认得出的链排成链式调用卡片的样子,不管值不值得排成卡片;groups 是库规则的读法。不给就不排链卡片
attributeNames?: AttributeNames // 筛选属性和值叫什么,和属性表的叫法一致;筛选栏、种类图标的悬停提示用它 attributeNames?: AttributeNames // 筛选属性和值叫什么,和属性表的叫法一致;筛选栏、种类图标的悬停提示用它
} }
@@ -1174,6 +1242,7 @@ export interface RuleContext {
translate: (node: Node) => Inline[] // 借当前翻译插件的 expression;没有翻译插件时照抄源码 translate: (node: Node) => Inline[] // 借当前翻译插件的 expression;没有翻译插件时照抄源码
verbatim: (node: Node, role?: TokenRole) => Inline[] // 借当前翻译插件的 verbatim;没有翻译插件时照抄源码 verbatim: (node: Node, role?: TokenRole) => Inline[] // 借当前翻译插件的 verbatim;没有翻译插件时照抄源码
doc: (node: Node) => Doc | undefined // 借当前翻译插件的 doc:正文和块标签,规则按自己的卡片把标签放到对应的行 doc: (node: Node) => Doc | undefined // 借当前翻译插件的 doc:正文和块标签,规则按自己的卡片把标签放到对应的行
chain: (node: Node, groups?: readonly ChainGroup[]) => ChainView | undefined // 借当前翻译插件的 chain:规则给的读法(见「链式调用卡片」);不是链、翻译插件不排链时没有
lookup: (index: WorkspaceIndex, name: Node) => IndexEntry | undefined // name 指的定义在 index 里认出的那一项(见「规则认领时查别的文件里的定义」);还没查到是 undefined lookup: (index: WorkspaceIndex, name: Node) => IndexEntry | undefined // name 指的定义在 index 里认出的那一项(见「规则认领时查别的文件里的定义」);还没查到是 undefined
} }
@@ -1825,13 +1894,17 @@ react.component 23
文件导入了对应 crate 才启用(来源等于 crate 名,或以 `crate::` 开头)。tokio 不单独做卡片,异步已经写在函数上。样例 `fixtures/rustLibs.rs`。 文件导入了对应 crate 才启用(来源等于 crate 名,或以 `crate::` 开头)。tokio 不单独做卡片,异步已经写在函数上。样例 `fixtures/rustLibs.rs`。
axum 的 `Router`、sqlx 的查询写在函数体里时,语句看整句、`let` 看初始值、返回块看返回的值(`rules/rustRows.ts` 的 `valueCard`,两条规则共用)。认领 `let` 时卡片第一行是「变量」(变量名照翻,卡片和这一行的定义范围都是它,同没认领时的变量块);`let … else` 的 else、实参里的闭包照常是卡片的子块;块原来的「变量」「返回」概念照常排在卡片种类前面。 axum 的 `Router`、sqlx 的查询、tauri 的 `Builder` 写在函数体里时,语句看它的式子(`return x` 看 x)、`let` 看初始值、返回块看返回的值(`rules/rustRows.ts` 的 `valueCard`,几条规则共用)。认领 `let` 时卡片第一行是「变量」(变量名照翻,卡片和这一行的定义范围都是它,同没认领时的变量块);`let … else` 的 else、实参里的闭包照常是卡片的子块;块原来的「变量」「返回」概念照常排在卡片种类前面。拆成子块的那几段(实参里闭包、async 块主体里的各句)讲在子块自己的卡片上,规则在值里找查询、路由时跳过它们(`valueCard` 交给规则的 `own`),同一句不会外面那句、子块各出一张卡。链式调用排成库自己的卡片时用「链式调用卡片」那一套(`RuleContext.chain` 带上规则的读法,「起点」「步骤」两行是 `chainRows`)。
- serde(`rules/serde.ts`,`libraries: ['serde']`):`derive` 了 `Serialize` 或 `Deserialize` 的结构体。种类 `serde.struct`,标签「可序列化」,图标 `braces`,颜色同结构体(暗 #4ec9b0 / 亮 #267f99)。名称后面再标一个「可序列化」。`rename_all = "camelCase"` 收成选项「字段名改驼峰」。字段表多一列「序列化」:`rename` 写「改名 xxx」,`skip` / `skip_serializing` 写「不输出」,没标是「—」。说明里的 `@param` 同结构体对到字段表的「说明」列。 - serde(`rules/serde.ts`,`libraries: ['serde']`):`derive` 了 `Serialize` 或 `Deserialize` 的结构体。种类 `serde.struct`,标签「可序列化」,图标 `braces`,颜色同结构体(暗 #4ec9b0 / 亮 #267f99)。名称后面再标一个「可序列化」。`rename_all = "camelCase"` 收成选项「字段名改驼峰」。字段表多一列「序列化」:`rename` 写「改名 xxx」,`skip` / `skip_serializing` 写「不输出」,没标是「—」。说明里的 `@param` 同结构体对到字段表的「说明」列。
- thiserror(`rules/thiserror.ts`,`libraries: ['thiserror']`):`derive` 了 `Error` 的枚举。种类 `thiserror.error`,标签「错误」,图标 `triangle-alert`,颜色同异常(暗 #f14c4c / 亮 #cd3131)。变体表「变体 | 何时 | 展示」:何时是变体上面的文档注释,展示是 `#[error("…")]` 的文案。变体上的 `#[from]` 或 `#[source]` 在展示后面标「透传来源」。 - thiserror(`rules/thiserror.ts`,`libraries: ['thiserror']`):`derive` 了 `Error` 的枚举。种类 `thiserror.error`,标签「错误」,图标 `triangle-alert`,颜色同异常(暗 #f14c4c / 亮 #cd3131)。变体表「变体 | 何时 | 展示」:何时是变体上面的文档注释,展示是 `#[error("…")]` 的文案。变体上的 `#[from]` 或 `#[source]` 在展示后面标「透传来源」。
- axum(`rules/axum.ts`,`libraries: ['axum']`):处理函数上的 `#[get("/path")]`、`#[axum::post(…)]` 等(get / post / put / delete / patch / head / options / trace),或语句、`let` 的初始值、返回值里 `Router` 的 `.route(路径, get(函数))`(一句只出一张卡,讲链上最后写的那个 `route`)。函数已经标了路由属性时,这句 `route` 不再单独成卡。种类 `axum.route`,标签「接口」,图标 `globe`,颜色同 FastAPI 接口(暗 #61afef / 亮 #1a6fb5)。属性表:名称、说明、异步(是)、请求(一项「方法」、一项「路径」、路径里的 `{名字}` 对上参数写成「路径参数」,`Path(id): Path<Uuid>` 写 `id: Uuid`)、参数(说明里写了 `@param` 才有:参数是 `Path(id)` 这类模式,不对名字,照写成「名称 \| 说明」表)、返回(`@return` 跟在后面)、异常(`@throws`)。 - axum(`rules/axum.ts`,`libraries: ['axum']`):
- 路由器:语句、`let` 的初始值、返回值是 `Router` 的链(起点 `Router::new()` / `Router::default()`,或链里有 `.route`)时是「路由器」链式调用卡片,种类 `axum.router`,图标 `network`,颜色同 FastAPI 路由器(暗 #7aa2f7 / 亮 #34548a)。连着的 `.route` 合成「路由 N 个」一步,下面一张表「路径 \| 方法 \| 处理函数」,每条路由都列出来:`get(a).post(b)` 一个方法一行,路径去掉引号、带下标,方法大写,处理函数是名字时按函数着色、带下标(⌘ + 点击跳到它);`with_state` 共享状态、`layer` 中间件、`route_layer` 路由中间件、`nest` 嵌套路由、`nest_service` 嵌套服务、`merge` 合并路由、`fallback` 兜底处理。
- 接口:处理函数上的 `#[get("/path")]`、`#[axum::post(…)]` 等(get / post / put / delete / patch / head / options / trace),或只写了一步 `.route(路径, get(函数))` 的 `Router`(`Router::new().route("/health", get(health))`,不是两步以上的链)。函数已经标了路由属性时,这句 `route` 不再单独成卡。种类 `axum.route`,标签「接口」,图标 `globe`,颜色同 FastAPI 接口(暗 #61afef / 亮 #1a6fb5)。属性表:名称、说明、异步(是)、请求(一项「方法」、一项「路径」、路径里的 `{名字}` 对上参数写成「路径参数」,`Path(id): Path<Uuid>` 写 `id: Uuid`)、参数(说明里写了 `@param` 才有:参数是 `Path(id)` 这类模式,不对名字,照写成「名称 \| 说明」表)、返回(`@return` 跟在后面)、异常(`@throws`)。
- sqlx(`rules/sqlx.ts`,`libraries: ['sqlx']`):`query!` / `query_as!` / `query_scalar!` 宏,或 `query` / `query_as` / `query_scalar` 函数(参数是后面连着的 `.bind(…)`)。种类 `sqlx.query`,标签「查询」,图标 `database`,颜色暗 #ce9178 / 亮 #a31515。前面的注释同别的块,是卡片的「注释」一行(宿主插在第一行后面)。SQL 原文等宽,函数写法传进来的不是字符串(`&sql`)时照翻成一行;参数 `$1`、`$2`… 依次对上宏里 SQL 后面的实参或各个 `.bind`;`query_as!` 的第一个实参、`query_as::<_, T>` / `query_scalar::<_, T>` 尖括号里第二个类型是返回类型,`query!`、`query_scalar!`、`query` 和没写尖括号的返回类型是「—」。 - sqlx(`rules/sqlx.ts`,`libraries: ['sqlx']`):`query!` / `query_as!` / `query_scalar!` 宏,或 `query` / `query_as` / `query_scalar` 函数(参数是后面连着的 `.bind(…)`)。种类 `sqlx.query`,标签「查询」,图标 `database`,颜色暗 #ce9178 / 亮 #a31515。前面的注释同别的块,是卡片的「注释」一行(宿主插在第一行后面)。SQL 原文等宽,函数写法传进来的不是字符串(`&sql`)时照翻成一行;参数 `$1`、`$2`… 依次对上宏里 SQL 后面的实参或各个 `.bind`;`query_as!` 的第一个实参、`query_as::<_, T>` / `query_scalar::<_, T>` 尖括号里第二个类型是返回类型,`query!`、`query_scalar!`、`query` 和没写尖括号的返回类型是「—」。
- tauri(`rules/tauri.ts`,`libraries: ['tauri']`):`#[tauri::command]` 的函数。种类 `tauri.command`,标签「桌面命令」,图标 `square-function`,颜色暗 #e5c07b / 亮 #9a6a00。名称后面再标「桌面命令」。参数表「名称 | 类型 | 来源」:`State<…>` 是「窗口状态」,其余是「调用方传入」;说明里的 `@param` 对上时多一列「说明」,`@return` 跟在「返回」后面,`@throws` 成「异常」表。 - tauri(`rules/tauri.ts`,`libraries: ['tauri']`):
- 桌面命令:`#[tauri::command]` 的函数。种类 `tauri.command`,标签「桌面命令」,图标 `square-function`,颜色暗 #e5c07b / 亮 #9a6a00。名称后面再标「桌面命令」。参数表「名称 | 类型 | 来源」:`State<…>` 是「窗口状态」,其余是「调用方传入」;说明里的 `@param` 对上时多一列「说明」,`@return` 跟在「返回」后面,`@throws` 成「异常」表。
- 桌面应用:语句、`let` 的初始值、返回值是 `tauri::Builder::default()` / `new()` 起头的链(导入了 tauri 的 `Builder`、没起别名时写 `Builder::default()` 也算)时是「桌面应用」链式调用卡片,种类 `tauri.app`,图标 `package`,颜色同桌面命令。连着的 `.plugin` 合成「插件 N 个」一步,下面一张表「插件 \| 配置」:插件是 crate 名(按类型着色、带下标),`X::Builder::new().a(…).build()` 的配置写中间那几步(`open_js_links_on_click(false)`),`X::init(…)` 写实参,没有写「—」,认不出的写法整个照抄在插件那一格;`.setup` 启动时、`.on_window_event` 窗口事件、`.manage` 托管状态;`.invoke_handler(tauri::generate_handler![…])` 叫「命令 N 个」,值是各个命令名(路径照写,最后那节按函数着色、带下标,⌘ 悬停跳到命令函数);`build`(中间可以隔着 `expect` / `unwrap`)到 `run` 合成「构建并运行」,每步一行排成小链。
## 命令规则 ## 命令规则
@@ -1985,6 +2058,8 @@ shell 脚本大半是一条条命令,一条命令读成什么取决于命令
- 隐式返回值:函数体、闭包体、async 块最后那个不带分号的式子是 return,译文前面补「返回」;排在最后的 if / match / `{}` / `unsafe {}` 自己不是 return,照控制流拆,把「最后那个式子是返回值」传给各支;循环体、`let … else` 的 else 里不传。 - 隐式返回值:函数体、闭包体、async 块最后那个不带分号的式子是 return,译文前面补「返回」;排在最后的 if / match / `{}` / `unsafe {}` 自己不是 return,照控制流拆,把「最后那个式子是返回值」传给各支;循环体、`let … else` 的 else 里不传。
- `unsafe {}`、`async {}`、带标签的 `'a: {}` → 带子块的 statement,头部是 `unsafe` / `async move` / 标签;前面什么都没写的 `{}` 同 TypeScript 展平成各句。 - `unsafe {}`、`async {}`、带标签的 `'a: {}` → 带子块的 statement,头部是 `unsafe` / `async move` / 标签;前面什么都没写的 `{}` 同 TypeScript 展平成各句。
- 表达式语句、`let` 的值带着闭包、async 块时(值本身,或调用的实参里第一个:`tokio::spawn(async move { … })`、`.for_each(|x| { … })`,`.await`、`?` 看里面的调用),同 TypeScript 的回调,这句照常一行,子块来自那个 `{}`。 - 表达式语句、`let` 的值带着闭包、async 块时(值本身,或调用的实参里第一个:`tokio::spawn(async move { … })`、`.for_each(|x| { … })`,`.await`、`?` 看里面的调用),同 TypeScript 的回调,这句照常一行,子块来自那个 `{}`。
- 式子(表达式语句的式子、`let` 的值、`return` 的值、末尾的返回值)是带收起来的闭包的两步以上的链式调用时(见「链式调用卡片」),这一块的头部是整句,子块来自链里每个收起来的闭包、async 块(只有一个实参、实参本身是链的那一步取小链里的),闭包主体直接是 match 时子块是那一块条件;宿主把它们挂到各自那一步下面。
- 链式调用(`LanguageAdapter.chain`):两步以上的 `.方法(…)`,`.await`、`?` 归前一步,宏调用、取字段断开链;见「链式调用卡片」。
- 块里写的项(嵌套的 `fn`、`struct`、`use`、`const`……)跟文件顶层同一条路;注释同上面几条。 - 块里写的项(嵌套的 `fn`、`struct`、`use`、`const`……)跟文件顶层同一条路;注释同上面几条。
- 调用(`LanguageAdapter.call`):`call_expression` 的被调用者和实参(都是按位置传的),名字取路径、方法、泛型函数的最后一节;`Some(x)` 这类写法和调用一样,不给 construct;宏调用不算。跨几行写的调用同别的语言排成「调用 … · N 个参数」加实参表。 - 调用(`LanguageAdapter.call`):`call_expression` 的被调用者和实参(都是按位置传的),名字取路径、方法、泛型函数的最后一节;`Some(x)` 这类写法和调用一样,不给 construct;宏调用不算。跨几行写的调用同别的语言排成「调用 … · N 个参数」加实参表。
- `trait` → trait(图标 `network`,颜色同声明关键字的蓝)。同 `impl`:身体里的各项是子块,规则 `rules/rustImpl.ts`(种类 `rust.trait`,徽章「特质」暗 #569cd6 / 亮 #0000ff)把每张方法卡挂在方法表「名称 | 参数 | 返回」讲它的那个子行上,带默认实现的方法展开后有函数体子块。 - `trait` → trait(图标 `network`,颜色同声明关键字的蓝)。同 `impl`:身体里的各项是子块,规则 `rules/rustImpl.ts`(种类 `rust.trait`,徽章「特质」暗 #569cd6 / 亮 #0000ff)把每张方法卡挂在方法表「名称 | 参数 | 返回」讲它的那个子行上,带默认实现的方法展开后有函数体子块。
@@ -2106,6 +2181,7 @@ interface BlockViewBase {
concepts: BlockConcept[] // 认出来的概念,从左到右;webview 按图标名画,不自己用种类查 concepts: BlockConcept[] // 认出来的概念,从左到右;webview 按图标名画,不自己用种类查
badge?: KindBadge // 库规则的卡片才有:筛选栏里这个种类的名字,卡片边框的颜色;图标在 concepts 里。和类块一样默认折叠 badge?: KindBadge // 库规则的卡片才有:筛选栏里这个种类的名字,卡片边框的颜色;图标在 concepts 里。和类块一样默认折叠
slot?: { row: number, item: number } // 库规则挂在父卡片子行上的子块才有(RuleSlot):挂在父卡片第 row 行的第 item 个子行上,点它才在这一行下面展开(它的块 id 记成折叠着就是收着) slot?: { row: number, item: number } // 库规则挂在父卡片子行上的子块才有(RuleSlot):挂在父卡片第 row 行的第 item 个子行上,点它才在这一行下面展开(它的块 id 记成折叠着就是收着)
step?: { row: number, step: number } // 父卡片链式调用里收起来的闭包、async 块的子块才有:挂在父卡片第 row 行那条链的第 step 步下面(宿主按 ChainStep.range 挂),那一步展开时画在它下面
commentTarget?: CommentTarget // 「重写注释」写到哪(见「重写注释」);嵌着的代码里的块、语言没给出新写的办法又还没有注释的块没有,不给按钮 commentTarget?: CommentTarget // 「重写注释」写到哪(见「重写注释」);嵌着的代码里的块、语言没给出新写的办法又还没有注释的块没有,不给按钮
children: BlockView[] children: BlockView[]
} }
@@ -2116,7 +2192,7 @@ type CommentTarget = { kind: 'replace', startLine: number, endLine: number } | {
/** /**
* 属性表块(有 facts)和库规则认领的块只带 properties(「注释」一行由宿主插在里面),其余块只带 translation(文件开头的说明是 `{ markdown }`);没有翻译插件时是空数组。 * 属性表块(有 facts)和库规则认领的块只带 properties(「注释」一行由宿主插在里面),其余块只带 translation(文件开头的说明是 `{ markdown }`);没有翻译插件时是空数组。
* 一行译文里有跨几行写的字面量时 items 是拆开的各项(TextTranslation.items),有跨几行写的调用时 table 是摊开实参的表(TextTranslation.table),块带说明(TextBlock.doc)时 doc 是翻译插件读出的说明正文(Translator.doc 的 body), * 一行译文里有跨几行写的字面量时 items 是拆开的各项(TextTranslation.items),有跨几行写的调用时 table 是摊开实参的表(TextTranslation.table),块带说明(TextBlock.doc)时 doc 是翻译插件读出的说明正文(Translator.doc 的 body),
* 挂着注释时 rows 是「注释」一行,webview 依次排在译文下面。差异的标记里一行译文的卡片的 rows 同属性表逐行标。 * rows 是翻译插件排在下面的几行(整句是链式调用时的「起点」「步骤」)连同「注释」一行(插在第一行后面),没有前者时只有「注释」一行,webview 依次排在译文下面;译文是空的不画那一行。差异的标记里一行译文的卡片的 rows 同属性表逐行标。
*/ */
type BlockView = BlockViewBase & ({ translation: PreviewText, items?: PropertyItem[], table?: PreviewTable, doc?: Markdown, rows?: PropertyRow[] } | { properties: PropertyRow[] }) type BlockView = BlockViewBase & ({ translation: PreviewText, items?: PropertyItem[], table?: PreviewTable, doc?: Markdown, rows?: PropertyRow[] } | { properties: PropertyRow[] })
``` ```
@@ -2343,7 +2419,7 @@ vscode/webview-ui/code-reader.html + src/codeReader/ 预览界面(React,Vit
- 语言插件(`languages/bash.test.ts`,真实解析):`fixtures/fetchRuntime.sh` 的代码块树(种类、行号、层级,同原型 `SHELL_BLOCKS`,原型略去的行也在);elif / else 展平、while / for 的主体是子块、条件串和命令串;解释器(env、写死的路径)、选项(连写拆开、`-o`、`+`、`set --` 不是)、变量(local 一句几个、没值的、readonly 和顶层全大写写死的是常量)、函数(按位置的参数和名字、打印的几句、被 `$(…)` 拿去用、写了的 return);命令的词(写死的文字、有展开的没有)和重定向;同一文件里的名字(函数、赋值、local、for、read、展开,第几个参数不算);行尾 `# @Comment`。 - 语言插件(`languages/bash.test.ts`,真实解析):`fixtures/fetchRuntime.sh` 的代码块树(种类、行号、层级,同原型 `SHELL_BLOCKS`,原型略去的行也在);elif / else 展平、while / for 的主体是子块、条件串和命令串;解释器(env、写死的路径)、选项(连写拆开、`-o`、`+`、`set --` 不是)、变量(local 一句几个、没值的、readonly 和顶层全大写写死的是常量)、函数(按位置的参数和名字、打印的几句、被 `$(…)` 拿去用、写了的 return);命令的词(写死的文字、有展开的没有)和重定向;同一文件里的名字(函数、赋值、local、for、read、展开,第几个参数不算);行尾 `# @Comment`。
- 中文直译(`translators/bashZh.test.ts`,走 `readBlockViews`):`fetchRuntime.sh` 整份逐行同 `FETCH_READING`(即上面「Shell 脚本」的样例);展开(长度、去头去尾、截取、没设时、替换、特殊变量)、条件、重定向、命令规则(不认识的选项照抄、没有规则的照抄)、`&&` / `||`、遍历、`$(dirname "$0")`、常量;字符串色 / 变量色 / 常量色;规则出错照抄命令并报告。 - 中文直译(`translators/bashZh.test.ts`,走 `readBlockViews`):`fetchRuntime.sh` 整份逐行同 `FETCH_READING`(即上面「Shell 脚本」的样例);展开(长度、去头去尾、截取、没设时、替换、特殊变量)、条件、重定向、命令规则(不认识的选项照抄、没有规则的照抄)、`&&` / `||`、遍历、`$(dirname "$0")`、常量;字符串色 / 变量色 / 常量色;规则出错照抄命令并报告。
- 宿主:命令规则按语言、注册顺序给(`registry.test.ts`),shellscript 的 document 消息带命令规则读的译文、shell 的种类名、同一文件里的名字(`editor/documentMessage.test.ts`),跳到之前最近的定义、定义处算写入(`localSymbols.test.ts`)。 - 宿主:命令规则按语言、注册顺序给(`registry.test.ts`),shellscript 的 document 消息带命令规则读的译文、shell 的种类名、同一文件里的名字(`editor/documentMessage.test.ts`),跳到之前最近的定义、定义处算写入(`localSymbols.test.ts`)。
- Rust(`languages/rust.test.ts`、`rules/rustLibs.test.ts`,真实解析):`fixtures/rustLang.rs` 的导入、结构体、枚举、实现(方法挂在方法表的子行上)、函数(异步、函数体里 match 的各支)、特质(同实现)逐行同预览;函数体子块(执行器的 `device_resume`:let、let … else、if、隐式返回;if / else if let / else、match 的守卫和各支、排在最后的 if;三种循环;闭包、嵌套 fn、unsafe / async / 带标签的块、展平的 `{}`、实参里的闭包和 async 块;函数体里的注释;特质的默认方法和 impl Trait for 的方法没有可见性),调用的结构和跨几行写的调用;给结构体加一个字段,字段表那一行标成新增。`fixtures/rustComments.rs` 开头连着写的 `//` 合成一段,是文件的说明,预览是去掉 `//` 的三段 Markdown;别的注释挂到后面那一项(「注释」一行),行尾 `//` 不单独成块,`//!` 连着几行合成一段、是文件的说明,`///` 并进下一个函数当说明、普通注释同时是它的「注释」,`mod`、`impl` 身体里同一套。编译属性:Tauri `main.rs` 的 `cfg_attr` 卡片逐行(属性的着色、「非 调试构建」、「整个 crate」、windows 子系统的说明),别的文件顶层的 `allow` 是本模块、列出 lint 名,认不得的属性没有说明、不知道文件名时是所在模块,`cfg_attr` 里几个属性是一张表、套着的条件加括号,`isCrateRoot` 的几种路径。`fixtures/rustLibs.rs` 的 serde(改名、不输出、字段名改驼峰)、thiserror(展示、透传来源)、axum(方法、路径、路径参数)、sqlx、tauri 逐行同预览;函数体里 `let` 的初始值(`query!`、`query_as::<_, T>(…).bind(…)`、`let … else` 的 `query_scalar!`)和末尾的返回值(`Router` 的 `.route`、`query!`)出库卡片,「变量」一行是变量名、也是定义,卡片留着变量、返回概念,else 照常是子块;函数写法拼出来的 SQL 照翻、各个 `.bind` 依次是 `$1`、`$2`;没导入 serde 时 derive 仍是结构体;改 axum 的路径,路径那一格标成改过。`axum::routing` 这种来源算导入了 axum。 - Rust(`languages/rust.test.ts`、`rules/rustLibs.test.ts`,真实解析):`fixtures/rustLang.rs` 的导入、结构体、枚举、实现(方法挂在方法表的子行上)、函数(异步、函数体里 match 的各支)、特质(同实现)逐行同预览;函数体子块(执行器的 `device_resume`:let、let … else、if、隐式返回;if / else if let / else、match 的守卫和各支、排在最后的 if;三种循环;闭包、嵌套 fn、unsafe / async / 带标签的块、展平的 `{}`、实参里的闭包和 async 块;函数体里的注释;特质的默认方法和 impl Trait for 的方法没有可见性),调用的结构和跨几行写的调用;给结构体加一个字段,字段表那一行标成新增。`fixtures/rustComments.rs` 开头连着写的 `//` 合成一段,是文件的说明,预览是去掉 `//` 的三段 Markdown;别的注释挂到后面那一项(「注释」一行),行尾 `//` 不单独成块,`//!` 连着几行合成一段、是文件的说明,`///` 并进下一个函数当说明、普通注释同时是它的「注释」,`mod`、`impl` 身体里同一套。编译属性:Tauri `main.rs` 的 `cfg_attr` 卡片逐行(属性的着色、「非 调试构建」、「整个 crate」、windows 子系统的说明),别的文件顶层的 `allow` 是本模块、列出 lint 名,认不得的属性没有说明、不知道文件名时是所在模块,`cfg_attr` 里几个属性是一张表、套着的条件加括号,`isCrateRoot` 的几种路径。`fixtures/rustLibs.rs` 的 serde(改名、不输出、字段名改驼峰)、thiserror(展示、透传来源)、axum(方法、路径、路径参数)、sqlx、tauri 逐行同预览;函数体里 `let` 的初始值(`query!`、`query_as::<_, T>(…).bind(…)`、`let … else` 的 `query_scalar!`)和末尾的返回值(`Router` 的 `.route`、`query!`)出库卡片,「变量」一行是变量名、也是定义,卡片留着变量、返回概念,else 照常是子块;函数写法拼出来的 SQL 照翻、各个 `.bind` 依次是 `$1`、`$2`;没导入 serde 时 derive 仍是结构体;改 axum 的路径,路径那一格标成改过。`axum::routing` 这种来源算导入了 axum。链式调用(`languages/rust.test.ts`「rust 链式调用」、`rules/rustLibs.test.ts`):读链(`.await` / `?` 归前一步、注释归步骤和行尾的归上一步、起点带 `?`、取字段和一步的不算、收起来的闭包的句数和 match)、带收起来的闭包的链的块树(头部整句、子块来自各闭包、小链里的闭包),`fixtures/rustChain.rs` 的通用卡片逐行(起点、步骤、合成的 `.plugin` 表、注释、闭包框、子块挂在第几步)、单行带闭包和变量初始值、标准库中文名和悬停原名、`.await` / `?`、返回值、单行无闭包照旧、小链、按位置分列的合成表;tauri 桌面应用卡片逐行(插件表、命令名带下标、构建并运行),axum 路由器卡片列出全部路由(一个路径几个方法、nest / layer / with_state),实参里闭包、async 块里的查询和路由不再外面那句也出卡。宿主:发给页面时链里的下标、步的范围从块的开头算、子块带 `step`(`editor/pageBlocks.test.ts`),`renderedNames` 算上链里的名字(`nameResolution.test.ts`)。webview:轨道、合成的表、注释、闭包框默认收着、展开那一步画子块、小链的空心点、变量初始值下面的轨道(`BlockTree.test.tsx`),步骤的折叠 id、默认收着、标了改动的展开、`unfoldToShow`(`viewState.test.ts`),`cardTexts` 的各步、跳到链里显示的名字(`reveal.test.ts`)。
- Dockerfile: - Dockerfile:
- 语言插件(`languages/dockerfile.test.ts`,真实解析):两份 luffy 的 Dockerfile 的代码块树(同原型,后端的三行注释是阶段说明);并块(紧挨着才并,空行、注释、别的指令隔开,COPY 要从同一个地方,ADD、heredoc 的 COPY 不并,第一个 FROM 之前的是顶层);ONBUILD 和各种设置;facts(解析指令、阶段的名称 / 序号 / 说明 / 标签 / 摘要 / 平台 / 接着前面的阶段、构建参数和环境变量并块、健康检查两种写法和 NONE、启动);嵌着的 shell 的几段(续行去掉、heredoc 正文);数组写法的命令(VOLUME、SHELL 的数组不算);同一文件里的名字(阶段名在 --from、--mount 的 from、FROM 里,变量);中文名;着色。 - 语言插件(`languages/dockerfile.test.ts`,真实解析):两份 luffy 的 Dockerfile 的代码块树(同原型,后端的三行注释是阶段说明);并块(紧挨着才并,空行、注释、别的指令隔开,COPY 要从同一个地方,ADD、heredoc 的 COPY 不并,第一个 FROM 之前的是顶层);ONBUILD 和各种设置;facts(解析指令、阶段的名称 / 序号 / 说明 / 标签 / 摘要 / 平台 / 接着前面的阶段、构建参数和环境变量并块、健康检查两种写法和 NONE、启动);嵌着的 shell 的几段(续行去掉、heredoc 正文);数组写法的命令(VOLUME、SHELL 的数组不算);同一文件里的名字(阶段名在 --from、--mount 的 from、FROM 里,变量);中文名;着色。
- 中文直译(`translators/dockerfileZh.test.ts`,走 `readBlockViews`,RUN 交给 bash 的插件):两份 luffy 的 Dockerfile 整份逐行同 `NEXT_READING`、`BACKEND_READING`;阶段的各种写法、变量的展开和注解、RUN 的选项 / 数组写法 / heredoc / 一条循环 / 带重定向的一串、没有 shell 插件时照抄、复制和 ADD、设置、健康检查、启动;阶段名和表里变量名的源码下标、RUN 的源码按 shell 着色。 - 中文直译(`translators/dockerfileZh.test.ts`,走 `readBlockViews`,RUN 交给 bash 的插件):两份 luffy 的 Dockerfile 整份逐行同 `NEXT_READING`、`BACKEND_READING`;阶段的各种写法、变量的展开和注解、RUN 的选项 / 数组写法 / heredoc / 一条循环 / 带重定向的一串、没有 shell 插件时照抄、复制和 ADD、设置、健康检查、启动;阶段名和表里变量名的源码下标、RUN 的源码按 shell 着色。