🐛 fix(vscode): Rust 卡片照抄的类型、签名逐个名字带下标,返回类型也能悬停跳转
This commit is contained in:
1 parent
ecb6dc89c6
commit
55595e948c
17 files changed
+220
-122
No files matched your search
@@ -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 {
|
||||
|
||||
Reference in new issue
Block a user