52 lines
2.3 KiB
TypeScript
52 lines
2.3 KiB
TypeScript
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<BlockKind | null | undefined>
|
||
|
||
/** 排一遍视图数据用的:交给翻译插件的 calleeKind,和这一遍问了哪些调用。 */
|
||
export interface CalleeSession {
|
||
calleeKind: (call: CallFacts) => BlockKind | undefined
|
||
requests: () => CalleeRequest[]
|
||
}
|
||
|
||
/** 一份打开着的文档里调用的名字查到定义成哪种块;什么时候查、查到了怎么叫宿主重排见 DeferredAnswers。 */
|
||
export class DocumentCallees {
|
||
private readonly answers: DeferredAnswers<CalleeRequest, BlockKind>
|
||
|
||
constructor(changed: () => void, delays?: readonly number[], schedule?: (run: () => void, ms: number) => ReturnType<typeof setTimeout>) {
|
||
this.answers = new DeferredAnswers(({ callee }) => callee, (a, b) => (a ?? null) === (b ?? null), changed, delays, schedule)
|
||
}
|
||
|
||
/** 查到的种类变过几次(见 DeferredAnswers.revision) */
|
||
get revision(): number {
|
||
return this.answers.revision
|
||
}
|
||
|
||
/** 被调用的不是名字(没有 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()
|
||
}
|
||
}
|