@@ -7,8 +7,8 @@ use itertools::Itertools;
7
7
use syntax:: {
8
8
AstNode , AstToken , NodeOrToken ,
9
9
SyntaxKind :: WHITESPACE ,
10
- T ,
11
- ast:: { self , make, syntax_factory:: SyntaxFactory } ,
10
+ SyntaxToken , T ,
11
+ ast:: { self , TokenTree , make, syntax_factory:: SyntaxFactory } ,
12
12
} ;
13
13
14
14
// Assist: extract_expressions_from_format_string
@@ -58,10 +58,11 @@ pub(crate) fn extract_expressions_from_format_string(
58
58
tt. syntax ( ) . text_range ( ) ,
59
59
|edit| {
60
60
// 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) ;
62
64
63
65
let existing_args = if let [
64
- _opening_bracket,
65
66
NodeOrToken :: Token ( _format_string) ,
66
67
_args_start_comma,
67
68
tokens @ ..,
@@ -90,9 +91,11 @@ pub(crate) fn extract_expressions_from_format_string(
90
91
91
92
// Start building the new args
92
93
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 ;
94
95
let mut placeholder_indexes = vec ! [ ] ;
95
96
97
+ new_tt_bits. push ( NodeOrToken :: Token ( make:: tokens:: literal ( & new_fmt) ) ) ;
98
+
96
99
for arg in extracted_args {
97
100
if matches ! ( arg, Arg :: Expr ( _) | Arg :: Placeholder ) {
98
101
// insert ", " before each arg
@@ -150,7 +153,9 @@ pub(crate) fn extract_expressions_from_format_string(
150
153
}
151
154
152
155
// 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
+ {
154
159
let annotation = edit. make_tabstop_after ( cap) ;
155
160
editor. add_annotation ( literal, annotation) ;
156
161
}
@@ -163,6 +168,17 @@ pub(crate) fn extract_expressions_from_format_string(
163
168
Some ( ( ) )
164
169
}
165
170
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
+
166
182
#[ cfg( test) ]
167
183
mod tests {
168
184
use super :: * ;
@@ -186,6 +202,24 @@ fn main() {
186
202
) ;
187
203
}
188
204
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
+
189
223
#[ test]
190
224
fn single_arg ( ) {
191
225
check_assist (
0 commit comments