@@ -7,8 +7,8 @@ use itertools::Itertools;
77use syntax:: {
88 AstNode , AstToken , NodeOrToken ,
99 SyntaxKind :: WHITESPACE ,
10- T ,
11- ast:: { self , make, syntax_factory:: SyntaxFactory } ,
10+ SyntaxToken , T ,
11+ ast:: { self , TokenTree , make, syntax_factory:: SyntaxFactory } ,
1212} ;
1313
1414// Assist: extract_expressions_from_format_string
@@ -58,10 +58,11 @@ pub(crate) fn extract_expressions_from_format_string(
5858 tt. syntax ( ) . text_range ( ) ,
5959 |edit| {
6060 // Extract existing arguments in macro
61- let tokens = tt. token_trees_and_tokens ( ) . collect_vec ( ) ;
61+ let mut raw_tokens = tt. token_trees_and_tokens ( ) . skip ( 1 ) . collect_vec ( ) ;
62+ let format_string_index = format_str_index ( & raw_tokens, & fmt_string) ;
63+ let tokens = raw_tokens. split_off ( format_string_index) ;
6264
6365 let existing_args = if let [
64- _opening_bracket,
6566 NodeOrToken :: Token ( _format_string) ,
6667 _args_start_comma,
6768 tokens @ ..,
@@ -90,9 +91,11 @@ pub(crate) fn extract_expressions_from_format_string(
9091
9192 // Start building the new args
9293 let mut existing_args = existing_args. into_iter ( ) ;
93- let mut new_tt_bits = vec ! [ NodeOrToken :: Token ( make :: tokens :: literal ( & new_fmt ) ) ] ;
94+ let mut new_tt_bits = raw_tokens ;
9495 let mut placeholder_indexes = vec ! [ ] ;
9596
97+ new_tt_bits. push ( NodeOrToken :: Token ( make:: tokens:: literal ( & new_fmt) ) ) ;
98+
9699 for arg in extracted_args {
97100 if matches ! ( arg, Arg :: Expr ( _) | Arg :: Placeholder ) {
98101 // insert ", " before each arg
@@ -150,7 +153,9 @@ pub(crate) fn extract_expressions_from_format_string(
150153 }
151154
152155 // Add the final tabstop after the format literal
153- if let Some ( NodeOrToken :: Token ( literal) ) = new_tt. token_trees_and_tokens ( ) . nth ( 1 ) {
156+ if let Some ( NodeOrToken :: Token ( literal) ) =
157+ new_tt. token_trees_and_tokens ( ) . nth ( 1 + format_string_index)
158+ {
154159 let annotation = edit. make_tabstop_after ( cap) ;
155160 editor. add_annotation ( literal, annotation) ;
156161 }
@@ -163,6 +168,17 @@ pub(crate) fn extract_expressions_from_format_string(
163168 Some ( ( ) )
164169}
165170
171+ fn format_str_index (
172+ raw_tokens : & [ NodeOrToken < TokenTree , SyntaxToken > ] ,
173+ fmt_string : & ast:: String ,
174+ ) -> usize {
175+ let fmt_string = fmt_string. syntax ( ) ;
176+ raw_tokens
177+ . iter ( )
178+ . position ( |tt| tt. as_token ( ) . is_some_and ( |tt| tt == fmt_string) )
179+ . unwrap_or_default ( )
180+ }
181+
166182#[ cfg( test) ]
167183mod tests {
168184 use super :: * ;
@@ -186,6 +202,24 @@ fn main() {
186202 ) ;
187203 }
188204
205+ #[ test]
206+ fn multiple_middle_arg_on_write ( ) {
207+ check_assist (
208+ extract_expressions_from_format_string,
209+ r#"
210+ //- minicore: write
211+ fn main() {
212+ write!(writer(), "{} {x + 1:b} {}$0", y + 2, 2);
213+ }
214+ "# ,
215+ r#"
216+ fn main() {
217+ write!(writer(), "{} {:b} {}"$0, y + 2, x + 1, 2);
218+ }
219+ "# ,
220+ ) ;
221+ }
222+
189223 #[ test]
190224 fn single_arg ( ) {
191225 check_assist (
0 commit comments