diff options
Diffstat (limited to 'crates/ide_completion/src/completions/keyword.rs')
-rw-r--r-- | crates/ide_completion/src/completions/keyword.rs | 85 |
1 files changed, 52 insertions, 33 deletions
diff --git a/crates/ide_completion/src/completions/keyword.rs b/crates/ide_completion/src/completions/keyword.rs index eb81f9765..b635e0ca3 100644 --- a/crates/ide_completion/src/completions/keyword.rs +++ b/crates/ide_completion/src/completions/keyword.rs | |||
@@ -1,7 +1,8 @@ | |||
1 | //! Completes keywords. | 1 | //! Completes keywords. |
2 | 2 | ||
3 | use std::iter; | ||
4 | |||
3 | use syntax::SyntaxKind; | 5 | use syntax::SyntaxKind; |
4 | use test_utils::mark; | ||
5 | 6 | ||
6 | use crate::{CompletionContext, CompletionItem, CompletionItemKind, CompletionKind, Completions}; | 7 | use crate::{CompletionContext, CompletionItem, CompletionItemKind, CompletionKind, Completions}; |
7 | 8 | ||
@@ -11,29 +12,30 @@ pub(crate) fn complete_use_tree_keyword(acc: &mut Completions, ctx: &CompletionC | |||
11 | 12 | ||
12 | if ctx.use_item_syntax.is_some() { | 13 | if ctx.use_item_syntax.is_some() { |
13 | if ctx.path_qual.is_none() { | 14 | if ctx.path_qual.is_none() { |
14 | CompletionItem::new(CompletionKind::Keyword, source_range, "crate::") | 15 | let mut item = CompletionItem::new(CompletionKind::Keyword, source_range, "crate::"); |
15 | .kind(CompletionItemKind::Keyword) | 16 | item.kind(CompletionItemKind::Keyword).insert_text("crate::"); |
16 | .insert_text("crate::") | 17 | item.add_to(acc); |
17 | .add_to(acc); | 18 | } |
19 | let mut item = CompletionItem::new(CompletionKind::Keyword, source_range, "self"); | ||
20 | item.kind(CompletionItemKind::Keyword); | ||
21 | item.add_to(acc); | ||
22 | if iter::successors(ctx.path_qual.clone(), |p| p.qualifier()) | ||
23 | .all(|p| p.segment().and_then(|s| s.super_token()).is_some()) | ||
24 | { | ||
25 | let mut item = CompletionItem::new(CompletionKind::Keyword, source_range, "super::"); | ||
26 | item.kind(CompletionItemKind::Keyword).insert_text("super::"); | ||
27 | item.add_to(acc); | ||
18 | } | 28 | } |
19 | CompletionItem::new(CompletionKind::Keyword, source_range, "self") | ||
20 | .kind(CompletionItemKind::Keyword) | ||
21 | .add_to(acc); | ||
22 | CompletionItem::new(CompletionKind::Keyword, source_range, "super::") | ||
23 | .kind(CompletionItemKind::Keyword) | ||
24 | .insert_text("super::") | ||
25 | .add_to(acc); | ||
26 | } | 29 | } |
27 | 30 | ||
28 | // Suggest .await syntax for types that implement Future trait | 31 | // Suggest .await syntax for types that implement Future trait |
29 | if let Some(receiver) = &ctx.dot_receiver { | 32 | if let Some(receiver) = &ctx.dot_receiver { |
30 | if let Some(ty) = ctx.sema.type_of_expr(receiver) { | 33 | if let Some(ty) = ctx.sema.type_of_expr(receiver) { |
31 | if ty.impls_future(ctx.db) { | 34 | if ty.impls_future(ctx.db) { |
32 | CompletionItem::new(CompletionKind::Keyword, ctx.source_range(), "await") | 35 | let mut item = |
33 | .kind(CompletionItemKind::Keyword) | 36 | CompletionItem::new(CompletionKind::Keyword, ctx.source_range(), "await"); |
34 | .detail("expr.await") | 37 | item.kind(CompletionItemKind::Keyword).detail("expr.await").insert_text("await"); |
35 | .insert_text("await") | 38 | item.add_to(acc); |
36 | .add_to(acc); | ||
37 | } | 39 | } |
38 | }; | 40 | }; |
39 | } | 41 | } |
@@ -41,11 +43,11 @@ pub(crate) fn complete_use_tree_keyword(acc: &mut Completions, ctx: &CompletionC | |||
41 | 43 | ||
42 | pub(crate) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionContext) { | 44 | pub(crate) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionContext) { |
43 | if ctx.token.kind() == SyntaxKind::COMMENT { | 45 | if ctx.token.kind() == SyntaxKind::COMMENT { |
44 | mark::hit!(no_keyword_completion_in_comments); | 46 | cov_mark::hit!(no_keyword_completion_in_comments); |
45 | return; | 47 | return; |
46 | } | 48 | } |
47 | if ctx.record_lit_syntax.is_some() { | 49 | if ctx.record_lit_syntax.is_some() { |
48 | mark::hit!(no_keyword_completion_in_record_lit); | 50 | cov_mark::hit!(no_keyword_completion_in_record_lit); |
49 | return; | 51 | return; |
50 | } | 52 | } |
51 | 53 | ||
@@ -85,6 +87,7 @@ pub(crate) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionConte | |||
85 | if ctx.is_expr { | 87 | if ctx.is_expr { |
86 | add_keyword(ctx, acc, "match", "match $0 {}"); | 88 | add_keyword(ctx, acc, "match", "match $0 {}"); |
87 | add_keyword(ctx, acc, "while", "while $0 {}"); | 89 | add_keyword(ctx, acc, "while", "while $0 {}"); |
90 | add_keyword(ctx, acc, "while let", "while let $1 = $0 {}"); | ||
88 | add_keyword(ctx, acc, "loop", "loop {$0}"); | 91 | add_keyword(ctx, acc, "loop", "loop {$0}"); |
89 | add_keyword(ctx, acc, "if", "if $0 {}"); | 92 | add_keyword(ctx, acc, "if", "if $0 {}"); |
90 | add_keyword(ctx, acc, "if let", "if let $1 = $0 {}"); | 93 | add_keyword(ctx, acc, "if let", "if let $1 = $0 {}"); |
@@ -159,29 +162,31 @@ pub(crate) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionConte | |||
159 | } | 162 | } |
160 | 163 | ||
161 | fn add_keyword(ctx: &CompletionContext, acc: &mut Completions, kw: &str, snippet: &str) { | 164 | fn add_keyword(ctx: &CompletionContext, acc: &mut Completions, kw: &str, snippet: &str) { |
162 | let builder = CompletionItem::new(CompletionKind::Keyword, ctx.source_range(), kw) | 165 | let mut item = CompletionItem::new(CompletionKind::Keyword, ctx.source_range(), kw); |
163 | .kind(CompletionItemKind::Keyword); | 166 | item.kind(CompletionItemKind::Keyword); |
164 | let builder = match ctx.config.snippet_cap { | 167 | |
168 | match ctx.config.snippet_cap { | ||
165 | Some(cap) => { | 169 | Some(cap) => { |
166 | let tmp; | 170 | let tmp; |
167 | let snippet = if snippet.ends_with('}') && ctx.incomplete_let { | 171 | let snippet = if snippet.ends_with('}') && ctx.incomplete_let { |
168 | mark::hit!(let_semi); | 172 | cov_mark::hit!(let_semi); |
169 | tmp = format!("{};", snippet); | 173 | tmp = format!("{};", snippet); |
170 | &tmp | 174 | &tmp |
171 | } else { | 175 | } else { |
172 | snippet | 176 | snippet |
173 | }; | 177 | }; |
174 | builder.insert_snippet(cap, snippet) | 178 | item.insert_snippet(cap, snippet); |
179 | } | ||
180 | None => { | ||
181 | item.insert_text(if snippet.contains('$') { kw } else { snippet }); | ||
175 | } | 182 | } |
176 | None => builder.insert_text(if snippet.contains('$') { kw } else { snippet }), | ||
177 | }; | 183 | }; |
178 | acc.add(builder.build()); | 184 | item.add_to(acc); |
179 | } | 185 | } |
180 | 186 | ||
181 | #[cfg(test)] | 187 | #[cfg(test)] |
182 | mod tests { | 188 | mod tests { |
183 | use expect_test::{expect, Expect}; | 189 | use expect_test::{expect, Expect}; |
184 | use test_utils::mark; | ||
185 | 190 | ||
186 | use crate::{ | 191 | use crate::{ |
187 | test_utils::{check_edit, completion_list}, | 192 | test_utils::{check_edit, completion_list}, |
@@ -204,9 +209,17 @@ mod tests { | |||
204 | "#]], | 209 | "#]], |
205 | ); | 210 | ); |
206 | 211 | ||
212 | // FIXME: `self` shouldn't be shown here and the check below | ||
207 | check( | 213 | check( |
208 | r"use a::$0", | 214 | r"use a::$0", |
209 | expect![[r#" | 215 | expect![[r#" |
216 | kw self | ||
217 | "#]], | ||
218 | ); | ||
219 | |||
220 | check( | ||
221 | r"use super::$0", | ||
222 | expect![[r#" | ||
210 | kw self | 223 | kw self |
211 | kw super:: | 224 | kw super:: |
212 | "#]], | 225 | "#]], |
@@ -215,9 +228,8 @@ mod tests { | |||
215 | check( | 228 | check( |
216 | r"use a::{b, $0}", | 229 | r"use a::{b, $0}", |
217 | expect![[r#" | 230 | expect![[r#" |
218 | kw self | 231 | kw self |
219 | kw super:: | 232 | "#]], |
220 | "#]], | ||
221 | ); | 233 | ); |
222 | } | 234 | } |
223 | 235 | ||
@@ -256,6 +268,7 @@ mod tests { | |||
256 | kw trait | 268 | kw trait |
257 | kw match | 269 | kw match |
258 | kw while | 270 | kw while |
271 | kw while let | ||
259 | kw loop | 272 | kw loop |
260 | kw if | 273 | kw if |
261 | kw if let | 274 | kw if let |
@@ -283,6 +296,7 @@ mod tests { | |||
283 | kw trait | 296 | kw trait |
284 | kw match | 297 | kw match |
285 | kw while | 298 | kw while |
299 | kw while let | ||
286 | kw loop | 300 | kw loop |
287 | kw if | 301 | kw if |
288 | kw if let | 302 | kw if let |
@@ -310,6 +324,7 @@ mod tests { | |||
310 | kw trait | 324 | kw trait |
311 | kw match | 325 | kw match |
312 | kw while | 326 | kw while |
327 | kw while let | ||
313 | kw loop | 328 | kw loop |
314 | kw if | 329 | kw if |
315 | kw if let | 330 | kw if let |
@@ -344,6 +359,7 @@ fn quux() -> i32 { | |||
344 | expect![[r#" | 359 | expect![[r#" |
345 | kw match | 360 | kw match |
346 | kw while | 361 | kw while |
362 | kw while let | ||
347 | kw loop | 363 | kw loop |
348 | kw if | 364 | kw if |
349 | kw if let | 365 | kw if let |
@@ -393,6 +409,7 @@ fn quux() -> i32 { | |||
393 | kw trait | 409 | kw trait |
394 | kw match | 410 | kw match |
395 | kw while | 411 | kw while |
412 | kw while let | ||
396 | kw loop | 413 | kw loop |
397 | kw if | 414 | kw if |
398 | kw if let | 415 | kw if let |
@@ -475,7 +492,7 @@ fn quux() -> i32 { | |||
475 | 492 | ||
476 | #[test] | 493 | #[test] |
477 | fn no_keyword_completion_in_comments() { | 494 | fn no_keyword_completion_in_comments() { |
478 | mark::check!(no_keyword_completion_in_comments); | 495 | cov_mark::check!(no_keyword_completion_in_comments); |
479 | check( | 496 | check( |
480 | r#" | 497 | r#" |
481 | fn test() { | 498 | fn test() { |
@@ -552,6 +569,7 @@ pub mod future { | |||
552 | expect![[r#" | 569 | expect![[r#" |
553 | kw match | 570 | kw match |
554 | kw while | 571 | kw while |
572 | kw while let | ||
555 | kw loop | 573 | kw loop |
556 | kw if | 574 | kw if |
557 | kw if let | 575 | kw if let |
@@ -579,7 +597,7 @@ struct Foo { | |||
579 | 597 | ||
580 | #[test] | 598 | #[test] |
581 | fn skip_struct_initializer() { | 599 | fn skip_struct_initializer() { |
582 | mark::check!(no_keyword_completion_in_record_lit); | 600 | cov_mark::check!(no_keyword_completion_in_record_lit); |
583 | check( | 601 | check( |
584 | r#" | 602 | r#" |
585 | struct Foo { | 603 | struct Foo { |
@@ -611,6 +629,7 @@ fn foo() { | |||
611 | expect![[r#" | 629 | expect![[r#" |
612 | kw match | 630 | kw match |
613 | kw while | 631 | kw while |
632 | kw while let | ||
614 | kw loop | 633 | kw loop |
615 | kw if | 634 | kw if |
616 | kw if let | 635 | kw if let |
@@ -622,7 +641,7 @@ fn foo() { | |||
622 | 641 | ||
623 | #[test] | 642 | #[test] |
624 | fn let_semi() { | 643 | fn let_semi() { |
625 | mark::check!(let_semi); | 644 | cov_mark::check!(let_semi); |
626 | check_edit( | 645 | check_edit( |
627 | "match", | 646 | "match", |
628 | r#" | 647 | r#" |