Skip to content

Commit b93e2d5

Browse files
committed
perf(linter): run next/no-duplicate-head on nodes instead of symbols
1 parent f54d7d4 commit b93e2d5

File tree

2 files changed

+22
-15
lines changed

2 files changed

+22
-15
lines changed

crates/oxc_linter/src/generated/rule_runner_impls.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1714,8 +1714,9 @@ impl RuleRunner for crate::rules::nextjs::no_document_import_in_page::NoDocument
17141714
}
17151715

17161716
impl RuleRunner for crate::rules::nextjs::no_duplicate_head::NoDuplicateHead {
1717-
const NODE_TYPES: Option<&AstTypesBitset> = None;
1718-
const RUN_FUNCTIONS: RuleRunFunctionsImplemented = RuleRunFunctionsImplemented::RunOnSymbol;
1717+
const NODE_TYPES: Option<&AstTypesBitset> =
1718+
Some(&AstTypesBitset::from_types(&[AstType::ImportDeclaration]));
1719+
const RUN_FUNCTIONS: RuleRunFunctionsImplemented = RuleRunFunctionsImplemented::Run;
17191720
}
17201721

17211722
impl RuleRunner for crate::rules::nextjs::no_head_element::NoHeadElement {

crates/oxc_linter/src/rules/nextjs/no_duplicate_head.rs

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use oxc_ast::AstKind;
22
use oxc_diagnostics::{LabeledSpan, OxcDiagnostic};
33
use oxc_macros::declare_oxc_lint;
4+
use oxc_semantic::AstNode;
45
use oxc_span::GetSpan;
56

67
use crate::{context::LintContext, rule::Rule};
@@ -72,20 +73,27 @@ declare_oxc_lint!(
7273
);
7374

7475
impl Rule for NoDuplicateHead {
75-
fn run_on_symbol(&self, symbol_id: oxc_semantic::SymbolId, ctx: &LintContext<'_>) {
76-
let symbols = ctx.scoping();
77-
let name = symbols.symbol_name(symbol_id);
78-
if name != "Head" {
76+
fn run<'a>(&self, node: &AstNode<'a>, ctx: &LintContext<'a>) {
77+
let AstKind::ImportDeclaration(import_decl) = node.kind() else {
7978
return;
80-
}
79+
};
80+
let Some(specifiers) = &import_decl.specifiers else {
81+
return;
82+
};
83+
let Some(head_specifier) = specifiers.iter().find(|s| s.name() == "Head") else {
84+
return;
85+
};
86+
87+
let scoping = ctx.scoping();
88+
let symbol_id = head_specifier.local().symbol_id();
8189

82-
let flags = symbols.symbol_flags(symbol_id);
90+
let flags = scoping.symbol_flags(symbol_id);
8391
if !flags.is_import() {
8492
return;
8593
}
8694

87-
let scope_id = symbols.symbol_scope_id(symbol_id);
88-
if scope_id != ctx.scoping().root_scope_id() {
95+
let scope_id = scoping.symbol_scope_id(symbol_id);
96+
if scope_id != scoping.root_scope_id() {
8997
return;
9098
}
9199

@@ -100,7 +108,7 @@ impl Rule for NoDuplicateHead {
100108
LabeledSpan::underline(span)
101109
};
102110

103-
for reference in symbols.get_resolved_references(symbol_id) {
111+
for reference in scoping.get_resolved_references(symbol_id) {
104112
if !reference.is_read() {
105113
continue;
106114
}
@@ -125,11 +133,9 @@ impl Rule for NoDuplicateHead {
125133
}
126134

127135
// `labels` is empty if 0 or 1 `<Head>` found
128-
if labels.is_empty() {
129-
return;
136+
if !labels.is_empty() {
137+
ctx.diagnostic(no_duplicate_head(labels));
130138
}
131-
132-
ctx.diagnostic(no_duplicate_head(labels));
133139
}
134140
}
135141

0 commit comments

Comments
 (0)