diff options
| author | Esteban Küber <esteban@commure.com> | 2018-07-19 23:14:00 -0700 |
|---|---|---|
| committer | Esteban Küber <esteban@commure.com> | 2018-07-19 23:18:07 -0700 |
| commit | f4306ffbfcb2280f180e51ce6421e1c6c28dccec (patch) | |
| tree | ed1c8c08d11b030da780ef599b66ae79b8d68e3c /src/libfmt_macros | |
| parent | 154dee2dccd45f929b0a3d2ce2d45739513f77c8 (diff) | |
| download | rust-f4306ffbfcb2280f180e51ce6421e1c6c28dccec.tar.gz rust-f4306ffbfcb2280f180e51ce6421e1c6c28dccec.zip | |
Use correct spans for format string errors
When encountering format string errors in a raw string, or regular string literal with embedded newlines, account for the positional change to use correct spans. :drive by fix: 🚗
Diffstat (limited to 'src/libfmt_macros')
| -rw-r--r-- | src/libfmt_macros/Cargo.toml | 3 | ||||
| -rw-r--r-- | src/libfmt_macros/lib.rs | 40 |
2 files changed, 34 insertions, 9 deletions
diff --git a/src/libfmt_macros/Cargo.toml b/src/libfmt_macros/Cargo.toml index b3f4d2deae2..6e6af9c2ff5 100644 --- a/src/libfmt_macros/Cargo.toml +++ b/src/libfmt_macros/Cargo.toml @@ -7,3 +7,6 @@ version = "0.0.0" name = "fmt_macros" path = "lib.rs" crate-type = ["dylib"] + +[dependencies] +syntax = { path = "../libsyntax" } diff --git a/src/libfmt_macros/lib.rs b/src/libfmt_macros/lib.rs index ee590bc3b5e..54cf3d24173 100644 --- a/src/libfmt_macros/lib.rs +++ b/src/libfmt_macros/lib.rs @@ -28,6 +28,8 @@ pub use self::Alignment::*; pub use self::Flag::*; pub use self::Count::*; +extern crate syntax; + use std::str; use std::string; use std::iter; @@ -150,18 +152,27 @@ pub struct Parser<'a> { pub errors: Vec<ParseError>, /// Current position of implicit positional argument pointer curarg: usize, + /// The style of the string (raw or not), used to position spans correctly + style: syntax::ast::StrStyle, + /// How many newlines have been seen in the string so far, to adjust the error spans + seen_newlines: usize, } impl<'a> Iterator for Parser<'a> { type Item = Piece<'a>; fn next(&mut self) -> Option<Piece<'a>> { + let raw = match self.style { + syntax::ast::StrStyle::Raw(raw) => raw as usize + self.seen_newlines, + _ => 0, + }; if let Some(&(pos, c)) = self.cur.peek() { match c { '{' => { + let pos = pos + raw + 1; self.cur.next(); if self.consume('{') { - Some(String(self.string(pos + 1))) + Some(String(self.string(pos))) } else { let ret = Some(NextArgument(self.argument())); self.must_consume('}'); @@ -169,8 +180,8 @@ impl<'a> Iterator for Parser<'a> { } } '}' => { + let pos = pos + raw + 1; self.cur.next(); - let pos = pos + 1; if self.consume('}') { Some(String(self.string(pos))) } else { @@ -184,6 +195,10 @@ impl<'a> Iterator for Parser<'a> { None } } + '\n' => { + self.seen_newlines += 1; + Some(String(self.string(pos))) + } _ => Some(String(self.string(pos))), } } else { @@ -194,12 +209,14 @@ impl<'a> Iterator for Parser<'a> { impl<'a> Parser<'a> { /// Creates a new parser for the given format string - pub fn new(s: &'a str) -> Parser<'a> { + pub fn new(s: &'a str, style: syntax::ast::StrStyle) -> Parser<'a> { Parser { input: s, cur: s.char_indices().peekable(), errors: vec![], curarg: 0, + style, + seen_newlines: 0, } } @@ -262,14 +279,19 @@ impl<'a> Parser<'a> { /// found, an error is emitted. fn must_consume(&mut self, c: char) { self.ws(); + let raw = match self.style { + syntax::ast::StrStyle::Raw(raw) => raw as usize, + _ => 0, + }; + let padding = raw + self.seen_newlines; if let Some(&(pos, maybe)) = self.cur.peek() { if c == maybe { self.cur.next(); } else { self.err(format!("expected `{:?}`, found `{:?}`", c, maybe), format!("expected `{}`", c), - pos + 1, - pos + 1); + pos + padding + 1, + pos + padding + 1); } } else { let msg = format!("expected `{:?}` but string was terminated", c); @@ -282,8 +304,8 @@ impl<'a> Parser<'a> { self.err_with_note(msg, format!("expected `{:?}`", c), "if you intended to print `{`, you can escape it using `{{`", - pos, - pos); + pos + padding, + pos + padding); } else { self.err(msg, format!("expected `{:?}`", c), pos, pos); } @@ -540,7 +562,7 @@ mod tests { use super::*; fn same(fmt: &'static str, p: &[Piece<'static>]) { - let parser = Parser::new(fmt); + let parser = Parser::new(fmt, syntax::ast::StrStyle::Cooked); assert!(parser.collect::<Vec<Piece<'static>>>() == p); } @@ -556,7 +578,7 @@ mod tests { } fn musterr(s: &str) { - let mut p = Parser::new(s); + let mut p = Parser::new(fmt, syntax::ast::StrStyle::Cooked); p.next(); assert!(!p.errors.is_empty()); } |
