import type { BlockKind, CallFacts } from './contract' import { DeferredAnswers } from './deferredAnswers' /** * 调用的名字的定义是哪种块(SourceDocument.calleeKind):翻译插件靠它分新建对象还是调用函数。 * 按被调用的表达式原文记(`user_service.update_user`),同一份文档里写法一样的调用按一处查;问语言扩展时问它最后那个名字。这里不碰 VS Code。 */ /** 问的一次调用:被调用的表达式原文,和它最后那个名字在源码里的下标。 */ export interface CalleeRequest { callee: string, offset: number } /** 这份文档里 offset 处名字的定义是哪种块:查了没有是 null,语言扩展没答(还没起来)是 undefined。 */ export type CalleeSource = (offset: number) => Promise /** 排一遍视图数据用的:交给翻译插件的 calleeKind,和这一遍问了哪些调用。 */ export interface CalleeSession { calleeKind: (call: CallFacts) => BlockKind | undefined requests: () => CalleeRequest[] } /** 一份打开着的文档里调用的名字查到定义成哪种块;什么时候查、查到了怎么叫宿主重排见 DeferredAnswers。 */ export class DocumentCallees { private readonly answers: DeferredAnswers constructor(changed: () => void, delays?: readonly number[], schedule?: (run: () => void, ms: number) => ReturnType) { this.answers = new DeferredAnswers(({ callee }) => callee, (a, b) => (a ?? null) === (b ?? null), changed, delays, schedule) } /** 被调用的不是名字(没有 CallFacts.name)的不问,按调用算。 */ session(): CalleeSession { const session = this.answers.session() return { calleeKind: call => call.name ? session.ask({ callee: call.callee.text, offset: call.name.startIndex }) : undefined, requests: session.questions, } } /** 查 version 这一版问的调用:这个版本查过的不再查。 */ resolve(version: number, requests: readonly CalleeRequest[], source: CalleeSource): void { this.answers.resolve(version, requests, ({ offset }) => source(offset)) } dispose(): void { this.answers.dispose() } }