✨ feat(vscode): 代码阅读的调用嵌套:实参的值又是跨多行的调用时在值那一格里写它的一行、套它的实参表,一层层往下套;埋在式子里后面还跟着东西的调用括起来
This commit is contained in:
1 parent
dc100692b3
commit
285d711740
16 files changed
+471
-55
No files matched your search
@@ -3,7 +3,7 @@ import type { ZhTable } from './zhTemplate'
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import { createPythonAdapter } from '../languages/python'
|
||||
import { createTypeScriptAdapter } from '../languages/typescript'
|
||||
import { flatSegments, propertyLines, readFixture, segmentText, walk, WASM_DIR, withBlocks } from '../testSupport'
|
||||
import { flatSegments, propertyLines, readFixture, segmentText, tableLines, walk, WASM_DIR, withBlocks } from '../testSupport'
|
||||
import { pythonZhTranslator } from './pythonZh'
|
||||
import { typescriptZhTranslator } from './typescriptZh'
|
||||
import { createZhTemplateTranslator } from './zhTemplate'
|
||||
@@ -1049,10 +1049,6 @@ describe('跨几行写的调用', () => {
|
||||
}
|
||||
}
|
||||
|
||||
function tableLines(table: PreviewTable | undefined): string[] {
|
||||
return (table?.items ?? []).map(item => item.cells.map(segmentText).join(' | '))
|
||||
}
|
||||
|
||||
const USER_DETAIL = [
|
||||
'id | user.id',
|
||||
'username | user.username',
|
||||
@@ -1146,21 +1142,125 @@ describe('跨几行写的调用', () => {
|
||||
expect(asked).not.toContain('file.read')
|
||||
})
|
||||
|
||||
it('*x 写「展开」、**x 写「展开关键字」,「第 N 个」只数按位置传的;实参里的调用不再排成表', async () => {
|
||||
it('*x 写「展开」、**x 写「展开关键字」,「第 N 个」只数按位置传的', async () => {
|
||||
const source = [
|
||||
'run(',
|
||||
' first,',
|
||||
' *rest,',
|
||||
' second,',
|
||||
' key=Inner(',
|
||||
' x=1,',
|
||||
' ),',
|
||||
' key=value,',
|
||||
' **options,',
|
||||
')',
|
||||
].join('\n')
|
||||
const line = (await translateAll(py, 'python', pythonZhTranslator, source)).get(1)
|
||||
expect(text(line?.segments)).toBe('调用 run · 5 个参数')
|
||||
expect(tableLines(line?.table)).toEqual(['第 1 个 | first', '展开 | rest', '第 2 个 | second', 'key | Inner( x=1 )', '展开关键字 | options'])
|
||||
expect(tableLines(line?.table)).toEqual(['第 1 个 | first', '展开 | rest', '第 2 个 | second', 'key | value', '展开关键字 | options'])
|
||||
})
|
||||
|
||||
it('嵌套:实参的值是跨几行写的调用(可以带 await)时,值那一格写它的一行,它的实参表排在格子里;一行写完的调用、只是式子里有调用的照旧一行', async () => {
|
||||
const payment = readFixture('paymentConsoleRoutes.py')
|
||||
const { asked, calleeKind } = kinds({ PaymentCapabilityDiagnostic: 'class', CredentialPresence: 'class' })
|
||||
const line = (await translateAll(py, 'python', pythonZhTranslator, payment, calleeKind)).get(64)
|
||||
expect(text(line?.segments)).toBe('返回 新建 PaymentCapabilityDiagnostic · 15 个参数')
|
||||
expect(tableLines(line?.table)).toEqual([
|
||||
'native_enabled | bool(settings.WECHAT_PAY_MCH_ID)',
|
||||
'h5_enabled | settings.WECHAT_H5_ENABLED',
|
||||
'jsapi_enabled | settings.WECHAT_JSAPI_ENABLED',
|
||||
'jsapi_ready | jsapi_ready(settings)',
|
||||
'pay_app_id_masked | _mask_app_id(settings.WECHAT_PAY_APP_ID)',
|
||||
'mp_app_id_masked | _mask_app_id(settings.WECHAT_MP_APP_ID)',
|
||||
'credentials_present | 新建 CredentialPresence · 4 个参数',
|
||||
' mp_app_secret | bool(_secret_text(settings.WECHAT_MP_APP_SECRET))',
|
||||
' wechat_pay_api_v3_key | bool(settings.WECHAT_PAY_API_V3_KEY)',
|
||||
// 跨了两行、却是式子不是一次调用:照旧一行
|
||||
' wechat_pay_private_key | bool(private_key_path) 并且 Path(private_key_path).is_file()',
|
||||
' jsapi_intent_master_key | _intent_key_present(settings)',
|
||||
'oauth_callback_host | oauth_host',
|
||||
'pay_origin | pay_origin',
|
||||
'allowed_pay_origins | allowed',
|
||||
'jsapi_auth_dir_hint | ⟦列表|遍历 hint_origins 的每个 origin,仅当 origin,取 f"{origin}/"⟧',
|
||||
'domain_whitelist | "unknown_manual_check"',
|
||||
'merchant_binding | "unknown_manual_check"',
|
||||
'recovery_required_count | count',
|
||||
'recovery_required_earliest | earliest',
|
||||
])
|
||||
expect(line?.table?.columns).toEqual(['参数', '值'])
|
||||
// 里层和外层一样:问定义分新建和调用,名字带源码下标
|
||||
expect(asked).toEqual(expect.arrayContaining(['PaymentCapabilityDiagnostic', 'CredentialPresence']))
|
||||
const nested = line?.table?.items[6]
|
||||
expect(nested?.table?.columns).toEqual(['参数', '值'])
|
||||
expect(nested?.cells[1].find(piece => 'role' in piece && piece.text === 'CredentialPresence')).toEqual({ text: 'CredentialPresence', role: 'type', offset: payment.indexOf('CredentialPresence(', payment.indexOf('credentials_present=')) })
|
||||
expect(nested?.table?.items[0].cells[0]).toEqual([{ text: 'mp_app_secret', role: 'variable', offset: payment.indexOf('mp_app_secret=') }])
|
||||
const unresolved = (await translateAll(py, 'python', pythonZhTranslator, payment)).get(64)
|
||||
expect(segmentText(unresolved?.table?.items[6].cells[1] ?? [])).toBe('调用 CredentialPresence · 4 个参数')
|
||||
})
|
||||
|
||||
it('嵌套一层层往下套;await 的调用写「等待」', async () => {
|
||||
const source = [
|
||||
'return Outer(',
|
||||
' inner=Middle(',
|
||||
' leaf=Leaf(',
|
||||
' value=1,',
|
||||
' ),',
|
||||
' flag=await fetch(',
|
||||
' key,',
|
||||
' ),',
|
||||
' ),',
|
||||
')',
|
||||
].join('\n')
|
||||
const { asked, calleeKind } = kinds({ Outer: 'class', Middle: 'class', Leaf: 'class' })
|
||||
const line = (await translateAll(py, 'python', pythonZhTranslator, source, calleeKind)).get(1)
|
||||
expect(text(line?.segments)).toBe('返回 新建 Outer · 1 个参数')
|
||||
expect(tableLines(line?.table)).toEqual([
|
||||
'inner | 新建 Middle · 2 个参数',
|
||||
' leaf | 新建 Leaf · 1 个参数',
|
||||
' value | 1',
|
||||
' flag | 等待 调用 fetch · 1 个参数',
|
||||
' 第 1 个 | key',
|
||||
])
|
||||
expect([...asked].sort()).toEqual(['Leaf', 'Middle', 'Outer', 'fetch'])
|
||||
})
|
||||
|
||||
it('埋在式子里的跨几行调用也排:后面紧跟着同一个式子的别的部分(.x()、[0]、or)时整行括起来,后面是分隔符或什么都没有时不括', async () => {
|
||||
const chained = readFixture('chainedCalls.py')
|
||||
const rows = await describeAll(py, 'python', pythonZhTranslator, chained)
|
||||
expect(propertyLines(rows.get(18) ?? []).slice(1)).toEqual([
|
||||
'初始值: (调用 base64.b64encode · 1 个参数).decode()',
|
||||
' 第 1 个 | f"{admin_user}:{admin_password}".encode()',
|
||||
])
|
||||
// 调用跨几行的是外面那次:被调用的里面那次调用照旧一行,挤成一行时圆括号贴着里面的内容
|
||||
expect(propertyLines(rows.get(55) ?? []).slice(1, 2)).toEqual(['初始值: 等待 调用 config.get_payment_driver(order.payment_method).query_refund_status · 2 个参数'])
|
||||
|
||||
const source = [
|
||||
'first = make(',
|
||||
' a,',
|
||||
')[0]',
|
||||
'either = make(',
|
||||
' a,',
|
||||
') or fallback',
|
||||
'other = fallback or make(',
|
||||
' a,',
|
||||
')',
|
||||
'items = [',
|
||||
' make(',
|
||||
' a,',
|
||||
' ),',
|
||||
' b,',
|
||||
']',
|
||||
'run(',
|
||||
' key=Model(',
|
||||
' a=1,',
|
||||
' ).model_dump(),',
|
||||
')',
|
||||
].join('\n')
|
||||
const values = await describeAll(py, 'python', pythonZhTranslator, source)
|
||||
const value = (line: number): string | undefined => propertyLines(values.get(line) ?? []).find(row => row.startsWith('初始值'))
|
||||
expect(value(1)).toBe('初始值: (调用 make · 1 个参数)[0]')
|
||||
expect(value(4)).toBe('初始值: (调用 make · 1 个参数) 或者 fallback')
|
||||
expect(value(7)).toBe('初始值: fallback 或者 调用 make · 1 个参数')
|
||||
expect(value(10)).toBe('初始值: [ 调用 make · 1 个参数, b ]')
|
||||
const cell = (await translateAll(py, 'python', pythonZhTranslator, source)).get(16)
|
||||
expect(tableLines(cell?.table)).toEqual(['key | (调用 Model · 1 个参数).model_dump()', ' a | 1'])
|
||||
})
|
||||
|
||||
it('typeScript:new 写法就是新建,不带 new 的是调用,都不问定义;...x 写「展开」', async () => {
|
||||
@@ -1184,6 +1284,26 @@ describe('跨几行写的调用', () => {
|
||||
expect(asked).toEqual([])
|
||||
})
|
||||
|
||||
it('typeScript 嵌套:实参是跨几行写的调用、new 时同样排在值那一格里', async () => {
|
||||
const line = (await translateAll(ts, 'typescript', typescriptZhTranslator, readFixture('nestedCalls.ts.txt'))).get(3)
|
||||
expect(text(line?.segments)).toBe('调用 context.subscriptions.push · 4 个参数')
|
||||
expect(tableLines(line?.table)).toEqual([
|
||||
'第 1 个 | treeView',
|
||||
'第 2 个 | 调用 commands.registerCommand · 2 个参数',
|
||||
' 第 1 个 | \'superpowers.openKanban\'',
|
||||
' 第 2 个 | () => { KanbanWebviewPanel.createOrShow(context) }',
|
||||
'第 3 个 | 调用 commands.registerCommand · 2 个参数',
|
||||
' 第 1 个 | \'superpowers.refresh\'',
|
||||
' 第 2 个 | () => { KanbanWebviewPanel.refresh() }',
|
||||
'第 4 个 | 调用 commands.registerCommand · 2 个参数',
|
||||
' 第 1 个 | \'superpowers.setGiteaToken\'',
|
||||
' 第 2 个 | () => { KanbanWebviewPanel.createOrShow(context) KanbanWebviewPanel.requestEditAuth() }',
|
||||
])
|
||||
const source = 'const server = new Server(\n new Options(\n port,\n ),\n handler,\n)'
|
||||
const rows = await describeAll(ts, 'typescript', typescriptZhTranslator, source)
|
||||
expect(propertyLines(rows.get(1) ?? []).slice(-4)).toEqual(['值: 新建 Server · 2 个参数', ' 第 1 个 | 新建 Options · 1 个参数', ' 第 1 个 | port', ' 第 2 个 | handler'])
|
||||
})
|
||||
|
||||
it('链式调用跨了几行、实参列表各自写在一行里的不排成表;回调主体不在块头部里的调用也不排', async () => {
|
||||
const source = [
|
||||
'const ids = items',
|
||||
|
||||
Reference in new issue
Block a user