⚡ perf(vscode): 代码阅读预览注释里的引用解析过就记着:标坏链接、悬停、点击同一个引用只问一次 Pylance,同时问的等同一个结果,文档版本或块树、导入、用到的名字换了才作废,指到的别的文件改过再问,找不到和语言自带的不留;悬停看别的文件里的定义时读成的文档各预览共用,同一版不再重新解析,留最近 8 份,注册的插件变了全部重读
This commit is contained in:
1 parent
3983032356
commit
cfde0fedf5
9 files changed
+595
-70
No files matched your search
@@ -2,6 +2,7 @@ import type { NamedKind } from './blockView'
|
||||
import type { BlockKind, LanguageAdapter } from './contract'
|
||||
import type { TreeSitterRuntime } from './runtime'
|
||||
import { kindAt, readNamedKinds } from './blockView'
|
||||
import { RecentPromises } from './recentPromises'
|
||||
|
||||
/** 定义所在的那份文件(TextDocument 的子集):uri、版本、语言、内容。 */
|
||||
export interface KindSource {
|
||||
@@ -20,17 +21,19 @@ const LIMIT = 64
|
||||
* 最近用过的留 limit 份。这里不碰 VS Code。
|
||||
*/
|
||||
export class DefinitionKinds {
|
||||
private readonly files = new Map<string, { version: number, kinds: Promise<NamedKind[] | undefined> }>()
|
||||
private readonly files: RecentPromises<NamedKind[] | undefined>
|
||||
|
||||
constructor(
|
||||
private readonly languageFor: (languageId: string) => LanguageAdapter | undefined,
|
||||
private readonly runtime: Pick<TreeSitterRuntime, 'parse'>,
|
||||
private readonly limit = LIMIT,
|
||||
) {}
|
||||
limit = LIMIT,
|
||||
) {
|
||||
this.files = new RecentPromises(limit)
|
||||
}
|
||||
|
||||
/** uri 这份文件 version 这一版各块的名字和种类(预览发文档时读出的)。 */
|
||||
remember(uri: string, version: number, kinds: NamedKind[]): void {
|
||||
this.keep(uri, version, Promise.resolve(kinds))
|
||||
this.files.set(uri, version, Promise.resolve(kinds))
|
||||
}
|
||||
|
||||
/** file 里 offset 处的名字定义的是哪种块;没有语言插件、不在哪块的名字上时没有。 */
|
||||
@@ -40,32 +43,12 @@ export class DefinitionKinds {
|
||||
}
|
||||
|
||||
private kindsOf(file: KindSource): Promise<NamedKind[] | undefined> {
|
||||
const known = this.files.get(file.uri)
|
||||
if (known?.version === file.version) {
|
||||
this.keep(file.uri, known.version, known.kinds)
|
||||
return known.kinds
|
||||
}
|
||||
const known = this.files.get(file.uri, file.version)
|
||||
if (known)
|
||||
return known
|
||||
const adapter = this.languageFor(file.languageId)
|
||||
if (!adapter)
|
||||
return Promise.resolve(undefined)
|
||||
const kinds = readNamedKinds(this.runtime, adapter, file.languageId, file.getText())
|
||||
this.keep(file.uri, file.version, kinds)
|
||||
// 解析失败的不记,下次重来
|
||||
kinds.catch(() => {
|
||||
if (this.files.get(file.uri)?.kinds === kinds)
|
||||
this.files.delete(file.uri)
|
||||
})
|
||||
return kinds
|
||||
}
|
||||
|
||||
/** 记下(或用到了)一份:挪到最近用过的那头,多了丢最久没用的。 */
|
||||
private keep(uri: string, version: number, kinds: Promise<NamedKind[] | undefined>): void {
|
||||
this.files.delete(uri)
|
||||
this.files.set(uri, { version, kinds })
|
||||
for (const oldest of this.files.keys()) {
|
||||
if (this.files.size <= this.limit)
|
||||
break
|
||||
this.files.delete(oldest)
|
||||
}
|
||||
return this.files.set(file.uri, file.version, readNamedKinds(this.runtime, adapter, file.languageId, file.getText()))
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user