@@ -4,14 +4,13 @@ use std::{
44} ;
55
66use itertools:: Itertools ;
7- use rustc_hash:: FxHashSet ;
7+ use rustc_hash:: FxHashMap ;
88
99use oxc_diagnostics:: OxcDiagnostic ;
1010use oxc_span:: { CompactStr , format_compact_str} ;
1111
1212use crate :: {
1313 AllowWarnDeny , LintConfig , LintFilter , LintFilterKind , Oxlintrc , RuleCategory , RuleEnum ,
14- RuleWithSeverity ,
1514 config:: { ESLintRule , LintPlugins , OxlintOverrides , OxlintRules , overrides:: OxlintOverride } ,
1615 rules:: RULES ,
1716} ;
@@ -20,7 +19,7 @@ use super::Config;
2019
2120#[ must_use = "You dropped your builder without building a Linter! Did you mean to call .build()?" ]
2221pub struct ConfigStoreBuilder {
23- pub ( super ) rules : FxHashSet < RuleWithSeverity > ,
22+ pub ( super ) rules : FxHashMap < RuleEnum , AllowWarnDeny > ,
2423 config : LintConfig ,
2524 overrides : OxlintOverrides ,
2625 cache : RulesCache ,
@@ -39,7 +38,7 @@ impl ConfigStoreBuilder {
3938 /// You can think of this as `oxlint -A all`.
4039 pub fn empty ( ) -> Self {
4140 let config = LintConfig :: default ( ) ;
42- let rules = FxHashSet :: default ( ) ;
41+ let rules = FxHashMap :: default ( ) ;
4342 let overrides = OxlintOverrides :: default ( ) ;
4443 let cache = RulesCache :: new ( config. plugins ) ;
4544
@@ -54,15 +53,8 @@ impl ConfigStoreBuilder {
5453 let config = LintConfig { plugins : LintPlugins :: all ( ) , ..LintConfig :: default ( ) } ;
5554 let overrides = OxlintOverrides :: default ( ) ;
5655 let cache = RulesCache :: new ( config. plugins ) ;
57- Self {
58- rules : RULES
59- . iter ( )
60- . map ( |rule| RuleWithSeverity { rule : rule. clone ( ) , severity : AllowWarnDeny :: Warn } )
61- . collect ( ) ,
62- config,
63- overrides,
64- cache,
65- }
56+ let rules = RULES . iter ( ) . map ( |rule| ( rule. clone ( ) , AllowWarnDeny :: Warn ) ) . collect ( ) ;
57+ Self { rules, config, overrides, cache }
6658 }
6759
6860 /// Create a [`ConfigStoreBuilder`] from a loaded or manually built [`Oxlintrc`].
@@ -104,7 +96,7 @@ impl ConfigStoreBuilder {
10496
10597 let config = LintConfig { plugins, settings, env, globals, path : Some ( path) } ;
10698 let rules =
107- if start_empty { FxHashSet :: default ( ) } else { Self :: warn_correctness ( plugins) } ;
99+ if start_empty { FxHashMap :: default ( ) } else { Self :: warn_correctness ( plugins) } ;
108100 let cache = RulesCache :: new ( config. plugins ) ;
109101 let mut builder = Self { rules, config, overrides, cache } ;
110102
@@ -222,12 +214,15 @@ impl ConfigStoreBuilder {
222214 }
223215
224216 #[ cfg( test) ]
225- pub ( crate ) fn with_rule ( mut self , rule : RuleWithSeverity ) -> Self {
226- self . rules . insert ( rule) ;
217+ pub ( crate ) fn with_rule ( mut self , rule : RuleEnum , severity : AllowWarnDeny ) -> Self {
218+ self . rules . insert ( rule, severity ) ;
227219 self
228220 }
229221
230- pub ( crate ) fn with_rules < R : IntoIterator < Item = RuleWithSeverity > > ( mut self , rules : R ) -> Self {
222+ pub ( crate ) fn with_rules < R : IntoIterator < Item = ( RuleEnum , AllowWarnDeny ) > > (
223+ mut self ,
224+ rules : R ,
225+ ) -> Self {
231226 self . rules . extend ( rules) ;
232227 self
233228 }
@@ -263,12 +258,12 @@ impl ConfigStoreBuilder {
263258 } ,
264259 AllowWarnDeny :: Allow => match filter {
265260 LintFilterKind :: Category ( category) => {
266- self . rules . retain ( |rule| rule. category ( ) != * category) ;
261+ self . rules . retain ( |rule, _ | rule. category ( ) != * category) ;
267262 }
268263 LintFilterKind :: Rule ( plugin, rule) => {
269- self . rules . retain ( |r| r. plugin_name ( ) != plugin || r. name ( ) != rule) ;
264+ self . rules . retain ( |r, _ | r. plugin_name ( ) != plugin || r. name ( ) != rule) ;
270265 }
271- LintFilterKind :: Generic ( name) => self . rules . retain ( |rule| rule. name ( ) != name) ,
266+ LintFilterKind :: Generic ( name) => self . rules . retain ( |rule, _ | rule. name ( ) != name) ,
272267 LintFilterKind :: All => self . rules . clear ( ) ,
273268 } ,
274269 }
@@ -287,14 +282,13 @@ impl ConfigStoreBuilder {
287282 // NOTE: we may want to warn users if they're configuring a rule that does not exist.
288283 let rules_to_configure = all_rules. iter ( ) . filter ( query) ;
289284 for rule in rules_to_configure {
290- match self . rules . take ( rule) {
291- Some ( mut existing_rule) => {
292- existing_rule. severity = severity;
293- self . rules . insert ( existing_rule) ;
294- }
295- _ => {
296- self . rules . insert ( RuleWithSeverity :: new ( rule. clone ( ) , severity) ) ;
297- }
285+ // If the rule is already in the list, just update its severity.
286+ // Otherwise, add it to the map.
287+
288+ if let Some ( existing_rule) = self . rules . get_mut ( rule) {
289+ * existing_rule = severity;
290+ } else {
291+ self . rules . insert ( rule. clone ( ) , severity) ;
298292 }
299293 }
300294 }
@@ -306,17 +300,20 @@ impl ConfigStoreBuilder {
306300 // to be taken out.
307301 let plugins = self . plugins ( ) ;
308302 let mut rules = if self . cache . is_stale ( ) {
309- self . rules . into_iter ( ) . filter ( |r| plugins. contains ( r. plugin_name ( ) . into ( ) ) ) . collect ( )
303+ self . rules
304+ . into_iter ( )
305+ . filter ( |( r, _) | plugins. contains ( r. plugin_name ( ) . into ( ) ) )
306+ . collect ( )
310307 } else {
311308 self . rules . into_iter ( ) . collect :: < Vec < _ > > ( )
312309 } ;
313- rules. sort_unstable_by_key ( |r | r. id ( ) ) ;
310+ rules. sort_unstable_by_key ( |( r , _ ) | r. id ( ) ) ;
314311
315312 Ok ( Config :: new ( rules, self . config , self . overrides ) )
316313 }
317314
318315 /// Warn for all correctness rules in the given set of plugins.
319- fn warn_correctness ( plugins : LintPlugins ) -> FxHashSet < RuleWithSeverity > {
316+ fn warn_correctness ( plugins : LintPlugins ) -> FxHashMap < RuleEnum , AllowWarnDeny > {
320317 RULES
321318 . iter ( )
322319 . filter ( |rule| {
@@ -325,7 +322,7 @@ impl ConfigStoreBuilder {
325322 rule. category ( ) == RuleCategory :: Correctness
326323 && plugins. contains ( LintPlugins :: from ( rule. plugin_name ( ) ) )
327324 } )
328- . map ( |rule| RuleWithSeverity { rule : rule . clone ( ) , severity : AllowWarnDeny :: Warn } )
325+ . map ( |rule| ( rule. clone ( ) , AllowWarnDeny :: Warn ) )
329326 . collect ( )
330327 }
331328
@@ -344,13 +341,13 @@ impl ConfigStoreBuilder {
344341 let new_rules = self
345342 . rules
346343 . iter ( )
347- . sorted_by_key ( |x | ( x . plugin_name ( ) , x . name ( ) ) )
348- . map ( |r : & RuleWithSeverity | ESLintRule {
344+ . sorted_by_key ( |( r , _ ) | ( r . plugin_name ( ) , r . name ( ) ) )
345+ . map ( |( r , severity ) | ESLintRule {
349346 plugin_name : r. plugin_name ( ) . to_string ( ) ,
350- rule_name : r. rule . name ( ) . to_string ( ) ,
351- severity : r . severity ,
347+ rule_name : r. name ( ) . to_string ( ) ,
348+ severity : * severity,
352349 config : rule_name_to_rule
353- . get ( & get_name ( r. plugin_name ( ) , r. rule . name ( ) ) )
350+ . get ( & get_name ( r. plugin_name ( ) , r. name ( ) ) )
354351 . and_then ( |r| r. config . clone ( ) ) ,
355352 } )
356353 . collect ( ) ;
@@ -519,10 +516,10 @@ mod test {
519516
520517 // populated with all correctness-level ESLint rules at a "warn" severity
521518 assert ! ( !builder. rules. is_empty( ) ) ;
522- for rule in & builder. rules {
519+ for ( rule, severity ) in & builder. rules {
523520 assert_eq ! ( rule. category( ) , RuleCategory :: Correctness ) ;
524- assert_eq ! ( rule . severity, AllowWarnDeny :: Warn ) ;
525- let plugin = rule. rule . plugin_name ( ) ;
521+ assert_eq ! ( * severity, AllowWarnDeny :: Warn ) ;
522+ let plugin = rule. plugin_name ( ) ;
526523 let name = rule. name ( ) ;
527524 assert ! (
528525 builder. plugins( ) . contains( plugin. into( ) ) ,
@@ -551,9 +548,9 @@ mod test {
551548 assert ! ( !builder. rules. is_empty( ) ) ;
552549 assert_eq ! ( initial_rule_count, rule_count_after_deny) ;
553550
554- for rule in & builder. rules {
551+ for ( rule, severity ) in & builder. rules {
555552 assert_eq ! ( rule. category( ) , RuleCategory :: Correctness ) ;
556- assert_eq ! ( rule . severity, AllowWarnDeny :: Deny ) ;
553+ assert_eq ! ( * severity, AllowWarnDeny :: Deny ) ;
557554
558555 let plugin = rule. plugin_name ( ) ;
559556 let name = rule. name ( ) ;
@@ -579,12 +576,12 @@ mod test {
579576 "Changing a single rule from warn to deny should not add a new one, just modify what's already there."
580577 ) ;
581578
582- let no_const_assign = builder
579+ let ( _ , severity ) = builder
583580 . rules
584581 . iter ( )
585- . find ( |r | r. plugin_name ( ) == "eslint" && r. name ( ) == "no-const-assign" )
582+ . find ( |( r , _ ) | r. plugin_name ( ) == "eslint" && r. name ( ) == "no-const-assign" )
586583 . expect ( "Could not find eslint/no-const-assign after configuring it to 'deny'" ) ;
587- assert_eq ! ( no_const_assign . severity, AllowWarnDeny :: Deny ) ;
584+ assert_eq ! ( * severity, AllowWarnDeny :: Deny ) ;
588585 }
589586 }
590587 // turn on a rule that isn't configured yet and set it to "warn"
@@ -595,15 +592,15 @@ mod test {
595592 let filter = LintFilter :: new ( AllowWarnDeny :: Warn , filter_string) . unwrap ( ) ;
596593 let builder = ConfigStoreBuilder :: default ( ) ;
597594 // sanity check: not already turned on
598- assert ! ( !builder. rules. iter( ) . any( |r | r. name( ) == "no-console" ) ) ;
595+ assert ! ( !builder. rules. iter( ) . any( |( r , _ ) | r. name( ) == "no-console" ) ) ;
599596 let builder = builder. with_filter ( & filter) ;
600- let no_console = builder
597+ let ( _ , severity ) = builder
601598 . rules
602599 . iter ( )
603- . find ( |r | r. plugin_name ( ) == "eslint" && r. name ( ) == "no-console" )
600+ . find ( |( r , _ ) | r. plugin_name ( ) == "eslint" && r. name ( ) == "no-console" )
604601 . expect ( "Could not find eslint/no-console after configuring it to 'warn'" ) ;
605602
606- assert_eq ! ( no_console . severity, AllowWarnDeny :: Warn ) ;
603+ assert_eq ! ( * severity, AllowWarnDeny :: Warn ) ;
607604 }
608605 }
609606
@@ -618,11 +615,11 @@ mod test {
618615 !builder. rules. is_empty( ) ,
619616 "warning on categories after allowing all rules should populate the rules set"
620617 ) ;
621- for rule in & builder. rules {
618+ for ( rule, severity ) in & builder. rules {
622619 let plugin = rule. plugin_name ( ) ;
623620 let name = rule. name ( ) ;
624621 assert_eq ! (
625- rule . severity,
622+ * severity,
626623 AllowWarnDeny :: Warn ,
627624 "{plugin}/{name} should have a warning severity"
628625 ) ;
@@ -656,7 +653,7 @@ mod test {
656653 desired_plugins. set ( LintPlugins :: TYPESCRIPT , false ) ;
657654
658655 let linter = ConfigStoreBuilder :: default ( ) . with_plugins ( desired_plugins) . build ( ) . unwrap ( ) ;
659- for rule in linter. base . rules . iter ( ) {
656+ for ( rule, _ ) in linter. base . rules . iter ( ) {
660657 let name = rule. name ( ) ;
661658 let plugin = rule. plugin_name ( ) ;
662659 assert_ne ! (
@@ -727,32 +724,28 @@ mod test {
727724 )
728725 . unwrap ( ) ;
729726 let builder = ConfigStoreBuilder :: from_oxlintrc ( false , oxlintrc) . unwrap ( ) ;
730- for rule in & builder. rules {
727+ for ( rule, severity ) in & builder. rules {
731728 let name = rule. name ( ) ;
732729 let plugin = rule. plugin_name ( ) ;
733730 let category = rule. category ( ) ;
734731 match category {
735732 RuleCategory :: Correctness => {
736733 if name == "no-const-assign" {
737734 assert_eq ! (
738- rule . severity,
735+ * severity,
739736 AllowWarnDeny :: Deny ,
740737 "no-const-assign should be denied" ,
741738 ) ;
742739 } else {
743740 assert_eq ! (
744- rule . severity,
741+ * severity,
745742 AllowWarnDeny :: Warn ,
746743 "{plugin}/{name} should be a warning"
747744 ) ;
748745 }
749746 }
750747 RuleCategory :: Suspicious => {
751- assert_eq ! (
752- rule. severity,
753- AllowWarnDeny :: Deny ,
754- "{plugin}/{name} should be denied"
755- ) ;
748+ assert_eq ! ( * severity, AllowWarnDeny :: Deny , "{plugin}/{name} should be denied" ) ;
756749 }
757750 invalid => {
758751 panic ! ( "Found rule {plugin}/{name} with an unexpected category {invalid:?}" ) ;
@@ -796,25 +789,26 @@ mod test {
796789 update_rules_config
797790 . rules( )
798791 . iter( )
799- . any( |r | r. name( ) == "no-debugger" && r . severity == AllowWarnDeny :: Warn )
792+ . any( |( r , severity ) | r. name( ) == "no-debugger" && * severity == AllowWarnDeny :: Warn )
800793 ) ;
801794 assert ! (
802795 update_rules_config
803796 . rules( )
804797 . iter( )
805- . any( |r | r. name( ) == "no-console" && r . severity == AllowWarnDeny :: Warn )
798+ . any( |( r , severity ) | r. name( ) == "no-console" && * severity == AllowWarnDeny :: Warn )
806799 ) ;
807800 assert ! (
808801 !update_rules_config
809802 . rules( )
810803 . iter( )
811- . any( |r | r. name( ) == "no-null" && r . severity == AllowWarnDeny :: Allow )
804+ . any( |( r , severity ) | r. name( ) == "no-null" && * severity == AllowWarnDeny :: Allow )
812805 ) ;
813806 assert ! (
814807 update_rules_config
815808 . rules( )
816809 . iter( )
817- . any( |r| r. name( ) == "prefer-as-const" && r. severity == AllowWarnDeny :: Warn )
810+ . any( |( r, severity) | r. name( ) == "prefer-as-const"
811+ && * severity == AllowWarnDeny :: Warn )
818812 ) ;
819813 }
820814
@@ -831,7 +825,7 @@ mod test {
831825 }
832826 "# ,
833827 ) ;
834- assert ! ( warn_all. rules( ) . iter( ) . all( |r| r . severity == AllowWarnDeny :: Warn ) ) ;
828+ assert ! ( warn_all. rules( ) . iter( ) . all( |( _ , severity ) | * severity == AllowWarnDeny :: Warn ) ) ;
835829
836830 let deny_all = config_store_from_str (
837831 r#"
@@ -844,7 +838,7 @@ mod test {
844838 }
845839 "# ,
846840 ) ;
847- assert ! ( deny_all. rules( ) . iter( ) . all( |r| r . severity == AllowWarnDeny :: Deny ) ) ;
841+ assert ! ( deny_all. rules( ) . iter( ) . all( |( _ , severity ) | * severity == AllowWarnDeny :: Deny ) ) ;
848842
849843 let allow_all = config_store_from_str (
850844 r#"
@@ -857,7 +851,7 @@ mod test {
857851 }
858852 "# ,
859853 ) ;
860- assert ! ( allow_all. rules( ) . iter( ) . all( |r| r . severity == AllowWarnDeny :: Allow ) ) ;
854+ assert ! ( allow_all. rules( ) . iter( ) . all( |( _ , severity ) | * severity == AllowWarnDeny :: Allow ) ) ;
861855 assert_eq ! ( allow_all. number_of_rules( ) , 0 ) ;
862856
863857 let allow_and_override_config = config_store_from_str (
@@ -879,19 +873,20 @@ mod test {
879873 allow_and_override_config
880874 . rules( )
881875 . iter( )
882- . any( |r | r. name( ) == "no-var" && r . severity == AllowWarnDeny :: Warn )
876+ . any( |( r , severity ) | r. name( ) == "no-var" && * severity == AllowWarnDeny :: Warn )
883877 ) ;
884878 assert ! (
885879 allow_and_override_config
886880 . rules( )
887881 . iter( )
888- . any( |r| r. name( ) == "approx-constant" && r. severity == AllowWarnDeny :: Deny )
882+ . any( |( r, severity) | r. name( ) == "approx-constant"
883+ && * severity == AllowWarnDeny :: Deny )
889884 ) ;
890885 assert ! (
891886 allow_and_override_config
892887 . rules( )
893888 . iter( )
894- . any( |r | r. name( ) == "no-null" && r . severity == AllowWarnDeny :: Deny )
889+ . any( |( r , severity ) | r. name( ) == "no-null" && * severity == AllowWarnDeny :: Deny )
895890 ) ;
896891 }
897892
0 commit comments