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

VS Code扩展如何为decoration的before/after添加hoverMessage

VS Code扩展实现before装饰元素单独绑定hover效果方案

VS Code原生DecorationOptions的hoverMessage属性默认绑定到装饰覆盖的整个文本范围,不支持直接给before/after伪元素单独配置悬停提示,GitLens的同款效果是通过拆分装饰+零宽范围+自定义Hover提供者的组合方案实现的,具体实现步骤如下:

步骤1:拆分两组独立装饰

不要把图标和hover触发逻辑放在同一个装饰里,拆成两个完全独立的装饰配置:

  • 第一组为图标展示装饰:保留原有before图标配置,覆盖你需要标记的代码文本范围,不配置任何hoverMessage,负责在代码前渲染图标,鼠标悬停在代码上时不会触发任何提示。
  • 第二组为hover触发装饰:不配置任何渲染样式,将range设置为原装饰起始位置的零宽范围(即起止位置都是原range的startPos,不覆盖任何实际代码字符),用于定位before图标的悬停触发区域,存储需要展示的hover内容。

对应实现代码:

import * as vscode from 'vscode';

// 提前注册两个全局装饰类型,扩展停用时记得调用dispose()销毁
const codeIconDecorationType = vscode.window.createTextEditorDecorationType({
  before: {
    margin: '0 4px 0 0',
    height: vscode.workspace.getConfiguration('editor').get('fontSize')
  }
});
const hoverTriggerDecorationType = vscode.window.createTextEditorDecorationType({
  // 无任何渲染配置,完全透明不影响界面显示
});

// 模块级变量存储当前生效的触发装饰,兼容低版本VS Code
let activeHoverTriggers: vscode.DecorationOptions[] = [];

// 渲染装饰的逻辑
function renderDecorations(editor: vscode.TextEditor) {
  const iconDecorations: vscode.DecorationOptions[] = [];
  const triggerDecorations: vscode.DecorationOptions[] = [];

  // 遍历你所有需要加装饰的位置数据
  decorationList.forEach(item => {
    const { startPos, endPos, iconBase64, hoverContent } = item;
    // 图标装饰:覆盖代码范围,不带hover
    iconDecorations.push({
      range: new vscode.Range(startPos, endPos),
      renderOptions: {
        before: {
          contentIconPath: vscode.Uri.parse(iconBase64)
        }
      }
    });
    // 触发装饰:零宽范围,绑定hover内容
    triggerDecorations.push({
      range: new vscode.Range(startPos, startPos),
      hoverMessage: hoverContent
    });
  });

  // 给编辑器挂载两组装饰
  editor.setDecorations(codeIconDecorationType, iconDecorations);
  editor.setDecorations(hoverTriggerDecorationType, triggerDecorations);
  // 更新缓存的触发装饰列表
  activeHoverTriggers = triggerDecorations;
}

步骤2:注册Hover Provider响应触发

注册全局Hover提供者,判断当前鼠标悬停位置是否命中零宽触发装饰的位置,命中时返回对应hover内容即可:

vscode.languages.registerHoverProvider('*', {
  provideHover(document, position) {
    const activeEditor = vscode.window.activeTextEditor;
    if (!activeEditor || activeEditor.document !== document) return null;

    // 遍历缓存的触发装饰,判断是否命中
    for (const trigger of activeHoverTriggers) {
      // 零宽装饰的起止位置一致,匹配即命中图标悬停区域
      if (trigger.range.start.isEqual(position)) {
        return new vscode.Hover(trigger.hoverMessage);
      }
    }
    return null;
  }
});

效果说明

  • 鼠标悬停在before图标上时,刚好命中零宽范围的起始位置,会弹出配置的hover提示
  • 鼠标悬停在range覆盖的代码文本上时,不会命中零宽触发点,不会弹出任何提示,和GitLens的图标悬停效果完全一致
  • 若需要调整hover触发的热区大小,可适当调整零宽range的范围,比如设置为从startPos到startPos偏移1个字符的位置即可扩大触发区域

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 17:06:58