Ensure that redirect warnings appear exactly once per code (#3500)

This commit is contained in:
Charlie Marsh 2023-03-14 11:22:14 -04:00 committed by GitHub
parent 8c7317eb8d
commit 1eff3dffa5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 39 additions and 17 deletions

View file

@ -1,8 +1,31 @@
use std::sync::Mutex;
use anyhow::Result;
use colored::Colorize;
use fern;
use log::Level;
use once_cell::sync::Lazy;
pub(crate) static WARNINGS: Lazy<Mutex<Vec<&'static str>>> = Lazy::new(Mutex::default);
/// Warn a user once, with uniqueness determined by the given ID.
#[macro_export]
macro_rules! warn_user_once_by_id {
($id:expr, $($arg:tt)*) => {
use colored::Colorize;
use log::warn;
if let Ok(mut states) = $crate::logging::WARNINGS.lock() {
if !states.contains(&$id) {
let message = format!("{}", format_args!($($arg)*));
warn!("{}", message.bold());
states.push($id);
}
}
};
}
/// Warn a user once, with uniqueness determined by the calling location itself.
#[macro_export]
macro_rules! warn_user_once {
($($arg:tt)*) => {

View file

@ -7,11 +7,12 @@ use std::path::{Path, PathBuf};
use anyhow::{anyhow, Result};
use globset::{Glob, GlobMatcher};
use regex::Regex;
use ruff_cache::cache_dir;
use rustc_hash::{FxHashMap, FxHashSet};
use strum::IntoEnumIterator;
use self::rule_table::RuleTable;
use ruff_cache::cache_dir;
use ruff_macros::CacheKey;
use crate::registry::{Rule, RuleNamespace, INCOMPATIBLE_CODES};
use crate::rule_selector::{RuleSelector, Specificity};
use crate::rules::{
@ -22,8 +23,9 @@ use crate::rules::{
};
use crate::settings::configuration::Configuration;
use crate::settings::types::{FilePatternSet, PerFileIgnore, PythonVersion, SerializationFormat};
use crate::warn_user_once;
use ruff_macros::CacheKey;
use crate::warn_user_once_by_id;
use self::rule_table::RuleTable;
pub mod configuration;
pub mod defaults;
@ -361,7 +363,8 @@ impl From<&Configuration> for RuleTable {
for (from, target) in redirects {
// TODO(martin): This belongs into the ruff_cli crate.
crate::warn_user!(
warn_user_once_by_id!(
from,
"`{from}` has been remapped to `{}{}`.",
target.linter().common_prefix(),
target.short_code()
@ -389,16 +392,11 @@ impl From<&Configuration> for RuleTable {
// Validate that we didn't enable any incompatible rules. Use this awkward
// approach to give each pair it's own `warn_user_once`.
let [pair1, pair2] = INCOMPATIBLE_CODES;
let (preferred, expendable, message) = pair1;
for (preferred, expendable, message) in INCOMPATIBLE_CODES {
if rules.enabled(preferred) && rules.enabled(expendable) {
warn_user_once!("{}", message);
warn_user_once_by_id!(expendable.as_ref(), "{}", message);
rules.disable(expendable);
}
let (preferred, expendable, message) = pair2;
if rules.enabled(preferred) && rules.enabled(expendable) {
warn_user_once!("{}", message);
rules.disable(expendable);
}
rules
@ -428,12 +426,13 @@ pub fn resolve_per_file_ignores(
mod tests {
use rustc_hash::FxHashSet;
use super::configuration::RuleSelection;
use crate::codes::{self, Pycodestyle};
use crate::registry::Rule;
use crate::settings::configuration::Configuration;
use crate::settings::rule_table::RuleTable;
use super::configuration::RuleSelection;
#[allow(clippy::needless_pass_by_value)]
fn resolve_rules(selections: impl IntoIterator<Item = RuleSelection>) -> FxHashSet<Rule> {
RuleTable::from(&Configuration {
@ -471,7 +470,7 @@ mod tests {
let actual = resolve_rules([RuleSelection {
select: Some(vec![Pycodestyle::W.into()]),
ignore: vec![codes::Pycodestyle::W292.into()],
ignore: vec![Pycodestyle::W292.into()],
..RuleSelection::default()
}]);
let expected = FxHashSet::from_iter([