diff options
Diffstat (limited to 'crates')
4 files changed, 141 insertions, 8 deletions
diff --git a/crates/assists/src/handlers/move_guard.rs b/crates/assists/src/handlers/move_guard.rs index 452115fe6..e1855b63d 100644 --- a/crates/assists/src/handlers/move_guard.rs +++ b/crates/assists/src/handlers/move_guard.rs | |||
@@ -1,5 +1,5 @@ | |||
1 | use syntax::{ | 1 | use syntax::{ |
2 | ast::{edit::AstNodeEdit, make, AstNode, IfExpr, MatchArm}, | 2 | ast::{edit::AstNodeEdit, make, AstNode, BlockExpr, Expr, IfExpr, MatchArm}, |
3 | SyntaxKind::WHITESPACE, | 3 | SyntaxKind::WHITESPACE, |
4 | }; | 4 | }; |
5 | 5 | ||
@@ -92,9 +92,20 @@ pub(crate) fn move_guard_to_arm_body(acc: &mut Assists, ctx: &AssistContext) -> | |||
92 | pub(crate) fn move_arm_cond_to_match_guard(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { | 92 | pub(crate) fn move_arm_cond_to_match_guard(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { |
93 | let match_arm: MatchArm = ctx.find_node_at_offset::<MatchArm>()?; | 93 | let match_arm: MatchArm = ctx.find_node_at_offset::<MatchArm>()?; |
94 | let match_pat = match_arm.pat()?; | 94 | let match_pat = match_arm.pat()?; |
95 | |||
96 | let arm_body = match_arm.expr()?; | 95 | let arm_body = match_arm.expr()?; |
97 | let if_expr: IfExpr = IfExpr::cast(arm_body.syntax().clone())?; | 96 | |
97 | let mut replace_node = None; | ||
98 | let if_expr: IfExpr = IfExpr::cast(arm_body.syntax().clone()).or_else(|| { | ||
99 | let block_expr = BlockExpr::cast(arm_body.syntax().clone())?; | ||
100 | if let Expr::IfExpr(e) = block_expr.expr()? { | ||
101 | replace_node = Some(block_expr.syntax().clone()); | ||
102 | Some(e) | ||
103 | } else { | ||
104 | None | ||
105 | } | ||
106 | })?; | ||
107 | let replace_node = replace_node.unwrap_or_else(|| if_expr.syntax().clone()); | ||
108 | |||
98 | let cond = if_expr.condition()?; | 109 | let cond = if_expr.condition()?; |
99 | let then_block = if_expr.then_branch()?; | 110 | let then_block = if_expr.then_branch()?; |
100 | 111 | ||
@@ -109,19 +120,23 @@ pub(crate) fn move_arm_cond_to_match_guard(acc: &mut Assists, ctx: &AssistContex | |||
109 | 120 | ||
110 | let buf = format!(" if {}", cond.syntax().text()); | 121 | let buf = format!(" if {}", cond.syntax().text()); |
111 | 122 | ||
112 | let target = if_expr.syntax().text_range(); | ||
113 | acc.add( | 123 | acc.add( |
114 | AssistId("move_arm_cond_to_match_guard", AssistKind::RefactorRewrite), | 124 | AssistId("move_arm_cond_to_match_guard", AssistKind::RefactorRewrite), |
115 | "Move condition to match guard", | 125 | "Move condition to match guard", |
116 | target, | 126 | replace_node.text_range(), |
117 | |edit| { | 127 | |edit| { |
118 | let then_only_expr = then_block.statements().next().is_none(); | 128 | let then_only_expr = then_block.statements().next().is_none(); |
119 | 129 | ||
120 | match &then_block.expr() { | 130 | match &then_block.expr() { |
121 | Some(then_expr) if then_only_expr => { | 131 | Some(then_expr) if then_only_expr => { |
122 | edit.replace(if_expr.syntax().text_range(), then_expr.syntax().text()) | 132 | edit.replace(replace_node.text_range(), then_expr.syntax().text()) |
123 | } | 133 | } |
124 | _ => edit.replace(if_expr.syntax().text_range(), then_block.syntax().text()), | 134 | _ if replace_node != *if_expr.syntax() => { |
135 | // Dedent because if_expr is in a BlockExpr | ||
136 | let replace_with = then_block.dedent(1.into()).syntax().text(); | ||
137 | edit.replace(replace_node.text_range(), replace_with) | ||
138 | } | ||
139 | _ => edit.replace(replace_node.text_range(), then_block.syntax().text()), | ||
125 | } | 140 | } |
126 | 141 | ||
127 | edit.insert(match_pat.syntax().text_range().end(), buf); | 142 | edit.insert(match_pat.syntax().text_range().end(), buf); |
@@ -225,6 +240,33 @@ fn main() { | |||
225 | } | 240 | } |
226 | 241 | ||
227 | #[test] | 242 | #[test] |
243 | fn move_arm_cond_in_block_to_match_guard_works() { | ||
244 | check_assist( | ||
245 | move_arm_cond_to_match_guard, | ||
246 | r#" | ||
247 | fn main() { | ||
248 | match 92 { | ||
249 | x => { | ||
250 | <|>if x > 10 { | ||
251 | false | ||
252 | } | ||
253 | }, | ||
254 | _ => true | ||
255 | } | ||
256 | } | ||
257 | "#, | ||
258 | r#" | ||
259 | fn main() { | ||
260 | match 92 { | ||
261 | x if x > 10 => false, | ||
262 | _ => true | ||
263 | } | ||
264 | } | ||
265 | "#, | ||
266 | ); | ||
267 | } | ||
268 | |||
269 | #[test] | ||
228 | fn move_arm_cond_to_match_guard_if_let_not_works() { | 270 | fn move_arm_cond_to_match_guard_if_let_not_works() { |
229 | check_assist_not_applicable( | 271 | check_assist_not_applicable( |
230 | move_arm_cond_to_match_guard, | 272 | move_arm_cond_to_match_guard, |
@@ -290,4 +332,35 @@ fn main() { | |||
290 | "#, | 332 | "#, |
291 | ); | 333 | ); |
292 | } | 334 | } |
335 | |||
336 | #[test] | ||
337 | fn move_arm_cond_in_block_to_match_guard_if_multiline_body_works() { | ||
338 | check_assist( | ||
339 | move_arm_cond_to_match_guard, | ||
340 | r#" | ||
341 | fn main() { | ||
342 | match 92 { | ||
343 | x => { | ||
344 | if x > 10 { | ||
345 | 92;<|> | ||
346 | false | ||
347 | } | ||
348 | } | ||
349 | _ => true | ||
350 | } | ||
351 | } | ||
352 | "#, | ||
353 | r#" | ||
354 | fn main() { | ||
355 | match 92 { | ||
356 | x if x > 10 => { | ||
357 | 92; | ||
358 | false | ||
359 | } | ||
360 | _ => true | ||
361 | } | ||
362 | } | ||
363 | "#, | ||
364 | ) | ||
365 | } | ||
293 | } | 366 | } |
diff --git a/crates/parser/src/grammar.rs b/crates/parser/src/grammar.rs index 562e92252..4ab206a83 100644 --- a/crates/parser/src/grammar.rs +++ b/crates/parser/src/grammar.rs | |||
@@ -184,7 +184,11 @@ fn opt_visibility(p: &mut Parser) -> bool { | |||
184 | // pub(self) struct S; | 184 | // pub(self) struct S; |
185 | // pub(self) struct S; | 185 | // pub(self) struct S; |
186 | // pub(self) struct S; | 186 | // pub(self) struct S; |
187 | T![crate] | T![self] | T![super] => { | 187 | |
188 | // test pub_parens_typepath | ||
189 | // struct B(pub (super::A)); | ||
190 | // struct B(pub (crate::A,)); | ||
191 | T![crate] | T![self] | T![super] if p.nth(2) != T![:] => { | ||
188 | p.bump_any(); | 192 | p.bump_any(); |
189 | p.bump_any(); | 193 | p.bump_any(); |
190 | p.expect(T![')']); | 194 | p.expect(T![')']); |
diff --git a/crates/syntax/test_data/parser/inline/ok/0153_pub_parens_typepath.rast b/crates/syntax/test_data/parser/inline/ok/0153_pub_parens_typepath.rast new file mode 100644 index 000000000..c204f0e2d --- /dev/null +++ b/crates/syntax/test_data/parser/inline/ok/0153_pub_parens_typepath.rast | |||
@@ -0,0 +1,54 @@ | |||
1 | [email protected] | ||
2 | [email protected] | ||
3 | [email protected] "struct" | ||
4 | [email protected] " " | ||
5 | [email protected] | ||
6 | [email protected] "B" | ||
7 | [email protected] | ||
8 | [email protected] "(" | ||
9 | [email protected] | ||
10 | [email protected] | ||
11 | [email protected] "pub" | ||
12 | [email protected] " " | ||
13 | [email protected] | ||
14 | [email protected] "(" | ||
15 | [email protected] | ||
16 | [email protected] | ||
17 | [email protected] | ||
18 | [email protected] | ||
19 | [email protected] "super" | ||
20 | [email protected] "::" | ||
21 | [email protected] | ||
22 | [email protected] | ||
23 | [email protected] "A" | ||
24 | [email protected] ")" | ||
25 | [email protected] ")" | ||
26 | [email protected] ";" | ||
27 | [email protected] "\n" | ||
28 | [email protected] | ||
29 | [email protected] "struct" | ||
30 | [email protected] " " | ||
31 | [email protected] | ||
32 | [email protected] "B" | ||
33 | [email protected] | ||
34 | [email protected] "(" | ||
35 | [email protected] | ||
36 | [email protected] | ||
37 | [email protected] "pub" | ||
38 | [email protected] " " | ||
39 | [email protected] | ||
40 | [email protected] "(" | ||
41 | [email protected] | ||
42 | [email protected] | ||
43 | [email protected] | ||
44 | [email protected] | ||
45 | [email protected] "crate" | ||
46 | [email protected] "::" | ||
47 | [email protected] | ||
48 | [email protected] | ||
49 | [email protected] "A" | ||
50 | [email protected] "," | ||
51 | [email protected] ")" | ||
52 | [email protected] ")" | ||
53 | [email protected] ";" | ||
54 | [email protected] "\n" | ||
diff --git a/crates/syntax/test_data/parser/inline/ok/0153_pub_parens_typepath.rs b/crates/syntax/test_data/parser/inline/ok/0153_pub_parens_typepath.rs new file mode 100644 index 000000000..d4c163822 --- /dev/null +++ b/crates/syntax/test_data/parser/inline/ok/0153_pub_parens_typepath.rs | |||
@@ -0,0 +1,2 @@ | |||
1 | struct B(pub (super::A)); | ||
2 | struct B(pub (crate::A,)); | ||