aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
Diffstat (limited to 'crates')
-rw-r--r--crates/assists/src/handlers/move_guard.rs87
-rw-r--r--crates/parser/src/grammar.rs6
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0153_pub_parens_typepath.rast54
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0153_pub_parens_typepath.rs2
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 @@
1use syntax::{ 1use 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) ->
92pub(crate) fn move_arm_cond_to_match_guard(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { 92pub(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#"
247fn main() {
248 match 92 {
249 x => {
250 <|>if x > 10 {
251 false
252 }
253 },
254 _ => true
255 }
256}
257"#,
258 r#"
259fn 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#"
341fn main() {
342 match 92 {
343 x => {
344 if x > 10 {
345 92;<|>
346 false
347 }
348 }
349 _ => true
350 }
351}
352"#,
353 r#"
354fn 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 @@
1struct B(pub (super::A));
2struct B(pub (crate::A,));