support rename after adding label
diff --git a/crates/ide-assists/src/handlers/add_label_to_loop.rs b/crates/ide-assists/src/handlers/add_label_to_loop.rs
index d2b9034..b84ad24 100644
--- a/crates/ide-assists/src/handlers/add_label_to_loop.rs
+++ b/crates/ide-assists/src/handlers/add_label_to_loop.rs
@@ -1,7 +1,14 @@
-use ide_db::syntax_helpers::node_ext::for_each_break_and_continue_expr;
+use ide_db::{
+    source_change::SourceChangeBuilder, syntax_helpers::node_ext::for_each_break_and_continue_expr,
+};
 use syntax::{
-    T,
-    ast::{self, AstNode, HasLoopBody},
+    SyntaxToken, T,
+    ast::{
+        self, AstNode, HasLoopBody,
+        make::{self, tokens},
+        syntax_factory::SyntaxFactory,
+    },
+    syntax_editor::{Position, SyntaxEditor},
 };
 
 use crate::{AssistContext, AssistId, Assists};
@@ -21,9 +28,9 @@
 // ->
 // ```
 // fn main() {
-//     'l: loop {
-//         break 'l;
-//         continue 'l;
+//     ${1:'l}: loop {
+//         break ${2:'l};
+//         continue ${0:'l};
 //     }
 // }
 // ```
@@ -39,30 +46,56 @@
         "Add Label",
         loop_expr.syntax().text_range(),
         |builder| {
-            builder.insert(loop_kw.text_range().start(), "'l: ");
+            let make = SyntaxFactory::with_mappings();
+            let mut editor = builder.make_editor(loop_expr.syntax());
+
+            let label = make.lifetime("'l");
+            let elements = vec![
+                label.syntax().clone().into(),
+                make::token(T![:]).into(),
+                tokens::single_space().into(),
+            ];
+            editor.insert_all(Position::before(&loop_kw), elements);
+
+            if let Some(cap) = ctx.config.snippet_cap {
+                editor.add_annotation(label.syntax(), builder.make_placeholder_snippet(cap));
+            }
 
             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")
-                        }
-                    }
-                    _ => {}
-                },
-            );
+            for_each_break_and_continue_expr(loop_expr.label(), loop_body, &mut |expr| {
+                let token = match expr {
+                    ast::Expr::BreakExpr(break_expr) => break_expr.break_token(),
+                    ast::Expr::ContinueExpr(continue_expr) => continue_expr.continue_token(),
+                    _ => return,
+                };
+                if let Some(token) = token {
+                    insert_label_after_token(&mut editor, &make, &token, ctx, builder);
+                }
+            });
+
+            editor.add_mappings(make.finish_with_mappings());
+            builder.add_file_edits(ctx.vfs_file_id(), editor);
+            builder.rename();
         },
     )
 }
 
+fn insert_label_after_token(
+    editor: &mut SyntaxEditor,
+    make: &SyntaxFactory,
+    token: &SyntaxToken,
+    ctx: &AssistContext<'_>,
+    builder: &mut SourceChangeBuilder,
+) {
+    let label = make.lifetime("'l");
+    let elements = vec![tokens::single_space().into(), label.syntax().clone().into()];
+    editor.insert_all(Position::after(token), elements);
+
+    if let Some(cap) = ctx.config.snippet_cap {
+        editor.add_annotation(label.syntax(), builder.make_placeholder_snippet(cap));
+    }
+}
+
 #[cfg(test)]
 mod tests {
     use crate::tests::{check_assist, check_assist_not_applicable};
@@ -82,9 +115,9 @@
 }"#,
             r#"
 fn main() {
-    'l: loop {
-        break 'l;
-        continue 'l;
+    ${1:'l}: loop {
+        break ${2:'l};
+        continue ${0:'l};
     }
 }"#,
         );
@@ -107,9 +140,9 @@
 }"#,
             r#"
 fn main() {
-    'l: loop {
-        break 'l;
-        continue 'l;
+    ${1:'l}: loop {
+        break ${2:'l};
+        continue ${0:'l};
         loop {
             break;
             continue;
@@ -139,9 +172,9 @@
     loop {
         break;
         continue;
-        'l: loop {
-            break 'l;
-            continue 'l;
+        ${1:'l}: loop {
+            break ${2:'l};
+            continue ${0:'l};
         }
     }
 }"#,
diff --git a/crates/ide-assists/src/tests/generated.rs b/crates/ide-assists/src/tests/generated.rs
index 7f0836a..160b31a 100644
--- a/crates/ide-assists/src/tests/generated.rs
+++ b/crates/ide-assists/src/tests/generated.rs
@@ -183,9 +183,9 @@
 "#####,
         r#####"
 fn main() {
-    'l: loop {
-        break 'l;
-        continue 'l;
+    ${1:'l}: loop {
+        break ${2:'l};
+        continue ${0:'l};
     }
 }
 "#####,