✨ feat(vscode): 代码阅读加枚举卡片,Python enum 库规则和 TypeScript enum 画成同一张表

This commit is contained in:
cruldra committed 2026-09-26 20:10:36 +08:00
1 parent 2251e67ef8
commit de355661f0
24 files changed
+858 -83

No files matched your search

+60 -9
View File
@@ -4,7 +4,7 @@ import type { Disposable } from 'vscode'
export type { Node }
export type BlockKind
= | 'import' | 'function' | 'class' | 'type' | 'field' | 'const' | 'variable'
= | 'import' | 'function' | 'class' | 'enum' | 'type' | 'field' | 'const' | 'variable'
| 'if' | 'else' | 'loop' | 'try' | 'catch' | 'finally' | 'return' | 'statement' | 'comment'
/** 源码里一段的下标:源码字符串下标(web-tree-sitter 的 startIndex / endIndex),end 为开区间。 */
@@ -70,6 +70,37 @@ export interface ClassFacts {
implements: Node[]
}
/** 枚举的一个成员;节点都指向源码。 */
export interface EnumMemberFacts {
name: Node
/** 源码里写的值;没写(TypeScript 的自增成员)、或值交给库自动取(Python 的 `auto()`)时没有。 */
value?: Node
/** 没写值、语言算得出来时的值(TypeScript 数值枚举自增:0、1、2……);算不出来时没有。 */
computed?: number
/**
* 成员的说明文字节点(注释、JSDoc、属性 docstring),照源码顺序:紧挨在它上面(从上一个成员之后起)单独成行的、
* 写在它这一行行尾的、Python 紧跟在它后面的属性 docstring。翻译插件逐个取原文连起来。
*/
docs: Node[]
}
/**
* 枚举:TypeScript 的 `enum` 由语言插件报;Python 没有枚举语法,自带 enum 库的写法(`class X(enum.Enum)`)由库规则认成这种块。
* 两边同一种块、同一张属性表。
*/
export interface EnumFacts {
name: Node
/** 枚举自己的说明,同 ClassFacts.doc。 */
doc?: Node
/** 同 ClassFacts.access。 */
access?: Access
decorators: Node[]
/** 照源码写的父类(Python 的 `str, enum.Enum`);TypeScript 没有。 */
bases: BaseFacts[]
/** 照源码顺序。 */
members: EnumMemberFacts[]
}
/** 导入的一项。 */
export type ImportItem
= | { kind: 'named', name: Node, alias?: Node } // import { a as b }、from m import a as b
@@ -145,7 +176,7 @@ export interface VariableFacts {
* - kind:块的种类(BlockKind);
* - access:访问级别,'public' | 'private' | 'protected',语言可以加自己的值(Kotlin 的 'internal',见 BlockShape.attributes);
* - async、abstract、typeOnly:异步、抽象、仅类型,值是 'true' | 'false'。
* 宿主从块的 kind 和 facts 推出它们(FunctionFacts.access / async、ClassFacts.access / abstract、ImportFacts.typeOnly、VariableFacts.access),
* 宿主从块的 kind 和 facts 推出它们(FunctionFacts.access / async、ClassFacts.access / abstract、EnumFacts.access、ImportFacts.typeOnly、VariableFacts.access),
* 语言插件不用另报;facts 里没填的(语言没有这个概念、块没有这一项),块就没有这个属性,也不受这个属性的筛选影响。
*/
export const COMMON_ATTRIBUTES = ['kind', 'access', 'async', 'abstract', 'typeOnly'] as const
@@ -174,12 +205,17 @@ export interface BlockShape {
/** 预览成属性表的块:语言插件从语法树读出结构化信息(facts),翻译插件把它排成属性表。 */
export interface FunctionBlock extends BlockShape { kind: 'function', facts: FunctionFacts }
export interface ClassBlock extends BlockShape { kind: 'class', facts: ClassFacts }
/** 枚举块的头部是整个枚举(成员都在属性表里讲),没有子块;库规则认出来的枚举(Python)是整个类,留下的方法等是子块。 */
export interface EnumBlock extends BlockShape { kind: 'enum', facts: EnumFacts }
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
export type FactBlock = FunctionBlock | ClassBlock | EnumBlock | ImportBlock | VariableBlock
/** 带说明(facts.doc)的块。 */
export type DocumentedBlock = FunctionBlock | ClassBlock | VariableBlock
export type DocumentedBlock = FunctionBlock | ClassBlock | EnumBlock | VariableBlock
/** 属性表块的种类和 facts,不带块的形状(节点、头部、子块):库规则把一块认成现成的一种属性表块时给它(RuleFacts)。 */
export type BlockFacts = FactBlock extends infer B ? B extends FactBlock ? Pick<B, 'kind' | 'facts'> : never : never
export type TextKind = Exclude<BlockKind, FactBlock['kind']>
@@ -301,7 +337,7 @@ export interface Translator {
displayLanguage: string
/** 只翻 header 那一段;注释块给去掉注释符号的 Markdown 原文。 */
translate: (block: TextBlock, document: SourceDocument) => PreviewText
/** 函数、类、导入、常量、变量块 → 属性表。 */
/** 函数、类、枚举、导入、常量、变量块 → 属性表。 */
describe: (block: FactBlock, document: SourceDocument) => PropertyRow[]
/** 一个表达式或类型节点整个翻成一行译文,译法同属性表里的值:库规则翻默认值、类型时借它。 */
expression: (node: Node, document: SourceDocument) => Inline[]
@@ -318,9 +354,13 @@ export interface ThemeColor { dark: string, light: string }
export interface KindBadge { label: string, color: ThemeColor }
/**
* 库规则认领一块后给出的替身:预览里它代替原来那块,是一张属性表(种类标签、每一行都由规则给),下面挂着原块留下的子块。
* 库规则认领一块后给出的替身,预览里它代替原来那块,下面挂着原块留下的子块:
* 规则自己的卡片(RuleCard),或认成契约里现成的一种属性表块(RuleFacts)。
*/
export interface RuleBlock {
export type RuleBlock = RuleCard | RuleFacts
/** 规则自己的卡片:一张属性表,种类标签、每一行都由规则给(用词归规则)。 */
export interface RuleCard {
/** 种类 id,写成「规则 id.名字」(sqlalchemy.table):筛选的 kind 属性值就是它,筛选记住的也是它,要稳定。 */
kind: string
/** 种类标签的文字和颜色:筛选栏里这个种类也叫这个名字。 */
@@ -338,6 +378,16 @@ export interface RuleBlock {
absorbs: CodeBlock[]
}
/**
* 把这块认成契约里现成的一种属性表块(Python 自带 enum 库的类 → 枚举块):宿主当语言插件报的这种块处理,
* 种类、种类名、颜色、属性表、筛选属性都和语言自带的这种块一样,由翻译插件排;规则只给 facts(库的知识),不给用词。
* 块的头部是原块整条语句(facts 里的节点都在里面),absorbs 同 RuleCard.absorbs。
*/
export interface RuleFacts {
as: BlockFacts
absorbs: CodeBlock[]
}
/** 库规则看一块时宿主给的:这份源码、它的导入,以及借当前翻译插件翻表达式、取说明的办法。 */
export interface RuleContext {
document: SourceDocument
@@ -396,8 +446,9 @@ export interface RuleWorkspace {
}
/**
* 库规则:认出某个库的一种写法(SQLAlchemy 的模型类),把那块整个换成一张专门的卡片;文件导入了它关心的库才启用。
* 规则只经契约拿信息:块(kind、node、header、children、facts)和 RuleContext;用词(属性名、种类名、类型的译名)属于规则自己。
* 库规则:认出某个库的一种写法(SQLAlchemy 的模型类),把那块整个换成一张专门的卡片,或认成现成的一种属性表块
* (enum 库的类 → 枚举块);文件导入了它关心的库才启用。
* 规则只经契约拿信息:块(kind、node、header、children、facts)和 RuleContext;卡片的用词(属性名、种类名、类型的译名)属于规则自己。
*/
export interface LibraryRule {
id: string // 'sqlalchemy'