Files
superwork/vscode/src/codeReader/calleeKinds.test.ts
T

104 lines
4.6 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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')
})
})