refactor: Move ALL from RuleCodePrefix to RuleSelector

This commit is contained in:
Martin Fischer 2023-01-24 11:50:41 +01:00 committed by Charlie Marsh
parent abc9810e2b
commit 28018442f6
4 changed files with 129 additions and 42 deletions

View File

@ -1188,13 +1188,13 @@
"RuleSelector": {
"type": "string",
"enum": [
"ALL",
"A",
"A0",
"A00",
"A001",
"A002",
"A003",
"ALL",
"ANN",
"ANN0",
"ANN00",

View File

@ -5,8 +5,6 @@ use proc_macro2::Span;
use quote::quote;
use syn::Ident;
const ALL: &str = "ALL";
/// A hash map from deprecated `RuleSelector` to latest
/// `RuleSelector`.
pub static PREFIX_REDIRECTS: Lazy<HashMap<&'static str, &'static str>> = Lazy::new(|| {
@ -116,7 +114,6 @@ pub fn expand<'a>(
all_codes.insert(code_str);
}
prefix_to_codes.insert(ALL.to_string(), all_codes);
prefix_to_codes.insert("PL".to_string(), pl_codes);
// Add any prefix aliases (e.g., "U" to "UP").
@ -148,6 +145,7 @@ pub fn expand<'a>(
quote! {
#[derive(
::strum_macros::EnumIter,
::strum_macros::EnumString,
::strum_macros::AsRefStr,
Debug,
@ -158,7 +156,6 @@ pub fn expand<'a>(
Clone,
::serde::Serialize,
::serde::Deserialize,
::schemars::JsonSchema,
)]
pub enum #prefix_ident {
#(#prefix_variants,)*
@ -207,11 +204,6 @@ fn generate_impls<'a>(
let specificity_match_arms = prefix_to_codes.keys().map(|prefix_str| {
let prefix = Ident::new(prefix_str, Span::call_site());
if prefix_str == ALL {
quote! {
#prefix_ident::#prefix => Specificity::All,
}
} else {
let mut num_numeric = prefix_str.chars().filter(|char| char.is_numeric()).count();
if prefix_str != "PL" && prefix_str.starts_with("PL") {
num_numeric += 1;
@ -228,7 +220,6 @@ fn generate_impls<'a>(
quote! {
#prefix_ident::#prefix => #suffix_len,
}
}
});
quote! {

View File

@ -1,33 +1,120 @@
use std::str::FromStr;
use schemars::_serde_json::Value;
use schemars::schema::{InstanceType, Schema, SchemaObject};
use schemars::JsonSchema;
use serde::de::{self, Visitor};
use serde::{Deserialize, Serialize};
use strum::IntoEnumIterator;
use crate::registry::{Rule, RuleCodePrefix};
use crate::registry::{Rule, RuleCodePrefix, RuleIter};
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
pub struct RuleSelector(RuleCodePrefix);
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub enum RuleSelector {
/// All rules
All,
Prefix(RuleCodePrefix),
}
impl FromStr for RuleSelector {
type Err = strum::ParseError;
type Err = ParseError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(Self(RuleCodePrefix::from_str(s)?))
if s == "ALL" {
Ok(Self::All)
} else {
Ok(Self::Prefix(
RuleCodePrefix::from_str(s).map_err(|_| ParseError::Unknown(s.to_string()))?,
))
}
}
}
#[derive(Debug, thiserror::Error)]
pub enum ParseError {
#[error("Unknown rule selector `{0}`")]
// TODO(martin): tell the user how to discover rule codes via the CLI once such a command is
// implemented (but that should of course be done only in ruff_cli and not here)
Unknown(String),
}
impl Serialize for RuleSelector {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
match self {
RuleSelector::All => serializer.serialize_str("ALL"),
RuleSelector::Prefix(prefix) => prefix.serialize(serializer),
}
}
}
impl<'de> Deserialize<'de> for RuleSelector {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
// We are not simply doing:
// let s: &str = Deserialize::deserialize(deserializer)?;
// FromStr::from_str(s).map_err(de::Error::custom)
// here because the toml crate apparently doesn't support that
// (as of toml v0.6.0 running `cargo test` failed with the above two lines)
deserializer.deserialize_str(SelectorVisitor)
}
}
struct SelectorVisitor;
impl Visitor<'_> for SelectorVisitor {
type Value = RuleSelector;
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
formatter.write_str(
"expected a string code identifying a linter or specific rule, or a partial rule code \
or ALL to refer to all rules",
)
}
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
where
E: de::Error,
{
FromStr::from_str(v).map_err(de::Error::custom)
}
}
impl From<RuleCodePrefix> for RuleSelector {
fn from(prefix: RuleCodePrefix) -> Self {
Self(prefix)
Self::Prefix(prefix)
}
}
impl IntoIterator for &RuleSelector {
type IntoIter = ::std::vec::IntoIter<Self::Item>;
type IntoIter = RuleSelectorIter;
type Item = Rule;
fn into_iter(self) -> Self::IntoIter {
self.0.into_iter()
match self {
RuleSelector::All => RuleSelectorIter::All(Rule::iter()),
RuleSelector::Prefix(prefix) => RuleSelectorIter::Prefix(prefix.into_iter()),
}
}
}
pub enum RuleSelectorIter {
All(RuleIter),
Prefix(std::vec::IntoIter<Rule>),
}
impl Iterator for RuleSelectorIter {
type Item = Rule;
fn next(&mut self) -> Option<Self::Item> {
match self {
RuleSelectorIter::All(iter) => iter.next(),
RuleSelectorIter::Prefix(iter) => iter.next(),
}
}
}
@ -37,7 +124,7 @@ impl IntoIterator for &RuleSelector {
// 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)
RuleSelector::Prefix(prefix)
}
impl JsonSchema for RuleSelector {
@ -45,14 +132,26 @@ impl JsonSchema for RuleSelector {
"RuleSelector".to_string()
}
fn json_schema(gen: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema {
<RuleCodePrefix as JsonSchema>::json_schema(gen)
fn json_schema(_gen: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema {
Schema::Object(SchemaObject {
instance_type: Some(InstanceType::String.into()),
enum_values: Some(
std::iter::once("ALL".to_string())
.chain(RuleCodePrefix::iter().map(|s| s.as_ref().to_string()))
.map(Value::String)
.collect(),
),
..SchemaObject::default()
})
}
}
impl RuleSelector {
pub(crate) fn specificity(&self) -> Specificity {
self.0.specificity()
match self {
RuleSelector::All => Specificity::All,
RuleSelector::Prefix(prefix) => prefix.specificity(),
}
}
}

View File

@ -239,10 +239,7 @@ impl From<&Configuration> for RuleTable {
let mut rules = RuleTable::empty();
let fixable = resolve_codes([RuleCodeSpec {
select: config
.fixable
.as_deref()
.unwrap_or(&[crate::registry::RuleCodePrefix::ALL.into()]),
select: config.fixable.as_deref().unwrap_or(&[RuleSelector::All]),
ignore: config.unfixable.as_deref().unwrap_or_default(),
}]);