mirror of https://github.com/astral-sh/ruff
refactor: Move ALL from RuleCodePrefix to RuleSelector
This commit is contained in:
parent
abc9810e2b
commit
28018442f6
|
|
@ -1188,13 +1188,13 @@
|
||||||
"RuleSelector": {
|
"RuleSelector": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"enum": [
|
"enum": [
|
||||||
|
"ALL",
|
||||||
"A",
|
"A",
|
||||||
"A0",
|
"A0",
|
||||||
"A00",
|
"A00",
|
||||||
"A001",
|
"A001",
|
||||||
"A002",
|
"A002",
|
||||||
"A003",
|
"A003",
|
||||||
"ALL",
|
|
||||||
"ANN",
|
"ANN",
|
||||||
"ANN0",
|
"ANN0",
|
||||||
"ANN00",
|
"ANN00",
|
||||||
|
|
|
||||||
|
|
@ -5,8 +5,6 @@ use proc_macro2::Span;
|
||||||
use quote::quote;
|
use quote::quote;
|
||||||
use syn::Ident;
|
use syn::Ident;
|
||||||
|
|
||||||
const ALL: &str = "ALL";
|
|
||||||
|
|
||||||
/// A hash map from deprecated `RuleSelector` to latest
|
/// A hash map from deprecated `RuleSelector` to latest
|
||||||
/// `RuleSelector`.
|
/// `RuleSelector`.
|
||||||
pub static PREFIX_REDIRECTS: Lazy<HashMap<&'static str, &'static str>> = Lazy::new(|| {
|
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);
|
all_codes.insert(code_str);
|
||||||
}
|
}
|
||||||
|
|
||||||
prefix_to_codes.insert(ALL.to_string(), all_codes);
|
|
||||||
prefix_to_codes.insert("PL".to_string(), pl_codes);
|
prefix_to_codes.insert("PL".to_string(), pl_codes);
|
||||||
|
|
||||||
// Add any prefix aliases (e.g., "U" to "UP").
|
// Add any prefix aliases (e.g., "U" to "UP").
|
||||||
|
|
@ -148,6 +145,7 @@ pub fn expand<'a>(
|
||||||
|
|
||||||
quote! {
|
quote! {
|
||||||
#[derive(
|
#[derive(
|
||||||
|
::strum_macros::EnumIter,
|
||||||
::strum_macros::EnumString,
|
::strum_macros::EnumString,
|
||||||
::strum_macros::AsRefStr,
|
::strum_macros::AsRefStr,
|
||||||
Debug,
|
Debug,
|
||||||
|
|
@ -158,7 +156,6 @@ pub fn expand<'a>(
|
||||||
Clone,
|
Clone,
|
||||||
::serde::Serialize,
|
::serde::Serialize,
|
||||||
::serde::Deserialize,
|
::serde::Deserialize,
|
||||||
::schemars::JsonSchema,
|
|
||||||
)]
|
)]
|
||||||
pub enum #prefix_ident {
|
pub enum #prefix_ident {
|
||||||
#(#prefix_variants,)*
|
#(#prefix_variants,)*
|
||||||
|
|
@ -207,27 +204,21 @@ fn generate_impls<'a>(
|
||||||
|
|
||||||
let specificity_match_arms = prefix_to_codes.keys().map(|prefix_str| {
|
let specificity_match_arms = prefix_to_codes.keys().map(|prefix_str| {
|
||||||
let prefix = Ident::new(prefix_str, Span::call_site());
|
let prefix = Ident::new(prefix_str, Span::call_site());
|
||||||
if prefix_str == ALL {
|
let mut num_numeric = prefix_str.chars().filter(|char| char.is_numeric()).count();
|
||||||
quote! {
|
if prefix_str != "PL" && prefix_str.starts_with("PL") {
|
||||||
#prefix_ident::#prefix => Specificity::All,
|
num_numeric += 1;
|
||||||
}
|
}
|
||||||
} else {
|
let suffix_len = match num_numeric {
|
||||||
let mut num_numeric = prefix_str.chars().filter(|char| char.is_numeric()).count();
|
0 => quote! { Specificity::Linter },
|
||||||
if prefix_str != "PL" && prefix_str.starts_with("PL") {
|
1 => quote! { Specificity::Code1Char },
|
||||||
num_numeric += 1;
|
2 => quote! { Specificity::Code2Chars },
|
||||||
}
|
3 => quote! { Specificity::Code3Chars },
|
||||||
let suffix_len = match num_numeric {
|
4 => quote! { Specificity::Code4Chars },
|
||||||
0 => quote! { Specificity::Linter },
|
5 => quote! { Specificity::Code5Chars },
|
||||||
1 => quote! { Specificity::Code1Char },
|
_ => panic!("Invalid prefix: {prefix}"),
|
||||||
2 => quote! { Specificity::Code2Chars },
|
};
|
||||||
3 => quote! { Specificity::Code3Chars },
|
quote! {
|
||||||
4 => quote! { Specificity::Code4Chars },
|
#prefix_ident::#prefix => #suffix_len,
|
||||||
5 => quote! { Specificity::Code5Chars },
|
|
||||||
_ => panic!("Invalid prefix: {prefix}"),
|
|
||||||
};
|
|
||||||
quote! {
|
|
||||||
#prefix_ident::#prefix => #suffix_len,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,33 +1,120 @@
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
|
use schemars::_serde_json::Value;
|
||||||
|
use schemars::schema::{InstanceType, Schema, SchemaObject};
|
||||||
use schemars::JsonSchema;
|
use schemars::JsonSchema;
|
||||||
|
use serde::de::{self, Visitor};
|
||||||
use serde::{Deserialize, Serialize};
|
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)]
|
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
|
||||||
pub struct RuleSelector(RuleCodePrefix);
|
pub enum RuleSelector {
|
||||||
|
/// All rules
|
||||||
|
All,
|
||||||
|
Prefix(RuleCodePrefix),
|
||||||
|
}
|
||||||
|
|
||||||
impl FromStr for RuleSelector {
|
impl FromStr for RuleSelector {
|
||||||
type Err = strum::ParseError;
|
type Err = ParseError;
|
||||||
|
|
||||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
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 {
|
impl From<RuleCodePrefix> for RuleSelector {
|
||||||
fn from(prefix: RuleCodePrefix) -> Self {
|
fn from(prefix: RuleCodePrefix) -> Self {
|
||||||
Self(prefix)
|
Self::Prefix(prefix)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IntoIterator for &RuleSelector {
|
impl IntoIterator for &RuleSelector {
|
||||||
type IntoIter = ::std::vec::IntoIter<Self::Item>;
|
type IntoIter = RuleSelectorIter;
|
||||||
type Item = Rule;
|
type Item = Rule;
|
||||||
|
|
||||||
fn into_iter(self) -> Self::IntoIter {
|
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).
|
// RuleSelector` (see https://github.com/rust-lang/rust/issues/67792).
|
||||||
// TODO(martin): Remove once RuleSelector is an enum with Linter & Rule variants
|
// TODO(martin): Remove once RuleSelector is an enum with Linter & Rule variants
|
||||||
pub(crate) const fn prefix_to_selector(prefix: RuleCodePrefix) -> RuleSelector {
|
pub(crate) const fn prefix_to_selector(prefix: RuleCodePrefix) -> RuleSelector {
|
||||||
RuleSelector(prefix)
|
RuleSelector::Prefix(prefix)
|
||||||
}
|
}
|
||||||
|
|
||||||
impl JsonSchema for RuleSelector {
|
impl JsonSchema for RuleSelector {
|
||||||
|
|
@ -45,14 +132,26 @@ impl JsonSchema for RuleSelector {
|
||||||
"RuleSelector".to_string()
|
"RuleSelector".to_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn json_schema(gen: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema {
|
fn json_schema(_gen: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema {
|
||||||
<RuleCodePrefix as JsonSchema>::json_schema(gen)
|
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 {
|
impl RuleSelector {
|
||||||
pub(crate) fn specificity(&self) -> Specificity {
|
pub(crate) fn specificity(&self) -> Specificity {
|
||||||
self.0.specificity()
|
match self {
|
||||||
|
RuleSelector::All => Specificity::All,
|
||||||
|
RuleSelector::Prefix(prefix) => prefix.specificity(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -239,10 +239,7 @@ impl From<&Configuration> for RuleTable {
|
||||||
let mut rules = RuleTable::empty();
|
let mut rules = RuleTable::empty();
|
||||||
|
|
||||||
let fixable = resolve_codes([RuleCodeSpec {
|
let fixable = resolve_codes([RuleCodeSpec {
|
||||||
select: config
|
select: config.fixable.as_deref().unwrap_or(&[RuleSelector::All]),
|
||||||
.fixable
|
|
||||||
.as_deref()
|
|
||||||
.unwrap_or(&[crate::registry::RuleCodePrefix::ALL.into()]),
|
|
||||||
ignore: config.unfixable.as_deref().unwrap_or_default(),
|
ignore: config.unfixable.as_deref().unwrap_or_default(),
|
||||||
}]);
|
}]);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue