aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_ide
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_ide')
-rw-r--r--crates/ra_ide/src/completion/complete_dot.rs984
-rw-r--r--crates/ra_ide/src/completion/complete_keyword.rs35
-rw-r--r--crates/ra_ide/src/completion/complete_qualified_path.rs39
-rw-r--r--crates/ra_ide/src/completion/presentation.rs69
4 files changed, 407 insertions, 720 deletions
diff --git a/crates/ra_ide/src/completion/complete_dot.rs b/crates/ra_ide/src/completion/complete_dot.rs
index 520652a37..667a8b949 100644
--- a/crates/ra_ide/src/completion/complete_dot.rs
+++ b/crates/ra_ide/src/completion/complete_dot.rs
@@ -2,16 +2,11 @@
2 2
3use hir::{HasVisibility, Type}; 3use hir::{HasVisibility, Type};
4use rustc_hash::FxHashSet; 4use rustc_hash::FxHashSet;
5use test_utils::mark;
5 6
6use crate::{ 7use crate::completion::{completion_context::CompletionContext, completion_item::Completions};
7 completion::{
8 completion_context::CompletionContext,
9 completion_item::{CompletionKind, Completions},
10 },
11 CompletionItem,
12};
13 8
14/// Complete dot accesses, i.e. fields or methods (and .await syntax). 9/// Complete dot accesses, i.e. fields or methods.
15pub(super) fn complete_dot(acc: &mut Completions, ctx: &CompletionContext) { 10pub(super) fn complete_dot(acc: &mut Completions, ctx: &CompletionContext) {
16 let dot_receiver = match &ctx.dot_receiver { 11 let dot_receiver = match &ctx.dot_receiver {
17 Some(expr) => expr, 12 Some(expr) => expr,
@@ -23,18 +18,12 @@ pub(super) fn complete_dot(acc: &mut Completions, ctx: &CompletionContext) {
23 _ => return, 18 _ => return,
24 }; 19 };
25 20
26 if !ctx.is_call { 21 if ctx.is_call {
22 mark::hit!(test_no_struct_field_completion_for_method_call);
23 } else {
27 complete_fields(acc, ctx, &receiver_ty); 24 complete_fields(acc, ctx, &receiver_ty);
28 } 25 }
29 complete_methods(acc, ctx, &receiver_ty); 26 complete_methods(acc, ctx, &receiver_ty);
30
31 // Suggest .await syntax for types that implement Future trait
32 if receiver_ty.impls_future(ctx.db) {
33 CompletionItem::new(CompletionKind::Keyword, ctx.source_range(), "await")
34 .detail("expr.await")
35 .insert_text("await")
36 .add_to(acc);
37 }
38} 27}
39 28
40fn complete_fields(acc: &mut Completions, ctx: &CompletionContext, receiver: &Type) { 29fn complete_fields(acc: &mut Completions, ctx: &CompletionContext, receiver: &Type) {
@@ -72,801 +61,356 @@ fn complete_methods(acc: &mut Completions, ctx: &CompletionContext, receiver: &T
72 61
73#[cfg(test)] 62#[cfg(test)]
74mod tests { 63mod tests {
75 use crate::completion::{test_utils::do_completion, CompletionItem, CompletionKind}; 64 use expect::{expect, Expect};
76 use insta::assert_debug_snapshot; 65 use test_utils::mark;
66
67 use crate::completion::{test_utils::completion_list, CompletionKind};
77 68
78 fn do_ref_completion(code: &str) -> Vec<CompletionItem> { 69 fn check(ra_fixture: &str, expect: Expect) {
79 do_completion(code, CompletionKind::Reference) 70 let actual = completion_list(ra_fixture, CompletionKind::Reference);
71 expect.assert_eq(&actual);
80 } 72 }
81 73
82 #[test] 74 #[test]
83 fn test_struct_field_completion() { 75 fn test_struct_field_and_method_completion() {
84 assert_debug_snapshot!( 76 check(
85 do_ref_completion( 77 r#"
86 r" 78struct S { foo: u32 }
87 struct A { the_field: u32 } 79impl S {
88 fn foo(a: A) { 80 fn bar(&self) {}
89 a.<|> 81}
90 } 82fn foo(s: S) { s.<|> }
91 ", 83"#,
92 ), 84 expect![[r#"
93 @r###" 85 me bar() fn bar(&self)
94 [ 86 fd foo u32
95 CompletionItem { 87 "#]],
96 label: "the_field",
97 source_range: 45..45,
98 delete: 45..45,
99 insert: "the_field",
100 kind: Field,
101 detail: "u32",
102 },
103 ]
104 "###
105 ); 88 );
106 } 89 }
107 90
108 #[test] 91 #[test]
109 fn test_struct_field_completion_self() { 92 fn test_struct_field_completion_self() {
110 assert_debug_snapshot!( 93 check(
111 do_ref_completion( 94 r#"
112 r" 95struct S { the_field: (u32,) }
113 struct A { 96impl S {
114 /// This is the_field 97 fn foo(self) { self.<|> }
115 the_field: (u32,) 98}
116 } 99"#,
117 impl A { 100 expect![[r#"
118 fn foo(self) { 101 me foo() fn foo(self)
119 self.<|> 102 fd the_field (u32,)
120 } 103 "#]],
121 } 104 )
122 ",
123 ),
124 @r###"
125 [
126 CompletionItem {
127 label: "foo()",
128 source_range: 102..102,
129 delete: 102..102,
130 insert: "foo()$0",
131 kind: Method,
132 lookup: "foo",
133 detail: "fn foo(self)",
134 },
135 CompletionItem {
136 label: "the_field",
137 source_range: 102..102,
138 delete: 102..102,
139 insert: "the_field",
140 kind: Field,
141 detail: "(u32,)",
142 documentation: Documentation(
143 "This is the_field",
144 ),
145 },
146 ]
147 "###
148 );
149 } 105 }
150 106
151 #[test] 107 #[test]
152 fn test_struct_field_completion_autoderef() { 108 fn test_struct_field_completion_autoderef() {
153 assert_debug_snapshot!( 109 check(
154 do_ref_completion( 110 r#"
155 r" 111struct A { the_field: (u32, i32) }
156 struct A { the_field: (u32, i32) } 112impl A {
157 impl A { 113 fn foo(&self) { self.<|> }
158 fn foo(&self) { 114}
159 self.<|> 115"#,
160 } 116 expect![[r#"
161 } 117 me foo() fn foo(&self)
162 ", 118 fd the_field (u32, i32)
163 ), 119 "#]],
164 @r###" 120 )
165 [
166 CompletionItem {
167 label: "foo()",
168 source_range: 77..77,
169 delete: 77..77,
170 insert: "foo()$0",
171 kind: Method,
172 lookup: "foo",
173 detail: "fn foo(&self)",
174 },
175 CompletionItem {
176 label: "the_field",
177 source_range: 77..77,
178 delete: 77..77,
179 insert: "the_field",
180 kind: Field,
181 detail: "(u32, i32)",
182 },
183 ]
184 "###
185 );
186 } 121 }
187 122
188 #[test] 123 #[test]
189 fn test_no_struct_field_completion_for_method_call() { 124 fn test_no_struct_field_completion_for_method_call() {
190 assert_debug_snapshot!( 125 mark::check!(test_no_struct_field_completion_for_method_call);
191 do_ref_completion( 126 check(
192 r" 127 r#"
193 struct A { the_field: u32 } 128struct A { the_field: u32 }
194 fn foo(a: A) { 129fn foo(a: A) { a.<|>() }
195 a.<|>() 130"#,
196 } 131 expect![[""]],
197 ",
198 ),
199 @"[]"
200 ); 132 );
201 } 133 }
202 134
203 #[test] 135 #[test]
204 fn test_struct_field_visibility_private() { 136 fn test_visibility_filtering() {
205 assert_debug_snapshot!( 137 check(
206 do_ref_completion( 138 r#"
207 r" 139mod inner {
208 mod inner { 140 pub struct A {
209 struct A { 141 private_field: u32,
210 private_field: u32, 142 pub pub_field: u32,
211 pub pub_field: u32, 143 pub(crate) crate_field: u32,
212 pub(crate) crate_field: u32, 144 pub(super) super_field: u32,
213 pub(super) super_field: u32,
214 }
215 }
216 fn foo(a: inner::A) {
217 a.<|>
218 }
219 ",
220 ),
221 @r###"
222 [
223 CompletionItem {
224 label: "crate_field",
225 source_range: 192..192,
226 delete: 192..192,
227 insert: "crate_field",
228 kind: Field,
229 detail: "u32",
230 },
231 CompletionItem {
232 label: "pub_field",
233 source_range: 192..192,
234 delete: 192..192,
235 insert: "pub_field",
236 kind: Field,
237 detail: "u32",
238 },
239 CompletionItem {
240 label: "super_field",
241 source_range: 192..192,
242 delete: 192..192,
243 insert: "super_field",
244 kind: Field,
245 detail: "u32",
246 },
247 ]
248 "###
249 );
250 } 145 }
251 146}
252 #[test] 147fn foo(a: inner::A) { a.<|> }
253 fn test_union_field_completion() { 148"#,
254 assert_debug_snapshot!( 149 expect![[r#"
255 do_ref_completion( 150 fd crate_field u32
256 r" 151 fd pub_field u32
257 union Un { 152 fd super_field u32
258 field: u8, 153 "#]],
259 other: u16,
260 }
261
262 fn foo(u: Un) {
263 u.<|>
264 }
265 ",
266 ),
267 @r###"
268 [
269 CompletionItem {
270 label: "field",
271 source_range: 67..67,
272 delete: 67..67,
273 insert: "field",
274 kind: Field,
275 detail: "u8",
276 },
277 CompletionItem {
278 label: "other",
279 source_range: 67..67,
280 delete: 67..67,
281 insert: "other",
282 kind: Field,
283 detail: "u16",
284 },
285 ]
286 "###
287 ); 154 );
288 }
289 155
290 #[test] 156 check(
291 fn test_method_completion() { 157 r#"
292 assert_debug_snapshot!( 158struct A {}
293 do_ref_completion( 159mod m {
294 r" 160 impl super::A {
295 struct A {} 161 fn private_method(&self) {}
296 impl A { 162 pub(super) fn the_method(&self) {}
297 fn the_method(&self) {} 163 }
298 } 164}
299 fn foo(a: A) { 165fn foo(a: A) { a.<|> }
300 a.<|> 166"#,
301 } 167 expect![[r#"
302 ", 168 me the_method() pub(super) fn the_method(&self)
303 ), 169 "#]],
304 @r###"
305 [
306 CompletionItem {
307 label: "the_method()",
308 source_range: 71..71,
309 delete: 71..71,
310 insert: "the_method()$0",
311 kind: Method,
312 lookup: "the_method",
313 detail: "fn the_method(&self)",
314 },
315 ]
316 "###
317 ); 170 );
318 } 171 }
319 172
320 #[test] 173 #[test]
321 fn test_method_completion_only_fitting_impls() { 174 fn test_union_field_completion() {
322 assert_debug_snapshot!( 175 check(
323 do_ref_completion( 176 r#"
324 r" 177union U { field: u8, other: u16 }
325 struct A<T> {} 178fn foo(u: U) { u.<|> }
326 impl A<u32> { 179"#,
327 fn the_method(&self) {} 180 expect![[r#"
328 } 181 fd field u8
329 impl A<i32> { 182 fd other u16
330 fn the_other_method(&self) {} 183 "#]],
331 }
332 fn foo(a: A<u32>) {
333 a.<|>
334 }
335 ",
336 ),
337 @r###"
338 [
339 CompletionItem {
340 label: "the_method()",
341 source_range: 134..134,
342 delete: 134..134,
343 insert: "the_method()$0",
344 kind: Method,
345 lookup: "the_method",
346 detail: "fn the_method(&self)",
347 },
348 ]
349 "###
350 ); 184 );
351 } 185 }
352 186
353 #[test] 187 #[test]
354 fn test_method_completion_private() { 188 fn test_method_completion_only_fitting_impls() {
355 assert_debug_snapshot!( 189 check(
356 do_ref_completion( 190 r#"
357 r" 191struct A<T> {}
358 struct A {} 192impl A<u32> {
359 mod m { 193 fn the_method(&self) {}
360 impl super::A { 194}
361 fn private_method(&self) {} 195impl A<i32> {
362 pub(super) fn the_method(&self) {} 196 fn the_other_method(&self) {}
363 } 197}
364 } 198fn foo(a: A<u32>) { a.<|> }
365 fn foo(a: A) { 199"#,
366 a.<|> 200 expect![[r#"
367 } 201 me the_method() fn the_method(&self)
368 ", 202 "#]],
369 ), 203 )
370 @r###"
371 [
372 CompletionItem {
373 label: "the_method()",
374 source_range: 147..147,
375 delete: 147..147,
376 insert: "the_method()$0",
377 kind: Method,
378 lookup: "the_method",
379 detail: "pub(super) fn the_method(&self)",
380 },
381 ]
382 "###
383 );
384 } 204 }
385 205
386 #[test] 206 #[test]
387 fn test_trait_method_completion() { 207 fn test_trait_method_completion() {
388 assert_debug_snapshot!( 208 check(
389 do_ref_completion( 209 r#"
390 r" 210struct A {}
391 struct A {} 211trait Trait { fn the_method(&self); }
392 trait Trait { fn the_method(&self); } 212impl Trait for A {}
393 impl Trait for A {} 213fn foo(a: A) { a.<|> }
394 fn foo(a: A) { 214"#,
395 a.<|> 215 expect![[r#"
396 } 216 me the_method() fn the_method(&self)
397 ", 217 "#]],
398 ),
399 @r###"
400 [
401 CompletionItem {
402 label: "the_method()",
403 source_range: 90..90,
404 delete: 90..90,
405 insert: "the_method()$0",
406 kind: Method,
407 lookup: "the_method",
408 detail: "fn the_method(&self)",
409 },
410 ]
411 "###
412 ); 218 );
413 } 219 }
414 220
415 #[test] 221 #[test]
416 fn test_trait_method_completion_deduplicated() { 222 fn test_trait_method_completion_deduplicated() {
417 assert_debug_snapshot!( 223 check(
418 do_ref_completion( 224 r"
419 r" 225struct A {}
420 struct A {} 226trait Trait { fn the_method(&self); }
421 trait Trait { fn the_method(&self); } 227impl<T> Trait for T {}
422 impl<T> Trait for T {} 228fn foo(a: &A) { a.<|> }
423 fn foo(a: &A) { 229",
424 a.<|> 230 expect![[r#"
425 } 231 me the_method() fn the_method(&self)
426 ", 232 "#]],
427 ),
428 @r###"
429 [
430 CompletionItem {
431 label: "the_method()",
432 source_range: 94..94,
433 delete: 94..94,
434 insert: "the_method()$0",
435 kind: Method,
436 lookup: "the_method",
437 detail: "fn the_method(&self)",
438 },
439 ]
440 "###
441 ); 233 );
442 } 234 }
443 235
444 #[test] 236 #[test]
445 fn completes_trait_method_from_other_module() { 237 fn completes_trait_method_from_other_module() {
446 assert_debug_snapshot!( 238 check(
447 do_ref_completion(
448 r"
449 struct A {}
450 mod m {
451 pub trait Trait { fn the_method(&self); }
452 }
453 use m::Trait;
454 impl Trait for A {}
455 fn foo(a: A) {
456 a.<|>
457 }
458 ",
459 ),
460 @r###"
461 [
462 CompletionItem {
463 label: "the_method()",
464 source_range: 122..122,
465 delete: 122..122,
466 insert: "the_method()$0",
467 kind: Method,
468 lookup: "the_method",
469 detail: "fn the_method(&self)",
470 },
471 ]
472 "###
473 );
474 }
475
476 #[test]
477 fn test_no_non_self_method() {
478 assert_debug_snapshot!(
479 do_ref_completion(
480 r" 239 r"
481 struct A {} 240struct A {}
482 impl A { 241mod m {
483 fn the_method() {} 242 pub trait Trait { fn the_method(&self); }
484 } 243}
485 fn foo(a: A) { 244use m::Trait;
486 a.<|> 245impl Trait for A {}
487 } 246fn foo(a: A) { a.<|> }
488 ", 247",
489 ), 248 expect![[r#"
490 @"[]" 249 me the_method() fn the_method(&self)
250 "#]],
491 ); 251 );
492 } 252 }
493 253
494 #[test] 254 #[test]
495 fn test_method_attr_filtering() { 255 fn test_no_non_self_method() {
496 assert_debug_snapshot!( 256 check(
497 do_ref_completion( 257 r#"
498 r" 258struct A {}
499 struct A {} 259impl A {
500 impl A { 260 fn the_method() {}
501 #[inline] 261}
502 fn the_method(&self) { 262fn foo(a: A) {
503 let x = 1; 263 a.<|>
504 let y = 2; 264}
505 } 265"#,
506 } 266 expect![[""]],
507 fn foo(a: A) {
508 a.<|>
509 }
510 ",
511 ),
512 @r###"
513 [
514 CompletionItem {
515 label: "the_method()",
516 source_range: 128..128,
517 delete: 128..128,
518 insert: "the_method()$0",
519 kind: Method,
520 lookup: "the_method",
521 detail: "fn the_method(&self)",
522 },
523 ]
524 "###
525 ); 267 );
526 } 268 }
527 269
528 #[test] 270 #[test]
529 fn test_tuple_field_completion() { 271 fn test_tuple_field_completion() {
530 assert_debug_snapshot!( 272 check(
531 do_ref_completion( 273 r#"
532 r" 274fn foo() {
533 fn foo() { 275 let b = (0, 3.14);
534 let b = (0, 3.14); 276 b.<|>
535 b.<|> 277}
536 } 278"#,
537 ", 279 expect![[r#"
538 ), 280 fd 0 i32
539 @r###" 281 fd 1 f64
540 [ 282 "#]],
541 CompletionItem { 283 )
542 label: "0",
543 source_range: 38..38,
544 delete: 38..38,
545 insert: "0",
546 kind: Field,
547 detail: "i32",
548 },
549 CompletionItem {
550 label: "1",
551 source_range: 38..38,
552 delete: 38..38,
553 insert: "1",
554 kind: Field,
555 detail: "f64",
556 },
557 ]
558 "###
559 );
560 } 284 }
561 285
562 #[test] 286 #[test]
563 fn test_tuple_field_inference() { 287 fn test_tuple_field_inference() {
564 assert_debug_snapshot!( 288 check(
565 do_ref_completion( 289 r#"
566 r" 290pub struct S;
567 pub struct S; 291impl S { pub fn blah(&self) {} }
568 impl S {
569 pub fn blah(&self) {}
570 }
571 292
572 struct T(S); 293struct T(S);
573 294
574 impl T { 295impl T {
575 fn foo(&self) { 296 fn foo(&self) {
576 // FIXME: This doesn't work without the trailing `a` as `0.` is a float 297 // FIXME: This doesn't work without the trailing `a` as `0.` is a float
577 self.0.a<|> 298 self.0.a<|>
578 }
579 }
580 ",
581 ),
582 @r###"
583 [
584 CompletionItem {
585 label: "blah()",
586 source_range: 190..191,
587 delete: 190..191,
588 insert: "blah()$0",
589 kind: Method,
590 lookup: "blah",
591 detail: "pub fn blah(&self)",
592 },
593 ]
594 "###
595 );
596 } 299 }
597 300}
598 #[test] 301"#,
599 fn test_completion_works_in_consts() { 302 expect![[r#"
600 assert_debug_snapshot!( 303 me blah() pub fn blah(&self)
601 do_ref_completion( 304 "#]],
602 r"
603 struct A { the_field: u32 }
604 const X: u32 = {
605 A { the_field: 92 }.<|>
606 };
607 ",
608 ),
609 @r###"
610 [
611 CompletionItem {
612 label: "the_field",
613 source_range: 69..69,
614 delete: 69..69,
615 insert: "the_field",
616 kind: Field,
617 detail: "u32",
618 },
619 ]
620 "###
621 ); 305 );
622 } 306 }
623 307
624 #[test] 308 #[test]
625 fn test_completion_await_impls_future() { 309 fn test_completion_works_in_consts() {
626 assert_debug_snapshot!( 310 check(
627 do_completion( 311 r#"
628 r###" 312struct A { the_field: u32 }
629 //- /main.rs 313const X: u32 = {
630 use std::future::*; 314 A { the_field: 92 }.<|>
631 struct A {} 315};
632 impl Future for A {} 316"#,
633 fn foo(a: A) { 317 expect![[r#"
634 a.<|> 318 fd the_field u32
635 } 319 "#]],
636
637 //- /std/lib.rs
638 pub mod future {
639 #[lang = "future_trait"]
640 pub trait Future {}
641 }
642 "###, CompletionKind::Keyword),
643 @r###"
644 [
645 CompletionItem {
646 label: "await",
647 source_range: 74..74,
648 delete: 74..74,
649 insert: "await",
650 detail: "expr.await",
651 },
652 ]
653 "###
654 )
655 }
656
657 #[test]
658 fn test_super_super_completion() {
659 assert_debug_snapshot!(
660 do_ref_completion(
661 r"
662 mod a {
663 const A: usize = 0;
664
665 mod b {
666 const B: usize = 0;
667
668 mod c {
669 use super::super::<|>
670 }
671 }
672 }
673 ",
674 ),
675 @r###"
676 [
677 CompletionItem {
678 label: "A",
679 source_range: 120..120,
680 delete: 120..120,
681 insert: "A",
682 kind: Const,
683 },
684 CompletionItem {
685 label: "b",
686 source_range: 120..120,
687 delete: 120..120,
688 insert: "b",
689 kind: Module,
690 },
691 ]
692 "###
693 ); 320 );
694 } 321 }
695 322
696 #[test] 323 #[test]
697 fn works_in_simple_macro_1() { 324 fn works_in_simple_macro_1() {
698 assert_debug_snapshot!( 325 check(
699 do_ref_completion( 326 r#"
700 r" 327macro_rules! m { ($e:expr) => { $e } }
701 macro_rules! m { ($e:expr) => { $e } } 328struct A { the_field: u32 }
702 struct A { the_field: u32 } 329fn foo(a: A) {
703 fn foo(a: A) { 330 m!(a.x<|>)
704 m!(a.x<|>) 331}
705 } 332"#,
706 ", 333 expect![[r#"
707 ), 334 fd the_field u32
708 @r###" 335 "#]],
709 [
710 CompletionItem {
711 label: "the_field",
712 source_range: 91..92,
713 delete: 91..92,
714 insert: "the_field",
715 kind: Field,
716 detail: "u32",
717 },
718 ]
719 "###
720 );
721 }
722
723 #[test]
724 fn works_in_simple_macro_recursive() {
725 assert_debug_snapshot!(
726 do_ref_completion(
727 r"
728 macro_rules! m { ($e:expr) => { $e } }
729 struct A { the_field: u32 }
730 fn foo(a: A) {
731 m!(a.x<|>)
732 }
733 ",
734 ),
735 @r###"
736 [
737 CompletionItem {
738 label: "the_field",
739 source_range: 91..92,
740 delete: 91..92,
741 insert: "the_field",
742 kind: Field,
743 detail: "u32",
744 },
745 ]
746 "###
747 ); 336 );
748 } 337 }
749 338
750 #[test] 339 #[test]
751 fn works_in_simple_macro_2() { 340 fn works_in_simple_macro_2() {
752 // this doesn't work yet because the macro doesn't expand without the token -- maybe it can be fixed with better recovery 341 // this doesn't work yet because the macro doesn't expand without the token -- maybe it can be fixed with better recovery
753 assert_debug_snapshot!( 342 check(
754 do_ref_completion( 343 r#"
755 r" 344macro_rules! m { ($e:expr) => { $e } }
756 macro_rules! m { ($e:expr) => { $e } } 345struct A { the_field: u32 }
757 struct A { the_field: u32 } 346fn foo(a: A) {
758 fn foo(a: A) { 347 m!(a.<|>)
759 m!(a.<|>) 348}
760 } 349"#,
761 ", 350 expect![[r#"
762 ), 351 fd the_field u32
763 @r###" 352 "#]],
764 [
765 CompletionItem {
766 label: "the_field",
767 source_range: 91..91,
768 delete: 91..91,
769 insert: "the_field",
770 kind: Field,
771 detail: "u32",
772 },
773 ]
774 "###
775 ); 353 );
776 } 354 }
777 355
778 #[test] 356 #[test]
779 fn works_in_simple_macro_recursive_1() { 357 fn works_in_simple_macro_recursive_1() {
780 assert_debug_snapshot!( 358 check(
781 do_ref_completion( 359 r#"
782 r" 360macro_rules! m { ($e:expr) => { $e } }
783 macro_rules! m { ($e:expr) => { $e } } 361struct A { the_field: u32 }
784 struct A { the_field: u32 } 362fn foo(a: A) {
785 fn foo(a: A) { 363 m!(m!(m!(a.x<|>)))
786 m!(m!(m!(a.x<|>))) 364}
787 } 365"#,
788 ", 366 expect![[r#"
789 ), 367 fd the_field u32
790 @r###" 368 "#]],
791 [
792 CompletionItem {
793 label: "the_field",
794 source_range: 97..98,
795 delete: 97..98,
796 insert: "the_field",
797 kind: Field,
798 detail: "u32",
799 },
800 ]
801 "###
802 ); 369 );
803 } 370 }
804 371
805 #[test] 372 #[test]
806 fn macro_expansion_resilient() { 373 fn macro_expansion_resilient() {
807 assert_debug_snapshot!( 374 check(
808 do_ref_completion( 375 r#"
809 r" 376macro_rules! dbg {
810 macro_rules! dbg { 377 () => {};
811 () => {}; 378 ($val:expr) => {
812 ($val:expr) => { 379 match $val { tmp => { tmp } }
813 match $val { tmp => { tmp } } 380 };
814 }; 381 // Trailing comma with single argument is ignored
815 // Trailing comma with single argument is ignored 382 ($val:expr,) => { $crate::dbg!($val) };
816 ($val:expr,) => { $crate::dbg!($val) }; 383 ($($val:expr),+ $(,)?) => {
817 ($($val:expr),+ $(,)?) => { 384 ($($crate::dbg!($val)),+,)
818 ($($crate::dbg!($val)),+,) 385 };
819 }; 386}
820 } 387struct A { the_field: u32 }
821 struct A { the_field: u32 } 388fn foo(a: A) {
822 fn foo(a: A) { 389 dbg!(a.<|>)
823 dbg!(a.<|>) 390}
824 } 391"#,
825 ", 392 expect![[r#"
826 ), 393 fd the_field u32
827 @r###" 394 "#]],
828 [
829 CompletionItem {
830 label: "the_field",
831 source_range: 327..327,
832 delete: 327..327,
833 insert: "the_field",
834 kind: Field,
835 detail: "u32",
836 },
837 ]
838 "###
839 ); 395 );
840 } 396 }
841 397
842 #[test] 398 #[test]
843 fn test_method_completion_3547() { 399 fn test_method_completion_issue_3547() {
844 assert_debug_snapshot!( 400 check(
845 do_ref_completion( 401 r#"
846 r" 402struct HashSet<T> {}
847 struct HashSet<T> {} 403impl<T> HashSet<T> {
848 impl<T> HashSet<T> { 404 pub fn the_method(&self) {}
849 pub fn the_method(&self) {} 405}
850 } 406fn foo() {
851 fn foo() { 407 let s: HashSet<_>;
852 let s: HashSet<_>; 408 s.<|>
853 s.<|> 409}
854 } 410"#,
855 ", 411 expect![[r#"
856 ), 412 me the_method() pub fn the_method(&self)
857 @r###" 413 "#]],
858 [
859 CompletionItem {
860 label: "the_method()",
861 source_range: 116..116,
862 delete: 116..116,
863 insert: "the_method()$0",
864 kind: Method,
865 lookup: "the_method",
866 detail: "pub fn the_method(&self)",
867 },
868 ]
869 "###
870 ); 414 );
871 } 415 }
872} 416}
diff --git a/crates/ra_ide/src/completion/complete_keyword.rs b/crates/ra_ide/src/completion/complete_keyword.rs
index 086b917ce..340d57a49 100644
--- a/crates/ra_ide/src/completion/complete_keyword.rs
+++ b/crates/ra_ide/src/completion/complete_keyword.rs
@@ -35,6 +35,19 @@ pub(super) fn complete_use_tree_keyword(acc: &mut Completions, ctx: &CompletionC
35 } 35 }
36 _ => {} 36 _ => {}
37 } 37 }
38
39 // Suggest .await syntax for types that implement Future trait
40 if let Some(receiver) = &ctx.dot_receiver {
41 if let Some(ty) = ctx.sema.type_of_expr(receiver) {
42 if ty.impls_future(ctx.db) {
43 CompletionItem::new(CompletionKind::Keyword, ctx.source_range(), "await")
44 .kind(CompletionItemKind::Keyword)
45 .detail("expr.await")
46 .insert_text("await")
47 .add_to(acc);
48 }
49 };
50 }
38} 51}
39 52
40pub(super) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionContext) { 53pub(super) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionContext) {
@@ -490,4 +503,26 @@ Some multi-line comment<|>
490 expect![[""]], 503 expect![[""]],
491 ); 504 );
492 } 505 }
506
507 #[test]
508 fn test_completion_await_impls_future() {
509 check(
510 r#"
511//- /main.rs
512use std::future::*;
513struct A {}
514impl Future for A {}
515fn foo(a: A) { a.<|> }
516
517//- /std/lib.rs
518pub mod future {
519 #[lang = "future_trait"]
520 pub trait Future {}
521}
522"#,
523 expect![[r#"
524 kw await expr.await
525 "#]],
526 )
527 }
493} 528}
diff --git a/crates/ra_ide/src/completion/complete_qualified_path.rs b/crates/ra_ide/src/completion/complete_qualified_path.rs
index f133ce3ce..a16866cd2 100644
--- a/crates/ra_ide/src/completion/complete_qualified_path.rs
+++ b/crates/ra_ide/src/completion/complete_qualified_path.rs
@@ -1206,6 +1206,45 @@ mod tests {
1206 } 1206 }
1207 1207
1208 #[test] 1208 #[test]
1209 fn test_super_super_completion() {
1210 assert_debug_snapshot!(
1211 do_reference_completion(
1212 r"
1213 mod a {
1214 const A: usize = 0;
1215
1216 mod b {
1217 const B: usize = 0;
1218
1219 mod c {
1220 use super::super::<|>
1221 }
1222 }
1223 }
1224 ",
1225 ),
1226 @r###"
1227 [
1228 CompletionItem {
1229 label: "A",
1230 source_range: 120..120,
1231 delete: 120..120,
1232 insert: "A",
1233 kind: Const,
1234 },
1235 CompletionItem {
1236 label: "b",
1237 source_range: 120..120,
1238 delete: 120..120,
1239 insert: "b",
1240 kind: Module,
1241 },
1242 ]
1243 "###
1244 );
1245 }
1246
1247 #[test]
1209 fn completes_reexported_items_under_correct_name() { 1248 fn completes_reexported_items_under_correct_name() {
1210 assert_debug_snapshot!( 1249 assert_debug_snapshot!(
1211 do_reference_completion( 1250 do_reference_completion(
diff --git a/crates/ra_ide/src/completion/presentation.rs b/crates/ra_ide/src/completion/presentation.rs
index bd48156b0..dc391c46b 100644
--- a/crates/ra_ide/src/completion/presentation.rs
+++ b/crates/ra_ide/src/completion/presentation.rs
@@ -644,6 +644,75 @@ fn foo() { A { the<|> } }
644 } 644 }
645 645
646 #[test] 646 #[test]
647 fn renders_docs() {
648 check(
649 r#"
650struct S {
651 /// Field docs
652 foo:
653}
654impl S {
655 /// Method docs
656 fn bar(self) { self.<|> }
657}"#,
658 expect![[r#"
659 [
660 CompletionItem {
661 label: "bar()",
662 source_range: 94..94,
663 delete: 94..94,
664 insert: "bar()$0",
665 kind: Method,
666 lookup: "bar",
667 detail: "fn bar(self)",
668 documentation: Documentation(
669 "Method docs",
670 ),
671 },
672 CompletionItem {
673 label: "foo",
674 source_range: 94..94,
675 delete: 94..94,
676 insert: "foo",
677 kind: Field,
678 detail: "{unknown}",
679 documentation: Documentation(
680 "Field docs",
681 ),
682 },
683 ]
684 "#]],
685 )
686 }
687
688 #[test]
689 fn dont_render_attrs() {
690 check(
691 r#"
692struct S;
693impl S {
694 #[inline]
695 fn the_method(&self) { }
696}
697fn foo(s: S) { s.<|> }
698"#,
699 expect![[r#"
700 [
701 CompletionItem {
702 label: "the_method()",
703 source_range: 81..81,
704 delete: 81..81,
705 insert: "the_method()$0",
706 kind: Method,
707 lookup: "the_method",
708 detail: "fn the_method(&self)",
709 },
710 ]
711 "#]],
712 )
713 }
714
715 #[test]
647 fn inserts_parens_for_function_calls() { 716 fn inserts_parens_for_function_calls() {
648 mark::check!(inserts_parens_for_function_calls); 717 mark::check!(inserts_parens_for_function_calls);
649 check_edit( 718 check_edit(