const vscode = require('vscode'); const { relations } = require('./graph.cjs'); const { uri } = require('./inspection.cjs'); function command(name, args) { return `command:${name}?${encodeURIComponent(JSON.stringify(args))}`; } async function description(inspection, index, symbol, root) { const value = index.documentation.find(item => item.symbol === symbol.name); if (!value) return undefined; const documentIndex = { files: [index.documentation_files[value.file]] }; await inspection.verify(documentIndex, 0, root); return { ...value, uri: uri(documentIndex, 0, root) }; } function registerHover(context, selector, inspection, lookup) { context.subscriptions.push(vscode.languages.registerHoverProvider(selector, { async provideHover(document, position) { const state = await lookup(document, position); if (!state?.symbols.length) return undefined; const contents = []; for (const symbol of state.symbols) { const page = new vscode.MarkdownString(); page.isTrusted = { enabledCommands: ['dever.showCalls', 'dever.openDomainLinks', 'dever.previewDocumentation'] }; page.appendMarkdown(`**${symbol.name}**\n\n`); if (state.index.documentation_errors.length) { page.appendMarkdown('**说明校验未通过。** 失效或重复的标题详见“Dever”输出;签名和调用关系仍来自源码。\n\n'); } for (const signature of symbol.signatures) page.appendCodeblock(signature, 'dever'); const detail = await description(inspection, state.index, symbol, state.root); if (detail) { page.baseUri = detail.uri; page.appendMarkdown(`${detail.markdown}\n\n`); } else { page.appendMarkdown('尚未提供领域说明;签名和关系来自已保存源码。\n\n'); } for (const incoming of [true, false]) { const related = relations(state.index, symbol.id, incoming); const label = incoming ? '调用方' : '调用目标'; const names = related.slice(0, 4).map(item => `\`${item.symbol.name}\``).join('、'); page.appendMarkdown(`${label}:${names || '当前静态索引中无记录'}${related.length > 4 ? `,共 ${related.length} 个` : ''}。\n\n`); } const links = []; for (const site of symbol.declarations.slice(0, 1)) { const target = uri(state.index, site.file, state.root).with({ fragment: `L${site.start.line + 1},${site.start.character + 1}` }); links.push(`[源码](${target.toString()})`); } if (detail) links.push(`[说明](${command('dever.previewDocumentation', [state.root, symbol.name])})`); links.push(`[调用详情](${command('dever.showCalls', [state.root, symbol.name])})`); links.push(`[领域流程](${command('dever.openDomainLinks', [state.root, symbol.name])})`); page.appendMarkdown(links.join(' · ')); contents.push(page); } return new vscode.Hover(contents); } })); } module.exports = { registerHover, description, command };