104 lines
4.6 KiB
TypeScript
104 lines
4.6 KiB
TypeScript
import type { BlockKind, CallFacts, Node } from './contract'
|
||
import { describe, expect, it, vi } from 'vitest'
|
||
import { DocumentCallees } from './calleeKinds'
|
||
|
||
/** 一次调用:只用到被调用的表达式原文,和最后那个名字的下标。 */
|
||
function call(callee: string, nameAt?: number): CallFacts {
|
||
const facts = { callee: { text: callee } as Node, argumentList: {} as Node, arguments: [] }
|
||
return nameAt === undefined ? facts : { ...facts, name: { startIndex: nameAt } as Node }
|
||
}
|
||
|
||
/** 各下标处名字的定义是哪种块(语言扩展答的;没有的是没答);记下问了哪些下标。 */
|
||
function source(kinds: Record<number, BlockKind | null>): { asked: number[], kindOf: (offset: number) => Promise<BlockKind | null | undefined> } {
|
||
const asked: number[] = []
|
||
return {
|
||
asked,
|
||
kindOf: async (offset) => {
|
||
asked.push(offset)
|
||
return kinds[offset]
|
||
},
|
||
}
|
||
}
|
||
|
||
describe('调用的名字定义成哪种块(DocumentCallees)', () => {
|
||
it('第一遍当没查到,按被调用的表达式原文记下问了什么(写法一样的按一处问);查到后叫宿主重排,再排时交出来', async () => {
|
||
let changed = 0
|
||
const callees = new DocumentCallees(() => changed++, [])
|
||
const first = callees.session()
|
||
expect(first.calleeKind(call('UserDetailResponse', 40))).toBeUndefined()
|
||
expect(first.calleeKind(call('UserDetailResponse', 90))).toBeUndefined()
|
||
expect(first.calleeKind(call('user_service.update_user', 120))).toBeUndefined()
|
||
expect(first.requests()).toEqual([{ callee: 'UserDetailResponse', offset: 40 }, { callee: 'user_service.update_user', offset: 120 }])
|
||
|
||
const from = source({ 40: 'class', 120: 'function' })
|
||
callees.resolve(1, first.requests(), from.kindOf)
|
||
await vi.waitFor(() => expect(changed).toBe(1))
|
||
const second = callees.session()
|
||
expect(second.calleeKind(call('UserDetailResponse', 12))).toBe('class')
|
||
expect(second.calleeKind(call('user_service.update_user', 7))).toBe('function')
|
||
|
||
// 同一版本再发一遍:问过的不再查
|
||
callees.resolve(1, first.requests(), from.kindOf)
|
||
await Promise.resolve()
|
||
expect(from.asked).toEqual([40, 120])
|
||
})
|
||
|
||
it('revision:查到的答案变了才加一,新版本查到的一样不加(差异按它定旧版本要不要重新解析)', async () => {
|
||
const callees = new DocumentCallees(() => {}, [])
|
||
const session = callees.session()
|
||
session.calleeKind(call('Detail', 40))
|
||
session.calleeKind(call('build', 5))
|
||
expect(callees.revision).toBe(0)
|
||
const kinds: Record<number, BlockKind | null> = { 40: 'class', 5: null }
|
||
callees.resolve(1, session.requests(), source(kinds).kindOf)
|
||
await vi.waitFor(() => expect(callees.revision).toBe(1))
|
||
const same = source(kinds)
|
||
callees.resolve(2, session.requests(), same.kindOf)
|
||
await vi.waitFor(() => expect(same.asked).toEqual([40, 5]))
|
||
await Promise.resolve()
|
||
expect(callees.revision).toBe(1)
|
||
kinds[40] = 'function'
|
||
callees.resolve(3, session.requests(), source(kinds).kindOf)
|
||
await vi.waitFor(() => expect(callees.revision).toBe(2))
|
||
})
|
||
|
||
it('被调用的不是名字(没有 name)不问;查了没有(null)不算变了', async () => {
|
||
let changed = 0
|
||
const callees = new DocumentCallees(() => changed++, [])
|
||
const session = callees.session()
|
||
expect(session.calleeKind(call('handlers[k]'))).toBeUndefined()
|
||
session.calleeKind(call('build', 5))
|
||
expect(session.requests()).toEqual([{ callee: 'build', offset: 5 }])
|
||
const from = source({ 5: null })
|
||
callees.resolve(1, session.requests(), from.kindOf)
|
||
await vi.waitFor(() => expect(from.asked).toEqual([5]))
|
||
await Promise.resolve()
|
||
expect(changed).toBe(0)
|
||
})
|
||
|
||
it('语言扩展还没起来(没答):隔一会儿只再查没答的,查到了再叫重排', async () => {
|
||
let changed = 0
|
||
const pending: (() => void)[] = []
|
||
const scheduled: number[] = []
|
||
const callees = new DocumentCallees(() => changed++, [5, 10], (task, ms) => {
|
||
scheduled.push(ms)
|
||
pending.push(task)
|
||
return setTimeout(() => {}, 0)
|
||
})
|
||
const session = callees.session()
|
||
session.calleeKind(call('Detail', 40))
|
||
session.calleeKind(call('run', 60))
|
||
const kinds: Record<number, BlockKind | null> = { 60: 'function' }
|
||
const from = source(kinds)
|
||
callees.resolve(1, session.requests(), from.kindOf)
|
||
await vi.waitFor(() => expect(scheduled).toEqual([5]))
|
||
expect(changed).toBe(1)
|
||
|
||
kinds[40] = 'class'
|
||
pending.shift()?.()
|
||
await vi.waitFor(() => expect(changed).toBe(2))
|
||
expect(from.asked).toEqual([40, 60, 40])
|
||
expect(callees.session().calleeKind(call('Detail', 40))).toBe('class')
|
||
})
|
||
})
|