aboutsummaryrefslogtreecommitdiff
path: root/crates/ide_completion/src/completions/keyword.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ide_completion/src/completions/keyword.rs')
-rw-r--r--crates/ide_completion/src/completions/keyword.rs278
1 files changed, 60 insertions, 218 deletions
diff --git a/crates/ide_completion/src/completions/keyword.rs b/crates/ide_completion/src/completions/keyword.rs
index ba13d3707..407f796ef 100644
--- a/crates/ide_completion/src/completions/keyword.rs
+++ b/crates/ide_completion/src/completions/keyword.rs
@@ -18,26 +18,22 @@ pub(crate) fn complete_use_tree_keyword(acc: &mut Completions, ctx: &CompletionC
18 item 18 item
19 }; 19 };
20 20
21 if ctx.use_item_syntax.is_some() { 21 if ctx.in_use_tree() {
22 let qual = ctx.path_qual(); 22 match &ctx.path_context {
23 if qual.is_none() { 23 Some(PathCompletionContext { qualifier: Some(qual), use_tree_parent, .. }) => {
24 kw_completion("crate::").add_to(acc); 24 if iter::successors(Some(qual.clone()), |p| p.qualifier())
25 } 25 .all(|p| p.segment().and_then(|s| s.super_token()).is_some())
26 kw_completion("self").add_to(acc); 26 {
27 if iter::successors(qual.cloned(), |p| p.qualifier()) 27 kw_completion("super::").add_to(acc);
28 .all(|p| p.segment().and_then(|s| s.super_token()).is_some()) 28 }
29 { 29 if *use_tree_parent {
30 kw_completion("super::").add_to(acc); 30 kw_completion("self").add_to(acc);
31 } 31 }
32 } 32 }
33 33 _ => {
34 // Suggest .await syntax for types that implement Future trait 34 kw_completion("crate::").add_to(acc);
35 if let Some(receiver) = ctx.dot_receiver() { 35 kw_completion("self::").add_to(acc);
36 if let Some(ty) = ctx.sema.type_of_expr(receiver) { 36 kw_completion("super::").add_to(acc);
37 if ty.impls_future(ctx.db) {
38 let mut item = kw_completion("await");
39 item.detail("expr.await");
40 item.add_to(acc);
41 } 37 }
42 }; 38 };
43 } 39 }
@@ -52,6 +48,23 @@ pub(crate) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionConte
52 cov_mark::hit!(no_keyword_completion_in_record_lit); 48 cov_mark::hit!(no_keyword_completion_in_record_lit);
53 return; 49 return;
54 } 50 }
51 if ctx.attribute_under_caret.is_some() {
52 cov_mark::hit!(no_keyword_completion_in_attr_of_expr);
53 return;
54 }
55
56 // Suggest .await syntax for types that implement Future trait
57 if let Some(receiver) = ctx.dot_receiver() {
58 if let Some(ty) = ctx.sema.type_of_expr(receiver) {
59 if ty.impls_future(ctx.db) {
60 let mut item =
61 CompletionItem::new(CompletionKind::Keyword, ctx.source_range(), "await");
62 item.kind(CompletionItemKind::Keyword).detail("expr.await");
63 item.add_to(acc);
64 }
65 };
66 }
67
55 let mut add_keyword = |kw, snippet| add_keyword(ctx, acc, kw, snippet); 68 let mut add_keyword = |kw, snippet| add_keyword(ctx, acc, kw, snippet);
56 69
57 let expects_assoc_item = ctx.expects_assoc_item(); 70 let expects_assoc_item = ctx.expects_assoc_item();
@@ -60,6 +73,9 @@ pub(crate) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionConte
60 73
61 if ctx.has_impl_or_trait_prev_sibling() { 74 if ctx.has_impl_or_trait_prev_sibling() {
62 add_keyword("where", "where "); 75 add_keyword("where", "where ");
76 if ctx.has_impl_prev_sibling() {
77 add_keyword("for", "for ");
78 }
63 return; 79 return;
64 } 80 }
65 if ctx.previous_token_is(T![unsafe]) { 81 if ctx.previous_token_is(T![unsafe]) {
@@ -75,7 +91,9 @@ pub(crate) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionConte
75 return; 91 return;
76 } 92 }
77 93
78 if expects_item || ctx.expects_non_trait_assoc_item() || ctx.expect_record_field() { 94 if !ctx.has_visibility_prev_sibling()
95 && (expects_item || ctx.expects_non_trait_assoc_item() || ctx.expect_field())
96 {
79 add_keyword("pub(crate)", "pub(crate) "); 97 add_keyword("pub(crate)", "pub(crate) ");
80 add_keyword("pub", "pub "); 98 add_keyword("pub", "pub ");
81 } 99 }
@@ -88,11 +106,13 @@ pub(crate) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionConte
88 } 106 }
89 107
90 if expects_item || has_block_expr_parent { 108 if expects_item || has_block_expr_parent {
109 if !ctx.has_visibility_prev_sibling() {
110 add_keyword("impl", "impl $1 {\n $0\n}");
111 add_keyword("extern", "extern $0");
112 }
91 add_keyword("use", "use $0"); 113 add_keyword("use", "use $0");
92 add_keyword("impl", "impl $1 {\n $0\n}");
93 add_keyword("trait", "trait $1 {\n $0\n}"); 114 add_keyword("trait", "trait $1 {\n $0\n}");
94 add_keyword("static", "static $0"); 115 add_keyword("static", "static $0");
95 add_keyword("extern", "extern $0");
96 add_keyword("mod", "mod $0"); 116 add_keyword("mod", "mod $0");
97 } 117 }
98 118
@@ -102,6 +122,10 @@ pub(crate) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionConte
102 add_keyword("union", "union $1 {\n $0\n}"); 122 add_keyword("union", "union $1 {\n $0\n}");
103 } 123 }
104 124
125 if ctx.expects_type() {
126 return;
127 }
128
105 if ctx.expects_expression() { 129 if ctx.expects_expression() {
106 if !has_block_expr_parent { 130 if !has_block_expr_parent {
107 add_keyword("unsafe", "unsafe {\n $0\n}"); 131 add_keyword("unsafe", "unsafe {\n $0\n}");
@@ -186,75 +210,16 @@ mod tests {
186 use expect_test::{expect, Expect}; 210 use expect_test::{expect, Expect};
187 211
188 use crate::{ 212 use crate::{
189 test_utils::{check_edit, completion_list}, 213 tests::{check_edit, filtered_completion_list},
190 CompletionKind, 214 CompletionKind,
191 }; 215 };
192 216
193 fn check(ra_fixture: &str, expect: Expect) { 217 fn check(ra_fixture: &str, expect: Expect) {
194 let actual = completion_list(ra_fixture, CompletionKind::Keyword); 218 let actual = filtered_completion_list(ra_fixture, CompletionKind::Keyword);
195 expect.assert_eq(&actual) 219 expect.assert_eq(&actual)
196 } 220 }
197 221
198 #[test] 222 #[test]
199 fn test_keywords_in_use_stmt() {
200 check(
201 r"use $0",
202 expect![[r#"
203 kw crate::
204 kw self
205 kw super::
206 "#]],
207 );
208
209 // FIXME: `self` shouldn't be shown here and the check below
210 check(
211 r"use a::$0",
212 expect![[r#"
213 kw self
214 "#]],
215 );
216
217 check(
218 r"use super::$0",
219 expect![[r#"
220 kw self
221 kw super::
222 "#]],
223 );
224
225 check(
226 r"use a::{b, $0}",
227 expect![[r#"
228 kw self
229 "#]],
230 );
231 }
232
233 #[test]
234 fn test_keywords_at_source_file_level() {
235 check(
236 r"m$0",
237 expect![[r#"
238 kw pub(crate)
239 kw pub
240 kw unsafe
241 kw fn
242 kw const
243 kw type
244 kw use
245 kw impl
246 kw trait
247 kw static
248 kw extern
249 kw mod
250 kw enum
251 kw struct
252 kw union
253 "#]],
254 );
255 }
256
257 #[test]
258 fn test_keywords_in_function() { 223 fn test_keywords_in_function() {
259 check( 224 check(
260 r"fn quux() { $0 }", 225 r"fn quux() { $0 }",
@@ -263,11 +228,11 @@ mod tests {
263 kw fn 228 kw fn
264 kw const 229 kw const
265 kw type 230 kw type
266 kw use
267 kw impl 231 kw impl
232 kw extern
233 kw use
268 kw trait 234 kw trait
269 kw static 235 kw static
270 kw extern
271 kw mod 236 kw mod
272 kw match 237 kw match
273 kw while 238 kw while
@@ -291,11 +256,11 @@ mod tests {
291 kw fn 256 kw fn
292 kw const 257 kw const
293 kw type 258 kw type
294 kw use
295 kw impl 259 kw impl
260 kw extern
261 kw use
296 kw trait 262 kw trait
297 kw static 263 kw static
298 kw extern
299 kw mod 264 kw mod
300 kw match 265 kw match
301 kw while 266 kw while
@@ -319,11 +284,11 @@ mod tests {
319 kw fn 284 kw fn
320 kw const 285 kw const
321 kw type 286 kw type
322 kw use
323 kw impl 287 kw impl
288 kw extern
289 kw use
324 kw trait 290 kw trait
325 kw static 291 kw static
326 kw extern
327 kw mod 292 kw mod
328 kw match 293 kw match
329 kw while 294 kw while
@@ -370,49 +335,6 @@ fn quux() -> i32 {
370 } 335 }
371 336
372 #[test] 337 #[test]
373 fn test_keywords_in_trait_def() {
374 check(
375 r"trait My { $0 }",
376 expect![[r#"
377 kw unsafe
378 kw fn
379 kw const
380 kw type
381 "#]],
382 );
383 }
384
385 #[test]
386 fn test_keywords_in_impl_def() {
387 check(
388 r"impl My { $0 }",
389 expect![[r#"
390 kw pub(crate)
391 kw pub
392 kw unsafe
393 kw fn
394 kw const
395 kw type
396 "#]],
397 );
398 }
399
400 #[test]
401 fn test_keywords_in_impl_def_with_attr() {
402 check(
403 r"impl My { #[foo] $0 }",
404 expect![[r#"
405 kw pub(crate)
406 kw pub
407 kw unsafe
408 kw fn
409 kw const
410 kw type
411 "#]],
412 );
413 }
414
415 #[test]
416 fn test_keywords_in_loop() { 338 fn test_keywords_in_loop() {
417 check( 339 check(
418 r"fn my() { loop { $0 } }", 340 r"fn my() { loop { $0 } }",
@@ -421,11 +343,11 @@ fn quux() -> i32 {
421 kw fn 343 kw fn
422 kw const 344 kw const
423 kw type 345 kw type
424 kw use
425 kw impl 346 kw impl
347 kw extern
348 kw use
426 kw trait 349 kw trait
427 kw static 350 kw static
428 kw extern
429 kw mod 351 kw mod
430 kw match 352 kw match
431 kw while 353 kw while
@@ -443,18 +365,6 @@ fn quux() -> i32 {
443 } 365 }
444 366
445 #[test] 367 #[test]
446 fn test_keywords_after_unsafe_in_item_list() {
447 check(
448 r"unsafe $0",
449 expect![[r#"
450 kw fn
451 kw trait
452 kw impl
453 "#]],
454 );
455 }
456
457 #[test]
458 fn test_keywords_after_unsafe_in_block_expr() { 368 fn test_keywords_after_unsafe_in_block_expr() {
459 check( 369 check(
460 r"fn my_fn() { unsafe $0 }", 370 r"fn my_fn() { unsafe $0 }",
@@ -467,44 +377,6 @@ fn quux() -> i32 {
467 } 377 }
468 378
469 #[test] 379 #[test]
470 fn test_mut_in_ref_and_in_fn_parameters_list() {
471 check(
472 r"fn my_fn(&$0) {}",
473 expect![[r#"
474 kw mut
475 "#]],
476 );
477 check(
478 r"fn my_fn($0) {}",
479 expect![[r#"
480 kw mut
481 "#]],
482 );
483 check(
484 r"fn my_fn() { let &$0 }",
485 expect![[r#"
486 kw mut
487 "#]],
488 );
489 }
490
491 #[test]
492 fn test_where_keyword() {
493 check(
494 r"trait A $0",
495 expect![[r#"
496 kw where
497 "#]],
498 );
499 check(
500 r"impl A $0",
501 expect![[r#"
502 kw where
503 "#]],
504 );
505 }
506
507 #[test]
508 fn no_keyword_completion_in_comments() { 380 fn no_keyword_completion_in_comments() {
509 cov_mark::check!(no_keyword_completion_in_comments); 381 cov_mark::check!(no_keyword_completion_in_comments);
510 check( 382 check(
@@ -536,17 +408,11 @@ Some multi-line comment$0
536 fn test_completion_await_impls_future() { 408 fn test_completion_await_impls_future() {
537 check( 409 check(
538 r#" 410 r#"
539//- /main.rs crate:main deps:std 411//- minicore: future
540use std::future::*; 412use core::future::*;
541struct A {} 413struct A {}
542impl Future for A {} 414impl Future for A {}
543fn foo(a: A) { a.$0 } 415fn foo(a: A) { a.$0 }
544
545//- /std/lib.rs crate:std
546pub mod future {
547 #[lang = "future_trait"]
548 pub trait Future {}
549}
550"#, 416"#,
551 expect![[r#" 417 expect![[r#"
552 kw await expr.await 418 kw await expr.await
@@ -555,20 +421,12 @@ pub mod future {
555 421
556 check( 422 check(
557 r#" 423 r#"
558//- /main.rs crate:main deps:std 424//- minicore: future
559use std::future::*; 425use std::future::*;
560fn foo() { 426fn foo() {
561 let a = async {}; 427 let a = async {};
562 a.$0 428 a.$0
563} 429}
564
565//- /std/lib.rs crate:std
566pub mod future {
567 #[lang = "future_trait"]
568 pub trait Future {
569 type Output;
570 }
571}
572"#, 430"#,
573 expect![[r#" 431 expect![[r#"
574 kw await expr.await 432 kw await expr.await
@@ -595,22 +453,6 @@ pub mod future {
595 } 453 }
596 454
597 #[test] 455 #[test]
598 fn before_field() {
599 check(
600 r#"
601struct Foo {
602 $0
603 pub f: i32,
604}
605"#,
606 expect![[r#"
607 kw pub(crate)
608 kw pub
609 "#]],
610 )
611 }
612
613 #[test]
614 fn skip_struct_initializer() { 456 fn skip_struct_initializer() {
615 cov_mark::check!(no_keyword_completion_in_record_lit); 457 cov_mark::check!(no_keyword_completion_in_record_lit);
616 check( 458 check(