many-to-one 0/9: Introduce RuleSelector::Linter variant

We want to remove the variants denoting whole Linters
from the RuleCodePrefix enum, so we have to introduce
a new RuleSelector::Linter variant.
This commit is contained in:
Martin Fischer 2023-02-03 03:40:09 +01:00 committed by Charlie Marsh
parent 49d22d8fe2
commit 502ce80c91
5 changed files with 75 additions and 59 deletions

View file

@ -6,8 +6,8 @@ use itertools::Itertools;
use super::external_config::ExternalConfig; use super::external_config::ExternalConfig;
use super::plugin::Plugin; use super::plugin::Plugin;
use super::{parser, plugin}; use super::{parser, plugin};
use crate::registry::RuleCodePrefix; use crate::registry::Linter;
use crate::rule_selector::{prefix_to_selector, RuleSelector}; use crate::rule_selector::RuleSelector;
use crate::rules::flake8_pytest_style::types::{ use crate::rules::flake8_pytest_style::types::{
ParametrizeNameType, ParametrizeValuesRowType, ParametrizeValuesType, ParametrizeNameType, ParametrizeValuesRowType, ParametrizeValuesType,
}; };
@ -23,9 +23,8 @@ use crate::settings::pyproject::Pyproject;
use crate::warn_user; use crate::warn_user;
const DEFAULT_SELECTORS: &[RuleSelector] = &[ const DEFAULT_SELECTORS: &[RuleSelector] = &[
prefix_to_selector(RuleCodePrefix::F), RuleSelector::Linter(Linter::Pyflakes),
prefix_to_selector(RuleCodePrefix::E), RuleSelector::Linter(Linter::Pycodestyle),
prefix_to_selector(RuleCodePrefix::W),
]; ];
pub fn convert( pub fn convert(
@ -433,7 +432,7 @@ pub fn convert(
/// plugins. /// plugins.
fn resolve_select(plugins: &[Plugin]) -> HashSet<RuleSelector> { fn resolve_select(plugins: &[Plugin]) -> HashSet<RuleSelector> {
let mut select: HashSet<_> = DEFAULT_SELECTORS.iter().cloned().collect(); let mut select: HashSet<_> = DEFAULT_SELECTORS.iter().cloned().collect();
select.extend(plugins.iter().map(Plugin::selector)); select.extend(plugins.iter().map(|p| Linter::from(p).into()));
select select
} }
@ -448,7 +447,7 @@ mod tests {
use super::convert; use super::convert;
use crate::flake8_to_ruff::converter::DEFAULT_SELECTORS; use crate::flake8_to_ruff::converter::DEFAULT_SELECTORS;
use crate::flake8_to_ruff::ExternalConfig; use crate::flake8_to_ruff::ExternalConfig;
use crate::registry::RuleCodePrefix; use crate::registry::Linter;
use crate::rule_selector::RuleSelector; use crate::rule_selector::RuleSelector;
use crate::rules::pydocstyle::settings::Convention; use crate::rules::pydocstyle::settings::Convention;
use crate::rules::{flake8_quotes, pydocstyle}; use crate::rules::{flake8_quotes, pydocstyle};
@ -578,7 +577,7 @@ mod tests {
pydocstyle: Some(pydocstyle::settings::Options { pydocstyle: Some(pydocstyle::settings::Options {
convention: Some(Convention::Numpy), convention: Some(Convention::Numpy),
}), }),
..default_options([RuleCodePrefix::D.into()]) ..default_options([Linter::Pydocstyle.into()])
}); });
assert_eq!(actual, expected); assert_eq!(actual, expected);
@ -602,7 +601,7 @@ mod tests {
docstring_quotes: None, docstring_quotes: None,
avoid_escape: None, avoid_escape: None,
}), }),
..default_options([RuleCodePrefix::Q.into()]) ..default_options([Linter::Flake8Quotes.into()])
}); });
assert_eq!(actual, expected); assert_eq!(actual, expected);

View file

@ -196,7 +196,7 @@ mod tests {
use anyhow::Result; use anyhow::Result;
use super::{parse_files_to_codes_mapping, parse_prefix_codes, parse_strings}; use super::{parse_files_to_codes_mapping, parse_prefix_codes, parse_strings};
use crate::registry::RuleCodePrefix; use crate::registry::{Linter, RuleCodePrefix};
use crate::rule_selector::RuleSelector; use crate::rule_selector::RuleSelector;
use crate::settings::types::PatternPrefixPair; use crate::settings::types::PatternPrefixPair;
@ -296,23 +296,23 @@ mod tests {
let expected: Vec<PatternPrefixPair> = vec![ let expected: Vec<PatternPrefixPair> = vec![
PatternPrefixPair { PatternPrefixPair {
pattern: "t/*".to_string(), pattern: "t/*".to_string(),
prefix: RuleCodePrefix::D.into(), prefix: Linter::Pydocstyle.into(),
}, },
PatternPrefixPair { PatternPrefixPair {
pattern: "setup.py".to_string(), pattern: "setup.py".to_string(),
prefix: RuleCodePrefix::D.into(), prefix: Linter::Pydocstyle.into(),
}, },
PatternPrefixPair { PatternPrefixPair {
pattern: "examples/*".to_string(), pattern: "examples/*".to_string(),
prefix: RuleCodePrefix::D.into(), prefix: Linter::Pydocstyle.into(),
}, },
PatternPrefixPair { PatternPrefixPair {
pattern: "docs/*".to_string(), pattern: "docs/*".to_string(),
prefix: RuleCodePrefix::D.into(), prefix: Linter::Pydocstyle.into(),
}, },
PatternPrefixPair { PatternPrefixPair {
pattern: "extra/*".to_string(), pattern: "extra/*".to_string(),
prefix: RuleCodePrefix::D.into(), prefix: Linter::Pydocstyle.into(),
}, },
]; ];
assert_eq!(actual, expected); assert_eq!(actual, expected);

View file

@ -4,7 +4,7 @@ use std::str::FromStr;
use anyhow::anyhow; use anyhow::anyhow;
use crate::registry::RuleCodePrefix; use crate::registry::Linter;
use crate::rule_selector::RuleSelector; use crate::rule_selector::RuleSelector;
#[derive(Clone, Ord, PartialOrd, Eq, PartialEq)] #[derive(Clone, Ord, PartialOrd, Eq, PartialEq)]
@ -131,43 +131,42 @@ impl fmt::Debug for Plugin {
} }
} }
// TODO(martin): Convert into `impl From<Plugin> for Linter` impl From<&Plugin> for Linter {
impl Plugin { fn from(plugin: &Plugin) -> Self {
pub fn selector(&self) -> RuleSelector { match plugin {
match self { Plugin::Flake82020 => Linter::Flake82020,
Plugin::Flake82020 => RuleCodePrefix::YTT.into(), Plugin::Flake8Annotations => Linter::Flake8Annotations,
Plugin::Flake8Annotations => RuleCodePrefix::ANN.into(), Plugin::Flake8Bandit => Linter::Flake8Bandit,
Plugin::Flake8Bandit => RuleCodePrefix::S.into(), Plugin::Flake8BlindExcept => Linter::Flake8BlindExcept,
Plugin::Flake8BlindExcept => RuleCodePrefix::BLE.into(), Plugin::Flake8BooleanTrap => Linter::Flake8BooleanTrap,
Plugin::Flake8BooleanTrap => RuleCodePrefix::FBT.into(), Plugin::Flake8Bugbear => Linter::Flake8Bugbear,
Plugin::Flake8Bugbear => RuleCodePrefix::B.into(), Plugin::Flake8Builtins => Linter::Flake8Builtins,
Plugin::Flake8Builtins => RuleCodePrefix::A.into(), Plugin::Flake8Commas => Linter::Flake8Commas,
Plugin::Flake8Commas => RuleCodePrefix::COM.into(), Plugin::Flake8Comprehensions => Linter::Flake8Comprehensions,
Plugin::Flake8Comprehensions => RuleCodePrefix::C4.into(), Plugin::Flake8Datetimez => Linter::Flake8Datetimez,
Plugin::Flake8Datetimez => RuleCodePrefix::DTZ.into(), Plugin::Flake8Debugger => Linter::Flake8Debugger,
Plugin::Flake8Debugger => RuleCodePrefix::T1.into(), Plugin::Flake8Docstrings => Linter::Pydocstyle,
Plugin::Flake8Docstrings => RuleCodePrefix::D.into(), Plugin::Flake8Eradicate => Linter::Eradicate,
Plugin::Flake8Eradicate => RuleCodePrefix::ERA.into(), Plugin::Flake8ErrMsg => Linter::Flake8ErrMsg,
Plugin::Flake8ErrMsg => RuleCodePrefix::EM.into(), Plugin::Flake8Executable => Linter::Flake8Executable,
Plugin::Flake8Executable => RuleCodePrefix::EXE.into(), Plugin::Flake8ImplicitStrConcat => Linter::Flake8ImplicitStrConcat,
Plugin::Flake8ImplicitStrConcat => RuleCodePrefix::ISC.into(), Plugin::Flake8ImportConventions => Linter::Flake8ImportConventions,
Plugin::Flake8ImportConventions => RuleCodePrefix::ICN.into(), Plugin::Flake8NoPep420 => Linter::Flake8NoPep420,
Plugin::Flake8NoPep420 => RuleCodePrefix::INP.into(), Plugin::Flake8Pie => Linter::Flake8Pie,
Plugin::Flake8Pie => RuleCodePrefix::PIE.into(), Plugin::Flake8Print => Linter::Flake8Print,
Plugin::Flake8Print => RuleCodePrefix::T2.into(), Plugin::Flake8PytestStyle => Linter::Flake8PytestStyle,
Plugin::Flake8PytestStyle => RuleCodePrefix::PT.into(), Plugin::Flake8Quotes => Linter::Flake8Quotes,
Plugin::Flake8Quotes => RuleCodePrefix::Q.into(), Plugin::Flake8Return => Linter::Flake8Return,
Plugin::Flake8Return => RuleCodePrefix::RET.into(), Plugin::Flake8Simplify => Linter::Flake8Simplify,
Plugin::Flake8Simplify => RuleCodePrefix::SIM.into(), Plugin::Flake8TidyImports => Linter::Flake8TidyImports,
Plugin::Flake8TidyImports => RuleCodePrefix::TID.into(), Plugin::Flake8TypeChecking => Linter::Flake8TypeChecking,
Plugin::Flake8TypeChecking => RuleCodePrefix::TCH.into(), Plugin::Flake8UnusedArguments => Linter::Flake8UnusedArguments,
Plugin::Flake8UnusedArguments => RuleCodePrefix::ARG.into(), Plugin::Flake8UsePathlib => Linter::Flake8UsePathlib,
Plugin::Flake8UsePathlib => RuleCodePrefix::PTH.into(), Plugin::McCabe => Linter::McCabe,
Plugin::McCabe => RuleCodePrefix::C9.into(), Plugin::PEP8Naming => Linter::PEP8Naming,
Plugin::PEP8Naming => RuleCodePrefix::N.into(), Plugin::PandasVet => Linter::PandasVet,
Plugin::PandasVet => RuleCodePrefix::PD.into(), Plugin::Pyupgrade => Linter::Pyupgrade,
Plugin::Pyupgrade => RuleCodePrefix::UP.into(), Plugin::Tryceratops => Linter::Tryceratops,
Plugin::Tryceratops => RuleCodePrefix::TRY.into(),
} }
} }
} }
@ -334,7 +333,7 @@ pub fn infer_plugins_from_codes(selectors: &HashSet<RuleSelector>) -> Vec<Plugin
for selector in selectors { for selector in selectors {
if selector if selector
.into_iter() .into_iter()
.any(|rule| plugin.selector().into_iter().any(|r| r == rule)) .any(|rule| Linter::from(plugin).into_iter().any(|r| r == rule))
{ {
return true; return true;
} }

View file

@ -562,7 +562,7 @@ ruff_macros::define_rule_mapping!(
DJ013 => rules::flake8_django::rules::NonLeadingReceiverDecorator, DJ013 => rules::flake8_django::rules::NonLeadingReceiverDecorator,
); );
#[derive(EnumIter, Debug, PartialEq, Eq, RuleNamespace)] #[derive(EnumIter, Debug, PartialEq, Eq, Clone, Hash, RuleNamespace)]
pub enum Linter { pub enum Linter {
/// [Pyflakes](https://pypi.org/project/pyflakes/) /// [Pyflakes](https://pypi.org/project/pyflakes/)
#[prefix = "F"] #[prefix = "F"]

View file

@ -8,19 +8,26 @@ use serde::{Deserialize, Serialize};
use strum::IntoEnumIterator; use strum::IntoEnumIterator;
use strum_macros::EnumIter; use strum_macros::EnumIter;
use crate::registry::{Rule, RuleCodePrefix, RuleIter}; use crate::registry::{Linter, Rule, RuleCodePrefix, RuleIter, RuleNamespace};
use crate::rule_redirects::get_redirect; use crate::rule_redirects::get_redirect;
#[derive(Debug, Clone, PartialEq, Eq, Hash)] #[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum RuleSelector { pub enum RuleSelector {
/// All rules /// All rules
All, All,
Linter(Linter),
Prefix { Prefix {
prefix: RuleCodePrefix, prefix: RuleCodePrefix,
redirected_from: Option<&'static str>, redirected_from: Option<&'static str>,
}, },
} }
impl From<Linter> for RuleSelector {
fn from(linter: Linter) -> Self {
Self::Linter(linter)
}
}
impl FromStr for RuleSelector { impl FromStr for RuleSelector {
type Err = ParseError; type Err = ParseError;
@ -32,6 +39,14 @@ impl FromStr for RuleSelector {
Some((from, target)) => (target, Some(from)), Some((from, target)) => (target, Some(from)),
None => (s, None), None => (s, None),
}; };
let (linter, code) =
Linter::parse_code(s).ok_or_else(|| ParseError::Unknown(s.to_string()))?;
if code.is_empty() {
return Ok(Self::Linter(linter));
}
Ok(Self::Prefix { Ok(Self::Prefix {
prefix: RuleCodePrefix::from_str(s) prefix: RuleCodePrefix::from_str(s)
.map_err(|_| ParseError::Unknown(s.to_string()))?, .map_err(|_| ParseError::Unknown(s.to_string()))?,
@ -53,6 +68,7 @@ impl RuleSelector {
pub fn short_code(&self) -> &'static str { pub fn short_code(&self) -> &'static str {
match self { match self {
RuleSelector::All => "ALL", RuleSelector::All => "ALL",
RuleSelector::Linter(linter) => linter.common_prefix(),
RuleSelector::Prefix { prefix, .. } => prefix.into(), RuleSelector::Prefix { prefix, .. } => prefix.into(),
} }
} }
@ -117,14 +133,15 @@ impl IntoIterator for &RuleSelector {
fn into_iter(self) -> Self::IntoIter { fn into_iter(self) -> Self::IntoIter {
match self { match self {
RuleSelector::All => RuleSelectorIter::All(Rule::iter()), RuleSelector::All => RuleSelectorIter::All(Rule::iter()),
RuleSelector::Prefix { prefix, .. } => RuleSelectorIter::Prefix(prefix.into_iter()), RuleSelector::Linter(linter) => RuleSelectorIter::Vec(linter.into_iter()),
RuleSelector::Prefix { prefix, .. } => RuleSelectorIter::Vec(prefix.into_iter()),
} }
} }
} }
pub enum RuleSelectorIter { pub enum RuleSelectorIter {
All(RuleIter), All(RuleIter),
Prefix(std::vec::IntoIter<Rule>), Vec(std::vec::IntoIter<Rule>),
} }
impl Iterator for RuleSelectorIter { impl Iterator for RuleSelectorIter {
@ -133,7 +150,7 @@ impl Iterator for RuleSelectorIter {
fn next(&mut self) -> Option<Self::Item> { fn next(&mut self) -> Option<Self::Item> {
match self { match self {
RuleSelectorIter::All(iter) => iter.next(), RuleSelectorIter::All(iter) => iter.next(),
RuleSelectorIter::Prefix(iter) => iter.next(), RuleSelectorIter::Vec(iter) => iter.next(),
} }
} }
} }
@ -173,6 +190,7 @@ impl RuleSelector {
pub(crate) fn specificity(&self) -> Specificity { pub(crate) fn specificity(&self) -> Specificity {
match self { match self {
RuleSelector::All => Specificity::All, RuleSelector::All => Specificity::All,
RuleSelector::Linter(..) => Specificity::Linter,
RuleSelector::Prefix { prefix, .. } => prefix.specificity(), RuleSelector::Prefix { prefix, .. } => prefix.specificity(),
} }
} }