Skip to content

Commit a8ed603

Browse files
authored
Rollup merge of rust-lang#52888 - estebank:shell-sugg, r=oli-obk
Use suggestions for shell format arguments Follow up to rust-lang#52649.
2 parents 312f18c + 75ff0dd commit a8ed603

File tree

4 files changed

+70
-39
lines changed

4 files changed

+70
-39
lines changed

src/libsyntax_ext/format_foreign.rs

Lines changed: 46 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -774,31 +774,41 @@ pub mod shell {
774774

775775
#[derive(Clone, PartialEq, Debug)]
776776
pub enum Substitution<'a> {
777-
Ordinal(u8),
778-
Name(&'a str),
779-
Escape,
777+
Ordinal(u8, (usize, usize)),
778+
Name(&'a str, (usize, usize)),
779+
Escape((usize, usize)),
780780
}
781781

782782
impl<'a> Substitution<'a> {
783783
pub fn as_str(&self) -> String {
784-
match *self {
785-
Substitution::Ordinal(n) => format!("${}", n),
786-
Substitution::Name(n) => format!("${}", n),
787-
Substitution::Escape => "$$".into(),
784+
match self {
785+
Substitution::Ordinal(n, _) => format!("${}", n),
786+
Substitution::Name(n, _) => format!("${}", n),
787+
Substitution::Escape(_) => "$$".into(),
788788
}
789789
}
790790

791791
pub fn position(&self) -> Option<(usize, usize)> {
792-
match *self {
793-
_ => None,
792+
match self {
793+
Substitution::Ordinal(_, pos) |
794+
Substitution::Name(_, pos) |
795+
Substitution::Escape(pos) => Some(*pos),
796+
}
797+
}
798+
799+
pub fn set_position(&mut self, start: usize, end: usize) {
800+
match self {
801+
Substitution::Ordinal(_, ref mut pos) |
802+
Substitution::Name(_, ref mut pos) |
803+
Substitution::Escape(ref mut pos) => *pos = (start, end),
794804
}
795805
}
796806

797807
pub fn translate(&self) -> Option<String> {
798808
match *self {
799-
Substitution::Ordinal(n) => Some(format!("{{{}}}", n)),
800-
Substitution::Name(n) => Some(format!("{{{}}}", n)),
801-
Substitution::Escape => None,
809+
Substitution::Ordinal(n, _) => Some(format!("{{{}}}", n)),
810+
Substitution::Name(n, _) => Some(format!("{{{}}}", n)),
811+
Substitution::Escape(_) => None,
802812
}
803813
}
804814
}
@@ -807,20 +817,26 @@ pub mod shell {
807817
pub fn iter_subs(s: &str) -> Substitutions {
808818
Substitutions {
809819
s,
820+
pos: 0,
810821
}
811822
}
812823

813824
/// Iterator over substitutions in a string.
814825
pub struct Substitutions<'a> {
815826
s: &'a str,
827+
pos: usize,
816828
}
817829

818830
impl<'a> Iterator for Substitutions<'a> {
819831
type Item = Substitution<'a>;
820832
fn next(&mut self) -> Option<Self::Item> {
821833
match parse_next_substitution(self.s) {
822-
Some((sub, tail)) => {
834+
Some((mut sub, tail)) => {
823835
self.s = tail;
836+
if let Some((start, end)) = sub.position() {
837+
sub.set_position(start + self.pos, end + self.pos);
838+
self.pos += end;
839+
}
824840
Some(sub)
825841
},
826842
None => None,
@@ -837,15 +853,15 @@ pub mod shell {
837853
let at = {
838854
let start = s.find('$')?;
839855
match s[start+1..].chars().next()? {
840-
'$' => return Some((Substitution::Escape, &s[start+2..])),
856+
'$' => return Some((Substitution::Escape((start, start+2)), &s[start+2..])),
841857
c @ '0' ..= '9' => {
842858
let n = (c as u8) - b'0';
843-
return Some((Substitution::Ordinal(n), &s[start+2..]));
859+
return Some((Substitution::Ordinal(n, (start, start+2)), &s[start+2..]));
844860
},
845861
_ => {/* fall-through */},
846862
}
847863

848-
Cur::new_at_start(&s[start..])
864+
Cur::new_at(&s[..], start)
849865
};
850866

851867
let at = at.at_next_cp()?;
@@ -855,7 +871,10 @@ pub mod shell {
855871
None
856872
} else {
857873
let end = at_next_cp_while(inner, is_ident_tail);
858-
Some((Substitution::Name(at.slice_between(end).unwrap()), end.slice_after()))
874+
let slice = at.slice_between(end).unwrap();
875+
let start = at.at - 1;
876+
let end_pos = at.at + slice.len();
877+
Some((Substitution::Name(slice, (start, end_pos)), end.slice_after()))
859878
}
860879
}
861880

@@ -907,24 +926,24 @@ pub mod shell {
907926
fn test_escape() {
908927
assert_eq!(pns("has no escapes"), None);
909928
assert_eq!(pns("has no escapes, either $"), None);
910-
assert_eq!(pns("*so* has a $$ escape"), Some((S::Escape, " escape")));
911-
assert_eq!(pns("$$ leading escape"), Some((S::Escape, " leading escape")));
912-
assert_eq!(pns("trailing escape $$"), Some((S::Escape, "")));
929+
assert_eq!(pns("*so* has a $$ escape"), Some((S::Escape((11, 13)), " escape")));
930+
assert_eq!(pns("$$ leading escape"), Some((S::Escape((0, 2)), " leading escape")));
931+
assert_eq!(pns("trailing escape $$"), Some((S::Escape((16, 18)), "")));
913932
}
914933

915934
#[test]
916935
fn test_parse() {
917936
macro_rules! assert_pns_eq_sub {
918-
($in_:expr, $kind:ident($arg:expr)) => {
919-
assert_eq!(pns(concat!($in_, "!")), Some((S::$kind($arg.into()), "!")))
937+
($in_:expr, $kind:ident($arg:expr, $pos:expr)) => {
938+
assert_eq!(pns(concat!($in_, "!")), Some((S::$kind($arg.into(), $pos), "!")))
920939
};
921940
}
922941

923-
assert_pns_eq_sub!("$0", Ordinal(0));
924-
assert_pns_eq_sub!("$1", Ordinal(1));
925-
assert_pns_eq_sub!("$9", Ordinal(9));
926-
assert_pns_eq_sub!("$N", Name("N"));
927-
assert_pns_eq_sub!("$NAME", Name("NAME"));
942+
assert_pns_eq_sub!("$0", Ordinal(0, (0, 2)));
943+
assert_pns_eq_sub!("$1", Ordinal(1, (0, 2)));
944+
assert_pns_eq_sub!("$9", Ordinal(9, (0, 2)));
945+
assert_pns_eq_sub!("$N", Name("N", (0, 2)));
946+
assert_pns_eq_sub!("$NAME", Name("NAME", (0, 5)));
928947
}
929948

930949
#[test]
@@ -961,13 +980,6 @@ mod strcursor {
961980
}
962981

963982
impl<'a> StrCursor<'a> {
964-
pub fn new_at_start(s: &'a str) -> StrCursor<'a> {
965-
StrCursor {
966-
s,
967-
at: 0,
968-
}
969-
}
970-
971983
pub fn new_at(s: &'a str, at: usize) -> StrCursor<'a> {
972984
StrCursor {
973985
s,

src/test/ui/macros/format-foreign.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,6 @@ fn main() {
2222
println!("{} %f", "one", 2.0); //~ ERROR never used
2323

2424
println!("Hi there, $NAME.", NAME="Tim"); //~ ERROR never used
25+
println!("$1 $0 $$ $NAME", 1, 2, NAME=3);
26+
//~^ ERROR multiple unused formatting arguments
2527
}

src/test/ui/macros/format-foreign.stderr

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,10 +52,25 @@ error: named argument never used
5252
--> $DIR/format-foreign.rs:24:39
5353
|
5454
LL | println!("Hi there, $NAME.", NAME="Tim"); //~ ERROR never used
55-
| ^^^^^
55+
| ----- ^^^^^
56+
| |
57+
| help: format specifiers use curly braces: `{NAME}`
5658
|
57-
= help: `$NAME` should be written as `{NAME}`
5859
= note: shell formatting not supported; see the documentation for `std::fmt`
5960

60-
error: aborting due to 5 previous errors
61+
error: multiple unused formatting arguments
62+
--> $DIR/format-foreign.rs:25:32
63+
|
64+
LL | println!("$1 $0 $$ $NAME", 1, 2, NAME=3);
65+
| ---------------- ^ ^ ^
66+
| |
67+
| multiple missing formatting specifiers
68+
|
69+
= note: shell formatting not supported; see the documentation for `std::fmt`
70+
help: format specifiers use curly braces
71+
|
72+
LL | println!("{1} {0} $$ {NAME}", 1, 2, NAME=3);
73+
| ^^^ ^^^ ^^^^^^
74+
75+
error: aborting due to 6 previous errors
6176

src/test/ui/macros/format-unused-lables.stderr

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,10 @@ error: multiple unused formatting arguments
3030
--> $DIR/format-unused-lables.rs:24:9
3131
|
3232
LL | println!("Some more $STUFF",
33-
| ------------------ multiple missing formatting specifiers
33+
| ------------------
34+
| | |
35+
| | help: format specifiers use curly braces: `{STUFF}`
36+
| multiple missing formatting specifiers
3437
LL | "woo!", //~ ERROR multiple unused formatting arguments
3538
| ^^^^^^
3639
LL | STUFF=
@@ -39,7 +42,6 @@ LL | "things"
3942
LL | , UNUSED="args");
4043
| ^^^^^^
4144
|
42-
= help: `$STUFF` should be written as `{STUFF}`
4345
= note: shell formatting not supported; see the documentation for `std::fmt`
4446

4547
error: aborting due to 4 previous errors

0 commit comments

Comments
 (0)