✨ feat(vscode): 代码阅读的调用与构造:跨多行写的调用排成「新建 / 调用 名字 · N 个参数」一行,实参摊成参数 / 值表;Python 查被调用名字的定义分新建和调用,查到后刷新
This commit is contained in:
1 parent
ebf228cdc7
commit
ecc415d763
30 files changed
+1033
-157
No files matched your search
@@ -8,9 +8,10 @@ import { AskThread } from './AskThread'
|
||||
import { BlockTools } from './BlockTools'
|
||||
import { CodeEditor } from './CodeEditor'
|
||||
import { KindIcon } from './kindIcons'
|
||||
import { PropertyGrid } from './PropertyGrid'
|
||||
import { PropertyGrid, PropertyTable } from './PropertyGrid'
|
||||
import { asksOf, historyOf } from './qa'
|
||||
import { TextPreview } from './TextPreview'
|
||||
import { translationTableId } from './viewState'
|
||||
|
||||
export interface BlockTreeState {
|
||||
version: number
|
||||
@@ -112,13 +113,21 @@ function BlockQa({ anchor, qa }: { anchor: string, qa: QaTree }): ReactElement {
|
||||
)
|
||||
}
|
||||
|
||||
/** 预览状态的内容:函数、类、枚举、导入、常量、变量块和库规则的卡片是属性表,其余是一行译文,带说明的译文下面接着说明。 */
|
||||
/**
|
||||
* 预览状态的内容:函数、类、枚举、导入、常量、变量块和库规则的卡片是属性表,其余是一行译文;
|
||||
* 译文下面依次接着摊开实参的表(跨几行写的调用)、说明。
|
||||
*/
|
||||
function BlockPreview({ block, tree }: { block: BlockView, tree: BlockTreeState }): ReactElement {
|
||||
if ('properties' in block)
|
||||
return <PropertyGrid blockId={block.id} rows={block.properties} collapsed={tree.collapsed} onToggleFold={tree.onToggleFold} />
|
||||
return (
|
||||
<>
|
||||
<TextPreview text={block.translation} />
|
||||
{block.table && (
|
||||
<div className="mt-[3px]">
|
||||
<PropertyTable parentId={translationTableId(block.id)} columns={block.table.columns} items={block.table.items} />
|
||||
</div>
|
||||
)}
|
||||
{block.doc && <TextPreview text={block.doc} className="mt-0.5" />}
|
||||
</>
|
||||
)
|
||||
|
||||
@@ -96,9 +96,9 @@ function PropertyItems({ parentId, items, folding }: { parentId: string, items:
|
||||
|
||||
/**
|
||||
* 给了列名的子行(输入参数、数据表的字段)排成表格:第一行是表头(列名),下面每个子行一行;外框圆角,格子之间、行之间一条分隔线。
|
||||
* 列宽按整列的内容定(见 tableTemplate),最后一列分剩下的,长了在格子里换行。
|
||||
* 列宽按整列的内容定(见 tableTemplate),最后一列分剩下的,长了在格子里换行。一行译文下面摊开实参的表也用它。
|
||||
*/
|
||||
function PropertyTable({ parentId, columns, items }: { parentId: string, columns: string[], items: PropertyItem[] }): ReactElement {
|
||||
export function PropertyTable({ parentId, columns, items }: { parentId: string, columns: string[], items: PropertyItem[] }): ReactElement {
|
||||
return (
|
||||
<div className="pl-[5px]">
|
||||
<div className="cr-table" role="table" style={{ gridTemplateColumns: tableTemplate(columns.length) }}>
|
||||
|
||||
@@ -95,6 +95,16 @@ describe('跳到定义:滚到哪块、展开哪些', () => {
|
||||
expect(revealPlan(BLOCKS, 4, 102)).toEqual({ id: '1.0.0', expand: ['1', '1.0'] })
|
||||
})
|
||||
|
||||
it('名字在一行译文下面那张表里(跨几行写的调用的实参):表总是展开的,目标是那块,不用展开什么', () => {
|
||||
const call: BlockView = {
|
||||
...textBlock('0.0', 'return', 1, [word('返回'), word('新建'), name('UserDetailResponse', 10)]),
|
||||
table: { columns: ['参数', '值'], items: [{ cells: [[name('id', 40)], [name('user', 43), { text: '.', role: 'plain' }, name('id', 48)]] }] },
|
||||
}
|
||||
const blocks = [textBlock('0', 'if', 0, [word('如果'), name('user', 3)], [call])]
|
||||
expect(revealPlan(blocks, 9, 48)).toEqual({ id: '0.0', expand: ['0'] })
|
||||
expect(occurrencePlan(blocks, { start: 40, end: 42, kind: 'read' }, () => false)).toEqual({ id: '0.0', expand: ['0'] })
|
||||
})
|
||||
|
||||
it('名字在框里(套了几层都算)也是显示着它', () => {
|
||||
const inner = { style: 'iteration' as const, label: '列表', segments: [word('遍历'), name('row', 30), word('取'), name('y', 40)] }
|
||||
const blocks: BlockView[] = [
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { BlockView, Occurrence, PreviewText, PropertyItem, SourceRange } from './types'
|
||||
import type { BlockView, Occurrence, PreviewTable, PreviewText, PropertyItem, SourceRange } from './types'
|
||||
import { blockPath } from './filter'
|
||||
import { showsOccurrence } from './occurrences'
|
||||
import { showsOffset } from './segments'
|
||||
@@ -38,19 +38,24 @@ function shows(text: PreviewText, offset: number): boolean {
|
||||
return !('markdown' in text) && showsOffset(text, offset)
|
||||
}
|
||||
|
||||
/** 一行译文下面那张表(总是展开的)里有格子满足 test。 */
|
||||
function tableShows(table: PreviewTable | undefined, test: (cell: PreviewText) => boolean): boolean {
|
||||
return table?.items.some(item => item.cells.some(test)) ?? false
|
||||
}
|
||||
|
||||
/**
|
||||
* 块里哪儿是 offset 处的定义,从具体到笼统:
|
||||
* ① 块自己的名字(函数名、类名、只声明一个变量时的变量名)→ 整块;
|
||||
* ② 属性表里讲这个定义的一行 / 子行(defines 盖住 offset:参数、导入项、多变量声明里的一个、对象一项的键)→ 只闪它,
|
||||
* 子行连它上面的各层(所在的行、嵌套时外层的子行)一起展开;
|
||||
* ③ 块里只是显示着这个名字(一行译文里的循环变量、没填 defines 的翻译插件)→ 整块,名字在子行里时展开它上面的各层。
|
||||
* ③ 块里只是显示着这个名字(一行译文和它下面的表里的名字、没填 defines 的翻译插件)→ 整块,名字在子行里时展开它上面的各层。
|
||||
* 不在这块里是 undefined。
|
||||
*/
|
||||
function locate(block: BlockView, offset: number): Spot | undefined {
|
||||
if (covers(block.defines, offset))
|
||||
return { expand: [] }
|
||||
if ('translation' in block)
|
||||
return shows(block.translation, offset) ? { expand: [] } : undefined
|
||||
return shows(block.translation, offset) || tableShows(block.table, cell => shows(cell, offset)) ? { expand: [] } : undefined
|
||||
const rows = block.properties.map((row, index) => ({ row, id: propertyRowId(block.id, index) }))
|
||||
for (const { row, id } of rows) {
|
||||
if (covers(row.defines, offset))
|
||||
@@ -120,10 +125,10 @@ export function uncoveredPlan(plan: RevealPlan, covered: ReadonlyMap<string, str
|
||||
return owner === undefined ? plan : { id: owner, expand: blockPath(owner).slice(0, -1) }
|
||||
}
|
||||
|
||||
/** 块里哪儿显示着满足 test 的文字(译文、属性行的值、各层子行的格子):要展开的属性行和子行;不在这块里是 undefined。 */
|
||||
/** 块里哪儿显示着满足 test 的文字(译文和它下面的表、属性行的值、各层子行的格子):要展开的属性行和子行;不在这块里是 undefined。 */
|
||||
function showingSpot(block: BlockView, test: (text: PreviewText) => boolean): string[] | undefined {
|
||||
if ('translation' in block)
|
||||
return test(block.translation) ? [] : undefined
|
||||
return test(block.translation) || tableShows(block.table, test) ? [] : undefined
|
||||
for (const [index, row] of block.properties.entries()) {
|
||||
if (test(row.value))
|
||||
return []
|
||||
|
||||
@@ -71,6 +71,12 @@ export interface PropertyRow extends Defines {
|
||||
columns?: string[]
|
||||
}
|
||||
|
||||
/** 一张带表头和边框的表:列名,每行几列对齐的格子,同 PropertyRow 给了 columns 的子行 */
|
||||
export interface PreviewTable {
|
||||
columns: string[]
|
||||
items: PropertyItem[]
|
||||
}
|
||||
|
||||
/** 一种颜色在暗色、亮色主题下各用哪个(CSS 颜色值);高对比主题跟着暗 / 亮走 */
|
||||
export interface ThemeColor { dark: string, light: string }
|
||||
|
||||
@@ -108,9 +114,9 @@ interface BlockViewBase {
|
||||
|
||||
/**
|
||||
* 函数、类、枚举、导入、常量、变量块和库规则的卡片预览时是属性表,注释块是 Markdown 说明,其余是一行译文;
|
||||
* 一行译文的块带说明时 doc 是说明的 Markdown 原文,排在译文下面
|
||||
* 一行译文下面依次是:跨几行写的调用摊开各个实参的表(table),块的说明(doc,Markdown 原文)
|
||||
*/
|
||||
export type BlockView = BlockViewBase & ({ translation: PreviewText, doc?: Markdown } | { properties: PropertyRow[] })
|
||||
export type BlockView = BlockViewBase & ({ translation: PreviewText, table?: PreviewTable, doc?: Markdown } | { properties: PropertyRow[] })
|
||||
|
||||
export interface TranslatorOption { id: string, label: string }
|
||||
|
||||
|
||||
@@ -90,3 +90,8 @@ export function propertyRowId(blockId: string, rowIndex: number): string {
|
||||
export function propertyItemId(parentId: string, itemIndex: number): string {
|
||||
return `${parentId}/${itemIndex}`
|
||||
}
|
||||
|
||||
/** 一行译文下面那张表(跨几行写的调用的实参)的 id:表里各行的 id 是 propertyItemId(它, 行号)。这张表总是展开的。 */
|
||||
export function translationTableId(blockId: string): string {
|
||||
return `${blockId}/t`
|
||||
}
|
||||
Reference in new issue
Block a user