mirror of
https://github.com/astral-sh/ruff.git
synced 2025-10-03 15:14:42 +00:00
Ensure that redirect warnings appear exactly once per code (#3500)
This commit is contained in:
parent
8c7317eb8d
commit
1eff3dffa5
2 changed files with 39 additions and 17 deletions
|
@ -1,8 +1,31 @@
|
||||||
|
use std::sync::Mutex;
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use colored::Colorize;
|
use colored::Colorize;
|
||||||
use fern;
|
use fern;
|
||||||
use log::Level;
|
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_export]
|
||||||
macro_rules! warn_user_once {
|
macro_rules! warn_user_once {
|
||||||
($($arg:tt)*) => {
|
($($arg:tt)*) => {
|
||||||
|
|
|
@ -7,11 +7,12 @@ use std::path::{Path, PathBuf};
|
||||||
use anyhow::{anyhow, Result};
|
use anyhow::{anyhow, Result};
|
||||||
use globset::{Glob, GlobMatcher};
|
use globset::{Glob, GlobMatcher};
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
use ruff_cache::cache_dir;
|
|
||||||
use rustc_hash::{FxHashMap, FxHashSet};
|
use rustc_hash::{FxHashMap, FxHashSet};
|
||||||
use strum::IntoEnumIterator;
|
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::registry::{Rule, RuleNamespace, INCOMPATIBLE_CODES};
|
||||||
use crate::rule_selector::{RuleSelector, Specificity};
|
use crate::rule_selector::{RuleSelector, Specificity};
|
||||||
use crate::rules::{
|
use crate::rules::{
|
||||||
|
@ -22,8 +23,9 @@ use crate::rules::{
|
||||||
};
|
};
|
||||||
use crate::settings::configuration::Configuration;
|
use crate::settings::configuration::Configuration;
|
||||||
use crate::settings::types::{FilePatternSet, PerFileIgnore, PythonVersion, SerializationFormat};
|
use crate::settings::types::{FilePatternSet, PerFileIgnore, PythonVersion, SerializationFormat};
|
||||||
use crate::warn_user_once;
|
use crate::warn_user_once_by_id;
|
||||||
use ruff_macros::CacheKey;
|
|
||||||
|
use self::rule_table::RuleTable;
|
||||||
|
|
||||||
pub mod configuration;
|
pub mod configuration;
|
||||||
pub mod defaults;
|
pub mod defaults;
|
||||||
|
@ -361,7 +363,8 @@ impl From<&Configuration> for RuleTable {
|
||||||
|
|
||||||
for (from, target) in redirects {
|
for (from, target) in redirects {
|
||||||
// TODO(martin): This belongs into the ruff_cli crate.
|
// TODO(martin): This belongs into the ruff_cli crate.
|
||||||
crate::warn_user!(
|
warn_user_once_by_id!(
|
||||||
|
from,
|
||||||
"`{from}` has been remapped to `{}{}`.",
|
"`{from}` has been remapped to `{}{}`.",
|
||||||
target.linter().common_prefix(),
|
target.linter().common_prefix(),
|
||||||
target.short_code()
|
target.short_code()
|
||||||
|
@ -389,16 +392,11 @@ impl From<&Configuration> for RuleTable {
|
||||||
|
|
||||||
// Validate that we didn't enable any incompatible rules. Use this awkward
|
// Validate that we didn't enable any incompatible rules. Use this awkward
|
||||||
// approach to give each pair it's own `warn_user_once`.
|
// approach to give each pair it's own `warn_user_once`.
|
||||||
let [pair1, pair2] = INCOMPATIBLE_CODES;
|
for (preferred, expendable, message) in INCOMPATIBLE_CODES {
|
||||||
let (preferred, expendable, message) = pair1;
|
|
||||||
if rules.enabled(preferred) && rules.enabled(expendable) {
|
if rules.enabled(preferred) && rules.enabled(expendable) {
|
||||||
warn_user_once!("{}", message);
|
warn_user_once_by_id!(expendable.as_ref(), "{}", message);
|
||||||
rules.disable(expendable);
|
rules.disable(expendable);
|
||||||
}
|
}
|
||||||
let (preferred, expendable, message) = pair2;
|
|
||||||
if rules.enabled(preferred) && rules.enabled(expendable) {
|
|
||||||
warn_user_once!("{}", message);
|
|
||||||
rules.disable(expendable);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
rules
|
rules
|
||||||
|
@ -428,12 +426,13 @@ pub fn resolve_per_file_ignores(
|
||||||
mod tests {
|
mod tests {
|
||||||
use rustc_hash::FxHashSet;
|
use rustc_hash::FxHashSet;
|
||||||
|
|
||||||
use super::configuration::RuleSelection;
|
|
||||||
use crate::codes::{self, Pycodestyle};
|
use crate::codes::{self, Pycodestyle};
|
||||||
use crate::registry::Rule;
|
use crate::registry::Rule;
|
||||||
use crate::settings::configuration::Configuration;
|
use crate::settings::configuration::Configuration;
|
||||||
use crate::settings::rule_table::RuleTable;
|
use crate::settings::rule_table::RuleTable;
|
||||||
|
|
||||||
|
use super::configuration::RuleSelection;
|
||||||
|
|
||||||
#[allow(clippy::needless_pass_by_value)]
|
#[allow(clippy::needless_pass_by_value)]
|
||||||
fn resolve_rules(selections: impl IntoIterator<Item = RuleSelection>) -> FxHashSet<Rule> {
|
fn resolve_rules(selections: impl IntoIterator<Item = RuleSelection>) -> FxHashSet<Rule> {
|
||||||
RuleTable::from(&Configuration {
|
RuleTable::from(&Configuration {
|
||||||
|
@ -471,7 +470,7 @@ mod tests {
|
||||||
|
|
||||||
let actual = resolve_rules([RuleSelection {
|
let actual = resolve_rules([RuleSelection {
|
||||||
select: Some(vec![Pycodestyle::W.into()]),
|
select: Some(vec![Pycodestyle::W.into()]),
|
||||||
ignore: vec![codes::Pycodestyle::W292.into()],
|
ignore: vec![Pycodestyle::W292.into()],
|
||||||
..RuleSelection::default()
|
..RuleSelection::default()
|
||||||
}]);
|
}]);
|
||||||
let expected = FxHashSet::from_iter([
|
let expected = FxHashSet::from_iter([
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue