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

196 lines
8.6 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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<T>` 里的 Base(一个表达式)和跟在它后面的泛型实参 `<T>`(语法里是两个节点);
* 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>` 里的 `T extends X = Y`)。 */
typeParameters: Node[]
/** 按源码顺序。 */
bases: BaseFacts[]
/** 实现的接口(TypeScript 的 `implements A, B<T>`),每个接口一项。 */
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<BlockKind, FactBlock['kind']>
/** 预览成一行译文的块。 */
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
}