Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 2 additions & 4 deletions crates/oxc_linter/src/ast_util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,6 @@ pub fn outermost_paren_parent<'a, 'b>(
semantic
.nodes()
.ancestors(node.id())
.skip(1)
.find(|parent| !matches!(parent.kind(), AstKind::ParenthesizedExpression(_)))
}

Expand All @@ -253,7 +252,6 @@ pub fn nth_outermost_paren_parent<'a, 'b>(
semantic
.nodes()
.ancestors(node.id())
.skip(1)
.filter(|parent| !matches!(parent.kind(), AstKind::ParenthesizedExpression(_)))
.nth(n)
}
Expand All @@ -264,7 +262,7 @@ pub fn iter_outer_expressions<'a, 's>(
semantic: &'s Semantic<'a>,
node_id: NodeId,
) -> impl Iterator<Item = AstKind<'a>> + 's {
semantic.nodes().ancestor_kinds(node_id).skip(1).filter(|parent| {
semantic.nodes().ancestor_kinds(node_id).filter(|parent| {
!matches!(
parent,
AstKind::ParenthesizedExpression(_)
Expand Down Expand Up @@ -661,7 +659,7 @@ pub fn is_default_this_binding<'a>(
current_node = parent;
}
AstKind::ReturnStatement(_) => {
let upper_func = semantic.nodes().ancestors(parent.id()).skip(1).find(|node| {
let upper_func = semantic.nodes().ancestors(parent.id()).find(|node| {
matches!(
node.kind(),
AstKind::Function(_) | AstKind::ArrowFunctionExpression(_)
Expand Down
8 changes: 4 additions & 4 deletions crates/oxc_linter/src/rules/eslint/func_names.rs
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,7 @@ impl Rule for FuncNames {

// a function which is calling itself inside is always valid
let ast_span =
ctx.nodes().ancestors(node.id()).skip(1).find_map(|p| match p.kind() {
ctx.nodes().ancestors(node.id()).find_map(|p| match p.kind() {
AstKind::Function(func) => {
let func_name = func.name()?;

Expand Down Expand Up @@ -314,7 +314,7 @@ impl Rule for FuncNames {
ctx.diagnostic_with_fix(
unnamed_diagnostic(&func_name_complete, report_span),
|fixer| {
guess_function_name(ctx, parent_node.id()).map_or_else(
guess_function_name(ctx, node.id()).map_or_else(
|| fixer.noop(),
|name| {
// if this name shadows a variable in the outer scope **and** that name is referenced
Expand Down Expand Up @@ -346,8 +346,8 @@ impl Rule for FuncNames {
}
}

fn guess_function_name<'a>(ctx: &LintContext<'a>, parent_id: NodeId) -> Option<Cow<'a, str>> {
for parent_kind in ctx.nodes().ancestor_kinds(parent_id) {
fn guess_function_name<'a>(ctx: &LintContext<'a>, node_id: NodeId) -> Option<Cow<'a, str>> {
for parent_kind in ctx.nodes().ancestor_kinds(node_id) {
match parent_kind {
AstKind::ParenthesizedExpression(_)
| AstKind::TSAsExpression(_)
Expand Down
1 change: 0 additions & 1 deletion crates/oxc_linter/src/rules/eslint/func_style.rs
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,6 @@ impl Rule for FuncStyle {
let arrow_func_ancestor = semantic
.nodes()
.ancestors(node.id())
.skip(1)
.find(|v| matches!(v.kind(), AstKind::FunctionBody(_)))
.map(|el| semantic.nodes().parent_node(el.id()));
if let Some(ret) = arrow_func_ancestor {
Expand Down
2 changes: 1 addition & 1 deletion crates/oxc_linter/src/rules/eslint/init_declarations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ impl Rule for InitDeclarations {
return;
}
let decl_ancestor =
ctx.nodes().ancestor_kinds(node.id()).skip(1).find(|el| {
ctx.nodes().ancestor_kinds(node.id()).find(|el| {
matches!(el, AstKind::TSModuleDeclaration(ts_module_decl) if ts_module_decl.declare)
});
if decl_ancestor.is_some() {
Expand Down
2 changes: 1 addition & 1 deletion crates/oxc_linter/src/rules/eslint/max_depth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ declare_oxc_lint!(
impl Rule for MaxDepth {
fn run<'a>(&self, node: &AstNode<'a>, ctx: &LintContext<'a>) {
if should_count(node, ctx.nodes()) {
let depth = ctx
let depth = 1 + ctx
.nodes()
.ancestors(node.id())
.take_while(|node| !should_stop(node))
Expand Down
4 changes: 2 additions & 2 deletions crates/oxc_linter/src/rules/eslint/max_nested_callbacks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,8 +108,8 @@ declare_oxc_lint!(

impl Rule for MaxNestedCallbacks {
fn run<'a>(&self, node: &AstNode<'a>, ctx: &LintContext<'a>) {
if is_function_node(node) {
let depth = ctx
if is_callback(node, ctx) {
let depth = 1 + ctx
.semantic()
.nodes()
.ancestors(node.id())
Expand Down
2 changes: 1 addition & 1 deletion crates/oxc_linter/src/rules/eslint/no_cond_assign.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ impl Rule for NoCondAssign {
}
AstKind::AssignmentExpression(expr) if self.config == NoCondAssignConfig::Always => {
let mut spans = vec![];
for ancestor in ctx.nodes().ancestors(node.id()).skip(1) {
for ancestor in ctx.nodes().ancestors(node.id()) {
match ancestor.kind() {
AstKind::IfStatement(if_stmt) => {
spans.push(if_stmt.test.span());
Expand Down
2 changes: 1 addition & 1 deletion crates/oxc_linter/src/rules/eslint/no_console.rs
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ fn remove_console<'c, 'a: 'c>(
node: &AstNode<'a>,
) -> RuleFix<'a> {
let mut node_to_delete = node;
for parent in ctx.nodes().ancestors(node.id()).skip(1) {
for parent in ctx.nodes().ancestors(node.id()) {
match parent.kind() {
AstKind::ParenthesizedExpression(_)
| AstKind::ExpressionStatement(_)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ fn is_constructor(node: &AstNode<'_>) -> bool {
}

fn is_definitely_in_constructor(ctx: &LintContext, node_id: NodeId) -> bool {
for ancestor_id in ctx.nodes().ancestor_ids(node_id).skip(1) {
for ancestor_id in ctx.nodes().ancestor_ids(node_id) {
match ctx.nodes().kind(ancestor_id) {
AstKind::Function(_) => {
return is_constructor(ctx.nodes().parent_node(ancestor_id));
Expand Down
1 change: 0 additions & 1 deletion crates/oxc_linter/src/rules/eslint/no_debugger.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@ impl Rule for NoDebugger {
let Some(parent) = ctx
.nodes()
.ancestors(node.id())
.skip(1)
.find(|p| !matches!(p.kind(), AstKind::ParenthesizedExpression(_)))
else {
return fixer.delete(&stmt.span).with_message(REMOVE_DEBUGGER);
Expand Down
2 changes: 1 addition & 1 deletion crates/oxc_linter/src/rules/eslint/no_empty_function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ impl NoEmptyFunction {
node: &AstNode<'a>,
ctx: &LintContext<'a>,
) -> ViolationInfo<'a> {
for parent in ctx.nodes().ancestor_kinds(node.id()).skip(1) {
for parent in ctx.nodes().ancestor_kinds(node.id()) {
match parent {
AstKind::Function(f) => {
if let Some(name) = f.name() {
Expand Down
2 changes: 1 addition & 1 deletion crates/oxc_linter/src/rules/eslint/no_eval.rs
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,7 @@ impl NoEval {
node: &'a AstNode<'b>,
semantic: &'a LintContext<'b>,
) -> Option<&'a AstNode<'b>> {
semantic.nodes().ancestors(node.id()).skip(1).find(|parent| {
semantic.nodes().ancestors(node.id()).find(|parent| {
!matches!(
parent.kind(),
AstKind::ParenthesizedExpression(_) | AstKind::ChainExpression(_)
Expand Down
4 changes: 2 additions & 2 deletions crates/oxc_linter/src/rules/eslint/no_extend_native.rs
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ fn get_define_property_call<'a>(
ctx: &'a LintContext,
node: &AstNode<'a>,
) -> Option<&'a AstNode<'a>> {
for parent in ctx.nodes().ancestors(node.id()).skip(1) {
for parent in ctx.nodes().ancestors(node.id()) {
if let AstKind::CallExpression(call_expr) = parent.kind() {
if is_define_property_call(call_expr) {
return Some(parent);
Expand Down Expand Up @@ -180,7 +180,7 @@ fn get_property_assignment<'a>(
ctx: &'a LintContext,
node: &AstNode<'a>,
) -> Option<&'a AstNode<'a>> {
for parent in ctx.nodes().ancestors(node.id()).skip(1) {
for parent in ctx.nodes().ancestors(node.id()) {
match parent.kind() {
AstKind::AssignmentExpression(assignment_expr)
if assignment_expr.left.span().contains_inclusive(node.span()) =>
Expand Down
22 changes: 8 additions & 14 deletions crates/oxc_linter/src/rules/eslint/no_extra_boolean_cast.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
use itertools::Itertools;
use oxc_ast::{
AstKind,
ast::{CallExpression, Expression, NewExpression},
Expand Down Expand Up @@ -210,19 +209,14 @@ fn is_unary_negation(node: &AstNode) -> bool {
}

fn get_real_parent<'a, 'b>(node: &AstNode, ctx: &'a LintContext<'b>) -> Option<&'a AstNode<'b>> {
for (_, parent) in
ctx.nodes().ancestors(node.id()).tuple_windows::<(&AstNode<'b>, &AstNode<'b>)>()
{
if let AstKind::Argument(_)
| AstKind::ParenthesizedExpression(_)
| AstKind::ChainExpression(_) = parent.kind()
{
continue;
}

return Some(parent);
}
None
ctx.nodes().ancestors(node.id()).find(|parent| {
!matches!(
parent.kind(),
AstKind::Argument(_)
| AstKind::ParenthesizedExpression(_)
| AstKind::ChainExpression(_)
)
})
}

/// Remove `!!` from `expr` if present.
Expand Down
3 changes: 1 addition & 2 deletions crates/oxc_linter/src/rules/eslint/no_labels.rs
Original file line number Diff line number Diff line change
Expand Up @@ -191,8 +191,7 @@ impl NoLabels {
stmt_node_id: NodeId,
ctx: &LintContext<'a>,
) -> bool {
let nodes = ctx.nodes();
for ancestor_kind in nodes.ancestor_kinds(stmt_node_id) {
for ancestor_kind in ctx.nodes().ancestor_kinds(stmt_node_id) {
if let AstKind::LabeledStatement(labeled_stmt) = ancestor_kind {
if label.name == labeled_stmt.label.name {
return self.is_allowed(&labeled_stmt.body);
Expand Down
14 changes: 5 additions & 9 deletions crates/oxc_linter/src/rules/eslint/no_new.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,17 +52,13 @@ impl Rule for NoNew {
let mut ancestors = ctx
.nodes()
.ancestors(node.id())
.filter(|a| !matches!(a.kind(), AstKind::ParenthesizedExpression(_)))
.map(AstNode::id)
.skip(1);
let Some(node_id) = ancestors.next() else { return };
.filter(|a| !matches!(a.kind(), AstKind::ParenthesizedExpression(_)));
let Some(node) = ancestors.next() else { return };

let kind = ctx.nodes().kind(node_id);
if matches!(kind, AstKind::ExpressionStatement(_)) {
if matches!(node.kind(), AstKind::ExpressionStatement(_)) {
ancestors.next(); // skip `FunctionBody`
if let Some(node_id) = ancestors.next() {
let kind = ctx.nodes().kind(node_id);
if matches!(kind, AstKind::ArrowFunctionExpression(e) if e.expression) {
if let Some(node) = ancestors.next() {
if matches!(node.kind(), AstKind::ArrowFunctionExpression(e) if e.expression) {
return;
}
}
Expand Down
13 changes: 6 additions & 7 deletions crates/oxc_linter/src/rules/eslint/no_new_func.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,13 +67,12 @@ impl Rule for NoNewFunc {
return;
};

let parent: Option<AstKind<'a>> =
ctx.nodes().ancestor_kinds(node.id()).skip(1).find(|node| {
!matches!(
node,
AstKind::ChainExpression(_) | AstKind::ParenthesizedExpression(_)
)
});
let parent = ctx.nodes().ancestor_kinds(node.id()).find(|node| {
!matches!(
node,
AstKind::ChainExpression(_) | AstKind::ParenthesizedExpression(_)
)
});

let Some(AstKind::CallExpression(parent_call_expr)) = parent else {
return;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,9 +113,8 @@ impl Rule for NoUnusedPrivateClassMembers {
}

fn is_read(current_node_id: NodeId, nodes: &AstNodes) -> bool {
for (curr, parent) in nodes
.ancestors(nodes.parent_id(current_node_id))
.tuple_windows::<(&AstNode<'_>, &AstNode<'_>)>()
for (curr, parent) in
nodes.ancestors(current_node_id).tuple_windows::<(&AstNode<'_>, &AstNode<'_>)>()
{
match (curr.kind(), parent.kind()) {
(member_expr, AstKind::AssignmentTarget(_) | AstKind::SimpleAssignmentTarget(_))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ impl NoUnusedVars {
param: &FormalParameter<'a>,
params_id: NodeId,
) -> bool {
let mut parents_iter = semantic.nodes().ancestor_kinds(params_id).skip(1);
let mut parents_iter = semantic.nodes().ancestor_kinds(params_id);

// in function declarations, the parent immediately before the
// FormalParameters is a TSDeclareBlock
Expand Down
20 changes: 10 additions & 10 deletions crates/oxc_linter/src/rules/eslint/no_unused_vars/symbol.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::{cell::OnceCell, fmt};
use std::{cell::OnceCell, fmt, iter};

use oxc_ast::{
AstKind,
Expand Down Expand Up @@ -99,30 +99,30 @@ impl<'s, 'a> Symbol<'s, 'a> {

#[inline]
pub fn iter_parents(&self) -> impl Iterator<Item = &AstNode<'a>> + '_ {
self.iter_self_and_parents().skip(1)
self.nodes().ancestors(self.declaration_id())
}

pub fn iter_self_and_parents(&self) -> impl Iterator<Item = &AstNode<'a>> + '_ {
self.nodes().ancestors(self.declaration_id())
let node_id = self.declaration_id();
let node = self.nodes().get_node(node_id);
iter::once(node).chain(self.nodes().ancestors(node_id))
}

pub fn iter_relevant_parents_of(
&self,
node_id: NodeId,
) -> impl Iterator<Item = &AstNode<'a>> + Clone + '_ {
self.nodes().ancestors(node_id).skip(1).filter(|n| Self::is_relevant_kind(n.kind()))
self.nodes().ancestors(node_id).filter(|n| Self::is_relevant_kind(n.kind()))
}

pub fn iter_relevant_parent_and_grandparent_kinds(
&self,
node_id: NodeId,
) -> impl Iterator<Item = (/* parent */ AstKind<'a>, /* grandparent */ AstKind<'a>)> + Clone + '_
{
let parents_iter = self
.nodes()
.ancestor_kinds(node_id)
// no skip
.filter(|kind| Self::is_relevant_kind(*kind));
let parents_iter = iter::once(self.nodes().kind(node_id)).chain(
self.nodes().ancestor_kinds(node_id).filter(|kind| Self::is_relevant_kind(*kind)),
);

let grandparents_iter = parents_iter.clone().skip(1);

Expand Down Expand Up @@ -184,7 +184,7 @@ impl<'a> Symbol<'_, 'a> {

/// We need to do this due to limitations of [`Semantic`].
fn in_export_node(&self) -> bool {
for parent in self.nodes().ancestors(self.declaration_id()).skip(1) {
for parent in self.nodes().ancestors(self.declaration_id()) {
match parent.kind() {
AstKind::ExportNamedDeclaration(_) | AstKind::ExportDefaultDeclaration(_) => {
return true;
Expand Down
4 changes: 2 additions & 2 deletions crates/oxc_linter/src/rules/eslint/no_unused_vars/usage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,7 @@ impl<'a> Symbol<'_, 'a> {
return false;
}

for parent in self.nodes().ancestors(reference.node_id()).map(AstNode::kind) {
for parent in self.nodes().ancestor_kinds(reference.node_id()) {
match parent {
AstKind::IdentifierReference(_)
| AstKind::SimpleAssignmentTarget(_)
Expand Down Expand Up @@ -405,7 +405,7 @@ impl<'a> Symbol<'_, 'a> {
let name = self.name();
let ref_span = self.get_ref_span(reference);

for node in self.nodes().ancestors(reference.node_id()).skip(1) {
for node in self.nodes().ancestors(reference.node_id()) {
match node.kind() {
// references used in declaration of another variable are definitely
// used by others
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,8 +116,7 @@ impl Rule for NoUselessConstructor {
return;
}

let class =
ctx.nodes().ancestors(node.id()).skip(1).find_map(|parent| parent.kind().as_class());
let class = ctx.nodes().ancestors(node.id()).find_map(|parent| parent.kind().as_class());
debug_assert!(class.is_some(), "Found a constructor outside of a class definition");
let Some(class) = class else {
return;
Expand Down
2 changes: 1 addition & 1 deletion crates/oxc_linter/src/rules/import/no_commonjs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ impl Rule for NoCommonjs {
let object = member_expr_kind.object();

if object.is_specific_id("module") && property_name == "exports" {
let Some(parent_node) = ctx.nodes().ancestors(node.id()).nth(3) else {
let Some(parent_node) = ctx.nodes().ancestors(node.id()).nth(2) else {
return;
};

Expand Down
13 changes: 5 additions & 8 deletions crates/oxc_linter/src/rules/jest/no_duplicate_hooks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -143,14 +143,11 @@ impl NoDuplicateHooks {
}

let hook_name = jest_fn_call.name.to_string();
let parent_node_id =
match ctx.nodes().ancestor_ids(node.id()).find(|n| hook_contexts.contains_key(n)) {
Some(n) => Some(n),
_ => Some(root_node_id),
};
let Some(parent_id) = parent_node_id else {
return;
};
let parent_id = ctx
.nodes()
.ancestor_ids(node.id())
.find(|n| hook_contexts.contains_key(n))
.unwrap_or(root_node_id);

let Some(contexts) = hook_contexts.get_mut(&parent_id) else {
return;
Expand Down
2 changes: 1 addition & 1 deletion crates/oxc_linter/src/rules/jest/prefer_each.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ impl PreferEach {
return;
}

for parent_node in ctx.nodes().ancestors(node.id()).skip(1) {
for parent_node in ctx.nodes().ancestors(node.id()) {
match parent_node.kind() {
AstKind::CallExpression(_) => return,
AstKind::ForStatement(_)
Expand Down
Loading
Loading