diff options
Diffstat (limited to 'crates/completion/src/item.rs')
-rw-r--r-- | crates/completion/src/item.rs | 76 |
1 files changed, 47 insertions, 29 deletions
diff --git a/crates/completion/src/item.rs b/crates/completion/src/item.rs index 24b9d036a..b13c3f376 100644 --- a/crates/completion/src/item.rs +++ b/crates/completion/src/item.rs | |||
@@ -2,8 +2,9 @@ | |||
2 | 2 | ||
3 | use std::fmt; | 3 | use std::fmt; |
4 | 4 | ||
5 | use hir::{Documentation, Mutability}; | 5 | use assists::utils::{insert_use, mod_path_to_ast, ImportScope, MergeBehaviour}; |
6 | use syntax::TextRange; | 6 | use hir::{Documentation, ModPath, Mutability}; |
7 | use syntax::{algo, TextRange}; | ||
7 | use text_edit::TextEdit; | 8 | use text_edit::TextEdit; |
8 | 9 | ||
9 | use crate::config::SnippetCap; | 10 | use crate::config::SnippetCap; |
@@ -200,25 +201,7 @@ impl CompletionItem { | |||
200 | trigger_call_info: None, | 201 | trigger_call_info: None, |
201 | score: None, | 202 | score: None, |
202 | ref_match: None, | 203 | ref_match: None, |
203 | } | 204 | import_data: None, |
204 | } | ||
205 | |||
206 | pub(crate) fn into_builder(self) -> Builder { | ||
207 | Builder { | ||
208 | source_range: self.source_range, | ||
209 | completion_kind: self.completion_kind, | ||
210 | label: self.label, | ||
211 | insert_text: None, | ||
212 | insert_text_format: self.insert_text_format, | ||
213 | detail: self.detail, | ||
214 | documentation: self.documentation, | ||
215 | lookup: self.lookup, | ||
216 | kind: self.kind, | ||
217 | text_edit: Some(self.text_edit), | ||
218 | deprecated: Some(self.deprecated), | ||
219 | trigger_call_info: Some(self.trigger_call_info), | ||
220 | score: self.score, | ||
221 | ref_match: self.ref_match, | ||
222 | } | 205 | } |
223 | } | 206 | } |
224 | 207 | ||
@@ -278,6 +261,7 @@ impl CompletionItem { | |||
278 | pub(crate) struct Builder { | 261 | pub(crate) struct Builder { |
279 | source_range: TextRange, | 262 | source_range: TextRange, |
280 | completion_kind: CompletionKind, | 263 | completion_kind: CompletionKind, |
264 | import_data: Option<(ModPath, ImportScope, Option<MergeBehaviour>)>, | ||
281 | label: String, | 265 | label: String, |
282 | insert_text: Option<String>, | 266 | insert_text: Option<String>, |
283 | insert_text_format: InsertTextFormat, | 267 | insert_text_format: InsertTextFormat, |
@@ -294,23 +278,50 @@ pub(crate) struct Builder { | |||
294 | 278 | ||
295 | impl Builder { | 279 | impl Builder { |
296 | pub(crate) fn build(self) -> CompletionItem { | 280 | pub(crate) fn build(self) -> CompletionItem { |
297 | let label = self.label; | 281 | let mut label = self.label; |
298 | let text_edit = match self.text_edit { | 282 | let mut lookup = self.lookup; |
283 | let mut insert_text = self.insert_text; | ||
284 | let mut text_edits = TextEdit::builder(); | ||
285 | |||
286 | if let Some((import_path, import_scope, merge_behaviour)) = self.import_data { | ||
287 | let import = mod_path_to_ast(&import_path); | ||
288 | let mut import_path_without_last_segment = import_path; | ||
289 | let _ = import_path_without_last_segment.segments.pop(); | ||
290 | |||
291 | if !import_path_without_last_segment.segments.is_empty() { | ||
292 | if lookup.is_none() { | ||
293 | lookup = Some(label.clone()); | ||
294 | } | ||
295 | if insert_text.is_none() { | ||
296 | insert_text = Some(label.clone()); | ||
297 | } | ||
298 | label = format!("{}::{}", import_path_without_last_segment, label); | ||
299 | } | ||
300 | |||
301 | let rewriter = insert_use(&import_scope, import, merge_behaviour); | ||
302 | if let Some(old_ast) = rewriter.rewrite_root() { | ||
303 | algo::diff(&old_ast, &rewriter.rewrite(&old_ast)).into_text_edit(&mut text_edits); | ||
304 | } | ||
305 | } | ||
306 | |||
307 | let original_edit = match self.text_edit { | ||
299 | Some(it) => it, | 308 | Some(it) => it, |
300 | None => TextEdit::replace( | 309 | None => { |
301 | self.source_range, | 310 | TextEdit::replace(self.source_range, insert_text.unwrap_or_else(|| label.clone())) |
302 | self.insert_text.unwrap_or_else(|| label.clone()), | 311 | } |
303 | ), | ||
304 | }; | 312 | }; |
305 | 313 | ||
314 | let mut resulting_edit = text_edits.finish(); | ||
315 | resulting_edit.union(original_edit).expect("Failed to unite text edits"); | ||
316 | |||
306 | CompletionItem { | 317 | CompletionItem { |
307 | source_range: self.source_range, | 318 | source_range: self.source_range, |
308 | label, | 319 | label, |
309 | insert_text_format: self.insert_text_format, | 320 | insert_text_format: self.insert_text_format, |
310 | text_edit, | 321 | text_edit: resulting_edit, |
311 | detail: self.detail, | 322 | detail: self.detail, |
312 | documentation: self.documentation, | 323 | documentation: self.documentation, |
313 | lookup: self.lookup, | 324 | lookup, |
314 | kind: self.kind, | 325 | kind: self.kind, |
315 | completion_kind: self.completion_kind, | 326 | completion_kind: self.completion_kind, |
316 | deprecated: self.deprecated.unwrap_or(false), | 327 | deprecated: self.deprecated.unwrap_or(false), |
@@ -379,6 +390,13 @@ impl Builder { | |||
379 | self.trigger_call_info = Some(true); | 390 | self.trigger_call_info = Some(true); |
380 | self | 391 | self |
381 | } | 392 | } |
393 | pub(crate) fn import_data( | ||
394 | mut self, | ||
395 | import_data: Option<(ModPath, ImportScope, Option<MergeBehaviour>)>, | ||
396 | ) -> Builder { | ||
397 | self.import_data = import_data; | ||
398 | self | ||
399 | } | ||
382 | pub(crate) fn set_ref_match( | 400 | pub(crate) fn set_ref_match( |
383 | mut self, | 401 | mut self, |
384 | ref_match: Option<(Mutability, CompletionScore)>, | 402 | ref_match: Option<(Mutability, CompletionScore)>, |