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.rs197
1 files changed, 104 insertions, 93 deletions
diff --git a/crates/ide_completion/src/completions/keyword.rs b/crates/ide_completion/src/completions/keyword.rs
index 96447a603..e71a04b6e 100644
--- a/crates/ide_completion/src/completions/keyword.rs
+++ b/crates/ide_completion/src/completions/keyword.rs
@@ -48,91 +48,92 @@ pub(crate) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionConte
48 cov_mark::hit!(no_keyword_completion_in_record_lit); 48 cov_mark::hit!(no_keyword_completion_in_record_lit);
49 return; 49 return;
50 } 50 }
51 let mut add_keyword = |kw, snippet| add_keyword(ctx, acc, kw, snippet);
51 52
52 let expects_assoc_item = ctx.expects_assoc_item(); 53 let expects_assoc_item = ctx.expects_assoc_item();
53 let has_block_expr_parent = ctx.has_block_expr_parent(); 54 let has_block_expr_parent = ctx.has_block_expr_parent();
54 let expects_item = ctx.expects_item(); 55 let expects_item = ctx.expects_item();
56
55 if ctx.has_impl_or_trait_prev_sibling() { 57 if ctx.has_impl_or_trait_prev_sibling() {
56 add_keyword(ctx, acc, "where", "where "); 58 // FIXME this also incorrectly shows up after a complete trait/impl
59 add_keyword("where", "where ");
57 return; 60 return;
58 } 61 }
59 if ctx.previous_token_is(T![unsafe]) { 62 if ctx.previous_token_is(T![unsafe]) {
60 if expects_item || has_block_expr_parent { 63 if expects_item || expects_assoc_item || has_block_expr_parent {
61 add_keyword(ctx, acc, "fn", "fn $1($2) {\n $0\n}") 64 add_keyword("fn", "fn $1($2) {\n $0\n}")
62 } 65 }
63 66
64 if expects_item || has_block_expr_parent { 67 if expects_item || has_block_expr_parent {
65 add_keyword(ctx, acc, "trait", "trait $1 {\n $0\n}"); 68 add_keyword("trait", "trait $1 {\n $0\n}");
66 add_keyword(ctx, acc, "impl", "impl $1 {\n $0\n}"); 69 add_keyword("impl", "impl $1 {\n $0\n}");
67 } 70 }
68 71
69 return; 72 return;
70 } 73 }
74
75 if expects_item || ctx.expects_non_trait_assoc_item() || ctx.expect_record_field() {
76 add_keyword("pub(crate)", "pub(crate) ");
77 add_keyword("pub", "pub ");
78 }
79
80 if expects_item || expects_assoc_item || has_block_expr_parent || ctx.is_match_arm {
81 add_keyword("unsafe", "unsafe ");
82 }
83
71 if expects_item || expects_assoc_item || has_block_expr_parent { 84 if expects_item || expects_assoc_item || has_block_expr_parent {
72 add_keyword(ctx, acc, "fn", "fn $1($2) {\n $0\n}"); 85 add_keyword("fn", "fn $1($2) {\n $0\n}");
86 add_keyword("const", "const $0");
87 add_keyword("type", "type $0");
73 } 88 }
89
74 if expects_item || has_block_expr_parent { 90 if expects_item || has_block_expr_parent {
75 add_keyword(ctx, acc, "use", "use "); 91 add_keyword("use", "use $0");
76 add_keyword(ctx, acc, "impl", "impl $1 {\n $0\n}"); 92 add_keyword("impl", "impl $1 {\n $0\n}");
77 add_keyword(ctx, acc, "trait", "trait $1 {\n $0\n}"); 93 add_keyword("trait", "trait $1 {\n $0\n}");
94 add_keyword("static", "static $0");
95 add_keyword("extern", "extern $0");
96 add_keyword("mod", "mod $0");
78 } 97 }
79 98
80 if expects_item { 99 if expects_item {
81 add_keyword(ctx, acc, "enum", "enum $1 {\n $0\n}"); 100 add_keyword("enum", "enum $1 {\n $0\n}");
82 add_keyword(ctx, acc, "struct", "struct $0"); 101 add_keyword("struct", "struct $0");
83 add_keyword(ctx, acc, "union", "union $1 {\n $0\n}"); 102 add_keyword("union", "union $1 {\n $0\n}");
84 } 103 }
85 104
86 if ctx.is_expr { 105 if ctx.expects_expression() {
87 add_keyword(ctx, acc, "match", "match $1 {\n $0\n}"); 106 add_keyword("match", "match $1 {\n $0\n}");
88 add_keyword(ctx, acc, "while", "while $1 {\n $0\n}"); 107 add_keyword("while", "while $1 {\n $0\n}");
89 add_keyword(ctx, acc, "while let", "while let $1 = $2 {\n $0\n}"); 108 add_keyword("while let", "while let $1 = $2 {\n $0\n}");
90 add_keyword(ctx, acc, "loop", "loop {\n $0\n}"); 109 add_keyword("loop", "loop {\n $0\n}");
91 add_keyword(ctx, acc, "if", "if $1 {\n $0\n}"); 110 add_keyword("if", "if $1 {\n $0\n}");
92 add_keyword(ctx, acc, "if let", "if let $1 = $2 {\n $0\n}"); 111 add_keyword("if let", "if let $1 = $2 {\n $0\n}");
93 add_keyword(ctx, acc, "for", "for $1 in $2 {\n $0\n}"); 112 add_keyword("for", "for $1 in $2 {\n $0\n}");
94 } 113 }
95 114
96 if ctx.previous_token_is(T![if]) || ctx.previous_token_is(T![while]) || has_block_expr_parent { 115 if ctx.previous_token_is(T![if]) || ctx.previous_token_is(T![while]) || has_block_expr_parent {
97 add_keyword(ctx, acc, "let", "let "); 116 add_keyword("let", "let ");
98 } 117 }
99 118
100 if ctx.after_if { 119 if ctx.after_if() {
101 add_keyword(ctx, acc, "else", "else {\n $0\n}"); 120 add_keyword("else", "else {\n $0\n}");
102 add_keyword(ctx, acc, "else if", "else if $1 {\n $0\n}"); 121 add_keyword("else if", "else if $1 {\n $0\n}");
103 }
104 if expects_item || has_block_expr_parent {
105 add_keyword(ctx, acc, "mod", "mod $0");
106 } 122 }
123
107 if ctx.expects_ident_pat_or_ref_expr() { 124 if ctx.expects_ident_pat_or_ref_expr() {
108 add_keyword(ctx, acc, "mut", "mut "); 125 add_keyword("mut", "mut ");
109 }
110 if expects_item || expects_assoc_item || has_block_expr_parent {
111 add_keyword(ctx, acc, "const", "const ");
112 add_keyword(ctx, acc, "type", "type ");
113 }
114 if expects_item || has_block_expr_parent {
115 add_keyword(ctx, acc, "static", "static ");
116 };
117 if expects_item || has_block_expr_parent {
118 add_keyword(ctx, acc, "extern", "extern ");
119 }
120 if expects_item || expects_assoc_item || has_block_expr_parent || ctx.is_match_arm {
121 add_keyword(ctx, acc, "unsafe", "unsafe ");
122 } 126 }
127
123 if ctx.in_loop_body { 128 if ctx.in_loop_body {
124 if ctx.can_be_stmt { 129 if ctx.can_be_stmt {
125 add_keyword(ctx, acc, "continue", "continue;"); 130 add_keyword("continue", "continue;");
126 add_keyword(ctx, acc, "break", "break;"); 131 add_keyword("break", "break;");
127 } else { 132 } else {
128 add_keyword(ctx, acc, "continue", "continue"); 133 add_keyword("continue", "continue");
129 add_keyword(ctx, acc, "break", "break"); 134 add_keyword("break", "break");
130 } 135 }
131 } 136 }
132 if expects_item || ctx.expects_non_trait_assoc_item() || ctx.expect_record_field() {
133 add_keyword(ctx, acc, "pub(crate)", "pub(crate) ");
134 add_keyword(ctx, acc, "pub", "pub ");
135 }
136 137
137 if !ctx.is_trivial_path { 138 if !ctx.is_trivial_path {
138 return; 139 return;
@@ -143,8 +144,6 @@ pub(crate) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionConte
143 }; 144 };
144 145
145 add_keyword( 146 add_keyword(
146 ctx,
147 acc,
148 "return", 147 "return",
149 match (ctx.can_be_stmt, fn_def.ret_type().is_some()) { 148 match (ctx.can_be_stmt, fn_def.ret_type().is_some()) {
150 (true, true) => "return $0;", 149 (true, true) => "return $0;",
@@ -161,15 +160,12 @@ fn add_keyword(ctx: &CompletionContext, acc: &mut Completions, kw: &str, snippet
161 160
162 match ctx.config.snippet_cap { 161 match ctx.config.snippet_cap {
163 Some(cap) => { 162 Some(cap) => {
164 let tmp; 163 if snippet.ends_with('}') && ctx.incomplete_let {
165 let snippet = if snippet.ends_with('}') && ctx.incomplete_let {
166 cov_mark::hit!(let_semi); 164 cov_mark::hit!(let_semi);
167 tmp = format!("{};", snippet); 165 item.insert_snippet(cap, format!("{};", snippet));
168 &tmp
169 } else { 166 } else {
170 snippet 167 item.insert_snippet(cap, snippet);
171 }; 168 }
172 item.insert_snippet(cap, snippet);
173 } 169 }
174 None => { 170 None => {
175 item.insert_text(if snippet.contains('$') { kw } else { snippet }); 171 item.insert_text(if snippet.contains('$') { kw } else { snippet });
@@ -232,21 +228,21 @@ mod tests {
232 check( 228 check(
233 r"m$0", 229 r"m$0",
234 expect![[r#" 230 expect![[r#"
231 kw pub(crate)
232 kw pub
233 kw unsafe
235 kw fn 234 kw fn
235 kw const
236 kw type
236 kw use 237 kw use
237 kw impl 238 kw impl
238 kw trait 239 kw trait
240 kw static
241 kw extern
242 kw mod
239 kw enum 243 kw enum
240 kw struct 244 kw struct
241 kw union 245 kw union
242 kw mod
243 kw const
244 kw type
245 kw static
246 kw extern
247 kw unsafe
248 kw pub(crate)
249 kw pub
250 "#]], 246 "#]],
251 ); 247 );
252 } 248 }
@@ -256,10 +252,16 @@ mod tests {
256 check( 252 check(
257 r"fn quux() { $0 }", 253 r"fn quux() { $0 }",
258 expect![[r#" 254 expect![[r#"
255 kw unsafe
259 kw fn 256 kw fn
257 kw const
258 kw type
260 kw use 259 kw use
261 kw impl 260 kw impl
262 kw trait 261 kw trait
262 kw static
263 kw extern
264 kw mod
263 kw match 265 kw match
264 kw while 266 kw while
265 kw while let 267 kw while let
@@ -268,12 +270,6 @@ mod tests {
268 kw if let 270 kw if let
269 kw for 271 kw for
270 kw let 272 kw let
271 kw mod
272 kw const
273 kw type
274 kw static
275 kw extern
276 kw unsafe
277 kw return 273 kw return
278 "#]], 274 "#]],
279 ); 275 );
@@ -284,10 +280,16 @@ mod tests {
284 check( 280 check(
285 r"fn quux() { if true { $0 } }", 281 r"fn quux() { if true { $0 } }",
286 expect![[r#" 282 expect![[r#"
283 kw unsafe
287 kw fn 284 kw fn
285 kw const
286 kw type
288 kw use 287 kw use
289 kw impl 288 kw impl
290 kw trait 289 kw trait
290 kw static
291 kw extern
292 kw mod
291 kw match 293 kw match
292 kw while 294 kw while
293 kw while let 295 kw while let
@@ -296,12 +298,6 @@ mod tests {
296 kw if let 298 kw if let
297 kw for 299 kw for
298 kw let 300 kw let
299 kw mod
300 kw const
301 kw type
302 kw static
303 kw extern
304 kw unsafe
305 kw return 301 kw return
306 "#]], 302 "#]],
307 ); 303 );
@@ -312,10 +308,16 @@ mod tests {
312 check( 308 check(
313 r#"fn quux() { if true { () } $0 }"#, 309 r#"fn quux() { if true { () } $0 }"#,
314 expect![[r#" 310 expect![[r#"
311 kw unsafe
315 kw fn 312 kw fn
313 kw const
314 kw type
316 kw use 315 kw use
317 kw impl 316 kw impl
318 kw trait 317 kw trait
318 kw static
319 kw extern
320 kw mod
319 kw match 321 kw match
320 kw while 322 kw while
321 kw while let 323 kw while let
@@ -326,12 +328,6 @@ mod tests {
326 kw let 328 kw let
327 kw else 329 kw else
328 kw else if 330 kw else if
329 kw mod
330 kw const
331 kw type
332 kw static
333 kw extern
334 kw unsafe
335 kw return 331 kw return
336 "#]], 332 "#]],
337 ); 333 );
@@ -353,6 +349,7 @@ fn quux() -> i32 {
353} 349}
354"#, 350"#,
355 expect![[r#" 351 expect![[r#"
352 kw unsafe
356 kw match 353 kw match
357 kw while 354 kw while
358 kw while let 355 kw while let
@@ -360,7 +357,6 @@ fn quux() -> i32 {
360 kw if 357 kw if
361 kw if let 358 kw if let
362 kw for 359 kw for
363 kw unsafe
364 kw return 360 kw return
365 "#]], 361 "#]],
366 ); 362 );
@@ -371,10 +367,10 @@ fn quux() -> i32 {
371 check( 367 check(
372 r"trait My { $0 }", 368 r"trait My { $0 }",
373 expect![[r#" 369 expect![[r#"
370 kw unsafe
374 kw fn 371 kw fn
375 kw const 372 kw const
376 kw type 373 kw type
377 kw unsafe
378 "#]], 374 "#]],
379 ); 375 );
380 } 376 }
@@ -384,12 +380,27 @@ fn quux() -> i32 {
384 check( 380 check(
385 r"impl My { $0 }", 381 r"impl My { $0 }",
386 expect![[r#" 382 expect![[r#"
383 kw pub(crate)
384 kw pub
385 kw unsafe
387 kw fn 386 kw fn
388 kw const 387 kw const
389 kw type 388 kw type
390 kw unsafe 389 "#]],
390 );
391 }
392
393 #[test]
394 fn test_keywords_in_impl_def_with_attr() {
395 check(
396 r"impl My { #[foo] $0 }",
397 expect![[r#"
391 kw pub(crate) 398 kw pub(crate)
392 kw pub 399 kw pub
400 kw unsafe
401 kw fn
402 kw const
403 kw type
393 "#]], 404 "#]],
394 ); 405 );
395 } 406 }
@@ -399,10 +410,16 @@ fn quux() -> i32 {
399 check( 410 check(
400 r"fn my() { loop { $0 } }", 411 r"fn my() { loop { $0 } }",
401 expect![[r#" 412 expect![[r#"
413 kw unsafe
402 kw fn 414 kw fn
415 kw const
416 kw type
403 kw use 417 kw use
404 kw impl 418 kw impl
405 kw trait 419 kw trait
420 kw static
421 kw extern
422 kw mod
406 kw match 423 kw match
407 kw while 424 kw while
408 kw while let 425 kw while let
@@ -411,12 +428,6 @@ fn quux() -> i32 {
411 kw if let 428 kw if let
412 kw for 429 kw for
413 kw let 430 kw let
414 kw mod
415 kw const
416 kw type
417 kw static
418 kw extern
419 kw unsafe
420 kw continue 431 kw continue
421 kw break 432 kw break
422 kw return 433 kw return