跳到主要内容

编辑器编辑和工作区编辑有什么差别?

结论​

改当前打开的这一份编辑器内容,用 TextEditor.edit。要改多个文件,或者还要创建、重命名、删除文件,用 WorkspaceEdit 再 workspace.applyEdit。

展开​

editor.edit 的构造器只作用于这个 TextEditor 里的文本:

const editor = vscode.window.activeTextEditor;
if (!editor) {
return;
}
await editor.edit((builder) => {
builder.replace(editor.selection, "新文本");
});

它参与这次编辑的撤销栈,适合格式化选区、插入片段这种单缓冲区操作。编辑器没打开、或者文件不在当前标签里,就拿不到 TextEditor。

WorkspaceEdit 是一批跨资源的修改:

const edit = new vscode.WorkspaceEdit();
edit.replace(uri, range, "新文本");
edit.createFile(newUri, { ignoreIfExists: true });
edit.renameFile(oldUri, renamedUri);
const ok = await vscode.workspace.applyEdit(edit);

重构「重命名符号并改所有引用」、补 import、生成新文件,都走这条路径。即使用户没打开那个文件也可以改。

选择:

  • 单文件、必须是当前编辑器、要立刻看到光标位置:editor.edit。
  • 多文件、未打开文件、伴随文件操作:WorkspaceEdit。
  • 语言服务器返回的 WorkspaceEdit 直接交给 applyEdit,不要自己拆成多次 editor.edit,否则撤销会被拆碎,失败也不原子。

applyEdit 返回布尔。返回 false 表示没应用,要提示用户,不要假装成功。

容易讲错的点​

  • editor.edit 的回调必须同步填完 builder。在回调里 await 之后再改 builder 是无效的。
  • 两次互不相关的 applyEdit 不是一个撤销步骤。要一次撤销就放进同一个 WorkspaceEdit。
  • 只改内存文档却用磁盘 API 写文件,会和未保存缓冲区冲突。