diff --git a/docs/superpowers/specs/code-reader/spec.md b/docs/superpowers/specs/code-reader/spec.md index 5e72cce..867d256 100644 --- a/docs/superpowers/specs/code-reader/spec.md +++ b/docs/superpowers/specs/code-reader/spec.md @@ -2038,7 +2038,6 @@ interface BlockViewBase { concepts: BlockConcept[] // 认出来的概念,从左到右;webview 按图标名画,不自己用种类查 badge?: KindBadge // 库规则的卡片才有:筛选栏里这个种类的名字,卡片边框的颜色;图标在 concepts 里。和类块一样默认折叠 slot?: { row: number, item: number } // 库规则挂在父卡片子行上的子块才有(RuleSlot):挂在父卡片第 row 行的第 item 个子行上,点它才在这一行下面展开(它的块 id 记成折叠着就是收着) - commentRow?: number // 「注释」一行排第几行,0 起:属性表卡片是 properties 的下标,一行译文的卡片是 rows 的下标;没有注释就没有 commentTarget?: CommentTarget // 「重写注释」写到哪(见「重写注释」);嵌着的代码里的块、语言没给行注释记号又还没有注释的块没有,不给按钮 children: BlockView[] } diff --git a/vscode/src/codeReader/blockView.test.ts b/vscode/src/codeReader/blockView.test.ts index e46a4f5..78ac664 100644 --- a/vscode/src/codeReader/blockView.test.ts +++ b/vscode/src/codeReader/blockView.test.ts @@ -396,7 +396,7 @@ describe('卡片上的「注释」一行', () => { const list = await views(py, 'python', pythonZhTranslator, source) expect(list.some(view => view.kind === 'comment')).toBe(false) const repo = list.find(view => view.kind === 'class') - expect(repo).toMatchObject({ startLine: 12, headerEndLine: 20, commentRow: 1, commentTarget: { kind: 'replace', startLine: 12, endLine: 15 } }) + expect(repo).toMatchObject({ startLine: 12, headerEndLine: 20, commentTarget: { kind: 'replace', startLine: 12, endLine: 15 } }) expect('properties' in repo! && repo.properties.map(row => row.label).slice(0, 3)).toEqual(['名称', '注释', '访问级别']) expect(commentText(repo)).toBe([ 'luffy_agent.user.models.User 在各方法体内按需局部导入 (非模块顶层):', @@ -435,11 +435,11 @@ describe('卡片上的「注释」一行', () => { const [, load] = await views(ts, 'typescript', typescriptZhTranslator, source) expect('properties' in load && load.properties.map(row => row.label).slice(0, 4)).toEqual(['名称', '说明', '注释', '访问级别']) expect(commentText(load)).toBe('讲 load\n\n第二段') - expect(load).toMatchObject({ startLine: 2, commentRow: 2, commentTarget: { kind: 'replace', startLine: 2, endLine: 4 } }) + expect(load).toMatchObject({ startLine: 2, commentTarget: { kind: 'replace', startLine: 2, endLine: 4 } }) const [check, returned] = load.children - expect(check).toMatchObject({ kind: 'if', startLine: 7, commentRow: 0, rows: [{ label: '注释', value: { markdown: '先检查' } }] }) + expect(check).toMatchObject({ kind: 'if', startLine: 7, rows: [{ label: '注释', value: { markdown: '先检查' } }] }) expect(returned).toMatchObject({ kind: 'return', commentTarget: { kind: 'insert', line: 11 } }) - expect(returned).not.toHaveProperty('commentRow') + expect(returned).not.toHaveProperty('rows') }) it('嵌着的代码里的块不能写注释:没有 commentTarget', async () => { diff --git a/vscode/src/codeReader/blockView.ts b/vscode/src/codeReader/blockView.ts index d66982f..1f40833 100644 --- a/vscode/src/codeReader/blockView.ts +++ b/vscode/src/codeReader/blockView.ts @@ -38,11 +38,6 @@ interface BlockViewBase { * 同一个 id 只留第一个。项目入口那一块的第一个换成入口(见 entries/entryMarks.ts)。webview 按这个画图标,不自己用种类查。 */ concepts: BlockConcept[] - /** - * 「注释」一行(讲这块的普通注释,BlockShape.comments)排在第几行,0 起:属性表卡片是 properties 里的下标, - * 一行译文的卡片是 rows 里的下标。没有注释就没有。 - */ - commentRow?: number /** 「重写注释」写到哪(见 CommentTarget);不能写注释的块(嵌着的代码里的、语言没说行注释怎么写又还没有注释的)没有。 */ commentTarget?: CommentTarget /** 库规则的卡片才有:筛选栏里这个种类的名字,卡片边框的颜色(RuleCard.badge)。图标在 concepts 里。预览同类块一样默认收起它的子块。 */ @@ -279,12 +274,11 @@ function blockSpans(list: readonly CodeBlock[], source: string): BlockSpan[] { /** * 「注释」一行插进属性表:排在第一行(名称这类讲它是谁的一行)后面,有说明(值是 Markdown 的一行)时排在说明后面。 - * 返回新的属性表和「注释」一行的下标。 */ -function withCommentRow(rows: readonly PropertyRow[], row: PropertyRow): { rows: PropertyRow[], at: number } { +function withCommentRow(rows: readonly PropertyRow[], row: PropertyRow): PropertyRow[] { const doc = rows.findIndex(item => 'markdown' in item.value) const at = doc >= 0 ? doc + 1 : Math.min(1, rows.length) - return { rows: [...rows.slice(0, at), row, ...rows.slice(at)], at } + return [...rows.slice(0, at), row, ...rows.slice(at)] } /** @@ -395,12 +389,9 @@ export function toBlockViews( return parts.length > 0 ? { label, value: { markdown: parts.join('\n\n') } } : undefined } /** 属性表卡片的属性表连同「注释」一行(见 withCommentRow)。 */ - function cardRows(block: CodeBlock, rows: PropertyRow[]): Pick & { properties: PropertyRow[] } { + function cardRows(block: CodeBlock, rows: PropertyRow[]): { properties: PropertyRow[] } { const row = commentRow(block) - if (!row) - return { properties: rows } - const { rows: properties, at } = withCommentRow(rows, row) - return { properties, commentRow: at } + return { properties: row ? withCommentRow(rows, row) : rows } } /** 「重写注释」写到哪(见 CommentTarget):块前面的普通注释换掉,没有就新写在块上面。 */ function commentTarget(block: CodeBlock): Pick { @@ -416,9 +407,9 @@ export function toBlockViews( return layerDocument.language.lineComment ? { commentTarget: { kind: 'insert', line: block.header.startRow } } : {} } /** 一行译文的卡片:译文、实参表、说明,有注释时下面再排「注释」一行。 */ - function textCard(block: TextBlock): Pick & ReturnType & { rows?: PropertyRow[] } { + function textCard(block: TextBlock): ReturnType & { rows?: PropertyRow[] } { const row = commentRow(block) - return { ...textView(block), ...(row && { rows: [row], commentRow: 0 }) } + return { ...textView(block), ...(row && { rows: [row] }) } } /** 块照它自己的样子(语言插件报的,或库规则认成的属性表块):编辑范围是 span,头部是块自己那部分,子块照常交给各规则看。scope 见 BlockAnchors.place */ diff --git a/vscode/src/codeReader/testSupport.ts b/vscode/src/codeReader/testSupport.ts index 4245d8d..dd5f1c3 100644 --- a/vscode/src/codeReader/testSupport.ts +++ b/vscode/src/codeReader/testSupport.ts @@ -118,11 +118,12 @@ export function viewLines(blocks: readonly BlockView[], indent = ''): string[] { }) } -/** 卡片上「注释」一行的 Markdown 原文(BlockView.commentRow);没有就是 undefined。 */ +/** 卡片上「注释」一行(中文翻译插件给它起的名字就是「注释」)的 Markdown 原文;没有就是 undefined。 */ export function commentText(view: BlockView | undefined): string | undefined { - if (!view || view.commentRow === undefined) + if (!view) return undefined - const row = 'properties' in view ? view.properties[view.commentRow] : view.rows?.[view.commentRow] + const rows = 'properties' in view ? view.properties : view.rows ?? [] + const row = rows.find(item => item.label === '注释') return row && 'markdown' in row.value ? row.value.markdown : undefined } diff --git a/vscode/webview-ui/src/codeReader/BlockTree.test.tsx b/vscode/webview-ui/src/codeReader/BlockTree.test.tsx index aa762ed..b7c1d61 100644 --- a/vscode/webview-ui/src/codeReader/BlockTree.test.tsx +++ b/vscode/webview-ui/src/codeReader/BlockTree.test.tsx @@ -120,7 +120,6 @@ describe('「注释」一行和「重写注释」按钮', () => { it('属性表卡片:「注释」一行照属性表画,按钮在右上角那排,不在这一行上', () => { const card = view('1', 'function', '', { properties: [{ label: '名称', value: [{ text: 'find', role: 'function' }] }, comment, { label: '异步', value: [{ text: '否', role: 'storage' }] }], - commentRow: 1, commentTarget: { kind: 'replace', startLine: 0, endLine: 0 }, }) const markup = html(card) @@ -129,7 +128,7 @@ describe('「注释」一行和「重写注释」按钮', () => { }) it('一行译文的卡片:「注释」一行排在译文下面,按钮同样在右上角那排', () => { - const markup = html(view('2', 'statement', 'save()', { rows: [comment], commentRow: 0, commentTarget: { kind: 'replace', startLine: 0, endLine: 0 } })) + const markup = html(view('2', 'statement', 'save()', { rows: [comment], commentTarget: { kind: 'replace', startLine: 0, endLine: 0 } })) expect(markup.indexOf('save()')).toBeLessThan(markup.indexOf('按名字找')) inToolbar(markup, '按注释规范重写') }) diff --git a/vscode/webview-ui/src/codeReader/types.ts b/vscode/webview-ui/src/codeReader/types.ts index a4e85b2..8d256ef 100644 --- a/vscode/webview-ui/src/codeReader/types.ts +++ b/vscode/webview-ui/src/codeReader/types.ts @@ -143,8 +143,6 @@ interface BlockViewBase { attributes: Record /** 这块认出来的概念,从左到右。webview 按图标名画,不自己用种类查 */ concepts: BlockConcept[] - /** 「注释」一行(讲这块的普通注释)排在第几行,0 起:属性表卡片是 properties 里的下标,一行译文的卡片是 rows 里的下标;没有注释就没有 */ - commentRow?: number /** 「重写注释」写到哪(扩展端用,这边只看有没有、是换掉还是新写);没有就不显示按钮 */ commentTarget?: CommentTarget /** 库规则的卡片才有:卡片边框的颜色,筛选栏里这个种类的名字。和类块一样默认收起子块 */