Skip to content

Commit aec0c08

Browse files
committed
perf(linter): allow analyzing node types in match blocks with guards (#14459)
Previously, we skipped guard conditions to be extra cautious. After thinking about it and using the runtime optimizations in practice, I think that we can allow patterns with guards, and we just assume that it may always be taken. So this should result in the largest set of AST kinds possible for a rule and will not narrow it down dynamically.
1 parent 9044187 commit aec0c08

File tree

2 files changed

+91
-25
lines changed

2 files changed

+91
-25
lines changed

crates/oxc_linter/src/generated/rule_runner_impls.rs

Lines changed: 89 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,8 @@ impl RuleRunner for crate::rules::eslint::default_case_last::DefaultCaseLast {
5555
}
5656

5757
impl RuleRunner for crate::rules::eslint::default_param_last::DefaultParamLast {
58-
const NODE_TYPES: Option<&AstTypesBitset> = None;
58+
const NODE_TYPES: Option<&AstTypesBitset> =
59+
Some(&AstTypesBitset::from_types(&[AstType::ArrowFunctionExpression, AstType::Function]));
5960
const RUN_FUNCTIONS: RuleRunFunctionsImplemented = RuleRunFunctionsImplemented::Run;
6061
}
6162

@@ -83,12 +84,18 @@ impl RuleRunner for crate::rules::eslint::func_style::FuncStyle {
8384
}
8485

8586
impl RuleRunner for crate::rules::eslint::getter_return::GetterReturn {
86-
const NODE_TYPES: Option<&AstTypesBitset> = None;
87+
const NODE_TYPES: Option<&AstTypesBitset> =
88+
Some(&AstTypesBitset::from_types(&[AstType::ArrowFunctionExpression, AstType::Function]));
8789
const RUN_FUNCTIONS: RuleRunFunctionsImplemented = RuleRunFunctionsImplemented::Run;
8890
}
8991

9092
impl RuleRunner for crate::rules::eslint::grouped_accessor_pairs::GroupedAccessorPairs {
91-
const NODE_TYPES: Option<&AstTypesBitset> = None;
93+
const NODE_TYPES: Option<&AstTypesBitset> = Some(&AstTypesBitset::from_types(&[
94+
AstType::ClassBody,
95+
AstType::ObjectExpression,
96+
AstType::TSInterfaceBody,
97+
AstType::TSTypeLiteral,
98+
]));
9299
const RUN_FUNCTIONS: RuleRunFunctionsImplemented = RuleRunFunctionsImplemented::Run;
93100
}
94101

@@ -204,7 +211,14 @@ impl RuleRunner for crate::rules::eslint::no_compare_neg_zero::NoCompareNegZero
204211
}
205212

206213
impl RuleRunner for crate::rules::eslint::no_cond_assign::NoCondAssign {
207-
const NODE_TYPES: Option<&AstTypesBitset> = None;
214+
const NODE_TYPES: Option<&AstTypesBitset> = Some(&AstTypesBitset::from_types(&[
215+
AstType::AssignmentExpression,
216+
AstType::ConditionalExpression,
217+
AstType::DoWhileStatement,
218+
AstType::ForStatement,
219+
AstType::IfStatement,
220+
AstType::WhileStatement,
221+
]));
208222
const RUN_FUNCTIONS: RuleRunFunctionsImplemented = RuleRunFunctionsImplemented::Run;
209223
}
210224

@@ -306,7 +320,8 @@ impl RuleRunner for crate::rules::eslint::no_else_return::NoElseReturn {
306320
}
307321

308322
impl RuleRunner for crate::rules::eslint::no_empty::NoEmpty {
309-
const NODE_TYPES: Option<&AstTypesBitset> = None;
323+
const NODE_TYPES: Option<&AstTypesBitset> =
324+
Some(&AstTypesBitset::from_types(&[AstType::BlockStatement, AstType::SwitchStatement]));
310325
const RUN_FUNCTIONS: RuleRunFunctionsImplemented = RuleRunFunctionsImplemented::Run;
311326
}
312327

@@ -341,7 +356,11 @@ impl RuleRunner for crate::rules::eslint::no_eq_null::NoEqNull {
341356
}
342357

343358
impl RuleRunner for crate::rules::eslint::no_eval::NoEval {
344-
const NODE_TYPES: Option<&AstTypesBitset> = None;
359+
const NODE_TYPES: Option<&AstTypesBitset> = Some(&AstTypesBitset::from_types(&[
360+
AstType::CallExpression,
361+
AstType::Program,
362+
AstType::ThisExpression,
363+
]));
345364
const RUN_FUNCTIONS: RuleRunFunctionsImplemented = RuleRunFunctionsImplemented::Run;
346365
}
347366

@@ -363,7 +382,8 @@ impl RuleRunner for crate::rules::eslint::no_extra_bind::NoExtraBind {
363382
}
364383

365384
impl RuleRunner for crate::rules::eslint::no_extra_boolean_cast::NoExtraBooleanCast {
366-
const NODE_TYPES: Option<&AstTypesBitset> = None;
385+
const NODE_TYPES: Option<&AstTypesBitset> =
386+
Some(&AstTypesBitset::from_types(&[AstType::CallExpression, AstType::UnaryExpression]));
367387
const RUN_FUNCTIONS: RuleRunFunctionsImplemented = RuleRunFunctionsImplemented::Run;
368388
}
369389

@@ -441,7 +461,8 @@ impl RuleRunner for crate::rules::eslint::no_lonely_if::NoLonelyIf {
441461
}
442462

443463
impl RuleRunner for crate::rules::eslint::no_loss_of_precision::NoLossOfPrecision {
444-
const NODE_TYPES: Option<&AstTypesBitset> = None;
464+
const NODE_TYPES: Option<&AstTypesBitset> =
465+
Some(&AstTypesBitset::from_types(&[AstType::NumericLiteral]));
445466
const RUN_FUNCTIONS: RuleRunFunctionsImplemented = RuleRunFunctionsImplemented::Run;
446467
}
447468

@@ -552,7 +573,11 @@ impl RuleRunner for crate::rules::eslint::no_redeclare::NoRedeclare {
552573
}
553574

554575
impl RuleRunner for crate::rules::eslint::no_regex_spaces::NoRegexSpaces {
555-
const NODE_TYPES: Option<&AstTypesBitset> = None;
576+
const NODE_TYPES: Option<&AstTypesBitset> = Some(&AstTypesBitset::from_types(&[
577+
AstType::CallExpression,
578+
AstType::NewExpression,
579+
AstType::RegExpLiteral,
580+
]));
556581
const RUN_FUNCTIONS: RuleRunFunctionsImplemented = RuleRunFunctionsImplemented::Run;
557582
}
558583

@@ -575,7 +600,8 @@ impl RuleRunner for crate::rules::eslint::no_return_assign::NoReturnAssign {
575600
}
576601

577602
impl RuleRunner for crate::rules::eslint::no_script_url::NoScriptUrl {
578-
const NODE_TYPES: Option<&AstTypesBitset> = None;
603+
const NODE_TYPES: Option<&AstTypesBitset> =
604+
Some(&AstTypesBitset::from_types(&[AstType::StringLiteral, AstType::TemplateLiteral]));
579605
const RUN_FUNCTIONS: RuleRunFunctionsImplemented = RuleRunFunctionsImplemented::Run;
580606
}
581607

@@ -683,7 +709,25 @@ impl RuleRunner for crate::rules::eslint::no_unsafe_negation::NoUnsafeNegation {
683709
}
684710

685711
impl RuleRunner for crate::rules::eslint::no_unsafe_optional_chaining::NoUnsafeOptionalChaining {
686-
const NODE_TYPES: Option<&AstTypesBitset> = None;
712+
const NODE_TYPES: Option<&AstTypesBitset> = Some(&AstTypesBitset::from_types(&[
713+
AstType::Argument,
714+
AstType::ArrayExpression,
715+
AstType::AssignmentExpression,
716+
AstType::AssignmentPattern,
717+
AstType::AssignmentTargetWithDefault,
718+
AstType::BinaryExpression,
719+
AstType::CallExpression,
720+
AstType::Class,
721+
AstType::ComputedMemberExpression,
722+
AstType::ForOfStatement,
723+
AstType::NewExpression,
724+
AstType::PrivateFieldExpression,
725+
AstType::StaticMemberExpression,
726+
AstType::TaggedTemplateExpression,
727+
AstType::UnaryExpression,
728+
AstType::VariableDeclarator,
729+
AstType::WithStatement,
730+
]));
687731
const RUN_FUNCTIONS: RuleRunFunctionsImplemented = RuleRunFunctionsImplemented::Run;
688732
}
689733

@@ -728,7 +772,12 @@ impl RuleRunner for crate::rules::eslint::no_useless_catch::NoUselessCatch {
728772
}
729773

730774
impl RuleRunner for crate::rules::eslint::no_useless_computed_key::NoUselessComputedKey {
731-
const NODE_TYPES: Option<&AstTypesBitset> = None;
775+
const NODE_TYPES: Option<&AstTypesBitset> = Some(&AstTypesBitset::from_types(&[
776+
AstType::BindingProperty,
777+
AstType::MethodDefinition,
778+
AstType::ObjectProperty,
779+
AstType::PropertyDefinition,
780+
]));
732781
const RUN_FUNCTIONS: RuleRunFunctionsImplemented = RuleRunFunctionsImplemented::Run;
733782
}
734783

@@ -745,7 +794,11 @@ impl RuleRunner for crate::rules::eslint::no_useless_constructor::NoUselessConst
745794
}
746795

747796
impl RuleRunner for crate::rules::eslint::no_useless_escape::NoUselessEscape {
748-
const NODE_TYPES: Option<&AstTypesBitset> = None;
797+
const NODE_TYPES: Option<&AstTypesBitset> = Some(&AstTypesBitset::from_types(&[
798+
AstType::RegExpLiteral,
799+
AstType::StringLiteral,
800+
AstType::TemplateLiteral,
801+
]));
749802
const RUN_FUNCTIONS: RuleRunFunctionsImplemented = RuleRunFunctionsImplemented::Run;
750803
}
751804

@@ -784,7 +837,10 @@ impl RuleRunner for crate::rules::eslint::operator_assignment::OperatorAssignmen
784837
}
785838

786839
impl RuleRunner for crate::rules::eslint::prefer_destructuring::PreferDestructuring {
787-
const NODE_TYPES: Option<&AstTypesBitset> = None;
840+
const NODE_TYPES: Option<&AstTypesBitset> = Some(&AstTypesBitset::from_types(&[
841+
AstType::AssignmentExpression,
842+
AstType::VariableDeclarator,
843+
]));
788844
const RUN_FUNCTIONS: RuleRunFunctionsImplemented = RuleRunFunctionsImplemented::Run;
789845
}
790846

@@ -966,7 +1022,8 @@ impl RuleRunner for crate::rules::import::namespace::Namespace {
9661022
}
9671023

9681024
impl RuleRunner for crate::rules::import::no_absolute_path::NoAbsolutePath {
969-
const NODE_TYPES: Option<&AstTypesBitset> = None;
1025+
const NODE_TYPES: Option<&AstTypesBitset> =
1026+
Some(&AstTypesBitset::from_types(&[AstType::CallExpression, AstType::ImportDeclaration]));
9701027
const RUN_FUNCTIONS: RuleRunFunctionsImplemented = RuleRunFunctionsImplemented::Run;
9711028
}
9721029

@@ -2033,7 +2090,8 @@ impl RuleRunner for crate::rules::react::jsx_filename_extension::JsxFilenameExte
20332090
}
20342091

20352092
impl RuleRunner for crate::rules::react::jsx_fragments::JsxFragments {
2036-
const NODE_TYPES: Option<&AstTypesBitset> = None;
2093+
const NODE_TYPES: Option<&AstTypesBitset> =
2094+
Some(&AstTypesBitset::from_types(&[AstType::JSXElement, AstType::JSXFragment]));
20372095
const RUN_FUNCTIONS: RuleRunFunctionsImplemented = RuleRunFunctionsImplemented::Run;
20382096
}
20392097

@@ -2300,7 +2358,11 @@ impl RuleRunner
23002358
impl RuleRunner
23012359
for crate::rules::typescript::consistent_type_definitions::ConsistentTypeDefinitions
23022360
{
2303-
const NODE_TYPES: Option<&AstTypesBitset> = None;
2361+
const NODE_TYPES: Option<&AstTypesBitset> = Some(&AstTypesBitset::from_types(&[
2362+
AstType::ExportDefaultDeclaration,
2363+
AstType::TSInterfaceDeclaration,
2364+
AstType::TSTypeAliasDeclaration,
2365+
]));
23042366
const RUN_FUNCTIONS: RuleRunFunctionsImplemented = RuleRunFunctionsImplemented::Run;
23052367
}
23062368

@@ -2341,7 +2403,10 @@ impl RuleRunner for crate::rules::typescript::no_base_to_string::NoBaseToString
23412403
impl RuleRunner
23422404
for crate::rules::typescript::no_confusing_non_null_assertion::NoConfusingNonNullAssertion
23432405
{
2344-
const NODE_TYPES: Option<&AstTypesBitset> = None;
2406+
const NODE_TYPES: Option<&AstTypesBitset> = Some(&AstTypesBitset::from_types(&[
2407+
AstType::AssignmentExpression,
2408+
AstType::BinaryExpression,
2409+
]));
23452410
const RUN_FUNCTIONS: RuleRunFunctionsImplemented = RuleRunFunctionsImplemented::Run;
23462411
}
23472412

@@ -2378,7 +2443,10 @@ impl RuleRunner for crate::rules::typescript::no_empty_interface::NoEmptyInterfa
23782443
}
23792444

23802445
impl RuleRunner for crate::rules::typescript::no_empty_object_type::NoEmptyObjectType {
2381-
const NODE_TYPES: Option<&AstTypesBitset> = None;
2446+
const NODE_TYPES: Option<&AstTypesBitset> = Some(&AstTypesBitset::from_types(&[
2447+
AstType::TSInterfaceDeclaration,
2448+
AstType::TSTypeLiteral,
2449+
]));
23822450
const RUN_FUNCTIONS: RuleRunFunctionsImplemented = RuleRunFunctionsImplemented::Run;
23832451
}
23842452

@@ -3134,7 +3202,8 @@ impl RuleRunner for crate::rules::unicorn::no_useless_switch_case::NoUselessSwit
31343202
}
31353203

31363204
impl RuleRunner for crate::rules::unicorn::no_useless_undefined::NoUselessUndefined {
3137-
const NODE_TYPES: Option<&AstTypesBitset> = None;
3205+
const NODE_TYPES: Option<&AstTypesBitset> =
3206+
Some(&AstTypesBitset::from_types(&[AstType::CallExpression, AstType::IdentifierReference]));
31383207
const RUN_FUNCTIONS: RuleRunFunctionsImplemented = RuleRunFunctionsImplemented::Run;
31393208
}
31403209

tasks/linter_codegen/src/match_detector.rs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -52,15 +52,12 @@ impl MatchDetector {
5252
}
5353

5454
fn extract_variants_from_match_arm(&mut self, arm: &Arm) -> CollectionResult {
55-
// If there are any guards, we can't be 100% sure which variants this runs on, as it may
56-
// run on any node type depending on the guard condition.
57-
if arm.guard.is_some() {
58-
return CollectionResult::Incomplete;
59-
}
6055
let pat = &arm.pat;
6156
match pat {
6257
Pat::TupleStruct(ts) => {
6358
if let Some(variant) = astkind_variant_from_path(&ts.path) {
59+
// NOTE: If there is a guard, we assume that it may or may not be taken and collect all AST kinds
60+
// regardless of the guard condition.
6461
self.node_types.insert(variant);
6562
CollectionResult::Complete
6663
} else {

0 commit comments

Comments
 (0)