aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_assists/src/handlers/early_return.rs
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2020-05-06 11:52:57 +0100
committerGitHub <[email protected]>2020-05-06 11:52:57 +0100
commit4de3c3eedc1f6576d59e00f0ddde3c70c97be066 (patch)
tree7922dca3f7c4133e2616257be537428337e479d6 /crates/ra_assists/src/handlers/early_return.rs
parentede8906844e206f252810d58533538cf1fb326d4 (diff)
parent233f01c9ba555e5d06f336cb0ff64e7a83e4a23a (diff)
Merge #4341
4341: Move target to AssistLabel r=matklad a=matklad Target is used for assists sorting, so we need it before we compute the action. bors r+ 🤖 Co-authored-by: Aleksey Kladov <[email protected]>
Diffstat (limited to 'crates/ra_assists/src/handlers/early_return.rs')
-rw-r--r--crates/ra_assists/src/handlers/early_return.rs159
1 files changed, 82 insertions, 77 deletions
diff --git a/crates/ra_assists/src/handlers/early_return.rs b/crates/ra_assists/src/handlers/early_return.rs
index 55ccc37b0..4bd6040b2 100644
--- a/crates/ra_assists/src/handlers/early_return.rs
+++ b/crates/ra_assists/src/handlers/early_return.rs
@@ -95,89 +95,94 @@ pub(crate) fn convert_to_guarded_return(ctx: AssistCtx) -> Option<Assist> {
95 then_block.syntax().last_child_or_token().filter(|t| t.kind() == R_CURLY)?; 95 then_block.syntax().last_child_or_token().filter(|t| t.kind() == R_CURLY)?;
96 let cursor_position = ctx.frange.range.start(); 96 let cursor_position = ctx.frange.range.start();
97 97
98 ctx.add_assist(AssistId("convert_to_guarded_return"), "Convert to guarded return", |edit| { 98 let target = if_expr.syntax().text_range();
99 let if_indent_level = IndentLevel::from_node(&if_expr.syntax()); 99 ctx.add_assist(
100 let new_block = match if_let_pat { 100 AssistId("convert_to_guarded_return"),
101 None => { 101 "Convert to guarded return",
102 // If. 102 target,
103 let new_expr = { 103 |edit| {
104 let then_branch = 104 let if_indent_level = IndentLevel::from_node(&if_expr.syntax());
105 make::block_expr(once(make::expr_stmt(early_expression).into()), None); 105 let new_block = match if_let_pat {
106 let cond = invert_boolean_expression(cond_expr); 106 None => {
107 let e = make::expr_if(make::condition(cond, None), then_branch); 107 // If.
108 if_indent_level.increase_indent(e) 108 let new_expr = {
109 }; 109 let then_branch =
110 replace(new_expr.syntax(), &then_block, &parent_block, &if_expr) 110 make::block_expr(once(make::expr_stmt(early_expression).into()), None);
111 } 111 let cond = invert_boolean_expression(cond_expr);
112 Some((path, bound_ident)) => { 112 let e = make::expr_if(make::condition(cond, None), then_branch);
113 // If-let. 113 if_indent_level.increase_indent(e)
114 let match_expr = {
115 let happy_arm = {
116 let pat = make::tuple_struct_pat(
117 path,
118 once(make::bind_pat(make::name("it")).into()),
119 );
120 let expr = {
121 let name_ref = make::name_ref("it");
122 let segment = make::path_segment(name_ref);
123 let path = make::path_unqualified(segment);
124 make::expr_path(path)
125 };
126 make::match_arm(once(pat.into()), expr)
127 }; 114 };
115 replace(new_expr.syntax(), &then_block, &parent_block, &if_expr)
116 }
117 Some((path, bound_ident)) => {
118 // If-let.
119 let match_expr = {
120 let happy_arm = {
121 let pat = make::tuple_struct_pat(
122 path,
123 once(make::bind_pat(make::name("it")).into()),
124 );
125 let expr = {
126 let name_ref = make::name_ref("it");
127 let segment = make::path_segment(name_ref);
128 let path = make::path_unqualified(segment);
129 make::expr_path(path)
130 };
131 make::match_arm(once(pat.into()), expr)
132 };
128 133
129 let sad_arm = make::match_arm( 134 let sad_arm = make::match_arm(
130 // FIXME: would be cool to use `None` or `Err(_)` if appropriate 135 // FIXME: would be cool to use `None` or `Err(_)` if appropriate
131 once(make::placeholder_pat().into()), 136 once(make::placeholder_pat().into()),
132 early_expression, 137 early_expression,
133 ); 138 );
134 139
135 make::expr_match(cond_expr, make::match_arm_list(vec![happy_arm, sad_arm])) 140 make::expr_match(cond_expr, make::match_arm_list(vec![happy_arm, sad_arm]))
136 }; 141 };
137 142
138 let let_stmt = make::let_stmt( 143 let let_stmt = make::let_stmt(
139 make::bind_pat(make::name(&bound_ident.syntax().to_string())).into(), 144 make::bind_pat(make::name(&bound_ident.syntax().to_string())).into(),
140 Some(match_expr), 145 Some(match_expr),
146 );
147 let let_stmt = if_indent_level.increase_indent(let_stmt);
148 replace(let_stmt.syntax(), &then_block, &parent_block, &if_expr)
149 }
150 };
151 edit.replace_ast(parent_block, ast::BlockExpr::cast(new_block).unwrap());
152 edit.set_cursor(cursor_position);
153
154 fn replace(
155 new_expr: &SyntaxNode,
156 then_block: &ast::BlockExpr,
157 parent_block: &ast::BlockExpr,
158 if_expr: &ast::IfExpr,
159 ) -> SyntaxNode {
160 let then_block_items = IndentLevel::from(1).decrease_indent(then_block.clone());
161 let end_of_then = then_block_items.syntax().last_child_or_token().unwrap();
162 let end_of_then =
163 if end_of_then.prev_sibling_or_token().map(|n| n.kind()) == Some(WHITESPACE) {
164 end_of_then.prev_sibling_or_token().unwrap()
165 } else {
166 end_of_then
167 };
168 let mut then_statements = new_expr.children_with_tokens().chain(
169 then_block_items
170 .syntax()
171 .children_with_tokens()
172 .skip(1)
173 .take_while(|i| *i != end_of_then),
141 ); 174 );
142 let let_stmt = if_indent_level.increase_indent(let_stmt); 175 replace_children(
143 replace(let_stmt.syntax(), &then_block, &parent_block, &if_expr) 176 &parent_block.syntax(),
177 RangeInclusive::new(
178 if_expr.clone().syntax().clone().into(),
179 if_expr.syntax().clone().into(),
180 ),
181 &mut then_statements,
182 )
144 } 183 }
145 }; 184 },
146 edit.target(if_expr.syntax().text_range()); 185 )
147 edit.replace_ast(parent_block, ast::BlockExpr::cast(new_block).unwrap());
148 edit.set_cursor(cursor_position);
149
150 fn replace(
151 new_expr: &SyntaxNode,
152 then_block: &ast::BlockExpr,
153 parent_block: &ast::BlockExpr,
154 if_expr: &ast::IfExpr,
155 ) -> SyntaxNode {
156 let then_block_items = IndentLevel::from(1).decrease_indent(then_block.clone());
157 let end_of_then = then_block_items.syntax().last_child_or_token().unwrap();
158 let end_of_then =
159 if end_of_then.prev_sibling_or_token().map(|n| n.kind()) == Some(WHITESPACE) {
160 end_of_then.prev_sibling_or_token().unwrap()
161 } else {
162 end_of_then
163 };
164 let mut then_statements = new_expr.children_with_tokens().chain(
165 then_block_items
166 .syntax()
167 .children_with_tokens()
168 .skip(1)
169 .take_while(|i| *i != end_of_then),
170 );
171 replace_children(
172 &parent_block.syntax(),
173 RangeInclusive::new(
174 if_expr.clone().syntax().clone().into(),
175 if_expr.syntax().clone().into(),
176 ),
177 &mut then_statements,
178 )
179 }
180 })
181} 186}
182 187
183#[cfg(test)] 188#[cfg(test)]