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

View file

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

View file

@ -4,7 +4,7 @@ use std::str::FromStr;
use anyhow::anyhow;
use crate::registry::RuleCodePrefix;
use crate::registry::Linter;
use crate::rule_selector::RuleSelector;
#[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 Plugin {
pub fn selector(&self) -> RuleSelector {
match self {
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::TCH.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(),
impl From<&Plugin> for Linter {
fn from(plugin: &Plugin) -> Self {
match plugin {
Plugin::Flake82020 => Linter::Flake82020,
Plugin::Flake8Annotations => Linter::Flake8Annotations,
Plugin::Flake8Bandit => Linter::Flake8Bandit,
Plugin::Flake8BlindExcept => Linter::Flake8BlindExcept,
Plugin::Flake8BooleanTrap => Linter::Flake8BooleanTrap,
Plugin::Flake8Bugbear => Linter::Flake8Bugbear,
Plugin::Flake8Builtins => Linter::Flake8Builtins,
Plugin::Flake8Commas => Linter::Flake8Commas,
Plugin::Flake8Comprehensions => Linter::Flake8Comprehensions,
Plugin::Flake8Datetimez => Linter::Flake8Datetimez,
Plugin::Flake8Debugger => Linter::Flake8Debugger,
Plugin::Flake8Docstrings => Linter::Pydocstyle,
Plugin::Flake8Eradicate => Linter::Eradicate,
Plugin::Flake8ErrMsg => Linter::Flake8ErrMsg,
Plugin::Flake8Executable => Linter::Flake8Executable,
Plugin::Flake8ImplicitStrConcat => Linter::Flake8ImplicitStrConcat,
Plugin::Flake8ImportConventions => Linter::Flake8ImportConventions,
Plugin::Flake8NoPep420 => Linter::Flake8NoPep420,
Plugin::Flake8Pie => Linter::Flake8Pie,
Plugin::Flake8Print => Linter::Flake8Print,
Plugin::Flake8PytestStyle => Linter::Flake8PytestStyle,
Plugin::Flake8Quotes => Linter::Flake8Quotes,
Plugin::Flake8Return => Linter::Flake8Return,
Plugin::Flake8Simplify => Linter::Flake8Simplify,
Plugin::Flake8TidyImports => Linter::Flake8TidyImports,
Plugin::Flake8TypeChecking => Linter::Flake8TypeChecking,
Plugin::Flake8UnusedArguments => Linter::Flake8UnusedArguments,
Plugin::Flake8UsePathlib => Linter::Flake8UsePathlib,
Plugin::McCabe => Linter::McCabe,
Plugin::PEP8Naming => Linter::PEP8Naming,
Plugin::PandasVet => Linter::PandasVet,
Plugin::Pyupgrade => Linter::Pyupgrade,
Plugin::Tryceratops => Linter::Tryceratops,
}
}
}
@ -334,7 +333,7 @@ pub fn infer_plugins_from_codes(selectors: &HashSet<RuleSelector>) -> Vec<Plugin
for selector in selectors {
if selector
.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;
}

View file

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

View file

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