diff options
Diffstat (limited to 'crates/ra_ide_api/src/completion/completion_item.rs')
-rw-r--r-- | crates/ra_ide_api/src/completion/completion_item.rs | 192 |
1 files changed, 2 insertions, 190 deletions
diff --git a/crates/ra_ide_api/src/completion/completion_item.rs b/crates/ra_ide_api/src/completion/completion_item.rs index 95bdd59b4..f515fcc14 100644 --- a/crates/ra_ide_api/src/completion/completion_item.rs +++ b/crates/ra_ide_api/src/completion/completion_item.rs | |||
@@ -1,16 +1,8 @@ | |||
1 | use std::fmt; | 1 | use std::fmt; |
2 | 2 | ||
3 | use hir::{Docs, Documentation, PerNs, Resolution}; | 3 | use hir::Documentation; |
4 | use ra_syntax::TextRange; | 4 | use ra_syntax::TextRange; |
5 | use ra_text_edit::{ TextEditBuilder, TextEdit}; | 5 | use ra_text_edit::{TextEditBuilder, TextEdit}; |
6 | use test_utils::tested_by; | ||
7 | |||
8 | use crate::completion::{ | ||
9 | completion_context::CompletionContext, | ||
10 | function_label, | ||
11 | const_label, | ||
12 | type_label | ||
13 | }; | ||
14 | 6 | ||
15 | /// `CompletionItem` describes a single completion variant in the editor pop-up. | 7 | /// `CompletionItem` describes a single completion variant in the editor pop-up. |
16 | /// It is basically a POD with various properties. To construct a | 8 | /// It is basically a POD with various properties. To construct a |
@@ -255,91 +247,6 @@ impl Builder { | |||
255 | self.documentation = docs.map(Into::into); | 247 | self.documentation = docs.map(Into::into); |
256 | self | 248 | self |
257 | } | 249 | } |
258 | pub(super) fn from_resolution( | ||
259 | mut self, | ||
260 | ctx: &CompletionContext, | ||
261 | resolution: &PerNs<Resolution>, | ||
262 | ) -> Builder { | ||
263 | use hir::ModuleDef::*; | ||
264 | |||
265 | let def = resolution.as_ref().take_types().or_else(|| resolution.as_ref().take_values()); | ||
266 | let def = match def { | ||
267 | None => return self, | ||
268 | Some(it) => it, | ||
269 | }; | ||
270 | let (kind, docs) = match def { | ||
271 | Resolution::Def(Module(it)) => (CompletionItemKind::Module, it.docs(ctx.db)), | ||
272 | Resolution::Def(Function(func)) => return self.from_function(ctx, *func), | ||
273 | Resolution::Def(Struct(it)) => (CompletionItemKind::Struct, it.docs(ctx.db)), | ||
274 | Resolution::Def(Enum(it)) => (CompletionItemKind::Enum, it.docs(ctx.db)), | ||
275 | Resolution::Def(EnumVariant(it)) => (CompletionItemKind::EnumVariant, it.docs(ctx.db)), | ||
276 | Resolution::Def(Const(it)) => (CompletionItemKind::Const, it.docs(ctx.db)), | ||
277 | Resolution::Def(Static(it)) => (CompletionItemKind::Static, it.docs(ctx.db)), | ||
278 | Resolution::Def(Trait(it)) => (CompletionItemKind::Trait, it.docs(ctx.db)), | ||
279 | Resolution::Def(Type(it)) => (CompletionItemKind::TypeAlias, it.docs(ctx.db)), | ||
280 | Resolution::GenericParam(..) => (CompletionItemKind::TypeParam, None), | ||
281 | Resolution::LocalBinding(..) => (CompletionItemKind::Binding, None), | ||
282 | Resolution::SelfType(..) => ( | ||
283 | CompletionItemKind::TypeParam, // (does this need its own kind?) | ||
284 | None, | ||
285 | ), | ||
286 | }; | ||
287 | self.kind = Some(kind); | ||
288 | self.documentation = docs; | ||
289 | |||
290 | self | ||
291 | } | ||
292 | |||
293 | pub(super) fn from_function( | ||
294 | mut self, | ||
295 | ctx: &CompletionContext, | ||
296 | function: hir::Function, | ||
297 | ) -> Builder { | ||
298 | // If not an import, add parenthesis automatically. | ||
299 | if ctx.use_item_syntax.is_none() && !ctx.is_call { | ||
300 | tested_by!(inserts_parens_for_function_calls); | ||
301 | let sig = function.signature(ctx.db); | ||
302 | if sig.params().is_empty() || sig.has_self_param() && sig.params().len() == 1 { | ||
303 | self.insert_text = Some(format!("{}()$0", self.label)); | ||
304 | } else { | ||
305 | self.insert_text = Some(format!("{}($0)", self.label)); | ||
306 | } | ||
307 | self.insert_text_format = InsertTextFormat::Snippet; | ||
308 | } | ||
309 | |||
310 | if let Some(docs) = function.docs(ctx.db) { | ||
311 | self.documentation = Some(docs); | ||
312 | } | ||
313 | |||
314 | if let Some(label) = function_item_label(ctx, function) { | ||
315 | self.detail = Some(label); | ||
316 | } | ||
317 | |||
318 | self.kind = Some(CompletionItemKind::Function); | ||
319 | self | ||
320 | } | ||
321 | |||
322 | pub(super) fn from_const(mut self, ctx: &CompletionContext, ct: hir::Const) -> Builder { | ||
323 | if let Some(docs) = ct.docs(ctx.db) { | ||
324 | self.documentation = Some(docs); | ||
325 | } | ||
326 | |||
327 | self.detail = Some(const_item_label(ctx, ct)); | ||
328 | self.kind = Some(CompletionItemKind::Const); | ||
329 | |||
330 | self | ||
331 | } | ||
332 | |||
333 | pub(super) fn from_type(mut self, ctx: &CompletionContext, ty: hir::Type) -> Builder { | ||
334 | if let Some(docs) = ty.docs(ctx.db) { | ||
335 | self.documentation = Some(docs); | ||
336 | } | ||
337 | |||
338 | self.detail = Some(type_item_label(ctx, ty)); | ||
339 | self.kind = Some(CompletionItemKind::TypeAlias); | ||
340 | |||
341 | self | ||
342 | } | ||
343 | } | 250 | } |
344 | 251 | ||
345 | impl<'a> Into<CompletionItem> for Builder { | 252 | impl<'a> Into<CompletionItem> for Builder { |
@@ -373,21 +280,6 @@ impl Into<Vec<CompletionItem>> for Completions { | |||
373 | } | 280 | } |
374 | } | 281 | } |
375 | 282 | ||
376 | fn function_item_label(ctx: &CompletionContext, function: hir::Function) -> Option<String> { | ||
377 | let node = function.source(ctx.db).1; | ||
378 | function_label(&node) | ||
379 | } | ||
380 | |||
381 | fn const_item_label(ctx: &CompletionContext, ct: hir::Const) -> String { | ||
382 | let node = ct.source(ctx.db).1; | ||
383 | const_label(&node) | ||
384 | } | ||
385 | |||
386 | fn type_item_label(ctx: &CompletionContext, ty: hir::Type) -> String { | ||
387 | let node = ty.source(ctx.db).1; | ||
388 | type_label(&node) | ||
389 | } | ||
390 | |||
391 | #[cfg(test)] | 283 | #[cfg(test)] |
392 | pub(crate) fn do_completion(code: &str, kind: CompletionKind) -> Vec<CompletionItem> { | 284 | pub(crate) fn do_completion(code: &str, kind: CompletionKind) -> Vec<CompletionItem> { |
393 | use crate::mock_analysis::{single_file_with_position, analysis_and_position}; | 285 | use crate::mock_analysis::{single_file_with_position, analysis_and_position}; |
@@ -411,83 +303,3 @@ pub(crate) fn check_completion(test_name: &str, code: &str, kind: CompletionKind | |||
411 | let kind_completions = do_completion(code, kind); | 303 | let kind_completions = do_completion(code, kind); |
412 | assert_debug_snapshot_matches!(test_name, kind_completions); | 304 | assert_debug_snapshot_matches!(test_name, kind_completions); |
413 | } | 305 | } |
414 | |||
415 | #[cfg(test)] | ||
416 | mod tests { | ||
417 | use test_utils::covers; | ||
418 | |||
419 | use super::*; | ||
420 | |||
421 | fn check_reference_completion(code: &str, expected_completions: &str) { | ||
422 | check_completion(code, expected_completions, CompletionKind::Reference); | ||
423 | } | ||
424 | |||
425 | #[test] | ||
426 | fn inserts_parens_for_function_calls() { | ||
427 | covers!(inserts_parens_for_function_calls); | ||
428 | check_reference_completion( | ||
429 | "inserts_parens_for_function_calls1", | ||
430 | r" | ||
431 | fn no_args() {} | ||
432 | fn main() { no_<|> } | ||
433 | ", | ||
434 | ); | ||
435 | check_reference_completion( | ||
436 | "inserts_parens_for_function_calls2", | ||
437 | r" | ||
438 | fn with_args(x: i32, y: String) {} | ||
439 | fn main() { with_<|> } | ||
440 | ", | ||
441 | ); | ||
442 | check_reference_completion( | ||
443 | "inserts_parens_for_function_calls3", | ||
444 | r" | ||
445 | struct S {} | ||
446 | impl S { | ||
447 | fn foo(&self) {} | ||
448 | } | ||
449 | fn bar(s: &S) { | ||
450 | s.f<|> | ||
451 | } | ||
452 | ", | ||
453 | ) | ||
454 | } | ||
455 | |||
456 | #[test] | ||
457 | fn dont_render_function_parens_in_use_item() { | ||
458 | check_reference_completion( | ||
459 | "dont_render_function_parens_in_use_item", | ||
460 | " | ||
461 | //- /lib.rs | ||
462 | mod m { pub fn foo() {} } | ||
463 | use crate::m::f<|>; | ||
464 | ", | ||
465 | ) | ||
466 | } | ||
467 | |||
468 | #[test] | ||
469 | fn dont_render_function_parens_if_already_call() { | ||
470 | check_reference_completion( | ||
471 | "dont_render_function_parens_if_already_call", | ||
472 | " | ||
473 | //- /lib.rs | ||
474 | fn frobnicate() {} | ||
475 | fn main() { | ||
476 | frob<|>(); | ||
477 | } | ||
478 | ", | ||
479 | ); | ||
480 | check_reference_completion( | ||
481 | "dont_render_function_parens_if_already_call_assoc_fn", | ||
482 | " | ||
483 | //- /lib.rs | ||
484 | struct Foo {} | ||
485 | impl Foo { fn new() -> Foo {} } | ||
486 | fn main() { | ||
487 | Foo::ne<|>(); | ||
488 | } | ||
489 | ", | ||
490 | ) | ||
491 | } | ||
492 | |||
493 | } | ||