Skip to content

Commit

Permalink
refactor(semantic): rename ancestors to ancestor_ids (#7215)
Browse files Browse the repository at this point in the history
pure refactor, renaming this method to make it more clear that it returns only IDs, not nodes. in preparation for the next PR.
  • Loading branch information
camchenry committed Nov 9, 2024
1 parent 846711c commit 42171eb
Show file tree
Hide file tree
Showing 14 changed files with 28 additions and 25 deletions.
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 {
ctx.nodes()
.ancestors(node_id)
.ancestor_ids(node_id)
.map(|id| ctx.nodes().get_node(id))
.skip_while(|node| !node.kind().is_function_like())
.nth(1)
Expand Down
2 changes: 1 addition & 1 deletion crates/oxc_linter/src/rules/eslint/no_new.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ impl Rule for NoNew {
return;
};

let mut ancestors = ctx.nodes().ancestors(node.id()).skip(1);
let mut ancestors = ctx.nodes().ancestor_ids(node.id()).skip(1);
let Some(node_id) = ancestors.next() else { return };

let kind = ctx.nodes().kind(node_id);
Expand Down
2 changes: 1 addition & 1 deletion crates/oxc_linter/src/rules/eslint/no_unsafe_finally.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ impl Rule for NoUnsafeFinally {

let nodes = ctx.nodes();
let mut label_inside = false;
for node_id in nodes.ancestors(node.id()) {
for node_id in nodes.ancestor_ids(node.id()) {
let ast_kind = nodes.kind(node_id);

if sentinel_node_type.test(ast_kind) {
Expand Down
2 changes: 1 addition & 1 deletion crates/oxc_linter/src/rules/jest/no_duplicate_hooks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ impl NoDuplicateHooks {

let hook_name = jest_fn_call.name.to_string();
let parent_node_id =
match ctx.nodes().ancestors(node.id()).find(|n| hook_contexts.contains_key(n)) {
match ctx.nodes().ancestor_ids(node.id()).find(|n| hook_contexts.contains_key(n)) {
Some(n) => Some(n),
_ => Some(root_node_id),
};
Expand Down
2 changes: 1 addition & 1 deletion crates/oxc_linter/src/rules/nextjs/no_duplicate_head.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ impl Rule for NoDuplicateHead {
}

if !matches!(
nodes.ancestors(reference.node_id()).nth(2).map(|node_id| nodes.kind(node_id)),
nodes.ancestor_ids(reference.node_id()).nth(2).map(|node_id| nodes.kind(node_id)),
Some(AstKind::JSXOpeningElement(_))
) {
continue;
Expand Down
2 changes: 1 addition & 1 deletion crates/oxc_linter/src/rules/oxc/bad_comparison_sequence.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ fn has_no_bad_comparison_in_parents<'a, 'b>(
node: &'b AstNode<'a>,
ctx: &'b LintContext<'a>,
) -> bool {
for node_id in ctx.nodes().ancestors(node.id()).skip(1) {
for node_id in ctx.nodes().ancestor_ids(node.id()).skip(1) {
let kind = ctx.nodes().kind(node_id);

// `a === b === c === d === e` only produce one error, since `(a === b === c) === d === e` will produce two errors.
Expand Down
2 changes: 1 addition & 1 deletion crates/oxc_linter/src/rules/oxc/missing_throw.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ impl Rule for MissingThrow {

impl MissingThrow {
fn has_missing_throw<'a>(node: &AstNode<'a>, ctx: &LintContext<'a>) -> bool {
let mut node_ancestors = ctx.nodes().ancestors(node.id()).skip(1);
let mut node_ancestors = ctx.nodes().ancestor_ids(node.id()).skip(1);

let Some(node_id) = node_ancestors.next() else {
return false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ impl Rule for PreferAwaitToThen {
// Already inside a yield or await
if ctx
.nodes()
.ancestors(node.id())
.ancestor_ids(node.id())
.any(|node_id| is_inside_yield_or_await(ctx.nodes().get_node(node_id)))
{
return;
Expand Down
2 changes: 1 addition & 1 deletion crates/oxc_linter/src/rules/react/no_is_mounted.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ impl Rule for NoIsMounted {
return;
}

for ancestor in ctx.nodes().ancestors(node.id()).skip(1) {
for ancestor in ctx.nodes().ancestor_ids(node.id()).skip(1) {
if matches!(
ctx.nodes().kind(ancestor),
AstKind::ObjectProperty(_) | AstKind::MethodDefinition(_)
Expand Down
13 changes: 8 additions & 5 deletions crates/oxc_linter/src/rules/react/rules_of_hooks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -324,7 +324,10 @@ fn has_conditional_path_accept_throw(
}

fn parent_func<'a>(nodes: &'a AstNodes<'a>, node: &AstNode) -> Option<&'a AstNode<'a>> {
nodes.ancestors(node.id()).map(|id| nodes.get_node(id)).find(|it| it.kind().is_function_like())
nodes
.ancestor_ids(node.id())
.map(|id| nodes.get_node(id))
.find(|it| it.kind().is_function_like())
}

/// Checks if the `node_id` is a callback argument,
Expand All @@ -346,7 +349,7 @@ fn is_non_react_func_arg(nodes: &AstNodes, node_id: NodeId) -> bool {

fn is_somewhere_inside_component_or_hook(nodes: &AstNodes, node_id: NodeId) -> bool {
nodes
.ancestors(node_id)
.ancestor_ids(node_id)
.map(|id| nodes.get_node(id))
.filter(|node| node.kind().is_function_like())
.map(|node| {
Expand All @@ -372,7 +375,7 @@ fn get_declaration_identifier<'a>(
nodes: &'a AstNodes<'a>,
node_id: NodeId,
) -> Option<Cow<'a, str>> {
nodes.ancestors(node_id).map(|id| nodes.kind(id)).find_map(|kind| {
nodes.ancestor_ids(node_id).map(|id| nodes.kind(id)).find_map(|kind| {
match kind {
// const useHook = () => {};
AstKind::VariableDeclaration(decl) if decl.declarations.len() == 1 => {
Expand All @@ -399,7 +402,7 @@ fn get_declaration_identifier<'a>(

fn is_export_default<'a>(nodes: &'a AstNodes<'a>, node_id: NodeId) -> bool {
nodes
.ancestors(node_id)
.ancestor_ids(node_id)
.map(|id| nodes.get_node(id))
.nth(1)
.is_some_and(|node| matches!(node.kind(), AstKind::ExportDefaultDeclaration(_)))
Expand All @@ -408,7 +411,7 @@ fn is_export_default<'a>(nodes: &'a AstNodes<'a>, node_id: NodeId) -> bool {
/// # Panics
/// `node_id` should always point to a valid `Function`.
fn is_memo_or_forward_ref_callback(nodes: &AstNodes, node_id: NodeId) -> bool {
nodes.ancestors(node_id).map(|id| nodes.get_node(id)).any(|node| {
nodes.ancestor_ids(node_id).map(|id| nodes.get_node(id)).any(|node| {
if let AstKind::CallExpression(call) = node.kind() {
call.callee_name().is_some_and(|name| matches!(name, "forwardRef" | "memo"))
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -618,7 +618,7 @@ fn ancestor_has_return_type<'a>(node: &AstNode<'a>, ctx: &LintContext<'a>) -> bo
return false;
}

for ancestor in ctx.nodes().ancestors(node.id()).skip(1) {
for ancestor in ctx.nodes().ancestor_ids(node.id()).skip(1) {
match ctx.nodes().kind(ancestor) {
AstKind::ArrowFunctionExpression(func) => {
if func.return_type.is_some() {
Expand Down
2 changes: 1 addition & 1 deletion crates/oxc_linter/src/utils/react.rs
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ pub fn get_parent_component<'a, 'b>(
node: &'b AstNode<'a>,
ctx: &'b LintContext<'a>,
) -> Option<&'b AstNode<'a>> {
for node_id in ctx.nodes().ancestors(node.id()) {
for node_id in ctx.nodes().ancestor_ids(node.id()) {
let node = ctx.nodes().get_node(node_id);
if is_es5_component(node) || is_es6_component(node) {
return Some(node);
Expand Down
16 changes: 8 additions & 8 deletions crates/oxc_semantic/src/checker/javascript.rs
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ pub fn check_binding_identifier<'a>(
// LexicalDeclaration : LetOrConst BindingList ;
// * It is a Syntax Error if the BoundNames of BindingList contains "let".
if !strict_mode && ident.name == "let" {
for node_id in ctx.nodes.ancestors(node.id()).skip(1) {
for node_id in ctx.nodes.ancestor_ids(node.id()).skip(1) {
match ctx.nodes.kind(node_id) {
AstKind::VariableDeclaration(decl) if decl.kind.is_lexical() => {
return ctx.error(invalid_let_declaration(decl.kind.as_str(), ident.span));
Expand All @@ -197,7 +197,7 @@ pub fn check_identifier_reference<'a>(
// Static Semantics: AssignmentTargetType
// 1. If this IdentifierReference is contained in strict mode code and StringValue of Identifier is "eval" or "arguments", return invalid.
if ctx.strict_mode() && matches!(ident.name.as_str(), "arguments" | "eval") {
for node_id in ctx.nodes.ancestors(node.id()).skip(1) {
for node_id in ctx.nodes.ancestor_ids(node.id()).skip(1) {
match ctx.nodes.kind(node_id) {
AstKind::AssignmentTarget(_) | AstKind::SimpleAssignmentTarget(_) => {
return ctx.error(unexpected_identifier_assign(&ident.name, ident.span));
Expand All @@ -214,7 +214,7 @@ pub fn check_identifier_reference<'a>(
// It is a Syntax Error if ContainsArguments of ClassStaticBlockStatementList is true.

if ident.name == "arguments" {
for node_id in ctx.nodes.ancestors(node.id()).skip(1) {
for node_id in ctx.nodes.ancestor_ids(node.id()).skip(1) {
match ctx.nodes.kind(node_id) {
AstKind::Function(_) => break,
AstKind::PropertyDefinition(_) => {
Expand Down Expand Up @@ -567,7 +567,7 @@ pub fn check_break_statement<'a>(
ctx: &SemanticBuilder<'a>,
) {
// It is a Syntax Error if this BreakStatement is not nested, directly or indirectly (but not crossing function or static initialization block boundaries), within an IterationStatement or a SwitchStatement.
for node_id in ctx.nodes.ancestors(node.id()).skip(1) {
for node_id in ctx.nodes.ancestor_ids(node.id()).skip(1) {
match ctx.nodes.kind(node_id) {
AstKind::Program(_) => {
return stmt.label.as_ref().map_or_else(
Expand Down Expand Up @@ -613,7 +613,7 @@ pub fn check_continue_statement<'a>(
ctx: &SemanticBuilder<'a>,
) {
// It is a Syntax Error if this ContinueStatement is not nested, directly or indirectly (but not crossing function or static initialization block boundaries), within an IterationStatement.
for node_id in ctx.nodes.ancestors(node.id()).skip(1) {
for node_id in ctx.nodes.ancestor_ids(node.id()).skip(1) {
match ctx.nodes.kind(node_id) {
AstKind::Program(_) => {
return stmt.label.as_ref().map_or_else(
Expand Down Expand Up @@ -666,7 +666,7 @@ pub fn check_labeled_statement<'a>(
node: &AstNode<'a>,
ctx: &SemanticBuilder<'a>,
) {
for node_id in ctx.nodes.ancestors(node.id()).skip(1) {
for node_id in ctx.nodes.ancestor_ids(node.id()).skip(1) {
match ctx.nodes.kind(node_id) {
// label cannot cross boundary on function or static block
AstKind::Function(_) | AstKind::StaticBlock(_) | AstKind::Program(_) => break,
Expand Down Expand Up @@ -863,7 +863,7 @@ pub fn check_super<'a>(sup: &Super, node: &AstNode<'a>, ctx: &SemanticBuilder<'a

// skip(1) is the self `Super`
// skip(2) is the parent `CallExpression` or `NewExpression`
for node_id in ctx.nodes.ancestors(node.id()).skip(2) {
for node_id in ctx.nodes.ancestor_ids(node.id()).skip(2) {
match ctx.nodes.kind(node_id) {
AstKind::MethodDefinition(def) => {
// ClassElement : MethodDefinition
Expand Down Expand Up @@ -1094,7 +1094,7 @@ pub fn check_unary_expression<'a>(
}

fn is_in_formal_parameters<'a>(node: &AstNode<'a>, ctx: &SemanticBuilder<'a>) -> bool {
for node_id in ctx.nodes.ancestors(node.id()).skip(1) {
for node_id in ctx.nodes.ancestor_ids(node.id()).skip(1) {
match ctx.nodes.kind(node_id) {
AstKind::FormalParameter(_) => return true,
AstKind::Program(_) | AstKind::Function(_) | AstKind::ArrowFunctionExpression(_) => {
Expand Down
2 changes: 1 addition & 1 deletion crates/oxc_semantic/src/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@ impl<'a> AstNodes<'a> {
/// pointed to by `node_id`. The last node will always be a [`Program`].
///
/// [`Program`]: oxc_ast::ast::Program
pub fn ancestors(&self, node_id: NodeId) -> impl Iterator<Item = NodeId> + '_ {
pub fn ancestor_ids(&self, node_id: NodeId) -> impl Iterator<Item = NodeId> + '_ {
let parent_ids = &self.parent_ids;
std::iter::successors(Some(node_id), |&node_id| parent_ids[node_id])
}
Expand Down

0 comments on commit 42171eb

Please sign in to comment.