📝 docs(code-reader): 规格补上定义卡片带出那块问过 AI 的问答

This commit is contained in:
cruldra committed 2026-10-15 19:59:51 +11:00
1 parent b99659ea68
commit 3240da45dc
1 file changed
+8 -2
+8 -2
View File
@@ -549,6 +549,12 @@
- 中文名:同一文件的带上这个版本眼下已知的;别的文件只认起了中文名的定义本身(定义处标 `definition`,后面淡淡写原名),用到它们的各处要问语言扩展,浮窗不等。都只带卡片上画出来的名字(`namesOnCard`)。
- 样子(`DefinitionPeekPopup.tsx`):portal 到页面根上的浮窗,外框用 VS Code 悬停框的边框、底色、阴影(`--vscode-editorHoverWidget-*`);标题一行「相对路径:行号」(路径从工作区文件夹算起,同挑选框),垫悬停框状态栏的底色、链接色,点了跳到定义(名字的同 ⌘ / Ctrl + 点击,发 `goToDefinition`;链接的同点链接,发 `openRepoLink`),浮窗跟着收。下面是卡片,卡片区最宽 640px、最高 420px,再大在里面滚。默认放在名字下方、左边对齐名字;下方放不下、上方空间更大就放上方,底边贴着名字往上长(卡片展开时不盖住名字);宽高再限到那边剩下的空间,钳在视口内。层级低于悬停提示,浮窗里名字的提示照样盖在它上面。
- 卡片只读:同页面上那张卡片(类、函数默认收起子块,能在浮窗里折叠展开,只记在浮窗里),块树不带编辑那部分(`BlockTreeState.edit`),没有编辑、问 AI、重写注释的按钮,不标差异、不筛选。浮窗里的名字下标是那个文件的,页面上管名字的几处都不认它们(浮窗根上标 `data-peek`):不按 ⌘ / Ctrl 变链接、不能跳,单击不高亮也不清页面上的高亮,不画页面上的高亮,不再弹卡片;注释里的仓库路径链接、不带路径的引用照样能点(引用按卡片那份文件找,见「注释的 Markdown 排版」),悬停不弹卡片。
- 问过 AI:卡片那块自己下面问过 AI 的带在卡片底下一节「问过 AI(N)」,所有语言、所有定义卡片都有(本文件的定义、工作区里别的文件、工作区外的库源码)。
- 范围:只带那块自己的问答(同一个块记号下面的那些),子块上问的不带。
- 对应规则(扩展端 `peekCard`):按「卡片那份文件 + 那块的块记号」精确对应,数据就是那块下面的对话那一份(`.spx/code-qa.json`,记在哪见「问 AI」:工作区外的库文件记在第一个工作区文件夹,键是 `~/…` 或绝对路径)。块记号是那块在它自己那份文件的块树里的 `anchor`:卡片的块和那个文件自己的预览用同一套视图数据(`BlockAnchors`)算出,同那个文件的预览挂对话用的。从内存里的问答表取(`CodeQa.blockThreads`,同页面上块下面画的那份),不等别的;带的图片换成页面能用的地址。cargo 库换了版本、路径变了就对不上,不另找。问答写进去后卡片不实时刷新,下次悬停重新取。
- 样子(`AskThread.tsx` 的 `AskedList`):同块下面的问答区(左边一条竖线、灰字),标题一行「问过 AI(N)」,下面按那块下面对话的先后(按时间)只列问题,回答收着;点一条展开 / 收起它的回答,回答同对话页(Markdown 排版、带的图片缩略图,点缩略图看大图)。大图画在浮窗里,看图时浮窗不收。跟卡片一起在卡片区里滚。没有问答就没有这一节。
- 只读:不能接着问、不能删,也没有「去那里接着问」的入口。
- 页面装好之前就放行各工作区文件夹的 `.spx/code-qa/`(`CodeQa.imageRoots`),别的工作区文件夹里的文件的问答图片也画得出。
- 按住 ⌘ / Ctrl 变链接、⌘ / Ctrl + 点击跳转、单击高亮各处出现都照旧;在浮窗外按下鼠标(单击名字、⌘ + 点击)先收起浮窗。
### 钉住卡片(Sticky Scroll)
@@ -2117,7 +2123,7 @@ type BlockView = BlockViewBase & ({ translation: PreviewText, items?: PropertyIt
- `{ type: 'document', version, languageId, blocks: BlockView[], attributes: FileAttribute[], translators: { id, label }[], translatorId, error?: string, reveal?: Reveal, names: ShownName[] }`,文档每次变化(防抖 150ms)重发。`names` 是这个版本眼下已知的中文名(`{ offset, length, name, definition? }`:源码下标 [offset, offset + length) 的名字显示成 name,definition 是定义处本身),见「中文名」。`attributes` 是这份文件里出现过的筛选属性,按筛选栏的先后排:`{ id, name, values: { id, name, count }[] }`,名字取翻译插件的 `attributeNames`,没有的用 id。`reveal = { line, definition? }` 只随新预览的第一份文档走:从文本编辑器切过来时是它顶部那一行(滚到包含这行的块、顶到顶部,折叠的不展开);跳到定义时还带 `definition`(定义处名字在源码里的下标),按「跳到定义」一节展开、滚动、闪。
- `{ type: 'reveal', line, definition? }`:同上,发给已经开着的预览。页面正在重新加载(标签页切回来)时收不到,扩展端改成随它 `ready` 后的第一份文档带过去。
- `{ type: 'definitionProbed', id, found }`:回答第 `id` 次 `probeDefinition`。
- `{ type: 'definitionPeeked', id, peek? }`:回答第 `id` 次 `peekDefinition` / `peekLink`。`peek` 是 `{ path, line, block: BlockView, names: ShownName[] }`:定义所在的文件(从工作区文件夹算起)、定义处那一行(0 起)、那块卡片连同子块、卡片上显示成中文名的名字(下标是那个文件的);没有卡片时不带。见「悬停看定义卡片」。
- `{ type: 'definitionPeeked', id, peek? }`:回答第 `id` 次 `peekDefinition` / `peekLink`。`peek` 是 `{ path, uri, line, block: BlockView, names: ShownName[], qa?: QaEntryView[] }`:定义所在的文件(从工作区文件夹算起)和这份文件本身、定义处那一行(0 起)、那块卡片连同子块、卡片上显示成中文名的名字(下标是那个文件的)、那块自己下面问过 AI 的各次(按时间先后,没问过时不带);没有卡片时不带。见「悬停看定义卡片」。
- `{ type: 'hoverDelay', delay, hidingDelay }`:VS Code 的 `editor.hover.delay` / `editor.hover.hidingDelay`(毫秒,按这份文件读),`ready` 后发一次,设置改了再发。
- `{ type: 'stickyScroll', enabled, maxLineCount }`:VS Code 的 `editor.stickyScroll.enabled` / `editor.stickyScroll.maxLineCount`(按这份文件读,语言自己的设置优先),`ready` 后发一次,设置改了再发;见「钉住卡片」。
- `{ type: 'occurrencesFound', id, occurrences: { start, end, kind: 'text' | 'read' | 'write' }[] }`:回答第 `id` 次 `findOccurrences`,`[start, end)` 是源码下标,`kind` 同 `DocumentHighlightKind`;语言扩展没答就是空数组。
@@ -2321,7 +2327,7 @@ vscode/webview-ui/code-reader.html + src/codeReader/ 预览界面(React,Vit
- 重写注释(`commentRewrite.test.ts`、`qa/claudeAsk.test.ts`):发给模型的就是 `/ecc:writing-code-comments 路径:起-止` 一句;读结构化结果(正文逐字长出来、读文件是在做的事、只回一段话没有正文、报错);命令行在只读那套后面加 `--json-schema`、stdin 里只有那一句;交回结构化正文 → 已有说明换说明(Python docstring 填回三引号、JSDoc 填回 `/** */`,不在声明上面再插一行)、只有前面的普通注释时换掉那几段(套回 `#` 和缩进)、文件开头的说明换它自己、说明和普通注释都有时只换说明;都没有时 Python 函数在主体里插 docstring、TypeScript 在声明上面插 `/** */`、Rust 在项上面插 `///`、只有行注释的语言仍插在块上面;没交回正文、出错、重写期间代码变了 → 失败不写,叫停 → 不写;套回壳的几种写法(三引号、`#`、`/** */`、`//`、`///`)。
- 注释的 Markdown:「注释」一行、文件开头的说明、函数和类「说明」的视图数据是 `{ markdown }`,原文照抄(reST 角色、双反引号、`{@link}`、HTML 都不转换,块标签拆出去),行注释连成的块留得住缩进四格的代码块;渲染时 HTML 当文字、带协议的网址和邮箱成链接、不带协议的文件名不成链接,`javascript:` / `command:` / `./` / `..` / 绝对路径的链接和 http 图片不渲染,仓库内图片按原图比例显示,点了打开原图,没有就写「找不到图片」,仓库路径链接能点、点了打开文件并跳到符号;跳到定义不认 Markdown 里的名字。不带路径的引用:行内规则(`webview-ui/.../markdown.test.ts`:`[Name]`、`[A.b]` 是 `symbol:` 链接,`` `[x]` ``、`items[i]`、`[会话进展]`、`[名字](路径)`、`[Agent](javascript:x)` 各自的结果,问 AI 的回答不认、带增删的注释照样认);问答(`repoLink.test.ts`:`symbol:` 地址只认标识符、点了发不带 `path` 的 `openRepoLink`、和仓库路径一起问、找不到的标坏、打开成功不再标、语言自带的名字当普通文字且点了不发、点了才知道是语言自带的也改当普通文字、同样的链接不再问、文档换了版本再问);扩展端(`symbolLinks.test.ts`:本文件优先于导入且不问语言扩展、本文件的 `Class.member`、类有成员没有就是找不到、导入的名字问定义再在那个类底下找成员、整模块导入从顶层找、找不到;代码里用到的语言自带的名字先挑用在说明的那个声明里的那处问定义、`Class.member` 在定义所在文件里找成员、没写到的语言自带的名字是 `builtin`、语言扩展答不上的也是;Python / TypeScript 代码里用到的本文件没定义的名字不含注释、字符串、属性名里的;两门语言自带的名字;Python / TypeScript 各种导入写法引进来的名字和问定义的位置,`gate.py` 的导入)。
- 行替换:多行块替换后缩进正确。
- 跳到定义:TS / Python 译文和属性表里的名字、点分模块名每一节、模块字符串带下标且指回源码原文,关键字、运算符、说明词不带(前面有中文注释也对得上);查到的定义 → 不动 / 原地 / 别的文件 / 挑选框,别的文件用哪种编辑器(`editor/openTarget.test.ts`:有代码阅读的用预览、带位置时滚到那一行闪定义处,没有的用默认的打开方式选中名字,打不开成文本的用默认的打开方式);webview 里按下标找目标块、要展开的祖先块和属性行,滚动位置。悬停看定义卡片:取哪块(`editor/definitionPeek.test.ts`:Python 源码走完整的语言插件 + 翻译插件,类名 → 类那块连同子块,参数 → 所在的函数,变量 → 变量那块,块外面 → 没有,挂在子行上的子块去掉 `slot`;卡片上的中文名只带画出来的、长度对得上的,别的文件只认定义本身),什么时候弹、收(`definitionPeek.test.ts`:停够延迟才问、没到时间移开不问、没有卡片不弹、迟到的回答丢掉、链接问 `peekLink` 点标题发 `openRepoLink`、没收到延迟不弹、移开过 `hidingDelay` 才收、移进浮窗不收、扫过别的名字不往后推、浮窗里不弹别的、换成新名字的卡片、Esc / 滚动后不再弹、换文档版本收起;指到符号的链接才弹;放在下方 / 上方 / 空间大的那边、钳在视口内),只读的卡片(`DefinitionPeekPopup.test.tsx`:类收起子块、没有编辑 / 问 AI / 重写按钮、中文名用卡片带的、引用不成链接;`markdown.test.ts` 的 `peek`)。闪哪一处(TS、Python 源码走完整的语言插件 + 翻译插件 + 视图数据):参数 → 它那个子行,导入项 → 它那一项,多变量声明里的一个 → 它的名称行,类的泛型参数 → 「类型参数」那一行,函数名 / 类名 / 单个变量名(含解构模式)→ 整块,循环变量 → 所在的块,翻译插件没填 `defines` → 整块(照样展开属性行);翻译插件给参数、导入项、声明的变量、泛型参数标的范围指回源码原文;块自己的名字只有函数、类和单变量声明有。
- 跳到定义:TS / Python 译文和属性表里的名字、点分模块名每一节、模块字符串带下标且指回源码原文,关键字、运算符、说明词不带(前面有中文注释也对得上);查到的定义 → 不动 / 原地 / 别的文件 / 挑选框,别的文件用哪种编辑器(`editor/openTarget.test.ts`:有代码阅读的用预览、带位置时滚到那一行闪定义处,没有的用默认的打开方式选中名字,打不开成文本的用默认的打开方式);webview 里按下标找目标块、要展开的祖先块和属性行,滚动位置。悬停看定义卡片:取哪块(`editor/definitionPeek.test.ts`:Python 源码走完整的语言插件 + 翻译插件,类名 → 类那块连同子块,参数 → 所在的函数,变量 → 变量那块,块外面 → 没有,挂在子行上的子块去掉 `slot`;卡片上的中文名只带画出来的、长度对得上的,别的文件只认定义本身),什么时候弹、收(`definitionPeek.test.ts`:停够延迟才问、没到时间移开不问、没有卡片不弹、迟到的回答丢掉、链接问 `peekLink` 点标题发 `openRepoLink`、没收到延迟不弹、移开过 `hidingDelay` 才收、移进浮窗不收、扫过别的名字不往后推、浮窗里不弹别的、换成新名字的卡片、Esc / 滚动后不再弹、换文档版本收起;指到符号的链接才弹;放在下方 / 上方 / 空间大的那边、钳在视口内),只读的卡片(`DefinitionPeekPopup.test.tsx`:类收起子块、没有编辑 / 问 AI / 重写按钮、中文名用卡片带的、引用不成链接;`markdown.test.ts` 的 `peek`),卡片带的问过 AI(`editor/previewEditor.test.ts`:本文件、别的文件、工作区外的库源码都按卡片那份文件和那块的记号带上,图片换成页面地址,子块上问的不带,没问过不带 `qa`;`qa/codeQa.test.ts`:放行各工作区文件夹的图片目录;`DefinitionPeekPopup.test.tsx`:「问过 AI(N)」只列问题、点开显示 Markdown 回答和图片、再点收起、大图画在浮窗里、没问过没有这一节)。闪哪一处(TS、Python 源码走完整的语言插件 + 翻译插件 + 视图数据):参数 → 它那个子行,导入项 → 它那一项,多变量声明里的一个 → 它的名称行,类的泛型参数 → 「类型参数」那一行,函数名 / 类名 / 单个变量名(含解构模式)→ 整块,循环变量 → 所在的块,翻译插件没填 `defines` → 整块(照样展开属性行);翻译插件给参数、导入项、声明的变量、泛型参数标的范围指回源码原文;块自己的名字只有函数、类和单变量声明有。
- 高亮各处出现:段的源码范围和出现重叠才亮、边界相接不算、没下标的不亮,讲别处名字的段(`refers`)按那个名字算、自己照抄的位置不算(`occurrences.test.ts` 的 `sourceOf`),点分模块名每一节各按自己的范围认(真实的 Python 译文和属性表:定义处按写入、用到处按读取);写入 → 强高亮色,读取、按文字 → 普通高亮色,同时碰上按写入;单击名字问、点空白处清、点按钮 / 链接 / 筛选栏不动、名字在按钮里照样问,拖选、双击第二下、带修饰键的点击不动,⌘ / Ctrl + 点击照旧发跳到定义、不问出现处;回答连同名字显示、空回答不亮、换名字时回答到前旧的留着、迟到的回答丢掉、答过「没有」再点照样再问、清掉后才到的回答丢掉、换文档版本或翻译清掉而同版本同翻译重发不清、没有文档时不问。键盘跳(`occurrences.test.ts`、`reveal.test.ts`、`editor/occurrenceNavigation.test.ts`):回答照源码先后排、点中的那处是当前那一处、「2/5」和「N 处」;往后 / 往前、到头接着跳,找不到的跳过、总数照旧、一处都找不到不动,点中的不在回答里从点中的地方数起;只有当前那一处描框;能不能跳(高亮、焦点、输入框)第一次必报、之后变了才报;页面上找第一处显示着它的地方、要展开的块 / 属性行 / 子行、跳过筛掉 / 编辑 / 盖住的块、Markdown 不算;`package.json` 的两条命令、默认键、`when`、命令面板,扩展和页面的代码里不写键、不拦键,上下文键有一个预览能跳就真、变了才设,命令发给能跳的预览、没有就发给活动的;按键那一刻的位置跳转时回一次、隔太久 / 点过鼠标 / 没按过键不回,跳完守住跳到的位置、过了 `KEY_SCROLL_MS` 或又按键、点鼠标不守。
- 钉住卡片(`stickyScroll.test.ts`、`StickyLines.test.tsx`、`BlockTree.test.tsx`):没有子块的高卡片(折叠着的函数)名称那行滚到后面、下面还看得见就钉,滚完时被顶上去;上沿刚滚过它那一行才钉、里层按自己那一行算,外层在上里层在下,同层前一张滚完、后一张还没到只钉外层;子块快滚完时最里那行被顶上去、正好到行顶时整行顶到上一行下面,最后一张子块同时是外层的结尾时里层先走、再顶外层;比上限深时留外层的;最多行数按设置和可视区域的四分之一;滚到顶上时上面钉着多高;钉的没变不重画。一行里是概念图标和标题:属性表第一行的值(中文名照换、不带属性名、不带说明)、一行译文、Markdown 只取第一行、空属性表只有图标。画出来的子层记着它是哪张卡片的,收着时没有。
- 中文名: