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

VS Code扩展开发:程序化获取指定语言活动代码片段及空白位置

解决方案

一、获取当前语言的所有活动代码片段

要覆盖用户自定义、内置及扩展提供的全部代码片段,可通过以下方式实现:

  1. 收集扩展提供的代码片段
    遍历所有已激活扩展,提取其package.json中contributes.snippets字段里对应当前语言的片段:
async function getExtensionSnippets(langId: string): Promise<string[]> {
  const snippetNames: string[] = [];
  for (const ext of vscode.extensions.all) {
    const pkg = ext.packageJSON;
    if (pkg.contributes?.snippets) {
      for (const snippetDef of pkg.contributes.snippets) {
        if (snippetDef.language === langId && snippetDef.path) {
          const snippetPath = ext.asAbsolutePath(snippetDef.path);
          const snippetContent = await vscode.workspace.fs.readFile(vscode.Uri.file(snippetPath));
          const snippets = JSON.parse(Buffer.from(snippetContent).toString());
          snippetNames.push(...Object.keys(snippets));
        }
      }
    }
  }
  return snippetNames;
}
  1. 收集用户自定义代码片段
    通过工作区配置获取用户针对当前语言的自定义片段:
function getUserSnippets(langId: string): string[] {
  const snippetConfig = vscode.workspace.getConfiguration('editor.snippets', vscode.Uri.parse(`file:///dummy.${langId}`));
  const userSnippets = snippetConfig.get<Record<string, any>>(langId) || {};
  return Object.keys(userSnippets);
}
  1. 合并去重验证
    将上述两部分结果合并去重,得到当前语言的完整代码片段名称列表,即可用来校验用户输入的<SNIPPET_NAME>是否合法。

另外,还可以通过触发临时补全请求获取实时片段列表(更适配动态注册的片段):

async function getSnippetsViaCompletion(document: vscode.TextDocument): Promise<string[]> {
  const validPosition = await getValidSnippetPosition(document);
  if (!validPosition) return [];
  
  const completions = await vscode.languages.getCompletionItems(document, validPosition);
  return completions
    .filter(item => item.kind === vscode.CompletionItemKind.Snippet)
    .map(item => item.label.toString());
}

二、获取语言无关的可触发片段提示的空白位置

要找到能触发所有代码片段提示的合法位置,需避开注释和字符串区域,步骤如下:

  1. 遍历文档寻找合法位置
    通过语法分词判断每行token类型,找到第一个非注释、非字符串的空白位置:
async function getValidSnippetPosition(document: vscode.TextDocument): Promise<vscode.Position | undefined> {
  for (let line = 0; line < document.lineCount; line++) {
    const lineText = document.lineAt(line).text;
    if (lineText.trim() === '') {
      const tokens = await vscode.languages.tokenize(document.getText(new vscode.Range(line, 0, line, 1)), document.languageId);
      const tokenType = tokens[0]?.type;
      if (!tokenType?.includes('comment') && !tokenType?.includes('string')) {
        return new vscode.Position(line, 0);
      }
    } else {
      const firstNonWhitespace = lineText.search(/\S/);
      if (firstNonWhitespace > 0) {
        const tokens = await vscode.languages.tokenize(document.getText(new vscode.Range(line, 0, line, firstNonWhitespace)), document.languageId);
        const tokenType = tokens[0]?.type;
        if (!tokenType?.includes('comment') && !tokenType?.includes('string')) {
          return new vscode.Position(line, 0);
        }
      }
    }
  }
  //  fallback:返回文档开头
  return new vscode.Position(0, 0);
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 20:03:11