✨ feat(vscode): 代码阅读认 axum、sqlx 和 tauri
This commit is contained in:
1 parent
44de0a1f70
commit
69608f9c70
9 files changed
+500
-3
No files matched your search
@@ -0,0 +1,81 @@
|
||||
import type { CodeBlock, Inline, KindBadge, LibraryRule, Node, PropertyRow, RuleCard, ThemeColor } from '../contract'
|
||||
import { commentPlain, firstSentence, macroInvocation, oneLine, stringContent } from '../languages/rust'
|
||||
import { named } from '../languages/shared'
|
||||
|
||||
/** 查询卡用字符串那种橙。 */
|
||||
const COLOR: ThemeColor = { dark: '#ce9178', light: '#a31515' }
|
||||
const BADGE: KindBadge = { label: '查询', color: COLOR, icon: 'database' }
|
||||
const MACROS = new Set(['query', 'query_as', 'query_scalar'])
|
||||
|
||||
/**
|
||||
* sqlx::query! / query_as! 这类宏。一句说明、等宽 SQL、参数、返回类型。
|
||||
* 文件里导入了 sqlx 才启用。
|
||||
*/
|
||||
export const sqlxRule: LibraryRule = {
|
||||
id: 'sqlx',
|
||||
label: 'sqlx 查询',
|
||||
languageIds: ['rust'],
|
||||
libraries: ['sqlx'],
|
||||
claim: (block) => {
|
||||
if (block.kind === 'comment')
|
||||
return nextQuery(block.node) ? { omit: true } : undefined
|
||||
const macro = block.kind === 'statement' ? findQuery(block.node) : undefined
|
||||
return macro ? card(block, macro) : undefined
|
||||
},
|
||||
attributeNames: () => ({ attributes: {}, values: { kind: { 'sqlx.query': '查询' } } }),
|
||||
}
|
||||
|
||||
function card(block: CodeBlock, macro: Node): RuleCard {
|
||||
const call = macroInvocation(macro)
|
||||
const args = call?.args ?? []
|
||||
const typed = call?.name.split('::').pop() !== 'query'
|
||||
const sqlNode = args[typed ? 1 : 0]
|
||||
const sql = stringContent(sqlNode) ?? ''
|
||||
const params = args.slice(typed ? 2 : 1)
|
||||
const returned = typed ? args[0] : undefined
|
||||
const note = precedingNote(block.node)
|
||||
const rows: PropertyRow[] = [
|
||||
...(note ? [{ label: '说明', value: { markdown: note } }] : []),
|
||||
{ label: 'SQL', value: [{ text: sql, role: 'string', ...(sqlNode && { offset: sqlNode.startIndex }) }] },
|
||||
...(params.length > 0
|
||||
? [{ label: '参数', value: [{ text: params.map((param, index) => `$${index + 1} = ${oneLine(param.text)}`).join('、'), role: 'plain' as const }] }]
|
||||
: []),
|
||||
{ label: '返回类型', value: returned ? [{ text: oneLine(returned.text), role: 'type', offset: returned.startIndex }] : [hint('—')] },
|
||||
]
|
||||
return { kind: 'sqlx.query', badge: BADGE, rows, absorbs: [] }
|
||||
}
|
||||
|
||||
function findQuery(node: Node): Node | undefined {
|
||||
if (node.type === 'macro_invocation') {
|
||||
const last = node.childForFieldName('macro')?.text.split('::').pop()
|
||||
if (last && MACROS.has(last))
|
||||
return node
|
||||
}
|
||||
for (const child of named(node)) {
|
||||
const found = findQuery(child)
|
||||
if (found)
|
||||
return found
|
||||
}
|
||||
return undefined
|
||||
}
|
||||
|
||||
function nextQuery(comment: Node): Node | undefined {
|
||||
let next = comment.nextNamedSibling
|
||||
while (next?.type === 'attribute_item')
|
||||
next = next.nextNamedSibling
|
||||
return next ? findQuery(next) : undefined
|
||||
}
|
||||
|
||||
function precedingNote(node: Node): string | undefined {
|
||||
let prev = node.previousNamedSibling
|
||||
while (prev?.type === 'attribute_item')
|
||||
prev = prev.previousNamedSibling
|
||||
if (!prev || (prev.type !== 'line_comment' && prev.type !== 'block_comment'))
|
||||
return undefined
|
||||
const sentence = firstSentence(commentPlain(prev))
|
||||
return sentence || undefined
|
||||
}
|
||||
|
||||
function hint(text: string): Inline {
|
||||
return { text, role: 'hint' }
|
||||
}
|
||||
Reference in new issue
Block a user