✨ feat(vscode): 只有从「未提交的更改」点开的预览才对比上一次提交
This commit is contained in:
1 parent
4ec2b9d5d6
commit
3c7513b7cd
18 files changed
+366
-143
No files matched your search
@@ -221,13 +221,14 @@
|
||||
|
||||
### 代码差异
|
||||
|
||||
审 AI 写的代码时,侧栏只列改动的文件(「未提交的更改」「选工单」审查),预览的卡片标出这个文件相比改之前加了什么、改了什么、删了什么(原型插件菜单「代码差异」:画板「代码差异 · 全部 / 只看改动 / 标记说明」)。普通文件树下预览和平时一样,不标。
|
||||
审 AI 写的代码时,从只列改动的文件的地方(侧栏「未提交的更改」一栏、「选工单」审查)点开,预览的卡片标出这个文件相比改之前加了什么、改了什么、删了什么(原型插件菜单「代码差异」:画板「代码差异 · 全部 / 只看改动 / 标记说明」)。从主栏、收藏栏点开,点链接、跳定义这些别处打开的预览和平时一样,不标。
|
||||
|
||||
- 对比基准(`diff/diffBase.ts` 的 `DiffBase`,由开着的侧栏筛选给:`TreeFilter.diffBase`,`TreeFilters` 转给预览):
|
||||
- 「未提交的更改」开着、文件在工作区的仓库里(`workspaceOrder`,审查的工作副本不算):对比上一次提交(HEAD),文案「对比:上一次提交」。
|
||||
- 审查工单、文件在这张工单的工作副本里:对比 PR 目标分支与 PR 头的合并基(Gitea PR 的 `merge_base`,没给时退回目标分支的提交,同看板「改动」tab)上的版本,改名的取改名前的路径(`reviewBaseFile`);文案「对比:PR 目标分支 <base 分支名>」(PR 的 `base.ref`)。合并基是 PR 头的祖先,拉 PR 的提交时已经在本机,直接在工作副本里取。
|
||||
- 对比基准(`diff/diffBase.ts` 的 `DiffBase`,`previewDiffBases` 按文件在哪、这个标签页是从哪儿打开的给):
|
||||
- 从侧栏「未提交的更改」一栏点开的、文件在工作区的仓库里有没提交的改动(`workspaceOrder`,审查的工作副本不算):对比上一次提交(HEAD),文案「对比:上一次提交」。从主栏、收藏栏点开,点仓库链接、⌘ / Ctrl + 点击跳到定义、点调用树、侧栏「问 AI」、编辑器右上角切回「预览」这些别处打开的不比。
|
||||
- 从哪儿打开的是打开请求自带的(`editor/previewEditor.ts` 的 `OpenRequest.from`:`uncommitted` / `other`):侧栏文件行的打开命令带上这一栏的 `from`(`explorer/fileTree.ts` 的 `FileOpenCommand`),`PreviewEditorProvider.open` 把请求交给新建的预览;打开的是已经开着的预览时交给切到的那个,以最后一次从哪儿点开为准(从「未提交的更改」点开就比,再从主栏点开同一个文件就不比);只切标签页不变。页面把它记进 webview 状态,VS Code 重启后恢复的标签页没有打开请求,随 `ready` 报回来,照关掉前的比;页面也没记过的(VS Code 自己换编辑器打开的)不比。
|
||||
- 审查工单、文件在这张工单的工作副本里(不管从哪儿打开):对比 PR 目标分支与 PR 头的合并基(Gitea PR 的 `merge_base`,没给时退回目标分支的提交,同看板「改动」tab)上的版本,改名的取改名前的路径(`reviewBaseFile`);文案「对比:PR 目标分支 <base 分支名>」(PR 的 `base.ref`)。合并基是 PR 头的祖先,拉 PR 的提交时已经在本机,直接在工作副本里取。
|
||||
- 取旧内容:`git/fileAt.ts` 的 `fileAtRef`(`git ls-tree` 看有没有这个文件、`git show <提交>:<路径>` 取内容,走 `runGit`);基准里没有这个文件(未跟踪、新加的、PR 里新加的、仓库还没有提交)不逐张标绿,顶部一条横幅「新文件,全部是新增」,后面淡色写原因(「还没被 git 跟踪,上一次提交里没有这个文件」「上一次提交里没有这个文件」「PR 目标分支 master 里没有这个文件」「仓库里还没有提交」)。
|
||||
- 什么时候比(`diff/previewDiff.ts` 的 `PreviewDiff`,每个预览一个):每发出一份文档(编辑、保存、块编辑写回、换翻译)之后按眼下的基准重新比;换了筛选、基准挪了(「未提交的更改」盯着的 git 状态变了,比如提交后 HEAD 动了;审查进 / 重读工单)打开着的预览也重新比。预览先照常画文档,差异算好了再补发(`diff` 消息),打开不变慢。取过的旧内容按基准的 key(提交 + 路径)记着,编辑时不用每次问 git;旧版本每次用同一个语言插件、翻译插件、库规则重新排成视图数据,规则查定义、调用的种类用这份文档眼下查到的答案,两边同样的写法翻得一样。取不到旧内容、旧版本解析失败时记日志、不标。
|
||||
- 什么时候比(`diff/previewDiff.ts` 的 `PreviewDiff`,每个预览一个):每发出一份文档(编辑、保存、块编辑写回、换翻译)之后按眼下的基准重新比;基准挪了(盯着的 git 状态变了,比如提交后 HEAD 动了;审查进 / 重读工单)、开着的预览又被点开换了从哪儿打开的,打开着的预览也重新比。预览先照常画文档,差异算好了再补发(`diff` 消息),打开不变慢。取过的旧内容按基准的 key(提交 + 路径)记着,编辑时不用每次问 git;旧版本每次用同一个语言插件、翻译插件、库规则重新排成视图数据,规则查定义、调用的种类用这份文档眼下查到的答案,两边同样的写法翻得一样。取不到旧内容、旧版本解析失败时记日志、不标。
|
||||
- 块怎么对上(`diff/blockDiff.ts`,纯函数):同一父块下的兄弟块对齐——有名字的块(`defines`:函数名、类名、只声明一个变量时的变量名、规则卡片讲的名字)按「种类 + 名字」配,同名的照先后,挪了位置也配得上;没名字的块(语句、调用、注释……)以此为锚,最长公共子序列找出种类、源码都没变的,夹在相邻两个锚中间的按先后找种类相同、内容最像(按词比,相似度到一半)的配成修改。配不上的旧有新无算删除、旧无新有算新增;改名算一删一增。配上的块整段源码(去共同缩进)一样算没变,否则算修改,接着比子块;自己的内容改了、或源码变了子块却都没变的,是「自己改了」(上一处 / 下一处、总览条停在它上面)。
|
||||
- 卡片里标什么(`diff/viewDiff.ts`,纯函数):修改的卡片在渲染用的视图数据这一层比(翻译好的属性表、一行译文、摊开实参的表、说明),所有语言、库规则的卡片走同一条路:
|
||||
- 属性表按属性名配行;配上的行值变了:着色的词按词(一段着色的词一个)对齐,大部分没变时逐截标(新加的一截绿底、删掉的一截红底划掉),没变的不到四成时整段写成旧值(红底划掉)紧跟新值(绿底);说明这类 Markdown 按词比,中文按字、标点各算一个(`diffWordsWithSpace`)。带子行的行子行改了时只标子行,值(「3 个」「字典 2 项」这类汇总)跟着变、不另标——原型里参数多了一行时「输入参数」的个数也没标。
|
||||
@@ -2072,13 +2073,14 @@ type BlockView = BlockViewBase & ({ translation: PreviewText, table?: PreviewTab
|
||||
- `{ type: 'moveOccurrence', step: 1 | -1 }`:两条命令发来,跳到下一处 / 上一处出现。
|
||||
- `{ type: 'displayNames', version, names: ShownName[] }`:version 这份文档里显示成中文名的名字,查到一步发一步;页面只收自己眼下这个版本的。
|
||||
- `{ type: 'filter', excluded: Record<属性 id, 值 id[]>, onlyChanges }`:整个工作区共用的块筛选和「只看改动」开关(见「代码差异」)。webview 发 `ready` 后先于第一份文档发一次(第一份文档按筛选画),之后任何一个预览改了都发给所有开着的预览(包括改的那个)。
|
||||
- `{ type: 'diff', diff: DocumentDiff | null }`:这份文件相比对比基准改了什么(见「代码差异」),每发一份文档之后算好了补发,换了筛选、基准挪了再发;`null` 是不比了。`DocumentDiff` 是 `{ base, version, newFile?, blocks: Record<块记号, { change: 'add' | 'mod', outermost?, own?, marks? }>, removed: { parent, after?, block, line, kindName }[], stats: { add, mod, del }, lineCount }`:块按记号认;`marks` 是卡片里要标的(属性表各行、子行、一行译文、摊开实参的表、说明的增删,行和子行按下标,只在页面上正是 `version` 这一版时画);删掉的块 `block` 是旧版本的视图数据(只带它自己的内容、词不带下标),`parent` / `after` 是它挂在哪块下面、排在哪块后面(记号),`line` 是它在新文件里的位置。
|
||||
- `{ type: 'diff', diff: DocumentDiff | null }`:这份文件相比对比基准改了什么(见「代码差异」),每发一份文档之后算好了补发,基准挪了、换了从哪儿打开的再发;`null` 是不比了。`DocumentDiff` 是 `{ base, version, newFile?, blocks: Record<块记号, { change: 'add' | 'mod', outermost?, own?, marks? }>, removed: { parent, after?, block, line, kindName }[], stats: { add, mod, del }, lineCount }`:块按记号认;`marks` 是卡片里要标的(属性表各行、子行、一行译文、摊开实参的表、说明的增删,行和子行按下标,只在页面上正是 `version` 这一版时画);删掉的块 `block` 是旧版本的视图数据(只带它自己的内容、词不带下标),`parent` / `after` 是它挂在哪块下面、排在哪块后面(记号),`line` 是它在新文件里的位置。
|
||||
- `{ type: 'qa', available, threads: { anchor, entries: { id, question, answer, createdAt, profile?, images? }[] }[], running: { askId, anchor, question, text, activity? }[] }`:这份文件的问答(见「问 AI」)。`ready` 后发一次,存的问答、正在答的问题变了再发给开着这份文件的所有预览;`available` 为假时文件不在工作区文件夹里,不给「问 AI」;`images` 是问题带的图片在预览里能直接用的地址(`webview.asWebviewUri`);`running` 让重新加载的页面接上还在答的问题(不带图片,接上的这一问不显示缩略图,答完回到历史里照常有)。
|
||||
- `{ type: 'askProfiles', options: { id, label }[], selected }`:「问 AI」的 profile 下拉(`id` 是 profile 名,「默认」的 `id` 是 `''`、`label` 是「默认」)。`ready` 后发一次(每次现读 profile 目录),任何一个预览选了都发给所有开着的预览(包括选的那个)。
|
||||
- `{ type: 'answer', askId, text, activity? }`:`askId` 那个问题的回答长了(`text` 是到现在为止的全文)或换了在做的事。webview 攒着、最多每 80ms 画一次。
|
||||
- `{ type: 'answerEnd', askId, status: 'done' | 'failed' | 'stopped', text?, error?, entryId? }`:答完了。`done` 带最终回答和存下的那条的 id(历史里不再重复显示它),`failed` 带给人看的原因,`stopped` 是被叫停、没存。
|
||||
- `{ type: 'rewriteProgress', anchor, question, text, activity? }`:`anchor` 那块正在重写注释:`question` 是发给模型的那一句,`text` 是正文到现在为止写出来的,`activity` 是正在读什么。`{ type: 'rewriteEnd', anchor, status: 'done' | 'failed' | 'stopped', error? }`:重写完了(见「重写注释」)。
|
||||
- `{ type: 'repoLinksChecked', id, missing, unresolved }`:回答第 `id` 次 `checkRepoLinks`,`missing` 是仓库里没有的路径,`unresolved` 是找不到的不带路径的引用。`{ type: 'repoLinkBroken' | 'repoLinkOpened', path?, symbol? }`:点了以后打不开 / 打开了;没有 `path` 的是不带路径的引用。见「注释的 Markdown 排版」。
|
||||
- `{ type: 'openedFrom', from: 'uncommitted' | 'other' }`:这个标签页是从哪儿打开的(见「代码差异」),页面记进 webview 状态。`ready` 后发一次,开着时又被点开再发。
|
||||
- webview → 扩展:
|
||||
- `{ type: 'probeDefinition', id, version, offset }`:按住修饰键指到带 `offset` 的名字上时问有没有定义,`id` 每问一次加一;`version` 不是当前文档版本就不答。
|
||||
- `{ type: 'goToDefinition', version, offset }`:修饰键 + 点击,按「跳到定义」一节跳。这两条都只带下标:扩展端按发出去的文档认出规则标了引用的下标交给规则查(见「规则自己查定义」),其余问语言扩展。
|
||||
@@ -2086,7 +2088,7 @@ type BlockView = BlockViewBase & ({ translation: PreviewText, table?: PreviewTab
|
||||
- `{ type: 'findOccurrences', id, version, offset }`:单击带 `offset` 的名字,问它在这份文档里的各处出现;`id` 每问一次加一,`version` 不是当前文档版本就不答。
|
||||
- `{ type: 'occurrenceNavigation', available }`:眼下能不能用键盘在各处出现之间跳,页面加载后报一次、之后变了才报;扩展端按它设 `superpowers.codeReader.hasOccurrences`。
|
||||
- `{ type: 'checkRepoLinks', id, paths, symbols }`:页面上的仓库路径问哪些没有,不带路径的引用问哪些找不到(`id` 每问一次加一)。`{ type: 'openRepoLink', path?, symbol? }`:点了注释里的仓库链接(带 `path`)或不带路径的引用(只带 `symbol`)。见「注释的 Markdown 排版」。
|
||||
- `{ type: 'ready' }`
|
||||
- `{ type: 'ready', openedFrom? }`:页面准备好了;`openedFrom` 是 webview 状态里记着的这个标签页是从哪儿打开的,新开的页面没记过就不带。
|
||||
- `{ type: 'edit', startLine, endLine, text }`:用 `WorkspaceEdit` 把这几行整行替换成 `text`(每行补回原来第一行的缩进)。
|
||||
- `{ type: 'rewriteComment', anchor }`:给 `anchor` 那块重写注释(见「重写注释」);`{ type: 'stopRewrite', anchor }`:叫停,不写文件。
|
||||
- `{ type: 'selectTranslator', id }`:按 `languageId` 记到 `globalState`,重发文档。
|
||||
@@ -2195,11 +2197,11 @@ vscode/src/codeReader/
|
||||
review/reviewWorktree.ts 本机这张工单的工作副本在哪、备好 PR 最新的代码(已有的快进、没有的建)
|
||||
review/changeDecorations.ts FileDecorationProvider:审查时给改过的文件上色、挂徽标
|
||||
review/reviewMode.ts ReviewMode:选工单弹框、进出审查、刷新、按工作区记住,审查时预览对比什么(diffBase)
|
||||
uncommitted/uncommittedMode.ts UncommittedMode:「未提交的更改」进出、盯 git 状态重摆,开着时预览对比上一次提交(diffBase);纯函数在 uncommittedFiles.ts
|
||||
explorer/treeFilters.ts TreeFilters:侧栏的几种筛选同时只开一种,开着的那种定预览对比什么,换了筛选、基准变了通知预览
|
||||
uncommitted/uncommittedView.ts UncommittedView:侧栏「未提交的更改」一栏,盯 git 状态重摆,点开的文件带 `from: uncommitted`;纯函数在 uncommittedFiles.ts
|
||||
uncommitted/headBases.ts HeadBases:从「未提交的更改」点开的预览对比上一次提交(diffBase),git 状态变了通知预览重新比
|
||||
explorer/treeLocator.ts TreeLocator:侧栏的树定位到某个文件 / 目录(跟着当前文件走、目录链接),按 FileTreeProvider 的 nodeOf、getParent 找行
|
||||
explorer/treeReveal.ts 定位用到的判断:树上一行和要找的路径什么关系、explorer.autoReveal / autoRevealExclude 怎么认(纯函数)
|
||||
diff/diffBase.ts DiffBase:对比基准(文案、旧内容怎么取、缓存用的 key、基准里没有这个文件时的说明)
|
||||
diff/diffBase.ts DiffBase:对比基准(文案、旧内容怎么取、缓存用的 key、基准里没有这个文件时的说明);OpenedFrom、previewDiffBases:预览对比什么(审查按位置,上一次提交只给从「未提交的更改」点开的)
|
||||
diff/blockDiff.ts 两棵块树比:兄弟块对齐(名字 / 最长公共子序列 / 相似度)、新增修改删除、删掉的块放哪、统计(纯函数)
|
||||
diff/viewDiff.ts 一块卡片里的内容比:属性表按属性名、子行按第一列、着色的词逐截、Markdown 逐词;删掉的块只留自己的内容、去掉源码下标(纯函数)
|
||||
diff/previewDiff.ts PreviewDiff:一个预览的差异,发完文档再比、旧内容按 key 记着、只发最后一次的结果;DocumentDiff 消息的形状(不碰 VS Code)
|
||||
@@ -2307,6 +2309,7 @@ vscode/webview-ui/code-reader.html + src/codeReader/ 预览界面(React,Vit
|
||||
- 代码差异:
|
||||
- 块对齐和整棵树(`diff/blockDiff.test.ts`,真实的 Python 解析):原型的 `mutex.py`(改之前是编的)比出「新增 2 · 修改 3 · 删除 1」,新增块的子孙跟着算新增、只有最外面挂小标,`try_acquire` 自己改了、带属性表的标记,子块 `token` 改了、`ok` 和返回没变,`release` 只有子块改了(不算自己改了),删掉的 `_is_owner` 排在新增的 `renew` 后面、只带自己的内容、没有源码下标;没变的文件没有改动;子块里删掉的排在最前面时没有 after。对齐:有名字的按种类 + 名字配(挪了位置也配、同名照先后、种类不同不配、改名一删一增),没名字的按最长公共子序列和相似度配,种类不同不按相似度配。
|
||||
- 卡片里的标记(`diff/viewDiff.test.ts`):只是源码下标不同不算改;大部分没变时逐截标、删掉的去掉下标,改得多整段旧值 → 新值;框按样式、框头、框里的词比;Markdown 按词、中文按字;一种文字换成另一种按字比;子行按第一列配(加行、删行放回原来的位置、改了的只标那一格、新加的行下面各层也是新加的);属性行按属性名配、子行改了不另标值;一行译文、摊开实参的表、说明各比各的;属性表和一行译文没法比。
|
||||
- 对比什么看从哪儿打开的(`diff/diffBase.test.ts`、`editor/previewEditor.test.ts`、`explorer/fileTree.test.ts`、`viewState.test.ts`):审查工作副本里的不管从哪儿打开都对比 PR 目标分支,别的只有从「未提交的更改」点开的对比上一次提交;新开的预览按打开请求、开着的再被点开换成这次的(不比了发 null)、只切标签页不变;没有打开请求的按页面记着的、页面没记过的不比,打开请求比页面记着的优先;「未提交的更改」一栏的文件行命令带 `uncommitted`、别的栏带 `other`;页面记着从哪儿打开的、认不得的值当没记过。
|
||||
- 什么时候比(`diff/previewDiff.test.ts`):比完发出去(统计、删掉的块带种类名、一共几行);基准里没有这个文件是新文件;没有基准不发、发过后基准没了发一次 null;旧内容按 key 记着、key 变了重取;同一份文档同一个基准不再比;取不到旧内容记一笔、清掉、下次重取;慢的旧结果不盖掉新的。
|
||||
- 取旧内容(`git/fileAt.test.ts`,真的 git):取的是提交里的、不是工作区改过的;提交里没有这个文件是 null;提交不存在抛错。对比基准的字(`uncommittedFiles.test.ts`、`reviewRules.test.ts`、`changedFiles.test.ts`):未跟踪的按状态认(两种 `git.untrackedChanges` 设置都认)、上一次提交里没有时的三种说明;PR 目标分支的文案;改名的取改名前的路径、PR 里新加的目标分支上没有。「只看改动」开关(`editor/blockFilter.test.ts`):记进 `workspaceState`、关了不记、改了发给所有预览带着眼下的块筛选。
|
||||
- 页面(`diffView.test.ts`、`markdown.test.ts`、`viewState.test.ts`):块按记号认成页面上的 id、找不到的不标、不是这一版不画卡片里的标记,删掉的块按层挂、找不到挂处的和被筛掉的不画,新文件不逐块标,标了改动的默认展开;统计的字;删掉的块收起时的名字;只看改动折哪几段(改过的块下面按层折、删掉的块打断、被筛掉的不算、点开过的和要露出来的不折);各处改动的先后和行、被筛掉的不算;上一处 / 下一处接着走、按视口顶上的行找、到头绕回;带增删的 Markdown 照常排版、跨行逐行包、新加的列表项留住记号。
|
||||
|
||||
Reference in new issue
Block a user