⚡ perf(vscode): 预览发文档后在后台问语言扩展的请求排队发:同时在途最多 4 个、离视口近的先问、文档改了排着的作废,看得见的中文名先交

This commit is contained in:
cruldra committed 2026-10-13 14:15:37 +11:00
1 parent 5a0c5490ea
commit 12ad047b4d
7 files changed
+335 -45

No files matched your search

+22 -11
View File
@@ -30,6 +30,7 @@ import { DefinitionKinds } from '../definitionKinds'
import { PreviewDiff } from '../diff/previewDiff'
import { blockReplacement } from '../editText'
import { locate } from '../folderStore'
import { LanguageRequests } from '../languageRequests'
import { definitionFor, symbolAt, symbolOccurrences } from '../localSymbols'
import { DocumentNames, resolveNames } from '../nameResolution'
import { PATH_ASK_ANCHOR } from '../qa/pathQa'
@@ -208,7 +209,9 @@ class Preview {
visibleLine: number | undefined
/** 最近一次发出去的文档(版本、块树、源码):问 AI 时按块的记号在里面找那块代码,对比基准变了时拿它重新比 */
private sent: SentDocument | undefined
/** 能看调用树的块(函数、类、接口卡片)落在几棵调用树里。文档发出去之后再数,不挡住第一次预览;同一版文档数过的页面重新加载后接着用 */
/** 发文档后在后台问语言扩展的请求(中文名、库规则查的定义、调用的种类)排队发:在途的有上限,离视口近的先发,文档改了排着的作废 */
private readonly requests = new LanguageRequests(() => this.document.version, () => this.visibleLine)
/** 能看调用树的块(函数、类、接口卡片)落在几棵调用树里。文档发出去之后再数,不挡住第一次预览,离视口近的先数;同一版文档数过的页面重新加载后接着用 */
private readonly callTrees = new CallTreeSession(
message => this.post(message),
() => {
@@ -220,6 +223,7 @@ class Preview {
load: (block, cancelled) => loadBlockCalls(this.document, block, this.owner.indexed, cancelled),
}
},
offset => this.requests.distance(this.document.positionAt(offset).line),
)
/** 最近一次发出去的文档里语言插件自己认得出的名字(LanguageAdapter.symbols):语言扩展查不到定义、各处出现时用 */
@@ -430,9 +434,9 @@ class Preview {
void this.diff.update(this.sent)
// 文档在解析期间又改了的,等下一次发文档再查
if (version === this.document.version) {
this.names.resolve(version, report => resolveNames(displayNames, message.blocks, this.nameSources(), report))
this.lookups.resolve(version, session.requests(), this.lookupSources())
this.callees.resolve(version, callees.requests(), offset => this.calleeKind(offset))
this.names.resolve(version, report => resolveNames(displayNames, message.blocks, this.nameSources(version), report))
this.lookups.resolve(version, session.requests(), this.lookupSources(version))
this.callees.resolve(version, callees.requests(), offset => this.queued(version, offset, () => this.calleeKind(offset), undefined))
this.callTrees.documentSent()
}
}
@@ -501,25 +505,31 @@ class Preview {
.map(({ uri, range }) => ({ uri: uri.toString(), line: range.start.line, character: range.start.character }))
}
/** 找中文名落在哪些名字上时问的:这份文档的语言扩展、工作区里的中文名索引。 */
private nameSources(): NameSources {
/** 找 version 这一版的中文名落在哪些名字上时问的:这份文档的语言扩展(排队问)、工作区里的中文名索引、页面的视口。 */
private nameSources(version: number): NameSources {
const { document } = this
return {
uri: document.uri.toString(),
occurrences: async offset => (await this.occurrences(offset)).map(({ start, end }) => ({ start, end })),
definitions: offset => this.definitionStarts(offset),
occurrences: offset => this.queued(version, offset, async () => (await this.occurrences(offset)).map(({ start, end }) => ({ start, end })), []),
definitions: offset => this.queued(version, offset, () => this.definitionStarts(offset), []),
indexed: name => this.owner.indexedNames(document.languageId, name),
visible: offset => this.requests.visible(document.positionAt(offset).line),
}
}
/** 查库规则问的名字时问的:规则的工作区索引、这份文档的语言扩展。 */
private lookupSources(): LookupSources {
/** 查 version 这一版库规则问的名字时问的:规则的工作区索引、这份文档的语言扩展(排队问)。 */
private lookupSources(version: number): LookupSources {
return {
find: (index, key) => this.owner.indexed(index, key),
definitions: offset => this.definitionStarts(offset),
definitions: offset => this.queued(version, offset, () => this.definitionStarts(offset), []),
}
}
/** 排进后台请求的队(见 LanguageRequests):version 这一版文档 offset 处要问的,没发就作废的交回 dropped(当语言扩展没答)。 */
private queued<T>(version: number, offset: number, request: () => Promise<T>, dropped: T): Promise<T> {
return this.requests.run(version, this.document.positionAt(offset).line, request, dropped)
}
/** 跳到高亮着的名字的下一处 / 上一处出现;页面还没 ready 就算了(还没有高亮)。 */
moveOccurrence(step: 1 | -1): void {
if (this.ready)
@@ -552,6 +562,7 @@ class Preview {
dispose(): void {
this.callTrees.dispose()
this.requests.dispose()
clearTimeout(this.timer)
this.names.dispose()
this.lookups.dispose()