mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-25 11:17:13 +00:00
Fix extract_expressions_from_format_string on write!
**Input**: ```rust fn main() { write!(f, "{2+3}$0") } ``` **Old output**: ```rust fn main() { write!("{}"$0, 2+3) } ``` **This PR output**: ```rust fn main() { write!(f, "{}"$0, 2+3) } ```
This commit is contained in:
parent
31db5b5be9
commit
62508aaca1
@ -7,8 +7,8 @@ use itertools::Itertools;
|
|||||||
use syntax::{
|
use syntax::{
|
||||||
AstNode, AstToken, NodeOrToken,
|
AstNode, AstToken, NodeOrToken,
|
||||||
SyntaxKind::WHITESPACE,
|
SyntaxKind::WHITESPACE,
|
||||||
T,
|
SyntaxToken, T,
|
||||||
ast::{self, make, syntax_factory::SyntaxFactory},
|
ast::{self, TokenTree, make, syntax_factory::SyntaxFactory},
|
||||||
};
|
};
|
||||||
|
|
||||||
// Assist: extract_expressions_from_format_string
|
// Assist: extract_expressions_from_format_string
|
||||||
@ -58,10 +58,11 @@ pub(crate) fn extract_expressions_from_format_string(
|
|||||||
tt.syntax().text_range(),
|
tt.syntax().text_range(),
|
||||||
|edit| {
|
|edit| {
|
||||||
// Extract existing arguments in macro
|
// Extract existing arguments in macro
|
||||||
let tokens = tt.token_trees_and_tokens().collect_vec();
|
let mut raw_tokens = tt.token_trees_and_tokens().skip(1).collect_vec();
|
||||||
|
let format_string_index = format_str_index(&raw_tokens, &fmt_string);
|
||||||
|
let tokens = raw_tokens.split_off(format_string_index);
|
||||||
|
|
||||||
let existing_args = if let [
|
let existing_args = if let [
|
||||||
_opening_bracket,
|
|
||||||
NodeOrToken::Token(_format_string),
|
NodeOrToken::Token(_format_string),
|
||||||
_args_start_comma,
|
_args_start_comma,
|
||||||
tokens @ ..,
|
tokens @ ..,
|
||||||
@ -90,9 +91,11 @@ pub(crate) fn extract_expressions_from_format_string(
|
|||||||
|
|
||||||
// Start building the new args
|
// Start building the new args
|
||||||
let mut existing_args = existing_args.into_iter();
|
let mut existing_args = existing_args.into_iter();
|
||||||
let mut new_tt_bits = vec![NodeOrToken::Token(make::tokens::literal(&new_fmt))];
|
let mut new_tt_bits = raw_tokens;
|
||||||
let mut placeholder_indexes = vec![];
|
let mut placeholder_indexes = vec![];
|
||||||
|
|
||||||
|
new_tt_bits.push(NodeOrToken::Token(make::tokens::literal(&new_fmt)));
|
||||||
|
|
||||||
for arg in extracted_args {
|
for arg in extracted_args {
|
||||||
if matches!(arg, Arg::Expr(_) | Arg::Placeholder) {
|
if matches!(arg, Arg::Expr(_) | Arg::Placeholder) {
|
||||||
// insert ", " before each arg
|
// insert ", " before each arg
|
||||||
@ -150,7 +153,9 @@ pub(crate) fn extract_expressions_from_format_string(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Add the final tabstop after the format literal
|
// Add the final tabstop after the format literal
|
||||||
if let Some(NodeOrToken::Token(literal)) = new_tt.token_trees_and_tokens().nth(1) {
|
if let Some(NodeOrToken::Token(literal)) =
|
||||||
|
new_tt.token_trees_and_tokens().nth(1 + format_string_index)
|
||||||
|
{
|
||||||
let annotation = edit.make_tabstop_after(cap);
|
let annotation = edit.make_tabstop_after(cap);
|
||||||
editor.add_annotation(literal, annotation);
|
editor.add_annotation(literal, annotation);
|
||||||
}
|
}
|
||||||
@ -163,6 +168,17 @@ pub(crate) fn extract_expressions_from_format_string(
|
|||||||
Some(())
|
Some(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn format_str_index(
|
||||||
|
raw_tokens: &[NodeOrToken<TokenTree, SyntaxToken>],
|
||||||
|
fmt_string: &ast::String,
|
||||||
|
) -> usize {
|
||||||
|
let fmt_string = fmt_string.syntax();
|
||||||
|
raw_tokens
|
||||||
|
.iter()
|
||||||
|
.position(|tt| tt.as_token().is_some_and(|tt| tt == fmt_string))
|
||||||
|
.unwrap_or_default()
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
@ -186,6 +202,24 @@ fn main() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn multiple_middle_arg_on_write() {
|
||||||
|
check_assist(
|
||||||
|
extract_expressions_from_format_string,
|
||||||
|
r#"
|
||||||
|
//- minicore: write
|
||||||
|
fn main() {
|
||||||
|
write!(writer(), "{} {x + 1:b} {}$0", y + 2, 2);
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
r#"
|
||||||
|
fn main() {
|
||||||
|
write!(writer(), "{} {:b} {}"$0, y + 2, x + 1, 2);
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn single_arg() {
|
fn single_arg() {
|
||||||
check_assist(
|
check_assist(
|
||||||
|
Loading…
x
Reference in New Issue
Block a user