Skip to content

Commit db8bba1

Browse files
committed
Rewrite the compiletest directive parser
1 parent 92c6c03 commit db8bba1

File tree

8 files changed

+1707
-0
lines changed

8 files changed

+1707
-0
lines changed

Cargo.lock

+1
Original file line numberDiff line numberDiff line change
@@ -822,6 +822,7 @@ dependencies = [
822822
"rustfix 0.8.1",
823823
"serde",
824824
"serde_json",
825+
"strsim",
825826
"tracing",
826827
"tracing-subscriber",
827828
"unified-diff",

src/tools/compiletest/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ walkdir = "2"
2525
glob = "0.3.0"
2626
anyhow = "1"
2727
home = "0.5.5"
28+
strsim = "0.11.1"
2829

2930
[target.'cfg(unix)'.dependencies]
3031
libc = "0.2"

src/tools/compiletest/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ pub mod compute_diff;
1313
pub mod errors;
1414
pub mod header;
1515
mod json;
16+
mod load_cfg;
1617
mod raise_fd_limit;
1718
mod read2;
1819
pub mod runtest;

src/tools/compiletest/src/load_cfg.rs

+169
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
#![allow(unused)]
2+
3+
mod itemlist;
4+
mod prepare;
5+
6+
use error::{Error, ErrorExt, Result};
7+
8+
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
9+
pub struct LineCol {
10+
pub line: usize,
11+
pub col: usize,
12+
}
13+
14+
impl LineCol {
15+
const fn new(line: usize, col: usize) -> Self {
16+
Self { line, col }
17+
}
18+
}
19+
20+
/// When we need to e.g. build regexes that include a pattern, we need to know what kind of
21+
/// comments to use. Usually we just build a regex for all expressions, even though we don't
22+
/// use them.
23+
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
24+
enum CommentTy {
25+
Slashes,
26+
Hash,
27+
Semi,
28+
}
29+
30+
impl CommentTy {
31+
const fn as_str(self) -> &'static str {
32+
match self {
33+
CommentTy::Slashes => "//",
34+
CommentTy::Hash => "#",
35+
CommentTy::Semi => ";",
36+
}
37+
}
38+
39+
const fn directive(self) -> &'static str {
40+
match self {
41+
CommentTy::Slashes => "//@",
42+
CommentTy::Hash => "#@",
43+
CommentTy::Semi => ";@",
44+
}
45+
}
46+
47+
const fn all() -> &'static [Self] {
48+
&[Self::Slashes, Self::Hash, Self::Semi]
49+
}
50+
}
51+
52+
/// Errors used within the `load_cfg` module
53+
mod error {
54+
use std::fmt;
55+
use std::path::{Path, PathBuf};
56+
57+
use super::LineCol;
58+
59+
pub type Error = Box<dyn std::error::Error>;
60+
pub type Result<T, E = Error> = std::result::Result<T, E>;
61+
62+
#[derive(Debug)]
63+
struct FullError {
64+
msg: Box<str>,
65+
fname: Option<PathBuf>,
66+
pos: Option<LineCol>,
67+
context: Vec<Box<str>>,
68+
}
69+
70+
impl fmt::Display for FullError {
71+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
72+
write!(f, "error: {}", self.msg)?;
73+
74+
let path = self.fname.as_ref().map_or(Path::new("unknown").display(), |p| p.display());
75+
write!(f, "\n parsing '{path}'",)?;
76+
77+
let pos = self.pos.unwrap_or_default();
78+
write!(f, " at line {}, column {}", pos.line, pos.col)?;
79+
80+
if !self.context.is_empty() {
81+
write!(f, "\ncontext: {:#?}", self.context)?;
82+
}
83+
84+
Ok(())
85+
}
86+
}
87+
88+
impl std::error::Error for FullError {}
89+
90+
/// Give us an easy way to tack context onto an error.
91+
pub trait ErrorExt {
92+
fn pos(self, pos: LineCol) -> Self;
93+
fn line(self, line: usize) -> Self;
94+
fn col(self, col: usize) -> Self;
95+
fn fname(self, fname: impl Into<PathBuf>) -> Self;
96+
fn context(self, ctx: impl Into<Box<str>>) -> Self;
97+
}
98+
99+
impl ErrorExt for Error {
100+
fn pos(self, pos: LineCol) -> Self {
101+
let mut fe = to_fullerr(self);
102+
fe.pos = Some(pos);
103+
fe
104+
}
105+
106+
fn line(self, line: usize) -> Self {
107+
let mut fe = to_fullerr(self);
108+
match fe.pos.as_mut() {
109+
Some(v) => v.line = line,
110+
None => fe.pos = Some(LineCol::new(line, 0)),
111+
};
112+
fe
113+
}
114+
115+
fn col(self, col: usize) -> Self {
116+
let mut fe = to_fullerr(self);
117+
match fe.pos.as_mut() {
118+
Some(v) => v.col = col,
119+
None => fe.pos = Some(LineCol::new(0, col)),
120+
};
121+
fe
122+
}
123+
124+
fn fname(self, fname: impl Into<PathBuf>) -> Self {
125+
let mut fe = to_fullerr(self);
126+
fe.fname = Some(fname.into());
127+
fe
128+
}
129+
130+
fn context(self, ctx: impl Into<Box<str>>) -> Self {
131+
let mut fe = to_fullerr(self);
132+
fe.context.push(ctx.into());
133+
fe
134+
}
135+
}
136+
137+
impl<T> ErrorExt for Result<T> {
138+
fn pos(self, pos: LineCol) -> Self {
139+
self.map_err(|e| e.pos(pos))
140+
}
141+
142+
fn line(self, line: usize) -> Self {
143+
self.map_err(|e| e.line(line))
144+
}
145+
146+
fn col(self, col: usize) -> Self {
147+
self.map_err(|e| e.col(col))
148+
}
149+
150+
fn fname(self, fname: impl Into<PathBuf>) -> Self {
151+
self.map_err(|e| e.fname(fname))
152+
}
153+
154+
fn context(self, ctx: impl Into<Box<str>>) -> Self {
155+
self.map_err(|e| e.context(ctx))
156+
}
157+
}
158+
159+
fn to_fullerr(e: Error) -> Box<FullError> {
160+
e.downcast().unwrap_or_else(|e| {
161+
Box::new(FullError {
162+
msg: e.to_string().into(),
163+
fname: None,
164+
pos: None,
165+
context: Vec::new(),
166+
})
167+
})
168+
}
169+
}

0 commit comments

Comments
 (0)