mirror of
https://github.com/astral-sh/ruff.git
synced 2025-08-01 17:32:25 +00:00
refactor: Turn RuleSelector into a newtype around RuleCodePrefix
Yet another refactor to let us implement the many-to-many mapping
between codes and rules in a prefix-agnostic way.
We want to break up the RuleCodePrefix[1] enum into smaller enums.
To facilitate that this commit introduces a new wrapping type around
RuleCodePrefix so that we can start breaking it apart.
[1]: Actually `RuleCodePrefix` is the previous name of the autogenerated
enum ... I renamed it in b19258a243
to
RuleSelector since `ALL` isn't a prefix. This commit now renames it back
but only because the new `RuleSelector` wrapper type, introduced in this
commit, will let us move the `ALL` variant from `RuleCodePrefix` to
`RuleSelector` in the next commit.
This commit is contained in:
parent
a20482961b
commit
abc9810e2b
18 changed files with 209 additions and 121 deletions
|
@ -3,11 +3,12 @@ use std::path::PathBuf;
|
|||
use clap::{command, Parser};
|
||||
use regex::Regex;
|
||||
use ruff::logging::LogLevel;
|
||||
use ruff::registry::{Rule, RuleSelector};
|
||||
use ruff::registry::Rule;
|
||||
use ruff::resolver::ConfigProcessor;
|
||||
use ruff::settings::types::{
|
||||
FilePattern, PatternPrefixPair, PerFileIgnore, PythonVersion, SerializationFormat,
|
||||
};
|
||||
use ruff::RuleSelector;
|
||||
use rustc_hash::FxHashMap;
|
||||
|
||||
#[derive(Debug, Parser)]
|
||||
|
|
|
@ -53,7 +53,7 @@ pub fn define_rule_mapping(mapping: &Mapping) -> proc_macro2::TokenStream {
|
|||
|
||||
let rulecodeprefix = super::rule_code_prefix::expand(
|
||||
&Ident::new("Rule", Span::call_site()),
|
||||
&Ident::new("RuleSelector", Span::call_site()),
|
||||
&Ident::new("RuleCodePrefix", Span::call_site()),
|
||||
mapping.entries.iter().map(|(code, ..)| code),
|
||||
|code| code_to_name[code],
|
||||
);
|
||||
|
|
|
@ -147,17 +147,6 @@ pub fn expand<'a>(
|
|||
});
|
||||
|
||||
quote! {
|
||||
#[derive(PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub enum Specificity {
|
||||
All,
|
||||
Linter,
|
||||
Code1Char,
|
||||
Code2Chars,
|
||||
Code3Chars,
|
||||
Code4Chars,
|
||||
Code5Chars,
|
||||
}
|
||||
|
||||
#[derive(
|
||||
::strum_macros::EnumString,
|
||||
::strum_macros::AsRefStr,
|
||||
|
@ -244,7 +233,9 @@ fn generate_impls<'a>(
|
|||
|
||||
quote! {
|
||||
impl #prefix_ident {
|
||||
pub fn specificity(&self) -> Specificity {
|
||||
pub(crate) fn specificity(&self) -> crate::rule_selector::Specificity {
|
||||
use crate::rule_selector::Specificity;
|
||||
|
||||
#[allow(clippy::match_same_arms)]
|
||||
match self {
|
||||
#(#specificity_match_arms)*
|
||||
|
|
|
@ -84,14 +84,14 @@ pub fn derive_impl(input: DeriveInput) -> syn::Result<proc_macro2::TokenStream>
|
|||
|
||||
if field != "Pycodestyle" {
|
||||
into_iter_match_arms.extend(quote! {
|
||||
#ident::#field => RuleSelector::#prefix_ident.into_iter(),
|
||||
#ident::#field => RuleCodePrefix::#prefix_ident.into_iter(),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
into_iter_match_arms.extend(quote! {
|
||||
#ident::Pycodestyle => {
|
||||
let rules: Vec<_> = (&RuleSelector::E).into_iter().chain(&RuleSelector::W).collect();
|
||||
let rules: Vec<_> = (&RuleCodePrefix::E).into_iter().chain(&RuleCodePrefix::W).collect();
|
||||
rules.into_iter()
|
||||
}
|
||||
});
|
||||
|
|
|
@ -5,7 +5,8 @@ use anyhow::Result;
|
|||
use super::external_config::ExternalConfig;
|
||||
use super::plugin::Plugin;
|
||||
use super::{parser, plugin};
|
||||
use crate::registry::RuleSelector;
|
||||
use crate::registry::RuleCodePrefix;
|
||||
use crate::rule_selector::{prefix_to_selector, RuleSelector};
|
||||
use crate::rules::flake8_pytest_style::types::{
|
||||
ParametrizeNameType, ParametrizeValuesRowType, ParametrizeValuesType,
|
||||
};
|
||||
|
@ -20,7 +21,11 @@ use crate::settings::options::Options;
|
|||
use crate::settings::pyproject::Pyproject;
|
||||
use crate::warn_user;
|
||||
|
||||
const DEFAULT_SELECTORS: &[RuleSelector] = &[RuleSelector::F, RuleSelector::E, RuleSelector::W];
|
||||
const DEFAULT_SELECTORS: &[RuleSelector] = &[
|
||||
prefix_to_selector(RuleCodePrefix::F),
|
||||
prefix_to_selector(RuleCodePrefix::E),
|
||||
prefix_to_selector(RuleCodePrefix::W),
|
||||
];
|
||||
|
||||
pub fn convert(
|
||||
config: &HashMap<String, HashMap<String, Option<String>>>,
|
||||
|
@ -426,7 +431,8 @@ mod tests {
|
|||
use super::convert;
|
||||
use crate::flake8_to_ruff::converter::DEFAULT_SELECTORS;
|
||||
use crate::flake8_to_ruff::ExternalConfig;
|
||||
use crate::registry::RuleSelector;
|
||||
use crate::registry::RuleCodePrefix;
|
||||
use crate::rule_selector::RuleSelector;
|
||||
use crate::rules::pydocstyle::settings::Convention;
|
||||
use crate::rules::{flake8_quotes, pydocstyle};
|
||||
use crate::settings::options::Options;
|
||||
|
@ -555,7 +561,7 @@ mod tests {
|
|||
pydocstyle: Some(pydocstyle::settings::Options {
|
||||
convention: Some(Convention::Numpy),
|
||||
}),
|
||||
..default_options([RuleSelector::D])
|
||||
..default_options([RuleCodePrefix::D.into()])
|
||||
});
|
||||
assert_eq!(actual, expected);
|
||||
|
||||
|
@ -579,7 +585,7 @@ mod tests {
|
|||
docstring_quotes: None,
|
||||
avoid_escape: None,
|
||||
}),
|
||||
..default_options([RuleSelector::Q])
|
||||
..default_options([RuleCodePrefix::Q.into()])
|
||||
});
|
||||
assert_eq!(actual, expected);
|
||||
|
||||
|
|
|
@ -5,7 +5,8 @@ use once_cell::sync::Lazy;
|
|||
use regex::Regex;
|
||||
use rustc_hash::FxHashMap;
|
||||
|
||||
use crate::registry::{RuleSelector, PREFIX_REDIRECTS};
|
||||
use crate::registry::PREFIX_REDIRECTS;
|
||||
use crate::rule_selector::RuleSelector;
|
||||
use crate::settings::types::PatternPrefixPair;
|
||||
use crate::warn_user;
|
||||
|
||||
|
@ -21,7 +22,7 @@ pub fn parse_prefix_codes(value: &str) -> Vec<RuleSelector> {
|
|||
continue;
|
||||
}
|
||||
if let Some(code) = PREFIX_REDIRECTS.get(code) {
|
||||
codes.push(code.clone());
|
||||
codes.push(code.clone().into());
|
||||
} else if let Ok(code) = RuleSelector::from_str(code) {
|
||||
codes.push(code);
|
||||
} else {
|
||||
|
@ -92,7 +93,7 @@ impl State {
|
|||
for filename in &self.filenames {
|
||||
codes.push(PatternPrefixPair {
|
||||
pattern: filename.clone(),
|
||||
prefix: code.clone(),
|
||||
prefix: code.clone().into(),
|
||||
});
|
||||
}
|
||||
} else if let Ok(code) = RuleSelector::from_str(code) {
|
||||
|
@ -205,7 +206,8 @@ mod tests {
|
|||
use anyhow::Result;
|
||||
|
||||
use super::{parse_files_to_codes_mapping, parse_prefix_codes, parse_strings};
|
||||
use crate::registry::RuleSelector;
|
||||
use crate::registry::RuleCodePrefix;
|
||||
use crate::rule_selector::RuleSelector;
|
||||
use crate::settings::types::PatternPrefixPair;
|
||||
|
||||
#[test]
|
||||
|
@ -219,19 +221,19 @@ mod tests {
|
|||
assert_eq!(actual, expected);
|
||||
|
||||
let actual = parse_prefix_codes("F401");
|
||||
let expected = vec![RuleSelector::F401];
|
||||
let expected = vec![RuleCodePrefix::F401.into()];
|
||||
assert_eq!(actual, expected);
|
||||
|
||||
let actual = parse_prefix_codes("F401,");
|
||||
let expected = vec![RuleSelector::F401];
|
||||
let expected = vec![RuleCodePrefix::F401.into()];
|
||||
assert_eq!(actual, expected);
|
||||
|
||||
let actual = parse_prefix_codes("F401,E501");
|
||||
let expected = vec![RuleSelector::F401, RuleSelector::E501];
|
||||
let expected = vec![RuleCodePrefix::F401.into(), RuleCodePrefix::E501.into()];
|
||||
assert_eq!(actual, expected);
|
||||
|
||||
let actual = parse_prefix_codes("F401, E501");
|
||||
let expected = vec![RuleSelector::F401, RuleSelector::E501];
|
||||
let expected = vec![RuleCodePrefix::F401.into(), RuleCodePrefix::E501.into()];
|
||||
assert_eq!(actual, expected);
|
||||
}
|
||||
|
||||
|
@ -284,11 +286,11 @@ mod tests {
|
|||
let expected: Vec<PatternPrefixPair> = vec![
|
||||
PatternPrefixPair {
|
||||
pattern: "locust/test/*".to_string(),
|
||||
prefix: RuleSelector::F841,
|
||||
prefix: RuleCodePrefix::F841.into(),
|
||||
},
|
||||
PatternPrefixPair {
|
||||
pattern: "examples/*".to_string(),
|
||||
prefix: RuleSelector::F841,
|
||||
prefix: RuleCodePrefix::F841.into(),
|
||||
},
|
||||
];
|
||||
assert_eq!(actual, expected);
|
||||
|
@ -304,23 +306,23 @@ mod tests {
|
|||
let expected: Vec<PatternPrefixPair> = vec![
|
||||
PatternPrefixPair {
|
||||
pattern: "t/*".to_string(),
|
||||
prefix: RuleSelector::D,
|
||||
prefix: RuleCodePrefix::D.into(),
|
||||
},
|
||||
PatternPrefixPair {
|
||||
pattern: "setup.py".to_string(),
|
||||
prefix: RuleSelector::D,
|
||||
prefix: RuleCodePrefix::D.into(),
|
||||
},
|
||||
PatternPrefixPair {
|
||||
pattern: "examples/*".to_string(),
|
||||
prefix: RuleSelector::D,
|
||||
prefix: RuleCodePrefix::D.into(),
|
||||
},
|
||||
PatternPrefixPair {
|
||||
pattern: "docs/*".to_string(),
|
||||
prefix: RuleSelector::D,
|
||||
prefix: RuleCodePrefix::D.into(),
|
||||
},
|
||||
PatternPrefixPair {
|
||||
pattern: "extra/*".to_string(),
|
||||
prefix: RuleSelector::D,
|
||||
prefix: RuleCodePrefix::D.into(),
|
||||
},
|
||||
];
|
||||
assert_eq!(actual, expected);
|
||||
|
@ -342,47 +344,47 @@ mod tests {
|
|||
let expected: Vec<PatternPrefixPair> = vec![
|
||||
PatternPrefixPair {
|
||||
pattern: "scrapy/__init__.py".to_string(),
|
||||
prefix: RuleSelector::E402,
|
||||
prefix: RuleCodePrefix::E402.into(),
|
||||
},
|
||||
PatternPrefixPair {
|
||||
pattern: "scrapy/core/downloader/handlers/http.py".to_string(),
|
||||
prefix: RuleSelector::F401,
|
||||
prefix: RuleCodePrefix::F401.into(),
|
||||
},
|
||||
PatternPrefixPair {
|
||||
pattern: "scrapy/http/__init__.py".to_string(),
|
||||
prefix: RuleSelector::F401,
|
||||
prefix: RuleCodePrefix::F401.into(),
|
||||
},
|
||||
PatternPrefixPair {
|
||||
pattern: "scrapy/linkextractors/__init__.py".to_string(),
|
||||
prefix: RuleSelector::E402,
|
||||
prefix: RuleCodePrefix::E402.into(),
|
||||
},
|
||||
PatternPrefixPair {
|
||||
pattern: "scrapy/linkextractors/__init__.py".to_string(),
|
||||
prefix: RuleSelector::F401,
|
||||
prefix: RuleCodePrefix::F401.into(),
|
||||
},
|
||||
PatternPrefixPair {
|
||||
pattern: "scrapy/selector/__init__.py".to_string(),
|
||||
prefix: RuleSelector::F401,
|
||||
prefix: RuleCodePrefix::F401.into(),
|
||||
},
|
||||
PatternPrefixPair {
|
||||
pattern: "scrapy/spiders/__init__.py".to_string(),
|
||||
prefix: RuleSelector::E402,
|
||||
prefix: RuleCodePrefix::E402.into(),
|
||||
},
|
||||
PatternPrefixPair {
|
||||
pattern: "scrapy/spiders/__init__.py".to_string(),
|
||||
prefix: RuleSelector::F401,
|
||||
prefix: RuleCodePrefix::F401.into(),
|
||||
},
|
||||
PatternPrefixPair {
|
||||
pattern: "scrapy/utils/url.py".to_string(),
|
||||
prefix: RuleSelector::F403,
|
||||
prefix: RuleCodePrefix::F403.into(),
|
||||
},
|
||||
PatternPrefixPair {
|
||||
pattern: "scrapy/utils/url.py".to_string(),
|
||||
prefix: RuleSelector::F405,
|
||||
prefix: RuleCodePrefix::F405.into(),
|
||||
},
|
||||
PatternPrefixPair {
|
||||
pattern: "tests/test_loader.py".to_string(),
|
||||
prefix: RuleSelector::E741,
|
||||
prefix: RuleCodePrefix::E741.into(),
|
||||
},
|
||||
];
|
||||
assert_eq!(actual, expected);
|
||||
|
|
|
@ -4,7 +4,8 @@ use std::str::FromStr;
|
|||
|
||||
use anyhow::anyhow;
|
||||
|
||||
use crate::registry::RuleSelector;
|
||||
use crate::registry::RuleCodePrefix;
|
||||
use crate::rule_selector::RuleSelector;
|
||||
|
||||
#[derive(Clone, Ord, PartialOrd, Eq, PartialEq)]
|
||||
pub enum Plugin {
|
||||
|
@ -130,42 +131,43 @@ impl fmt::Debug for Plugin {
|
|||
}
|
||||
}
|
||||
|
||||
// TODO(martin): Convert into `impl From<Plugin> for Linter`
|
||||
impl Plugin {
|
||||
pub fn selector(&self) -> RuleSelector {
|
||||
match self {
|
||||
Plugin::Flake82020 => RuleSelector::YTT,
|
||||
Plugin::Flake8Annotations => RuleSelector::ANN,
|
||||
Plugin::Flake8Bandit => RuleSelector::S,
|
||||
Plugin::Flake8BlindExcept => RuleSelector::BLE,
|
||||
Plugin::Flake8BooleanTrap => RuleSelector::FBT,
|
||||
Plugin::Flake8Bugbear => RuleSelector::B,
|
||||
Plugin::Flake8Builtins => RuleSelector::A,
|
||||
Plugin::Flake8Commas => RuleSelector::COM,
|
||||
Plugin::Flake8Comprehensions => RuleSelector::C4,
|
||||
Plugin::Flake8Datetimez => RuleSelector::DTZ,
|
||||
Plugin::Flake8Debugger => RuleSelector::T1,
|
||||
Plugin::Flake8Docstrings => RuleSelector::D,
|
||||
Plugin::Flake8Eradicate => RuleSelector::ERA,
|
||||
Plugin::Flake8ErrMsg => RuleSelector::EM,
|
||||
Plugin::Flake8Executable => RuleSelector::EXE,
|
||||
Plugin::Flake8ImplicitStrConcat => RuleSelector::ISC,
|
||||
Plugin::Flake8ImportConventions => RuleSelector::ICN,
|
||||
Plugin::Flake8NoPep420 => RuleSelector::INP,
|
||||
Plugin::Flake8Pie => RuleSelector::PIE,
|
||||
Plugin::Flake8Print => RuleSelector::T2,
|
||||
Plugin::Flake8PytestStyle => RuleSelector::PT,
|
||||
Plugin::Flake8Quotes => RuleSelector::Q,
|
||||
Plugin::Flake8Return => RuleSelector::RET,
|
||||
Plugin::Flake8Simplify => RuleSelector::SIM,
|
||||
Plugin::Flake8TidyImports => RuleSelector::TID,
|
||||
Plugin::Flake8TypeChecking => RuleSelector::TYP,
|
||||
Plugin::Flake8UnusedArguments => RuleSelector::ARG,
|
||||
Plugin::Flake8UsePathlib => RuleSelector::PTH,
|
||||
Plugin::McCabe => RuleSelector::C9,
|
||||
Plugin::PEP8Naming => RuleSelector::N,
|
||||
Plugin::PandasVet => RuleSelector::PD,
|
||||
Plugin::Pyupgrade => RuleSelector::UP,
|
||||
Plugin::Tryceratops => RuleSelector::TRY,
|
||||
Plugin::Flake82020 => RuleCodePrefix::YTT.into(),
|
||||
Plugin::Flake8Annotations => RuleCodePrefix::ANN.into(),
|
||||
Plugin::Flake8Bandit => RuleCodePrefix::S.into(),
|
||||
Plugin::Flake8BlindExcept => RuleCodePrefix::BLE.into(),
|
||||
Plugin::Flake8BooleanTrap => RuleCodePrefix::FBT.into(),
|
||||
Plugin::Flake8Bugbear => RuleCodePrefix::B.into(),
|
||||
Plugin::Flake8Builtins => RuleCodePrefix::A.into(),
|
||||
Plugin::Flake8Commas => RuleCodePrefix::COM.into(),
|
||||
Plugin::Flake8Comprehensions => RuleCodePrefix::C4.into(),
|
||||
Plugin::Flake8Datetimez => RuleCodePrefix::DTZ.into(),
|
||||
Plugin::Flake8Debugger => RuleCodePrefix::T1.into(),
|
||||
Plugin::Flake8Docstrings => RuleCodePrefix::D.into(),
|
||||
Plugin::Flake8Eradicate => RuleCodePrefix::ERA.into(),
|
||||
Plugin::Flake8ErrMsg => RuleCodePrefix::EM.into(),
|
||||
Plugin::Flake8Executable => RuleCodePrefix::EXE.into(),
|
||||
Plugin::Flake8ImplicitStrConcat => RuleCodePrefix::ISC.into(),
|
||||
Plugin::Flake8ImportConventions => RuleCodePrefix::ICN.into(),
|
||||
Plugin::Flake8NoPep420 => RuleCodePrefix::INP.into(),
|
||||
Plugin::Flake8Pie => RuleCodePrefix::PIE.into(),
|
||||
Plugin::Flake8Print => RuleCodePrefix::T2.into(),
|
||||
Plugin::Flake8PytestStyle => RuleCodePrefix::PT.into(),
|
||||
Plugin::Flake8Quotes => RuleCodePrefix::Q.into(),
|
||||
Plugin::Flake8Return => RuleCodePrefix::RET.into(),
|
||||
Plugin::Flake8Simplify => RuleCodePrefix::SIM.into(),
|
||||
Plugin::Flake8TidyImports => RuleCodePrefix::TID.into(),
|
||||
Plugin::Flake8TypeChecking => RuleCodePrefix::TYP.into(),
|
||||
Plugin::Flake8UnusedArguments => RuleCodePrefix::ARG.into(),
|
||||
Plugin::Flake8UsePathlib => RuleCodePrefix::PTH.into(),
|
||||
Plugin::McCabe => RuleCodePrefix::C9.into(),
|
||||
Plugin::PEP8Naming => RuleCodePrefix::N.into(),
|
||||
Plugin::PandasVet => RuleCodePrefix::PD.into(),
|
||||
Plugin::Pyupgrade => RuleCodePrefix::UP.into(),
|
||||
Plugin::Tryceratops => RuleCodePrefix::TRY.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,6 +37,7 @@ mod noqa;
|
|||
mod python;
|
||||
pub mod registry;
|
||||
pub mod resolver;
|
||||
mod rule_selector;
|
||||
mod rules;
|
||||
mod rustpython_helpers;
|
||||
pub mod settings;
|
||||
|
@ -47,6 +48,7 @@ mod violations;
|
|||
mod visibility;
|
||||
|
||||
use cfg_if::cfg_if;
|
||||
pub use rule_selector::RuleSelector;
|
||||
pub use violation::{AutofixKind, Availability as AutofixAvailability};
|
||||
pub use violations::IOError;
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@ use strum_macros::{AsRefStr, EnumIter};
|
|||
|
||||
use crate::ast::types::Range;
|
||||
use crate::fix::Fix;
|
||||
use crate::rule_selector::{prefix_to_selector, RuleSelector};
|
||||
use crate::violation::Violation;
|
||||
use crate::{rules, violations};
|
||||
|
||||
|
@ -607,19 +608,25 @@ pub trait RuleNamespace: Sized {
|
|||
/// The prefix, name and selector for an upstream linter category.
|
||||
pub struct LinterCategory(pub &'static str, pub &'static str, pub RuleSelector);
|
||||
|
||||
// TODO(martin): Move these constant definitions back to Linter::categories impl
|
||||
// once RuleSelector is an enum with a Linter variant
|
||||
const PYCODESTYLE_CATEGORIES: &[LinterCategory] = &[
|
||||
LinterCategory("E", "Error", prefix_to_selector(RuleCodePrefix::E)),
|
||||
LinterCategory("W", "Warning", prefix_to_selector(RuleCodePrefix::W)),
|
||||
];
|
||||
|
||||
const PYLINT_CATEGORIES: &[LinterCategory] = &[
|
||||
LinterCategory("PLC", "Convention", prefix_to_selector(RuleCodePrefix::PLC)),
|
||||
LinterCategory("PLE", "Error", prefix_to_selector(RuleCodePrefix::PLE)),
|
||||
LinterCategory("PLR", "Refactor", prefix_to_selector(RuleCodePrefix::PLR)),
|
||||
LinterCategory("PLW", "Warning", prefix_to_selector(RuleCodePrefix::PLW)),
|
||||
];
|
||||
|
||||
impl Linter {
|
||||
pub fn categories(&self) -> Option<&'static [LinterCategory]> {
|
||||
match self {
|
||||
Linter::Pycodestyle => Some(&[
|
||||
LinterCategory("E", "Error", RuleSelector::E),
|
||||
LinterCategory("W", "Warning", RuleSelector::W),
|
||||
]),
|
||||
Linter::Pylint => Some(&[
|
||||
LinterCategory("PLC", "Convention", RuleSelector::PLC),
|
||||
LinterCategory("PLE", "Error", RuleSelector::PLE),
|
||||
LinterCategory("PLR", "Refactor", RuleSelector::PLR),
|
||||
LinterCategory("PLW", "Warning", RuleSelector::PLW),
|
||||
]),
|
||||
Linter::Pycodestyle => Some(PYCODESTYLE_CATEGORIES),
|
||||
Linter::Pylint => Some(PYLINT_CATEGORIES),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
|
68
src/rule_selector.rs
Normal file
68
src/rule_selector.rs
Normal file
|
@ -0,0 +1,68 @@
|
|||
use std::str::FromStr;
|
||||
|
||||
use schemars::JsonSchema;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::registry::{Rule, RuleCodePrefix};
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
|
||||
pub struct RuleSelector(RuleCodePrefix);
|
||||
|
||||
impl FromStr for RuleSelector {
|
||||
type Err = strum::ParseError;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
Ok(Self(RuleCodePrefix::from_str(s)?))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<RuleCodePrefix> for RuleSelector {
|
||||
fn from(prefix: RuleCodePrefix) -> Self {
|
||||
Self(prefix)
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoIterator for &RuleSelector {
|
||||
type IntoIter = ::std::vec::IntoIter<Self::Item>;
|
||||
type Item = Rule;
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
self.0.into_iter()
|
||||
}
|
||||
}
|
||||
|
||||
/// A const alternative to the `impl From<RuleCodePrefix> for RuleSelector`
|
||||
// to let us keep the fields of RuleSelector private.
|
||||
// Note that Rust doesn't yet support `impl const From<RuleCodePrefix> for
|
||||
// RuleSelector` (see https://github.com/rust-lang/rust/issues/67792).
|
||||
// TODO(martin): Remove once RuleSelector is an enum with Linter & Rule variants
|
||||
pub(crate) const fn prefix_to_selector(prefix: RuleCodePrefix) -> RuleSelector {
|
||||
RuleSelector(prefix)
|
||||
}
|
||||
|
||||
impl JsonSchema for RuleSelector {
|
||||
fn schema_name() -> String {
|
||||
"RuleSelector".to_string()
|
||||
}
|
||||
|
||||
fn json_schema(gen: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema {
|
||||
<RuleCodePrefix as JsonSchema>::json_schema(gen)
|
||||
}
|
||||
}
|
||||
|
||||
impl RuleSelector {
|
||||
pub(crate) fn specificity(&self) -> Specificity {
|
||||
self.0.specificity()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub(crate) enum Specificity {
|
||||
All,
|
||||
Linter,
|
||||
Code1Char,
|
||||
Code2Chars,
|
||||
Code3Chars,
|
||||
Code4Chars,
|
||||
Code5Chars,
|
||||
}
|
|
@ -12,14 +12,14 @@ mod tests {
|
|||
use textwrap::dedent;
|
||||
|
||||
use crate::linter::check_path;
|
||||
use crate::registry::{Rule, RuleSelector};
|
||||
use crate::registry::{Rule, RuleCodePrefix};
|
||||
use crate::settings::flags;
|
||||
use crate::source_code::{Indexer, Locator, Stylist};
|
||||
use crate::{directives, rustpython_helpers, settings};
|
||||
|
||||
fn rule_code(contents: &str, expected: &[Rule]) -> Result<()> {
|
||||
let contents = dedent(contents);
|
||||
let settings = settings::Settings::for_rules(&RuleSelector::PD);
|
||||
let settings = settings::Settings::for_rules(&RuleCodePrefix::PD);
|
||||
let tokens: Vec<LexResult> = rustpython_helpers::tokenize(&contents);
|
||||
let locator = Locator::new(&contents);
|
||||
let stylist = Stylist::from_contents(&contents, &locator);
|
||||
|
|
|
@ -15,7 +15,7 @@ mod tests {
|
|||
use textwrap::dedent;
|
||||
|
||||
use crate::linter::{check_path, test_path};
|
||||
use crate::registry::{Rule, RuleSelector};
|
||||
use crate::registry::{Rule, RuleCodePrefix};
|
||||
use crate::settings::flags;
|
||||
use crate::source_code::{Indexer, Locator, Stylist};
|
||||
use crate::{directives, rustpython_helpers, settings};
|
||||
|
@ -209,7 +209,7 @@ mod tests {
|
|||
/// Note that all tests marked with `#[ignore]` should be considered TODOs.
|
||||
fn flakes(contents: &str, expected: &[Rule]) -> Result<()> {
|
||||
let contents = dedent(contents);
|
||||
let settings = settings::Settings::for_rules(&RuleSelector::F);
|
||||
let settings = settings::Settings::for_rules(&RuleCodePrefix::F);
|
||||
let tokens: Vec<LexResult> = rustpython_helpers::tokenize(&contents);
|
||||
let locator = Locator::new(&contents);
|
||||
let stylist = Stylist::from_contents(&contents, &locator);
|
||||
|
|
|
@ -13,7 +13,7 @@ use shellexpand;
|
|||
use shellexpand::LookupError;
|
||||
|
||||
use crate::fs;
|
||||
use crate::registry::RuleSelector;
|
||||
use crate::rule_selector::RuleSelector;
|
||||
use crate::rules::{
|
||||
flake8_annotations, flake8_bandit, flake8_bugbear, flake8_builtins, flake8_errmsg,
|
||||
flake8_implicit_str_concat, flake8_import_conventions, flake8_pytest_style, flake8_quotes,
|
||||
|
|
|
@ -6,7 +6,8 @@ use rustc_hash::FxHashSet;
|
|||
use super::hashable::{HashableGlobSet, HashableHashSet};
|
||||
use super::types::{FilePattern, PythonVersion};
|
||||
use super::Settings;
|
||||
use crate::registry::RuleSelector;
|
||||
use crate::registry::RuleCodePrefix;
|
||||
use crate::rule_selector::{prefix_to_selector, RuleSelector};
|
||||
use crate::rules::{
|
||||
flake8_annotations, flake8_bandit, flake8_bugbear, flake8_builtins, flake8_errmsg,
|
||||
flake8_implicit_str_concat, flake8_import_conventions, flake8_pytest_style, flake8_quotes,
|
||||
|
@ -14,7 +15,10 @@ use crate::rules::{
|
|||
pydocstyle, pylint, pyupgrade,
|
||||
};
|
||||
|
||||
pub const PREFIXES: &[RuleSelector] = &[RuleSelector::E, RuleSelector::F];
|
||||
pub const PREFIXES: &[RuleSelector] = &[
|
||||
prefix_to_selector(RuleCodePrefix::E),
|
||||
prefix_to_selector(RuleCodePrefix::F),
|
||||
];
|
||||
|
||||
pub const TARGET_VERSION: PythonVersion = PythonVersion::Py310;
|
||||
|
||||
|
|
|
@ -11,7 +11,8 @@ use rustc_hash::FxHashSet;
|
|||
use self::hashable::{HashableGlobMatcher, HashableGlobSet, HashableHashSet, HashableRegex};
|
||||
use self::rule_table::RuleTable;
|
||||
use crate::cache::cache_dir;
|
||||
use crate::registry::{Rule, RuleSelector, Specificity, INCOMPATIBLE_CODES};
|
||||
use crate::registry::{Rule, INCOMPATIBLE_CODES};
|
||||
use crate::rule_selector::{RuleSelector, Specificity};
|
||||
use crate::rules::{
|
||||
flake8_annotations, flake8_bandit, flake8_bugbear, flake8_builtins, flake8_errmsg,
|
||||
flake8_implicit_str_concat, flake8_import_conventions, flake8_pytest_style, flake8_quotes,
|
||||
|
@ -238,7 +239,10 @@ impl From<&Configuration> for RuleTable {
|
|||
let mut rules = RuleTable::empty();
|
||||
|
||||
let fixable = resolve_codes([RuleCodeSpec {
|
||||
select: config.fixable.as_deref().unwrap_or(&[RuleSelector::ALL]),
|
||||
select: config
|
||||
.fixable
|
||||
.as_deref()
|
||||
.unwrap_or(&[crate::registry::RuleCodePrefix::ALL.into()]),
|
||||
ignore: config.unfixable.as_deref().unwrap_or_default(),
|
||||
}]);
|
||||
|
||||
|
@ -352,13 +356,13 @@ fn validate_enabled(enabled: FxHashSet<Rule>) -> FxHashSet<Rule> {
|
|||
mod tests {
|
||||
use rustc_hash::FxHashSet;
|
||||
|
||||
use crate::registry::{Rule, RuleSelector};
|
||||
use crate::registry::{Rule, RuleCodePrefix};
|
||||
use crate::settings::{resolve_codes, RuleCodeSpec};
|
||||
|
||||
#[test]
|
||||
fn rule_codes() {
|
||||
let actual = resolve_codes([RuleCodeSpec {
|
||||
select: &[RuleSelector::W],
|
||||
select: &[RuleCodePrefix::W.into()],
|
||||
ignore: &[],
|
||||
}]);
|
||||
let expected = FxHashSet::from_iter([
|
||||
|
@ -369,33 +373,33 @@ mod tests {
|
|||
assert_eq!(actual, expected);
|
||||
|
||||
let actual = resolve_codes([RuleCodeSpec {
|
||||
select: &[RuleSelector::W6],
|
||||
select: &[RuleCodePrefix::W6.into()],
|
||||
ignore: &[],
|
||||
}]);
|
||||
let expected = FxHashSet::from_iter([Rule::InvalidEscapeSequence]);
|
||||
assert_eq!(actual, expected);
|
||||
|
||||
let actual = resolve_codes([RuleCodeSpec {
|
||||
select: &[RuleSelector::W],
|
||||
ignore: &[RuleSelector::W292],
|
||||
select: &[RuleCodePrefix::W.into()],
|
||||
ignore: &[RuleCodePrefix::W292.into()],
|
||||
}]);
|
||||
let expected = FxHashSet::from_iter([Rule::DocLineTooLong, Rule::InvalidEscapeSequence]);
|
||||
assert_eq!(actual, expected);
|
||||
|
||||
let actual = resolve_codes([RuleCodeSpec {
|
||||
select: &[RuleSelector::W605],
|
||||
ignore: &[RuleSelector::W605],
|
||||
select: &[RuleCodePrefix::W605.into()],
|
||||
ignore: &[RuleCodePrefix::W605.into()],
|
||||
}]);
|
||||
let expected = FxHashSet::from_iter([]);
|
||||
assert_eq!(actual, expected);
|
||||
|
||||
let actual = resolve_codes([
|
||||
RuleCodeSpec {
|
||||
select: &[RuleSelector::W],
|
||||
ignore: &[RuleSelector::W292],
|
||||
select: &[RuleCodePrefix::W.into()],
|
||||
ignore: &[RuleCodePrefix::W292.into()],
|
||||
},
|
||||
RuleCodeSpec {
|
||||
select: &[RuleSelector::W292],
|
||||
select: &[RuleCodePrefix::W292.into()],
|
||||
ignore: &[],
|
||||
},
|
||||
]);
|
||||
|
@ -408,12 +412,12 @@ mod tests {
|
|||
|
||||
let actual = resolve_codes([
|
||||
RuleCodeSpec {
|
||||
select: &[RuleSelector::W],
|
||||
ignore: &[RuleSelector::W292],
|
||||
select: &[RuleCodePrefix::W.into()],
|
||||
ignore: &[RuleCodePrefix::W292.into()],
|
||||
},
|
||||
RuleCodeSpec {
|
||||
select: &[RuleSelector::W292],
|
||||
ignore: &[RuleSelector::W],
|
||||
select: &[RuleCodePrefix::W292.into()],
|
||||
ignore: &[RuleCodePrefix::W.into()],
|
||||
},
|
||||
]);
|
||||
let expected = FxHashSet::from_iter([Rule::NoNewLineAtEndOfFile]);
|
||||
|
|
|
@ -5,7 +5,7 @@ use rustc_hash::FxHashMap;
|
|||
use schemars::JsonSchema;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::registry::RuleSelector;
|
||||
use crate::rule_selector::RuleSelector;
|
||||
use crate::rules::{
|
||||
flake8_annotations, flake8_bandit, flake8_bugbear, flake8_builtins, flake8_errmsg,
|
||||
flake8_implicit_str_concat, flake8_import_conventions, flake8_pytest_style, flake8_quotes,
|
||||
|
|
|
@ -129,7 +129,7 @@ mod tests {
|
|||
use anyhow::Result;
|
||||
use rustc_hash::FxHashMap;
|
||||
|
||||
use crate::registry::RuleSelector;
|
||||
use crate::registry::RuleCodePrefix;
|
||||
use crate::rules::flake8_quotes::settings::Quote;
|
||||
use crate::rules::flake8_tidy_imports::banned_api::ApiBan;
|
||||
use crate::rules::flake8_tidy_imports::relative_imports::Strictness;
|
||||
|
@ -212,7 +212,7 @@ select = ["E501"]
|
|||
pyproject.tool,
|
||||
Some(Tools {
|
||||
ruff: Some(Options {
|
||||
select: Some(vec![RuleSelector::E501]),
|
||||
select: Some(vec![RuleCodePrefix::E501.into()]),
|
||||
..Options::default()
|
||||
})
|
||||
})
|
||||
|
@ -230,8 +230,8 @@ ignore = ["E501"]
|
|||
pyproject.tool,
|
||||
Some(Tools {
|
||||
ruff: Some(Options {
|
||||
extend_select: Some(vec![RuleSelector::RUF100]),
|
||||
ignore: Some(vec![RuleSelector::E501]),
|
||||
extend_select: Some(vec![RuleCodePrefix::RUF100.into()]),
|
||||
ignore: Some(vec![RuleCodePrefix::E501.into()]),
|
||||
..Options::default()
|
||||
})
|
||||
})
|
||||
|
@ -293,7 +293,7 @@ other-attribute = 1
|
|||
external: Some(vec!["V101".to_string()]),
|
||||
per_file_ignores: Some(FxHashMap::from_iter([(
|
||||
"__init__.py".to_string(),
|
||||
vec![RuleSelector::F401]
|
||||
vec![RuleCodePrefix::F401.into()]
|
||||
)])),
|
||||
flake8_bugbear: Some(flake8_bugbear::settings::Options {
|
||||
extend_immutable_calls: Some(vec![
|
||||
|
|
|
@ -12,7 +12,8 @@ use serde::{de, Deserialize, Deserializer, Serialize};
|
|||
|
||||
use super::hashable::HashableHashSet;
|
||||
use crate::fs;
|
||||
use crate::registry::{Rule, RuleSelector};
|
||||
use crate::registry::Rule;
|
||||
use crate::rule_selector::RuleSelector;
|
||||
|
||||
#[derive(
|
||||
Clone, Copy, Debug, PartialOrd, Ord, PartialEq, Eq, Serialize, Deserialize, Hash, JsonSchema,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue