Skip to content

Commit 88595fe

Browse files
committed
Fix semicolon for toggle_macro_delimiter
Example --- ```rust macro_rules! sth { () => {}; } sth!$0{ } ``` (old test `sth!{};` is a syntax error in item place) **Before this PR** ```rust macro_rules! sth { () => {}; } sth![ ] ``` **After this PR** ```rust macro_rules! sth { () => {}; } sth![ ]; ```
1 parent d7666fa commit 88595fe

1 file changed

Lines changed: 145 additions & 4 deletions

File tree

crates/ide-assists/src/handlers/toggle_macro_delimiter.rs

Lines changed: 145 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,14 @@ pub(crate) fn toggle_macro_delimiter(acc: &mut Assists, ctx: &AssistContext<'_>)
8686
}
8787
MacroDelims::LCur | MacroDelims::RCur => {
8888
editor.replace(ltoken, make.token(T!['[']));
89-
editor.replace(rtoken, make.token(T![']']));
89+
if semicolon.is_some() || !needs_semicolon(token_tree) {
90+
editor.replace(rtoken, make.token(T![']']));
91+
} else {
92+
editor.replace_with_many(
93+
rtoken,
94+
vec![make.token(T![']']).into(), make.token(T![;]).into()],
95+
);
96+
}
9097
}
9198
}
9299
editor.add_mappings(make.finish_with_mappings());
@@ -103,6 +110,30 @@ fn macro_semicolon(makro: &ast::MacroCall) -> Option<SyntaxToken> {
103110
})
104111
}
105112

113+
fn needs_semicolon(tt: ast::TokenTree) -> bool {
114+
(|| {
115+
let call = ast::MacroCall::cast(tt.syntax().parent()?)?;
116+
let container = call.syntax().parent()?;
117+
let kind = container.kind();
118+
119+
if call.semicolon_token().is_some() {
120+
return Some(false);
121+
}
122+
123+
Some(
124+
ast::ItemList::can_cast(kind)
125+
|| ast::SourceFile::can_cast(kind)
126+
|| ast::AssocItemList::can_cast(kind)
127+
|| ast::ExternItemList::can_cast(kind)
128+
|| ast::MacroItems::can_cast(kind)
129+
|| ast::MacroExpr::can_cast(kind)
130+
&& ast::ExprStmt::cast(container.parent()?)
131+
.is_some_and(|it| it.semicolon_token().is_none()),
132+
)
133+
})()
134+
.unwrap_or(false)
135+
}
136+
106137
#[cfg(test)]
107138
mod tests {
108139
use crate::tests::{check_assist, check_assist_not_applicable};
@@ -161,7 +192,7 @@ macro_rules! sth {
161192
() => {};
162193
}
163194
164-
sth!$0{ };
195+
sth!$0{ }
165196
"#,
166197
r#"
167198
macro_rules! sth {
@@ -170,7 +201,117 @@ macro_rules! sth {
170201
171202
sth![ ];
172203
"#,
173-
)
204+
);
205+
206+
check_assist(
207+
toggle_macro_delimiter,
208+
r#"
209+
macro_rules! sth {
210+
() => {};
211+
}
212+
213+
fn foo() -> i32 {
214+
sth!$0{ }
215+
2
216+
}
217+
"#,
218+
r#"
219+
macro_rules! sth {
220+
() => {};
221+
}
222+
223+
fn foo() -> i32 {
224+
sth![ ];
225+
2
226+
}
227+
"#,
228+
);
229+
230+
check_assist(
231+
toggle_macro_delimiter,
232+
r#"
233+
macro_rules! sth {
234+
() => {2};
235+
}
236+
237+
fn foo() {
238+
sth!$0{ };
239+
}
240+
"#,
241+
r#"
242+
macro_rules! sth {
243+
() => {2};
244+
}
245+
246+
fn foo() {
247+
sth![ ];
248+
}
249+
"#,
250+
);
251+
252+
check_assist(
253+
toggle_macro_delimiter,
254+
r#"
255+
macro_rules! sth {
256+
() => {2};
257+
}
258+
259+
fn foo() -> i32 {
260+
sth!$0{ }
261+
}
262+
"#,
263+
r#"
264+
macro_rules! sth {
265+
() => {2};
266+
}
267+
268+
fn foo() -> i32 {
269+
sth![ ]
270+
}
271+
"#,
272+
);
273+
274+
check_assist(
275+
toggle_macro_delimiter,
276+
r#"
277+
macro_rules! sth {
278+
() => {};
279+
}
280+
impl () {
281+
sth!$0{}
282+
}
283+
"#,
284+
r#"
285+
macro_rules! sth {
286+
() => {};
287+
}
288+
impl () {
289+
sth![];
290+
}
291+
"#,
292+
);
293+
294+
check_assist(
295+
toggle_macro_delimiter,
296+
r#"
297+
macro_rules! sth {
298+
() => {2};
299+
}
300+
301+
fn foo() -> i32 {
302+
bar(sth!$0{ })
303+
}
304+
"#,
305+
r#"
306+
macro_rules! sth {
307+
() => {2};
308+
}
309+
310+
fn foo() -> i32 {
311+
bar(sth![ ])
312+
}
313+
"#,
314+
);
174315
}
175316

176317
#[test]
@@ -204,7 +345,7 @@ mod abc {
204345
() => {};
205346
}
206347
207-
sth!$0{ };
348+
sth!$0{ }
208349
}
209350
"#,
210351
r#"

0 commit comments

Comments
 (0)