✨ feat(vscode): 代码阅读鼠标停在名字和注释链接上弹出定义所在那块的卡片,别的文件的也行

This commit is contained in:
cruldra committed 2026-10-08 07:17:26 +08:00
1 parent bc7380c716
commit a48b016d73
20 files changed
+1145 -89

No files matched your search

+41 -29
View File
@@ -18,9 +18,27 @@ import { asksOf, historyOf } from './qa'
import { TextPreview } from './TextPreview'
import { tableId } from './viewState'
export interface BlockTreeState {
/**
* 块树里改代码的那部分:哪些块在编辑、点「编辑」、按注释规范重写。页面上的块树才有;定义卡片浮窗里的块树没有,
* 卡片只读,不画右上角的按钮
*/
export interface EditTree {
version: number
editing: ReadonlySet<string>
/** 刚点了「编辑」、要把光标放进去的块 */
focusId: string | null
onFocused: () => void
onToggleEdit: (id: string) => void
/** 按注释规范重写的过程,按块的记号。只在这一页上 */
rewrites: ReadonlyMap<string, RewriteRun>
onRewriteComment: (anchor: string) => void
/** 叫停这块正在进行的重写,不写文件 */
onStopRewrite: (anchor: string) => void
}
export interface BlockTreeState {
/** 能编辑(页面上的块树);定义卡片浮窗里没有 */
edit?: EditTree
/** 眼下折叠着的块 id、属性行 id 和子行 id(propertyRowId、propertyItemId):用户的选择叠在默认上,见 collapsedIds */
collapsed: ReadonlySet<string>
/** 按筛选不画的块(连同子孙),见 applyFilter */
@@ -31,18 +49,9 @@ export interface BlockTreeState {
covered: ReadonlyMap<string, string>
/** 种类叫什么(种类图标的悬停提示和 aria-label):翻译插件给种类起的名字(库规则的种类是规则给的 badge.label),没给就是 id */
kindName: (kind: string) => string
/** 刚点了「编辑」、要把光标放进去的块 */
focusId: string | null
onFocused: () => void
onToggleEdit: (id: string) => void
onToggleFold: (id: string) => void
/** 一次记下几块、几行折叠还是展开(点子行展开一块、同一行里别的收起) */
onSetFolds: (folds: Record<string, boolean>) => void
/** 按注释规范重写的过程,按块的记号。只在这一页上 */
rewrites: ReadonlyMap<string, RewriteRun>
onRewriteComment: (anchor: string) => void
/** 叫停这块正在进行的重写,不写文件 */
onStopRewrite: (anchor: string) => void
/** 问 AI;文件不在工作区文件夹里(问答没地方存)时没有 */
qa?: QaTree
/** 代码差异:新增、修改的块和删掉的块;侧栏开着「未提交的更改」或审查工单、基准里有这个文件时才有 */
@@ -152,7 +161,7 @@ export function BlockLevel({ blocks, owner, tree, slotted = false }: { blocks: B
<BlockCard block={block} tree={tree} />
</ChangeRow>
{tree.qa && <BlockQa key={block.anchor} anchor={block.anchor} qa={tree.qa} />}
<BlockRewrite anchor={block.anchor} tree={tree} />
{tree.edit && <BlockRewrite anchor={block.anchor} edit={tree.edit} />}
{hasShownChildren(block, tree) && !tree.collapsed.has(block.id) && (
<BlockLevel blocks={block.children} owner={block} tree={tree} />
)}
@@ -184,11 +193,11 @@ function BlockQa({ anchor, qa }: { anchor: string, qa: QaTree }): ReactElement {
)
}
function BlockRewrite({ anchor, tree }: { anchor: string, tree: BlockTreeState }): ReactElement | null {
const run = tree.rewrites.get(anchor)
function BlockRewrite({ anchor, edit }: { anchor: string, edit: EditTree }): ReactElement | null {
const run = edit.rewrites.get(anchor)
if (!run)
return null
return <RewriteThread run={run} onStop={() => tree.onStopRewrite(anchor)} />
return <RewriteThread run={run} onStop={() => edit.onStopRewrite(anchor)} />
}
/**
@@ -233,9 +242,10 @@ function cardSlots(block: BlockView, tree: BlockTreeState): GridSlots | undefine
}
}
/** 一块:折叠箭头、种类图标、预览内容或源码、右上角的一排图标按钮(BlockTools)。 */
/** 一块:折叠箭头、种类图标、预览内容或源码、右上角的一排图标按钮(BlockTools,只读的块树没有)。 */
function BlockCard({ block, tree }: { block: BlockView, tree: BlockTreeState }): ReactElement {
const editing = tree.editing.has(block.id)
const { edit } = tree
const editing = edit?.editing.has(block.id) ?? false
const collapsed = tree.collapsed.has(block.id)
// 点父卡片子行才展开的子块:画出来就是展开着的,箭头收起整张
const toggled = block.slot !== undefined
@@ -267,14 +277,14 @@ function BlockCard({ block, tree }: { block: BlockView, tree: BlockTreeState }):
: <span className="w-3.5 shrink-0" />}
<KindIcon concepts={block.concepts} />
<div className="min-w-0 flex-1">
{editing
{edit && editing
? (
<CodeEditor
block={block}
version={tree.version}
autoFocus={tree.focusId === block.id}
onAutoFocused={tree.onFocused}
onExit={() => tree.onToggleEdit(block.id)}
version={edit.version}
autoFocus={edit.focusId === block.id}
onAutoFocused={edit.onFocused}
onExit={() => edit.onToggleEdit(block.id)}
/>
)
: <BlockPreview block={block} tree={tree} marks={tree.diff?.current ? change?.marks : undefined} />}
@@ -285,14 +295,16 @@ function BlockCard({ block, tree }: { block: BlockView, tree: BlockTreeState }):
已被筛选隐藏,临时显示
</span>
)}
<BlockTools
editing={editing}
onToggleEdit={() => tree.onToggleEdit(block.id)}
asking={tree.qa?.state.open.includes(block.anchor)}
onToggleAsk={tree.qa && (() => tree.qa?.onToggle(block.anchor))}
rewriting={tree.rewrites.get(block.anchor)?.status === 'running'}
onRewrite={block.commentStartLine !== undefined ? () => tree.onRewriteComment(block.anchor) : undefined}
/>
{edit && (
<BlockTools
editing={editing}
onToggleEdit={() => edit.onToggleEdit(block.id)}
asking={tree.qa?.state.open.includes(block.anchor)}
onToggleAsk={tree.qa && (() => tree.qa?.onToggle(block.anchor))}
rewriting={edit.rewrites.get(block.anchor)?.status === 'running'}
onRewrite={block.commentStartLine !== undefined ? () => edit.onRewriteComment(block.anchor) : undefined}
/>
)}
</div>
)
}