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

52 lines
2.3 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 } 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()
}
}