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:
Martin Fischer 2023-01-24 09:55:09 +01:00 committed by Charlie Marsh
parent a20482961b
commit abc9810e2b
18 changed files with 209 additions and 121 deletions

View file

@ -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)]

View file

@ -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],
);

View file

@ -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)*

View file

@ -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()
}
});

View file

@ -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);

View file

@ -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);

View file

@ -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(),
}
}
}

View file

@ -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;

View file

@ -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
View 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,
}

View file

@ -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);

View file

@ -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);

View file

@ -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,

View file

@ -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;

View file

@ -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]);

View file

@ -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,

View file

@ -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![

View file

@ -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,