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

VSCode语言服务端/客户端:如何前置格式化内嵌补全结果?

解决VS Code Inline补全幽灵文本预格式化问题

要在inline补全显示为幽灵文本前完成格式化,无需创建可见的临时编辑器,直接利用VS Code的executeFormatRangeProviderAPI对内存中的临时文档处理即可,具体实现如下:

改进的格式化函数

export async function prettifyInlineCompletion(
  originalDoc: vscode.TextDocument,
  position: vscode.Position,
  completionText: string
): Promise<string> {
  // 1. 构建包含补全内容的临时文档:原文档到补全位置的内容 + 补全文本
  const originalText = originalDoc.getText();
  const textBeforeCompletion = originalText.substring(0, originalDoc.offsetAt(position));
  const tempDocContent = textBeforeCompletion + completionText;
  
  // 2. 创建内存临时文档,不会显示给用户
  const tempDoc = await vscode.workspace.openTextDocument({
    content: tempDocContent,
    language: originalDoc.languageId
  });
  
  // 3. 计算补全文本在临时文档中的范围
  const completionStartOffset = textBeforeCompletion.length;
  const completionEndOffset = completionStartOffset + completionText.length;
  const completionRange = new vscode.Range(
    tempDoc.positionAt(completionStartOffset),
    tempDoc.positionAt(completionEndOffset)
  );
  
  // 4. 调用格式化提供者执行格式化
  const formatEdits = await vscode.commands.executeCommand<vscode.TextEdit[]>(
    'vscode.executeFormatRangeProvider',
    tempDoc.uri,
    completionRange,
    originalDoc.options // 复用原文档的格式化配置
  );
  
  if (!formatEdits || formatEdits.length === 0) {
    return completionText; // 无格式化操作则返回原文本
  }
  
  // 5. 逆序应用编辑操作,避免偏移量错乱
  let formattedContent = tempDocContent;
  formatEdits.sort((a, b) => b.range.start.compareTo(a.range.start));
  for (const edit of formatEdits) {
    const startOffset = tempDoc.offsetAt(edit.range.start);
    const endOffset = tempDoc.offsetAt(edit.range.end);
    formattedContent = formattedContent.substring(0, startOffset) + edit.newText + formattedContent.substring(endOffset);
  }
  
  // 提取格式化后的补全文本
  const formattedCompletion = formattedContent.substring(completionStartOffset);
  return formattedCompletion;
}

在Inline补全中间件中集成

修改provideInlineCompletionItems中间件,对每个补全项应用格式化:

async provideInlineCompletionItems(
  document: vscode.TextDocument,
  position: vscode.Position,
  context: vscode.InlineCompletionContext,
  token: vscode.CancellationToken,
  next: ProvideInlineCompletionItemsSignature,
) {
  const result = await next(document, position, context, token);
  if (!result || token.isCancellationRequested) {
    return result;
  }
  
  // 处理单个补全项或补全列表
  const processCompletion = async (item: vscode.InlineCompletionItem) => {
    if (typeof item.insertText === 'string') {
      const formattedText = await prettifyInlineCompletion(document, position, item.insertText);
      return { ...item, insertText: formattedText };
    }
    return item; // 如需支持SnippetString可扩展此处逻辑
  };
  
  let prettifiedResult: vscode.InlineCompletionItem[] | vscode.InlineCompletionList | undefined;
  if (Array.isArray(result)) {
    prettifiedResult = await Promise.all(result.map(processCompletion));
  } else if (result instanceof vscode.InlineCompletionList) {
    prettifiedResult = new vscode.InlineCompletionList(
      await Promise.all(result.items.map(processCompletion)),
      result.incomplete
    );
  }
  
  return prettifiedResult;
}

核心优势

  • 无临时标签页:内存文档不会在编辑器中显示,完全后台处理
  • 配置一致性:复用原文档的格式化选项,和用户当前编辑环境保持一致
  • 上下文兼容:临时文档包含补全位置前的原内容,保证格式化工具能识别正确的语法结构(如缩进、代码块)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 05:40:40