You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在VS Code扩展的悬浮提示中添加重载滚动箭头?

实现VS Code悬停提示中的重载列表滚动箭头

VS Code原生Hover API仅支持静态Markdown内容,要实现类似主流语言扩展的重载切换箭头,需要通过自定义HTML交互内容结合信任配置来实现,以下是具体步骤:

1. 配置扩展权限

在扩展的package.json中添加配置项,允许悬停内容执行脚本:

"contributes": {
  "configuration": {
    "properties": {
      "your-extension-id.allowUnsafeHover": {
        "type": "boolean",
        "default": false,
        "description": "允许悬停提示中的自定义HTML与脚本,用于重载切换功能"
      }
    }
  }
}

2. 构建交互式Hover内容

在Hover Provider中,生成包含切换按钮的HTML内容,并启用VS Code的HTML支持与信任标记:

import * as vscode from 'vscode';

export function activate(context: vscode.ExtensionContext) {
  const hoverProvider = vscode.languages.registerHoverProvider('target-language', {
    async provideHover(doc: vscode.TextDocument, pos: vscode.Position): Promise<vscode.Hover | undefined> {
      // 替换为你的重载获取逻辑
      const overloads = await fetchMethodOverloads(doc, pos);
      if (!overloads || overloads.length <= 1) {
        return new vscode.Hover(new vscode.MarkdownString(overloads?.[0].markdown || ''));
      }

      // 构建带切换箭头的HTML结构
      const initialIndex = 0;
      const html = `
        <div style="display: flex; align-items: center; gap: 8px;">
          <button class="overload-btn" onclick="switchOverload(${initialIndex - 1})" style="padding: 4px 8px; border: none; border-radius: 4px; background: var(--vscode-button-background); color: var(--vscode-button-foreground); cursor: pointer;">←</button>
          <div id="overload-content" style="flex: 1;">${overloads[initialIndex].html}</div>
          <button class="overload-btn" onclick="switchOverload(${initialIndex + 1})" style="padding: 4px 8px; border: none; border-radius: 4px; background: var(--vscode-button-background); color: var(--vscode-button-foreground); cursor: pointer;">→</button>
          <span style="font-size: 12px; color: var(--vscode-descriptionForeground);">${initialIndex + 1}/${overloads.length}</span>
        </div>
        <script>
          let currentIdx = ${initialIndex};
          const overloadList = ${JSON.stringify(overloads.map(o => o.html))};
          const total = overloadList.length;

          function switchOverload(newIdx) {
            if (newIdx < 0 || newIdx >= total) return;
            currentIdx = newIdx;
            document.getElementById('overload-content').innerHTML = overloadList[currentIdx];
            // 更新按钮状态
            document.querySelectorAll('.overload-btn')[0].disabled = currentIdx === 0;
            document.querySelectorAll('.overload-btn')[1].disabled = currentIdx === total - 1;
            document.querySelector('span').textContent = \`\${currentIdx + 1}/\${total}\`;
          }

          // 初始化按钮禁用状态
          document.querySelectorAll('.overload-btn')[0].disabled = currentIdx === 0;
          document.querySelectorAll('.overload-btn')[1].disabled = currentIdx === total - 1;
        </script>
      `;

      const md = new vscode.MarkdownString(html);
      md.supportHtml = true;
      md.isTrusted = true; // 必须开启才能执行脚本
      
      return new vscode.Hover(md);
    }
  });

  context.subscriptions.push(hoverProvider);
}

// 模拟获取方法重载的函数,需替换为实际解析逻辑
async function fetchMethodOverloads(doc: vscode.TextDocument, pos: vscode.Position) {
  return [
    { markdown: `\`func calculate(a: int) -> int\``, html: `<code>func calculate(a: int) -> int</code>` },
    { markdown: `\`func calculate(a: float, b: float) -> float\``, html: `<code>func calculate(a: float, b: float) -> float</code>` },
    { markdown: `\`func calculate(values: [int]) -> int\``, html: `<code>func calculate(values: [int]) -> int</code>` }
  ];
}

3. 安全提示与适配

  • 由于启用了isTrusted,需在扩展文档中明确告知用户安全风险,建议仅在信任工作区开启对应配置。
  • 样式使用VS Code的主题CSS变量(如var(--vscode-button-background)),确保在不同主题下显示正常。

替代方案:复用快速选择框

若不想使用自定义HTML,可通过showQuickPick让用户选择重载,体验稍逊但无需处理脚本权限:

async function provideHover(doc: vscode.TextDocument, pos: vscode.Position) {
  const overloads = await fetchMethodOverloads(doc, pos);
  if (!overloads || overloads.length <= 1) {
    return new vscode.Hover(new vscode.MarkdownString(overloads?.[0].markdown || ''));
  }

  const selected = await vscode.window.showQuickPick(
    overloads.map((o, i) => ({ label: `${i+1}. ${o.markdown}`, detail: o.markdown })),
    { placeHolder: "选择方法重载" }
  );

  return selected ? new vscode.Hover(new vscode.MarkdownString(selected.detail)) : undefined;
}

内容的提问来源于stack exchange,提问作者FogyX

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 11:02:51