Unnamed repository; edit this file 'description' to name the repository.
Auto merge of #12481 - XFFXFF:add_label_to_loop, r=Veykril
assist: add label to loop
closes: #12392
I changed `'loop` to `'l`, as `cargo check` says `'loop` is an invalid label name.
| -rw-r--r-- | crates/ide-assists/src/handlers/add_label_to_loop.rs | 164 | ||||
| -rw-r--r-- | crates/ide-assists/src/lib.rs | 2 | ||||
| -rw-r--r-- | crates/ide-assists/src/tests/generated.rs | 23 |
3 files changed, 189 insertions, 0 deletions
diff --git a/crates/ide-assists/src/handlers/add_label_to_loop.rs b/crates/ide-assists/src/handlers/add_label_to_loop.rs new file mode 100644 index 0000000000..a14cc45989 --- /dev/null +++ b/crates/ide-assists/src/handlers/add_label_to_loop.rs @@ -0,0 +1,164 @@ +use ide_db::syntax_helpers::node_ext::for_each_break_and_continue_expr; +use syntax::{ + ast::{self, AstNode, HasLoopBody}, + T, +}; + +use crate::{AssistContext, AssistId, AssistKind, Assists}; + +// Assist: add_label_to_loop +// +// Adds a label to a loop. +// +// ``` +// fn main() { +// loop$0 { +// break; +// continue; +// } +// } +// ``` +// -> +// ``` +// fn main() { +// 'l: loop { +// break 'l; +// continue 'l; +// } +// } +// ``` +pub(crate) fn add_label_to_loop(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { + let loop_kw = ctx.find_token_syntax_at_offset(T![loop])?; + let loop_expr = loop_kw.parent().and_then(ast::LoopExpr::cast)?; + if loop_expr.label().is_some() { + return None; + } + + acc.add( + AssistId("add_label_to_loop", AssistKind::Generate), + "Add Label", + loop_expr.syntax().text_range(), + |builder| { + builder.insert(loop_kw.text_range().start(), "'l: "); + + let loop_body = loop_expr.loop_body().and_then(|it| it.stmt_list()); + for_each_break_and_continue_expr( + loop_expr.label(), + loop_body, + &mut |expr| match expr { + ast::Expr::BreakExpr(break_expr) => { + if let Some(break_token) = break_expr.break_token() { + builder.insert(break_token.text_range().end(), " 'l") + } + } + ast::Expr::ContinueExpr(continue_expr) => { + if let Some(continue_token) = continue_expr.continue_token() { + builder.insert(continue_token.text_range().end(), " 'l") + } + } + _ => {} + }, + ); + }, + ) +} + +#[cfg(test)] +mod tests { + use crate::tests::{check_assist, check_assist_not_applicable}; + + use super::*; + + #[test] + fn add_label() { + check_assist( + add_label_to_loop, + r#" +fn main() { + loop$0 { + break; + continue; + } +}"#, + r#" +fn main() { + 'l: loop { + break 'l; + continue 'l; + } +}"#, + ); + } + + #[test] + fn add_label_to_outer_loop() { + check_assist( + add_label_to_loop, + r#" +fn main() { + loop$0 { + break; + continue; + loop { + break; + continue; + } + } +}"#, + r#" +fn main() { + 'l: loop { + break 'l; + continue 'l; + loop { + break; + continue; + } + } +}"#, + ); + } + + #[test] + fn add_label_to_inner_loop() { + check_assist( + add_label_to_loop, + r#" +fn main() { + loop { + break; + continue; + loop$0 { + break; + continue; + } + } +}"#, + r#" +fn main() { + loop { + break; + continue; + 'l: loop { + break 'l; + continue 'l; + } + } +}"#, + ); + } + + #[test] + fn do_not_add_label_if_exists() { + check_assist_not_applicable( + add_label_to_loop, + r#" +fn main() { + 'l: loop$0 { + break 'l; + continue 'l; + } +}"#, + ); + } +} diff --git a/crates/ide-assists/src/lib.rs b/crates/ide-assists/src/lib.rs index 94fbaff400..7b9134efb4 100644 --- a/crates/ide-assists/src/lib.rs +++ b/crates/ide-assists/src/lib.rs @@ -104,6 +104,7 @@ mod handlers { pub(crate) type Handler = fn(&mut Assists, &AssistContext) -> Option<()>; mod add_explicit_type; + mod add_label_to_loop; mod add_lifetime_to_type; mod add_missing_impl_members; mod add_turbo_fish; @@ -193,6 +194,7 @@ mod handlers { &[ // These are alphabetic for the foolish consistency add_explicit_type::add_explicit_type, + add_label_to_loop::add_label_to_loop, add_missing_match_arms::add_missing_match_arms, add_lifetime_to_type::add_lifetime_to_type, add_return_type::add_return_type, diff --git a/crates/ide-assists/src/tests/generated.rs b/crates/ide-assists/src/tests/generated.rs index 2d57101409..e8d48607be 100644 --- a/crates/ide-assists/src/tests/generated.rs +++ b/crates/ide-assists/src/tests/generated.rs @@ -103,6 +103,29 @@ impl Trait<u32> for () { } #[test] +fn doctest_add_label_to_loop() { + check_doc_test( + "add_label_to_loop", + r#####" +fn main() { + loop$0 { + break; + continue; + } +} +"#####, + r#####" +fn main() { + 'l: loop { + break 'l; + continue 'l; + } +} +"#####, + ) +} + +#[test] fn doctest_add_lifetime_to_type() { check_doc_test( "add_lifetime_to_type", |