//! Module-layout checks.
//!
//! `clippy::mod_module_files` is the primary enforcement for the no-`mod.rs`
//! rule, but it is a `restriction` lint with reported cases of failing to fire
//! (rust-clippy#8123), and a layout rule that silently stops being enforced is
//! worse than no rule. This is the independent second mechanism.
use std::fs;
use std::path::{Path, PathBuf};
use anyhow::{Result, bail};
pub(crate) fn run() -> Result<()> {
let root = crate::workspace_root()?;
let mut mod_rs = Vec::new();
for dir in ["crates", "xtask"] {
let path = root.join(dir);
if path.is_dir() {
walk(&path, &mut mod_rs)?;
}
}
if !mod_rs.is_empty() {
eprintln!("module layout: `mod.rs` is not permitted; use `foo.rs` alongside `foo/`");
for p in &mod_rs {
eprintln!(" {}", p.display());
}
bail!("layout check failed");
}
eprintln!("layout: ok (no mod.rs)");
Ok(())
}
fn walk(dir: &Path, mod_rs: &mut Vec<PathBuf>) -> Result<()> {
for entry in fs::read_dir(dir)? {
let entry = entry?;
let path = entry.path();
let file_type = entry.file_type()?;
if file_type.is_dir() {
if path.file_name().is_some_and(|n| n == "target") {
continue;
}
walk(&path, mod_rs)?;
continue;
}
if path.file_name().is_some_and(|n| n == "mod.rs") {
mod_rs.push(path);
}
}
Ok(())
}