🐛 fix(vscode): Rust 卡片照抄的类型、签名逐个名字带下标,返回类型也能悬停跳转

This commit is contained in:
cruldra committed 2026-10-15 19:48:56 +11:00
1 parent ecb6dc89c6
commit 55595e948c
17 files changed
+220 -122

No files matched your search

+18 -24
View File
@@ -1,6 +1,7 @@
import type { FunctionBlock, Inline, KindBadge, LibraryRule, Node, PropertyItem, PropertyRow, RuleCard, RuleContext, ThemeColor } from '../contract'
import { returnNote, throwsRows, writtenParamRows } from './docRows'
import { attributeName, docSummary, named, oneLine, returnText, stringContent } from './rustTree'
import { returnValue } from './rustRows'
import { attributeName, docSummary, named, stringContent } from './rustTree'
/** 和 FastAPI 接口同一个蓝。 */
const COLOR: ThemeColor = { dark: '#61afef', light: '#1a6fb5' }
@@ -52,14 +53,14 @@ function attributeRoute(block: FunctionBlock): Route | undefined {
function card(block: FunctionBlock, route: Route, context: RuleContext): RuleCard {
const doc = block.facts.doc && context.doc(block.facts.doc)
const summary = docSummary(doc)
const params = pathParams(route.path, block.node)
const params = pathParams(route.path, block.node, context)
const rows: PropertyRow[] = [
nameRow(block.facts.name),
...(summary ? [{ label: '说明', value: { markdown: summary } }] : []),
...(block.facts.async ? [{ label: '异步', value: [keyword('是')] }] : []),
requestRow(route, params),
...writtenParamRows(doc?.params ?? [], '参数'),
{ label: '返回', value: [plain(returnText(block.node))], ...returnNote(doc) },
{ label: '返回', value: returnValue(block.facts.returnType, context), ...returnNote(doc) },
...throwsRows(doc),
]
return {
@@ -86,7 +87,7 @@ function handled(node: Node, handler: string | undefined): boolean {
function routerCard(node: Node, route: Route & { handlerNode?: Node }, context: RuleContext): RuleCard {
const fn = route.handler ? functionNamed(node, route.handler) : undefined
const params = fn ? pathParams(route.path, fn) : []
const params = fn ? pathParams(route.path, fn, context) : []
const comment = fn && leadingDoc(fn)
const doc = docSummary(comment && context.doc(comment))
return {
@@ -96,17 +97,17 @@ function routerCard(node: Node, route: Route & { handlerNode?: Node }, context:
{ label: '名称', value: route.handler ? [plain(route.handler)] : [hint('路由')] },
...(doc ? [{ label: '说明', value: { markdown: doc } }] : []),
requestRow(route, params),
{ label: '返回', value: [plain(fn ? returnText(fn) : '—')] },
{ label: '返回', value: fn ? returnValue(fn.childForFieldName('return_type'), context) : [plain('—')] },
],
absorbs: [],
}
}
function requestRow(route: Route, params: string[]): PropertyRow {
function requestRow(route: Route, params: Inline[][]): PropertyRow {
const items: PropertyItem[] = [
{ cells: [[plain('方法')], [keyword(route.method)]] },
{ cells: [[plain('路径')], [{ text: route.path, role: 'string' }]] },
...(params.length > 0 ? [{ cells: [[plain('路径参数')], params.map(text => plain(text)).flatMap((part, index) => index === 0 ? [part] : [plain(', '), part])] }] : []),
...(params.length > 0 ? [{ cells: [[plain('路径参数')], params.flatMap((part, index) => index === 0 ? part : [plain(', '), ...part])] }] : []),
]
return {
label: '请求',
@@ -141,15 +142,12 @@ function routesOn(node: Node, found: (Route & { handlerNode?: Node })[] = []): (
return found
}
/** 路径里的 {名字} 对上参数。Path(id): Path<Uuid> 写成 id: Uuid。 */
function pathParams(path: string, fn: Node): string[] {
/** 路径里的 `{名字}` 对上函数的参数:`Path(id): Path<Uuid>` 写成 `id: Uuid`,类型照抄成一行、名字各自带源码下标。 */
function pathParams(path: string, fn: Node, context: RuleContext): Inline[][] {
const names = [...path.matchAll(/\{(\w+)\}/g)].map(match => match[1] ?? '')
return names.flatMap((name) => {
const param = parameterNamed(fn, name)
if (!param)
return [`${name}`]
const type = innerType(param.childForFieldName('type'))
return [type ? `${name}: ${type}` : name]
return names.map((name) => {
const type = innerType(parameterNamed(fn, name)?.childForFieldName('type'))
return type ? [plain(`${name}: `), ...context.verbatim(type)] : [plain(name)]
})
}
@@ -163,15 +161,11 @@ function parameterNamed(fn: Node, name: string): Node | undefined {
})
}
function innerType(type: Node | null): string | undefined {
if (!type)
return undefined
if (type.type === 'generic_type' && type.childForFieldName('type')?.text === 'Path') {
const arg = named(type.childForFieldName('type_arguments'))[0]
if (arg)
return oneLine(arg.text)
}
return oneLine(type.text)
/** 路径参数的类型:`Path<Uuid>` 取尖括号里的第一个,别的写法就是它自己。 */
function innerType(type: Node | null | undefined): Node | undefined {
if (type?.type === 'generic_type' && type.childForFieldName('type')?.text === 'Path')
return named(type.childForFieldName('type_arguments'))[0] ?? type
return type ?? undefined
}
function itemAttributesHasRoute(fn: Node): boolean {