-
Notifications
You must be signed in to change notification settings - Fork 895
/
register_rules.rs
98 lines (85 loc) · 3.2 KB
/
register_rules.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
use quote::quote;
use syn::parse::Parse;
use syn::{Attribute, Ident, Path, Token};
pub fn register_rules(input: &Input) -> proc_macro2::TokenStream {
let mut rule_variants = quote!();
let mut rule_message_formats_match_arms = quote!();
let mut rule_autofixable_match_arms = quote!();
let mut rule_explanation_match_arms = quote!();
let mut from_impls_for_diagnostic_kind = quote!();
for (path, name, attr) in &input.entries {
rule_variants.extend(quote! {
#(#attr)*
#name,
});
// Apply the `attrs` to each arm, like `[cfg(feature = "foo")]`.
rule_message_formats_match_arms
.extend(quote! {#(#attr)* Self::#name => <#path as ruff_diagnostics::Violation>::message_formats(),});
rule_autofixable_match_arms.extend(
quote! {#(#attr)* Self::#name => <#path as ruff_diagnostics::Violation>::AUTOFIX,},
);
rule_explanation_match_arms.extend(quote! {#(#attr)* Self::#name => #path::explanation(),});
// Enable conversion from `DiagnosticKind` to `Rule`.
from_impls_for_diagnostic_kind
.extend(quote! {#(#attr)* stringify!(#name) => &Rule::#name,});
}
quote! {
#[derive(
EnumIter,
Debug,
PartialEq,
Eq,
Clone,
Hash,
PartialOrd,
Ord,
::ruff_macros::CacheKey,
AsRefStr,
::strum_macros::IntoStaticStr,
)]
#[strum(serialize_all = "kebab-case")]
pub enum Rule { #rule_variants }
impl Rule {
/// Returns the format strings used to report violations of this rule.
pub fn message_formats(&self) -> &'static [&'static str] {
match self { #rule_message_formats_match_arms }
}
/// Returns the documentation for this rule.
pub fn explanation(&self) -> Option<&'static str> {
match self { #rule_explanation_match_arms }
}
/// Returns the autofix status of this rule.
pub fn autofixable(&self) -> Option<ruff_diagnostics::AutofixKind> {
match self { #rule_autofixable_match_arms }
}
}
pub trait AsRule {
fn rule(&self) -> &'static Rule;
}
impl AsRule for ruff_diagnostics::DiagnosticKind {
fn rule(&self) -> &'static Rule {
match self.name.as_str() {
#from_impls_for_diagnostic_kind
_ => unreachable!("invalid rule name: {}", self.name),
}
}
}
}
}
pub struct Input {
entries: Vec<(Path, Ident, Vec<Attribute>)>,
}
impl Parse for Input {
fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
let mut entries = Vec::new();
while !input.is_empty() {
// Grab the `#[cfg(...)]` attributes.
let attrs = input.call(Attribute::parse_outer)?;
let path: Path = input.parse()?;
let name = path.segments.last().unwrap().ident.clone();
let _: Token![,] = input.parse()?;
entries.push((path, name, attrs));
}
Ok(Self { entries })
}
}