Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add rust edition feature #12

Merged
merged 13 commits into from
Dec 4, 2024
4 changes: 2 additions & 2 deletions src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,8 @@ mod tests {
assert_eq!(args.stderr_file, Some(path::PathBuf::from("test.stderr")));
}

/// clap reports most development errors as `debug_assert!`s
/// See this for more details, [here](https://docs.rs/clap/4.5.15/clap/_derive/_tutorial/chapter_4/index.html)
// clap reports most development errors as `debug_assert!`s
// See this for more details, [here](https://docs.rs/clap/4.5.15/clap/_derive/_tutorial/chapter_4/index.html)
#[test]
fn debug_args() {
use clap::CommandFactory;
Expand Down
21 changes: 16 additions & 5 deletions src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,19 @@ use {
std::{fmt, str::FromStr},
};

// https://docs.rs/once_cell/1.19.0/once_cell/#lazily-compiled-regex
/// Macro used to lazily create a new regex the first time it is invoked.
///
/// # Arguments
///
/// * `re` - The regex literal string used to build the automaton
///
/// # Example
///
/// ```rust
/// assert!(regex!(r"\w").is_match(" "));
/// ```
///
/// Taken from here https://docs.rs/once_cell/1.20.2/once_cell/index.html#lazily-compiled-regex
#[macro_export]
macro_rules! regex {
($re:literal $(,)?) => {{
Expand Down Expand Up @@ -72,26 +84,25 @@ pub struct Error {
/// What kind of message we expect (e.g., warning, error, suggestion).
/// `None` if not specified or unknown message kind.
pub kind: Option<RustcErrorKind>,
///Note: if we are loading this from rustc source file, this might be incomplete
/// Note: if we are loading this from rustc source file, this might be incomplete
pub msg: String,
pub error_code: Option<String>,
}

impl fmt::Display for Error {
/// Formats the `Error` for display according to `DejaGnu` format
/// See `DejaGnu` documentation [here](https://gcc.gnu.org/onlinedocs/gccint/testsuites/directives-used-within-dejagnu-tests/syntax-and-descriptions-of-test-directives.html)
/// See [`DejaGnu` documentation](https://gcc.gnu.org/onlinedocs/gccint/testsuites/directives-used-within-dejagnu-tests/syntax-and-descriptions-of-test-directives.html)
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
use RustcErrorKind::*;

MahadMuhammad marked this conversation as resolved.
Show resolved Hide resolved
let error_code = self.error_code.as_ref().map_or("", |code| &code[..]);

let error_type = match &self.kind {
Some(Help) => "help",
Some(Error) => "dg-error",
Some(Note) => "dg-note",
Some(Suggestion) => "suggestion",
Some(Warning) => "dg-warning",
None => "dg-error",
Some(Error) | None => "dg-error",
};

let error_code = if error_code.is_empty() {
Expand Down
91 changes: 91 additions & 0 deletions src/header.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
//! This module contains the logic for parsing rust test headers
//! See [rustc dev guide](https://rustc-dev-guide.rust-lang.org/tests/headers.html#test-headers)

#[derive(Debug)]
pub struct HeaderLine<'ln> {
pub line_number: usize,
/// The main part of the header directive, after removing the comment prefix
/// and the optional revision specifier.
pub _directive: &'ln str,
/// DejaGnu formatted header line
pub dejagnu_header: String,
}

pub fn parse_additional_options(code: &str) -> Vec<HeaderLine> {
let mut headers = Vec::new();

for (line_number, line) in code.lines().enumerate() {
let line = line.trim();
if line.is_empty() || line.starts_with("fn") || line.starts_with("mod") {
continue;
}
if is_header_line(line) {
if let Some(header_info) = add_additional_options(line, line_number) {
headers.push(header_info);
}
}
}
headers
}

pub fn is_header_line(line: &str) -> bool {
line.trim_start().starts_with("//@")
}

fn add_additional_options(code: &str, line_number: usize) -> Option<HeaderLine> {
//TODO: If we know the file extension, then update this to
// let comment = if testfile.extension().is_some_and(|e| e == "rs") { "//@" } else { "#" };
let comment = "//@";

if let Some((_header_revision, non_revisioned_directive_line)) = line_directive(comment, code) {
// The non_revisioned_directive_line is the directive without the "//@" prefix
let edition = parse_edition(non_revisioned_directive_line)?;
Some(HeaderLine {
line_number: line_number + 1, // 1 based-indexed instead of zero based
_directive: "edition",
dejagnu_header: to_dejagnu_edition(edition.as_str()),
})
} else {
None
}
}

fn line_directive<'line>(
comment: &str,
original_line: &'line str,
) -> Option<(Option<&'line str>, &'line str)> {
let after_comment = original_line
.trim_start()
.strip_prefix(comment)?
.trim_start();

if let Some(after_open_bracket) = after_comment.strip_prefix('[') {
let (line_revision, directive) = after_open_bracket.split_once(']')?;

Some((Some(line_revision), directive.trim_start()))
} else {
Some((None, after_comment))
}
}

fn parse_edition(line: &str) -> Option<String> {
parse_name_value_directive(line, "edition")
}

fn parse_name_value_directive(line: &str, directive: &str) -> Option<String> {
let colon = directive.len();

if line.starts_with(directive) && line.as_bytes().get(colon) == Some(&b':') {
let value = line[(colon + 1)..].to_owned();
Some(value)
} else {
None
}
}

fn to_dejagnu_edition(edition: &str) -> String {
format!(
"// {{ dg-additional-options \"-frust-edition={}\" }}",
edition
)
}
233 changes: 233 additions & 0 deletions src/known-directives.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,233 @@
// Copied from https://github.com/rust-lang/rust/blob/master/src/tools/compiletest/src/command-list.rs
MahadMuhammad marked this conversation as resolved.
Show resolved Hide resolved
pub const KNOWN_DIRECTIVE_NAMES: &[&str] = &[
"assembly-output",
"aux-bin",
"aux-build",
"aux-codegen-backend",
"aux-crate",
"build-aux-docs",
"build-fail",
"build-pass",
"check-fail",
"check-pass",
"check-run-results",
"check-stdout",
"check-test-line-numbers-match",
"compare-output-lines-by-subset",
"compile-flags",
"doc-flags",
"dont-check-compiler-stderr",
"dont-check-compiler-stdout",
"dont-check-failure-status",
"edition",
"error-pattern",
"exec-env",
"failure-status",
"filecheck-flags",
"forbid-output",
"force-host",
"ignore-16bit",
"ignore-32bit",
"ignore-64bit",
"ignore-aarch64",
"ignore-aarch64-unknown-linux-gnu",
"ignore-android",
"ignore-apple",
"ignore-arm",
"ignore-avr",
"ignore-beta",
"ignore-cdb",
"ignore-compare-mode-next-solver",
"ignore-compare-mode-polonius",
"ignore-cross-compile",
"ignore-debug",
"ignore-eabi",
"ignore-emscripten",
"ignore-endian-big",
"ignore-freebsd",
"ignore-fuchsia",
"ignore-gdb",
"ignore-gdb-version",
"ignore-gnu",
"ignore-haiku",
"ignore-horizon",
"ignore-i686-pc-windows-gnu",
"ignore-i686-pc-windows-msvc",
"ignore-illumos",
"ignore-ios",
"ignore-linux",
"ignore-lldb",
"ignore-llvm-version",
"ignore-loongarch64",
"ignore-macabi",
"ignore-macos",
"ignore-mode-assembly",
"ignore-mode-codegen",
"ignore-mode-codegen-units",
"ignore-mode-coverage-map",
"ignore-mode-coverage-run",
"ignore-mode-crashes",
"ignore-mode-debuginfo",
"ignore-mode-incremental",
"ignore-mode-js-doc-test",
"ignore-mode-mir-opt",
"ignore-mode-pretty",
"ignore-mode-run-make",
"ignore-mode-run-pass-valgrind",
"ignore-mode-rustdoc",
"ignore-mode-rustdoc-json",
"ignore-mode-ui",
"ignore-mode-ui-fulldeps",
"ignore-msp430",
"ignore-msvc",
"ignore-musl",
"ignore-netbsd",
"ignore-nightly",
"ignore-none",
"ignore-nto",
"ignore-nvptx64",
"ignore-nvptx64-nvidia-cuda",
"ignore-openbsd",
"ignore-pass",
"ignore-remote",
"ignore-riscv64",
"ignore-s390x",
"ignore-sgx",
"ignore-spirv",
"ignore-stable",
"ignore-stage1",
"ignore-stage2",
"ignore-test",
"ignore-thumb",
"ignore-thumbv8m.base-none-eabi",
"ignore-thumbv8m.main-none-eabi",
"ignore-tvos",
"ignore-unix",
"ignore-unknown",
"ignore-uwp",
"ignore-visionos",
"ignore-vxworks",
"ignore-wasi",
"ignore-wasm",
"ignore-wasm32",
"ignore-wasm32-bare",
"ignore-wasm64",
"ignore-watchos",
"ignore-windows",
"ignore-windows-gnu",
"ignore-windows-msvc",
"ignore-x32",
"ignore-x86",
"ignore-x86_64",
"ignore-x86_64-apple-darwin",
"ignore-x86_64-unknown-linux-gnu",
"incremental",
"known-bug",
"llvm-cov-flags",
"min-cdb-version",
"min-gdb-version",
"min-lldb-version",
"min-llvm-version",
"min-system-llvm-version",
"needs-asm-support",
"needs-dlltool",
"needs-dynamic-linking",
"needs-force-clang-based-tests",
"needs-git-hash",
"needs-llvm-components",
"needs-profiler-support",
"needs-relocation-model-pic",
"needs-run-enabled",
"needs-rust-lld",
"needs-rust-lldb",
"needs-sanitizer-address",
"needs-sanitizer-cfi",
"needs-sanitizer-dataflow",
"needs-sanitizer-hwaddress",
"needs-sanitizer-kcfi",
"needs-sanitizer-leak",
"needs-sanitizer-memory",
"needs-sanitizer-memtag",
"needs-sanitizer-safestack",
"needs-sanitizer-shadow-call-stack",
"needs-sanitizer-support",
"needs-sanitizer-thread",
"needs-symlink",
"needs-threads",
"needs-unwind",
"needs-wasmtime",
"needs-xray",
"no-auto-check-cfg",
"no-prefer-dynamic",
"normalize-stderr-32bit",
"normalize-stderr-64bit",
"normalize-stderr-test",
"normalize-stdout-test",
"only-16bit",
"only-32bit",
"only-64bit",
"only-aarch64",
"only-aarch64-unknown-linux-gnu",
"only-apple",
"only-arm",
"only-avr",
"only-beta",
"only-bpf",
"only-cdb",
"only-gnu",
"only-i686-pc-windows-gnu",
"only-i686-pc-windows-msvc",
"only-ios",
"only-linux",
"only-loongarch64",
"only-loongarch64-unknown-linux-gnu",
"only-macos",
"only-mips",
"only-mips64",
"only-msp430",
"only-msvc",
"only-nightly",
"only-nvptx64",
"only-riscv64",
"only-sparc",
"only-sparc64",
"only-stable",
"only-thumb",
"only-tvos",
"only-unix",
"only-visionos",
"only-wasm32",
"only-wasm32-bare",
"only-wasm32-wasip1",
"only-watchos",
"only-windows",
"only-windows-gnu",
"only-windows-msvc",
"only-x86",
"only-x86_64",
"only-x86_64-fortanix-unknown-sgx",
"only-x86_64-pc-windows-gnu",
"only-x86_64-pc-windows-msvc",
"only-x86_64-unknown-linux-gnu",
"pp-exact",
"pretty-compare-only",
"pretty-expanded",
"pretty-mode",
"regex-error-pattern",
"remap-src-base",
"revisions",
"run-fail",
"run-flags",
"run-pass",
"run-rustfix",
"rustc-env",
"rustfix-only-machine-applicable",
"should-fail",
"should-ice",
"stderr-per-bitwidth",
"test-mir-pass",
"unique-doc-out-dir",
"unset-exec-env",
"unset-rustc-env",
"unused-revision-names",
];
Loading