diff --git a/Cargo.lock b/Cargo.lock index accf97ec..51fb09b7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -315,6 +315,7 @@ dependencies = [ "clap-cargo", "clap-verbosity-flag", "directories", + "fs-err", "gix", "handlebars", "human-panic", @@ -753,6 +754,15 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "fs-err" +version = "2.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88a41f105fe1d5b6b34b2055e3dc59bb79b46b48b2040b9e6c7b4b5de097aa41" +dependencies = [ + "autocfg", +] + [[package]] name = "futures-channel" version = "0.3.30" diff --git a/Cargo.toml b/Cargo.toml index 558730a3..d22200e9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -50,6 +50,7 @@ anstream = "0.6.13" assert_cmd = "2.0" similar-asserts = { version = "1.5.0", features = ["serde"] } predicates = "3.1.0" +fs-err = "2.11.0" # In dev and test profiles, compile all dependencies with optimizations enabled, # but still checking debug assertions and overflows. diff --git a/src/query.rs b/src/query.rs index 91438f2e..4574b605 100644 --- a/src/query.rs +++ b/src/query.rs @@ -223,6 +223,9 @@ impl From>> for OverrideStack { #[cfg(test)] mod tests { + use std::borrow::Cow; + use std::collections::BTreeSet; + use std::path::PathBuf; use std::sync::{Arc, OnceLock}; use std::{collections::BTreeMap, path::Path}; @@ -694,6 +697,42 @@ mod tests { RequiredSemverUpdate::Minor ); } + + pub(super) fn check_all_lint_files_are_used_in_add_lints(added_lints: &[&str]) { + let mut lints_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR")); + lints_dir.push("src"); + lints_dir.push("lints"); + + let expected_lints: BTreeSet<_> = added_lints.iter().copied().collect(); + let mut missing_lints: BTreeSet = Default::default(); + + let dir_contents = + fs_err::read_dir(lints_dir).expect("failed to read 'src/lints' directory"); + for file in dir_contents { + let file = file.expect("failed to examine file"); + let path = file.path(); + + // Check if we found a `*.ron` file. If so, that's a lint. + if path.extension().map(|x| x.to_string_lossy()) == Some(Cow::Borrowed("ron")) { + let stem = path + .file_stem() + .map(|x| x.to_string_lossy()) + .expect("failed to get file name as utf-8"); + + // Check if the lint was added using our `add_lints!()` macro. + // If not, that's an error. + if !expected_lints.contains(stem.as_ref()) { + missing_lints.insert(stem.to_string()); + } + } + } + + assert!( + missing_lints.is_empty(), + "some lints in 'src/lints/' haven't been registered using the `add_lints!()` macro, \ + so they won't be part of cargo-semver-checks: {missing_lints:?}" + ) + } } macro_rules! add_lints { @@ -706,6 +745,17 @@ macro_rules! add_lints { super::tests::check_query_execution(stringify!($name)) } )* + + #[test] + fn all_lint_files_are_used_in_add_lints() { + let added_lints = [ + $( + stringify!($name), + )* + ]; + + super::tests::check_all_lint_files_are_used_in_add_lints(&added_lints); + } } fn get_queries() -> Vec<(&'static str, &'static str)> {