✨ feat(vscode): 代码阅读支持库规则,内置 SQLAlchemy 模型类显示成数据表卡片

This commit is contained in:
cruldra committed 2026-09-26 18:29:40 +08:00
1 parent 32be7d54b6
commit 5ece24cef9
26 files changed
+1768 -81

No files matched your search

+67
View File
@@ -284,15 +284,82 @@ export interface Translator {
id: string // 'typescript.zh-template'
label: string // '中文直译'
languageIds: string[]
/** 译文用的语言(BCP 47 的语言部分,例如 'zh'):库规则按它挑自己的词表。 */
displayLanguage: string
/** 只翻 header 那一段;注释块给去掉注释符号的 Markdown 原文。 */
translate: (block: TextBlock, document: SourceDocument) => PreviewText
/** 函数、类、导入、常量、变量块 → 属性表。 */
describe: (block: FactBlock, document: SourceDocument) => PropertyRow[]
/** 一个表达式或类型节点整个翻成一行译文,译法同属性表里的值:库规则翻默认值、类型时借它。 */
expression: (node: Node, document: SourceDocument) => Inline[]
/** 一段说明文字(注释、docstring、当说明用的字符串)去掉注释符号、引号和共同缩进后的 Markdown 原文,同属性表的「说明」;没有文字时没有。 */
doc: (node: Node, document: SourceDocument) => Markdown | undefined
/** 筛选属性和值叫什么,和属性表里的属性名、值用同一套叫法;不给就都显示 id。 */
attributeNames?: AttributeNames
}
/** 一种颜色在暗色、亮色主题下各用哪个(CSS 颜色值);高对比主题跟着暗 / 亮走。 */
export interface ThemeColor { dark: string, light: string }
/** 种类标签:文字和颜色。 */
export interface KindBadge { label: string, color: ThemeColor }
/**
* 库规则认领一块后给出的替身:预览里它代替原来那块,是一张属性表(种类标签、每一行都由规则给),下面挂着原块留下的子块。
*/
export interface RuleBlock {
/** 种类 id,写成「规则 id.名字」(sqlalchemy.table):筛选的 kind 属性值就是它,筛选记住的也是它,要稳定。 */
kind: string
/** 种类标签的文字和颜色:筛选栏里这个种类也叫这个名字。 */
badge: KindBadge
rows: PropertyRow[]
/** 块自己的名字(类名)在源码里的范围:跳到的定义就是它时闪整块。 */
defines?: SourceRange
/** 规则自己的筛选属性,叠在宿主从原块推出的属性上(同 BlockShape.attributes);kind 总是上面的 kind,这里填了不算。 */
attributes?: BlockAttributes
/**
* 并进这一块的子块(原块 children 里的对象本身):不再单独成块,内容由 rows 讲。
* 这一块的编辑范围从原块头部开始、到最后一个并进来的子块结束,连成一段;夹在这段中间的别的子块(注释等)也跟着并进来,
* 不然同一行能在两处改。这段以后的子块(方法等)照常是这一块的子块,也照常交给各规则看。
*/
absorbs: CodeBlock[]
}
/** 库规则看一块时宿主给的:这份源码、它的导入,以及借当前翻译插件翻表达式、取说明的办法。 */
export interface RuleContext {
document: SourceDocument
/** 这份源码里各处导入的 facts,照源码顺序:规则拿它认出库里名字的别名(`from sqlalchemy import Enum as SQLEnum`)。 */
imports: ImportFacts[]
/** 当前翻译插件的 displayLanguage;没有翻译插件时没有。规则按它挑自己的词表,没有这种语言的词表就用自己默认的那份。 */
displayLanguage?: string
/** 用当前翻译插件把一个表达式或类型节点翻成一行译文(Translator.expression):名字带源码下标,能跳到定义、高亮各处出现;没有翻译插件时照抄源码。 */
translate: (node: Node) => Inline[]
/** 用当前翻译插件取一段说明文字(Translator.doc);没有翻译插件、没有文字时没有。 */
doc: (node: Node) => Markdown | undefined
}
/**
* 库规则:认出某个库的一种写法(SQLAlchemy 的模型类),把那块整个换成一张专门的卡片;文件导入了它关心的库才启用。
* 规则只经契约拿信息:块(kind、node、header、children、facts)和 RuleContext;用词(属性名、种类名、类型的译名)属于规则自己。
*/
export interface LibraryRule {
id: string // 'sqlalchemy'
label: string // 'SQLAlchemy 数据表'
languageIds: string[]
/**
* 关心的库(模块名):这份源码里有一条导入(ImportFacts.sources,去掉引号)等于它、或以「它.」「它/」开头(它的子模块)才启用。
* 宿主按语言插件给的导入判断,规则不用自己读导入语句。
*/
libraries: string[]
/**
* 看一块:认领就返回替身,不认就返回 undefined。宿主从顶层往下每块都问(被认领的块留下的子块照样问)。
* 几个规则都认同一块时先注册的算;规则抛错、或替身不合上面的约定时,宿主记日志、当它没认,接着问下一个规则。
*/
claim: (block: CodeBlock, context: RuleContext) => RuleBlock | undefined
}
export interface CodeReaderApi {
registerLanguage: (adapter: LanguageAdapter) => Disposable
registerTranslator: (translator: Translator) => Disposable
registerLibraryRule: (rule: LibraryRule) => Disposable
}