mirror of
https://github.com/astral-sh/ruff.git
synced 2025-08-03 18:28:24 +00:00
refactor: Simplify attribute handling in rule_code_prefix
if_all_same(codes.values().cloned()).unwrap_or_default() was quite unreadable because it wasn't obvious that codes.values() are the prefixes. It's better to introduce another Map rather than having Maps within Maps.
This commit is contained in:
parent
fa191cceeb
commit
9011456aa1
1 changed files with 35 additions and 17 deletions
|
@ -1,4 +1,4 @@
|
|||
use std::collections::BTreeMap;
|
||||
use std::collections::{BTreeMap, BTreeSet};
|
||||
|
||||
use proc_macro2::Span;
|
||||
use quote::quote;
|
||||
|
@ -11,10 +11,10 @@ pub fn expand<'a>(
|
|||
variant_name: impl Fn(&str) -> &'a Ident,
|
||||
) -> proc_macro2::TokenStream {
|
||||
// Build up a map from prefix to matching RuleCodes.
|
||||
let mut prefix_to_codes: BTreeMap<String, BTreeMap<String, Vec<Attribute>>> =
|
||||
BTreeMap::default();
|
||||
let mut prefix_to_codes: BTreeMap<String, BTreeSet<String>> = BTreeMap::default();
|
||||
let mut attributes: BTreeMap<String, &[Attribute]> = BTreeMap::default();
|
||||
|
||||
let mut pl_codes = BTreeMap::new();
|
||||
let mut pl_codes = BTreeSet::new();
|
||||
|
||||
for (variant, attr) in variants {
|
||||
let code_str = variant.to_string();
|
||||
|
@ -28,26 +28,32 @@ pub fn expand<'a>(
|
|||
prefix_to_codes
|
||||
.entry(prefix)
|
||||
.or_default()
|
||||
.entry(code_str.clone())
|
||||
.or_insert_with(|| attr.clone());
|
||||
.insert(code_str.clone());
|
||||
}
|
||||
if code_str.starts_with("PL") {
|
||||
pl_codes.insert(code_str, attr.clone());
|
||||
pl_codes.insert(code_str.clone());
|
||||
}
|
||||
attributes.insert(code_str, attr);
|
||||
}
|
||||
|
||||
prefix_to_codes.insert("PL".to_string(), pl_codes);
|
||||
|
||||
let prefix_variants = prefix_to_codes.iter().map(|(prefix, codes)| {
|
||||
let prefix = Ident::new(prefix, Span::call_site());
|
||||
let attr = if_all_same(codes.values().cloned()).unwrap_or_default();
|
||||
let attrs = attributes_for_prefix(codes, &attributes);
|
||||
quote! {
|
||||
#(#attr)*
|
||||
#attrs
|
||||
#prefix
|
||||
}
|
||||
});
|
||||
|
||||
let prefix_impl = generate_impls(rule_type, prefix_ident, &prefix_to_codes, variant_name);
|
||||
let prefix_impl = generate_impls(
|
||||
rule_type,
|
||||
prefix_ident,
|
||||
&prefix_to_codes,
|
||||
variant_name,
|
||||
&attributes,
|
||||
);
|
||||
|
||||
quote! {
|
||||
#[derive(
|
||||
|
@ -76,21 +82,23 @@ pub fn expand<'a>(
|
|||
fn generate_impls<'a>(
|
||||
rule_type: &Ident,
|
||||
prefix_ident: &Ident,
|
||||
prefix_to_codes: &BTreeMap<String, BTreeMap<String, Vec<Attribute>>>,
|
||||
prefix_to_codes: &BTreeMap<String, BTreeSet<String>>,
|
||||
variant_name: impl Fn(&str) -> &'a Ident,
|
||||
attributes: &BTreeMap<String, &[Attribute]>,
|
||||
) -> proc_macro2::TokenStream {
|
||||
let into_iter_match_arms = prefix_to_codes.iter().map(|(prefix_str, codes)| {
|
||||
let prefix = Ident::new(prefix_str, Span::call_site());
|
||||
let attr = if_all_same(codes.values().cloned()).unwrap_or_default();
|
||||
let codes = codes.iter().map(|(code, attr)| {
|
||||
let attrs = attributes_for_prefix(codes, attributes);
|
||||
let codes = codes.iter().map(|code| {
|
||||
let rule_variant = variant_name(code);
|
||||
let attrs = attributes[code];
|
||||
quote! {
|
||||
#(#attr)*
|
||||
#(#attrs)*
|
||||
#rule_type::#rule_variant
|
||||
}
|
||||
});
|
||||
quote! {
|
||||
#(#attr)*
|
||||
#attrs
|
||||
#prefix_ident::#prefix => vec![#(#codes),*].into_iter(),
|
||||
}
|
||||
});
|
||||
|
@ -110,9 +118,9 @@ fn generate_impls<'a>(
|
|||
5 => quote! { Specificity::Code5Chars },
|
||||
_ => panic!("Invalid prefix: {prefix}"),
|
||||
};
|
||||
let attr = if_all_same(codes.values().cloned()).unwrap_or_default();
|
||||
let attrs = attributes_for_prefix(codes, attributes);
|
||||
quote! {
|
||||
#(#attr)*
|
||||
#attrs
|
||||
#prefix_ident::#prefix => #suffix_len,
|
||||
}
|
||||
});
|
||||
|
@ -143,6 +151,16 @@ fn generate_impls<'a>(
|
|||
}
|
||||
}
|
||||
|
||||
fn attributes_for_prefix(
|
||||
codes: &BTreeSet<String>,
|
||||
attributes: &BTreeMap<String, &[Attribute]>,
|
||||
) -> proc_macro2::TokenStream {
|
||||
match if_all_same(codes.iter().map(|code| attributes[code])) {
|
||||
Some(attr) => quote!(#(#attr)*),
|
||||
None => quote!(),
|
||||
}
|
||||
}
|
||||
|
||||
/// If all values in an iterator are the same, return that value. Otherwise,
|
||||
/// return `None`.
|
||||
fn if_all_same<T: PartialEq>(iter: impl Iterator<Item = T>) -> Option<T> {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue