Skip to content

Commit 57ea982

Browse files
committed
Auto merge of rust-lang#13991 - vasilev-alex:add-braces-assist, r=Veykril
feat: add braces assist This assist adds support for adding braces where it may be appropriate (e.g. lambda expressions) ![ex](https://user-images.githubusercontent.com/4973437/213783924-7c8a8ab5-6a52-4d80-837c-cf2a9b56f061.gif)
2 parents 1d32a7b + 2a48370 commit 57ea982

File tree

3 files changed

+182
-0
lines changed

3 files changed

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

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,

crates/ide-assists/src/tests/generated.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,31 @@
22
33
use super::check_doc_test;
44

5+
#[test]
6+
fn doctest_add_braces() {
7+
check_doc_test(
8+
"add_braces",
9+
r#####"
10+
fn foo(n: i32) -> i32 {
11+
match n {
12+
1 =>$0 n + 1,
13+
_ => 0
14+
}
15+
}
16+
"#####,
17+
r#####"
18+
fn foo(n: i32) -> i32 {
19+
match n {
20+
1 => {
21+
n + 1
22+
},
23+
_ => 0
24+
}
25+
}
26+
"#####,
27+
)
28+
}
29+
530
#[test]
631
fn doctest_add_explicit_type() {
732
check_doc_test(

0 commit comments

Comments
 (0)