add if let and while let postfix for Option and Result #4348

Signed-off-by: Benjamin Coenen <5719034+bnjjj@users.noreply.github.com>
This commit is contained in:
Benjamin Coenen 2020-05-07 11:23:38 +02:00
parent 9cb55966fe
commit 6203e9c4fa
2 changed files with 221 additions and 1 deletions

View File

@ -1083,6 +1083,28 @@ impl Type {
matches!(self.ty.value, Ty::Apply(ApplicationTy { ctor: TypeCtor::Bool, .. }))
}
pub fn is_option(&self, db: &dyn HirDatabase) -> bool {
if let Some(adt_ty) = self.as_adt() {
if let Adt::Enum(_) = adt_ty {
if self.display(db).to_string().starts_with("Option<") {
return true;
}
}
}
false
}
pub fn is_result(&self, db: &dyn HirDatabase) -> bool {
if let Some(adt_ty) = self.as_adt() {
if let Adt::Enum(_) = adt_ty {
if self.display(db).to_string().starts_with("Result<") {
return true;
}
}
}
false
}
pub fn is_mutable_reference(&self) -> bool {
matches!(
self.ty.value,

View File

@ -38,7 +38,47 @@ pub(super) fn complete_postfix(acc: &mut Completions, ctx: &CompletionContext) {
None => return,
};
if receiver_ty.is_bool() || receiver_ty.is_unknown() {
if receiver_ty.is_option(ctx.db) {
postfix_snippet(
ctx,
cap,
&dot_receiver,
"ifl",
"if let Some {}",
&format!("if let Some($1) = {} {{\n $0\n}}", receiver_text),
)
.add_to(acc);
postfix_snippet(
ctx,
cap,
&dot_receiver,
"while",
"while let Some {}",
&format!("while let Some($1) = {} {{\n $0\n}}", receiver_text),
)
.add_to(acc);
} else if receiver_ty.is_result(ctx.db) {
postfix_snippet(
ctx,
cap,
&dot_receiver,
"ifl",
"if let Ok {}",
&format!("if let Ok($1) = {} {{\n $0\n}}", receiver_text),
)
.add_to(acc);
postfix_snippet(
ctx,
cap,
&dot_receiver,
"while",
"while let Ok {}",
&format!("while let Ok($1) = {} {{\n $0\n}}", receiver_text),
)
.add_to(acc);
} else if receiver_ty.is_bool() || receiver_ty.is_unknown() {
postfix_snippet(
ctx,
cap,
@ -235,6 +275,164 @@ mod tests {
);
}
#[test]
fn postfix_completion_works_for_option() {
assert_debug_snapshot!(
do_postfix_completion(
r#"
enum Option<T> {
Some(T),
None,
}
fn main() {
let bar = Option::Some(true);
bar.<|>
}
"#,
),
@r###"
[
CompletionItem {
label: "box",
source_range: 210..210,
delete: 206..210,
insert: "Box::new(bar)",
detail: "Box::new(expr)",
},
CompletionItem {
label: "dbg",
source_range: 210..210,
delete: 206..210,
insert: "dbg!(bar)",
detail: "dbg!(expr)",
},
CompletionItem {
label: "ifl",
source_range: 210..210,
delete: 206..210,
insert: "if let Some($1) = bar {\n $0\n}",
detail: "if let Some {}",
},
CompletionItem {
label: "match",
source_range: 210..210,
delete: 206..210,
insert: "match bar {\n ${1:_} => {$0\\},\n}",
detail: "match expr {}",
},
CompletionItem {
label: "not",
source_range: 210..210,
delete: 206..210,
insert: "!bar",
detail: "!expr",
},
CompletionItem {
label: "ref",
source_range: 210..210,
delete: 206..210,
insert: "&bar",
detail: "&expr",
},
CompletionItem {
label: "refm",
source_range: 210..210,
delete: 206..210,
insert: "&mut bar",
detail: "&mut expr",
},
CompletionItem {
label: "while",
source_range: 210..210,
delete: 206..210,
insert: "while let Some($1) = bar {\n $0\n}",
detail: "while let Some {}",
},
]
"###
);
}
#[test]
fn postfix_completion_works_for_result() {
assert_debug_snapshot!(
do_postfix_completion(
r#"
enum Result<T, E> {
Ok(T),
Err(E),
}
fn main() {
let bar = Result::Ok(true);
bar.<|>
}
"#,
),
@r###"
[
CompletionItem {
label: "box",
source_range: 211..211,
delete: 207..211,
insert: "Box::new(bar)",
detail: "Box::new(expr)",
},
CompletionItem {
label: "dbg",
source_range: 211..211,
delete: 207..211,
insert: "dbg!(bar)",
detail: "dbg!(expr)",
},
CompletionItem {
label: "ifl",
source_range: 211..211,
delete: 207..211,
insert: "if let Ok($1) = bar {\n $0\n}",
detail: "if let Ok {}",
},
CompletionItem {
label: "match",
source_range: 211..211,
delete: 207..211,
insert: "match bar {\n ${1:_} => {$0\\},\n}",
detail: "match expr {}",
},
CompletionItem {
label: "not",
source_range: 211..211,
delete: 207..211,
insert: "!bar",
detail: "!expr",
},
CompletionItem {
label: "ref",
source_range: 211..211,
delete: 207..211,
insert: "&bar",
detail: "&expr",
},
CompletionItem {
label: "refm",
source_range: 211..211,
delete: 207..211,
insert: "&mut bar",
detail: "&mut expr",
},
CompletionItem {
label: "while",
source_range: 211..211,
delete: 207..211,
insert: "while let Ok($1) = bar {\n $0\n}",
detail: "while let Ok {}",
},
]
"###
);
}
#[test]
fn some_postfix_completions_ignored() {
assert_debug_snapshot!(