编辑器编辑和工作区编辑有什么差别?
结论
改当前打开的这一份编辑器内容,用 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 写文件,会和未保存缓冲区冲突。