From 54d51bc48396b89954a10c936f6797064ccdbc29 Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Fri, 15 Nov 2019 21:40:05 -0800 Subject: [PATCH] Allow multiple cfgs per comment in "revisions:" tests The `//[X]~` syntax filters errors for tests that are run across multiple cfgs with `// revisions:`. This commit extends that syntax to accept `//[X,Y]~`, which will match multiple cfgs to the same error annotation. This is functionally the same as writing two comments, `//[X]~` and `//[Y]~`, but can fit on a single line. --- src/tools/compiletest/src/errors.rs | 89 +++++++++++++++-------------- 1 file changed, 47 insertions(+), 42 deletions(-) diff --git a/src/tools/compiletest/src/errors.rs b/src/tools/compiletest/src/errors.rs index 5b3936ffc1e..2524468766f 100644 --- a/src/tools/compiletest/src/errors.rs +++ b/src/tools/compiletest/src/errors.rs @@ -7,7 +7,9 @@ use std::path::Path; use std::str::FromStr; +use lazy_static::lazy_static; use log::*; +use regex::Regex; #[derive(Clone, Debug, PartialEq)] pub enum ErrorKind { @@ -85,20 +87,16 @@ pub fn load_errors(testfile: &Path, cfg: Option<&str>) -> Vec { // updating it in the map callback below.) let mut last_nonfollow_error = None; - let tag = match cfg { - Some(rev) => format!("//[{}]~", rev), - None => "//~".to_string(), - }; - rdr.lines() .enumerate() .filter_map(|(line_num, line)| { - parse_expected(last_nonfollow_error, line_num + 1, &line.unwrap(), &tag).map( + parse_expected(last_nonfollow_error, line_num + 1, &line.unwrap(), cfg).map( |(which, error)| { match which { FollowPrevious(_) => {} _ => last_nonfollow_error = Some(error.line_num), } + error }, ) @@ -110,46 +108,53 @@ fn parse_expected( last_nonfollow_error: Option, line_num: usize, line: &str, - tag: &str, + cfg: Option<&str>, ) -> Option<(WhichLine, Error)> { - let start = line.find(tag)?; - let (follow, adjusts) = if line[start + tag.len()..].chars().next().unwrap() == '|' { - (true, 0) - } else { - ( - false, - line[start + tag.len()..] - .chars() - .take_while(|c| *c == '^') - .count(), - ) + // Matches comments like: + // //~ + // //~| + // //~^ + // //~^^^^^ + // //[cfg1]~ + // //[cfg1,cfg2]~^^ + lazy_static! { + static ref RE: Regex = + Regex::new(r"//(?:\[(?P[\w,]+)])?~(?P\||\^*)").unwrap(); + } + + let captures = RE.captures(line)?; + + match (cfg, captures.name("cfgs")) { + // Only error messages that contain our `cfg` betweeen the square brackets apply to us. + (Some(cfg), Some(filter)) if !filter.as_str().split(',').any(|s| s == cfg) + => return None, + (Some(_), Some(_)) => {} + + (None, Some(_)) => panic!("Only tests with revisions should use `//[X]~`"), + + // If an error has no list of revisions, it applies to all revisions. + (Some(_), None) | (None, None) => {} + } + + let (follow, adjusts) = match &captures["adjust"] { + "|" => (true, 0), + circumflexes => (false, circumflexes.len()), }; - let kind_start = start + tag.len() + adjusts + (follow as usize); - let (kind, msg); - match line[kind_start..] + + // Get the part of the comment after the sigil (e.g. `~^^` or ~|). + let (_, mut msg) = line.split_at(captures.get(0).unwrap().end()); + + let first_word = msg .split_whitespace() .next() - .expect("Encountered unexpected empty comment") - .parse::() - { - Ok(k) => { - // If we find `//~ ERROR foo` or something like that: - kind = Some(k); - let letters = line[kind_start..].chars(); - msg = letters - .skip_while(|c| c.is_whitespace()) - .skip_while(|c| !c.is_whitespace()) - .collect::(); - } - Err(_) => { - // Otherwise we found `//~ foo`: - kind = None; - let letters = line[kind_start..].chars(); - msg = letters - .skip_while(|c| c.is_whitespace()) - .collect::(); - } + .expect("Encountered unexpected empty comment"); + + // If we find `//~ ERROR foo` or something like that, skip the first word. + let kind = first_word.parse::().ok(); + if let Some(_) = kind { + msg = &msg.trim_start().split_at(first_word.len()).1; } + let msg = msg.trim().to_owned(); let (which, line_num) = if follow { @@ -171,7 +176,7 @@ fn parse_expected( debug!( "line={} tag={:?} which={:?} kind={:?} msg={:?}", - line_num, tag, which, kind, msg + line_num, &captures[0], which, kind, msg ); Some(( which, -- 2.44.0