diff options
author | Dmitry <[email protected]> | 2020-08-14 19:32:05 +0100 |
---|---|---|
committer | Dmitry <[email protected]> | 2020-08-14 19:32:05 +0100 |
commit | 178c3e135a2a249692f7784712492e7884ae0c00 (patch) | |
tree | ac6b769dbf7162150caa0c1624786a4dd79ff3be /crates/assists/src/handlers/replace_let_with_if_let.rs | |
parent | 06ff8e6c760ff05f10e868b5d1f9d79e42fbb49c (diff) | |
parent | c2594daf2974dbd4ce3d9b7ec72481764abaceb5 (diff) |
Merge remote-tracking branch 'origin/master'
Diffstat (limited to 'crates/assists/src/handlers/replace_let_with_if_let.rs')
-rw-r--r-- | crates/assists/src/handlers/replace_let_with_if_let.rs | 100 |
1 files changed, 100 insertions, 0 deletions
diff --git a/crates/assists/src/handlers/replace_let_with_if_let.rs b/crates/assists/src/handlers/replace_let_with_if_let.rs new file mode 100644 index 000000000..ed6d0c29b --- /dev/null +++ b/crates/assists/src/handlers/replace_let_with_if_let.rs | |||
@@ -0,0 +1,100 @@ | |||
1 | use std::iter::once; | ||
2 | |||
3 | use syntax::{ | ||
4 | ast::{ | ||
5 | self, | ||
6 | edit::{AstNodeEdit, IndentLevel}, | ||
7 | make, | ||
8 | }, | ||
9 | AstNode, T, | ||
10 | }; | ||
11 | |||
12 | use crate::{utils::TryEnum, AssistContext, AssistId, AssistKind, Assists}; | ||
13 | |||
14 | // Assist: replace_let_with_if_let | ||
15 | // | ||
16 | // Replaces `let` with an `if-let`. | ||
17 | // | ||
18 | // ``` | ||
19 | // # enum Option<T> { Some(T), None } | ||
20 | // | ||
21 | // fn main(action: Action) { | ||
22 | // <|>let x = compute(); | ||
23 | // } | ||
24 | // | ||
25 | // fn compute() -> Option<i32> { None } | ||
26 | // ``` | ||
27 | // -> | ||
28 | // ``` | ||
29 | // # enum Option<T> { Some(T), None } | ||
30 | // | ||
31 | // fn main(action: Action) { | ||
32 | // if let Some(x) = compute() { | ||
33 | // } | ||
34 | // } | ||
35 | // | ||
36 | // fn compute() -> Option<i32> { None } | ||
37 | // ``` | ||
38 | pub(crate) fn replace_let_with_if_let(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { | ||
39 | let let_kw = ctx.find_token_at_offset(T![let])?; | ||
40 | let let_stmt = let_kw.ancestors().find_map(ast::LetStmt::cast)?; | ||
41 | let init = let_stmt.initializer()?; | ||
42 | let original_pat = let_stmt.pat()?; | ||
43 | let ty = ctx.sema.type_of_expr(&init)?; | ||
44 | let happy_variant = TryEnum::from_ty(&ctx.sema, &ty).map(|it| it.happy_case()); | ||
45 | |||
46 | let target = let_kw.text_range(); | ||
47 | acc.add( | ||
48 | AssistId("replace_let_with_if_let", AssistKind::RefactorRewrite), | ||
49 | "Replace with if-let", | ||
50 | target, | ||
51 | |edit| { | ||
52 | let with_placeholder: ast::Pat = match happy_variant { | ||
53 | None => make::wildcard_pat().into(), | ||
54 | Some(var_name) => make::tuple_struct_pat( | ||
55 | make::path_unqualified(make::path_segment(make::name_ref(var_name))), | ||
56 | once(make::wildcard_pat().into()), | ||
57 | ) | ||
58 | .into(), | ||
59 | }; | ||
60 | let block = | ||
61 | make::block_expr(None, None).indent(IndentLevel::from_node(let_stmt.syntax())); | ||
62 | let if_ = make::expr_if(make::condition(init, Some(with_placeholder)), block); | ||
63 | let stmt = make::expr_stmt(if_); | ||
64 | |||
65 | let placeholder = stmt.syntax().descendants().find_map(ast::WildcardPat::cast).unwrap(); | ||
66 | let stmt = stmt.replace_descendant(placeholder.into(), original_pat); | ||
67 | |||
68 | edit.replace_ast(ast::Stmt::from(let_stmt), ast::Stmt::from(stmt)); | ||
69 | }, | ||
70 | ) | ||
71 | } | ||
72 | |||
73 | #[cfg(test)] | ||
74 | mod tests { | ||
75 | use crate::tests::check_assist; | ||
76 | |||
77 | use super::*; | ||
78 | |||
79 | #[test] | ||
80 | fn replace_let_unknown_enum() { | ||
81 | check_assist( | ||
82 | replace_let_with_if_let, | ||
83 | r" | ||
84 | enum E<T> { X(T), Y(T) } | ||
85 | |||
86 | fn main() { | ||
87 | <|>let x = E::X(92); | ||
88 | } | ||
89 | ", | ||
90 | r" | ||
91 | enum E<T> { X(T), Y(T) } | ||
92 | |||
93 | fn main() { | ||
94 | if let x = E::X(92) { | ||
95 | } | ||
96 | } | ||
97 | ", | ||
98 | ) | ||
99 | } | ||
100 | } | ||