From 926984519375551637ef99101fc06e788ae53a10 Mon Sep 17 00:00:00 2001 From: cruldra Date: Thu, 15 Oct 2026 17:07:07 +1100 Subject: [PATCH] =?UTF-8?q?=F0=9F=93=9D=20docs(code-reader):=20=E8=A7=84?= =?UTF-8?q?=E6=A0=BC=E8=A1=A5=E4=B8=8A=20Rust=20=E5=87=BD=E6=95=B0?= =?UTF-8?q?=E4=BD=93=E6=8B=86=E5=9D=97=E3=80=81=E7=89=B9=E8=B4=A8=E6=96=B9?= =?UTF-8?q?=E6=B3=95=E5=8D=A1=E5=92=8C=E8=B0=83=E7=94=A8=E7=BB=93=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/superpowers/specs/code-reader/spec.md | 28 ++++++++++++++-------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/docs/superpowers/specs/code-reader/spec.md b/docs/superpowers/specs/code-reader/spec.md index 30270f1..effb908 100644 --- a/docs/superpowers/specs/code-reader/spec.md +++ b/docs/superpowers/specs/code-reader/spec.md @@ -181,7 +181,7 @@ | health 健康检查 | `activity` | start 启动 | `play` | trait 特质 | `network` | | impl 实现 | `square-function` | module 模块 | `layers` | attribute 编译属性 | `sliders-horizontal` | - 库规则的种类用规则给的图标(`KindBadge.icon`),跟在语言的种类图标后面:SQLAlchemy 数据表 `database`、数据类 `package`、Pydantic 数据模型 `braces`(和类型块同一个图标,颜色不同)、Celery 应用 `server-cog`、定时任务 `calendar-clock`、FastAPI 接口 `globe`、FastAPI 路由器 `network`、React 组件 `atom`、状态 `toggle-right`、引用 `anchor`、数据源 `download`、派生值 `sigma`、副作用 `zap`、事件处理函数 `mouse-pointer-click`、渲染输出 `layout-template`、serde 可序列化 `braces`、thiserror 错误 `triangle-alert`、axum 接口 `globe`、sqlx 查询 `database`、tauri 桌面命令 `square-function`。数据类写了 `frozen=True` 再加一把锁(`lock`,悬停「不可修改」)。实现块再由规则 `rust.impl` 换成卡片,左边因此有两个「实现」图标。 + 库规则的种类用规则给的图标(`KindBadge.icon`),跟在语言的种类图标后面:SQLAlchemy 数据表 `database`、数据类 `package`、Pydantic 数据模型 `braces`(和类型块同一个图标,颜色不同)、Celery 应用 `server-cog`、定时任务 `calendar-clock`、FastAPI 接口 `globe`、FastAPI 路由器 `network`、React 组件 `atom`、状态 `toggle-right`、引用 `anchor`、数据源 `download`、派生值 `sigma`、副作用 `zap`、事件处理函数 `mouse-pointer-click`、渲染输出 `layout-template`、serde 可序列化 `braces`、thiserror 错误 `triangle-alert`、axum 接口 `globe`、sqlx 查询 `database`、tauri 桌面命令 `square-function`。数据类写了 `frozen=True` 再加一把锁(`lock`,悬停「不可修改」)。实现块、特质块再由规则 `rust.impl`、`rust.trait` 换成卡片,左边因此有两个「实现」「特质」图标。 这组图标由插件自己定义,是一个封闭的集合:契约里的 `KIND_ICON_NAMES`(上表 26 个——命令、管道、执行共用一个,解释器、解析指令共用一个,选项、设置、编译属性共用一个,字段、标签共用一个——加库规则用的 14 个(React 的组件、状态、引用、数据源、派生值、副作用、事件处理函数、渲染输出的 8 个也在里面),lucide 的 kebab-case 名字),类型 `KindIconName` 是它们的联合,概念的 `icon` 只能写其中一个,写别的是类型错误。内置种类 → 图标名在 `contract.ts` 的 `KIND_ICONS`(宿主写进概念列表)。webview 给每个名字配一个逐个 import 的 lucide 图标组件(`kindIcons.tsx` 的 `KIND_ICON_COMPONENTS`,打包只带这些,预览脚本约 157 kB);webview 的 `KindIconName` 照契约手抄,`kindIconNames.test.ts` 核对两边一样。规则要新图标就把名字加进这组、在 webview 配上图标,没有按任意名字找图标的路。 - 右上角的图标按钮(原型组件 `Reader / BlockTools`,普通块、属性表块、库规则的卡片共用):只有图标、不带字,名字写在悬停提示和 `aria-label` 里;整排是 `role="group"`(`aria-label="块操作"`)。最前面是「按注释规范重写」(注释图标,块还没有注释时叫「按注释规范写注释」,重写过、记录收着时叫「展开重写记录」;不能写注释的块没有,见「重写注释」),然后是「问 AI」(sparkles 图标,点开 / 收起块下面的问答区,展开时带按下的底色、`aria-expanded`;文件不在工作区文件夹里时没有,见「问 AI」),再是「编辑 / 预览」切换:预览时铅笔「编辑」,编辑时眼睛「预览」、带按下的底色(`--vscode-toolbar-activeBackground`)。按钮宽 24px、高 20px(和种类图标同高),图标 14px、`descriptionForeground` 色;悬停 `--vscode-toolbar-hoverBackground`,键盘聚焦描 1px `--vscode-focusBorder`;Tab 能走到,回车 / 空格切换。 @@ -1956,9 +1956,9 @@ shell 脚本大半是一条条命令,一条命令读成什么取决于命令 可见性:`pub` 公开,没写是本模块,`pub(super)` 父模块,`pub(crate)` 和 `pub(in …)` 本 crate。公开写在 `facts.access`,其余写在块的 `access` 属性上(筛选值 `module` / `super` / `crate`)。说明是紧挨在前面的文档注释(`///`、`/**`)正文的第一句,句号留着;连着几行的 `///` 算一段(`facts.doc` 是第一条,中文直译的 `docNodes` 往下连),中间可以隔着 `#[…]`。卡片(含 Rust 库规则的)都经翻译插件的 `doc`(规则经 `context.doc`)读说明,块标签拆开放:函数的 `@param` 进参数表的「说明」列、`@return` 跟在「返回」后面、`@throws` 成「异常」表,结构体的 `@param` 对到字段表的「说明」列,对不上的列成「对不上的参数」。 -注释和别的语言走同一条路(`listBlocks`,Rust 的 `CommentRules` 在 `languages/rust.ts`),文件顶层、`mod` 身体、`impl` 身体都一样: +注释和别的语言走同一条路(`listBlocks`,Rust 的 `CommentRules` 在 `languages/rust.ts`),文件顶层、`mod` 身体、`trait` / `impl` 身体、函数体(含条件、match、循环里的各层)都一样: -- 连续的行注释合成一段注释:相邻行、写法相同才合,`//`、讲所在模块或 crate 的 `//!`、讲下一项的 `///` 各是一种写法,不混着合。中间空的 `//` 不打断,是 Markdown 里的空行、分段;隔着空行、隔着别的语句就断开。合好的注释挂到它讲的项上(见「注释挂到它讲的块上」);`//!` 写在文件开头是文件的说明,写在 `mod` 身体里交给那个模块。函数体不拆,函数体里的注释留在函数的源码里。 +- 连续的行注释合成一段注释:相邻行、写法相同才合,`//`、讲所在模块或 crate 的 `//!`、讲下一项的 `///` 各是一种写法,不混着合。中间空的 `//` 不打断,是 Markdown 里的空行、分段;隔着空行、隔着别的语句就断开。合好的注释挂到它讲的项上(见「注释挂到它讲的块上」);`//!` 写在文件开头是文件的说明,写在 `mod` 身体里交给那个模块。 - 和上一条语句同一行的 `//` 是行尾注释,不单独成块。 - `///`(和 `/**` 开头的块注释)后面紧跟的是函数、结构体、枚举、特质、实现、模块、常量、`static` 时,是这一项的说明:进 `facts.doc`(第一条注释节点),头部往上延到它开头;后面是 `use`、宏调用、`let` 这类不带说明的项,或隔着别的注释时,是普通注释,挂到它讲的项上。 - 注释的预览(「注释」一行、文件开头的说明)是去掉 `//`(`///`、`//!` 连那个 `/`、`!`)和后面一个空格的原文,按「注释的 Markdown 排版」显示。语法包把 `///`、`//!` 行尾的换行算进注释节点,块的范围不算这个换行。 @@ -1966,8 +1966,16 @@ shell 脚本大半是一条条命令,一条命令读成什么取决于命令 - `use` → import。来源是路径去掉最后一节(`std::sync::Arc` 的来源是 `std::sync`)。导入项表「名字 | 别名」,没起别名是「—」,`*` 是「*」。 - `struct` → class(中文直译把这个种类叫「结构体」)。字段不单独成块,表「字段 | 类型 | 可见性」。元组结构体没有这张表。 - `enum` → enum。变体表「变体 | 携带的数据」:没带数据是「—」,`Failed(String)` 写类型,`Running { pid: u32 }` 写字段原文。 -- `fn` → function。有才显示:说明、异步(只有 `async fn` 写「是」)、可见性、输入参数表「名称 | 类型」、返回(没写是 `()`)。函数体里直接写的 `match` 收成「分情况」表「分支 | 做什么」,N 支:优先用这一支里的注释,否则是 `return` 那句或这一支的第一句,不展开成子块。 -- `trait` → trait(图标 `network`,颜色同声明关键字的蓝)。方法表「名称 | 参数 | 返回」,只列签名,不展开函数体。 +- `fn` → function。有才显示:说明、异步(只有 `async fn` 写「是」)、可见性(特质里、`impl Trait for Type` 里的方法跟着特质,没有这一行)、输入参数表「名称 | 类型」、返回(没写是 `()`)。函数体各句是子块(自由函数、`impl` / `trait` 里的方法、嵌套的 `fn`、闭包都拆),同 Python / TypeScript 的函数: + - `let` → variable(名称是模式,`let Some(x) = …` 就是 `Some(x)`);`let … else { … }` 的 else 照 if / else 的写法成一块 else,是这个变量块唯一的子块(节点仍是整条 `let`,头部只有 else 这个词)。值是主体写成 `{}` 的闭包时是 function(名称是变量的模式,没有可见性,写了返回类型才有「返回」),主体不是 `{}` 的闭包照旧是 variable,同 TypeScript 的箭头函数。 + - `if` / `if let` 和 `else if` / `else` 展平成兄弟块 if / else,同 TypeScript;`match` 一块 if、每一支一块 if,同 Python 的 match / case、TypeScript 的 switch / case,一支的头部是模式和守卫(到 `=>` 之前),子块来自 `=>` 后面的值(`{}` 里的各句,不是 `{}` 时这个值本身一块)。 + - `loop` / `while` / `while let` / `for` → loop;`return` → return;`break`、`continue`、调用、宏调用、`?`、赋值这些表达式语句 → statement。 + - 隐式返回值:函数体、闭包体、async 块最后那个不带分号的式子是 return,译文前面补「返回」;排在最后的 if / match / `{}` / `unsafe {}` 自己不是 return,照控制流拆,把「最后那个式子是返回值」传给各支;循环体、`let … else` 的 else 里不传。 + - `unsafe {}`、`async {}`、带标签的 `'a: {}` → 带子块的 statement,头部是 `unsafe` / `async move` / 标签;前面什么都没写的 `{}` 同 TypeScript 展平成各句。 + - 表达式语句、`let` 的值带着闭包、async 块时(值本身,或调用的实参里第一个:`tokio::spawn(async move { … })`、`.for_each(|x| { … })`,`.await`、`?` 看里面的调用),同 TypeScript 的回调,这句照常一行,子块来自那个 `{}`。 + - 块里写的项(嵌套的 `fn`、`struct`、`use`、`const`……)跟文件顶层同一条路;注释同上面几条。 + - 调用(`LanguageAdapter.call`):`call_expression` 的被调用者和实参(都是按位置传的),名字取路径、方法、泛型函数的最后一节;`Some(x)` 这类写法和调用一样,不给 construct;宏调用不算。跨几行写的调用同别的语言排成「调用 … · N 个参数」加实参表。 +- `trait` → trait(图标 `network`,颜色同声明关键字的蓝)。同 `impl`:身体里的各项是子块,规则 `rules/rustImpl.ts`(种类 `rust.trait`,徽章「特质」暗 #569cd6 / 亮 #0000ff)把每张方法卡挂在方法表「名称 | 参数 | 返回」讲它的那个子行上,带默认实现的方法展开后有函数体子块。 - `impl` → impl(图标 `square-function`,颜色同函数)。标题是「某类型 的方法」(`impl Trait for Type` 取 Type)。方法是子块。不看导入的规则 `rules/rustImpl.ts`(`libraries: []`,种类 `rust.impl`)把每张方法卡挂在方法表讲它的那个子行上(`RuleSlot`),点方法名展开。方法卡的参数表叫「参数」。身体里的 `const`、`static` 不收成语句,跟文件顶层同一条路(见下)。 - `mod 名字 { … }`(`mod_item` 有 `body`)→ module(中文「模块」,图标 `layers`,颜色同阶段)。卡片行:名称、说明(有文档注释才有)、可见性(没写也是本模块,跟结构体一样总有这一行)。身体用和文件顶层同一套规则拆成子块,排在这张卡片下面,不另做一张表把子块塞进某一行。模块自己的文档注释留在模块卡片上,身体里每项自己的文档注释留在那一项上。`mod 名字;` 没有身体,不拆,仍是一条 statement。 - `const`(`const_item`)→ const,`static`(`static_item`)→ variable。属性表不另写一套译文,走中文模板里常量 / 变量那一套:名称、说明、访问级别(公开才有,模板里叫「公共」)、类型、值(`static` 的值叫「初始值」)。文件顶层、模块身体、impl 身体同一条路。 @@ -1978,7 +1986,7 @@ shell 脚本大半是一条条命令,一条命令读成什么取决于命令 - 作用范围(按 keyword 着色):写在文件顶层时,crate 根文件是「整个 crate」,别的文件是「本模块」,宿主没给文件名(`SourceDocument.fileName`)时是「所在模块」;写在 `mod` 身体里是「本模块」,`impl` 身体里是「本 impl 块」。crate 根文件按 Cargo 默认的认法(`rules/rustTree.ts` 的 `isCrateRoot`):`main.rs`、`lib.rs`,`src/bin/` 下的 `.rs`,包根下 `examples/`、`tests/`、`benches/` 里直接放的 `.rs`(`src/` 下同名目录里的是模块)。 - 说明(按 comment 着色,列出的名字按 variable):认得的属性才有。`windows_subsystem = "windows"`「在 Windows 上编译为图形界面程序(windows 子系统),启动时不弹出控制台窗口」,`= "console"`「在 Windows 上编译为控制台程序(console 子系统),启动时打开控制台窗口」;`allow` / `warn` / `deny` / `forbid`「编译检查(lint)级别设为放行 / 警告 / 报错 / 强制报错(内层不能再放宽):」后面列括号里的各项;`feature`「启用实验特性(需 nightly 编译器):」后面列名字;`no_std`「不链接标准库 std,只使用核心库 core」;`no_main`「不使用标准的 main 入口函数,程序入口另行提供」;`recursion_limit = "N"`「宏展开等编译期递归的深度上限设为 N(默认 128)」。 - 挂在函数、结构体上的外部属性 `#[…]` 不变:算进那一项的头部,`derive`、库规则照旧。 -- 其余(`let`、宏调用)→ statement。不拆函数体。模块身体里宏调用后面多出来的那个空 `;`(`empty_statement`)不成块。 +- 文件顶层、模块身体里的其余(`let`、宏调用)→ statement。模块身体里宏调用后面多出来的那个空 `;`(`empty_statement`)不成块。 ### 属性表信息(facts)从哪来 @@ -1994,7 +2002,7 @@ shell 脚本大半是一条条命令,一条命令读成什么取决于命令 - Shell:解释器取 `#!` 后面的整句,第一个词是 `env` 的是按 PATH 找、程序名是它后面那个词,否则是写死的路径、程序名是路径最后一节。选项:每个开关一项,单字母换成 bash 的长名字(e → errexit、u → nounset、x → xtrace……),`-o 名字` 照写,`-` 开、`+` 关。变量:`variable_assignment` 的 name / value,声明里没给值的只有 name。函数:name 是函数名,doc 是紧贴在上面的注释;`positional` 是主体里(不进嵌套的函数)用到的 `$N` / `${N}` / `${N:-…}`,照位置排,`local x="$N"`、`x=$N` 给它起名字;`prints` 是没重定向到别处的 `echo` / `printf`(进 if、循环、分情况,不进 `$(…)`、管道、嵌套的函数);`captured` 看同一文件里有没有 `$(函数名 …)`;`returns` 是主体里的 `return` 命令。 - Dockerfile:解析指令是每行注释 `# 名字=值` 的名字(小写)和值;阶段取 `image_spec` 的 name / tag / digest 字段、`as` 字段(image_alias),stage 看镜像名是不是前面某个阶段的名字(不分大小写),选项是 `param`、`mount_param` 节点的原文 `--名字=值`(值在语法树里没有单独的节点,按原文拆,记下值从哪开始);变量是 `env_pair` 的 name / value、`arg_instruction` 的 name / default;健康检查的 none 看有没有 NONE,检查命令是里面的 `cmd_instruction`;数组写法取 `json_string_array`,shell 写法取 `shell_command` 里各个 `shell_fragment`(`line_continuation` 不算),只有一个 `<