aboutsummaryrefslogtreecommitdiff
path: root/crates/assists/src
diff options
context:
space:
mode:
Diffstat (limited to 'crates/assists/src')
-rw-r--r--crates/assists/src/handlers/move_guard.rs87
-rw-r--r--crates/assists/src/handlers/remove_dbg.rs87
2 files changed, 164 insertions, 10 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/assists/src/handlers/remove_dbg.rs b/crates/assists/src/handlers/remove_dbg.rs
index e10616779..9731344b8 100644
--- a/crates/assists/src/handlers/remove_dbg.rs
+++ b/crates/assists/src/handlers/remove_dbg.rs
@@ -93,8 +93,9 @@ fn needs_parentheses_around_macro_contents(macro_contents: Vec<SyntaxElement>) -
93 if macro_contents.len() < 2 { 93 if macro_contents.len() < 2 {
94 return false; 94 return false;
95 } 95 }
96 let mut macro_contents = macro_contents.into_iter().peekable();
96 let mut unpaired_brackets_in_contents = Vec::new(); 97 let mut unpaired_brackets_in_contents = Vec::new();
97 for element in macro_contents { 98 while let Some(element) = macro_contents.next() {
98 match element.kind() { 99 match element.kind() {
99 T!['('] | T!['['] | T!['{'] => unpaired_brackets_in_contents.push(element), 100 T!['('] | T!['['] | T!['{'] => unpaired_brackets_in_contents.push(element),
100 T![')'] => { 101 T![')'] => {
@@ -118,8 +119,14 @@ fn needs_parentheses_around_macro_contents(macro_contents: Vec<SyntaxElement>) -
118 symbol_kind => { 119 symbol_kind => {
119 let symbol_not_in_bracket = unpaired_brackets_in_contents.is_empty(); 120 let symbol_not_in_bracket = unpaired_brackets_in_contents.is_empty();
120 if symbol_not_in_bracket 121 if symbol_not_in_bracket
121 && symbol_kind != SyntaxKind::COLON 122 && symbol_kind != SyntaxKind::COLON // paths
122 && symbol_kind.is_punct() 123 && (symbol_kind != SyntaxKind::DOT // field/method access
124 || macro_contents // range expressions consist of two SyntaxKind::Dot in macro invocations
125 .peek()
126 .map(|element| element.kind() == SyntaxKind::DOT)
127 .unwrap_or(false))
128 && symbol_kind != SyntaxKind::QUESTION // try operator
129 && (symbol_kind.is_punct() || symbol_kind == SyntaxKind::AS_KW)
123 { 130 {
124 return true; 131 return true;
125 } 132 }
@@ -243,6 +250,25 @@ fn main() {
243 } 250 }
244 251
245 #[test] 252 #[test]
253 fn test_remove_dbg_method_chaining() {
254 check_assist(
255 remove_dbg,
256 r#"let res = <|>dbg!(foo().bar()).baz();"#,
257 r#"let res = foo().bar().baz();"#,
258 );
259 check_assist(
260 remove_dbg,
261 r#"let res = <|>dbg!(foo.bar()).baz();"#,
262 r#"let res = foo.bar().baz();"#,
263 );
264 }
265
266 #[test]
267 fn test_remove_dbg_field_chaining() {
268 check_assist(remove_dbg, r#"let res = <|>dbg!(foo.bar).baz;"#, r#"let res = foo.bar.baz;"#);
269 }
270
271 #[test]
246 fn test_remove_dbg_from_inside_fn() { 272 fn test_remove_dbg_from_inside_fn() {
247 check_assist_target( 273 check_assist_target(
248 remove_dbg, 274 remove_dbg,
@@ -280,4 +306,59 @@ fn main() {
280}"#, 306}"#,
281 ); 307 );
282 } 308 }
309
310 #[test]
311 fn test_remove_dbg_try_expr() {
312 check_assist(
313 remove_dbg,
314 r#"let res = <|>dbg!(result?).foo();"#,
315 r#"let res = result?.foo();"#,
316 );
317 }
318
319 #[test]
320 fn test_remove_dbg_await_expr() {
321 check_assist(
322 remove_dbg,
323 r#"let res = <|>dbg!(fut.await).foo();"#,
324 r#"let res = fut.await.foo();"#,
325 );
326 }
327
328 #[test]
329 fn test_remove_dbg_as_cast() {
330 check_assist(
331 remove_dbg,
332 r#"let res = <|>dbg!(3 as usize).foo();"#,
333 r#"let res = (3 as usize).foo();"#,
334 );
335 }
336
337 #[test]
338 fn test_remove_dbg_index_expr() {
339 check_assist(
340 remove_dbg,
341 r#"let res = <|>dbg!(array[3]).foo();"#,
342 r#"let res = array[3].foo();"#,
343 );
344 check_assist(
345 remove_dbg,
346 r#"let res = <|>dbg!(tuple.3).foo();"#,
347 r#"let res = tuple.3.foo();"#,
348 );
349 }
350
351 #[test]
352 fn test_remove_dbg_range_expr() {
353 check_assist(
354 remove_dbg,
355 r#"let res = <|>dbg!(foo..bar).foo();"#,
356 r#"let res = (foo..bar).foo();"#,
357 );
358 check_assist(
359 remove_dbg,
360 r#"let res = <|>dbg!(foo..=bar).foo();"#,
361 r#"let res = (foo..=bar).foo();"#,
362 );
363 }
283} 364}