mirror of
https://github.com/astral-sh/ruff.git
synced 2025-09-27 12:29:28 +00:00
Turn Linters', etc. implicit into_iter()
s into explicit rules()
(#5436)
## Summary As discussed on ~IRC~ Discord, this will make it easier for e.g. the docs generation stuff to get all rules for a linter (using `all_rules()`) instead of just non-nursery ones, and it also makes it more Explicit Is Better Than Implicit to iterate over linter rules. Grepping for `Item = Rule` reveals some remaining implicit `IntoIterator`s that I didn't feel were necessarily in scope for this (and honestly, iterating over a `RuleSet` makes sense).
This commit is contained in:
parent
a647f31600
commit
6acc316d19
8 changed files with 50 additions and 52 deletions
|
@ -333,7 +333,7 @@ pub(crate) fn infer_plugins_from_codes(selectors: &HashSet<RuleSelector>) -> Vec
|
||||||
for selector in selectors {
|
for selector in selectors {
|
||||||
if selector
|
if selector
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.any(|rule| Linter::from(plugin).into_iter().any(|r| r == rule))
|
.any(|rule| Linter::from(plugin).rules().any(|r| r == rule))
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,7 @@ impl Rule {
|
||||||
pub fn from_code(code: &str) -> Result<Self, FromCodeError> {
|
pub fn from_code(code: &str) -> Result<Self, FromCodeError> {
|
||||||
let (linter, code) = Linter::parse_code(code).ok_or(FromCodeError::Unknown)?;
|
let (linter, code) = Linter::parse_code(code).ok_or(FromCodeError::Unknown)?;
|
||||||
let prefix: RuleCodePrefix = RuleCodePrefix::parse(&linter, code)?;
|
let prefix: RuleCodePrefix = RuleCodePrefix::parse(&linter, code)?;
|
||||||
Ok(prefix.into_iter().next().unwrap())
|
Ok(prefix.rules().next().unwrap())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -158,16 +158,16 @@ impl IntoIterator for &RuleSelector {
|
||||||
}
|
}
|
||||||
RuleSelector::C => RuleSelectorIter::Chain(
|
RuleSelector::C => RuleSelectorIter::Chain(
|
||||||
Linter::Flake8Comprehensions
|
Linter::Flake8Comprehensions
|
||||||
.into_iter()
|
.rules()
|
||||||
.chain(Linter::McCabe.into_iter()),
|
.chain(Linter::McCabe.rules()),
|
||||||
),
|
),
|
||||||
RuleSelector::T => RuleSelectorIter::Chain(
|
RuleSelector::T => RuleSelectorIter::Chain(
|
||||||
Linter::Flake8Debugger
|
Linter::Flake8Debugger
|
||||||
.into_iter()
|
.rules()
|
||||||
.chain(Linter::Flake8Print.into_iter()),
|
.chain(Linter::Flake8Print.rules()),
|
||||||
),
|
),
|
||||||
RuleSelector::Linter(linter) => RuleSelectorIter::Vec(linter.into_iter()),
|
RuleSelector::Linter(linter) => RuleSelectorIter::Vec(linter.rules()),
|
||||||
RuleSelector::Prefix { prefix, .. } => RuleSelectorIter::Vec(prefix.into_iter()),
|
RuleSelector::Prefix { prefix, .. } => RuleSelectorIter::Vec(prefix.clone().rules()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -346,7 +346,7 @@ mod clap_completion {
|
||||||
let prefix = p.linter().common_prefix();
|
let prefix = p.linter().common_prefix();
|
||||||
let code = p.short_code();
|
let code = p.short_code();
|
||||||
|
|
||||||
let mut rules_iter = p.into_iter();
|
let mut rules_iter = p.rules();
|
||||||
let rule1 = rules_iter.next();
|
let rule1 = rules_iter.next();
|
||||||
let rule2 = rules_iter.next();
|
let rule2 = rules_iter.next();
|
||||||
|
|
||||||
|
|
|
@ -327,7 +327,7 @@ mod tests {
|
||||||
fn contents(contents: &str, snapshot: &str) {
|
fn contents(contents: &str, snapshot: &str) {
|
||||||
let diagnostics = test_snippet(
|
let diagnostics = test_snippet(
|
||||||
contents,
|
contents,
|
||||||
&settings::Settings::for_rules(&Linter::Flake8TypeChecking),
|
&settings::Settings::for_rules(Linter::Flake8TypeChecking.rules()),
|
||||||
);
|
);
|
||||||
assert_messages!(snapshot, diagnostics);
|
assert_messages!(snapshot, diagnostics);
|
||||||
}
|
}
|
||||||
|
|
|
@ -353,8 +353,10 @@ mod tests {
|
||||||
"PD901_fail_df_var"
|
"PD901_fail_df_var"
|
||||||
)]
|
)]
|
||||||
fn contents(contents: &str, snapshot: &str) {
|
fn contents(contents: &str, snapshot: &str) {
|
||||||
let diagnostics =
|
let diagnostics = test_snippet(
|
||||||
test_snippet(contents, &settings::Settings::for_rules(&Linter::PandasVet));
|
contents,
|
||||||
|
&settings::Settings::for_rules(Linter::PandasVet.rules()),
|
||||||
|
);
|
||||||
assert_messages!(snapshot, diagnostics);
|
assert_messages!(snapshot, diagnostics);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -490,7 +490,7 @@ mod tests {
|
||||||
"load_after_unbind_from_class_scope"
|
"load_after_unbind_from_class_scope"
|
||||||
)]
|
)]
|
||||||
fn contents(contents: &str, snapshot: &str) {
|
fn contents(contents: &str, snapshot: &str) {
|
||||||
let diagnostics = test_snippet(contents, &Settings::for_rules(&Linter::Pyflakes));
|
let diagnostics = test_snippet(contents, &Settings::for_rules(Linter::Pyflakes.rules()));
|
||||||
assert_messages!(snapshot, diagnostics);
|
assert_messages!(snapshot, diagnostics);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -498,7 +498,7 @@ mod tests {
|
||||||
/// Note that all tests marked with `#[ignore]` should be considered TODOs.
|
/// Note that all tests marked with `#[ignore]` should be considered TODOs.
|
||||||
fn flakes(contents: &str, expected: &[Rule]) {
|
fn flakes(contents: &str, expected: &[Rule]) {
|
||||||
let contents = dedent(contents);
|
let contents = dedent(contents);
|
||||||
let settings = Settings::for_rules(&Linter::Pyflakes);
|
let settings = Settings::for_rules(Linter::Pyflakes.rules());
|
||||||
let tokens: Vec<LexResult> = ruff_rustpython::tokenize(&contents);
|
let tokens: Vec<LexResult> = ruff_rustpython::tokenize(&contents);
|
||||||
let locator = Locator::new(&contents);
|
let locator = Locator::new(&contents);
|
||||||
let stylist = Stylist::from_tokens(&tokens, &locator);
|
let stylist = Stylist::from_tokens(&tokens, &locator);
|
||||||
|
|
|
@ -102,10 +102,10 @@ pub(crate) fn generate() -> String {
|
||||||
));
|
));
|
||||||
table_out.push('\n');
|
table_out.push('\n');
|
||||||
table_out.push('\n');
|
table_out.push('\n');
|
||||||
generate_table(&mut table_out, prefix, &linter);
|
generate_table(&mut table_out, prefix.clone().rules(), &linter);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
generate_table(&mut table_out, &linter, &linter);
|
generate_table(&mut table_out, linter.rules(), &linter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -155,30 +155,13 @@ pub(crate) fn map_codes(func: &ItemFn) -> syn::Result<TokenStream> {
|
||||||
}
|
}
|
||||||
|
|
||||||
output.extend(quote! {
|
output.extend(quote! {
|
||||||
impl IntoIterator for &#linter {
|
impl #linter {
|
||||||
type Item = Rule;
|
pub fn rules(self) -> ::std::vec::IntoIter<Rule> {
|
||||||
type IntoIter = ::std::vec::IntoIter<Self::Item>;
|
|
||||||
|
|
||||||
fn into_iter(self) -> Self::IntoIter {
|
|
||||||
match self { #prefix_into_iter_match_arms }
|
match self { #prefix_into_iter_match_arms }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
output.extend(quote! {
|
|
||||||
impl IntoIterator for &RuleCodePrefix {
|
|
||||||
type Item = Rule;
|
|
||||||
type IntoIter = ::std::vec::IntoIter<Self::Item>;
|
|
||||||
|
|
||||||
fn into_iter(self) -> Self::IntoIter {
|
|
||||||
match self {
|
|
||||||
#(RuleCodePrefix::#linter_idents(prefix) => prefix.into_iter(),)*
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
output.extend(quote! {
|
output.extend(quote! {
|
||||||
impl RuleCodePrefix {
|
impl RuleCodePrefix {
|
||||||
pub fn parse(linter: &Linter, code: &str) -> Result<Self, crate::registry::FromCodeError> {
|
pub fn parse(linter: &Linter, code: &str) -> Result<Self, crate::registry::FromCodeError> {
|
||||||
|
@ -188,6 +171,12 @@ pub(crate) fn map_codes(func: &ItemFn) -> syn::Result<TokenStream> {
|
||||||
#(Linter::#linter_idents => RuleCodePrefix::#linter_idents(#linter_idents::from_str(code).map_err(|_| crate::registry::FromCodeError::Unknown)?),)*
|
#(Linter::#linter_idents => RuleCodePrefix::#linter_idents(#linter_idents::from_str(code).map_err(|_| crate::registry::FromCodeError::Unknown)?),)*
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn rules(self) -> ::std::vec::IntoIter<Rule> {
|
||||||
|
match self {
|
||||||
|
#(RuleCodePrefix::#linter_idents(prefix) => prefix.clone().rules(),)*
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -344,32 +333,39 @@ fn generate_iter_impl(
|
||||||
linter_to_rules: &BTreeMap<Ident, BTreeMap<String, Rule>>,
|
linter_to_rules: &BTreeMap<Ident, BTreeMap<String, Rule>>,
|
||||||
linter_idents: &[&Ident],
|
linter_idents: &[&Ident],
|
||||||
) -> TokenStream {
|
) -> TokenStream {
|
||||||
let mut linter_into_iter_match_arms = quote!();
|
let mut linter_rules_match_arms = quote!();
|
||||||
|
let mut linter_all_rules_match_arms = quote!();
|
||||||
for (linter, map) in linter_to_rules {
|
for (linter, map) in linter_to_rules {
|
||||||
let rule_paths = map
|
let rule_paths = map.values().filter(|rule| !is_nursery(&rule.group)).map(
|
||||||
.values()
|
|Rule { attrs, path, .. }| {
|
||||||
.filter(|rule| {
|
let rule_name = path.segments.last().unwrap();
|
||||||
// Nursery rules have to be explicitly selected, so we ignore them when looking at
|
quote!(#(#attrs)* Rule::#rule_name)
|
||||||
// linter-level selectors (e.g., `--select SIM`).
|
},
|
||||||
!is_nursery(&rule.group)
|
);
|
||||||
})
|
linter_rules_match_arms.extend(quote! {
|
||||||
.map(|Rule { attrs, path, .. }| {
|
Linter::#linter => vec![#(#rule_paths,)*].into_iter(),
|
||||||
|
});
|
||||||
|
let rule_paths = map.values().map(|Rule { attrs, path, .. }| {
|
||||||
let rule_name = path.segments.last().unwrap();
|
let rule_name = path.segments.last().unwrap();
|
||||||
quote!(#(#attrs)* Rule::#rule_name)
|
quote!(#(#attrs)* Rule::#rule_name)
|
||||||
});
|
});
|
||||||
linter_into_iter_match_arms.extend(quote! {
|
linter_all_rules_match_arms.extend(quote! {
|
||||||
Linter::#linter => vec![#(#rule_paths,)*].into_iter(),
|
Linter::#linter => vec![#(#rule_paths,)*].into_iter(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
quote! {
|
quote! {
|
||||||
impl IntoIterator for &Linter {
|
impl Linter {
|
||||||
type Item = Rule;
|
/// Rules not in the nursery.
|
||||||
type IntoIter = ::std::vec::IntoIter<Self::Item>;
|
pub fn rules(self: &Linter) -> ::std::vec::IntoIter<Rule> {
|
||||||
|
|
||||||
fn into_iter(self) -> Self::IntoIter {
|
|
||||||
match self {
|
match self {
|
||||||
#linter_into_iter_match_arms
|
#linter_rules_match_arms
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// All rules, including those in the nursery.
|
||||||
|
pub fn all_rules(self: &Linter) -> ::std::vec::IntoIter<Rule> {
|
||||||
|
match self {
|
||||||
|
#linter_all_rules_match_arms
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue