mirror of
https://github.com/danbulant/oxc
synced 2026-05-24 12:21:58 +00:00
refactor(semantic): rename ancestors to ancestor_ids (#7215)
pure refactor, renaming this method to make it more clear that it returns only IDs, not nodes. in preparation for the next PR.
This commit is contained in:
parent
846711cf41
commit
42171eba94
14 changed files with 28 additions and 25 deletions
|
|
@ -67,7 +67,7 @@ fn is_constructor(node: &AstNode<'_>) -> bool {
|
||||||
|
|
||||||
fn is_definitely_in_constructor(ctx: &LintContext, node_id: NodeId) -> bool {
|
fn is_definitely_in_constructor(ctx: &LintContext, node_id: NodeId) -> bool {
|
||||||
ctx.nodes()
|
ctx.nodes()
|
||||||
.ancestors(node_id)
|
.ancestor_ids(node_id)
|
||||||
.map(|id| ctx.nodes().get_node(id))
|
.map(|id| ctx.nodes().get_node(id))
|
||||||
.skip_while(|node| !node.kind().is_function_like())
|
.skip_while(|node| !node.kind().is_function_like())
|
||||||
.nth(1)
|
.nth(1)
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,7 @@ impl Rule for NoNew {
|
||||||
return;
|
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 Some(node_id) = ancestors.next() else { return };
|
||||||
|
|
||||||
let kind = ctx.nodes().kind(node_id);
|
let kind = ctx.nodes().kind(node_id);
|
||||||
|
|
|
||||||
|
|
@ -69,7 +69,7 @@ impl Rule for NoUnsafeFinally {
|
||||||
|
|
||||||
let nodes = ctx.nodes();
|
let nodes = ctx.nodes();
|
||||||
let mut label_inside = false;
|
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);
|
let ast_kind = nodes.kind(node_id);
|
||||||
|
|
||||||
if sentinel_node_type.test(ast_kind) {
|
if sentinel_node_type.test(ast_kind) {
|
||||||
|
|
|
||||||
|
|
@ -143,7 +143,7 @@ impl NoDuplicateHooks {
|
||||||
|
|
||||||
let hook_name = jest_fn_call.name.to_string();
|
let hook_name = jest_fn_call.name.to_string();
|
||||||
let parent_node_id =
|
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(n) => Some(n),
|
||||||
_ => Some(root_node_id),
|
_ => Some(root_node_id),
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -79,7 +79,7 @@ impl Rule for NoDuplicateHead {
|
||||||
}
|
}
|
||||||
|
|
||||||
if !matches!(
|
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(_))
|
Some(AstKind::JSXOpeningElement(_))
|
||||||
) {
|
) {
|
||||||
continue;
|
continue;
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,7 @@ fn has_no_bad_comparison_in_parents<'a, 'b>(
|
||||||
node: &'b AstNode<'a>,
|
node: &'b AstNode<'a>,
|
||||||
ctx: &'b LintContext<'a>,
|
ctx: &'b LintContext<'a>,
|
||||||
) -> bool {
|
) -> 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);
|
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.
|
// `a === b === c === d === e` only produce one error, since `(a === b === c) === d === e` will produce two errors.
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,7 @@ impl Rule for MissingThrow {
|
||||||
|
|
||||||
impl MissingThrow {
|
impl MissingThrow {
|
||||||
fn has_missing_throw<'a>(node: &AstNode<'a>, ctx: &LintContext<'a>) -> bool {
|
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 {
|
let Some(node_id) = node_ancestors.next() else {
|
||||||
return false;
|
return false;
|
||||||
|
|
|
||||||
|
|
@ -53,7 +53,7 @@ impl Rule for PreferAwaitToThen {
|
||||||
// Already inside a yield or await
|
// Already inside a yield or await
|
||||||
if ctx
|
if ctx
|
||||||
.nodes()
|
.nodes()
|
||||||
.ancestors(node.id())
|
.ancestor_ids(node.id())
|
||||||
.any(|node_id| is_inside_yield_or_await(ctx.nodes().get_node(node_id)))
|
.any(|node_id| is_inside_yield_or_await(ctx.nodes().get_node(node_id)))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
|
|
@ -60,7 +60,7 @@ impl Rule for NoIsMounted {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for ancestor in ctx.nodes().ancestors(node.id()).skip(1) {
|
for ancestor in ctx.nodes().ancestor_ids(node.id()).skip(1) {
|
||||||
if matches!(
|
if matches!(
|
||||||
ctx.nodes().kind(ancestor),
|
ctx.nodes().kind(ancestor),
|
||||||
AstKind::ObjectProperty(_) | AstKind::MethodDefinition(_)
|
AstKind::ObjectProperty(_) | AstKind::MethodDefinition(_)
|
||||||
|
|
|
||||||
|
|
@ -324,7 +324,10 @@ fn has_conditional_path_accept_throw(
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parent_func<'a>(nodes: &'a AstNodes<'a>, node: &AstNode) -> Option<&'a AstNode<'a>> {
|
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,
|
/// Checks if the `node_id` is a callback argument,
|
||||||
|
|
@ -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 {
|
fn is_somewhere_inside_component_or_hook(nodes: &AstNodes, node_id: NodeId) -> bool {
|
||||||
nodes
|
nodes
|
||||||
.ancestors(node_id)
|
.ancestor_ids(node_id)
|
||||||
.map(|id| nodes.get_node(id))
|
.map(|id| nodes.get_node(id))
|
||||||
.filter(|node| node.kind().is_function_like())
|
.filter(|node| node.kind().is_function_like())
|
||||||
.map(|node| {
|
.map(|node| {
|
||||||
|
|
@ -372,7 +375,7 @@ fn get_declaration_identifier<'a>(
|
||||||
nodes: &'a AstNodes<'a>,
|
nodes: &'a AstNodes<'a>,
|
||||||
node_id: NodeId,
|
node_id: NodeId,
|
||||||
) -> Option<Cow<'a, str>> {
|
) -> 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 {
|
match kind {
|
||||||
// const useHook = () => {};
|
// const useHook = () => {};
|
||||||
AstKind::VariableDeclaration(decl) if decl.declarations.len() == 1 => {
|
AstKind::VariableDeclaration(decl) if decl.declarations.len() == 1 => {
|
||||||
|
|
@ -399,7 +402,7 @@ fn get_declaration_identifier<'a>(
|
||||||
|
|
||||||
fn is_export_default<'a>(nodes: &'a AstNodes<'a>, node_id: NodeId) -> bool {
|
fn is_export_default<'a>(nodes: &'a AstNodes<'a>, node_id: NodeId) -> bool {
|
||||||
nodes
|
nodes
|
||||||
.ancestors(node_id)
|
.ancestor_ids(node_id)
|
||||||
.map(|id| nodes.get_node(id))
|
.map(|id| nodes.get_node(id))
|
||||||
.nth(1)
|
.nth(1)
|
||||||
.is_some_and(|node| matches!(node.kind(), AstKind::ExportDefaultDeclaration(_)))
|
.is_some_and(|node| matches!(node.kind(), AstKind::ExportDefaultDeclaration(_)))
|
||||||
|
|
@ -408,7 +411,7 @@ fn is_export_default<'a>(nodes: &'a AstNodes<'a>, node_id: NodeId) -> bool {
|
||||||
/// # Panics
|
/// # Panics
|
||||||
/// `node_id` should always point to a valid `Function`.
|
/// `node_id` should always point to a valid `Function`.
|
||||||
fn is_memo_or_forward_ref_callback(nodes: &AstNodes, node_id: NodeId) -> bool {
|
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() {
|
if let AstKind::CallExpression(call) = node.kind() {
|
||||||
call.callee_name().is_some_and(|name| matches!(name, "forwardRef" | "memo"))
|
call.callee_name().is_some_and(|name| matches!(name, "forwardRef" | "memo"))
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -618,7 +618,7 @@ fn ancestor_has_return_type<'a>(node: &AstNode<'a>, ctx: &LintContext<'a>) -> bo
|
||||||
return false;
|
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) {
|
match ctx.nodes().kind(ancestor) {
|
||||||
AstKind::ArrowFunctionExpression(func) => {
|
AstKind::ArrowFunctionExpression(func) => {
|
||||||
if func.return_type.is_some() {
|
if func.return_type.is_some() {
|
||||||
|
|
|
||||||
|
|
@ -195,7 +195,7 @@ pub fn get_parent_component<'a, 'b>(
|
||||||
node: &'b AstNode<'a>,
|
node: &'b AstNode<'a>,
|
||||||
ctx: &'b LintContext<'a>,
|
ctx: &'b LintContext<'a>,
|
||||||
) -> Option<&'b AstNode<'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);
|
let node = ctx.nodes().get_node(node_id);
|
||||||
if is_es5_component(node) || is_es6_component(node) {
|
if is_es5_component(node) || is_es6_component(node) {
|
||||||
return Some(node);
|
return Some(node);
|
||||||
|
|
|
||||||
|
|
@ -171,7 +171,7 @@ pub fn check_binding_identifier<'a>(
|
||||||
// LexicalDeclaration : LetOrConst BindingList ;
|
// LexicalDeclaration : LetOrConst BindingList ;
|
||||||
// * It is a Syntax Error if the BoundNames of BindingList contains "let".
|
// * It is a Syntax Error if the BoundNames of BindingList contains "let".
|
||||||
if !strict_mode && ident.name == "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) {
|
match ctx.nodes.kind(node_id) {
|
||||||
AstKind::VariableDeclaration(decl) if decl.kind.is_lexical() => {
|
AstKind::VariableDeclaration(decl) if decl.kind.is_lexical() => {
|
||||||
return ctx.error(invalid_let_declaration(decl.kind.as_str(), ident.span));
|
return ctx.error(invalid_let_declaration(decl.kind.as_str(), ident.span));
|
||||||
|
|
@ -197,7 +197,7 @@ pub fn check_identifier_reference<'a>(
|
||||||
// Static Semantics: AssignmentTargetType
|
// Static Semantics: AssignmentTargetType
|
||||||
// 1. If this IdentifierReference is contained in strict mode code and StringValue of Identifier is "eval" or "arguments", return invalid.
|
// 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") {
|
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) {
|
match ctx.nodes.kind(node_id) {
|
||||||
AstKind::AssignmentTarget(_) | AstKind::SimpleAssignmentTarget(_) => {
|
AstKind::AssignmentTarget(_) | AstKind::SimpleAssignmentTarget(_) => {
|
||||||
return ctx.error(unexpected_identifier_assign(&ident.name, ident.span));
|
return ctx.error(unexpected_identifier_assign(&ident.name, ident.span));
|
||||||
|
|
@ -214,7 +214,7 @@ pub fn check_identifier_reference<'a>(
|
||||||
// It is a Syntax Error if ContainsArguments of ClassStaticBlockStatementList is true.
|
// It is a Syntax Error if ContainsArguments of ClassStaticBlockStatementList is true.
|
||||||
|
|
||||||
if ident.name == "arguments" {
|
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) {
|
match ctx.nodes.kind(node_id) {
|
||||||
AstKind::Function(_) => break,
|
AstKind::Function(_) => break,
|
||||||
AstKind::PropertyDefinition(_) => {
|
AstKind::PropertyDefinition(_) => {
|
||||||
|
|
@ -567,7 +567,7 @@ pub fn check_break_statement<'a>(
|
||||||
ctx: &SemanticBuilder<'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.
|
// 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) {
|
match ctx.nodes.kind(node_id) {
|
||||||
AstKind::Program(_) => {
|
AstKind::Program(_) => {
|
||||||
return stmt.label.as_ref().map_or_else(
|
return stmt.label.as_ref().map_or_else(
|
||||||
|
|
@ -613,7 +613,7 @@ pub fn check_continue_statement<'a>(
|
||||||
ctx: &SemanticBuilder<'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.
|
// 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) {
|
match ctx.nodes.kind(node_id) {
|
||||||
AstKind::Program(_) => {
|
AstKind::Program(_) => {
|
||||||
return stmt.label.as_ref().map_or_else(
|
return stmt.label.as_ref().map_or_else(
|
||||||
|
|
@ -666,7 +666,7 @@ pub fn check_labeled_statement<'a>(
|
||||||
node: &AstNode<'a>,
|
node: &AstNode<'a>,
|
||||||
ctx: &SemanticBuilder<'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) {
|
match ctx.nodes.kind(node_id) {
|
||||||
// label cannot cross boundary on function or static block
|
// label cannot cross boundary on function or static block
|
||||||
AstKind::Function(_) | AstKind::StaticBlock(_) | AstKind::Program(_) => break,
|
AstKind::Function(_) | AstKind::StaticBlock(_) | AstKind::Program(_) => break,
|
||||||
|
|
@ -863,7 +863,7 @@ pub fn check_super<'a>(sup: &Super, node: &AstNode<'a>, ctx: &SemanticBuilder<'a
|
||||||
|
|
||||||
// skip(1) is the self `Super`
|
// skip(1) is the self `Super`
|
||||||
// skip(2) is the parent `CallExpression` or `NewExpression`
|
// 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) {
|
match ctx.nodes.kind(node_id) {
|
||||||
AstKind::MethodDefinition(def) => {
|
AstKind::MethodDefinition(def) => {
|
||||||
// ClassElement : MethodDefinition
|
// ClassElement : MethodDefinition
|
||||||
|
|
@ -1094,7 +1094,7 @@ pub fn check_unary_expression<'a>(
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_in_formal_parameters<'a>(node: &AstNode<'a>, ctx: &SemanticBuilder<'a>) -> bool {
|
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) {
|
match ctx.nodes.kind(node_id) {
|
||||||
AstKind::FormalParameter(_) => return true,
|
AstKind::FormalParameter(_) => return true,
|
||||||
AstKind::Program(_) | AstKind::Function(_) | AstKind::ArrowFunctionExpression(_) => {
|
AstKind::Program(_) | AstKind::Function(_) | AstKind::ArrowFunctionExpression(_) => {
|
||||||
|
|
|
||||||
|
|
@ -220,7 +220,7 @@ impl<'a> AstNodes<'a> {
|
||||||
/// pointed to by `node_id`. The last node will always be a [`Program`].
|
/// pointed to by `node_id`. The last node will always be a [`Program`].
|
||||||
///
|
///
|
||||||
/// [`Program`]: oxc_ast::ast::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;
|
let parent_ids = &self.parent_ids;
|
||||||
std::iter::successors(Some(node_id), |&node_id| parent_ids[node_id])
|
std::iter::successors(Some(node_id), |&node_id| parent_ids[node_id])
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue