aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2020-11-09 11:54:42 +0000
committerGitHub <[email protected]>2020-11-09 11:54:42 +0000
commit2d3b0571bb02aa85e3aae390e5cfb10b0ada5c38 (patch)
tree8aebf9a517eef712cc704cd983677183be898010
parent2f247140817c9cbd9009085c9f9ccedb4f6a718f (diff)
parentbe00b6b8fa03f9b578ca5f736e745d4d99ffd649 (diff)
Merge #6465
6465: Support multiple file edits in AssistBuilder r=matklad a=Veykril Fixes #6459 Co-authored-by: Lukas Wirth <[email protected]>
-rw-r--r--crates/assists/src/assist_context.rs25
-rw-r--r--editors/code/src/snippets.ts23
2 files changed, 34 insertions, 14 deletions
diff --git a/crates/assists/src/assist_context.rs b/crates/assists/src/assist_context.rs
index 51a160f40..a17e592b0 100644
--- a/crates/assists/src/assist_context.rs
+++ b/crates/assists/src/assist_context.rs
@@ -208,7 +208,7 @@ pub(crate) struct AssistBuilder {
208 edit: TextEditBuilder, 208 edit: TextEditBuilder,
209 file_id: FileId, 209 file_id: FileId,
210 is_snippet: bool, 210 is_snippet: bool,
211 change: SourceChange, 211 source_file_edits: Vec<SourceFileEdit>,
212} 212}
213 213
214impl AssistBuilder { 214impl AssistBuilder {
@@ -217,20 +217,27 @@ impl AssistBuilder {
217 edit: TextEdit::builder(), 217 edit: TextEdit::builder(),
218 file_id, 218 file_id,
219 is_snippet: false, 219 is_snippet: false,
220 change: SourceChange::default(), 220 source_file_edits: Vec::default(),
221 } 221 }
222 } 222 }
223 223
224 pub(crate) fn edit_file(&mut self, file_id: FileId) { 224 pub(crate) fn edit_file(&mut self, file_id: FileId) {
225 self.commit();
225 self.file_id = file_id; 226 self.file_id = file_id;
226 } 227 }
227 228
228 fn commit(&mut self) { 229 fn commit(&mut self) {
229 let edit = mem::take(&mut self.edit).finish(); 230 let edit = mem::take(&mut self.edit).finish();
230 if !edit.is_empty() { 231 if !edit.is_empty() {
231 let new_edit = SourceFileEdit { file_id: self.file_id, edit }; 232 match self.source_file_edits.binary_search_by_key(&self.file_id, |edit| edit.file_id) {
232 assert!(!self.change.source_file_edits.iter().any(|it| it.file_id == new_edit.file_id)); 233 Ok(idx) => self.source_file_edits[idx]
233 self.change.source_file_edits.push(new_edit); 234 .edit
235 .union(edit)
236 .expect("overlapping edits for same file"),
237 Err(idx) => self
238 .source_file_edits
239 .insert(idx, SourceFileEdit { file_id: self.file_id, edit }),
240 }
234 } 241 }
235 } 242 }
236 243
@@ -277,10 +284,10 @@ impl AssistBuilder {
277 284
278 fn finish(mut self) -> SourceChange { 285 fn finish(mut self) -> SourceChange {
279 self.commit(); 286 self.commit();
280 let mut change = mem::take(&mut self.change); 287 SourceChange {
281 if self.is_snippet { 288 source_file_edits: mem::take(&mut self.source_file_edits),
282 change.is_snippet = true; 289 file_system_edits: Default::default(),
290 is_snippet: self.is_snippet,
283 } 291 }
284 change
285 } 292 }
286} 293}
diff --git a/editors/code/src/snippets.ts b/editors/code/src/snippets.ts
index 258b49982..fee736e7d 100644
--- a/editors/code/src/snippets.ts
+++ b/editors/code/src/snippets.ts
@@ -3,16 +3,29 @@ import * as vscode from 'vscode';
3import { assert } from './util'; 3import { assert } from './util';
4 4
5export async function applySnippetWorkspaceEdit(edit: vscode.WorkspaceEdit) { 5export async function applySnippetWorkspaceEdit(edit: vscode.WorkspaceEdit) {
6 assert(edit.entries().length === 1, `bad ws edit: ${JSON.stringify(edit)}`); 6 if (edit.entries().length === 1) {
7 const [uri, edits] = edit.entries()[0]; 7 const [uri, edits] = edit.entries()[0];
8 const editor = await editorFromUri(uri);
9 if (editor) await applySnippetTextEdits(editor, edits);
10 return;
11 }
12 for (const [uri, edits] of edit.entries()) {
13 const editor = await editorFromUri(uri);
14 if (editor) await editor.edit((builder) => {
15 for (const indel of edits) {
16 assert(!parseSnippet(indel.newText), `bad ws edit: snippet received with multiple edits: ${JSON.stringify(edit)}`);
17 builder.replace(indel.range, indel.newText);
18 }
19 });
20 }
21}
8 22
23async function editorFromUri(uri: vscode.Uri): Promise<vscode.TextEditor | undefined> {
9 if (vscode.window.activeTextEditor?.document.uri !== uri) { 24 if (vscode.window.activeTextEditor?.document.uri !== uri) {
10 // `vscode.window.visibleTextEditors` only contains editors whose contents are being displayed 25 // `vscode.window.visibleTextEditors` only contains editors whose contents are being displayed
11 await vscode.window.showTextDocument(uri, {}); 26 await vscode.window.showTextDocument(uri, {});
12 } 27 }
13 const editor = vscode.window.visibleTextEditors.find((it) => it.document.uri.toString() === uri.toString()); 28 return vscode.window.visibleTextEditors.find((it) => it.document.uri.toString() === uri.toString());
14 if (!editor) return;
15 await applySnippetTextEdits(editor, edits);
16} 29}
17 30
18export async function applySnippetTextEdits(editor: vscode.TextEditor, edits: vscode.TextEdit[]) { 31export async function applySnippetTextEdits(editor: vscode.TextEditor, edits: vscode.TextEdit[]) {