✨ feat(vscode): 代码阅读的调用嵌套:实参的值又是跨多行的调用时在值那一格里写它的一行、套它的实参表,一层层往下套;埋在式子里后面还跟着东西的调用括起来

This commit is contained in:
cruldra committed 2026-09-27 22:31:35 +08:00
1 parent dc100692b3
commit 285d711740
16 files changed
+471 -55

No files matched your search

@@ -11,7 +11,7 @@ import { KindIcon } from './kindIcons'
import { PropertyGrid, PropertyTable } from './PropertyGrid'
import { asksOf, historyOf } from './qa'
import { TextPreview } from './TextPreview'
import { translationTableId } from './viewState'
import { tableId } from './viewState'
export interface BlockTreeState {
version: number
@@ -125,7 +125,7 @@ function BlockPreview({ block, tree }: { block: BlockView, tree: BlockTreeState
<TextPreview text={block.translation} />
{block.table && (
<div className="mt-[3px]">
<PropertyTable parentId={translationTableId(block.id)} columns={block.table.columns} items={block.table.items} />
<PropertyTable parentId={tableId(block.id)} columns={block.table.columns} items={block.table.items} />
</div>
)}
{block.doc && <TextPreview text={block.doc} className="mt-0.5" />}
@@ -6,7 +6,7 @@ import { inlineText } from './segments'
import { SegmentText } from './SegmentText'
import { subRowsLayout, tableCells, tableTemplate } from './subRows'
import { TextPreview } from './TextPreview'
import { propertyItemId, propertyRowId } from './viewState'
import { propertyItemId, propertyRowId, tableId } from './viewState'
/** 列表子行里除最后一列以外各列的宽度(字典的键),最后一列占满剩下的;编辑区窄时按比例收,不把最后一列挤没 */
const CELL_WIDTHS = ['min(150px, 28%)', 'min(220px, 38%)']
@@ -96,7 +96,8 @@ function PropertyItems({ parentId, items, folding }: { parentId: string, items:
/**
* 给了列名的子行(输入参数、数据表的字段)排成表格:第一行是表头(列名),下面每个子行一行;外框圆角,格子之间、行之间一条分隔线。
* 列宽按整列的内容定(见 tableTemplate),最后一列分剩下的,长了在格子里换行。一行译文下面摊开实参的表也用它。
* 列宽按整列的内容定(见 tableTemplate),最后一列分剩下的,长了在格子里换行。一行译文下面摊开实参的表也用它;
* 行带 table(实参的值里跨几行写的调用)时,那张表排在最后一格里、文字下面,往右缩一点,一层层往下套。
*/
export function PropertyTable({ parentId, columns, items }: { parentId: string, columns: string[], items: PropertyItem[] }): ReactElement {
return (
@@ -105,15 +106,28 @@ export function PropertyTable({ parentId, columns, items }: { parentId: string,
<div className="cr-table-head" role="row">
{columns.map((name, i) => <span key={i} className="cr-table-cell" role="columnheader">{name}</span>)}
</div>
{items.map((item, index) => (
<div key={index} className="cr-table-row" role="row" data-id={propertyItemId(parentId, index)}>
{tableCells(item, columns).map((cell, i) => (
<p key={i} className="cr-table-cell cr-code min-w-0" role="cell">
<SegmentText segments={cell} />
</p>
))}
</div>
))}
{items.map((item, index) => {
const id = propertyItemId(parentId, index)
const cells = tableCells(item, columns)
return (
<div key={index} className="cr-table-row" role="row" data-id={id}>
{cells.map((cell, i) => item.table && i === cells.length - 1
? (
<div key={i} className="cr-table-cell flex min-w-0 flex-col gap-[3px]" role="cell">
<p className="cr-code">
<SegmentText segments={cell} />
</p>
<PropertyTable parentId={tableId(id)} columns={item.table.columns} items={item.table.items} />
</div>
)
: (
<p key={i} className="cr-table-cell cr-code min-w-0" role="cell">
<SegmentText segments={cell} />
</p>
))}
</div>
)
})}
</div>
</div>
)
@@ -105,6 +105,17 @@ describe('跳到定义:滚到哪块、展开哪些', () => {
expect(occurrencePlan(blocks, { start: 40, end: 42, kind: 'read' }, () => false)).toEqual({ id: '0.0', expand: ['0'] })
})
it('名字在值那一格里套着的实参表里(套了几层都算):一行译文下面的不用展开,变量初始值那一行下面的展开那一行', () => {
const leaf = { columns: ['参数', '值'], items: [{ cells: [[name('mp_app_secret', 70)], [name('secret', 90)]] }] }
const nested = { columns: ['参数', '值'], items: [{ cells: [[name('credentials', 50)], [word('新建'), name('CredentialPresence', 62)]], table: { columns: ['参数', '值'], items: [{ cells: [[name('inner', 66)], [word('新建')]], table: leaf }] } }] }
const blocks: BlockView[] = [
{ ...textBlock('0', 'return', 0, [word('返回'), word('新建'), name('Diagnostic', 10)]), table: nested },
factBlock('1', 'variable', 5, [{ label: '初始值', value: [word('新建'), name('Diagnostic', 110)], columns: ['参数', '值'], items: nested.items }]),
]
expect(revealPlan(blocks, 9, 90)).toEqual({ id: '0', expand: [] })
expect(occurrencePlan(blocks, { start: 70, end: 83, kind: 'read' }, id => id === '0')).toEqual({ id: '1', expand: ['1/p0'] })
})
it('名字在框里(套了几层都算)也是显示着它', () => {
const inner = { style: 'iteration' as const, label: '列表', segments: [word('遍历'), name('row', 30), word('取'), name('y', 40)] }
const blocks: BlockView[] = [
+7 -4
View File
@@ -38,9 +38,9 @@ function shows(text: PreviewText, offset: number): boolean {
return !('markdown' in text) && showsOffset(text, offset)
}
/** 一行译文下面那张表(总是展开的)里有格子满足 test。 */
/** 实参表(一行译文下面那张、值那一格里套着的,都总是展开的)里有格子满足 test,套着的表一层层都算。 */
function tableShows(table: PreviewTable | undefined, test: (cell: PreviewText) => boolean): boolean {
return table?.items.some(item => item.cells.some(test)) ?? false
return table?.items.some(item => item.cells.some(test) || tableShows(item.table, test)) ?? false
}
/**
@@ -87,10 +87,13 @@ function definingItem(items: PropertyItem[] | undefined, parentId: string, offse
return undefined
}
/** parentId 下面一层层的子行里,哪个的格子满足 test(显示着要找的名字):要展开的各层(parentId 到那个子行所在的那一层)。 */
/**
* parentId 下面一层层的子行里,哪个的格子(连它值那一格里套着的实参表)满足 test(显示着要找的名字):
* 要展开的各层(parentId 到那个子行所在的那一层)。
*/
function showingItem(items: PropertyItem[] | undefined, parentId: string, test: (cell: PreviewText) => boolean): string[] | undefined {
for (const [index, item] of (items ?? []).entries()) {
if (item.cells.some(test))
if (item.cells.some(test) || tableShows(item.table, test))
return [parentId]
const inner = showingItem(item.items, propertyItemId(parentId, index), test)
if (inner)
@@ -58,6 +58,8 @@ export interface PropertyItem extends Defines {
cells: Inline[][]
/** 展开在这个子行下面的下一层子行(字典 / 对象的值又是字典 / 对象时,它的各项),一层层可以一直往下套 */
items?: PropertyItem[]
/** 排在这一行最后一格里、那格文字下面的表(实参的值里跨几行写的调用的实参表),表里的行又可以带 table;总是展开 */
table?: PreviewTable
}
/**
@@ -91,7 +91,10 @@ export function propertyItemId(parentId: string, itemIndex: number): string {
return `${parentId}/${itemIndex}`
}
/** 一行译文下面那张表(跨几行写的调用的实参)的 id:表里各行的 id 是 propertyItemId(它, 行号)。这张表总是展开的。 */
export function translationTableId(blockId: string): string {
return `${blockId}/t`
/**
* 实参表的 id:一行译文下面那张(owner 是块 id),或实参表里一行的值那一格里套着的那张(owner 是那一行的 id);
* 表里各行的 id 是 propertyItemId(它, 行号)。这两种表总是展开的。
*/
export function tableId(ownerId: string): string {
return `${ownerId}/t`
}