✨ feat(vscode): 代码阅读预览顶部加块筛选栏
语言插件按和语言无关的 id 报块属性(通用的由宿主从 facts 推),翻译插件起名,webview 只按 id 筛; 筛选整个工作区共用、记在 workspaceState;JavaScript 不再显示「抽象:否」「仅类型:否」
This commit is contained in:
1 parent
4eaf2ae11d
commit
1c7e31c51a
29 files changed
+1364
-319
No files matched your search
@@ -1,4 +1,4 @@
|
||||
import type { Access, ClassFacts, Defines, EntryFacts, FactBlock, FunctionFacts, ImportFacts, ImportItem, Markdown, Node, PreviewText, PropertyItem, PropertyRow, Segment, SourceSpan, TextBlock, TokenRole, Translator, VariableBlock } from '../contract'
|
||||
import type { Access, AttributeNames, BlockKind, ClassFacts, CommonAttribute, Defines, EntryFacts, FactBlock, FunctionFacts, ImportFacts, ImportItem, Markdown, Node, PreviewText, PropertyItem, PropertyRow, Segment, SourceSpan, TextBlock, TokenRole, Translator, VariableBlock } from '../contract'
|
||||
import { commonIndent, splitLines } from '../editText'
|
||||
|
||||
/** 按所在语法节点区分译法的关键字,例如 Python 的 else:if 后「否则」,for / while 后「未中断时」。 */
|
||||
@@ -122,6 +122,34 @@ function slotChild(node: Node, slot: Exclude<TemplatePart, string>): Node | null
|
||||
return node.namedChildren.filter(child => child && !child.isExtra)[slot.namedChild]
|
||||
}
|
||||
|
||||
const ATTRIBUTE_ZH: Record<CommonAttribute, string> = { kind: '种类', access: '访问级别', async: '异步', abstract: '抽象', typeOnly: '仅类型' }
|
||||
const KIND_ZH: Record<BlockKind, string> = {
|
||||
import: '导入',
|
||||
function: '函数',
|
||||
class: '类',
|
||||
type: '类型',
|
||||
field: '字段',
|
||||
const: '常量',
|
||||
variable: '变量',
|
||||
if: '条件',
|
||||
else: '否则',
|
||||
loop: '循环',
|
||||
try: '尝试',
|
||||
catch: '捕获',
|
||||
finally: '最终',
|
||||
return: '返回',
|
||||
statement: '语句',
|
||||
comment: '注释',
|
||||
}
|
||||
const ACCESS_ZH: Record<Access, string> = { public: '公共', private: '私有', protected: '受保护' }
|
||||
const YES_NO: Record<'true' | 'false', string> = { true: '是', false: '否' }
|
||||
|
||||
/** 筛选属性和值的中文叫法;属性表里的访问级别、异步、抽象、仅类型这几行,属性名和值也用这一套。 */
|
||||
const ZH_ATTRIBUTE_NAMES: AttributeNames = {
|
||||
attributes: ATTRIBUTE_ZH,
|
||||
values: { kind: KIND_ZH, access: ACCESS_ZH, async: YES_NO, abstract: YES_NO, typeOnly: YES_NO },
|
||||
}
|
||||
|
||||
export function createZhTemplateTranslator(table: ZhTable): Translator {
|
||||
const operatorParents = new Set(table.operatorParents)
|
||||
const stringNodes = new Set(table.stringNodes)
|
||||
@@ -318,7 +346,7 @@ export function createZhTemplateTranslator(table: ZhTable): Translator {
|
||||
}
|
||||
}
|
||||
|
||||
return { id: table.id, label: table.label, languageIds: table.languageIds, translate, describe }
|
||||
return { id: table.id, label: table.label, languageIds: table.languageIds, translate, describe, attributeNames: ZH_ATTRIBUTE_NAMES }
|
||||
}
|
||||
|
||||
function segment(text: string, role: TokenRole, offset: number | undefined): Segment {
|
||||
@@ -375,14 +403,13 @@ interface Phrases {
|
||||
doc: (node: Node) => Markdown | undefined
|
||||
}
|
||||
|
||||
const ACCESS_ZH: Record<Access, string> = { public: '公共', private: '私有', protected: '受保护' }
|
||||
|
||||
function hint(text: string): Segment {
|
||||
return { text, role: 'hint' }
|
||||
}
|
||||
|
||||
function yesNo(value: boolean): Segment[] {
|
||||
return [{ text: value ? '是' : '否', role: 'storage' }]
|
||||
/** 布尔属性的一行:没有这个概念的语言(facts 里没填)没有这一行。 */
|
||||
function flagRows(attribute: 'async' | 'abstract' | 'typeOnly', value: boolean | undefined): PropertyRow[] {
|
||||
return value === undefined ? [] : [{ label: ATTRIBUTE_ZH[attribute], value: [{ text: YES_NO[`${value}`], role: 'storage' }] }]
|
||||
}
|
||||
|
||||
function count(n: number): Segment[] {
|
||||
@@ -394,7 +421,7 @@ function joined(parts: Segment[][], separator: string): Segment[] {
|
||||
}
|
||||
|
||||
function accessRows(access: Access | undefined): PropertyRow[] {
|
||||
return access ? [{ label: '访问级别', value: [{ text: ACCESS_ZH[access], role: 'keyword' }] }] : []
|
||||
return access ? [{ label: ATTRIBUTE_ZH.access, value: [{ text: ACCESS_ZH[access], role: 'keyword' }] }] : []
|
||||
}
|
||||
|
||||
/** 这一行 / 子行讲的定义:几个节点(导入项是名称和别名)合起来在源码里的范围;一个节点都没有就不填。 */
|
||||
@@ -422,13 +449,13 @@ function aliased(item: Segment[], alias: Node | undefined, say: Phrases): Segmen
|
||||
return [...item, { text: ' ', role: 'plain' }, { text: '作为', role: 'keyword' }, { text: ' ', role: 'plain' }, ...say.translated(alias)]
|
||||
}
|
||||
|
||||
/** 函数:名称 / 说明 / 访问级别 / 异步 / 装饰器 / 输入参数(每个参数一行:名称、类型、默认值)/ 输出参数。 */
|
||||
/** 函数:名称 / 说明 / 访问级别 / 异步(只有分这个的语言才有)/ 装饰器 / 输入参数(每个参数一行:名称、类型、默认值)/ 输出参数。 */
|
||||
function functionRows(facts: FunctionFacts, say: Phrases): PropertyRow[] {
|
||||
return [
|
||||
{ label: '名称', value: facts.name ? say.name(facts.name, 'function') : [hint('匿名')] },
|
||||
...docRows(facts.doc, say),
|
||||
...accessRows(facts.access),
|
||||
{ label: '异步', value: yesNo(facts.async) },
|
||||
...flagRows('async', facts.async),
|
||||
...decoratorRows(facts.decorators, say),
|
||||
{
|
||||
label: '输入参数',
|
||||
@@ -457,7 +484,7 @@ function classRows(facts: ClassFacts, say: Phrases): PropertyRow[] {
|
||||
{ label: '名称', value: facts.name ? say.name(facts.name, 'type') : [hint('匿名')] },
|
||||
...docRows(facts.doc, say),
|
||||
...accessRows(facts.access),
|
||||
...(facts.abstract === undefined ? [] : [{ label: '抽象', value: yesNo(facts.abstract) }]),
|
||||
...flagRows('abstract', facts.abstract),
|
||||
...decoratorRows(facts.decorators, say),
|
||||
...listRow('类型参数', facts.typeParameters.map(say.translated), defining(...facts.typeParameters)),
|
||||
...listRow('父类', facts.bases.map(base => base.typeArguments ? [...say.translated(base.value), ...say.translated(base.typeArguments)] : say.translated(base.value))),
|
||||
@@ -493,7 +520,7 @@ function importRows(facts: ImportFacts, say: Phrases): PropertyRow[] {
|
||||
}
|
||||
return [
|
||||
{ label: '来源', value: facts.sources.length > 0 ? joined(facts.sources.map(say.module), ', ') : [hint('无')] },
|
||||
...(facts.typeOnly === undefined ? [] : [{ label: '仅类型', value: yesNo(facts.typeOnly) }]),
|
||||
...flagRows('typeOnly', facts.typeOnly),
|
||||
{ label: '导入项', value: count(facts.items.length), items: facts.items.map(item => ({ cells: [itemText(item)], ...defining(...importNodes(item)) })) },
|
||||
]
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user