aboutsummaryrefslogtreecommitdiff
path: root/crates/completion/src/item.rs
diff options
context:
space:
mode:
authorKirill Bulatov <[email protected]>2020-12-03 09:13:28 +0000
committerKirill Bulatov <[email protected]>2020-12-07 21:41:08 +0000
commitf6d2540df09bc0dcd8a748ec0ed7cb33ac76d9f2 (patch)
treea206df6f66f41a9f4840d3e19204d67a46831513 /crates/completion/src/item.rs
parent68a747efe048e8e92eedafaa27b0c0d2f317f04d (diff)
Simplify import edit calculation
Diffstat (limited to 'crates/completion/src/item.rs')
-rw-r--r--crates/completion/src/item.rs63
1 files changed, 37 insertions, 26 deletions
diff --git a/crates/completion/src/item.rs b/crates/completion/src/item.rs
index 775245b3b..4e56f28f3 100644
--- a/crates/completion/src/item.rs
+++ b/crates/completion/src/item.rs
@@ -68,7 +68,7 @@ pub struct CompletionItem {
68 ref_match: Option<(Mutability, CompletionScore)>, 68 ref_match: Option<(Mutability, CompletionScore)>,
69 69
70 /// The import data to add to completion's edits. 70 /// The import data to add to completion's edits.
71 import_to_add: Option<ImportToAdd>, 71 import_to_add: Option<ImportEdit>,
72} 72}
73 73
74// We use custom debug for CompletionItem to make snapshot tests more readable. 74// We use custom debug for CompletionItem to make snapshot tests more readable.
@@ -209,7 +209,7 @@ impl CompletionItem {
209 score: None, 209 score: None,
210 ref_match: None, 210 ref_match: None,
211 import_to_add: None, 211 import_to_add: None,
212 resolve_import_immediately: true, 212 resolve_import_lazily: false,
213 } 213 }
214 } 214 }
215 215
@@ -262,27 +262,46 @@ impl CompletionItem {
262 self.ref_match 262 self.ref_match
263 } 263 }
264 264
265 pub fn import_to_add(&self) -> Option<&ImportToAdd> { 265 pub fn import_to_add(&self) -> Option<&ImportEdit> {
266 self.import_to_add.as_ref() 266 self.import_to_add.as_ref()
267 } 267 }
268} 268}
269 269
270/// An extra import to add after the completion is applied. 270/// An extra import to add after the completion is applied.
271#[derive(Debug, Clone)] 271#[derive(Debug, Clone)]
272pub struct ImportToAdd { 272pub struct ImportEdit {
273 pub import_path: ModPath, 273 pub import_path: ModPath,
274 pub import_scope: ImportScope, 274 pub import_scope: ImportScope,
275 pub merge_behaviour: Option<MergeBehaviour>, 275 pub merge_behaviour: Option<MergeBehaviour>,
276} 276}
277 277
278impl ImportEdit {
279 /// Attempts to insert the import to the given scope, producing a text edit.
280 /// May return no edit in edge cases, such as scope already containing the import.
281 pub fn to_text_edit(&self) -> Option<TextEdit> {
282 let _p = profile::span("ImportEdit::to_edit");
283
284 let rewriter = insert_use::insert_use(
285 &self.import_scope,
286 mod_path_to_ast(&self.import_path),
287 self.merge_behaviour,
288 );
289 let old_ast = rewriter.rewrite_root()?;
290 let mut import_insert = TextEdit::builder();
291 algo::diff(&old_ast, &rewriter.rewrite(&old_ast)).into_text_edit(&mut import_insert);
292
293 Some(import_insert.finish())
294 }
295}
296
278/// A helper to make `CompletionItem`s. 297/// A helper to make `CompletionItem`s.
279#[must_use] 298#[must_use]
280#[derive(Clone)] 299#[derive(Clone)]
281pub(crate) struct Builder { 300pub(crate) struct Builder {
282 source_range: TextRange, 301 source_range: TextRange,
283 completion_kind: CompletionKind, 302 completion_kind: CompletionKind,
284 import_to_add: Option<ImportToAdd>, 303 import_to_add: Option<ImportEdit>,
285 resolve_import_immediately: bool, 304 resolve_import_lazily: bool,
286 label: String, 305 label: String,
287 insert_text: Option<String>, 306 insert_text: Option<String>,
288 insert_text_format: InsertTextFormat, 307 insert_text_format: InsertTextFormat,
@@ -304,7 +323,6 @@ impl Builder {
304 let mut label = self.label; 323 let mut label = self.label;
305 let mut lookup = self.lookup; 324 let mut lookup = self.lookup;
306 let mut insert_text = self.insert_text; 325 let mut insert_text = self.insert_text;
307 let mut text_edits = TextEdit::builder();
308 326
309 if let Some(import_to_add) = self.import_to_add.as_ref() { 327 if let Some(import_to_add) = self.import_to_add.as_ref() {
310 let mut import_path_without_last_segment = import_to_add.import_path.to_owned(); 328 let mut import_path_without_last_segment = import_to_add.import_path.to_owned();
@@ -319,35 +337,28 @@ impl Builder {
319 } 337 }
320 label = format!("{}::{}", import_path_without_last_segment, label); 338 label = format!("{}::{}", import_path_without_last_segment, label);
321 } 339 }
322
323 if self.resolve_import_immediately {
324 let rewriter = insert_use::insert_use(
325 &import_to_add.import_scope,
326 mod_path_to_ast(&import_to_add.import_path),
327 import_to_add.merge_behaviour,
328 );
329 if let Some(old_ast) = rewriter.rewrite_root() {
330 algo::diff(&old_ast, &rewriter.rewrite(&old_ast))
331 .into_text_edit(&mut text_edits);
332 }
333 }
334 } 340 }
335 341
336 let original_edit = match self.text_edit { 342 let mut text_edit = match self.text_edit {
337 Some(it) => it, 343 Some(it) => it,
338 None => { 344 None => {
339 TextEdit::replace(self.source_range, insert_text.unwrap_or_else(|| label.clone())) 345 TextEdit::replace(self.source_range, insert_text.unwrap_or_else(|| label.clone()))
340 } 346 }
341 }; 347 };
342 348
343 let mut resulting_edit = text_edits.finish(); 349 if !self.resolve_import_lazily {
344 resulting_edit.union(original_edit).expect("Failed to unite text edits"); 350 if let Some(import_edit) =
351 self.import_to_add.as_ref().and_then(|import_edit| import_edit.to_text_edit())
352 {
353 text_edit.union(import_edit).expect("Failed to unite import and completion edits");
354 }
355 }
345 356
346 CompletionItem { 357 CompletionItem {
347 source_range: self.source_range, 358 source_range: self.source_range,
348 label, 359 label,
349 insert_text_format: self.insert_text_format, 360 insert_text_format: self.insert_text_format,
350 text_edit: resulting_edit, 361 text_edit,
351 detail: self.detail, 362 detail: self.detail,
352 documentation: self.documentation, 363 documentation: self.documentation,
353 lookup, 364 lookup,
@@ -422,11 +433,11 @@ impl Builder {
422 } 433 }
423 pub(crate) fn add_import( 434 pub(crate) fn add_import(
424 mut self, 435 mut self,
425 import_to_add: Option<ImportToAdd>, 436 import_to_add: Option<ImportEdit>,
426 resolve_import_immediately: bool, 437 resolve_import_lazily: bool,
427 ) -> Builder { 438 ) -> Builder {
428 self.import_to_add = import_to_add; 439 self.import_to_add = import_to_add;
429 self.resolve_import_immediately = resolve_import_immediately; 440 self.resolve_import_lazily = resolve_import_lazily;
430 self 441 self
431 } 442 }
432 pub(crate) fn set_ref_match( 443 pub(crate) fn set_ref_match(