Skip to content

Commit 69ffbe2

Browse files
committed
feat: add braces assist
1 parent d46d012 commit 69ffbe2

File tree

2 files changed

+159
-0
lines changed

2 files changed

+159
-0
lines changed
Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
use syntax::{
2+
ast::{self, edit::AstNodeEdit, make},
3+
AstNode,
4+
};
5+
6+
use crate::{AssistContext, AssistId, AssistKind, Assists};
7+
8+
enum ParentType {
9+
MatchArmExpr,
10+
ClosureExpr,
11+
}
12+
13+
fn get_replacement_node(ctx: &AssistContext<'_>) -> Option<(ParentType, ast::Expr)> {
14+
if let Some(match_arm) = ctx.find_node_at_offset::<ast::MatchArm>() {
15+
let match_arm_expr = match_arm.syntax().children().find_map(ast::Expr::cast)?;
16+
17+
if matches!(match_arm_expr, ast::Expr::BlockExpr(_)) {
18+
return None;
19+
}
20+
21+
return Some((ParentType::MatchArmExpr, match_arm_expr));
22+
} else if let Some(closure_expr) = ctx.find_node_at_offset::<ast::ClosureExpr>() {
23+
let body = closure_expr.body()?;
24+
25+
if matches!(body, ast::Expr::BlockExpr(_)) {
26+
return None;
27+
}
28+
29+
return Some((ParentType::ClosureExpr, body));
30+
}
31+
32+
None
33+
}
34+
35+
// Assist: add_braces
36+
//
37+
// Adds braces to lamda and match arm expressions
38+
//
39+
// ```
40+
// fn foo(n: i32) -> i32 {
41+
// match n {
42+
// 1 =>$0 n + 1,
43+
// _ => 0
44+
// }
45+
// }
46+
// ```
47+
// ->
48+
// ```
49+
// fn foo(n: i32) -> i32 {
50+
// match n {
51+
// 1 => {
52+
// n + 1
53+
// },
54+
// _ => 0
55+
// }
56+
// }
57+
// ```
58+
pub(crate) fn add_braces(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
59+
let (expr_type, expr) = get_replacement_node(ctx)?;
60+
61+
acc.add(
62+
AssistId("wrap_with_braces", AssistKind::RefactorRewrite),
63+
match expr_type {
64+
ParentType::ClosureExpr => "Add braces to lamda expression",
65+
ParentType::MatchArmExpr => "Add braces to arm expression",
66+
},
67+
expr.syntax().text_range(),
68+
|builder| {
69+
let block_expr = AstNodeEdit::indent(
70+
&make::block_expr(None, Some(expr.clone())),
71+
AstNodeEdit::indent_level(&expr),
72+
);
73+
74+
builder.replace(expr.syntax().text_range(), block_expr.syntax().text());
75+
},
76+
);
77+
78+
Some(())
79+
}
80+
81+
#[cfg(test)]
82+
mod tests {
83+
use crate::tests::{check_assist, check_assist_not_applicable};
84+
85+
use super::*;
86+
87+
#[test]
88+
fn suggest_add_braces_for_closure() {
89+
check_assist(
90+
add_braces,
91+
r#"
92+
fn foo() {
93+
t(|n|$0 n + 100);
94+
}
95+
"#,
96+
r#"
97+
fn foo() {
98+
t(|n| {
99+
n + 100
100+
});
101+
}
102+
"#,
103+
);
104+
}
105+
106+
#[test]
107+
fn no_assist_for_closures_with_braces() {
108+
check_assist_not_applicable(
109+
add_braces,
110+
r#"
111+
fn foo() {
112+
t(|n|$0 { n + 100 });
113+
}
114+
"#,
115+
);
116+
}
117+
118+
#[test]
119+
fn suggest_add_braces_for_match() {
120+
check_assist(
121+
add_braces,
122+
r#"
123+
fn foo() {
124+
match n {
125+
Some(n) $0=> 29,
126+
_ => ()
127+
};
128+
}
129+
"#,
130+
r#"
131+
fn foo() {
132+
match n {
133+
Some(n) => {
134+
29
135+
},
136+
_ => ()
137+
};
138+
}
139+
"#,
140+
);
141+
}
142+
143+
#[test]
144+
fn no_assist_for_match_with_braces() {
145+
check_assist_not_applicable(
146+
add_braces,
147+
r#"
148+
fn foo() {
149+
match n {
150+
Some(n) $0=> { return 29; },
151+
_ => ()
152+
};
153+
}
154+
"#,
155+
);
156+
}
157+
}

crates/ide-assists/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ mod handlers {
106106

107107
pub(crate) type Handler = fn(&mut Assists, &AssistContext<'_>) -> Option<()>;
108108

109+
mod add_braces;
109110
mod add_explicit_type;
110111
mod add_label_to_loop;
111112
mod add_lifetime_to_type;
@@ -209,6 +210,7 @@ mod handlers {
209210
pub(crate) fn all() -> &'static [Handler] {
210211
&[
211212
// These are alphabetic for the foolish consistency
213+
add_braces::add_braces,
212214
add_explicit_type::add_explicit_type,
213215
add_label_to_loop::add_label_to_loop,
214216
add_missing_match_arms::add_missing_match_arms,

0 commit comments

Comments
 (0)