✨ feat(vscode): 代码阅读加异常卡片,Python、TypeScript 的异常类画成同一张表(属性、构造参数),方法照常是子块

This commit is contained in:
cruldra committed 2026-09-27 10:42:10 +08:00
1 parent d5a092dd6f
commit 0afd012c94
21 files changed
+1118 -66

No files matched your search

+73 -17
View File
@@ -1,4 +1,4 @@
import type { Access, AttributeNames, BaseFacts, BlockKind, ClassFacts, CommonAttribute, Defines, EntryFacts, EnumFacts, FactBlock, FunctionFacts, ImportFacts, ImportItem, Inline, IterationClause, IterationFacts, IterationResult, LanguageAdapter, Markdown, Node, PreviewText, PropertyItem, PropertyRow, Segment, SegmentGroup, SourceDocument, SourceRange, SourceSpan, TextBlock, TokenRole, Translator, VariableBlock } from '../contract'
import type { Access, AttributeNames, BaseFacts, BlockKind, ClassFacts, CommonAttribute, Defines, EntryFacts, EnumFacts, ExceptionFacts, FactBlock, FunctionFacts, ImportFacts, ImportItem, Inline, IterationClause, IterationFacts, IterationResult, LanguageAdapter, Markdown, Node, ParameterFacts, PreviewText, PropertyItem, PropertyRow, Segment, SegmentGroup, SourceDocument, SourceRange, SourceSpan, TextBlock, TokenRole, Translator, VariableBlock } from '../contract'
import { commonIndent, splitLines } from '../editText'
/** 按所在语法节点区分译法的关键字,例如 Python 的 else:if 后「否则」,for / while 后「未中断时」。 */
@@ -148,6 +148,7 @@ const KIND_ZH: Record<BlockKind, string> = {
function: '函数',
class: '类',
enum: '枚举',
exception: '异常',
type: '类型',
field: '字段',
const: '常量',
@@ -451,6 +452,8 @@ export function createZhTemplateTranslator(table: ZhTable): Translator {
return classRows(block.facts, phrases)
case 'enum':
return enumRows(block.facts, phrases)
case 'exception':
return exceptionRows(block.facts, phrases)
case 'import':
return importRows(block.facts, phrases)
default:
@@ -599,23 +602,28 @@ function functionRows(facts: FunctionFacts, say: Phrases): PropertyRow[] {
...accessRows(facts.access),
...flagRows('async', facts.async),
...decoratorRows(facts.decorators, say),
{
label: '输入参数',
value: count(facts.parameters.length),
columns: ['名称', '类型', '默认值'],
items: facts.parameters.map(param => ({
cells: [
param.optional ? [...say.translated(param.name), { text: '?', role: 'plain' }] : say.translated(param.name),
param.type ? say.translated(param.type) : [hint('未标注')],
param.default ? say.translated(param.default) : [],
],
...defining(param.name),
})),
},
parameterRow('输入参数', facts.parameters, say),
{ label: '输出参数', value: facts.returnType ? say.translated(facts.returnType) : [hint('未标注')] },
]
}
/** 参数表:列名是名称 / 类型 / 默认值,每个参数一行,讲的定义是参数名;没有默认值的格子留空。 */
function parameterRow(label: string, parameters: ParameterFacts[], say: Phrases): PropertyRow {
return {
label,
value: count(parameters.length),
columns: ['名称', '类型', '默认值'],
items: parameters.map(param => ({
cells: [
param.optional ? [...say.translated(param.name), { text: '?', role: 'plain' }] : say.translated(param.name),
param.type ? say.translated(param.type) : [hint('未标注')],
param.default ? say.translated(param.default) : [],
],
...defining(param.name),
})),
}
}
/**
* 类:名称 / 说明 / 访问级别 / 抽象(只有分这个的语言才有)/ 装饰器 / 类型参数 / 父类 / 实现的接口,
* 说明及以后各行有才显示;类型参数、父类、实现的接口各是一行,多项用逗号隔开。类型参数那一行讲的是这几个泛型参数的定义。
@@ -646,14 +654,14 @@ function baseText(base: BaseFacts, say: Phrases): Inline[] {
* 说明是成员的注释、JSDoc、属性 docstring 的原文用空格连起来,一个成员都没有说明时不给这一列。
*/
function enumRows(facts: EnumFacts, say: Phrases): PropertyRow[] {
const docs = facts.members.map(member => member.docs.map(node => say.doc(node)?.markdown).filter(Boolean).join(' '))
const docs = facts.members.map(member => docsText(member.docs, say))
const described = docs.some(Boolean)
return [
{ label: '名称', value: say.name(facts.name, 'type') },
...docRows(facts.doc, say),
...accessRows(facts.access),
...decoratorRows(facts.decorators, say),
...(facts.bases.length > 0 ? [{ label: '继承', value: joined(facts.bases.map(base => baseText(base, say)), ', ') }] : []),
...baseRows(facts.bases, say),
{
label: '成员',
value: count(facts.members.length),
@@ -662,7 +670,7 @@ function enumRows(facts: EnumFacts, say: Phrases): PropertyRow[] {
cells: [
say.name(member.name, 'variable'),
member.value ? say.translated(member.value) : [hint(member.computed === undefined ? '自动' : String(member.computed))],
...(described ? [docs[i] ? [segment(docs[i], 'comment', undefined)] : []] : []),
...(described ? [docCell(docs[i])] : []),
],
...defining(member.name),
})),
@@ -670,6 +678,54 @@ function enumRows(facts: EnumFacts, say: Phrases): PropertyRow[] {
]
}
/**
* 异常(Python、TypeScript 同一张表):名称 / 说明 / 访问级别 / 装饰器 / 继承(照写的父类),说明及以后有才显示;
* 类属性收成一张表:属性 | 类型 | 值 | 说明,一个属性都没写类型时没有「类型」列、都没有说明时没有「说明」列,没写的格子留空;
* 构造参数同函数的输入参数表。没有类属性、没写构造函数时没有这两行。
*/
function exceptionRows(facts: ExceptionFacts, say: Phrases): PropertyRow[] {
const docs = facts.fields.map(field => docsText(field.docs, say))
const described = docs.some(Boolean)
const typed = facts.fields.some(field => field.type)
const fields: PropertyRow = {
label: '属性',
value: count(facts.fields.length),
columns: ['属性', ...(typed ? ['类型'] : []), '值', ...(described ? ['说明'] : [])],
items: facts.fields.map((field, i) => ({
cells: [
say.name(field.name, 'variable'),
...(typed ? [field.type ? say.translated(field.type) : []] : []),
field.value ? say.translated(field.value) : [],
...(described ? [docCell(docs[i])] : []),
],
...defining(field.name),
})),
}
return [
{ label: '名称', value: facts.name ? say.name(facts.name, 'type') : [hint('匿名')] },
...docRows(facts.doc, say),
...accessRows(facts.access),
...decoratorRows(facts.decorators, say),
...baseRows(facts.bases, say),
...(facts.fields.length > 0 ? [fields] : []),
...(facts.parameters ? [parameterRow('构造参数', facts.parameters, say)] : []),
]
}
/** 继承:照写的父类,逗号隔开;没有父类时没有这一行。 */
function baseRows(bases: BaseFacts[], say: Phrases): PropertyRow[] {
return bases.length > 0 ? [{ label: '继承', value: joined(bases.map(base => baseText(base, say)), ', ') }] : []
}
/** 表格里一格说明:几段说明文字的原文用空格连起来。 */
function docsText(nodes: Node[], say: Phrases): string {
return nodes.map(node => say.doc(node)?.markdown).filter(Boolean).join(' ')
}
function docCell(text: string): Inline[] {
return text ? [segment(text, 'comment', undefined)] : []
}
/** 函数、类、常量、变量的说明:有文字才有这一行。 */
function docRows(doc: Node | undefined, say: Phrases): PropertyRow[] {
const markdown = doc && say.doc(doc)