Skip to content

Commit 26249cf

Browse files
committed
feat(ast): add AstKind::ident_reference_is_assigned_to_in_parent method (#12597)
Similar to #12596. Add a method `AstKind::ident_reference_is_assigned_to_in_parent`. Given an `AstKind` representing an `IdentifierReference`, and an `AstKind` representing its parent, this method determines whether the identifier is being assigned to. Covers all possible positions where an `IdentifierReference` gets assigned to - `x = value`, `x++`, `[...x] = arr` etc. Note: This method is slightly different to `MemberExpressionKind::is_assigned_to_in_parent` - it includes additional match arm for `AssignmentTargetPropertyIdentifier` as parent. This can't be parent of a `MemberExpression`, but *can* be the parent of an `IdentifierReference`.
1 parent 106f56f commit 26249cf

File tree

1 file changed

+59
-0
lines changed

1 file changed

+59
-0
lines changed

crates/oxc_ast/src/ast_kind_impl.rs

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,65 @@ impl<'a> AstKind<'a> {
184184
Expression::V8IntrinsicExpression(e) => Self::V8IntrinsicExpression(e),
185185
}
186186
}
187+
188+
/// Given an [`AstKind`] which is an [`IdentifierReference`], and [`AstKind`] representing its parent node,
189+
/// returns `true` if the identifier is assigned to.
190+
///
191+
/// Note: `parent` must be the parent node of the identifier, and `self` must be an `IdentifierReference`.
192+
/// This method does not check those things, and may return incorrect results if either is not true.
193+
//
194+
// This method's implementation is identical to `MemberExpressionKind::is_assigned_to_in_parent`
195+
// except for addition of `AssignmentTargetPropertyIdentifier`.
196+
pub fn ident_reference_is_assigned_to_in_parent(&self, parent: &AstKind<'a>) -> bool {
197+
debug_assert!(matches!(self, AstKind::IdentifierReference(_)));
198+
199+
#[expect(clippy::match_same_arms)]
200+
match parent {
201+
// `ident++`, `--ident`
202+
// `UpdateExpression` has only 1 field containing child node - `argument`.
203+
AstKind::UpdateExpression(_) => true,
204+
// `[ident] = arr`
205+
// `ArrayAssignmentTarget` has only 1 field containing child nodes - `elements`.
206+
AstKind::ArrayAssignmentTarget(_) => true,
207+
// `[...ident] = arr`, `({ ...ident } = obj)`
208+
// `AssignmentTargetRest` has only 1 field containing child node - `target`.
209+
AstKind::AssignmentTargetRest(_) => true,
210+
// `ident = value`
211+
// Only match if ident is on left
212+
// - not on right e.g. `assignee = ident`.
213+
AstKind::AssignmentExpression(assign_expr) => {
214+
assign_expr.left.address() == self.address()
215+
}
216+
// `[ident = value] = arr`, `({ prop: ident = value } = obj)`
217+
// Only match if ident is the assignee
218+
// - not the default value e.g. `[assignee = ident] = arr`.
219+
AstKind::AssignmentTargetWithDefault(assign_target) => {
220+
assign_target.binding.address() == self.address()
221+
}
222+
// `({ ident } = obj)`
223+
// Only match if ident is the assignee
224+
// - not the default value e.g. `({ assignee = ident } = obj)`.
225+
AstKind::AssignmentTargetPropertyIdentifier(assign_target) => {
226+
let binding = &assign_target.binding;
227+
Address::from_ptr(binding) == self.address()
228+
}
229+
// `({ prop: ident } = obj)`
230+
// Only match if ident is the assignee
231+
// - not computed prop key e.g. `({ [ident]: assignee } = obj)`.
232+
AstKind::AssignmentTargetPropertyProperty(assign_target) => {
233+
assign_target.binding.address() == self.address()
234+
}
235+
// `for (ident in obj)`
236+
// Only match if ident is on left
237+
// - not object being iterated e.g. `for (assignee in ident)`
238+
AstKind::ForInStatement(for_stmt) => for_stmt.left.address() == self.address(),
239+
// `for (ident of obj)`
240+
// Only match if ident is on left
241+
// - not array being iterated e.g. `for (assignee of ident)`
242+
AstKind::ForOfStatement(for_stmt) => for_stmt.left.address() == self.address(),
243+
_ => false,
244+
}
245+
}
187246
}
188247

189248
impl AstKind<'_> {

0 commit comments

Comments
 (0)