refactor(semantic): rename iter_parents to ancestors (#7216)

for consistency with the `ancestor_ids` function, this changes it to use the same terminology but make it clear it actually returns the node, not just the ID.

this is pure refactor, no functional changes here.
This commit is contained in:
camchenry 2024-11-09 07:07:26 +00:00
parent 42171eba94
commit abf1602f33
33 changed files with 50 additions and 51 deletions

View file

@ -236,7 +236,7 @@ pub fn outermost_paren_parent<'a, 'b>(
) -> Option<&'b AstNode<'a>> {
semantic
.nodes()
.iter_parents(node.id())
.ancestors(node.id())
.skip(1)
.find(|parent| !matches!(parent.kind(), AstKind::ParenthesizedExpression(_)))
}
@ -248,7 +248,7 @@ pub fn nth_outermost_paren_parent<'a, 'b>(
) -> Option<&'b AstNode<'a>> {
semantic
.nodes()
.iter_parents(node.id())
.ancestors(node.id())
.skip(1)
.filter(|parent| !matches!(parent.kind(), AstKind::ParenthesizedExpression(_)))
.nth(n)
@ -260,7 +260,7 @@ pub fn iter_outer_expressions<'a, 's>(
semantic: &'s Semantic<'a>,
node_id: NodeId,
) -> impl Iterator<Item = &'s AstNode<'a>> + 's {
semantic.nodes().iter_parents(node_id).skip(1).filter(|parent| {
semantic.nodes().ancestors(node_id).skip(1).filter(|parent| {
!matches!(
parent.kind(),
AstKind::ParenthesizedExpression(_)

View file

@ -401,8 +401,8 @@ impl Rule for FuncNames {
}
// a function which is calling itself inside is always valid
let ast_span = ctx.nodes().iter_parents(node.id()).skip(1).find_map(|p| {
match p.kind() {
let ast_span =
ctx.nodes().ancestors(node.id()).skip(1).find_map(|p| match p.kind() {
AstKind::Function(func) => {
let func_name = func.name()?;
@ -413,8 +413,7 @@ impl Rule for FuncNames {
None
}
_ => None,
}
});
});
// we found a recursive function, remove it from the invalid list
if let Some(span) = ast_span {
@ -480,7 +479,7 @@ 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().iter_parents(parent_id).map(AstNode::kind) {
for parent_kind in ctx.nodes().ancestors(parent_id).map(AstNode::kind) {
match parent_kind {
AstKind::ParenthesizedExpression(_)
| AstKind::TSAsExpression(_)

View file

@ -79,7 +79,7 @@ impl Rule for NoCondAssign {
}
AstKind::AssignmentExpression(expr) if self.config == NoCondAssignConfig::Always => {
let mut spans = vec![];
for ancestor in ctx.nodes().iter_parents(node.id()).skip(1) {
for ancestor in ctx.nodes().ancestors(node.id()).skip(1) {
match ancestor.kind() {
AstKind::IfStatement(if_stmt) => {
spans.push(if_stmt.test.span());

View file

@ -40,7 +40,7 @@ impl Rule for NoDebugger {
ctx.diagnostic_with_fix(no_debugger_diagnostic(stmt.span), |fixer| {
let Some(parent) = ctx
.nodes()
.iter_parents(node.id())
.ancestors(node.id())
.skip(1)
.find(|p| !matches!(p.kind(), AstKind::ParenthesizedExpression(_)))
else {

View file

@ -76,7 +76,7 @@ fn get_function_name_and_kind<'a>(
node: &AstNode<'a>,
ctx: &LintContext<'a>,
) -> (&'static str, Option<Cow<'a, str>>) {
for parent in ctx.nodes().iter_parents(node.id()).skip(1).map(AstNode::kind) {
for parent in ctx.nodes().ancestors(node.id()).skip(1).map(AstNode::kind) {
match parent {
AstKind::Function(f) => {
if let Some(name) = f.name() {

View file

@ -142,7 +142,7 @@ fn get_define_property_call<'a>(
ctx: &'a LintContext,
node: &AstNode<'a>,
) -> Option<&'a AstNode<'a>> {
for parent in ctx.nodes().iter_parents(node.id()).skip(1) {
for parent in ctx.nodes().ancestors(node.id()).skip(1) {
if let AstKind::CallExpression(call_expr) = parent.kind() {
if is_define_property_call(call_expr) {
return Some(parent);
@ -179,7 +179,7 @@ fn get_property_assignment<'a>(
ctx: &'a LintContext,
node: &AstNode<'a>,
) -> Option<&'a AstNode<'a>> {
for parent in ctx.nodes().iter_parents(node.id()).skip(1) {
for parent in ctx.nodes().ancestors(node.id()).skip(1) {
match parent.kind() {
AstKind::AssignmentExpression(_) => return Some(parent),
AstKind::MemberExpression(MemberExpression::ComputedMemberExpression(computed)) => {

View file

@ -188,7 +188,7 @@ 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().iter_parents(node.id()).tuple_windows::<(&AstNode<'b>, &AstNode<'b>)>()
ctx.nodes().ancestors(node.id()).tuple_windows::<(&AstNode<'b>, &AstNode<'b>)>()
{
if let AstKind::Argument(_)
| AstKind::ParenthesizedExpression(_)

View file

@ -63,7 +63,7 @@ impl Rule for NoNewFunc {
}
AstKind::MemberExpression(mem_expr) => {
let parent: Option<&AstNode<'a>> =
ctx.nodes().iter_parents(node.id()).skip(1).find(|node| {
ctx.nodes().ancestors(node.id()).skip(1).find(|node| {
!matches!(
node.kind(),
AstKind::ChainExpression(_) | AstKind::ParenthesizedExpression(_)

View file

@ -116,7 +116,7 @@ impl Rule for NoUnusedPrivateClassMembers {
fn is_read(current_node_id: NodeId, nodes: &AstNodes) -> bool {
for (curr, parent) in nodes
.iter_parents(nodes.parent_id(current_node_id).unwrap_or(current_node_id))
.ancestors(nodes.parent_id(current_node_id).unwrap_or(current_node_id))
.tuple_windows::<(&AstNode<'_>, &AstNode<'_>)>()
{
match (curr.kind(), parent.kind()) {

View file

@ -255,7 +255,7 @@ impl NoUnusedVars {
param: &FormalParameter<'a>,
params_id: NodeId,
) -> bool {
let mut parents_iter = semantic.nodes().iter_parents(params_id).skip(1).map(AstNode::kind);
let mut parents_iter = semantic.nodes().ancestors(params_id).skip(1).map(AstNode::kind);
// in function declarations, the parent immediately before the
// FormalParameters is a TSDeclareBlock

View file

@ -102,7 +102,7 @@ impl<'s, 'a> Symbol<'s, 'a> {
}
pub fn iter_self_and_parents(&self) -> impl Iterator<Item = &AstNode<'a>> + '_ {
self.nodes().iter_parents(self.declaration_id())
self.nodes().ancestors(self.declaration_id())
}
#[inline]
@ -114,7 +114,7 @@ impl<'s, 'a> Symbol<'s, 'a> {
&self,
node_id: NodeId,
) -> impl Iterator<Item = &AstNode<'a>> + Clone + '_ {
self.nodes().iter_parents(node_id).skip(1).filter(|n| Self::is_relevant_kind(n.kind()))
self.nodes().ancestors(node_id).skip(1).filter(|n| Self::is_relevant_kind(n.kind()))
}
pub fn iter_relevant_parent_and_grandparent_kinds(
@ -124,7 +124,7 @@ impl<'s, 'a> Symbol<'s, 'a> {
{
let parents_iter = self
.nodes()
.iter_parents(node_id)
.ancestors(node_id)
.map(AstNode::kind)
// no skip
.filter(|kind| Self::is_relevant_kind(*kind));
@ -190,7 +190,7 @@ impl<'s, 'a> Symbol<'s, 'a> {
/// We need to do this due to limitations of [`Semantic`].
fn in_export_node(&self) -> bool {
for parent in self.nodes().iter_parents(self.declaration_id()).skip(1) {
for parent in self.nodes().ancestors(self.declaration_id()).skip(1) {
match parent.kind() {
AstKind::ModuleDeclaration(module) => {
return module.is_export();

View file

@ -178,7 +178,7 @@ impl<'s, 'a> Symbol<'s, 'a> {
/// for (let a of iter) { fn(b) }
/// ```
fn is_used_in_for_of_loop(&self, reference: &Reference) -> bool {
for parent in self.nodes().iter_parents(reference.node_id()) {
for parent in self.nodes().ancestors(reference.node_id()) {
match parent.kind() {
AstKind::ParenthesizedExpression(_)
| AstKind::IdentifierReference(_)
@ -222,7 +222,7 @@ impl<'s, 'a> Symbol<'s, 'a> {
return false;
}
for parent in self.nodes().iter_parents(reference.node_id()).map(AstNode::kind) {
for parent in self.nodes().ancestors(reference.node_id()).map(AstNode::kind) {
match parent {
AstKind::IdentifierReference(_)
| AstKind::SimpleAssignmentTarget(_)
@ -378,7 +378,7 @@ impl<'s, 'a> Symbol<'s, 'a> {
let name = self.name();
let ref_span = self.get_ref_span(reference);
for node in self.nodes().iter_parents(reference.node_id()).skip(1) {
for node in self.nodes().ancestors(reference.node_id()).skip(1) {
match node.kind() {
// references used in declaration of another variable are definitely
// used by others

View file

@ -118,7 +118,7 @@ impl Rule for NoUselessConstructor {
let class = ctx
.nodes()
.iter_parents(node.id())
.ancestors(node.id())
.skip(1)
.find(|parent| matches!(parent.kind(), AstKind::Class(_)));
debug_assert!(class.is_some(), "Found a constructor outside of a class definition");

View file

@ -157,7 +157,7 @@ impl Rule for NoCommonjs {
};
if member_expr.object().is_specific_id("module") && property_name == "exports" {
let Some(parent_node) = ctx.nodes().iter_parents(node.id()).nth(3) else {
let Some(parent_node) = ctx.nodes().ancestors(node.id()).nth(3) else {
return;
};

View file

@ -100,7 +100,7 @@ impl Rule for NoConditionalInTest {
| AstKind::ConditionalExpression(_)
| AstKind::LogicalExpression(_)
) {
let is_if_statement_in_test = ctx.nodes().iter_parents(node.id()).any(|node| {
let is_if_statement_in_test = ctx.nodes().ancestors(node.id()).any(|node| {
let AstKind::CallExpression(call_expr) = node.kind() else { return false };
let vitest_node = PossibleJestNode { node, original: None };

View file

@ -78,7 +78,7 @@ impl Rule for NoPageCustomFont {
fn is_inside_export_default(node: &AstNode<'_>, ctx: &LintContext<'_>) -> bool {
let mut is_inside_export_default = false;
for parent_node in ctx.nodes().iter_parents(node.id()) {
for parent_node in ctx.nodes().ancestors(node.id()) {
// export default function/class
let kind = parent_node.kind();
if matches!(kind, AstKind::ExportDefaultDeclaration(_)) {

View file

@ -184,7 +184,7 @@ fn check_reduce_usage<'a>(
}
// Check if the declaration resides within a call to reduce()
for parent in ctx.nodes().iter_parents(declaration.id()) {
for parent in ctx.nodes().ancestors(declaration.id()) {
if let AstKind::CallExpression(call_expr) = parent.kind() {
if is_method_call(call_expr, None, Some(&["reduce", "reduceRight"]), Some(1), Some(2)) {
ctx.diagnostic(get_reduce_diagnostic(call_expr, spread_span));
@ -245,7 +245,7 @@ fn check_loop_usage<'a>(
_ => return,
}
for parent in ctx.nodes().iter_parents(spread_node_id) {
for parent in ctx.nodes().ancestors(spread_node_id) {
if let Some(loop_span) = get_loop_span(parent.kind()) {
if !parent.kind().span().contains_inclusive(declaration.span)
&& parent.kind().span().contains_inclusive(spread_span)

View file

@ -116,7 +116,7 @@ impl Rule for NoCallbackInPromise {
}
} else if ctx
.nodes()
.iter_parents(node.id())
.ancestors(node.id())
.skip(1)
.any(|node| Self::is_inside_promise(node, ctx))
{
@ -133,7 +133,7 @@ impl NoCallbackInPromise {
return false;
}
ctx.nodes().iter_parents(node.id()).nth(2).is_some_and(|node| {
ctx.nodes().ancestors(node.id()).nth(2).is_some_and(|node| {
node.kind().as_call_expression().is_some_and(Self::has_promise_callback)
})
}

View file

@ -130,7 +130,7 @@ impl PreferAwaitToCallbacks {
}
fn is_inside_yield_or_await(id: NodeId, ctx: &LintContext) -> bool {
ctx.nodes().iter_parents(id).skip(1).any(|parent| {
ctx.nodes().ancestors(id).skip(1).any(|parent| {
matches!(parent.kind(), AstKind::AwaitExpression(_) | AstKind::YieldExpression(_))
})
}

View file

@ -141,7 +141,7 @@ pub fn is_children<'a, 'b>(node: &'b AstNode<'a>, ctx: &'b LintContext<'a>) -> b
return is_import(ctx, ident.name.as_str(), REACT, REACT) && local_name == CHILDREN;
}
fn is_within_children_to_array<'a, 'b>(node: &'b AstNode<'a>, ctx: &'b LintContext<'a>) -> bool {
let parents_iter = ctx.nodes().iter_parents(node.id()).skip(2);
let parents_iter = ctx.nodes().ancestors(node.id()).skip(2);
parents_iter
.filter(|parent_node| matches!(parent_node.kind(), AstKind::CallExpression(_)))
.any(|parent_node| is_children(parent_node, ctx) && is_to_array(parent_node))

View file

@ -176,7 +176,7 @@ fn should_ignore_component<'a, 'b>(node: &'b AstNode<'a>, ctx: &'b LintContext<'
let mut is_call_expression = false;
let mut is_component = false;
for parent in ctx.nodes().iter_parents(node.id()) {
for parent in ctx.nodes().ancestors(node.id()) {
if let AstKind::MethodDefinition(method_def) = parent.kind() {
if method_def.kind == MethodDefinitionKind::Constructor {
is_constructor = true;

View file

@ -127,7 +127,7 @@ impl NoExplicitAny {
fn is_in_rest<'a>(node: &AstNode<'a>, ctx: &LintContext<'a>) -> bool {
debug_assert!(matches!(node.kind(), AstKind::TSAnyKeyword(_)));
ctx.nodes()
.iter_parents(node.id())
.ancestors(node.id())
.any(|parent| matches!(parent.kind(), AstKind::BindingRestElement(_)))
}
}

View file

@ -108,7 +108,7 @@ impl Rule for NoNamespace {
}
fn is_declaration(node: &AstNode, ctx: &LintContext) -> bool {
ctx.nodes().iter_parents(node.id()).any(|node| {
ctx.nodes().ancestors(node.id()).any(|node| {
let AstKind::TSModuleDeclaration(declaration) = node.kind() else {
return false;
};

View file

@ -204,7 +204,7 @@ impl Rule for NoNull {
ctx.diagnostic_with_fix(no_null_diagnostic(null_literal.span), |fixer| {
let mut null_span = null_literal.span;
// Find the last parent that is a TSAsExpression (`null as any`) or TSNonNullExpression (`null!`)
for parent in ctx.nodes().iter_parents(node.id()).skip(1) {
for parent in ctx.nodes().ancestors(node.id()).skip(1) {
let parent = parent.kind();
if matches!(
parent,

View file

@ -68,7 +68,7 @@ fn has_hashbang(ctx: &LintContext) -> bool {
}
fn is_inside_process_event_handler(ctx: &LintContext, node: &AstNode) -> bool {
for parent in ctx.nodes().iter_parents(node.id()) {
for parent in ctx.nodes().ancestors(node.id()) {
if let AstKind::CallExpression(expr) = parent.kind() {
if is_method_call(expr, Some(&["process"]), Some(&["on", "once"]), Some(1), None) {
return true;

View file

@ -101,7 +101,7 @@ impl Rule for NoSinglePromiseInPromiseMethods {
.semantic()
.nodes()
// get first non-parenthesis parent node
.iter_parents(node.id())
.ancestors(node.id())
.skip(1) // first node is the call expr
.find(|parent| !is_ignorable_kind(&parent.kind()))
// check if it's an `await ...` expression
@ -126,7 +126,7 @@ fn is_promise_method_with_single_argument(call_expr: &CallExpression) -> bool {
}
fn is_fixable(call_node_id: NodeId, ctx: &LintContext<'_>) -> bool {
for parent in ctx.semantic().nodes().iter_parents(call_node_id).skip(1) {
for parent in ctx.semantic().nodes().ancestors(call_node_id).skip(1) {
match parent.kind() {
AstKind::CallExpression(_)
| AstKind::VariableDeclarator(_)

View file

@ -62,7 +62,7 @@ impl Rule for PreferDomNodeTextContent {
}
let mut ancestor_kinds =
ctx.nodes().iter_parents(node.id()).skip(1).map(AstNode::kind);
ctx.nodes().ancestors(node.id()).skip(1).map(AstNode::kind);
let (Some(parent_node_kind), Some(grand_parent_node_kind)) =
(ancestor_kinds.next(), ancestor_kinds.next())
else {
@ -88,7 +88,7 @@ impl Rule for PreferDomNodeTextContent {
}
let mut ancestor_kinds =
ctx.nodes().iter_parents(node.id()).skip(1).map(AstNode::kind);
ctx.nodes().ancestors(node.id()).skip(1).map(AstNode::kind);
let (Some(parent_node_kind), Some(grand_parent_node_kind)) =
(ancestor_kinds.next(), ancestor_kinds.next())
else {

View file

@ -80,7 +80,7 @@ fn run<'a>(possible_jest_node: &PossibleJestNode<'a, '_>, ctx: &LintContext<'a>)
) {
let if_statement_node = ctx
.nodes()
.iter_parents(node.id())
.ancestors(node.id())
.find(|node| matches!(node.kind(), AstKind::IfStatement(_)))?;
let if_statement = if_statement_node.kind().as_if_statement()?;

View file

@ -19,7 +19,7 @@ fn use_prefer_each(span: Span, fn_name: &str) -> OxcDiagnostic {
#[inline]
fn is_in_test(ctx: &LintContext<'_>, id: NodeId) -> bool {
ctx.nodes().iter_parents(id).any(|node| {
ctx.nodes().ancestors(id).any(|node| {
let AstKind::CallExpression(ancestor_call_expr) = node.kind() else { return false };
let Some(ancestor_member_expr) = ancestor_call_expr.callee.as_member_expression() else {
return false;
@ -97,7 +97,7 @@ impl PreferEach {
return;
}
for parent_node in ctx.nodes().iter_parents(node.id()).skip(1) {
for parent_node in ctx.nodes().ancestors(node.id()).skip(1) {
match parent_node.kind() {
AstKind::CallExpression(_) => {
return;

View file

@ -116,7 +116,7 @@ impl RequireLocalTestContextForConcurrentSnapshots {
}
let test_or_describe_node_found =
ctx.nodes().iter_parents(possible_jest_node.node.id()).any(|node| {
ctx.nodes().ancestors(possible_jest_node.node.id()).any(|node| {
if let AstKind::CallExpression(ancestor_call_expr) = node.kind() {
if let Some(ancestor_member_expr) =
ancestor_call_expr.callee.as_member_expression()

View file

@ -2055,12 +2055,12 @@ impl<'a> SemanticBuilder<'a> {
}
fn is_not_expression_statement_parent(&self) -> bool {
for node in self.nodes.iter_parents(self.current_node_id).skip(1) {
for node in self.nodes.ancestors(self.current_node_id).skip(1) {
return match node.kind() {
AstKind::ParenthesizedExpression(_) => continue,
AstKind::ExpressionStatement(_) => {
if self.current_scope_flags().is_arrow() {
if let Some(node) = self.nodes.iter_parents(node.id()).nth(2) {
if let Some(node) = self.nodes.ancestors(node.id()).nth(2) {
// (x) => x++
// ^^^ implicit return, we need to treat `x` as a read reference
if matches!(node.kind(), AstKind::ArrowFunctionExpression(arrow) if arrow.expression)

View file

@ -255,7 +255,7 @@ fn not_allowed_namespace_declaration(span: Span) -> OxcDiagnostic {
pub fn check_ts_module_declaration<'a>(decl: &TSModuleDeclaration<'a>, ctx: &SemanticBuilder<'a>) {
// skip current node
for node in ctx.nodes.iter_parents(ctx.current_node_id).skip(1) {
for node in ctx.nodes.ancestors(ctx.current_node_id).skip(1) {
match node.kind() {
AstKind::Program(_) | AstKind::TSModuleBlock(_) | AstKind::TSModuleDeclaration(_) => {
break;

View file

@ -132,7 +132,7 @@ impl<'a> AstNodes<'a> {
/// The first node produced by this iterator is the first parent of the node
/// pointed to by `node_id`. The last node will usually be a `Program`.
#[inline]
pub fn iter_parents(&self, node_id: NodeId) -> impl Iterator<Item = &AstNode<'a>> + Clone + '_ {
pub fn ancestors(&self, node_id: NodeId) -> impl Iterator<Item = &AstNode<'a>> + Clone + '_ {
AstNodeParentIter { current_node_id: Some(node_id), nodes: self }
}