perf(linter): reduce branches-sharing-code scratch allocations (#28483)

Get rid of 1 Vec that was just used for scratch, and use smallvec for
the other Vec.

On local fixtures:

Allocations: 24,658 → 346 (−98.6%)
Allocated bytes: 797,698 → 18,466 (−97.7%)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
Cam McHenryandCopilot authored and GitHub committed 2026-10-30 12:26:35 -04:00
1 parent c0065fd567
commit 7c93eef0bc
1 file changed
+14 -22
@@ -1,7 +1,7 @@
// Inspired by https://github.com/rust-lang/rust-clippy/blob/95f5a00d8628fba223c802251af3c42547927c5a/clippy_lints/src/ifs/branches_sharing_code.rs
use oxc_ast::{
AstKind,
ast::{Expression, IdentifierReference, IfStatement, Statement},
ast::{IdentifierReference, IfStatement, Statement},
};
use oxc_ast_visit::Visit;
use oxc_diagnostics::OxcDiagnostic;
@@ -10,6 +10,7 @@ use oxc_macros::declare_oxc_lint;
use oxc_semantic::{ReferenceId, SymbolId};
use oxc_span::{ContentEq, GetSpan, Span};
use rustc_hash::FxHashSet;
use smallvec::SmallVec;
use crate::{AstNode, ast_util::get_preceding_indent_str, context::LintContext, rule::Rule};
@@ -111,11 +112,9 @@ impl Rule for BranchesSharingCode {
return;
}
let (conditions, bodies) = extract_if_sequence(if_stmt);
if bodies.len() < 2 || bodies.len() == conditions.len() {
let Some(bodies) = extract_if_sequence(if_stmt) else {
return;
}
};
let (start_eq, end_eq) = scan_blocks_for_eq(&bodies);
@@ -341,30 +340,23 @@ fn scan_blocks_for_eq<'a>(bodies: &[&'a Statement<'a>]) -> (Option<usize>, Optio
fn extract_if_sequence<'a>(
if_stmt: &'a IfStatement<'a>,
) -> (Vec<&'a Expression<'a>>, Vec<&'a Statement<'a>>) {
let mut conditions = Vec::new();
let mut bodies = Vec::new();
) -> Option<SmallVec<[&'a Statement<'a>; 2]>> {
let mut bodies = SmallVec::new();
let mut current_if = Some(if_stmt);
while let Some(if_node) = current_if {
conditions.push(&if_node.test);
bodies.push(&if_node.consequent);
let mut current_if = if_stmt;
loop {
bodies.push(&current_if.consequent);
match &if_node.alternate {
Some(Statement::IfStatement(else_if)) => {
current_if = Some(else_if);
match current_if.alternate.as_ref()? {
Statement::IfStatement(else_if) => {
current_if = else_if;
}
Some(else_stmt) => {
else_stmt => {
bodies.push(else_stmt);
current_if = None;
}
None => {
current_if = None;
return Some(bodies);
}
}
}
(conditions, bodies)
}
#[test]