use std::sync::Mutex;
static PRINTED: Mutex<Vec<&'static str>> = Mutex::new(Vec::new());
pub fn warn_deprecated(id: &'static str, what: &str, guidance: &str) -> bool {
if !mark_seen(id) {
return false;
}
eprintln!("{}", format_deprecation_warning(what, guidance));
true
}
fn mark_seen(id: &'static str) -> bool {
let mut printed = PRINTED
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner);
if printed.contains(&id) {
false
} else {
printed.push(id);
true
}
}
#[must_use]
pub fn format_deprecation_warning(what: &str, guidance: &str) -> String {
format!("hh: warning: {what} is deprecated; {guidance}")
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn format_matches_the_standard_shape() {
assert_eq!(
format_deprecation_warning("`--foo`", "use `--bar` instead"),
"hh: warning: `--foo` is deprecated; use `--bar` instead"
);
}
#[test]
fn warn_deprecated_prints_at_most_once_per_id() {
let id = "test-only:warn_deprecated_prints_at_most_once_per_id";
assert!(
warn_deprecated(id, "thing", "do X instead"),
"first call for a fresh id must print"
);
assert!(
!warn_deprecated(id, "thing", "do X instead"),
"second call for the same id must be a no-op"
);
}
#[test]
fn distinct_ids_each_print_once() {
assert!(warn_deprecated(
"test-only:distinct_ids_each_print_once:a",
"a",
"guidance a"
));
assert!(warn_deprecated(
"test-only:distinct_ids_each_print_once:b",
"b",
"guidance b"
));
}
}