Skip to content

Commit 4fe2c46

Browse files
committed
wip: skip rules that do not have any relevant node types
1 parent 3c48f3c commit 4fe2c46

File tree

12 files changed

+4312
-30
lines changed

12 files changed

+4312
-30
lines changed

Cargo.lock

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

crates/oxc_linter/src/lib.rs

Lines changed: 33 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
use std::{path::Path, rc::Rc, sync::Arc};
55

66
use oxc_allocator::Allocator;
7+
use oxc_ast::ast_kind::AST_TYPE_MAX;
78
use oxc_semantic::{AstNode, Semantic};
89

910
#[cfg(all(feature = "oxlint2", not(feature = "disable_oxlint2")))]
@@ -25,6 +26,7 @@ mod module_graph_visitor;
2526
mod module_record;
2627
mod options;
2728
mod rule;
29+
mod rule_runner_impls;
2830
mod service;
2931
mod tsgolint;
3032
mod utils;
@@ -56,7 +58,7 @@ pub use crate::{
5658
module_record::ModuleRecord,
5759
options::LintOptions,
5860
options::{AllowWarnDeny, InvalidFilterKind, LintFilter, LintFilterKind},
59-
rule::{RuleCategory, RuleFixMeta, RuleMeta},
61+
rule::{RuleCategory, RuleFixMeta, RuleMeta, RuleRunner},
6062
service::{LintService, LintServiceOptions, RuntimeFileSystem},
6163
tsgolint::TsGoLintState,
6264
utils::{read_to_arena_str, read_to_string},
@@ -145,6 +147,9 @@ impl Linter {
145147
let should_run_on_jest_node =
146148
ctx_host.plugins().has_test() && ctx_host.frameworks().is_test();
147149

150+
// Collect rules into a Vec so that we can iterate over the rules multiple times
151+
let rules = rules.collect::<Vec<_>>();
152+
148153
// IMPORTANT: We have two branches here for performance reasons:
149154
//
150155
// 1) Branch where we iterate over each node, then each rule
@@ -164,9 +169,6 @@ impl Linter {
164169
//
165170
// See https://github.com/oxc-project/oxc/pull/6600 for more context.
166171
if semantic.nodes().len() > 200_000 {
167-
// Collect rules into a Vec so that we can iterate over the rules multiple times
168-
let rules = rules.collect::<Vec<_>>();
169-
170172
for (rule, ctx) in &rules {
171173
rule.run_once(ctx);
172174
}
@@ -191,23 +193,45 @@ impl Linter {
191193
}
192194
}
193195
} else {
194-
for (rule, ref ctx) in rules {
196+
let mut rules_by_ast_type = vec![Vec::new(); AST_TYPE_MAX as usize + 1];
197+
let mut rules_any_ast_type = vec![];
198+
199+
for (rule, ctx) in rules.iter() {
200+
if rule.should_run(&ctx_host) {
201+
let (ast_types, all_types) = rule.types_info();
202+
if all_types {
203+
rules_any_ast_type.push((rule, ctx));
204+
} else {
205+
for ty in ast_types {
206+
rules_by_ast_type[ty as usize].push((rule, ctx));
207+
}
208+
}
209+
}
210+
}
211+
212+
for (rule, ctx) in rules.iter() {
195213
rule.run_once(ctx);
196214

197215
for symbol in semantic.scoping().symbol_ids() {
198216
rule.run_on_symbol(symbol, ctx);
199217
}
200218

201-
for node in semantic.nodes() {
202-
rule.run(node, ctx);
203-
}
204-
205219
if should_run_on_jest_node {
206220
for jest_node in iter_possible_jest_call_node(semantic) {
207221
rule.run_on_jest_node(&jest_node, ctx);
208222
}
209223
}
210224
}
225+
226+
// Run rules on nodes
227+
for node in semantic.nodes() {
228+
for (rule, ctx) in &rules_by_ast_type[node.kind().ty() as usize] {
229+
rule.run(node, ctx);
230+
}
231+
for (rule, ctx) in &rules_any_ast_type {
232+
rule.run(node, ctx);
233+
}
234+
}
211235
}
212236

213237
#[cfg(all(feature = "oxlint2", not(feature = "disable_oxlint2")))]

crates/oxc_linter/src/rule.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use std::{fmt, hash::Hash};
55
use schemars::{JsonSchema, SchemaGenerator, schema::Schema};
66
use serde::{Deserialize, Serialize};
77

8-
use oxc_semantic::SymbolId;
8+
use oxc_semantic::{AstTypesBitset, SymbolId};
99

1010
use crate::{
1111
AstNode, FixKind,
@@ -66,6 +66,16 @@ pub trait Rule: Sized + Default + fmt::Debug {
6666
}
6767
}
6868

69+
pub trait RuleRunner: Rule {
70+
/// `AstType`s that rule acts on
71+
const NODE_TYPES: &AstTypesBitset;
72+
/// `true` if codegen can't figure out what node types rule acts on
73+
const ANY_NODE_TYPE: bool;
74+
75+
fn types_info(&self) -> (&'static AstTypesBitset, bool) {
76+
(Self::NODE_TYPES, Self::ANY_NODE_TYPE)
77+
}
78+
}
6979
pub trait RuleMeta {
7080
const NAME: &'static str;
7181

0 commit comments

Comments
 (0)