✨ feat(vscode): 代码阅读认出代码里起的中文名(Annotated[…, Comment("…")]、@Comment 装饰器、行尾 # @Comment、docstring / JSDoc 的参数说明),预览里定义和用到它的各处都写中文名,悬停看原名,定义处后面淡淡写原名

This commit is contained in:
cruldra committed 2026-09-27 00:56:39 +08:00
1 parent 1b1299dc1f
commit 44c221ea2b
45 files changed
+1685 -128

No files matched your search

+29 -16
View File
@@ -1,9 +1,9 @@
import type { Tree } from '@vscode/tree-sitter-wasm'
import type { RuleLocation, RulePosition, RuleWorkspace, WorkspaceIndex } from './contract'
import type { IndexedFile, IndexEntry, Node, RuleLocation, RulePosition, RuleWorkspace, WorkspaceIndex } from './contract'
import * as path from 'node:path'
/**
* 库规则的工作区索引(WorkspaceIndex)的宿主部分:找文件、预筛、解析、缓存,跟着文件改动只重看改了的文件。
* 工作区索引(WorkspaceIndex:库规则的,和宿主自己认中文名的)的宿主部分:找文件、预筛、解析、缓存,跟着文件改动只重看改了的文件。
* 规则只说要什么;这里不碰 VS Code,工作区的能力由 IndexHost 给(VS Code 里是 workspaceFiles.ts,测试里是内存里的文件)。
*/
@@ -52,10 +52,18 @@ function positionAt(starts: number[], index: number): RulePosition {
return { line: low, character: index - starts[low] }
}
/** 认出的一项在哪:定义处名字的位置,连同认的时候给的这一项(宿主自己的索引在项里多带东西,例如中文名)。 */
export interface IndexedEntry<E extends IndexEntry = IndexEntry> { location: RuleLocation, entry: E }
/** 认出的项是 E 的索引。 */
export interface WorkspaceIndexOf<E extends IndexEntry> extends WorkspaceIndex {
entries: (root: Node, file: IndexedFile) => E[]
}
/** 一份看过的文件:认出的各项,和建索引时问过在不在的文件(它们新建、删掉时这份要重看)。 */
interface Indexed {
interface Indexed<E extends IndexEntry> {
file: WorkspaceFile
entries: { key: string, location: RuleLocation }[]
entries: IndexedEntry<E>[]
asked: Set<string>
}
@@ -64,25 +72,25 @@ function compareLocations(a: RuleLocation, b: RuleLocation): number {
}
/** 一个 WorkspaceIndex 建出来的索引:建好之前的查询、文件改动都排在建索引后面,一件件来。 */
class BuiltIndex {
class BuiltIndex<E extends IndexEntry> {
/** include 找到的全部文件(按 keyOf),IndexedFile.exists 查的就是它 */
private readonly files = new Map<string, WorkspaceFile>()
/** 预筛过了、解析过的文件 */
private readonly indexed = new Map<string, Indexed>()
private readonly indexed = new Map<string, Indexed<E>>()
private readonly watcher: { dispose: () => void }
private queue: Promise<void>
constructor(private readonly index: WorkspaceIndex, private readonly host: IndexHost) {
constructor(private readonly index: WorkspaceIndexOf<E>, private readonly host: IndexHost) {
// 先盯着再找文件:找文件期间的改动排在建好之后补上
this.watcher = host.watch(index.include, event => this.enqueue(() => this.apply(event)))
this.queue = this.guard(() => this.build())
}
async lookup(key: string): Promise<RuleLocation[]> {
async lookup(key: string): Promise<IndexedEntry<E>[]> {
await this.queue
return [...this.indexed.values()]
.flatMap(indexed => indexed.entries.filter(entry => entry.key === key).map(entry => entry.location))
.sort(compareLocations)
.flatMap(indexed => indexed.entries.filter(({ entry }) => entry.key === key))
.sort((a, b) => compareLocations(a.location, b.location))
}
dispose(): void {
@@ -134,9 +142,9 @@ class BuiltIndex {
return this.files.has(other)
}
const starts = lineStarts(source)
const entries = this.index.entries(tree.rootNode, { path: file.path, source, exists }).map(({ key: entryKey, name }) => ({
key: entryKey,
location: { uri: file.uri, start: positionAt(starts, name.startIndex), end: positionAt(starts, name.endIndex) },
const entries = this.index.entries(tree.rootNode, { path: file.path, source, exists }).map(entry => ({
entry,
location: { uri: file.uri, start: positionAt(starts, entry.name.startIndex), end: positionAt(starts, entry.name.endIndex) },
}))
this.indexed.set(key, { file, entries, asked })
}
@@ -186,12 +194,17 @@ class BuiltIndex {
/** 各库规则的工作区索引:第一次查某个索引时才建,同一个 id 只建一份。 */
export class WorkspaceIndexes implements RuleWorkspace {
private readonly built = new Map<string, BuiltIndex>()
private readonly built = new Map<string, BuiltIndex<IndexEntry>>()
constructor(private readonly host: IndexHost) {}
lookup(index: WorkspaceIndex, key: string): Promise<RuleLocation[]> {
let built = this.built.get(index.id)
async lookup(index: WorkspaceIndex, key: string): Promise<RuleLocation[]> {
return (await this.find(index, key)).map(({ location }) => location)
}
/** 同 lookup,连同认出的那一项(第一次查时建,同一个 id 只建一份)。 */
find<E extends IndexEntry>(index: WorkspaceIndexOf<E>, key: string): Promise<IndexedEntry<E>[]> {
let built = this.built.get(index.id) as BuiltIndex<E> | undefined
if (!built) {
built = new BuiltIndex(index, this.host)
this.built.set(index.id, built)