⚡ perf(vscode): 预览发文档后在后台问语言扩展的请求排队发:同时在途最多 4 个、离视口近的先问、文档改了排着的作废,看得见的中文名先交
This commit is contained in:
1 parent
5a0c5490ea
commit
12ad047b4d
7 files changed
+335
-45
No files matched your search
@@ -76,12 +76,15 @@ export interface NameSources {
|
||||
definitions: (offset: number) => Promise<DefinitionStart[]>
|
||||
/** 工作区里定义的、原名叫 name 的中文名 */
|
||||
indexed: (name: string) => Promise<IndexedName[]>
|
||||
/** offset 处页面眼下看不看得见:别的文件定义的,看得见的先问、问完先交一次 */
|
||||
visible: (offset: number) => boolean
|
||||
}
|
||||
|
||||
/**
|
||||
* 找这份文档里显示成中文名的各处,分两步交出(先交本文件的,不等工作区索引建好;最后一次 final):
|
||||
* 1. 本文件定义的:每个定义问一次它的各处出现,落在视图数据里带下标的名字上的显示成中文名,定义处本身标 definition;
|
||||
* 2. 别的文件定义的:原名和工作区索引里某个中文名一样的名字才问定义提供者,定义处正是索引里那个定义才算。
|
||||
* 2. 别的文件定义的:原名和工作区索引里某个中文名一样的名字才问定义提供者,定义处正是索引里那个定义才算;
|
||||
* 页面看得见的先问,问完先交一次,再问其余的。
|
||||
* 返回语言扩展答没答(settled):定义处自己都查不到出现,或要问的定义一个都没答,是语言扩展还没起来,过一会儿再查。
|
||||
*/
|
||||
export async function resolveNames(
|
||||
@@ -109,23 +112,34 @@ export async function resolveNames(
|
||||
if (!shown.has(offset))
|
||||
byName.set(original, [...(byName.get(original) ?? []), offset])
|
||||
}
|
||||
let asked = 0
|
||||
let answered = 0
|
||||
const asks: { offset: number, original: string, elsewhere: IndexedName[] }[] = []
|
||||
await Promise.all([...byName].map(async ([original, offsets]) => {
|
||||
const elsewhere = (await sources.indexed(original)).filter(entry => entry.location.uri !== sources.uri)
|
||||
if (elsewhere.length === 0)
|
||||
return
|
||||
await Promise.all(offsets.map(async (offset) => {
|
||||
asked++
|
||||
const found = await sources.definitions(offset)
|
||||
if (found.length > 0)
|
||||
answered++
|
||||
const entry = elsewhere.find(({ location }) => found.some(at => at.uri === location.uri && at.line === location.start.line && at.character === location.start.character))
|
||||
if (entry)
|
||||
shown.set(offset, { offset, length: original.length, name: entry.text })
|
||||
}))
|
||||
for (const offset of elsewhere.length > 0 ? offsets : [])
|
||||
asks.push({ offset, original, elsewhere })
|
||||
}))
|
||||
if (asked > 0 && answered === 0)
|
||||
let answered = 0
|
||||
const ask = (list: typeof asks): Promise<unknown> => Promise.all(list.map(async ({ offset, original, elsewhere }) => {
|
||||
const found = await sources.definitions(offset)
|
||||
if (found.length > 0)
|
||||
answered++
|
||||
const entry = elsewhere.find(({ location }) => found.some(at => at.uri === location.uri && at.line === location.start.line && at.character === location.start.character))
|
||||
if (entry)
|
||||
shown.set(offset, { offset, length: original.length, name: entry.text })
|
||||
}))
|
||||
const near: typeof asks = []
|
||||
const far: typeof asks = []
|
||||
for (const item of asks)
|
||||
(sources.visible(item.offset) ? near : far).push(item)
|
||||
if (near.length > 0 && far.length > 0) {
|
||||
await ask(near)
|
||||
report([...shown.values()], false)
|
||||
await ask(far)
|
||||
}
|
||||
else {
|
||||
await ask(asks)
|
||||
}
|
||||
if (asks.length > 0 && answered === 0)
|
||||
settled = false
|
||||
report([...shown.values()], true)
|
||||
return settled
|
||||
@@ -184,6 +198,13 @@ export function shiftNames(names: readonly ShownName[], changes: readonly TextCh
|
||||
return current
|
||||
}
|
||||
|
||||
/** next 把 current 的每一个都盖住了(一模一样的一项),还多出几个。 */
|
||||
function adds(next: readonly ShownName[], current: readonly ShownName[]): boolean {
|
||||
const keyOf = ({ offset, length, name, definition }: ShownName): string => JSON.stringify([offset, length, name, definition])
|
||||
const keys = new Set(next.map(keyOf))
|
||||
return next.length > current.length && current.every(name => keys.has(keyOf(name)))
|
||||
}
|
||||
|
||||
/** 语言扩展还没起来时隔多久再查(毫秒),查到最后一次还没答就算了 */
|
||||
export const RETRY_DELAYS = [1000, 2000, 4000, 8000, 16000]
|
||||
|
||||
@@ -219,7 +240,8 @@ export class DocumentNames {
|
||||
|
||||
/**
|
||||
* 发出去了 version 这份文档:查它的中文名;同一个版本只查一次(页面重新加载时照旧用查到的)。
|
||||
* 手上还没有这个版本的中文名时查到一步交一步(先交本文件的),有(上一版挪过来的)就等查完一起换,免得少了的那些闪一下。
|
||||
* 查到一步交一步(先交本文件的,再交看得见的);比眼下显示着的(上一版挪过来的、上一步交过的)少了哪个、或者没多出什么的那一步不交,
|
||||
* 等查完一起换,免得少了的那些闪一下。
|
||||
* 查的过程中文档又改了的,查到的丢掉。
|
||||
*/
|
||||
resolve(version: number, run: (report: (names: ShownName[], final: boolean) => void) => Promise<boolean>): void {
|
||||
@@ -232,7 +254,7 @@ export class DocumentNames {
|
||||
}
|
||||
this.resolving = version
|
||||
const report = (names: ShownName[], final: boolean): void => {
|
||||
if (this.resolving !== version || (!final && this.names.length > 0))
|
||||
if (this.resolving !== version || (!final && !adds(names, this.names)))
|
||||
return
|
||||
this.names = names
|
||||
this.deliver(version, names)
|
||||
|
||||
Reference in new issue
Block a user