use oxc::allocator::TakeIn;
use oxc::ast::ast::Expression;
use oxc_traverse::TraverseCtx;
use crate::ast::query;
pub fn try_fold<'a>(
expr: &mut Expression<'a>,
ctx: &mut TraverseCtx<'a, ()>,
) -> Option<usize> {
{
let Expression::SequenceExpression(seq) = &*expr else {
return None;
};
if seq.expressions.len() <= 1 {
return None;
}
let len = seq.expressions.len();
let all_prefix_pure = seq.expressions[..len - 1]
.iter()
.all(query::is_side_effect_free);
if !all_prefix_pure {
return None;
}
}
let last = {
let Expression::SequenceExpression(seq) = &mut *expr else {
return None;
};
seq.expressions.last_mut()?.take_in(ctx.ast.allocator)
};
*expr = last;
Some(1)
}
#[cfg(test)]
mod tests {
use super::super::test_utils::fold;
#[test]
fn test_pure_prefix() {
let result = fold("(1, 2, 42);");
assert!(result.contains("42"), "should fold to last: {result}");
assert!(!result.contains(","), "should not have comma: {result}");
}
#[test]
fn test_effectful_prefix_not_folded() {
let result = fold("(foo(), 42);");
assert!(result.contains(","), "effectful prefix should not fold: {result}");
}
#[test]
fn test_single_element_not_folded() {
let result = fold("(42);");
assert!(result.contains("42"), "single element unchanged: {result}");
}
}