diff options
Diffstat (limited to 'crates')
-rw-r--r-- | crates/ra_hir/src/code_model.rs | 22 | ||||
-rw-r--r-- | crates/ra_ide/src/completion/complete_postfix.rs | 200 |
2 files changed, 221 insertions, 1 deletions
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index 5f480c304..7e840add5 100644 --- a/crates/ra_hir/src/code_model.rs +++ b/crates/ra_hir/src/code_model.rs | |||
@@ -1083,6 +1083,28 @@ impl Type { | |||
1083 | matches!(self.ty.value, Ty::Apply(ApplicationTy { ctor: TypeCtor::Bool, .. })) | 1083 | matches!(self.ty.value, Ty::Apply(ApplicationTy { ctor: TypeCtor::Bool, .. })) |
1084 | } | 1084 | } |
1085 | 1085 | ||
1086 | pub fn is_option(&self, db: &dyn HirDatabase) -> bool { | ||
1087 | if let Some(adt_ty) = self.as_adt() { | ||
1088 | if let Adt::Enum(_) = adt_ty { | ||
1089 | if self.display(db).to_string().starts_with("Option<") { | ||
1090 | return true; | ||
1091 | } | ||
1092 | } | ||
1093 | } | ||
1094 | false | ||
1095 | } | ||
1096 | |||
1097 | pub fn is_result(&self, db: &dyn HirDatabase) -> bool { | ||
1098 | if let Some(adt_ty) = self.as_adt() { | ||
1099 | if let Adt::Enum(_) = adt_ty { | ||
1100 | if self.display(db).to_string().starts_with("Result<") { | ||
1101 | return true; | ||
1102 | } | ||
1103 | } | ||
1104 | } | ||
1105 | false | ||
1106 | } | ||
1107 | |||
1086 | pub fn is_mutable_reference(&self) -> bool { | 1108 | pub fn is_mutable_reference(&self) -> bool { |
1087 | matches!( | 1109 | matches!( |
1088 | self.ty.value, | 1110 | self.ty.value, |
diff --git a/crates/ra_ide/src/completion/complete_postfix.rs b/crates/ra_ide/src/completion/complete_postfix.rs index 6a0f0c72e..dc32bbee2 100644 --- a/crates/ra_ide/src/completion/complete_postfix.rs +++ b/crates/ra_ide/src/completion/complete_postfix.rs | |||
@@ -38,7 +38,47 @@ pub(super) fn complete_postfix(acc: &mut Completions, ctx: &CompletionContext) { | |||
38 | None => return, | 38 | None => return, |
39 | }; | 39 | }; |
40 | 40 | ||
41 | if receiver_ty.is_bool() || receiver_ty.is_unknown() { | 41 | if receiver_ty.is_option(ctx.db) { |
42 | postfix_snippet( | ||
43 | ctx, | ||
44 | cap, | ||
45 | &dot_receiver, | ||
46 | "ifl", | ||
47 | "if let Some {}", | ||
48 | &format!("if let Some($1) = {} {{\n $0\n}}", receiver_text), | ||
49 | ) | ||
50 | .add_to(acc); | ||
51 | |||
52 | postfix_snippet( | ||
53 | ctx, | ||
54 | cap, | ||
55 | &dot_receiver, | ||
56 | "while", | ||
57 | "while let Some {}", | ||
58 | &format!("while let Some($1) = {} {{\n $0\n}}", receiver_text), | ||
59 | ) | ||
60 | .add_to(acc); | ||
61 | } else if receiver_ty.is_result(ctx.db) { | ||
62 | postfix_snippet( | ||
63 | ctx, | ||
64 | cap, | ||
65 | &dot_receiver, | ||
66 | "ifl", | ||
67 | "if let Ok {}", | ||
68 | &format!("if let Ok($1) = {} {{\n $0\n}}", receiver_text), | ||
69 | ) | ||
70 | .add_to(acc); | ||
71 | |||
72 | postfix_snippet( | ||
73 | ctx, | ||
74 | cap, | ||
75 | &dot_receiver, | ||
76 | "while", | ||
77 | "while let Ok {}", | ||
78 | &format!("while let Ok($1) = {} {{\n $0\n}}", receiver_text), | ||
79 | ) | ||
80 | .add_to(acc); | ||
81 | } else if receiver_ty.is_bool() || receiver_ty.is_unknown() { | ||
42 | postfix_snippet( | 82 | postfix_snippet( |
43 | ctx, | 83 | ctx, |
44 | cap, | 84 | cap, |
@@ -236,6 +276,164 @@ mod tests { | |||
236 | } | 276 | } |
237 | 277 | ||
238 | #[test] | 278 | #[test] |
279 | fn postfix_completion_works_for_option() { | ||
280 | assert_debug_snapshot!( | ||
281 | do_postfix_completion( | ||
282 | r#" | ||
283 | enum Option<T> { | ||
284 | Some(T), | ||
285 | None, | ||
286 | } | ||
287 | |||
288 | fn main() { | ||
289 | let bar = Option::Some(true); | ||
290 | bar.<|> | ||
291 | } | ||
292 | "#, | ||
293 | ), | ||
294 | @r###" | ||
295 | [ | ||
296 | CompletionItem { | ||
297 | label: "box", | ||
298 | source_range: 210..210, | ||
299 | delete: 206..210, | ||
300 | insert: "Box::new(bar)", | ||
301 | detail: "Box::new(expr)", | ||
302 | }, | ||
303 | CompletionItem { | ||
304 | label: "dbg", | ||
305 | source_range: 210..210, | ||
306 | delete: 206..210, | ||
307 | insert: "dbg!(bar)", | ||
308 | detail: "dbg!(expr)", | ||
309 | }, | ||
310 | CompletionItem { | ||
311 | label: "ifl", | ||
312 | source_range: 210..210, | ||
313 | delete: 206..210, | ||
314 | insert: "if let Some($1) = bar {\n $0\n}", | ||
315 | detail: "if let Some {}", | ||
316 | }, | ||
317 | CompletionItem { | ||
318 | label: "match", | ||
319 | source_range: 210..210, | ||
320 | delete: 206..210, | ||
321 | insert: "match bar {\n ${1:_} => {$0\\},\n}", | ||
322 | detail: "match expr {}", | ||
323 | }, | ||
324 | CompletionItem { | ||
325 | label: "not", | ||
326 | source_range: 210..210, | ||
327 | delete: 206..210, | ||
328 | insert: "!bar", | ||
329 | detail: "!expr", | ||
330 | }, | ||
331 | CompletionItem { | ||
332 | label: "ref", | ||
333 | source_range: 210..210, | ||
334 | delete: 206..210, | ||
335 | insert: "&bar", | ||
336 | detail: "&expr", | ||
337 | }, | ||
338 | CompletionItem { | ||
339 | label: "refm", | ||
340 | source_range: 210..210, | ||
341 | delete: 206..210, | ||
342 | insert: "&mut bar", | ||
343 | detail: "&mut expr", | ||
344 | }, | ||
345 | CompletionItem { | ||
346 | label: "while", | ||
347 | source_range: 210..210, | ||
348 | delete: 206..210, | ||
349 | insert: "while let Some($1) = bar {\n $0\n}", | ||
350 | detail: "while let Some {}", | ||
351 | }, | ||
352 | ] | ||
353 | "### | ||
354 | ); | ||
355 | } | ||
356 | |||
357 | #[test] | ||
358 | fn postfix_completion_works_for_result() { | ||
359 | assert_debug_snapshot!( | ||
360 | do_postfix_completion( | ||
361 | r#" | ||
362 | enum Result<T, E> { | ||
363 | Ok(T), | ||
364 | Err(E), | ||
365 | } | ||
366 | |||
367 | fn main() { | ||
368 | let bar = Result::Ok(true); | ||
369 | bar.<|> | ||
370 | } | ||
371 | "#, | ||
372 | ), | ||
373 | @r###" | ||
374 | [ | ||
375 | CompletionItem { | ||
376 | label: "box", | ||
377 | source_range: 211..211, | ||
378 | delete: 207..211, | ||
379 | insert: "Box::new(bar)", | ||
380 | detail: "Box::new(expr)", | ||
381 | }, | ||
382 | CompletionItem { | ||
383 | label: "dbg", | ||
384 | source_range: 211..211, | ||
385 | delete: 207..211, | ||
386 | insert: "dbg!(bar)", | ||
387 | detail: "dbg!(expr)", | ||
388 | }, | ||
389 | CompletionItem { | ||
390 | label: "ifl", | ||
391 | source_range: 211..211, | ||
392 | delete: 207..211, | ||
393 | insert: "if let Ok($1) = bar {\n $0\n}", | ||
394 | detail: "if let Ok {}", | ||
395 | }, | ||
396 | CompletionItem { | ||
397 | label: "match", | ||
398 | source_range: 211..211, | ||
399 | delete: 207..211, | ||
400 | insert: "match bar {\n ${1:_} => {$0\\},\n}", | ||
401 | detail: "match expr {}", | ||
402 | }, | ||
403 | CompletionItem { | ||
404 | label: "not", | ||
405 | source_range: 211..211, | ||
406 | delete: 207..211, | ||
407 | insert: "!bar", | ||
408 | detail: "!expr", | ||
409 | }, | ||
410 | CompletionItem { | ||
411 | label: "ref", | ||
412 | source_range: 211..211, | ||
413 | delete: 207..211, | ||
414 | insert: "&bar", | ||
415 | detail: "&expr", | ||
416 | }, | ||
417 | CompletionItem { | ||
418 | label: "refm", | ||
419 | source_range: 211..211, | ||
420 | delete: 207..211, | ||
421 | insert: "&mut bar", | ||
422 | detail: "&mut expr", | ||
423 | }, | ||
424 | CompletionItem { | ||
425 | label: "while", | ||
426 | source_range: 211..211, | ||
427 | delete: 207..211, | ||
428 | insert: "while let Ok($1) = bar {\n $0\n}", | ||
429 | detail: "while let Ok {}", | ||
430 | }, | ||
431 | ] | ||
432 | "### | ||
433 | ); | ||
434 | } | ||
435 | |||
436 | #[test] | ||
239 | fn some_postfix_completions_ignored() { | 437 | fn some_postfix_completions_ignored() { |
240 | assert_debug_snapshot!( | 438 | assert_debug_snapshot!( |
241 | do_postfix_completion( | 439 | do_postfix_completion( |