ide_completion/completions/
keyword.rs1use syntax::ast::{self, Item};
4
5use crate::{CompletionContext, Completions};
6
7pub(crate) fn complete_for_and_where(
8 acc: &mut Completions,
9 ctx: &CompletionContext<'_>,
10 keyword_item: &ast::Item,
11) {
12 let mut add_keyword = |kw, snippet| acc.add_keyword_snippet(ctx, kw, snippet);
13
14 match keyword_item {
15 Item::Impl(it) => {
16 if it.for_token().is_none() && it.trait_().is_none() && it.self_ty().is_some() {
17 add_keyword("for", "for $0");
18 }
19 add_keyword("where", "where $0");
20 }
21 Item::Enum(_)
22 | Item::Fn(_)
23 | Item::Struct(_)
24 | Item::Trait(_)
25 | Item::TypeAlias(_)
26 | Item::Union(_) => {
27 add_keyword("where", "where $0");
28 }
29 _ => (),
30 }
31}
32
33#[cfg(test)]
34mod tests {
35 use expect_test::expect;
36
37 use crate::tests::{check, check_edit};
38
39 #[test]
40 fn test_else_edit_after_if() {
41 check_edit(
42 "else",
43 r#"fn quux() { if true { () } $0 }"#,
44 r#"fn quux() { if true { () } else {
45 $0
46} }"#,
47 );
48 }
49
50 #[test]
51 fn test_keywords_after_unsafe_in_block_expr() {
52 check(
53 r"fn my_fn() { unsafe $0 }",
54 expect![[r#"
55 kw async
56 kw extern
57 kw fn
58 kw impl
59 kw impl for
60 kw trait
61 "#]],
62 );
63 }
64
65 #[test]
66 fn test_completion_await_impls_future() {
67 check(
68 r#"
69//- minicore: future
70use core::future::*;
71struct A {}
72impl Future for A {}
73fn foo(a: A) { a.$0 }
74"#,
75 expect![[r#"
76 me into_future() (as IntoFuture) fn(self) -> <Self as IntoFuture>::IntoFuture
77 kw await expr.await
78 sn box Box::new(expr)
79 sn call function(expr)
80 sn const const {}
81 sn dbg dbg!(expr)
82 sn dbgr dbg!(&expr)
83 sn deref *expr
84 sn let let
85 sn letm let mut
86 sn match match expr {}
87 sn ref &expr
88 sn refm &mut expr
89 sn return return expr
90 sn unsafe unsafe {}
91 "#]],
92 );
93
94 check(
95 r#"
96//- minicore: future
97use std::future::*;
98fn foo() {
99 let a = async {};
100 a.$0
101}
102"#,
103 expect![[r#"
104 me into_future() (use core::future::IntoFuture) fn(self) -> <Self as IntoFuture>::IntoFuture
105 kw await expr.await
106 sn box Box::new(expr)
107 sn call function(expr)
108 sn const const {}
109 sn dbg dbg!(expr)
110 sn dbgr dbg!(&expr)
111 sn deref *expr
112 sn let let
113 sn letm let mut
114 sn match match expr {}
115 sn ref &expr
116 sn refm &mut expr
117 sn return return expr
118 sn unsafe unsafe {}
119 "#]],
120 );
121 }
122
123 #[test]
124 fn test_completion_await_impls_into_future() {
125 check(
126 r#"
127//- minicore: future
128use core::future::*;
129struct A {}
130impl IntoFuture for A {}
131fn foo(a: A) { a.$0 }
132"#,
133 expect![[r#"
134 me into_future() (as IntoFuture) fn(self) -> <Self as IntoFuture>::IntoFuture
135 kw await expr.await
136 sn box Box::new(expr)
137 sn call function(expr)
138 sn const const {}
139 sn dbg dbg!(expr)
140 sn dbgr dbg!(&expr)
141 sn deref *expr
142 sn let let
143 sn letm let mut
144 sn match match expr {}
145 sn ref &expr
146 sn refm &mut expr
147 sn return return expr
148 sn unsafe unsafe {}
149 "#]],
150 );
151 }
152
153 #[test]
154 fn for_in_impl() {
155 check_edit(
156 "for",
157 r#"
158struct X;
159impl X $0 {}
160"#,
161 r#"
162struct X;
163impl X for $0 {}
164"#,
165 );
166 check_edit(
167 "for",
168 r#"
169fn foo() {
170 struct X;
171 impl X $0 {}
172}
173"#,
174 r#"
175fn foo() {
176 struct X;
177 impl X for $0 {}
178}
179"#,
180 );
181 check_edit(
182 "for",
183 r#"
184fn foo() {
185 struct X;
186 impl X $0
187}
188"#,
189 r#"
190fn foo() {
191 struct X;
192 impl X for $0
193}
194"#,
195 );
196 check_edit(
197 "for",
198 r#"
199fn foo() {
200 struct X;
201 impl X { fn bar() { $0 } }
202}
203"#,
204 r#"
205fn foo() {
206 struct X;
207 impl X { fn bar() { for $1 in $2 {
208 $0
209} } }
210}
211"#,
212 );
213 }
214
215 #[test]
216 fn let_semi() {
217 cov_mark::check!(let_semi);
218 check_edit(
219 "match",
220 r#"
221fn main() { let x = $0 }
222"#,
223 r#"
224fn main() { let x = match $1 {
225 $0
226}; }
227"#,
228 );
229
230 check_edit(
231 "if",
232 r#"
233fn main() {
234 let x = $0
235 let y = 92;
236}
237"#,
238 r#"
239fn main() {
240 let x = if $1 {
241 $2
242} else {
243 $0
244};
245 let y = 92;
246}
247"#,
248 );
249
250 check_edit(
251 "else",
252 r#"
253fn main() {
254 let x = if true {
255 ()
256 } $0
257 let y = 92;
258}
259"#,
260 r#"
261fn main() {
262 let x = if true {
263 ()
264 } else {
265 $0
266};
267 let y = 92;
268}
269"#,
270 );
271
272 check_edit(
273 "else if",
274 r#"
275fn main() {
276 let x = if true {
277 ()
278 } $0 else {};
279}
280"#,
281 r#"
282fn main() {
283 let x = if true {
284 ()
285 } else if $1 {
286 $0
287} else {};
288}
289"#,
290 );
291
292 check_edit(
293 "else if",
294 r#"
295fn main() {
296 let x = if true {
297 ()
298 } $0 else if true {};
299}
300"#,
301 r#"
302fn main() {
303 let x = if true {
304 ()
305 } else if $1 {
306 $0
307} else if true {};
308}
309"#,
310 );
311
312 check_edit(
313 "else",
314 r#"
315fn main() {
316 let x = 2 $0
317 let y = 92;
318}
319"#,
320 r#"
321fn main() {
322 let x = 2 else {
323 $0
324};
325 let y = 92;
326}
327"#,
328 );
329
330 check_edit(
331 "loop",
332 r#"
333fn main() {
334 let x = $0
335 bar();
336}
337"#,
338 r#"
339fn main() {
340 let x = loop {
341 $0
342};
343 bar();
344}
345"#,
346 );
347
348 check_edit(
349 "loop",
350 r#"
351fn main() {
352 let x = &$0
353 bar();
354}
355"#,
356 r#"
357fn main() {
358 let x = &loop {
359 $0
360};
361 bar();
362}
363"#,
364 );
365
366 check_edit(
367 "loop",
368 r#"
369fn main() {
370 let x = -$0
371 bar();
372}
373"#,
374 r#"
375fn main() {
376 let x = -loop {
377 $0
378};
379 bar();
380}
381"#,
382 );
383
384 check_edit(
385 "loop",
386 r#"
387fn main() {
388 let x = 2 + $0
389 bar();
390}
391"#,
392 r#"
393fn main() {
394 let x = 2 + loop {
395 $0
396};
397 bar();
398}
399"#,
400 );
401 }
402
403 #[test]
404 fn if_completion_in_match_guard() {
405 check_edit(
406 "if",
407 r"
408fn main() {
409 match () {
410 () $0
411 }
412}
413",
414 r"
415fn main() {
416 match () {
417 () if $0
418 }
419}
420",
421 )
422 }
423
424 #[test]
425 fn if_completion_in_match_arm_expr() {
426 check_edit(
427 "if",
428 r"
429fn main() {
430 match () {
431 () => $0
432 }
433}
434",
435 r"
436fn main() {
437 match () {
438 () => if $1 {
439 $0
440}
441 }
442}
443",
444 )
445 }
446
447 #[test]
448 fn if_completion_in_match_arm_expr_block() {
449 check_edit(
450 "if",
451 r"
452fn main() {
453 match () {
454 () => {
455 $0
456 }
457 }
458}
459",
460 r"
461fn main() {
462 match () {
463 () => {
464 if $1 {
465 $0
466}
467 }
468 }
469}
470",
471 )
472 }
473
474 #[test]
475 fn if_completion_in_parameter() {
476 check_edit(
477 "if",
478 r"
479fn main() {
480 foo($0)
481}
482",
483 r"
484fn main() {
485 foo(if $1 {
486 $2
487} else {
488 $0
489})
490}
491",
492 );
493
494 check_edit(
495 "if",
496 r"
497fn main() {
498 foo($0, 2)
499}
500",
501 r"
502fn main() {
503 foo(if $1 {
504 $2
505} else {
506 $0
507}, 2)
508}
509",
510 );
511
512 check_edit(
513 "if",
514 r"
515fn main() {
516 foo(2, $0)
517}
518",
519 r"
520fn main() {
521 foo(2, if $1 {
522 $2
523} else {
524 $0
525})
526}
527",
528 );
529
530 check_edit(
531 "if let",
532 r"
533fn main() {
534 foo(2, $0)
535}
536",
537 r"
538fn main() {
539 foo(2, if let $1 = $2 {
540 $3
541} else {
542 $0
543})
544}
545",
546 );
547 }
548
549 #[test]
550 fn if_completion_in_let_statement() {
551 check_edit(
552 "if",
553 r"
554fn main() {
555 let x = $0;
556}
557",
558 r"
559fn main() {
560 let x = if $1 {
561 $2
562} else {
563 $0
564};
565}
566",
567 );
568
569 check_edit(
570 "if let",
571 r"
572fn main() {
573 let x = $0;
574}
575",
576 r"
577fn main() {
578 let x = if let $1 = $2 {
579 $3
580} else {
581 $0
582};
583}
584",
585 );
586 }
587
588 #[test]
589 fn if_completion_in_format() {
590 check_edit(
591 "if",
592 r#"
593//- minicore: fmt
594fn main() {
595 format_args!("{}", $0);
596}
597"#,
598 r#"
599fn main() {
600 format_args!("{}", if $1 {
601 $2
602} else {
603 $0
604});
605}
606"#,
607 );
608
609 check_edit(
610 "if",
611 r#"
612//- minicore: fmt
613fn main() {
614 format_args!("{}", if$0);
615}
616"#,
617 r#"
618fn main() {
619 format_args!("{}", if $1 {
620 $2
621} else {
622 $0
623});
624}
625"#,
626 );
627 }
628
629 #[test]
630 fn if_completion_in_value_expected_expressions() {
631 check_edit(
632 "if",
633 r#"
634fn main() {
635 2 + $0;
636}
637"#,
638 r#"
639fn main() {
640 2 + if $1 {
641 $2
642} else {
643 $0
644};
645}
646"#,
647 );
648
649 check_edit(
650 "if",
651 r#"
652fn main() {
653 -$0;
654}
655"#,
656 r#"
657fn main() {
658 -if $1 {
659 $2
660} else {
661 $0
662};
663}
664"#,
665 );
666
667 check_edit(
668 "if",
669 r#"
670fn main() {
671 return $0;
672}
673"#,
674 r#"
675fn main() {
676 return if $1 {
677 $2
678} else {
679 $0
680};
681}
682"#,
683 );
684
685 check_edit(
686 "if",
687 r#"
688fn main() {
689 loop {
690 break $0;
691 }
692}
693"#,
694 r#"
695fn main() {
696 loop {
697 break if $1 {
698 $2
699} else {
700 $0
701};
702 }
703}
704"#,
705 );
706
707 check_edit(
708 "if",
709 r#"
710struct Foo { x: i32 }
711fn main() {
712 Foo { x: $0 }
713}
714"#,
715 r#"
716struct Foo { x: i32 }
717fn main() {
718 Foo { x: if $1 {
719 $2
720} else {
721 $0
722} }
723}
724"#,
725 );
726 }
727
728 #[test]
729 fn completes_let_in_block() {
730 check_edit(
731 "let",
732 r#"
733fn main() {
734 $0
735}
736"#,
737 r#"
738fn main() {
739 let $1 = $0;
740}
741"#,
742 );
743 check_edit(
744 "letm",
745 r#"
746fn main() {
747 $0
748}
749"#,
750 r#"
751fn main() {
752 let mut $1 = $0;
753}
754"#,
755 );
756 }
757
758 #[test]
759 fn completes_let_in_condition() {
760 check_edit(
761 "let",
762 r#"
763fn main() {
764 if $0 {}
765}
766"#,
767 r#"
768fn main() {
769 if let $1 = $0 {}
770}
771"#,
772 );
773 check_edit(
774 "letm",
775 r#"
776fn main() {
777 if $0 {}
778}
779"#,
780 r#"
781fn main() {
782 if let mut $1 = $0 {}
783}
784"#,
785 );
786 }
787
788 #[test]
789 fn completes_let_in_no_empty_condition() {
790 check_edit(
791 "let",
792 r#"
793fn main() {
794 if $0x {}
795}
796"#,
797 r#"
798fn main() {
799 if let $1 = $0x {}
800}
801"#,
802 );
803 check_edit(
804 "letm",
805 r#"
806fn main() {
807 if $0x {}
808}
809"#,
810 r#"
811fn main() {
812 if let mut $1 = $0x {}
813}
814"#,
815 );
816 }
817
818 #[test]
819 fn completes_let_in_condition_block() {
820 check_edit(
821 "let",
822 r#"
823fn main() {
824 if { $0 } {}
825}
826"#,
827 r#"
828fn main() {
829 if { let $1 = $0; } {}
830}
831"#,
832 );
833 check_edit(
834 "letm",
835 r#"
836fn main() {
837 if { $0 } {}
838}
839"#,
840 r#"
841fn main() {
842 if { let mut $1 = $0; } {}
843}
844"#,
845 );
846 }
847}