✨ feat(vscode): 代码阅读的解析与模板直译核心
This commit is contained in:
1 parent
af56985d9a
commit
4d34b8c715
24 files changed
+2294
No files matched your search
@@ -0,0 +1,50 @@
|
||||
import type { Tree } from '@vscode/tree-sitter-wasm'
|
||||
import type { LanguageAdapter } from './contract'
|
||||
import * as path from 'node:path'
|
||||
import { Language, Parser } from '@vscode/tree-sitter-wasm'
|
||||
|
||||
/** 打进扩展包里的 wasm 目录:dist/index.cjs 旁边的 dist/tree-sitter(esbuild 构建时复制)。只在打包产物里成立。 */
|
||||
export function bundledWasmDir(): string {
|
||||
return path.join(__dirname, 'tree-sitter')
|
||||
}
|
||||
|
||||
// web-tree-sitter 的运行时是进程级单例:Parser.init 只能有效调用一次,后来的 wasm 目录不再生效
|
||||
let runtimeReady: Promise<void> | undefined
|
||||
|
||||
function initRuntime(wasmDir: string): Promise<void> {
|
||||
runtimeReady ??= Parser.init({ locateFile: (file: string) => path.join(wasmDir, file) })
|
||||
.catch((err: unknown) => {
|
||||
runtimeReady = undefined
|
||||
throw err
|
||||
})
|
||||
return runtimeReady
|
||||
}
|
||||
|
||||
/** 解析运行时:初始化一次 web-tree-sitter,语法包按 wasm 路径懒加载并缓存。 */
|
||||
export class TreeSitterRuntime {
|
||||
private readonly parsers = new Map<string, Promise<Parser>>()
|
||||
|
||||
/** @param wasmDir 放 tree-sitter.wasm 的目录 */
|
||||
constructor(private readonly wasmDir: string) {}
|
||||
|
||||
/** 返回的语法树占着 wasm 内存,用完必须 `tree.delete()`。 */
|
||||
async parse(adapter: LanguageAdapter, languageId: string, source: string): Promise<Tree> {
|
||||
const parser = await this.parserFor(adapter.grammarPath(languageId))
|
||||
const tree = parser.parse(source)
|
||||
if (!tree)
|
||||
throw new Error(`tree-sitter 没能解析 ${languageId} 源码`)
|
||||
return tree
|
||||
}
|
||||
|
||||
private parserFor(grammarPath: string): Promise<Parser> {
|
||||
let parser = this.parsers.get(grammarPath)
|
||||
if (!parser) {
|
||||
parser = initRuntime(this.wasmDir)
|
||||
.then(() => Language.load(grammarPath))
|
||||
.then(language => new Parser().setLanguage(language))
|
||||
parser.catch(() => this.parsers.delete(grammarPath))
|
||||
this.parsers.set(grammarPath, parser)
|
||||
}
|
||||
return parser
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user