Skip to content

Commit 3364640

Browse files
feat(lint): add rule useAtIndex (#4120)
Co-authored-by: Victorien Elvinger <[email protected]>
1 parent d2273a6 commit 3364640

File tree

12 files changed

+2815
-22
lines changed

12 files changed

+2815
-22
lines changed

crates/biome_cli/src/execute/migrate/eslint_any_rule_to_biome.rs

Lines changed: 12 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/biome_configuration/src/analyzer/linter/rules.rs

Lines changed: 41 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -3377,6 +3377,9 @@ pub struct Nursery {
33773377
#[serde(skip_serializing_if = "Option::is_none")]
33783378
pub use_aria_props_supported_by_role:
33793379
Option<RuleConfiguration<biome_js_analyze::options::UseAriaPropsSupportedByRole>>,
3380+
#[doc = "Use at() instead of integer index access."]
3381+
#[serde(skip_serializing_if = "Option::is_none")]
3382+
pub use_at_index: Option<RuleFixConfiguration<biome_js_analyze::options::UseAtIndex>>,
33803383
#[doc = "Enforce declaring components only within modules that export React Components exclusively."]
33813384
#[serde(skip_serializing_if = "Option::is_none")]
33823385
pub use_component_export_only_modules:
@@ -3463,6 +3466,7 @@ impl Nursery {
34633466
"noValueAtRule",
34643467
"useAdjacentOverloadSignatures",
34653468
"useAriaPropsSupportedByRole",
3469+
"useAtIndex",
34663470
"useComponentExportOnlyModules",
34673471
"useConsistentCurlyBraces",
34683472
"useConsistentMemberAccessibility",
@@ -3500,9 +3504,9 @@ impl Nursery {
35003504
RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[24]),
35013505
RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[25]),
35023506
RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[28]),
3503-
RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[31]),
35043507
RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[32]),
3505-
RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[36]),
3508+
RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[33]),
3509+
RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[37]),
35063510
];
35073511
const ALL_RULES_AS_FILTERS: &'static [RuleFilter<'static>] = &[
35083512
RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[0]),
@@ -3544,6 +3548,7 @@ impl Nursery {
35443548
RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[36]),
35453549
RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[37]),
35463550
RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[38]),
3551+
RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[39]),
35473552
];
35483553
#[doc = r" Retrieves the recommended rules"]
35493554
pub(crate) fn is_recommended_true(&self) -> bool {
@@ -3705,56 +3710,61 @@ impl Nursery {
37053710
index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[28]));
37063711
}
37073712
}
3708-
if let Some(rule) = self.use_component_export_only_modules.as_ref() {
3713+
if let Some(rule) = self.use_at_index.as_ref() {
37093714
if rule.is_enabled() {
37103715
index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[29]));
37113716
}
37123717
}
3713-
if let Some(rule) = self.use_consistent_curly_braces.as_ref() {
3718+
if let Some(rule) = self.use_component_export_only_modules.as_ref() {
37143719
if rule.is_enabled() {
37153720
index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[30]));
37163721
}
37173722
}
3718-
if let Some(rule) = self.use_consistent_member_accessibility.as_ref() {
3723+
if let Some(rule) = self.use_consistent_curly_braces.as_ref() {
37193724
if rule.is_enabled() {
37203725
index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[31]));
37213726
}
37223727
}
3723-
if let Some(rule) = self.use_deprecated_reason.as_ref() {
3728+
if let Some(rule) = self.use_consistent_member_accessibility.as_ref() {
37243729
if rule.is_enabled() {
37253730
index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[32]));
37263731
}
37273732
}
3728-
if let Some(rule) = self.use_explicit_function_return_type.as_ref() {
3733+
if let Some(rule) = self.use_deprecated_reason.as_ref() {
37293734
if rule.is_enabled() {
37303735
index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[33]));
37313736
}
37323737
}
3733-
if let Some(rule) = self.use_import_restrictions.as_ref() {
3738+
if let Some(rule) = self.use_explicit_function_return_type.as_ref() {
37343739
if rule.is_enabled() {
37353740
index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[34]));
37363741
}
37373742
}
3738-
if let Some(rule) = self.use_sorted_classes.as_ref() {
3743+
if let Some(rule) = self.use_import_restrictions.as_ref() {
37393744
if rule.is_enabled() {
37403745
index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[35]));
37413746
}
37423747
}
3743-
if let Some(rule) = self.use_strict_mode.as_ref() {
3748+
if let Some(rule) = self.use_sorted_classes.as_ref() {
37443749
if rule.is_enabled() {
37453750
index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[36]));
37463751
}
37473752
}
3748-
if let Some(rule) = self.use_trim_start_end.as_ref() {
3753+
if let Some(rule) = self.use_strict_mode.as_ref() {
37493754
if rule.is_enabled() {
37503755
index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[37]));
37513756
}
37523757
}
3753-
if let Some(rule) = self.use_valid_autocomplete.as_ref() {
3758+
if let Some(rule) = self.use_trim_start_end.as_ref() {
37543759
if rule.is_enabled() {
37553760
index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[38]));
37563761
}
37573762
}
3763+
if let Some(rule) = self.use_valid_autocomplete.as_ref() {
3764+
if rule.is_enabled() {
3765+
index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[39]));
3766+
}
3767+
}
37583768
index_set
37593769
}
37603770
pub(crate) fn get_disabled_rules(&self) -> FxHashSet<RuleFilter<'static>> {
@@ -3904,56 +3914,61 @@ impl Nursery {
39043914
index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[28]));
39053915
}
39063916
}
3907-
if let Some(rule) = self.use_component_export_only_modules.as_ref() {
3917+
if let Some(rule) = self.use_at_index.as_ref() {
39083918
if rule.is_disabled() {
39093919
index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[29]));
39103920
}
39113921
}
3912-
if let Some(rule) = self.use_consistent_curly_braces.as_ref() {
3922+
if let Some(rule) = self.use_component_export_only_modules.as_ref() {
39133923
if rule.is_disabled() {
39143924
index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[30]));
39153925
}
39163926
}
3917-
if let Some(rule) = self.use_consistent_member_accessibility.as_ref() {
3927+
if let Some(rule) = self.use_consistent_curly_braces.as_ref() {
39183928
if rule.is_disabled() {
39193929
index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[31]));
39203930
}
39213931
}
3922-
if let Some(rule) = self.use_deprecated_reason.as_ref() {
3932+
if let Some(rule) = self.use_consistent_member_accessibility.as_ref() {
39233933
if rule.is_disabled() {
39243934
index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[32]));
39253935
}
39263936
}
3927-
if let Some(rule) = self.use_explicit_function_return_type.as_ref() {
3937+
if let Some(rule) = self.use_deprecated_reason.as_ref() {
39283938
if rule.is_disabled() {
39293939
index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[33]));
39303940
}
39313941
}
3932-
if let Some(rule) = self.use_import_restrictions.as_ref() {
3942+
if let Some(rule) = self.use_explicit_function_return_type.as_ref() {
39333943
if rule.is_disabled() {
39343944
index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[34]));
39353945
}
39363946
}
3937-
if let Some(rule) = self.use_sorted_classes.as_ref() {
3947+
if let Some(rule) = self.use_import_restrictions.as_ref() {
39383948
if rule.is_disabled() {
39393949
index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[35]));
39403950
}
39413951
}
3942-
if let Some(rule) = self.use_strict_mode.as_ref() {
3952+
if let Some(rule) = self.use_sorted_classes.as_ref() {
39433953
if rule.is_disabled() {
39443954
index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[36]));
39453955
}
39463956
}
3947-
if let Some(rule) = self.use_trim_start_end.as_ref() {
3957+
if let Some(rule) = self.use_strict_mode.as_ref() {
39483958
if rule.is_disabled() {
39493959
index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[37]));
39503960
}
39513961
}
3952-
if let Some(rule) = self.use_valid_autocomplete.as_ref() {
3962+
if let Some(rule) = self.use_trim_start_end.as_ref() {
39533963
if rule.is_disabled() {
39543964
index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[38]));
39553965
}
39563966
}
3967+
if let Some(rule) = self.use_valid_autocomplete.as_ref() {
3968+
if rule.is_disabled() {
3969+
index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[39]));
3970+
}
3971+
}
39573972
index_set
39583973
}
39593974
#[doc = r" Checks if, given a rule name, matches one of the rules contained in this category"]
@@ -4106,6 +4121,10 @@ impl Nursery {
41064121
.use_aria_props_supported_by_role
41074122
.as_ref()
41084123
.map(|conf| (conf.level(), conf.get_options())),
4124+
"useAtIndex" => self
4125+
.use_at_index
4126+
.as_ref()
4127+
.map(|conf| (conf.level(), conf.get_options())),
41094128
"useComponentExportOnlyModules" => self
41104129
.use_component_export_only_modules
41114130
.as_ref()

crates/biome_diagnostics_categories/src/categories.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,7 @@ define_categories! {
182182
"lint/nursery/noValueAtRule": "https://biomejs.dev/linter/rules/no-value-at-rule",
183183
"lint/nursery/useAdjacentOverloadSignatures": "https://biomejs.dev/linter/rules/use-adjacent-overload-signatures",
184184
"lint/nursery/useAriaPropsSupportedByRole": "https://biomejs.dev/linter/rules/use-aria-props-supported-by-role",
185+
"lint/nursery/useAtIndex": "https://biomejs.dev/linter/rules/use-at-index",
185186
"lint/nursery/useBiomeSuppressionComment": "https://biomejs.dev/linter/rules/use-biome-suppression-comment",
186187
"lint/nursery/useComponentExportOnlyModules": "https://biomejs.dev/linter/rules/use-components-only-module",
187188
"lint/nursery/useConsistentCurlyBraces": "https://biomejs.dev/linter/rules/use-consistent-curly-braces",

crates/biome_js_analyze/src/lint/nursery.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ pub mod no_template_curly_in_string;
2323
pub mod no_useless_escape_in_regex;
2424
pub mod use_adjacent_overload_signatures;
2525
pub mod use_aria_props_supported_by_role;
26+
pub mod use_at_index;
2627
pub mod use_component_export_only_modules;
2728
pub mod use_consistent_curly_braces;
2829
pub mod use_consistent_member_accessibility;
@@ -58,6 +59,7 @@ declare_lint_group! {
5859
self :: no_useless_escape_in_regex :: NoUselessEscapeInRegex ,
5960
self :: use_adjacent_overload_signatures :: UseAdjacentOverloadSignatures ,
6061
self :: use_aria_props_supported_by_role :: UseAriaPropsSupportedByRole ,
62+
self :: use_at_index :: UseAtIndex ,
6163
self :: use_component_export_only_modules :: UseComponentExportOnlyModules ,
6264
self :: use_consistent_curly_braces :: UseConsistentCurlyBraces ,
6365
self :: use_consistent_member_accessibility :: UseConsistentMemberAccessibility ,

0 commit comments

Comments
 (0)