✨ feat(vscode): 代码阅读能读嵌在一种语言里的另一种语言的代码:语言插件报出是哪几段,宿主交给那种语言的插件只解析这几段、分步、翻成子块并叠着上色,外层翻译插件只问读出来的样子;契约加构建文件的几种块(解析指令、阶段、执行、复制、设置、标签、健康检查、启动)、分作用范围的变量、并成一块的几条语句,引擎排这些块的属性表
This commit is contained in:
1 parent
834673391e
commit
3353cf870c
11 files changed
+603
-103
No files matched your search
@@ -1,5 +1,5 @@
|
||||
import type { Tree } from '@vscode/tree-sitter-wasm'
|
||||
import type { LanguageAdapter } from './contract'
|
||||
import type { Point, Range, Tree } from '@vscode/tree-sitter-wasm'
|
||||
import type { LanguageAdapter, SourceRange } from './contract'
|
||||
import * as path from 'node:path'
|
||||
import { Language, Parser } from '@vscode/tree-sitter-wasm'
|
||||
|
||||
@@ -8,6 +8,19 @@ export function bundledWasmDir(): string {
|
||||
return path.join(__dirname, 'tree-sitter')
|
||||
}
|
||||
|
||||
/** 源码下标的行列(行从 0 起,列按 UTF-16,同 web-tree-sitter 解析 JS 字符串时的算法)。 */
|
||||
function pointAt(source: string, index: number): Point {
|
||||
const lineStart = source.lastIndexOf('\n', index - 1) + 1
|
||||
let row = 0
|
||||
for (let at = source.indexOf('\n'); at !== -1 && at < index; at = source.indexOf('\n', at + 1))
|
||||
row++
|
||||
return { row, column: index - lineStart }
|
||||
}
|
||||
|
||||
function includedRange(source: string, { startIndex, endIndex }: SourceRange): Range {
|
||||
return { startIndex, endIndex, startPosition: pointAt(source, startIndex), endPosition: pointAt(source, endIndex) }
|
||||
}
|
||||
|
||||
// web-tree-sitter 的运行时是进程级单例:Parser.init 只能有效调用一次,后来的 wasm 目录不再生效
|
||||
let runtimeReady: Promise<void> | undefined
|
||||
|
||||
@@ -27,10 +40,13 @@ export class TreeSitterRuntime {
|
||||
/** @param wasmDir 放 tree-sitter.wasm 的目录 */
|
||||
constructor(private readonly wasmDir: string) {}
|
||||
|
||||
/** 返回的语法树占着 wasm 内存,用完必须 `tree.delete()`。 */
|
||||
async parse(adapter: LanguageAdapter, languageId: string, source: string): Promise<Tree> {
|
||||
/**
|
||||
* 返回的语法树占着 wasm 内存,用完必须 `tree.delete()`。给了 ranges 就只解析源码里的这几段(嵌着的代码,见 EmbeddedCode),
|
||||
* 节点的下标、行列照旧是整份源码的。
|
||||
*/
|
||||
async parse(adapter: LanguageAdapter, languageId: string, source: string, ranges?: readonly SourceRange[]): Promise<Tree> {
|
||||
const parser = await this.parserFor(adapter.grammarPath(languageId))
|
||||
const tree = parser.parse(source)
|
||||
const tree = parser.parse(source, null, ranges ? { includedRanges: ranges.map(range => includedRange(source, range)) } : undefined)
|
||||
if (!tree)
|
||||
throw new Error(`tree-sitter 没能解析 ${languageId} 源码`)
|
||||
return tree
|
||||
|
||||
Reference in new issue
Block a user