Rollup merge of #150205 - Enselic:line-no, r=Zalathar,jieyouxu
compiletest: Add `LineNumber` newtype to avoid `+1` magic here and there Start small. If it works well we can increase usage bit by bit as time passes. My main motivation for doing this is to get rid of the `+ 1` I otherwise have to add in https://github.com/rust-lang/rust/pull/150201 on this line: ```rs crate::directives::line::line_directive(file, zero_based_line_no + 1, &line) ``` But I think this is a nice general improvement by itself. Note that we keep using "0" to represent "no specific line" because changing to `Option<LineNumber>` everywhere is a very noisy and significant change. That _can_ be changed later if wanted, but let's not do it now.
This commit is contained in:
commit
c0337ca5f0
6 changed files with 42 additions and 17 deletions
|
|
@ -29,6 +29,8 @@ mod directive_names;
|
|||
mod file;
|
||||
mod handlers;
|
||||
mod line;
|
||||
mod line_number;
|
||||
pub(crate) use line_number::LineNumber;
|
||||
mod needs;
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
|
@ -591,7 +593,7 @@ fn iter_directives(
|
|||
];
|
||||
// Process the extra implied directives, with a dummy line number of 0.
|
||||
for directive_str in extra_directives {
|
||||
let directive_line = line_directive(testfile, 0, directive_str)
|
||||
let directive_line = line_directive(testfile, LineNumber::ZERO, directive_str)
|
||||
.unwrap_or_else(|| panic!("bad extra-directive line: {directive_str:?}"));
|
||||
it(&directive_line);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
use camino::Utf8Path;
|
||||
|
||||
use crate::directives::LineNumber;
|
||||
use crate::directives::line::{DirectiveLine, line_directive};
|
||||
|
||||
pub(crate) struct FileDirectives<'a> {
|
||||
|
|
@ -11,7 +12,7 @@ impl<'a> FileDirectives<'a> {
|
|||
pub(crate) fn from_file_contents(path: &'a Utf8Path, file_contents: &'a str) -> Self {
|
||||
let mut lines = vec![];
|
||||
|
||||
for (line_number, ln) in (1..).zip(file_contents.lines()) {
|
||||
for (line_number, ln) in LineNumber::enumerate().zip(file_contents.lines()) {
|
||||
let ln = ln.trim();
|
||||
|
||||
if let Some(directive_line) = line_directive(path, line_number, ln) {
|
||||
|
|
|
|||
|
|
@ -2,13 +2,15 @@ use std::fmt;
|
|||
|
||||
use camino::Utf8Path;
|
||||
|
||||
use crate::directives::LineNumber;
|
||||
|
||||
const COMPILETEST_DIRECTIVE_PREFIX: &str = "//@";
|
||||
|
||||
/// If the given line begins with the appropriate comment prefix for a directive,
|
||||
/// returns a struct containing various parts of the directive.
|
||||
pub(crate) fn line_directive<'a>(
|
||||
file_path: &'a Utf8Path,
|
||||
line_number: usize,
|
||||
line_number: LineNumber,
|
||||
original_line: &'a str,
|
||||
) -> Option<DirectiveLine<'a>> {
|
||||
// Ignore lines that don't start with the comment prefix.
|
||||
|
|
@ -60,7 +62,7 @@ pub(crate) struct DirectiveLine<'a> {
|
|||
/// Mostly used for diagnostics, but some directives (e.g. `//@ pp-exact`)
|
||||
/// also use it to compute a value based on the filename.
|
||||
pub(crate) file_path: &'a Utf8Path,
|
||||
pub(crate) line_number: usize,
|
||||
pub(crate) line_number: LineNumber,
|
||||
|
||||
/// Some test directives start with a revision name in square brackets
|
||||
/// (e.g. `[foo]`), and only apply to that revision of the test.
|
||||
|
|
|
|||
21
src/tools/compiletest/src/directives/line_number.rs
Normal file
21
src/tools/compiletest/src/directives/line_number.rs
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
/// A line number in a file. Internally the first line has index 1.
|
||||
/// If it is 0 it means "no specific line" (used e.g. for implied directives).
|
||||
/// When `Display`:ed, the first line is `1`.
|
||||
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub(crate) struct LineNumber(usize);
|
||||
|
||||
impl LineNumber {
|
||||
/// This represents "no specific line" (used e.g. for implied directives).
|
||||
pub(crate) const ZERO: Self = Self(0);
|
||||
|
||||
/// A never ending iterator over line numbers starting from the first line.
|
||||
pub(crate) fn enumerate() -> impl Iterator<Item = LineNumber> {
|
||||
(1..).map(LineNumber)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for LineNumber {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{}", self.0)
|
||||
}
|
||||
}
|
||||
|
|
@ -6,8 +6,8 @@ use semver::Version;
|
|||
use crate::common::{Config, Debugger, TestMode};
|
||||
use crate::directives::{
|
||||
self, AuxProps, DIRECTIVE_HANDLERS_MAP, DirectivesCache, EarlyProps, Edition, EditionRange,
|
||||
FileDirectives, KNOWN_DIRECTIVE_NAMES_SET, extract_llvm_version, extract_version_range,
|
||||
line_directive, parse_edition, parse_normalize_rule,
|
||||
FileDirectives, KNOWN_DIRECTIVE_NAMES_SET, LineNumber, extract_llvm_version,
|
||||
extract_version_range, line_directive, parse_edition, parse_normalize_rule,
|
||||
};
|
||||
use crate::executor::{CollectedTestDesc, ShouldFail};
|
||||
|
||||
|
|
@ -1000,7 +1000,8 @@ fn parse_edition_range(line: &str) -> Option<EditionRange> {
|
|||
let config = cfg().build();
|
||||
|
||||
let line_with_comment = format!("//@ {line}");
|
||||
let line = line_directive(Utf8Path::new("tmp.rs"), 0, &line_with_comment).unwrap();
|
||||
let line =
|
||||
line_directive(Utf8Path::new("tmp.rs"), LineNumber::ZERO, &line_with_comment).unwrap();
|
||||
|
||||
super::parse_edition_range(&config, &line)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ use std::io::{BufRead, BufReader};
|
|||
|
||||
use camino::{Utf8Path, Utf8PathBuf};
|
||||
|
||||
use crate::directives::LineNumber;
|
||||
use crate::runtest::ProcRes;
|
||||
|
||||
/// Representation of information to invoke a debugger and check its output
|
||||
|
|
@ -11,9 +12,9 @@ pub(super) struct DebuggerCommands {
|
|||
/// Commands for the debuuger
|
||||
pub commands: Vec<String>,
|
||||
/// Lines to insert breakpoints at
|
||||
pub breakpoint_lines: Vec<usize>,
|
||||
pub breakpoint_lines: Vec<LineNumber>,
|
||||
/// Contains the source line number to check and the line itself
|
||||
check_lines: Vec<(usize, String)>,
|
||||
check_lines: Vec<(LineNumber, String)>,
|
||||
/// Source file name
|
||||
file: Utf8PathBuf,
|
||||
}
|
||||
|
|
@ -26,15 +27,13 @@ impl DebuggerCommands {
|
|||
let mut breakpoint_lines = vec![];
|
||||
let mut commands = vec![];
|
||||
let mut check_lines = vec![];
|
||||
let mut counter = 0;
|
||||
let reader = BufReader::new(File::open(file.as_std_path()).unwrap());
|
||||
for (line_no, line) in reader.lines().enumerate() {
|
||||
counter += 1;
|
||||
for (line_number, line) in LineNumber::enumerate().zip(reader.lines()) {
|
||||
let line = line.map_err(|e| format!("Error while parsing debugger commands: {}", e))?;
|
||||
|
||||
// Breakpoints appear on lines with actual code, typically at the end of the line.
|
||||
if line.contains("#break") {
|
||||
breakpoint_lines.push(counter);
|
||||
breakpoint_lines.push(line_number);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -46,7 +45,7 @@ impl DebuggerCommands {
|
|||
commands.push(command);
|
||||
}
|
||||
if let Some(pattern) = parse_name_value(&line, &check_directive) {
|
||||
check_lines.push((line_no, pattern));
|
||||
check_lines.push((line_number, pattern));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -88,15 +87,14 @@ impl DebuggerCommands {
|
|||
);
|
||||
|
||||
for (src_lineno, err_line) in missing {
|
||||
write!(msg, "\n ({fname}:{num}) `{err_line}`", num = src_lineno + 1).unwrap();
|
||||
write!(msg, "\n ({fname}:{src_lineno}) `{err_line}`").unwrap();
|
||||
}
|
||||
|
||||
if !found.is_empty() {
|
||||
let init = "\nthe following subset of check directive(s) was found successfully:";
|
||||
msg.push_str(init);
|
||||
for (src_lineno, found_line) in found {
|
||||
write!(msg, "\n ({fname}:{num}) `{found_line}`", num = src_lineno + 1)
|
||||
.unwrap();
|
||||
write!(msg, "\n ({fname}:{src_lineno}) `{found_line}`").unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue