Skip to content

Commit 5b746ec

Browse files
committed
Auto merge of rust-lang#12481 - XFFXFF:add_label_to_loop, r=Veykril
assist: add label to loop closes: rust-lang#12392 I changed `'loop` to `'l`, as `cargo check` says `'loop` is an invalid label name.
2 parents ba32991 + e29a678 commit 5b746ec

File tree

3 files changed

+189
-0
lines changed

3 files changed

+189
-0
lines changed
Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
use ide_db::syntax_helpers::node_ext::for_each_break_and_continue_expr;
2+
use syntax::{
3+
ast::{self, AstNode, HasLoopBody},
4+
T,
5+
};
6+
7+
use crate::{AssistContext, AssistId, AssistKind, Assists};
8+
9+
// Assist: add_label_to_loop
10+
//
11+
// Adds a label to a loop.
12+
//
13+
// ```
14+
// fn main() {
15+
// loop$0 {
16+
// break;
17+
// continue;
18+
// }
19+
// }
20+
// ```
21+
// ->
22+
// ```
23+
// fn main() {
24+
// 'l: loop {
25+
// break 'l;
26+
// continue 'l;
27+
// }
28+
// }
29+
// ```
30+
pub(crate) fn add_label_to_loop(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
31+
let loop_kw = ctx.find_token_syntax_at_offset(T![loop])?;
32+
let loop_expr = loop_kw.parent().and_then(ast::LoopExpr::cast)?;
33+
if loop_expr.label().is_some() {
34+
return None;
35+
}
36+
37+
acc.add(
38+
AssistId("add_label_to_loop", AssistKind::Generate),
39+
"Add Label",
40+
loop_expr.syntax().text_range(),
41+
|builder| {
42+
builder.insert(loop_kw.text_range().start(), "'l: ");
43+
44+
let loop_body = loop_expr.loop_body().and_then(|it| it.stmt_list());
45+
for_each_break_and_continue_expr(
46+
loop_expr.label(),
47+
loop_body,
48+
&mut |expr| match expr {
49+
ast::Expr::BreakExpr(break_expr) => {
50+
if let Some(break_token) = break_expr.break_token() {
51+
builder.insert(break_token.text_range().end(), " 'l")
52+
}
53+
}
54+
ast::Expr::ContinueExpr(continue_expr) => {
55+
if let Some(continue_token) = continue_expr.continue_token() {
56+
builder.insert(continue_token.text_range().end(), " 'l")
57+
}
58+
}
59+
_ => {}
60+
},
61+
);
62+
},
63+
)
64+
}
65+
66+
#[cfg(test)]
67+
mod tests {
68+
use crate::tests::{check_assist, check_assist_not_applicable};
69+
70+
use super::*;
71+
72+
#[test]
73+
fn add_label() {
74+
check_assist(
75+
add_label_to_loop,
76+
r#"
77+
fn main() {
78+
loop$0 {
79+
break;
80+
continue;
81+
}
82+
}"#,
83+
r#"
84+
fn main() {
85+
'l: loop {
86+
break 'l;
87+
continue 'l;
88+
}
89+
}"#,
90+
);
91+
}
92+
93+
#[test]
94+
fn add_label_to_outer_loop() {
95+
check_assist(
96+
add_label_to_loop,
97+
r#"
98+
fn main() {
99+
loop$0 {
100+
break;
101+
continue;
102+
loop {
103+
break;
104+
continue;
105+
}
106+
}
107+
}"#,
108+
r#"
109+
fn main() {
110+
'l: loop {
111+
break 'l;
112+
continue 'l;
113+
loop {
114+
break;
115+
continue;
116+
}
117+
}
118+
}"#,
119+
);
120+
}
121+
122+
#[test]
123+
fn add_label_to_inner_loop() {
124+
check_assist(
125+
add_label_to_loop,
126+
r#"
127+
fn main() {
128+
loop {
129+
break;
130+
continue;
131+
loop$0 {
132+
break;
133+
continue;
134+
}
135+
}
136+
}"#,
137+
r#"
138+
fn main() {
139+
loop {
140+
break;
141+
continue;
142+
'l: loop {
143+
break 'l;
144+
continue 'l;
145+
}
146+
}
147+
}"#,
148+
);
149+
}
150+
151+
#[test]
152+
fn do_not_add_label_if_exists() {
153+
check_assist_not_applicable(
154+
add_label_to_loop,
155+
r#"
156+
fn main() {
157+
'l: loop$0 {
158+
break 'l;
159+
continue 'l;
160+
}
161+
}"#,
162+
);
163+
}
164+
}

crates/ide-assists/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ mod handlers {
104104
pub(crate) type Handler = fn(&mut Assists, &AssistContext) -> Option<()>;
105105

106106
mod add_explicit_type;
107+
mod add_label_to_loop;
107108
mod add_lifetime_to_type;
108109
mod add_missing_impl_members;
109110
mod add_turbo_fish;
@@ -193,6 +194,7 @@ mod handlers {
193194
&[
194195
// These are alphabetic for the foolish consistency
195196
add_explicit_type::add_explicit_type,
197+
add_label_to_loop::add_label_to_loop,
196198
add_missing_match_arms::add_missing_match_arms,
197199
add_lifetime_to_type::add_lifetime_to_type,
198200
add_return_type::add_return_type,

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

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,29 @@ impl Trait<u32> for () {
102102
)
103103
}
104104

105+
#[test]
106+
fn doctest_add_label_to_loop() {
107+
check_doc_test(
108+
"add_label_to_loop",
109+
r#####"
110+
fn main() {
111+
loop$0 {
112+
break;
113+
continue;
114+
}
115+
}
116+
"#####,
117+
r#####"
118+
fn main() {
119+
'l: loop {
120+
break 'l;
121+
continue 'l;
122+
}
123+
}
124+
"#####,
125+
)
126+
}
127+
105128
#[test]
106129
fn doctest_add_lifetime_to_type() {
107130
check_doc_test(

0 commit comments

Comments
 (0)