Skip to content

Commit 6203e9c

Browse files
committed
add if let and while let postfix for Option and Result #4348
Signed-off-by: Benjamin Coenen <5719034+bnjjj@users.noreply.github.com>
1 parent 9cb5596 commit 6203e9c

File tree

2 files changed

+221
-1
lines changed

2 files changed

+221
-1
lines changed

crates/ra_hir/src/code_model.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1083,6 +1083,28 @@ impl Type {
10831083
matches!(self.ty.value, Ty::Apply(ApplicationTy { ctor: TypeCtor::Bool, .. }))
10841084
}
10851085

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+
10861108
pub fn is_mutable_reference(&self) -> bool {
10871109
matches!(
10881110
self.ty.value,

crates/ra_ide/src/completion/complete_postfix.rs

Lines changed: 199 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,47 @@ pub(super) fn complete_postfix(acc: &mut Completions, ctx: &CompletionContext) {
3838
None => return,
3939
};
4040

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() {
4282
postfix_snippet(
4383
ctx,
4484
cap,
@@ -235,6 +275,164 @@ mod tests {
235275
);
236276
}
237277

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+
238436
#[test]
239437
fn some_postfix_completions_ignored() {
240438
assert_debug_snapshot!(

0 commit comments

Comments
 (0)