Skip to content

Commit

Permalink
perf(linter): get fewer parent nodes in `unicorn/prefer-dom-node-text…
Browse files Browse the repository at this point in the history
…-content` (#6467)

Profiling showed that this rule was one of the slower ones, partially due to the fact that it was constantly calling `ctx.nodes()` and `ctx.nodes().parent_node()`. I've tried to fix this by reordering the logic so that we only fetch the parent nodes right before we need it. If we can early return, such as the identifier name not being `innerText`, or the node kind not being right, then we can skip fetching the parent.

Before:

<img width="1147" alt="Screenshot 2024-10-12 at 3 05 05 AM" src="https://github.com/user-attachments/assets/4a551b04-370f-4ed9-b0d5-99d58b03235b">

After (-0.4% reduction in number of samples spent in this rule):

<img width="1146" alt="image" src="https://github.com/user-attachments/assets/340edc36-55cc-4bf4-aa8e-9a600848b798">
  • Loading branch information
camchenry committed Oct 13, 2024
1 parent 6d041fb commit 725f9f6
Showing 1 changed file with 51 additions and 41 deletions.
92 changes: 51 additions & 41 deletions crates/oxc_linter/src/rules/unicorn/prefer_dom_node_text_content.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,58 +44,68 @@ declare_oxc_lint!(

impl Rule for PreferDomNodeTextContent {
fn run<'a>(&self, node: &AstNode<'a>, ctx: &LintContext<'a>) {
if let AstKind::MemberExpression(member_expr) = node.kind() {
if let Some((span, name)) = member_expr.static_property_info() {
if name == "innerText" && !member_expr.is_computed() {
ctx.diagnostic_with_fix(
prefer_dom_node_text_content_diagnostic(span),
|fixer| fixer.replace(span, "textContent"),
);
match node.kind() {
AstKind::MemberExpression(member_expr) => {
if let Some((span, name)) = member_expr.static_property_info() {
if name == "innerText" && !member_expr.is_computed() {
ctx.diagnostic_with_fix(
prefer_dom_node_text_content_diagnostic(span),
|fixer| fixer.replace(span, "textContent"),
);
}
}
}
}

let Some(parent_node) = ctx.nodes().parent_node(node.id()) else {
return;
};

let Some(grand_parent_node) = ctx.nodes().parent_node(parent_node.id()) else {
return;
};
// `const {innerText} = node` or `({innerText: text} = node)`
AstKind::IdentifierName(identifier) => {
if identifier.name != "innerText" {
return;
}

let parent_node_kind = parent_node.kind();
let grand_parent_node_kind = grand_parent_node.kind();
let mut ancestor_kinds =
ctx.nodes().iter_parents(node.id()).skip(1).map(AstNode::kind);
let (Some(parent_node_kind), Some(grand_parent_node_kind)) =
(ancestor_kinds.next(), ancestor_kinds.next())
else {
return;
};

// `const {innerText} = node` or `({innerText: text} = node)`
if let AstKind::IdentifierName(identifier) = node.kind() {
if identifier.name == "innerText"
&& matches!(parent_node_kind, AstKind::PropertyKey(_))
&& (matches!(grand_parent_node_kind, AstKind::ObjectPattern(_))
|| matches!(
grand_parent_node_kind,
AstKind::ObjectAssignmentTarget(_)
| AstKind::SimpleAssignmentTarget(_)
| AstKind::AssignmentTarget(_)
))
{
ctx.diagnostic(prefer_dom_node_text_content_diagnostic(identifier.span));
return;
if matches!(parent_node_kind, AstKind::PropertyKey(_))
&& (matches!(grand_parent_node_kind, AstKind::ObjectPattern(_))
|| matches!(
grand_parent_node_kind,
AstKind::ObjectAssignmentTarget(_)
| AstKind::SimpleAssignmentTarget(_)
| AstKind::AssignmentTarget(_)
))
{
ctx.diagnostic(prefer_dom_node_text_content_diagnostic(identifier.span));
}
}
}
// `({innerText} = node)`
AstKind::IdentifierReference(identifier_ref) => {
if identifier_ref.name != "innerText" {
return;
}

// `({innerText} = node)`
if let AstKind::IdentifierReference(identifier_ref) = node.kind() {
if identifier_ref.name == "innerText"
&& matches!(
let mut ancestor_kinds =
ctx.nodes().iter_parents(node.id()).skip(1).map(AstNode::kind);
let (Some(parent_node_kind), Some(grand_parent_node_kind)) =
(ancestor_kinds.next(), ancestor_kinds.next())
else {
return;
};

if matches!(
parent_node_kind,
AstKind::ObjectAssignmentTarget(_)
| AstKind::AssignmentTarget(_)
| AstKind::SimpleAssignmentTarget(_)
)
&& matches!(grand_parent_node_kind, AstKind::AssignmentTargetPattern(_))
{
ctx.diagnostic(prefer_dom_node_text_content_diagnostic(identifier_ref.span));
) && matches!(grand_parent_node_kind, AstKind::AssignmentTargetPattern(_))
{
ctx.diagnostic(prefer_dom_node_text_content_diagnostic(identifier_ref.span));
}
}
_ => {}
}
}
}
Expand Down

0 comments on commit 725f9f6

Please sign in to comment.