1- use ide_db:: syntax_helpers:: node_ext:: for_each_break_and_continue_expr;
1+ use ide_db:: {
2+ source_change:: SourceChangeBuilder , syntax_helpers:: node_ext:: for_each_break_and_continue_expr,
3+ } ;
24use syntax:: {
3- T ,
4- ast:: { self , AstNode , HasLoopBody } ,
5+ SyntaxToken , T ,
6+ ast:: { self , AstNode , HasLoopBody , make, syntax_factory:: SyntaxFactory } ,
7+ syntax_editor:: { Position , SyntaxEditor } ,
58} ;
69
710use crate :: { AssistContext , AssistId , Assists } ;
@@ -39,30 +42,57 @@ pub(crate) fn add_label_to_loop(acc: &mut Assists, ctx: &AssistContext<'_>) -> O
3942 "Add Label" ,
4043 loop_expr. syntax ( ) . text_range ( ) ,
4144 |builder| {
42- builder. insert ( loop_kw. text_range ( ) . start ( ) , "'l: " ) ;
45+ let make = SyntaxFactory :: with_mappings ( ) ;
46+ let mut editor = builder. make_editor ( loop_expr. syntax ( ) ) ;
47+
48+ let label = make. lifetime ( "'l" ) ;
49+ let elements = vec ! [
50+ label. syntax( ) . clone( ) . into( ) ,
51+ make:: token( syntax:: SyntaxKind :: COLON ) . into( ) ,
52+ make:: token( syntax:: SyntaxKind :: WHITESPACE ) . into( ) ,
53+ ] ;
54+ editor. insert_all ( Position :: before ( & loop_kw) , elements) ;
55+
56+ if let Some ( cap) = ctx. config . snippet_cap {
57+ editor. add_annotation ( label. syntax ( ) , builder. make_placeholder_snippet ( cap) ) ;
58+ }
4359
4460 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- ) ;
61+ for_each_break_and_continue_expr ( loop_expr. label ( ) , loop_body, & mut |expr| {
62+ let token = match expr {
63+ ast:: Expr :: BreakExpr ( break_expr) => break_expr. break_token ( ) ,
64+ ast:: Expr :: ContinueExpr ( continue_expr) => continue_expr. continue_token ( ) ,
65+ _ => return ,
66+ } ;
67+ if let Some ( token) = token {
68+ insert_lifetime_after_token ( & mut editor, & make, & token, ctx, builder) ;
69+ }
70+ } ) ;
71+
72+ editor. add_mappings ( make. finish_with_mappings ( ) ) ;
73+ builder. add_file_edits ( ctx. vfs_file_id ( ) , editor) ;
74+ builder. rename ( ) ;
6275 } ,
6376 )
6477}
6578
79+ fn insert_lifetime_after_token (
80+ editor : & mut SyntaxEditor ,
81+ make : & SyntaxFactory ,
82+ token : & SyntaxToken ,
83+ ctx : & AssistContext < ' _ > ,
84+ builder : & mut SourceChangeBuilder ,
85+ ) {
86+ let label = make. lifetime ( "'l" ) ;
87+ let elements =
88+ vec ! [ make:: token( syntax:: SyntaxKind :: WHITESPACE ) . into( ) , label. syntax( ) . clone( ) . into( ) ] ;
89+ editor. insert_all ( Position :: after ( token) , elements) ;
90+
91+ if let Some ( cap) = ctx. config . snippet_cap {
92+ editor. add_annotation ( label. syntax ( ) , builder. make_placeholder_snippet ( cap) ) ;
93+ }
94+ }
95+
6696#[ cfg( test) ]
6797mod tests {
6898 use crate :: tests:: { check_assist, check_assist_not_applicable} ;
@@ -82,9 +112,9 @@ fn main() {
82112}"# ,
83113 r#"
84114fn main() {
85- 'l : loop {
86- break 'l ;
87- continue 'l ;
115+ ${1:'l} : loop {
116+ break ${2:'l} ;
117+ continue ${0:'l} ;
88118 }
89119}"# ,
90120 ) ;
@@ -107,9 +137,9 @@ fn main() {
107137}"# ,
108138 r#"
109139fn main() {
110- 'l : loop {
111- break 'l ;
112- continue 'l ;
140+ ${1:'l} : loop {
141+ break ${2:'l} ;
142+ continue ${0:'l} ;
113143 loop {
114144 break;
115145 continue;
@@ -139,9 +169,9 @@ fn main() {
139169 loop {
140170 break;
141171 continue;
142- 'l : loop {
143- break 'l ;
144- continue 'l ;
172+ ${1:'l} : loop {
173+ break ${2:'l} ;
174+ continue ${0:'l} ;
145175 }
146176 }
147177}"# ,
0 commit comments