✨ 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

+30 -22
View File
@@ -7,7 +7,7 @@ import { activeRules, claimBlock, claimedShape, importsIn } from './libraryRules
interface BlockViewBase {
/** 在树里的位置,例如 '6.1.0'。 */
id: string
/** BlockKind,或库规则认领的块的种类 id(RuleBlock.kind,带点,例如 sqlalchemy.table)。 */
/** BlockKind,或库规则卡片的种类 id(RuleCard.kind,带点,例如 sqlalchemy.table)。 */
kind: string
/**
* 编辑范围的起止行,0 起:一般是 header;库规则认领的块是原块整条语句(见 claimedShape),盖住它留下的子块的行。
@@ -23,13 +23,13 @@ interface BlockViewBase {
defines?: SourceRange
/** 筛选属性(含 kind),见 blockAttributes;库规则认领的块叠上规则给的,kind 是规则的种类 id。 */
attributes: BlockAttributes
/** 库规则认领的块才有:种类标签的文字和颜色(RuleBlock.badge)。预览同类块一样默认收起它的子块。 */
/** 库规则的卡片才有:种类标签的文字和颜色(RuleCard.badge)。预览同类块一样默认收起它的子块。 */
badge?: KindBadge
children: BlockView[]
}
/**
* 发给 webview 的一块(可序列化):函数、类、导入、常量、变量块和库规则认领的块预览时是属性表,注释块是 Markdown 说明,其余是一行译文。
* 发给 webview 的一块(可序列化):函数、类、枚举、导入、常量、变量块和库规则的卡片预览时是属性表,注释块是 Markdown 说明,其余是一行译文。
* 一行译文的块带说明(TextBlock.doc)时 doc 是翻译插件给的 Markdown 原文,预览排在译文下面。
*/
export type BlockView = BlockViewBase & ({ translation: PreviewText, doc?: Markdown } | { properties: PropertyRow[] })
@@ -103,6 +103,7 @@ function ownName(block: CodeBlock): Node | undefined {
switch (block.kind) {
case 'function':
case 'class':
case 'enum':
return block.facts.name
case 'const':
case 'variable':
@@ -122,7 +123,8 @@ const NO_RULES: RuleRun = { rules: [], report: () => {} }
/**
* 代码块树 → 视图数据:header 整行源码去共同缩进、按语法树着色、调用翻译插件。
* 每块先问启用的库规则,认领了就换成规则给的替身(见 RuleBlock),并进去的子块不再单独成块。
* 每块先问启用的库规则,认领了就换成规则给的替身(见 RuleBlock):规则的卡片,或认成的属性表块(交给翻译插件排,同语言插件报的这种块),
* 并进去的子块不再单独成块。
*/
export function toBlockViews(blocks: CodeBlock[], source: string, adapter: LanguageAdapter, translator: Translator | undefined, rules: RuleRun = NO_RULES): BlockView[] {
const lines = lineRanges(source)
@@ -153,34 +155,40 @@ export function toBlockViews(blocks: CodeBlock[], source: string, adapter: Langu
const doc = block.doc && translator?.doc(block.doc, document)
return { translation: translator ? translator.translate(block, document) : [], ...(doc && { doc }) }
}
const build = (block: CodeBlock, id: string): BlockView => {
const root = block.node.tree.rootNode
const claim = active.length > 0 ? claimBlock(block, active, context, rules.report) : undefined
if (claim) {
const { kind, badge, rows, defines, attributes } = claim.block
const { span, kept } = claimedShape(block, claim.block.absorbs)
return {
id,
kind,
...sourceRows(root, span.startRow, span.endRow),
...(defines && { defines: { startIndex: defines.startIndex, endIndex: defines.endIndex } }),
attributes: { ...blockAttributes(block), ...attributes, kind },
badge,
children: kept.map((child, i) => build(child, `${id}.${i}`)),
properties: rows,
}
}
/** 块照它自己的样子(语言插件报的,或库规则认成的属性表块):头部是编辑范围,子块照常交给各规则看。 */
function plain(block: CodeBlock, id: string): BlockView {
const name = ownName(block)
return {
id,
kind: block.kind,
...sourceRows(root, block.header.startRow, block.header.endRow),
...sourceRows(block.node.tree.rootNode, block.header.startRow, block.header.endRow),
...(name && { defines: { startIndex: name.startIndex, endIndex: name.endIndex } }),
attributes: blockAttributes(block),
children: block.children.map((child, i) => build(child, `${id}.${i}`)),
...('facts' in block ? { properties: translator ? translator.describe(block, document) : [] } : textView(block)),
}
}
function build(block: CodeBlock, id: string): BlockView {
const claim = active.length > 0 ? claimBlock(block, active, context, rules.report) : undefined
if (!claim)
return plain(block, id)
const { span, kept } = claimedShape(block, claim.block.absorbs)
if ('as' in claim.block) {
const { attributes } = block
return plain({ ...claim.block.as, node: block.node, header: span, children: kept, ...(attributes && { attributes }) }, id)
}
const { kind, badge, rows, defines, attributes } = claim.block
return {
id,
kind,
...sourceRows(block.node.tree.rootNode, span.startRow, span.endRow),
...(defines && { defines: { startIndex: defines.startIndex, endIndex: defines.endIndex } }),
attributes: { ...blockAttributes(block), ...attributes, kind },
badge,
children: kept.map((child, i) => build(child, `${id}.${i}`)),
properties: rows,
}
}
return blocks.map((block, i) => build(block, String(i)))
}