diff --git a/crates/ruff/src/flake8_to_ruff/plugin.rs b/crates/ruff/src/flake8_to_ruff/plugin.rs index 77f6645d29..c234556c8a 100644 --- a/crates/ruff/src/flake8_to_ruff/plugin.rs +++ b/crates/ruff/src/flake8_to_ruff/plugin.rs @@ -333,7 +333,7 @@ pub(crate) fn infer_plugins_from_codes(selectors: &HashSet) -> Vec for selector in selectors { if selector .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; } diff --git a/crates/ruff/src/registry.rs b/crates/ruff/src/registry.rs index dd47f24815..d53cd6ac7e 100644 --- a/crates/ruff/src/registry.rs +++ b/crates/ruff/src/registry.rs @@ -19,7 +19,7 @@ impl Rule { pub fn from_code(code: &str) -> Result { let (linter, code) = Linter::parse_code(code).ok_or(FromCodeError::Unknown)?; let prefix: RuleCodePrefix = RuleCodePrefix::parse(&linter, code)?; - Ok(prefix.into_iter().next().unwrap()) + Ok(prefix.rules().next().unwrap()) } } diff --git a/crates/ruff/src/rule_selector.rs b/crates/ruff/src/rule_selector.rs index 6247346a51..5eb5f1461b 100644 --- a/crates/ruff/src/rule_selector.rs +++ b/crates/ruff/src/rule_selector.rs @@ -158,16 +158,16 @@ impl IntoIterator for &RuleSelector { } RuleSelector::C => RuleSelectorIter::Chain( Linter::Flake8Comprehensions - .into_iter() - .chain(Linter::McCabe.into_iter()), + .rules() + .chain(Linter::McCabe.rules()), ), RuleSelector::T => RuleSelectorIter::Chain( Linter::Flake8Debugger - .into_iter() - .chain(Linter::Flake8Print.into_iter()), + .rules() + .chain(Linter::Flake8Print.rules()), ), - RuleSelector::Linter(linter) => RuleSelectorIter::Vec(linter.into_iter()), - RuleSelector::Prefix { prefix, .. } => RuleSelectorIter::Vec(prefix.into_iter()), + RuleSelector::Linter(linter) => RuleSelectorIter::Vec(linter.rules()), + RuleSelector::Prefix { prefix, .. } => RuleSelectorIter::Vec(prefix.clone().rules()), } } } @@ -346,7 +346,7 @@ mod clap_completion { let prefix = p.linter().common_prefix(); let code = p.short_code(); - let mut rules_iter = p.into_iter(); + let mut rules_iter = p.rules(); let rule1 = rules_iter.next(); let rule2 = rules_iter.next(); diff --git a/crates/ruff/src/rules/flake8_type_checking/mod.rs b/crates/ruff/src/rules/flake8_type_checking/mod.rs index 06ea6ab839..01aa8c60e4 100644 --- a/crates/ruff/src/rules/flake8_type_checking/mod.rs +++ b/crates/ruff/src/rules/flake8_type_checking/mod.rs @@ -327,7 +327,7 @@ mod tests { fn contents(contents: &str, snapshot: &str) { let diagnostics = test_snippet( contents, - &settings::Settings::for_rules(&Linter::Flake8TypeChecking), + &settings::Settings::for_rules(Linter::Flake8TypeChecking.rules()), ); assert_messages!(snapshot, diagnostics); } diff --git a/crates/ruff/src/rules/pandas_vet/mod.rs b/crates/ruff/src/rules/pandas_vet/mod.rs index 2032749fe2..295a83cd24 100644 --- a/crates/ruff/src/rules/pandas_vet/mod.rs +++ b/crates/ruff/src/rules/pandas_vet/mod.rs @@ -353,8 +353,10 @@ mod tests { "PD901_fail_df_var" )] fn contents(contents: &str, snapshot: &str) { - let diagnostics = - test_snippet(contents, &settings::Settings::for_rules(&Linter::PandasVet)); + let diagnostics = test_snippet( + contents, + &settings::Settings::for_rules(Linter::PandasVet.rules()), + ); assert_messages!(snapshot, diagnostics); } diff --git a/crates/ruff/src/rules/pyflakes/mod.rs b/crates/ruff/src/rules/pyflakes/mod.rs index 0bdbeaee1d..e796ac4563 100644 --- a/crates/ruff/src/rules/pyflakes/mod.rs +++ b/crates/ruff/src/rules/pyflakes/mod.rs @@ -490,7 +490,7 @@ mod tests { "load_after_unbind_from_class_scope" )] 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); } @@ -498,7 +498,7 @@ mod tests { /// Note that all tests marked with `#[ignore]` should be considered TODOs. fn flakes(contents: &str, expected: &[Rule]) { let contents = dedent(contents); - let settings = Settings::for_rules(&Linter::Pyflakes); + let settings = Settings::for_rules(Linter::Pyflakes.rules()); let tokens: Vec = ruff_rustpython::tokenize(&contents); let locator = Locator::new(&contents); let stylist = Stylist::from_tokens(&tokens, &locator); diff --git a/crates/ruff_dev/src/generate_rules_table.rs b/crates/ruff_dev/src/generate_rules_table.rs index 4d29bfea2b..6f1b18cfea 100644 --- a/crates/ruff_dev/src/generate_rules_table.rs +++ b/crates/ruff_dev/src/generate_rules_table.rs @@ -102,10 +102,10 @@ pub(crate) fn generate() -> String { )); 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 { - generate_table(&mut table_out, &linter, &linter); + generate_table(&mut table_out, linter.rules(), &linter); } } diff --git a/crates/ruff_macros/src/map_codes.rs b/crates/ruff_macros/src/map_codes.rs index d37113e0aa..eeee0d7ac9 100644 --- a/crates/ruff_macros/src/map_codes.rs +++ b/crates/ruff_macros/src/map_codes.rs @@ -155,30 +155,13 @@ pub(crate) fn map_codes(func: &ItemFn) -> syn::Result { } output.extend(quote! { - impl IntoIterator for &#linter { - type Item = Rule; - type IntoIter = ::std::vec::IntoIter; - - fn into_iter(self) -> Self::IntoIter { + impl #linter { + pub fn rules(self) -> ::std::vec::IntoIter { match self { #prefix_into_iter_match_arms } } } }); } - - output.extend(quote! { - impl IntoIterator for &RuleCodePrefix { - type Item = Rule; - type IntoIter = ::std::vec::IntoIter; - - fn into_iter(self) -> Self::IntoIter { - match self { - #(RuleCodePrefix::#linter_idents(prefix) => prefix.into_iter(),)* - } - } - } - }); - output.extend(quote! { impl RuleCodePrefix { pub fn parse(linter: &Linter, code: &str) -> Result { @@ -188,6 +171,12 @@ pub(crate) fn map_codes(func: &ItemFn) -> syn::Result { #(Linter::#linter_idents => RuleCodePrefix::#linter_idents(#linter_idents::from_str(code).map_err(|_| crate::registry::FromCodeError::Unknown)?),)* }) } + + pub fn rules(self) -> ::std::vec::IntoIter { + match self { + #(RuleCodePrefix::#linter_idents(prefix) => prefix.clone().rules(),)* + } + } } }); @@ -344,32 +333,39 @@ fn generate_iter_impl( linter_to_rules: &BTreeMap>, linter_idents: &[&Ident], ) -> 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 { - let rule_paths = map - .values() - .filter(|rule| { - // Nursery rules have to be explicitly selected, so we ignore them when looking at - // linter-level selectors (e.g., `--select SIM`). - !is_nursery(&rule.group) - }) - .map(|Rule { attrs, path, .. }| { + let rule_paths = map.values().filter(|rule| !is_nursery(&rule.group)).map( + |Rule { attrs, path, .. }| { let rule_name = path.segments.last().unwrap(); quote!(#(#attrs)* Rule::#rule_name) - }); - linter_into_iter_match_arms.extend(quote! { + }, + ); + linter_rules_match_arms.extend(quote! { + Linter::#linter => vec![#(#rule_paths,)*].into_iter(), + }); + let rule_paths = map.values().map(|Rule { attrs, path, .. }| { + let rule_name = path.segments.last().unwrap(); + quote!(#(#attrs)* Rule::#rule_name) + }); + linter_all_rules_match_arms.extend(quote! { Linter::#linter => vec![#(#rule_paths,)*].into_iter(), }); } quote! { - impl IntoIterator for &Linter { - type Item = Rule; - type IntoIter = ::std::vec::IntoIter; - - fn into_iter(self) -> Self::IntoIter { + impl Linter { + /// Rules not in the nursery. + pub fn rules(self: &Linter) -> ::std::vec::IntoIter { 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 { + match self { + #linter_all_rules_match_arms } } }