Skip to content

Commit ecc0722

Browse files
committed
restructure StyleChecker
1 parent aacc5cc commit ecc0722

File tree

1 file changed

+81
-50
lines changed

1 file changed

+81
-50
lines changed

libc-test/test/style.rs

Lines changed: 81 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,9 @@
2222
//! 6. extern functions
2323
//! 7. modules + pub use
2424
25-
use std::io::prelude::*;
25+
use std::fmt::Display;
2626
use std::ops::Deref;
27-
use std::path::Path;
27+
use std::path::{Path, PathBuf};
2828
use std::{env, fs};
2929

3030
use syn::parse::{Parse, ParseStream};
@@ -38,17 +38,13 @@ type Result<T> = std::result::Result<T, Error>;
3838
#[test]
3939
fn check_style() {
4040
let root_dir = Path::new(env!("CARGO_MANIFEST_DIR")).join("../src");
41-
let mut errors = Errors { errs: false };
42-
walk(&root_dir, &mut errors).expect("root dir should be walked successfully");
43-
44-
if errors.errs {
45-
panic!("found some lint errors");
46-
} else {
47-
eprintln!("good style!");
48-
}
41+
walk(&root_dir).unwrap();
42+
eprintln!("good style!");
4943
}
5044

51-
fn walk(root_dir: &Path, err: &mut Errors) -> Result<()> {
45+
fn walk(root_dir: &Path) -> Result<()> {
46+
let mut style_checker = StyleChecker::new();
47+
5248
for entry in glob::glob(&format!(
5349
"{}/**/*.rs",
5450
root_dir.to_str().expect("dir should be valid UTF-8")
@@ -64,34 +60,28 @@ fn walk(root_dir: &Path, err: &mut Errors) -> Result<()> {
6460
continue;
6561
}
6662

67-
let mut contents = String::new();
6863
let path = entry.as_path();
69-
fs::File::open(path)?.read_to_string(&mut contents)?;
70-
71-
let file = syn::parse_file(&contents)?;
72-
StyleChecker::new(|line, msg| err.error(&path, line, msg)).visit_file(&file);
64+
style_checker.check_file(path)?;
65+
style_checker.reset_state();
7366
}
7467

75-
Ok(())
76-
}
77-
78-
struct Errors {
79-
errs: bool,
68+
style_checker.finalize()
8069
}
8170

82-
struct StyleChecker<F>
83-
where
84-
F: FnMut(usize, &str),
85-
{
71+
#[derive(Default)]
72+
struct StyleChecker {
8673
state: State,
8774
// FIXME: see StyleChecker::set_state
8875
_s_macros: usize,
8976
f_macros: usize,
90-
on_err: F,
77+
errors: Vec<FileError>,
78+
/// Path of the currently active file
79+
path: PathBuf,
9180
}
9281

93-
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
82+
#[derive(Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
9483
enum State {
84+
#[default]
9585
Start,
9686
Imports,
9787
Typedefs,
@@ -115,24 +105,49 @@ enum ExprCfgElse {
115105
If(ExprCfgIf),
116106
}
117107

118-
impl<F> StyleChecker<F>
119-
where
120-
F: FnMut(usize, &str),
121-
{
122-
fn new(on_err: F) -> Self {
123-
Self {
124-
state: State::Start,
125-
_s_macros: 0,
126-
f_macros: 0,
127-
on_err,
108+
impl StyleChecker {
109+
fn new() -> Self {
110+
Self::default()
111+
}
112+
113+
/// Reads and parses the file at the given path and checks
114+
/// for any style violations.
115+
fn check_file(&mut self, path: &Path) -> Result<()> {
116+
let contents = fs::read_to_string(path)?;
117+
let file = syn::parse_file(&contents)?;
118+
119+
self.path = PathBuf::from(path);
120+
self.visit_file(&file);
121+
122+
Ok(())
123+
}
124+
125+
/// Resets the state of the [StyleChecker].
126+
fn reset_state(&mut self) {
127+
*self = Self {
128+
errors: std::mem::take(&mut self.errors),
129+
..Self::default()
130+
};
131+
}
132+
133+
/// Collect all errors into a single error, reporting them if any.
134+
fn finalize(self) -> Result<()> {
135+
if self.errors.is_empty() {
136+
return Ok(());
128137
}
138+
139+
for error in self.errors {
140+
eprintln!("{error}");
141+
}
142+
143+
Err("some tests failed".into())
129144
}
130145

131146
fn set_state(&mut self, new_state: State, line: usize) {
132147
if self.state > new_state {
133-
(self.on_err)(
148+
self.error(
134149
line,
135-
&format!(
150+
format!(
136151
"{} found after {} when it belongs before",
137152
new_state.desc(),
138153
self.state.desc()
@@ -142,7 +157,7 @@ where
142157

143158
if self.f_macros == 2 {
144159
self.f_macros += 1;
145-
(self.on_err)(line, "multiple f! macros in one module");
160+
self.error(line, "multiple f! macros in one module".to_string());
146161
}
147162

148163
// FIXME(#4109): multiple should be allowed if at least one is `cfg(not) within `cfg_if`.
@@ -177,24 +192,32 @@ where
177192
}
178193
self.state = initial_state;
179194
}
195+
196+
fn error(&mut self, line: usize, msg: String) {
197+
self.errors.push(FileError {
198+
path: self.path.clone(),
199+
line,
200+
msg,
201+
});
202+
}
180203
}
181204

182-
impl<'ast, F> Visit<'ast> for StyleChecker<F>
183-
where
184-
F: FnMut(usize, &str),
185-
{
205+
impl<'ast> Visit<'ast> for StyleChecker {
186206
fn visit_meta_list(&mut self, meta_list: &'ast syn::MetaList) {
187207
let line = meta_list.span().start().line;
188208
let meta_str = meta_list.tokens.to_string();
189209
if meta_list.path.is_ident("cfg")
190210
&& !(meta_str.contains("target_endian") || meta_str.contains("target_arch"))
191211
&& self.state != State::Structs
192212
{
193-
(self.on_err)(line, "use cfg_if! and submodules instead of #[cfg]");
213+
self.error(
214+
line,
215+
"use cfg_if! and submodules instead of #[cfg]".to_string(),
216+
);
194217
} else if meta_list.path.is_ident("derive")
195218
&& (meta_str.contains("Copy") || meta_str.contains("Clone"))
196219
{
197-
(self.on_err)(line, "impl Copy and Clone manually");
220+
self.error(line, "impl Copy and Clone manually".to_string());
198221
}
199222

200223
visit::visit_meta_list(self, meta_list);
@@ -330,9 +353,17 @@ impl State {
330353
}
331354
}
332355

333-
impl Errors {
334-
fn error(&mut self, path: &Path, line: usize, msg: &str) {
335-
self.errs = true;
336-
eprintln!("{}:{}: {}", path.display(), line, msg);
356+
#[derive(Debug)]
357+
struct FileError {
358+
path: PathBuf,
359+
line: usize,
360+
msg: String,
361+
}
362+
363+
impl Display for FileError {
364+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
365+
write!(f, "{}:{}: {}", self.path.display(), self.line, self.msg)
337366
}
338367
}
368+
369+
impl std::error::Error for FileError {}

0 commit comments

Comments
 (0)