Files
superwork/vscode/src/codeReader/testSupport.ts
T

46 lines
1.6 KiB
TypeScript

import type { BlockKind, CodeBlock, LanguageAdapter } from './contract'
import { readFileSync } from 'node:fs'
import * as path from 'node:path'
import { TreeSitterRuntime } from './runtime'
/** 单元测试直接用依赖包里的 wasm,不走打包产物。 */
export const WASM_DIR = path.resolve(__dirname, '../../node_modules/@vscode/tree-sitter-wasm/wasm')
export const runtime = new TreeSitterRuntime(WASM_DIR)
export function readFixture(name: string): string {
return readFileSync(path.join(__dirname, 'fixtures', name), 'utf8')
}
/** 解析 source,把代码块树交给 use;语法树随后释放。 */
export async function withBlocks<T>(adapter: LanguageAdapter, languageId: string, source: string, use: (blocks: CodeBlock[]) => T): Promise<T> {
const tree = await runtime.parse(adapter, languageId, source)
try {
return use(adapter.toBlocks(tree.rootNode, source))
}
finally {
tree.delete()
}
}
/** 和原型 CODE_TREE 同样的写法:at 是 1 起的行号(单行,或 [起, 止])。 */
export interface Outline { at: number | [number, number], kind: BlockKind, kids?: Outline[] }
export function outline(blocks: CodeBlock[]): Outline[] {
return blocks.map((block) => {
const from = block.header.startRow + 1
const to = block.header.endRow + 1
const item: Outline = { at: from === to ? from : [from, to], kind: block.kind }
if (block.children.length > 0)
item.kids = outline(block.children)
return item
})
}
export function walk(blocks: CodeBlock[], visit: (block: CodeBlock) => void): void {
for (const block of blocks) {
visit(block)
walk(block.children, visit)
}
}