fix suggestion-causes-error of print_literal and write_literal
This commit is contained in:
parent
551870df96
commit
6ed003d893
7 changed files with 199 additions and 11 deletions
|
|
@ -5,8 +5,8 @@ use clippy_utils::source::{SpanRangeExt, expand_past_previous_comma};
|
|||
use clippy_utils::{is_in_test, sym};
|
||||
use rustc_ast::token::LitKind;
|
||||
use rustc_ast::{
|
||||
FormatArgPosition, FormatArgPositionKind, FormatArgs, FormatArgsPiece, FormatOptions, FormatPlaceholder,
|
||||
FormatTrait,
|
||||
FormatArgPosition, FormatArgPositionKind, FormatArgs, FormatArgsPiece, FormatCount, FormatOptions,
|
||||
FormatPlaceholder, FormatTrait,
|
||||
};
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::{Expr, Impl, Item, ItemKind};
|
||||
|
|
@ -556,12 +556,7 @@ fn check_literal(cx: &LateContext<'_>, format_args: &FormatArgs, name: &str) {
|
|||
// Decrement the index of the remaining by the number of replaced positional arguments
|
||||
if !suggestion.is_empty() {
|
||||
for piece in &format_args.template {
|
||||
if let Some((span, index)) = positional_arg_piece_span(piece)
|
||||
&& suggestion.iter().all(|(s, _)| *s != span)
|
||||
{
|
||||
let decrement = replaced_position.iter().filter(|i| **i < index).count();
|
||||
suggestion.push((span, format!("{{{}}}", index.saturating_sub(decrement))));
|
||||
}
|
||||
relocalize_format_args_indexes(piece, &mut suggestion, &replaced_position);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -574,7 +569,7 @@ fn check_literal(cx: &LateContext<'_>, format_args: &FormatArgs, name: &str) {
|
|||
}
|
||||
}
|
||||
|
||||
/// Extract Span and its index from the given `piece`, iff it's positional argument.
|
||||
/// Extract Span and its index from the given `piece`, if it's positional argument.
|
||||
fn positional_arg_piece_span(piece: &FormatArgsPiece) -> Option<(Span, usize)> {
|
||||
match piece {
|
||||
FormatArgsPiece::Placeholder(FormatPlaceholder {
|
||||
|
|
@ -591,6 +586,57 @@ fn positional_arg_piece_span(piece: &FormatArgsPiece) -> Option<(Span, usize)> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Relocalizes the indexes of positional arguments in the format string
|
||||
fn relocalize_format_args_indexes(
|
||||
piece: &FormatArgsPiece,
|
||||
suggestion: &mut Vec<(Span, String)>,
|
||||
replaced_position: &[usize],
|
||||
) {
|
||||
if let FormatArgsPiece::Placeholder(FormatPlaceholder {
|
||||
argument:
|
||||
FormatArgPosition {
|
||||
index: Ok(index),
|
||||
// Only consider positional arguments
|
||||
kind: FormatArgPositionKind::Number,
|
||||
span: Some(span),
|
||||
},
|
||||
format_options,
|
||||
..
|
||||
}) = piece
|
||||
{
|
||||
if suggestion.iter().any(|(s, _)| s.overlaps(*span)) {
|
||||
// If the span is already in the suggestion, we don't need to process it again
|
||||
return;
|
||||
}
|
||||
|
||||
// lambda to get the decremented index based on the replaced positions
|
||||
let decremented_index = |index: usize| -> usize {
|
||||
let decrement = replaced_position.iter().filter(|&&i| i < index).count();
|
||||
index - decrement
|
||||
};
|
||||
|
||||
suggestion.push((*span, decremented_index(*index).to_string()));
|
||||
|
||||
// If there are format options, we need to handle them as well
|
||||
if *format_options != FormatOptions::default() {
|
||||
// lambda to process width and precision format counts and add them to the suggestion
|
||||
let mut process_format_count = |count: &Option<FormatCount>, formatter: &dyn Fn(usize) -> String| {
|
||||
if let Some(FormatCount::Argument(FormatArgPosition {
|
||||
index: Ok(format_arg_index),
|
||||
kind: FormatArgPositionKind::Number,
|
||||
span: Some(format_arg_span),
|
||||
})) = count
|
||||
{
|
||||
suggestion.push((*format_arg_span, formatter(decremented_index(*format_arg_index))));
|
||||
}
|
||||
};
|
||||
|
||||
process_format_count(&format_options.width, &|index: usize| format!("{index}$"));
|
||||
process_format_count(&format_options.precision, &|index: usize| format!(".{index}$"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Removes the raw marker, `#`s and quotes from a str, and returns if the literal is raw
|
||||
///
|
||||
/// `r#"a"#` -> (`a`, true)
|
||||
|
|
|
|||
|
|
@ -94,3 +94,14 @@ fn issue_13959() {
|
|||
"
|
||||
);
|
||||
}
|
||||
|
||||
fn issue_14930() {
|
||||
println!("Hello x is {0:2$.1$}", 0.01, 2, 3);
|
||||
//~^ print_literal
|
||||
println!("Hello x is {0:2$.1$}", 0.01, 2, 3);
|
||||
//~^ print_literal
|
||||
println!("Hello x is {0:2$.1$}", 0.01, 2, 3);
|
||||
//~^ print_literal
|
||||
println!("Hello x is {0:2$.1$}", 0.01, 2, 3);
|
||||
//~^ print_literal
|
||||
}
|
||||
|
|
|
|||
|
|
@ -95,3 +95,14 @@ fn issue_13959() {
|
|||
"#
|
||||
);
|
||||
}
|
||||
|
||||
fn issue_14930() {
|
||||
println!("Hello {3} is {0:2$.1$}", 0.01, 2, 3, "x");
|
||||
//~^ print_literal
|
||||
println!("Hello {2} is {0:3$.1$}", 0.01, 2, "x", 3);
|
||||
//~^ print_literal
|
||||
println!("Hello {1} is {0:3$.2$}", 0.01, "x", 2, 3);
|
||||
//~^ print_literal
|
||||
println!("Hello {0} is {1:3$.2$}", "x", 0.01, 2, 3);
|
||||
//~^ print_literal
|
||||
}
|
||||
|
|
|
|||
|
|
@ -229,5 +229,53 @@ LL + bar
|
|||
LL ~ "
|
||||
|
|
||||
|
||||
error: aborting due to 18 previous errors
|
||||
error: literal with an empty format string
|
||||
--> tests/ui/print_literal.rs:100:52
|
||||
|
|
||||
LL | println!("Hello {3} is {0:2$.1$}", 0.01, 2, 3, "x");
|
||||
| ^^^
|
||||
|
|
||||
help: try
|
||||
|
|
||||
LL - println!("Hello {3} is {0:2$.1$}", 0.01, 2, 3, "x");
|
||||
LL + println!("Hello x is {0:2$.1$}", 0.01, 2, 3);
|
||||
|
|
||||
|
||||
error: literal with an empty format string
|
||||
--> tests/ui/print_literal.rs:102:49
|
||||
|
|
||||
LL | println!("Hello {2} is {0:3$.1$}", 0.01, 2, "x", 3);
|
||||
| ^^^
|
||||
|
|
||||
help: try
|
||||
|
|
||||
LL - println!("Hello {2} is {0:3$.1$}", 0.01, 2, "x", 3);
|
||||
LL + println!("Hello x is {0:2$.1$}", 0.01, 2, 3);
|
||||
|
|
||||
|
||||
error: literal with an empty format string
|
||||
--> tests/ui/print_literal.rs:104:46
|
||||
|
|
||||
LL | println!("Hello {1} is {0:3$.2$}", 0.01, "x", 2, 3);
|
||||
| ^^^
|
||||
|
|
||||
help: try
|
||||
|
|
||||
LL - println!("Hello {1} is {0:3$.2$}", 0.01, "x", 2, 3);
|
||||
LL + println!("Hello x is {0:2$.1$}", 0.01, 2, 3);
|
||||
|
|
||||
|
||||
error: literal with an empty format string
|
||||
--> tests/ui/print_literal.rs:106:40
|
||||
|
|
||||
LL | println!("Hello {0} is {1:3$.2$}", "x", 0.01, 2, 3);
|
||||
| ^^^
|
||||
|
|
||||
help: try
|
||||
|
|
||||
LL - println!("Hello {0} is {1:3$.2$}", "x", 0.01, 2, 3);
|
||||
LL + println!("Hello x is {0:2$.1$}", 0.01, 2, 3);
|
||||
|
|
||||
|
||||
error: aborting due to 22 previous errors
|
||||
|
||||
|
|
|
|||
|
|
@ -87,3 +87,15 @@ fn issue_13959() {
|
|||
"
|
||||
);
|
||||
}
|
||||
|
||||
fn issue_14930() {
|
||||
let mut v = Vec::new();
|
||||
writeln!(v, "Hello x is {0:2$.1$}", 0.01, 2, 3);
|
||||
//~^ write_literal
|
||||
writeln!(v, "Hello x is {0:2$.1$}", 0.01, 2, 3);
|
||||
//~^ write_literal
|
||||
writeln!(v, "Hello x is {0:2$.1$}", 0.01, 2, 3);
|
||||
//~^ write_literal
|
||||
writeln!(v, "Hello x is {0:2$.1$}", 0.01, 2, 3);
|
||||
//~^ write_literal
|
||||
}
|
||||
|
|
|
|||
|
|
@ -88,3 +88,15 @@ fn issue_13959() {
|
|||
"#
|
||||
);
|
||||
}
|
||||
|
||||
fn issue_14930() {
|
||||
let mut v = Vec::new();
|
||||
writeln!(v, "Hello {3} is {0:2$.1$}", 0.01, 2, 3, "x");
|
||||
//~^ write_literal
|
||||
writeln!(v, "Hello {2} is {0:3$.1$}", 0.01, 2, "x", 3);
|
||||
//~^ write_literal
|
||||
writeln!(v, "Hello {1} is {0:3$.2$}", 0.01, "x", 2, 3);
|
||||
//~^ write_literal
|
||||
writeln!(v, "Hello {0} is {1:3$.2$}", "x", 0.01, 2, 3);
|
||||
//~^ write_literal
|
||||
}
|
||||
|
|
|
|||
|
|
@ -181,5 +181,53 @@ LL + bar
|
|||
LL ~ "
|
||||
|
|
||||
|
||||
error: aborting due to 14 previous errors
|
||||
error: literal with an empty format string
|
||||
--> tests/ui/write_literal.rs:94:55
|
||||
|
|
||||
LL | writeln!(v, "Hello {3} is {0:2$.1$}", 0.01, 2, 3, "x");
|
||||
| ^^^
|
||||
|
|
||||
help: try
|
||||
|
|
||||
LL - writeln!(v, "Hello {3} is {0:2$.1$}", 0.01, 2, 3, "x");
|
||||
LL + writeln!(v, "Hello x is {0:2$.1$}", 0.01, 2, 3);
|
||||
|
|
||||
|
||||
error: literal with an empty format string
|
||||
--> tests/ui/write_literal.rs:96:52
|
||||
|
|
||||
LL | writeln!(v, "Hello {2} is {0:3$.1$}", 0.01, 2, "x", 3);
|
||||
| ^^^
|
||||
|
|
||||
help: try
|
||||
|
|
||||
LL - writeln!(v, "Hello {2} is {0:3$.1$}", 0.01, 2, "x", 3);
|
||||
LL + writeln!(v, "Hello x is {0:2$.1$}", 0.01, 2, 3);
|
||||
|
|
||||
|
||||
error: literal with an empty format string
|
||||
--> tests/ui/write_literal.rs:98:49
|
||||
|
|
||||
LL | writeln!(v, "Hello {1} is {0:3$.2$}", 0.01, "x", 2, 3);
|
||||
| ^^^
|
||||
|
|
||||
help: try
|
||||
|
|
||||
LL - writeln!(v, "Hello {1} is {0:3$.2$}", 0.01, "x", 2, 3);
|
||||
LL + writeln!(v, "Hello x is {0:2$.1$}", 0.01, 2, 3);
|
||||
|
|
||||
|
||||
error: literal with an empty format string
|
||||
--> tests/ui/write_literal.rs:100:43
|
||||
|
|
||||
LL | writeln!(v, "Hello {0} is {1:3$.2$}", "x", 0.01, 2, 3);
|
||||
| ^^^
|
||||
|
|
||||
help: try
|
||||
|
|
||||
LL - writeln!(v, "Hello {0} is {1:3$.2$}", "x", 0.01, 2, 3);
|
||||
LL + writeln!(v, "Hello x is {0:2$.1$}", 0.01, 2, 3);
|
||||
|
|
||||
|
||||
error: aborting due to 18 previous errors
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue