mirror of
https://github.com/rust-lang/rust-analyzer
synced 2025-01-12 21:28:51 +00:00
Merge #6465
6465: Support multiple file edits in AssistBuilder r=matklad a=Veykril Fixes #6459 Co-authored-by: Lukas Wirth <lukastw97@gmail.com>
This commit is contained in:
commit
2d3b0571bb
2 changed files with 34 additions and 14 deletions
|
@ -208,7 +208,7 @@ pub(crate) struct AssistBuilder {
|
||||||
edit: TextEditBuilder,
|
edit: TextEditBuilder,
|
||||||
file_id: FileId,
|
file_id: FileId,
|
||||||
is_snippet: bool,
|
is_snippet: bool,
|
||||||
change: SourceChange,
|
source_file_edits: Vec<SourceFileEdit>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AssistBuilder {
|
impl AssistBuilder {
|
||||||
|
@ -217,20 +217,27 @@ impl AssistBuilder {
|
||||||
edit: TextEdit::builder(),
|
edit: TextEdit::builder(),
|
||||||
file_id,
|
file_id,
|
||||||
is_snippet: false,
|
is_snippet: false,
|
||||||
change: SourceChange::default(),
|
source_file_edits: Vec::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn edit_file(&mut self, file_id: FileId) {
|
pub(crate) fn edit_file(&mut self, file_id: FileId) {
|
||||||
|
self.commit();
|
||||||
self.file_id = file_id;
|
self.file_id = file_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn commit(&mut self) {
|
fn commit(&mut self) {
|
||||||
let edit = mem::take(&mut self.edit).finish();
|
let edit = mem::take(&mut self.edit).finish();
|
||||||
if !edit.is_empty() {
|
if !edit.is_empty() {
|
||||||
let new_edit = SourceFileEdit { file_id: self.file_id, edit };
|
match self.source_file_edits.binary_search_by_key(&self.file_id, |edit| edit.file_id) {
|
||||||
assert!(!self.change.source_file_edits.iter().any(|it| it.file_id == new_edit.file_id));
|
Ok(idx) => self.source_file_edits[idx]
|
||||||
self.change.source_file_edits.push(new_edit);
|
.edit
|
||||||
|
.union(edit)
|
||||||
|
.expect("overlapping edits for same file"),
|
||||||
|
Err(idx) => self
|
||||||
|
.source_file_edits
|
||||||
|
.insert(idx, SourceFileEdit { file_id: self.file_id, edit }),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -277,10 +284,10 @@ impl AssistBuilder {
|
||||||
|
|
||||||
fn finish(mut self) -> SourceChange {
|
fn finish(mut self) -> SourceChange {
|
||||||
self.commit();
|
self.commit();
|
||||||
let mut change = mem::take(&mut self.change);
|
SourceChange {
|
||||||
if self.is_snippet {
|
source_file_edits: mem::take(&mut self.source_file_edits),
|
||||||
change.is_snippet = true;
|
file_system_edits: Default::default(),
|
||||||
|
is_snippet: self.is_snippet,
|
||||||
}
|
}
|
||||||
change
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,16 +3,29 @@ import * as vscode from 'vscode';
|
||||||
import { assert } from './util';
|
import { assert } from './util';
|
||||||
|
|
||||||
export async function applySnippetWorkspaceEdit(edit: vscode.WorkspaceEdit) {
|
export async function applySnippetWorkspaceEdit(edit: vscode.WorkspaceEdit) {
|
||||||
assert(edit.entries().length === 1, `bad ws edit: ${JSON.stringify(edit)}`);
|
if (edit.entries().length === 1) {
|
||||||
const [uri, edits] = edit.entries()[0];
|
const [uri, edits] = edit.entries()[0];
|
||||||
|
const editor = await editorFromUri(uri);
|
||||||
|
if (editor) await applySnippetTextEdits(editor, edits);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (const [uri, edits] of edit.entries()) {
|
||||||
|
const editor = await editorFromUri(uri);
|
||||||
|
if (editor) await editor.edit((builder) => {
|
||||||
|
for (const indel of edits) {
|
||||||
|
assert(!parseSnippet(indel.newText), `bad ws edit: snippet received with multiple edits: ${JSON.stringify(edit)}`);
|
||||||
|
builder.replace(indel.range, indel.newText);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function editorFromUri(uri: vscode.Uri): Promise<vscode.TextEditor | undefined> {
|
||||||
if (vscode.window.activeTextEditor?.document.uri !== uri) {
|
if (vscode.window.activeTextEditor?.document.uri !== uri) {
|
||||||
// `vscode.window.visibleTextEditors` only contains editors whose contents are being displayed
|
// `vscode.window.visibleTextEditors` only contains editors whose contents are being displayed
|
||||||
await vscode.window.showTextDocument(uri, {});
|
await vscode.window.showTextDocument(uri, {});
|
||||||
}
|
}
|
||||||
const editor = vscode.window.visibleTextEditors.find((it) => it.document.uri.toString() === uri.toString());
|
return vscode.window.visibleTextEditors.find((it) => it.document.uri.toString() === uri.toString());
|
||||||
if (!editor) return;
|
|
||||||
await applySnippetTextEdits(editor, edits);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function applySnippetTextEdits(editor: vscode.TextEditor, edits: vscode.TextEdit[]) {
|
export async function applySnippetTextEdits(editor: vscode.TextEditor, edits: vscode.TextEdit[]) {
|
||||||
|
|
Loading…
Reference in a new issue