✨ feat(vscode): 代码阅读的链式调用卡片:语言插件读链、翻译模板排成起点和步骤
契约加 LanguageAdapter.chain、Translator.chain、RuleContext.chain、PropertyRow.chain、TextTranslation.rows;跨行写或实参里有闭包的链排成卡片,连着同名调用合成一步列出每次实参,注释挂在步骤上,闭包收起、子块挂到那一步(BlockView.step);Rust 插件读链、标准库常见方法写中文名;挤成一行时另起一行的 . 贴着前面
This commit is contained in:
1 parent
80eda7c18e
commit
ee595f3da9
16 files changed
+1041
-72
No files matched your search
@@ -4,7 +4,7 @@
|
||||
|
||||
import type { ClaudeImage } from '../../cc/spawnClaude'
|
||||
import type { FileAttribute } from '../attributes'
|
||||
import type { BlockSlot, CallTreeTarget, CommentTarget, SourceColors } from '../blockView'
|
||||
import type { BlockSlot, CallTreeTarget, ChainSlot, CommentTarget, SourceColors } from '../blockView'
|
||||
import type { ContractMiss } from '../callTree/endpoint'
|
||||
import type { CallTree } from '../callTree/model'
|
||||
import type { BlockAttributes, BlockConcept, KindBadge, Markdown, PreviewTable, PreviewText, PropertyItem, PropertyRow, SourceRange } from '../contract'
|
||||
@@ -85,6 +85,7 @@ interface PageCardBase {
|
||||
commentTarget?: CommentTarget['kind']
|
||||
badge?: KindBadge
|
||||
slot?: BlockSlot
|
||||
step?: ChainSlot
|
||||
callTree?: CallTreeTarget
|
||||
}
|
||||
|
||||
|
||||
@@ -3,8 +3,10 @@ import type { PageBlock } from './messages'
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import { toBlockViews } from '../blockView'
|
||||
import { createPythonAdapter } from '../languages/python'
|
||||
import { createRustAdapter } from '../languages/rust'
|
||||
import { WASM_DIR, withBlocks } from '../testSupport'
|
||||
import { pythonZhTranslator } from '../translators/pythonZh'
|
||||
import { rustZhTranslator } from '../translators/rustZh'
|
||||
import { pageBlocks } from './pageBlocks'
|
||||
|
||||
const py = createPythonAdapter(WASM_DIR)
|
||||
@@ -67,3 +69,22 @@ describe('发给页面的块带内容指纹:连子块、在源码里占的地
|
||||
expect(changed(before, hashes(await page(SOURCE.replace('os.getenv(key)', 'os.getenv(name)'))))).toEqual(['2', '2.0', '2.0.0', '2.0.0.0'])
|
||||
})
|
||||
})
|
||||
|
||||
describe('链式调用卡片发给页面', () => {
|
||||
const rust = createRustAdapter(WASM_DIR)
|
||||
|
||||
it('起点、各步的叫法和范围里的下标也从块的开头算,挂在链某一步下面的子块带着 step', async () => {
|
||||
const source = 'fn f() {\n rows.iter()\n .for_each(|r| {\n show(r);\n });\n}\n'
|
||||
const views = await withBlocks(rust, 'rust', source, blocks => toBlockViews(blocks, { source, language: rust, markers: [] }, rustZhTranslator))
|
||||
const [fn] = pageBlocks(views, source)
|
||||
const [statement] = fn?.children ?? []
|
||||
const base = source.indexOf(' rows')
|
||||
const rows = statement && 'translation' in statement ? statement.rows ?? [] : []
|
||||
expect(rows[0]?.value).toEqual([{ text: 'rows', role: 'variable', offset: source.indexOf('rows') - base }])
|
||||
const [, forEach] = rows[1]?.chain ?? []
|
||||
const [label] = forEach?.name ?? []
|
||||
expect(label && 'role' in label ? label.refers : undefined).toEqual({ startIndex: source.indexOf('for_each') - base, endIndex: source.indexOf('for_each') + 'for_each'.length - base })
|
||||
expect(forEach?.range).toEqual({ startIndex: source.indexOf('.for_each') - base, endIndex: source.indexOf(';\n}') - base })
|
||||
expect(statement?.children[0]?.step).toEqual({ row: 1, step: 1 })
|
||||
})
|
||||
})
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { BlockView } from '../blockView'
|
||||
import type { Inline, PreviewTable, PreviewText, PropertyItem, PropertyRow, Segment, SourceRange } from '../contract'
|
||||
import type { ChainStep, Inline, PreviewTable, PreviewText, PropertyItem, PropertyRow, Segment, SourceRange } from '../contract'
|
||||
import type { BlockMarks, ItemDiff, ItemsDiff, RowDiff, RowsDiff, TextDiff } from '../diff/viewDiff'
|
||||
import type { BlockSpan, PageBlock, PageCard } from './messages'
|
||||
import { createHash } from 'node:crypto'
|
||||
@@ -70,6 +70,19 @@ function shiftRow(row: PropertyRow, base: number): PropertyRow {
|
||||
value: shiftText(row.value, base),
|
||||
...(row.defines && { defines: shiftRange(row.defines, base) }),
|
||||
...(row.items && { items: row.items.map(item => shiftItem(item, base)) }),
|
||||
...(row.chain && { chain: row.chain.map(step => shiftStep(step, base)) }),
|
||||
}
|
||||
}
|
||||
|
||||
function shiftStep(step: ChainStep, base: number): ChainStep {
|
||||
return {
|
||||
...step,
|
||||
name: shiftInline(step.name, base),
|
||||
value: shiftInline(step.value, base),
|
||||
...(step.lines && { lines: step.lines.map(line => shiftInline(line, base)) }),
|
||||
...(step.rows && { rows: step.rows.map(row => shiftRow(row, base)) }),
|
||||
...(step.table && { table: shiftTable(step.table, base) }),
|
||||
range: shiftRange(step.range, base),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -85,6 +98,7 @@ export function pageCard(block: BlockView, base: number): PageCard {
|
||||
...(block.commentTarget && { commentTarget: block.commentTarget.kind }),
|
||||
...(block.badge && { badge: block.badge }),
|
||||
...(block.slot && { slot: block.slot }),
|
||||
...(block.step && { step: block.step }),
|
||||
...(block.callTree && { callTree: block.callTree }),
|
||||
}
|
||||
if ('properties' in block)
|
||||
|
||||
Reference in new issue
Block a user