summaryrefslogtreecommitdiff
path: root/compiler/rustc_parse_format
diff options
context:
space:
mode:
authorPreston From <prestonfrom@gmail.com>2022-07-16 15:13:14 -0600
committerPreston From <prestonfrom@gmail.com>2022-07-25 00:00:27 -0600
commit3330c7d1c3bcfd2c452b794db66705b92fb54a3c (patch)
tree54a0678eba5caf07335b5a1ede0314f515bde6f8 /compiler/rustc_parse_format
parent530c0a81d50c6e1c9b1bdee0970d27af02ca49be (diff)
downloadrust-3330c7d1c3bcfd2c452b794db66705b92fb54a3c.tar.gz
Generate correct suggestion with named arguments used positionally
Address issue #99265 by checking each positionally used argument to see if the argument is named and adding a lint to use the name instead. This way, when named arguments are used positionally in a different order than their argument order, the suggested lint is correct. For example: ``` println!("{b} {}", a=1, b=2); ``` This will now generate the suggestion: ``` println!("{b} {a}", a=1, b=2); ``` Additionally, this check now also correctly replaces or inserts only where the positional argument is (or would be if implicit). Also, width and precision are replaced with their argument names when they exists. Since the issues were so closely related, this fix for issue #99265 also fixes issue #99266. Fixes #99265 Fixes #99266
Diffstat (limited to 'compiler/rustc_parse_format')
-rw-r--r--compiler/rustc_parse_format/src/lib.rs20
-rw-r--r--compiler/rustc_parse_format/src/tests.rs28
2 files changed, 36 insertions, 12 deletions
diff --git a/compiler/rustc_parse_format/src/lib.rs b/compiler/rustc_parse_format/src/lib.rs
index 6e7553f5e49..5deb17b8651 100644
--- a/compiler/rustc_parse_format/src/lib.rs
+++ b/compiler/rustc_parse_format/src/lib.rs
@@ -104,8 +104,8 @@ pub struct FormatSpec<'a> {
pub enum Position<'a> {
/// The argument is implied to be located at an index
ArgumentImplicitlyIs(usize),
- /// The argument is located at a specific index given in the format
- ArgumentIs(usize),
+ /// The argument is located at a specific index given in the format,
+ ArgumentIs(usize, Option<InnerSpan>),
/// The argument has a name.
ArgumentNamed(&'a str, InnerSpan),
}
@@ -113,7 +113,7 @@ pub enum Position<'a> {
impl Position<'_> {
pub fn index(&self) -> Option<usize> {
match self {
- ArgumentIs(i) | ArgumentImplicitlyIs(i) => Some(*i),
+ ArgumentIs(i, ..) | ArgumentImplicitlyIs(i) => Some(*i),
_ => None,
}
}
@@ -502,8 +502,15 @@ impl<'a> Parser<'a> {
/// Returns `Some(parsed_position)` if the position is not implicitly
/// consuming a macro argument, `None` if it's the case.
fn position(&mut self) -> Option<Position<'a>> {
+ let start_position = self.cur.peek().map(|item| item.0);
if let Some(i) = self.integer() {
- Some(ArgumentIs(i))
+ let inner_span = start_position.and_then(|start| {
+ self.cur
+ .peek()
+ .cloned()
+ .and_then(|item| Some(self.to_span_index(start).to(self.to_span_index(item.0))))
+ });
+ Some(ArgumentIs(i, inner_span))
} else {
match self.cur.peek() {
Some(&(start, c)) if rustc_lexer::is_id_start(c) => {
@@ -574,6 +581,10 @@ impl<'a> Parser<'a> {
// no '0' flag and '0$' as the width instead.
if let Some(end) = self.consume_pos('$') {
spec.width = CountIsParam(0);
+
+ if let Some((pos, _)) = self.cur.peek().cloned() {
+ spec.width_span = Some(self.to_span_index(pos - 2).to(self.to_span_index(pos)));
+ }
havewidth = true;
spec.width_span = Some(self.to_span_index(end - 1).to(self.to_span_index(end + 1)));
} else {
@@ -586,6 +597,7 @@ impl<'a> Parser<'a> {
spec.width = w;
spec.width_span = sp;
}
+
if let Some(start) = self.consume_pos('.') {
if let Some(end) = self.consume_pos('*') {
// Resolve `CountIsNextParam`.
diff --git a/compiler/rustc_parse_format/src/tests.rs b/compiler/rustc_parse_format/src/tests.rs
index 9c305b4996a..a98f816644b 100644
--- a/compiler/rustc_parse_format/src/tests.rs
+++ b/compiler/rustc_parse_format/src/tests.rs
@@ -62,18 +62,30 @@ fn format_nothing() {
}
#[test]
fn format_position() {
- same("{3}", &[NextArgument(Argument { position: ArgumentIs(3), format: fmtdflt() })]);
+ same(
+ "{3}",
+ &[NextArgument(Argument {
+ position: ArgumentIs(3, Some(InnerSpan { start: 2, end: 3 })),
+ format: fmtdflt(),
+ })],
+ );
}
#[test]
fn format_position_nothing_else() {
- same("{3:}", &[NextArgument(Argument { position: ArgumentIs(3), format: fmtdflt() })]);
+ same(
+ "{3:}",
+ &[NextArgument(Argument {
+ position: ArgumentIs(3, Some(InnerSpan { start: 2, end: 3 })),
+ format: fmtdflt(),
+ })],
+ );
}
#[test]
fn format_type() {
same(
"{3:x}",
&[NextArgument(Argument {
- position: ArgumentIs(3),
+ position: ArgumentIs(3, Some(InnerSpan { start: 2, end: 3 })),
format: FormatSpec {
fill: None,
align: AlignUnknown,
@@ -93,7 +105,7 @@ fn format_align_fill() {
same(
"{3:>}",
&[NextArgument(Argument {
- position: ArgumentIs(3),
+ position: ArgumentIs(3, Some(InnerSpan { start: 2, end: 3 })),
format: FormatSpec {
fill: None,
align: AlignRight,
@@ -110,7 +122,7 @@ fn format_align_fill() {
same(
"{3:0<}",
&[NextArgument(Argument {
- position: ArgumentIs(3),
+ position: ArgumentIs(3, Some(InnerSpan { start: 2, end: 3 })),
format: FormatSpec {
fill: Some('0'),
align: AlignLeft,
@@ -127,7 +139,7 @@ fn format_align_fill() {
same(
"{3:*<abcd}",
&[NextArgument(Argument {
- position: ArgumentIs(3),
+ position: ArgumentIs(3, Some(InnerSpan { start: 2, end: 3 })),
format: FormatSpec {
fill: Some('*'),
align: AlignLeft,
@@ -181,7 +193,7 @@ fn format_counts() {
same(
"{1:0$.10x}",
&[NextArgument(Argument {
- position: ArgumentIs(1),
+ position: ArgumentIs(1, Some(InnerSpan { start: 2, end: 3 })),
format: FormatSpec {
fill: None,
align: AlignUnknown,
@@ -291,7 +303,7 @@ fn format_mixture() {
&[
String("abcd "),
NextArgument(Argument {
- position: ArgumentIs(3),
+ position: ArgumentIs(3, Some(InnerSpan { start: 7, end: 8 })),
format: FormatSpec {
fill: None,
align: AlignUnknown,