compiletest: extend syntax with support for choosing same line as previous line.
This commit is contained in:
parent
bad1062caa
commit
f5b795dc82
@ -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;
|
||||
|
||||
debug!("line={} kind={} msg={}", line_num, kind, msg);
|
||||
Some(ExpectedError {
|
||||
line: line_num - adjusts,
|
||||
kind: kind,
|
||||
msg: msg,
|
||||
})
|
||||
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={} which={} kind={} msg={}", line_num, which, kind, msg);
|
||||
Some((which, ExpectedError { line: line,
|
||||
kind: kind,
|
||||
msg: msg, }))
|
||||
})
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user