✨ feat(vscode): 代码阅读卡片横排多个概念图标
This commit is contained in:
1 parent
11fcbef225
commit
394cd2fc1c
19 files changed
+328
-99
No files matched your search
@@ -18,7 +18,7 @@
|
||||
| 扩展方式 | 写代码注册:语言插件、翻译插件都实现约定接口,通过本插件 `activate()` 导出的 API 注册;内置实现也走同一个 API |
|
||||
| 多种翻译怎么选 | 预览顶部筛选栏最右边的下拉框,整个文件一起换,按语言记住选择;只有一种时不显示 |
|
||||
| 块筛选 | 预览顶部钉住一条筛选栏,按块的属性(种类、访问级别、异步……)筛;属性由语言插件按和语言无关的 id 报(通用的由宿主从 facts 推),名字由翻译插件起,webview 不认识任何语言;筛选整个工作区共用、记住 |
|
||||
| 块的种类 | 块左边只画种类图标(插件自己定义的一组 lucide 图标里的一个,和一行字等高,种类色),种类名是鼠标停上去的提示和读屏念的文字,不再写字;内置种类的图标、颜色、名字由插件定(图标在 webview 一处、颜色在 CSS、名字由翻译插件起),库规则的种类由规则给(`KindBadge` 的名字、颜色、图标)。见「预览(代码块树)」 |
|
||||
| 块的种类 | 块左边横排这块认出来的概念图标(各 20px,间距紧)。默认是语言的种类(类、函数……):图标名由宿主按内置种类写进预览数据,名字由翻译插件起,颜色在 CSS;语言插件可以再声明概念,认到才出现。库规则认领时语言的概念留着,规则的种类追加在后面,规则还可以再带认出的概念。悬停各自的名字,读屏把名字连起来念。筛选的种类、卡片边框色仍是规则的种类。同一个概念 id 只留第一个。webview 只按图标名画。见「预览(代码块树)」 |
|
||||
| 侧栏点文件 | 支持的语言默认打开成「预览」;不支持的语言用普通编辑器打开 |
|
||||
| 块内修改 | 改的就是文件本身:未保存标记、⌘S 保存、⌘Z 撤销都照常,切回「预览」按新代码重新翻译 |
|
||||
| 折叠 | 有子块的块、属性表里带子行的行、带下一层的子行(字典 / 对象里嵌套的字典 / 对象)能折叠;函数块(含方法、嵌套函数)、类块、枚举块、异常块和库规则的卡片默认收起主体、属性表照常显示,其余块、属性行和子行默认展开;用户点过的按他点的记住 |
|
||||
@@ -123,8 +123,16 @@
|
||||
|
||||
- 每一句是一块:导入、函数、类、枚举、异常、类型、字段、常量、变量、条件、否则、循环、尝试、捕获、最终、返回、语句、注释;Shell 脚本另有解释器、选项、分情况、命令、管道(见「Shell 脚本」);Dockerfile 另有解析指令、阶段、执行、复制、设置、标签、健康检查、启动(见「Dockerfile」)。
|
||||
- 嵌套的块放在父块下面、往右缩进;每一层左边一条竖线(颜色 `--vscode-editorIndentGuide-background`)。
|
||||
- 块的组成(从左到右):折叠箭头(只有有子块的块才显示,其余占位对齐)、种类图标、内容、右上角一排图标按钮。
|
||||
- 种类图标(原型 `kindBadge`、画板「Prototype / 块种类图标」):块左边只画图标、不带字,和一行字等高(20px 的框,图形 16px,lucide 的线宽 2.2),颜色是种类色;种类的名字(翻译插件给 `kind` 值起的,见「筛选」;库规则的种类是规则给的 `badge.label`)写在悬停提示(见下「悬停提示」,同块右上角按钮)和 `aria-label` 里,`role="img"`。和折叠箭头、内容同一行顶对齐。每种内置种类由插件定图标、颜色、名字:图标从插件定义的一组图标里取(见下),内置种类 → 图标只在 webview 的一处(`kindIcons.tsx` 的 `KIND_ICONS`);颜色在 `codeReader.css` 的 `--cr-kind-*`(见「颜色」);名字由翻译插件给。同一类语义共用一个颜色,图标区分具体是哪种:
|
||||
- 块的组成(从左到右):折叠箭头(只有有子块的块才显示,其余占位对齐)、概念图标、内容、右上角一排图标按钮。
|
||||
- 概念图标(原型 `kindBadge`、画板「Prototype / 块种类图标」):块左边横排这块认出来的概念,各一个图标、不带字,和一行字等高(20px 的框,图形 16px,lucide 的线宽 2.2),间距紧。每个图标悬停自己的名字(`data-tooltip`,见下「悬停提示」);整排是一个 `role="img"`,读屏把名字用顿号连起来念。和折叠箭头、内容同一行顶对齐。webview 不自己用种类查图标:图标名由宿主放进预览数据的概念列表(`BlockView.concepts`),webview 只按名字画(`kindIcons.tsx` 的 `KIND_ICON_COMPONENTS`)。
|
||||
|
||||
一个概念(`BlockConcept`):稳定 id、悬停名、图标名(只能从 `KIND_ICON_NAMES` 里挑)、颜色。列表按这个顺序,同一个 id 只留第一个:
|
||||
|
||||
1. 语言的种类,就是这块原来的种类(类、函数、变量……)。图标是内置种类的(`contract.ts` 的 `KIND_ICONS`),名字是翻译插件给 `kind` 值起的(见「筛选」;没有翻译插件时是种类 id)。不另填颜色:图标按 id 用 CSS 的 `--cr-kind-*`(见「颜色」)。
|
||||
2. 语言插件另声明的概念(`LanguageAdapter.concepts`,可选)。认到才出现(比如异步、抽象)。不填就只有种类那一个。宿主不按语言写判断。
|
||||
3. 库规则认领成自己的卡片时,上面的留下,不换掉。规则的种类追加在后面:id 是 `RuleCard.kind`,名字、图标、颜色是 `badge` 的。规则还可以再带认出的概念(`RuleCard.concepts`)。筛选的 `kind`、卡片边框色仍是规则的种类(`badge.color`),不因为多了图标就改。认成现成属性表块的(`RuleFacts`,枚举)没有 badge,概念就是换成的那种块的语言种类。
|
||||
|
||||
每种内置种类由插件定图标、颜色、名字。同一类语义共用一个颜色,图标区分具体是哪种:
|
||||
|
||||
| 种类 | 图标 | 种类 | 图标 | 种类 | 图标 |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
@@ -140,9 +148,9 @@
|
||||
| copy 复制 | `copy` | setting 设置 | `sliders-horizontal` | label 标签 | `tag` |
|
||||
| health 健康检查 | `activity` | start 启动 | `play` | | |
|
||||
|
||||
库规则的种类用规则给的图标(`KindBadge.icon`):SQLAlchemy 数据表 `database`、数据类 `package`、Celery 应用 `server-cog`、定时任务 `calendar-clock`、FastAPI 接口 `globe`、FastAPI 路由器 `network`、React 组件 `atom`、副作用 `zap`、事件处理 `mouse-pointer-click`。
|
||||
库规则的种类用规则给的图标(`KindBadge.icon`),跟在语言的种类图标后面:SQLAlchemy 数据表 `database`、数据类 `package`、Celery 应用 `server-cog`、定时任务 `calendar-clock`、FastAPI 接口 `globe`、FastAPI 路由器 `network`、React 组件 `atom`、副作用 `zap`、事件处理 `mouse-pointer-click`。数据类写了 `frozen=True` 再加一把锁(`lock`,悬停「不可修改」)。
|
||||
|
||||
这组图标由插件自己定义,是一个封闭的集合:契约里的 `KIND_ICON_NAMES`(上表 26 个——命令、管道、执行共用一个,解释器、解析指令共用一个,选项、设置共用一个,字段、标签共用一个——加库规则用的 9 个(React 组件的原子、副作用的闪电、事件处理的点击手势也在里面),lucide 的 kebab-case 名字),类型 `KindIconName` 是它们的联合,`KindBadge.icon` 只能写其中一个,写别的是类型错误。webview 给每个名字配一个逐个 import 的 lucide 图标组件(`kindIcons.tsx` 的 `KIND_ICON_COMPONENTS`,打包只带这些,预览脚本约 157 kB);webview 的 `KindIconName` 照契约手抄,`kindIconNames.test.ts` 核对两边一样。规则要新图标就把名字加进这组、在 webview 配上图标,没有按任意名字找图标的路。
|
||||
这组图标由插件自己定义,是一个封闭的集合:契约里的 `KIND_ICON_NAMES`(上表 26 个——命令、管道、执行共用一个,解释器、解析指令共用一个,选项、设置共用一个,字段、标签共用一个——加库规则用的 9 个(React 组件的原子、副作用的闪电、事件处理的点击手势也在里面),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 能走到,回车 / 空格切换。
|
||||
- 悬停提示(整个插件的网页只走这一条路,预览和看板共用同一个组件):带提示的元素只写 `data-tooltip="提示"`(名字照旧写在 `aria-label` 里,只有图标的按钮必须有 `aria-label`),页面根上挂一个 `TooltipHost`(`webview-ui/src/components/ui/tooltip.tsx`)统一弹,不用原生 `title`;提示里的换行照样换行(看板摘修复弹框里「迁移」列出的几个文件一行一个);注释、回答里 Markdown 链接的标题(`[文字](网址 "标题")`)也写成 `data-tooltip`。网页的 TSX 里写原生 `title` 属性是 lint 错误(`vscode/eslint.config.mjs`),只有 `iframe` 这种必须带标题的元素例外,组件自己叫 `title` 的属性不算。原因:macOS 上 VS Code 带的 Electron(1.139 是 Electron 43)只在鼠标压着带 `title` 的元素自身边缘时才弹原生提示,停在它里面的图标、文字上不弹(electron/electron#49843,Electron 38 起),种类图标 20px 的框几乎被 16px 的图形占满,基本弹不出来;样子也是系统的。样子照 VS Code 的悬停框:`--vscode-editorHoverWidget-background` 底、`--vscode-editorHoverWidget-border` 边框、`--vscode-editorHoverWidget-foreground` 字、`0 2px 8px --vscode-widget-shadow` 阴影,11px 字,圆角 4px,最宽 22rem;优先在元素上方,上方放不下翻到下方,水平对着元素中间,贴边留 8px,不接鼠标。鼠标停 500ms 才弹,在同一个元素里移动不重新计时,已经弹着时移到另一个带提示的元素上立刻换;移开、移出页面、按下鼠标、按任意键(含 Esc)、滚动就收,收了之后鼠标不离开这个元素不再弹。键盘把焦点移到带提示的元素上(`:focus-visible`)立刻弹,焦点离开就收;提示不是元素自己的名字(`aria-label` 或它的字)时用 `aria-describedby` 挂到元素上,读屏当描述念。
|
||||
- 种类图标和底色按种类区分(颜色见「颜色」);注释块虚线框。
|
||||
@@ -891,6 +899,8 @@ export interface LanguageAdapter {
|
||||
steps?: (root: Node, source: string, languageId: string) => StepBlocks
|
||||
/** 认代码里给定义起的中文名(见「中文名」);不填就没有中文名。 */
|
||||
displayNames?: DisplayNameReader
|
||||
/** 这块除了自己的种类,还认得出的概念(异步、抽象)。认到才返回;不填就只有种类那一个。种类由宿主补在最前面,这里不要再报。 */
|
||||
concepts?: (block: CodeBlock) => BlockConcept[]
|
||||
}
|
||||
|
||||
/** 代码里给一个定义起的中文名:name 是定义处那个名字,text 是中文名。 */
|
||||
@@ -954,7 +964,13 @@ export interface ThemeColor { dark: string, light: string }
|
||||
export const KIND_ICON_NAMES = ['import', 'square-function', /* …22 个内置种类的… */ 'database', 'package', 'server-cog', 'calendar-clock', 'globe', 'network', 'atom', 'zap', 'mouse-pointer-click'] as const
|
||||
export type KindIconName = (typeof KIND_ICON_NAMES)[number]
|
||||
|
||||
/** 库规则的种类:块左边只画图标(种类色),label 是悬停提示和读屏念的名字,筛选栏里也叫它;icon 只能从 KindIconName 里挑。 */
|
||||
/** 内置种类 → 图标名。宿主写进概念列表,webview 不自己查。 */
|
||||
export const KIND_ICONS: Record<BlockKind, KindIconName>
|
||||
|
||||
/** 一块上认出的一个概念。颜色不填的是语言的种类(按 id 用 CSS 的种类色);规则的概念填颜色,只给这个图标上色。 */
|
||||
export interface BlockConcept { id: string, label: string, icon: KindIconName, color?: ThemeColor }
|
||||
|
||||
/** 库规则的种类:筛选栏里叫 label,卡片边框用 color,icon 进概念列表;icon 只能从 KindIconName 里挑。 */
|
||||
export interface KindBadge { label: string, color: ThemeColor, icon: KindIconName }
|
||||
|
||||
/** 库规则认领一块后给出的替身,下面挂着原块留下的子块:规则自己的卡片,或认成的现成属性表块;这块讲在了别的卡片里时是略去它。 */
|
||||
@@ -963,10 +979,11 @@ export type RuleBlock = RuleCard | RuleFacts | RuleOmit
|
||||
/** 这块讲在了别的卡片里,不再单独成块(React 的 "use client" 讲成组件卡片的「客户端组件」标签);不能有子块。 */
|
||||
export interface RuleOmit { omit: true }
|
||||
|
||||
/** 规则自己的卡片:一张属性表,种类的图标、颜色、名字和每一行都由规则给。 */
|
||||
/** 规则自己的卡片:一张属性表。种类(badge)决定筛选和边框色;卡片左边的图标是语言的概念再加这个种类、以及 concepts。 */
|
||||
export interface RuleCard {
|
||||
kind: string // 种类 id,「规则 id.名字」(sqlalchemy.table):筛选的 kind 值,要稳定
|
||||
badge: KindBadge // 种类的名字、颜色、图标;筛选栏里这个种类也叫这个名字
|
||||
badge: KindBadge // 种类的名字、颜色、图标;筛选栏里这个种类也叫这个名字,卡片边框用这个颜色
|
||||
concepts?: BlockConcept[] // 额外认出的概念,排在种类后面;语言的概念仍在更前面,同一个 id 只留第一个
|
||||
rows: PropertyRow[]
|
||||
defines?: SourceRange // 块自己的名字(类名):跳到的定义是它时闪整块
|
||||
attributes?: BlockAttributes // 规则自己的筛选属性,叠在宿主从原块推出的上面;kind 填了不算;名字由 LibraryRule.attributeNames 给
|
||||
@@ -1094,7 +1111,7 @@ export interface CommandRule {
|
||||
- 略去(`RuleOmit`,`{ omit: true }`):这块讲在了别的卡片里(React 文件开头的 `"use client"` 讲成组件卡片的「客户端组件」标签,组件上面没并进块头部的 JSDoc 讲成「说明」),预览不画它、不占块的位置(后面的块 id 接着往下数)。它不能有子块,有子块时宿主当替身不合约定。
|
||||
- 认成现成的属性表块(`RuleFacts`):`as` 是种类和 facts(`BlockFacts`,例如 `{ kind: 'enum', facts: EnumFacts }`),`absorbs` 同卡片。宿主把原块换成这种块(节点不变,头部是原块整条语句,子块是留下的),此后和语言插件报的这种块完全一样:翻译插件的 `describe` 排属性表、种类名取翻译插件的、颜色取这个种类的、筛选属性从 facts 推、块自己的名字从 facts 取。规则不给用词,也不给标签和颜色。只要检查并进来的是不是这块的子块。
|
||||
- 规则自己的卡片(`RuleCard`),下面几条都说的是它。
|
||||
- 卡片必须给:`kind`(写成「规则 id.名字」,宿主核对前缀;筛选记住的就是它,要稳定)、`badge`(种类的名字、暗 / 亮两种颜色和 lucide 图标名)、`rows`(用现成的 `PropertyRow`:属性名 + 着色的值或 Markdown,表格就是带 `columns` 的子行)、`absorbs`(并进来的子块)。可以给:`defines`(块自己的名字,跳到定义是它时闪整块)、`attributes`(自己的筛选属性)、`slots`(放进卡片某一行下面的子块,见下);表格子行填 `PropertyItem.defines`(字段名),跳到这个定义时只闪那一行。
|
||||
- 卡片必须给:`kind`(写成「规则 id.名字」,宿主核对前缀;筛选记住的就是它,要稳定)、`badge`(种类的名字、暗 / 亮两种颜色和 lucide 图标名)、`rows`(用现成的 `PropertyRow`:属性名 + 着色的值或 Markdown,表格就是带 `columns` 的子行)、`absorbs`(并进来的子块)。可以给:`defines`(块自己的名字,跳到定义是它时闪整块)、`attributes`(自己的筛选属性)、`concepts`(额外认出的概念,排在种类图标后面)、`slots`(放进卡片某一行下面的子块,见下);表格子行填 `PropertyItem.defines`(字段名),跳到这个定义时只闪那一行。
|
||||
- 放进卡片里的子块(`RuleSlot`):留下的子块(没并进来的)可以不排在卡片后面,画在卡片第 `row` 行下面当子卡片(React 组件的副作用画在「副作用」那一行下面);它照常转成块,照样问各规则(副作用那句也被 React 规则认成自己的卡片),编辑、问 AI、差异、筛选都照常。给了 `item` 的是那一行的子行里讲它的那一个:默认收着,点那个子行的第一格才展开、同一行里别的收起(事件处理表点名称)。一块只能放一处,不能同时并进来;`row` 要有这一行、`item` 要有这个子行。
|
||||
- 只经契约:规则拿到的是块(kind、node、header、children、facts)和 `RuleContext`;源码里的名字照抄时自己带下标(`Segment.offset`),表达式、类型交给 `context.translate`(当前翻译插件的 `expression`,名字带下标,⌘ + 点击、高亮各处出现照常),说明文字交给 `context.doc`(当前翻译插件的 `doc`,和别的「说明」一样按 Markdown 显示),别的文件里定义的名字交给 `context.lookup`(见「规则认领时查别的文件里的定义」);库自己的配色(HTTP 方法)写在段的 `color` 上。规则可以读自己那门语言的语法树(规则声明了 `languageIds`),但不 import 语言插件、翻译插件和宿主模块(`rules/contractOnly.test.ts` 检查 `rules/` 下非测试文件只 import `../contract` 和同目录的文件)。
|
||||
- 用词归规则:属性名、表头、种类名、类型译名都在规则自己的词表里,按 `context.displayLanguage`(翻译插件的 `displayLanguage`)挑,没有这种语言的词表就用规则默认的那份;加一种显示语言就是给规则加一份词表。webview 只画结构,不认识「数据表」这些字。
|
||||
@@ -1105,7 +1122,7 @@ export interface CommandRule {
|
||||
- 认领:宿主从顶层往下每块问一遍启用的规则,按注册顺序,第一个认领的算(先注册的优先);被认领的块留下的子块照样问。
|
||||
- 出错:规则抛错、或替身不合约定(种类 id 没带规则 id 前缀、并进来的不是这块的子块、属性表里的引用标的不是自己 / 规则没给 `resolve` / 引用的段没带下标、放进卡片里的块不是留下的子块 / 放了几处 / 没有那一行或子行、要略去的块还有子块)时,宿主记一条警告日志(输出面板「Superpowers」),当它没认、接着问下一个规则;都没认这块照常显示。预览不会因为规则出错而失败。
|
||||
- 并进来的子块:不再单独成块,由规则挑(`absorbs`),宿主不替规则多并。没并进来的子块(方法、规则不讲的注释)不管写在哪(字段中间也算),都照源码顺序是替身的子块,预览里照常看得见。替身的编辑范围同别的块,是原块整条语句(从头部开始,到原块连同各子块的最后一行,类就是整个类),盖住留下的子块的行:替身编辑时预览不画这些子块,同一行不会同时在两处能改(见「预览(代码块树)」)。内置规则并成员时连同紧挨在它前面的注释块一起并(讲的是这个成员),讲方法的注释、最后面的注释照常留下。
|
||||
- 卡片在预览里:种类图标、颜色取 `badge`(`icon`;颜色暗色、亮色主题各取一个),悬停提示是 `badge.label`,内容是 `rows`,放进卡片的子块画在它那一行下面(这一行有折叠箭头,收起时它们跟着收起;画成一层块,同块树),不算卡片的子块(卡片的折叠箭头只管后面留下的子块);筛选的 `kind` 是替身的种类 id,其余属性从原块推出(原来的类是公共的,数据表也是公共的),叠上规则给的(规则自己的属性叫 `LibraryRule.attributeNames` 给的名字,规则起名时抛错记日志、照写 id);筛选栏里这个种类叫 `badge.label`;和类块一样默认收起子块。
|
||||
- 卡片在预览里:左边的图标是语言的概念(原来的类、函数……)再加 `badge` 这一个、以及 `concepts`(同一个 id 只留第一个),悬停各自的名字;卡片边框色取 `badge.color`(暗色、亮色主题各取一个),内容是 `rows`,放进卡片的子块画在它那一行下面(这一行有折叠箭头,收起时它们跟着收起;画成一层块,同块树),不算卡片的子块(卡片的折叠箭头只管后面留下的子块);筛选的 `kind` 是替身的种类 id,其余属性从原块推出(原来的类是公共的,数据表也是公共的),叠上规则给的(规则自己的属性叫 `LibraryRule.attributeNames` 给的名字,规则起名时抛错记日志、照写 id);筛选栏里这个种类叫 `badge.label`;和类块一样默认收起子块。多了图标不改筛选、不改边框色。
|
||||
|
||||
### 规则自己查定义
|
||||
|
||||
@@ -1307,7 +1324,7 @@ export interface CommandRule {
|
||||
|
||||
### 内置:dataclasses 数据类(Python)
|
||||
|
||||
`vscode/src/codeReader/rules/dataclass.ts`,`libraries: ['dataclasses']`(Python 自带的库)。样例是 luffy 的 `user/repositories.py`、`commerce/payments/_driver.py`、`core/sms/services.py`、`sandbox/runtime.py` 里的数据类(节选在 `fixtures/dataclassModels.py`)。种类 `dataclasses.dataclass`,标签「数据类」(暗 #ef7fb0 / 亮 #b3306c),和类块一样默认收起子块。
|
||||
`vscode/src/codeReader/rules/dataclass.ts`,`libraries: ['dataclasses']`(Python 自带的库)。样例是 luffy 的 `user/repositories.py`、`commerce/payments/_driver.py`、`core/sms/services.py`、`sandbox/runtime.py` 里的数据类(节选在 `fixtures/dataclassModels.py`)。种类 `dataclasses.dataclass`,标签「数据类」(暗 #ef7fb0 / 亮 #b3306c),和类块一样默认收起子块。卡片左边的图标是「类」再加「数据类」。`frozen=True` 再加一把锁(概念 id `dataclasses.frozen`,悬停「不可修改」,颜色同常量 #9cdcfe / #001080)。`slots` 不加图标。
|
||||
|
||||
- 认哪些类:装饰器是 `@dataclass`、`@dataclass(...)`、`@dataclasses.dataclass(...)`(`import dataclasses as dc` 的 `dc.dataclass`、`from dataclasses import dataclass as data` 的 `data` 也算,别名按 `context.imports` 换回)。同名的别处的东西不算(`from pydantic.dataclasses import dataclass`、`@other.dataclass`)。
|
||||
- 字段照 dataclasses 的规则认:类主体里带注解的名字(`x: int`、`x: int = 1`),照源码顺序。`ClassVar[...]`(`typing.ClassVar`、只写 `ClassVar` 也算)是类变量,不是字段,照常是子块;`InitVar[...]` 是字段,类型写方括号里的,说明前面写「仅初始化时使用」;`_: KW_ONLY` 是记号,不是字段,它后面的字段(没单独写 `kw_only=` 的)在默认值一格写「只能按名字传参」。
|
||||
@@ -1745,7 +1762,8 @@ interface BlockViewBase {
|
||||
codeTokens: Segment[] // 源码着色(拼起来等于 code)
|
||||
defines?: SourceRange // 块自己的名字(函数名、类名、只声明一个变量时的变量名)在源码里的范围,扩展端从 facts 取(库规则的块取 RuleBlock.defines);跳到的定义是它时闪整块
|
||||
attributes: Record<string, string> // 筛选属性(含 kind),见「筛选」
|
||||
badge?: KindBadge // 库规则的卡片才有:种类的名字、颜色、图标;webview 按它画图标、上色、默认折叠
|
||||
concepts: BlockConcept[] // 认出来的概念,从左到右;webview 按图标名画,不自己用种类查
|
||||
badge?: KindBadge // 库规则的卡片才有:筛选栏里这个种类的名字,卡片边框的颜色;图标在 concepts 里。和类块一样默认折叠
|
||||
slot?: { row: number, item?: number } // 库规则放进父卡片属性表里的子块才有(RuleSlot):画在父卡片第 row 行下面;item 是讲它的子行,点它才展开(它的块 id 记成折叠着就是收着)
|
||||
children: BlockView[]
|
||||
}
|
||||
@@ -1904,7 +1922,7 @@ vscode/src/codeReader/
|
||||
editor/occurrences.ts 查名字的各处出现(vscode.executeDocumentHighlights)
|
||||
editor/occurrenceNavigation.ts 跳到下一处 / 上一处高亮:命令、上下文键
|
||||
index.ts registerCodeReader(context): CodeReaderApi
|
||||
vscode/webview-ui/code-reader.html + src/codeReader/ 预览界面(React,Vite 第二个入口;块右上角的图标按钮在 BlockTools.tsx,悬停提示在 src/components/ui/tooltip.tsx(和看板共用,页面根上挂一次),块的种类图标(这组图标名 → 图标组件、内置种类 → 图标名,都只在这一处)在 kindIcons.tsx,属性表在 PropertyGrid.tsx,子行排成表格还是列表在 subRows.ts,着色的词和框在 SegmentText.tsx,中文名换字在 displayNames.ts,Markdown 渲染在 markdown.ts / TextPreview.tsx,筛选栏在 FilterBar.tsx,筛选规则在 filter.ts,编辑时盖住哪些块、点「编辑」退出哪些块在 editing.ts,高亮各处出现的规则在 occurrences.ts、接到页面上在 useOccurrences.ts,问 AI 的问答区在 AskThread.tsx、状态和规则在 qa.ts、贴图拖图的规则在 qaImages.ts、收发在 useQa.ts;代码差异:页面上怎么标(块 id、删掉的块挂哪、只看改动折哪几段、各处改动、上一处 / 下一处跳到哪)在 diffView.ts,筛选栏第二行和新文件横幅在 DiffBar.tsx,卡片里的增删在 DiffText.tsx(Markdown 的增删在 markdown.ts 的 renderMarkdownDiff),总览条在 OverviewRuler.tsx,跳到一处改动在 useChangeNav.ts)
|
||||
vscode/webview-ui/code-reader.html + src/codeReader/ 预览界面(React,Vite 第二个入口;块右上角的图标按钮在 BlockTools.tsx,悬停提示在 src/components/ui/tooltip.tsx(和看板共用,页面根上挂一次),块的概念图标(图标名 → 图标组件只在 kindIcons.tsx;内置种类 → 图标名在 contract.ts 的 KIND_ICONS,宿主写进概念列表)在 kindIcons.tsx,属性表在 PropertyGrid.tsx,子行排成表格还是列表在 subRows.ts,着色的词和框在 SegmentText.tsx,中文名换字在 displayNames.ts,Markdown 渲染在 markdown.ts / TextPreview.tsx,筛选栏在 FilterBar.tsx,筛选规则在 filter.ts,编辑时盖住哪些块、点「编辑」退出哪些块在 editing.ts,高亮各处出现的规则在 occurrences.ts、接到页面上在 useOccurrences.ts,问 AI 的问答区在 AskThread.tsx、状态和规则在 qa.ts、贴图拖图的规则在 qaImages.ts、收发在 useQa.ts;代码差异:页面上怎么标(块 id、删掉的块挂哪、只看改动折哪几段、各处改动、上一处 / 下一处跳到哪)在 diffView.ts,筛选栏第二行和新文件横幅在 DiffBar.tsx,卡片里的增删在 DiffText.tsx(Markdown 的增删在 markdown.ts 的 renderMarkdownDiff),总览条在 OverviewRuler.tsx,跳到一处改动在 useChangeNav.ts)
|
||||
```
|
||||
|
||||
## 测试
|
||||
@@ -1972,7 +1990,7 @@ vscode/webview-ui/code-reader.html + src/codeReader/ 预览界面(React,Vit
|
||||
- 页面(`diffView.test.ts`、`markdown.test.ts`、`viewState.test.ts`):块按记号认成页面上的 id、找不到的不标、不是这一版不画卡片里的标记,删掉的块按层挂、找不到挂处的和被筛掉的不画,新文件不逐块标,标了改动的默认展开;统计的字;删掉的块收起时的名字;只看改动折哪几段(改过的块下面按层折、删掉的块打断、被筛掉的不算、点开过的和要露出来的不折);各处改动的先后和行、被筛掉的不算;上一处 / 下一处接着走、按视口顶上的行找、到头绕回;带增删的 Markdown 照常排版、跨行逐行包、新加的列表项留住记号。
|
||||
- 复制出什么(`explorer/copyText.test.ts`):文件、目录的名字 / 相对路径 / 绝对路径;不带后缀只去最后一个扩展名(`a.test.ts`、`archive.tar.gz`),`.env` 原样、`.env.local` → `.env`、没有扩展名的原样;相对路径总用 `/`,绝对路径照本机写法(Windows 反斜杠)。
|
||||
- 块右上角的图标按钮(webview `BlockTools.test.tsx`,渲染成 HTML):一组一个按钮、没有字、悬停提示(`data-tooltip`,没有原生 `title`)和 `aria-label` 是「编辑」/「预览」、有图标、编辑时带按下标记;给了「问 AI」时它排在前面、只有图标、问答区展开时带按下标记和 `aria-expanded`。
|
||||
- 块的种类图标(webview `kindIcons.test.tsx`,渲染成 HTML):内置种类的图标和原型一一对应;这组里每个名字画的就是 lucide 里同名的图标;webview 配了图标的名字和契约的 `KIND_ICON_NAMES` 一样、没有多的(`kindIconNames.test.ts`);只有图标、没有字,`role="img"`,悬停提示(`data-tooltip`,没有原生 `title`) 和 `aria-label` 是种类名,20px 的框、16px 的图形;库规则的卡片用规则给的图标。各库规则的测试核对 `badge` 的名字、颜色、图标。
|
||||
- 块的概念图标(webview `kindIcons.test.tsx`,渲染成 HTML):内置种类 → 图标名和原型一一对应(`contract.ts` 的 `KIND_ICONS`);这组里每个名字画的就是 lucide 里同名的图标;webview 配了图标的名字和契约的 `KIND_ICON_NAMES` 一样、没有多的(`kindIconNames.test.ts`);只有图标、没有字,悬停提示(`data-tooltip`,没有原生 `title`)是各自的名字,整排 `role="img"` 的 `aria-label` 把名字用顿号连起来,20px 的框、16px 的图形,横排间距紧;语言的种类按 id 上色,规则的图标用规则给的颜色。概念列表(`blockView.test.ts`、`rules/dataclass.test.ts`):普通类只有「类」;数据类是「类」和「数据类」,`frozen=True` 再加「不可修改」的锁,`slots` 不加;同一个 id 只留第一个(语言的种类优先于后面重复的);悬停名是这些。各库规则的测试核对 `badge` 的名字、颜色、图标。
|
||||
- 悬停提示(webview `components/ui/tooltip.test.ts`):停 500ms 才弹、在同一个元素里移动不重新计时、没等到就移开不弹、弹着时移到另一个上立刻换、移到没提示的地方就收、按下鼠标 / 按键 / 滚动就收且鼠标不离开不再弹、等着弹时按下这次不弹、键盘聚焦立刻弹失焦收、提示是空的不弹;位置在上方、上方放不下翻到下方、左右钳在视口内。Markdown 链接的标题写成 `data-tooltip`(`markdown.test.ts`);网页 TSX 里的原生 `title` 由 lint 规则拦(`button`、`span` 上报错,`iframe`、组件属性不报)。页面上(无头 Chrome,真的移鼠标、按 Tab):种类图标中心点命中的是图标里的线条、没有盖在上面的东西;停 250ms 还没弹、停满 500ms 在图标上方弹「函数」「接口」,颜色是悬停框的那组变量;Tab 到「编辑」立刻弹、Esc 收;页面上没有原生 `title`;看板上「待接管」、禁用的 .env 锁按钮(禁用的按钮照样弹)、刷新按钮、摘修复弹框里「迁移」的三行文件名(一行一个)都弹,Tab 到按钮立刻弹、Esc 收。亮、暗两套颜色都看过。
|
||||
- 问 AI:
|
||||
- 位置记号(`qa/anchor.test.ts`,真实的 Python 解析):有名字 / 没名字的块的记号、同一层重复的编号、两个函数里一样的条件互不影响;上面插几行、改空白记号不变;改别的函数的名字只动它和它里面的块;没名字的块自己的源码改了记号变、有名字的块改签名不变。
|
||||
|
||||
Reference in new issue
Block a user