diff options
| author | Felix S. Klock II <pnkfelix@pnkfx.org> | 2014-10-07 18:30:35 +0200 |
|---|---|---|
| committer | Felix S. Klock II <pnkfelix@pnkfx.org> | 2014-11-24 13:19:26 +0100 |
| commit | f5b795dc82edb4488bf237b470a68fcfec505bac (patch) | |
| tree | 99c30c5af9bee24ec15f2bc9d31ad549409a9b26 /src/compiletest/errors.rs | |
| parent | bad1062caaaefe0963d7b8513786c8283e74f1e7 (diff) | |
| download | rust-f5b795dc82edb4488bf237b470a68fcfec505bac.tar.gz rust-f5b795dc82edb4488bf237b470a68fcfec505bac.zip | |
compiletest: extend syntax with support for choosing same line as previous line.
Diffstat (limited to 'src/compiletest/errors.rs')
| -rw-r--r-- | src/compiletest/errors.rs | 65 |
1 files changed, 56 insertions, 9 deletions
diff --git a/src/compiletest/errors.rs b/src/compiletest/errors.rs index c795e69a44d..f15db7d9371 100644 --- a/src/compiletest/errors.rs +++ b/src/compiletest/errors.rs @@ -7,6 +7,7 @@ // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your // option. This file may not be copied, modified, or distributed // except according to those terms. +use self::WhichLine::*; use std::ascii::AsciiExt; use std::io::{BufferedReader, File}; @@ -18,28 +19,74 @@ pub struct ExpectedError { pub msg: String, } -pub static EXPECTED_PATTERN : &'static str = r"//~(?P<adjusts>\^*)\s*(?P<kind>\S*)\s*(?P<msg>.*)"; +/// Looks for either "//~| KIND MESSAGE" or "//~^^... KIND MESSAGE" +/// The former is a "follow" that inherits its target from the preceding line; +/// the latter is an "adjusts" that goes that many lines up. +/// +/// Goal is to enable tests both like: //~^^^ ERROR go up three +/// and also //~^ ERROR message one for the preceding line, and +/// //~| ERROR message two for that same line. + +pub static EXPECTED_PATTERN : &'static str = + r"//~(?P<follow>\|)?(?P<adjusts>\^*)\s*(?P<kind>\S*)\s*(?P<msg>.*)"; + +#[deriving(PartialEq, Show)] +enum WhichLine { ThisLine, FollowPrevious(uint), AdjustBackward(uint) } // Load any test directives embedded in the file pub fn load_errors(re: &Regex, testfile: &Path) -> Vec<ExpectedError> { let mut rdr = BufferedReader::new(File::open(testfile).unwrap()); + // `last_nonfollow_error` tracks the most recently seen + // line with an error template that did not use the + // follow-syntax, "//~| ...". + // + // (pnkfelix could not find an easy way to compose Iterator::scan + // and Iterator::filter_map to pass along this information into + // `parse_expected`. So instead I am storing that state here and + // updating it in the map callback below.) + let mut last_nonfollow_error = None; + rdr.lines().enumerate().filter_map(|(line_no, ln)| { - parse_expected(line_no + 1, ln.unwrap().as_slice(), re) + parse_expected(last_nonfollow_error, + line_no + 1, + ln.unwrap().as_slice(), re) + .map(|(which, error)| { + match which { + FollowPrevious(_) => {} + _ => last_nonfollow_error = Some(error.line), + } + error + }) }).collect() } -fn parse_expected(line_num: uint, line: &str, re: &Regex) -> Option<ExpectedError> { +fn parse_expected(last_nonfollow_error: Option<uint>, + line_num: uint, + line: &str, + re: &Regex) -> Option<(WhichLine, ExpectedError)> { re.captures(line).and_then(|caps| { let adjusts = caps.name("adjusts").len(); let kind = caps.name("kind").to_ascii_lower(); let msg = caps.name("msg").trim().to_string(); + let follow = caps.name("follow").len() > 0; + + let (which, line) = if follow { + assert!(adjusts == 0, "use either //~| or //~^, not both."); + let line = last_nonfollow_error.unwrap_or_else(|| { + panic!("encountered //~| without preceding //~^ line.") + }); + (FollowPrevious(line), line) + } else { + let which = + if adjusts > 0 { AdjustBackward(adjusts) } else { ThisLine }; + let line = line_num - adjusts; + (which, line) + }; - debug!("line={} kind={} msg={}", line_num, kind, msg); - Some(ExpectedError { - line: line_num - adjusts, - kind: kind, - msg: msg, - }) + debug!("line={} which={} kind={} msg={}", line_num, which, kind, msg); + Some((which, ExpectedError { line: line, + kind: kind, + msg: msg, })) }) } |
