diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index 67ecdaf9e5e13..48149e3b897e1 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -978,10 +978,10 @@ impl Config { } } - fn parse_custom_normalization(&self, line: &str) -> Option { + fn parse_custom_normalization(&self, raw_directive: &str) -> Option { // FIXME(Zalathar): Integrate name/value splitting into `DirectiveLine` // instead of doing it here. - let (directive_name, _value) = line.split_once(':')?; + let (directive_name, raw_value) = raw_directive.split_once(':')?; let kind = match directive_name { "normalize-stdout" => NormalizeKind::Stdout, @@ -991,11 +991,9 @@ impl Config { _ => return None, }; - // FIXME(Zalathar): The normalize rule parser should only care about - // the value part, not the "line" (which isn't even the whole line). - let Some((regex, replacement)) = parse_normalize_rule(line) else { + let Some((regex, replacement)) = parse_normalize_rule(raw_value) else { panic!( - "couldn't parse custom normalization rule: `{line}`\n\ + "couldn't parse custom normalization rule: `{raw_directive}`\n\ help: expected syntax is: `{directive_name}: \"REGEX\" -> \"REPLACEMENT\"`" ); }; @@ -1141,24 +1139,26 @@ enum NormalizeKind { /// Parses the regex and replacement values of a `//@ normalize-*` header, /// in the format: /// ```text -/// normalize-*: "REGEX" -> "REPLACEMENT" +/// "REGEX" -> "REPLACEMENT" /// ``` -fn parse_normalize_rule(header: &str) -> Option<(String, String)> { +fn parse_normalize_rule(raw_value: &str) -> Option<(String, String)> { // FIXME: Support escaped double-quotes in strings. let captures = static_regex!( r#"(?x) # (verbose mode regex) ^ - [^:\s]+:\s* # (header name followed by colon) + \s* # (leading whitespace) "(?[^"]*)" # "REGEX" \s+->\s+ # -> "(?[^"]*)" # "REPLACEMENT" $ "# ) - .captures(header)?; + .captures(raw_value)?; let regex = captures["regex"].to_owned(); let replacement = captures["replacement"].to_owned(); - // FIXME: Support escaped new-line in strings. + // A `\n` sequence in the replacement becomes an actual newline. + // FIXME: Do unescaping in a less ad-hoc way, and perhaps support escaped + // backslashes and double-quotes. let replacement = replacement.replace("\\n", "\n"); Some((regex, replacement)) } diff --git a/src/tools/compiletest/src/header/tests.rs b/src/tools/compiletest/src/header/tests.rs index cd7c6f8361ed3..618b66dfd4cb6 100644 --- a/src/tools/compiletest/src/header/tests.rs +++ b/src/tools/compiletest/src/header/tests.rs @@ -35,11 +35,14 @@ fn make_test_description( #[test] fn test_parse_normalize_rule() { - let good_data = &[( - r#"normalize-stderr-32bit: "something (32 bits)" -> "something ($WORD bits)""#, - "something (32 bits)", - "something ($WORD bits)", - )]; + let good_data = &[ + ( + r#""something (32 bits)" -> "something ($WORD bits)""#, + "something (32 bits)", + "something ($WORD bits)", + ), + (r#" " with whitespace" -> " replacement""#, " with whitespace", " replacement"), + ]; for &(input, expected_regex, expected_replacement) in good_data { let parsed = parse_normalize_rule(input); @@ -49,15 +52,15 @@ fn test_parse_normalize_rule() { } let bad_data = &[ - r#"normalize-stderr-32bit "something (32 bits)" -> "something ($WORD bits)""#, - r#"normalize-stderr-16bit: something (16 bits) -> something ($WORD bits)"#, - r#"normalize-stderr-32bit: something (32 bits) -> something ($WORD bits)"#, - r#"normalize-stderr-32bit: "something (32 bits) -> something ($WORD bits)"#, - r#"normalize-stderr-32bit: "something (32 bits)" -> "something ($WORD bits)"#, - r#"normalize-stderr-32bit: "something (32 bits)" -> "something ($WORD bits)"."#, + r#"something (11 bits) -> something ($WORD bits)"#, + r#"something (12 bits) -> something ($WORD bits)"#, + r#""something (13 bits) -> something ($WORD bits)"#, + r#""something (14 bits)" -> "something ($WORD bits)"#, + r#""something (15 bits)" -> "something ($WORD bits)"."#, ]; for &input in bad_data { + println!("- {input:?}"); let parsed = parse_normalize_rule(input); assert_eq!(parsed, None); } diff --git a/tests/ui/compiletest-self-test/normalize-with-revision.a.run.stderr b/tests/ui/compiletest-self-test/normalize-with-revision.a.run.stderr new file mode 100644 index 0000000000000..3eb3f6b4e5712 --- /dev/null +++ b/tests/ui/compiletest-self-test/normalize-with-revision.a.run.stderr @@ -0,0 +1,2 @@ +1st emitted line +second emitted line diff --git a/tests/ui/compiletest-self-test/normalize-with-revision.b.run.stderr b/tests/ui/compiletest-self-test/normalize-with-revision.b.run.stderr new file mode 100644 index 0000000000000..8d9156480abff --- /dev/null +++ b/tests/ui/compiletest-self-test/normalize-with-revision.b.run.stderr @@ -0,0 +1,2 @@ +first emitted line +2nd emitted line diff --git a/tests/ui/compiletest-self-test/normalize-with-revision.rs b/tests/ui/compiletest-self-test/normalize-with-revision.rs new file mode 100644 index 0000000000000..e1bbbb3eabb70 --- /dev/null +++ b/tests/ui/compiletest-self-test/normalize-with-revision.rs @@ -0,0 +1,20 @@ +//! Checks that `[rev] normalize-*` directives affect the specified revision, +//! and don't affect other revisions. +//! +//! This currently relies on the fact that `normalize-*` directives are +//! applied to run output, not just compiler output. If that ever changes, +//! this test might need to be adjusted. + +//@ edition: 2021 +//@ revisions: a b +//@ run-pass +//@ check-run-results + +//@ normalize-stderr: "output" -> "emitted" +//@[a] normalize-stderr: "first" -> "1st" +//@[b] normalize-stderr: "second" -> "2nd" + +fn main() { + eprintln!("first output line"); + eprintln!("second output line"); +}