import type { Node } from '@vscode/tree-sitter-wasm' import type { Disposable } from 'vscode' export type { Node } export type BlockKind = | 'import' | 'function' | 'class' | 'type' | 'field' | 'const' | 'variable' | 'if' | 'else' | 'loop' | 'try' | 'catch' | 'finally' | 'return' | 'statement' | 'comment' /** 源码里一段的下标:源码字符串下标(web-tree-sitter 的 startIndex / endIndex),end 为开区间。 */ export interface SourceRange { startIndex: number, endIndex: number } /** 源码里的一段,带起止行号(从 0 开始)。 */ export interface SourceSpan extends SourceRange { startRow: number, endRow: number } /** 访问级别。 */ export type Access = 'public' | 'private' | 'protected' /** 函数的一个参数;节点都指向源码。 */ export interface ParameterFacts { /** 参数名;解构参数是整个模式,`...rest`、`*args`、`**kwargs` 带着前缀。 */ name: Node /** TypeScript 的可省略参数 `x?`。 */ optional: boolean type?: Node default?: Node } export interface FunctionFacts { /** 匿名函数(`export default function () {}`)没有。 */ name?: Node /** * 函数自己的说明:TypeScript 是紧贴在声明前面的 JSDoc 注释(以 `/**` 开头),Python 是主体开头的 docstring(字符串节点)。 * 它算在块的头部里,不再单独成一块注释。 */ doc?: Node /** 嵌套在函数体、条件等语句块里的函数没有。 */ access?: Access async: boolean decorators: Node[] parameters: ParameterFacts[] returnType?: Node } /** * 父类的一项:TypeScript `extends Base` 里的 Base(一个表达式)和跟在它后面的泛型实参 ``(语法里是两个节点); * Python 类参数列表里的一项,`metaclass=ABCMeta` 这类关键字参数、`*bases` 也算。 */ export interface BaseFacts { value: Node typeArguments?: Node } export interface ClassFacts { /** 匿名类(`export default class {}`)没有;赋给变量、类字段的类表达式取变量名、字段名。 */ name?: Node /** 类自己的说明,同 FunctionFacts.doc:TypeScript 是紧贴在前面的 JSDoc,Python 是主体开头的 docstring。 */ doc?: Node /** 同函数:嵌套在函数体、条件等语句块里的类没有。 */ access?: Access /** 抽象类(TypeScript 的 `abstract class`);没有这个概念的语言不填。 */ abstract?: boolean decorators: Node[] /** 泛型参数,每个参数一项(TypeScript `` 里的 `T extends X = Y`)。 */ typeParameters: Node[] /** 按源码顺序。 */ bases: BaseFacts[] /** 实现的接口(TypeScript 的 `implements A, B`),每个接口一项。 */ implements: Node[] } /** 导入的一项。 */ export type ImportItem = | { kind: 'named', name: Node, alias?: Node } // import { a as b }、from m import a as b | { kind: 'default', alias: Node } // import x from 'm' | { kind: 'namespace', alias?: Node } // import * as x、from m import * | { kind: 'module', module: Node, alias?: Node } // import a.b as c、import x = require('m') export interface ImportFacts { /** 来源模块,节点就是源码里的写法:TypeScript 是字符串字面量,Python 是点分模块名;Python 的 `import a, b` 有多个。 */ sources: Node[] /** 只导入类型(TypeScript 的 `import type`);没有这个概念的语言不填。 */ typeOnly?: boolean /** 副作用导入(`import './x'`)没有。 */ items: ImportItem[] } export interface DeclaratorFacts { /** 变量名;解构声明是整个模式。 */ name: Node type?: Node value?: Node } export interface VariableFacts { /** 只有模块顶层(Python 还有类主体)的声明有。 */ access?: Access /** 一条语句声明几个变量(`let a = 1, b = 2`)就有几项。 */ declarators: DeclaratorFacts[] } export interface BlockShape { /** 这一块对应的语法树节点(整条语句)。 */ node: Node /** * 块自己显示 / 编辑的那一段:复合语句只到主体开始之前,其余是整条语句。 * 函数、类的说明(facts.doc)也算在里面:JSDoc 往上延到注释开头,docstring 往下延到字符串结尾。 */ header: SourceSpan children: CodeBlock[] } /** 预览成属性表的块:语言插件从语法树读出结构化信息(facts),翻译插件把它排成属性表。 */ export interface FunctionBlock extends BlockShape { kind: 'function', facts: FunctionFacts } export interface ClassBlock extends BlockShape { kind: 'class', facts: ClassFacts } export interface ImportBlock extends BlockShape { kind: 'import', facts: ImportFacts } export interface VariableBlock extends BlockShape { kind: 'const' | 'variable', facts: VariableFacts } export type FactBlock = FunctionBlock | ClassBlock | ImportBlock | VariableBlock /** 带说明(facts.doc)的块。 */ export type DocumentedBlock = FunctionBlock | ClassBlock export type TextKind = Exclude /** 预览成一行译文的块。 */ export interface TextBlock extends BlockShape { kind: TextKind } export type CodeBlock = TextBlock | FactBlock /** 着色用的词性,源码着色和译文着色共用。 */ export type TokenRole = | 'keyword' // 流程关键字:import from export if else for return try catch await … | 'storage' // 声明关键字与字面量关键字:const function async class interface new true false null … | 'operator' // 被翻成文字的运算符:全等 并且 或者 非 | 'hint' // 属性表里的说明词:未标注 无 N 个 默认导出 … | 'variable' | 'function' | 'type' | 'string' | 'number' | 'literal' | 'comment' | 'plain' /** * 一段着色的文字。offset:这段照抄自源码里的名字(标识符、属性名、类型名、点分模块名的一节)或字符串时, * 它在源码里的起始下标(同 SourceSpan 的下标),预览拿它向 VS Code 查定义、跳过去;译词、提示词没有。 */ export interface Segment { text: string, role: TokenRole, offset?: number } /** * 一段 Markdown 说明文字:注释、JSDoc、docstring 去掉注释符号、引号和共同缩进后的原文,不做别的转换 * (reStructuredText 的 `:func:`、JSDoc 的 `@param` 都照抄)。预览按 Markdown 渲染成注释色的段落、列表、代码块,源码里的 HTML 当文字显示。 */ export interface Markdown { markdown: string } /** 预览里显示的一段文字:着色的词(一行译文、属性值),或整段 Markdown 说明(注释块、函数和类的说明)。 */ export type PreviewText = Segment[] | Markdown /** * 属性表里的一行或一个子行讲的是哪个定义:定义出来的那个名字的节点(取自 facts,例如参数名、导入项的名称和别名、 * 声明的变量名、类的泛型参数)在源码里的范围。跳到定义时,定义处落在这个范围里就只闪这一行;不填(第三方翻译插件可以不填)就闪整块。 */ export interface Defines { defines?: SourceRange } /** 属性表里展开的一个子行:几列对齐的格子,例如参数的名称 / 类型 / 默认值。 */ export interface PropertyItem extends Defines { cells: Segment[][] } /** 属性表的一行:左列属性名,右列着色的值或 Markdown 说明;items 是展开在这一行下面的子行(输入参数、导入项)。 */ export interface PropertyRow extends Defines { label: string value: PreviewText items?: PropertyItem[] } /** 语言插件:语法树 → 代码块树。 */ export interface LanguageAdapter { id: string /** 覆盖的 VS Code languageId,例如 ['typescript', 'typescriptreact', 'javascript', 'javascriptreact']。 */ languageIds: string[] /** 该 languageId 用的语法包 .wasm 的绝对路径(宿主负责加载,保证和解析器运行时是同一份)。 */ grammarPath: (languageId: string) => string toBlocks: (root: Node, source: string) => CodeBlock[] /** 源码着色:给语法树叶子节点定词性。 */ tokenRole: (leaf: Node) => TokenRole } /** 翻译插件:代码块 → 一行译文或属性表。 */ export interface Translator { id: string // 'typescript.zh-template' label: string // '中文直译' languageIds: string[] /** 只翻 header 那一段;注释块给去掉注释符号的 Markdown 原文。 */ translate: (block: TextBlock, source: string) => PreviewText /** 函数、类、导入、常量、变量块 → 属性表。 */ describe: (block: FactBlock, source: string) => PropertyRow[] } export interface CodeReaderApi { registerLanguage: (adapter: LanguageAdapter) => Disposable registerTranslator: (translator: Translator) => Disposable }