1use bumpalo::Bump;
68
69use crate::ast::*;
70
71pub trait Fold<'src> {
83 fn fold_program<'new>(
85 &mut self,
86 arena: &'new Bump,
87 program: &Program<'_, 'src>,
88 ) -> Program<'new, 'src> {
89 fold_program(self, arena, program)
90 }
91
92 fn fold_stmt<'new>(&mut self, arena: &'new Bump, stmt: &Stmt<'_, 'src>) -> Stmt<'new, 'src> {
94 fold_stmt(self, arena, stmt)
95 }
96
97 fn fold_stmts<'new>(
100 &mut self,
101 arena: &'new Bump,
102 stmts: &[Stmt<'_, 'src>],
103 ) -> ArenaVec<'new, Stmt<'new, 'src>> {
104 fold_stmts(self, arena, stmts)
105 }
106
107 fn fold_block<'new>(
109 &mut self,
110 arena: &'new Bump,
111 block: &Block<'_, 'src>,
112 ) -> Block<'new, 'src> {
113 fold_block(self, arena, block)
114 }
115
116 fn fold_expr<'new>(&mut self, arena: &'new Bump, expr: &Expr<'_, 'src>) -> Expr<'new, 'src> {
118 fold_expr(self, arena, expr)
119 }
120
121 fn fold_param<'new>(
123 &mut self,
124 arena: &'new Bump,
125 param: &Param<'_, 'src>,
126 ) -> Param<'new, 'src> {
127 fold_param(self, arena, param)
128 }
129
130 fn fold_arg<'new>(&mut self, arena: &'new Bump, arg: &Arg<'_, 'src>) -> Arg<'new, 'src> {
132 fold_arg(self, arena, arg)
133 }
134
135 fn fold_class_member<'new>(
137 &mut self,
138 arena: &'new Bump,
139 member: &ClassMember<'_, 'src>,
140 ) -> ClassMember<'new, 'src> {
141 fold_class_member(self, arena, member)
142 }
143
144 fn fold_enum_member<'new>(
146 &mut self,
147 arena: &'new Bump,
148 member: &EnumMember<'_, 'src>,
149 ) -> EnumMember<'new, 'src> {
150 fold_enum_member(self, arena, member)
151 }
152
153 fn fold_property_hook<'new>(
155 &mut self,
156 arena: &'new Bump,
157 hook: &PropertyHook<'_, 'src>,
158 ) -> PropertyHook<'new, 'src> {
159 fold_property_hook(self, arena, hook)
160 }
161
162 fn fold_type_hint<'new>(
164 &mut self,
165 arena: &'new Bump,
166 type_hint: &TypeHint<'_, 'src>,
167 ) -> TypeHint<'new, 'src> {
168 fold_type_hint(self, arena, type_hint)
169 }
170
171 fn fold_attribute<'new>(
173 &mut self,
174 arena: &'new Bump,
175 attribute: &Attribute<'_, 'src>,
176 ) -> Attribute<'new, 'src> {
177 fold_attribute(self, arena, attribute)
178 }
179
180 fn fold_catch_clause<'new>(
182 &mut self,
183 arena: &'new Bump,
184 catch: &CatchClause<'_, 'src>,
185 ) -> CatchClause<'new, 'src> {
186 fold_catch_clause(self, arena, catch)
187 }
188
189 fn fold_match_arm<'new>(
191 &mut self,
192 arena: &'new Bump,
193 arm: &MatchArm<'_, 'src>,
194 ) -> MatchArm<'new, 'src> {
195 fold_match_arm(self, arena, arm)
196 }
197
198 fn fold_closure_use_var(
200 &mut self,
201 _arena: &Bump,
202 var: &ClosureUseVar<'src>,
203 ) -> ClosureUseVar<'src> {
204 var.clone()
205 }
206
207 fn fold_trait_use<'new>(
209 &mut self,
210 arena: &'new Bump,
211 trait_use: &TraitUseDecl<'_, 'src>,
212 ) -> TraitUseDecl<'new, 'src> {
213 fold_trait_use(self, arena, trait_use)
214 }
215
216 fn fold_trait_adaptation<'new>(
218 &mut self,
219 arena: &'new Bump,
220 adaptation: &TraitAdaptation<'_, 'src>,
221 ) -> TraitAdaptation<'new, 'src> {
222 fold_trait_adaptation(self, arena, adaptation)
223 }
224
225 fn fold_name<'new>(&mut self, arena: &'new Bump, name: &Name<'_, 'src>) -> Name<'new, 'src> {
227 fold_name(self, arena, name)
228 }
229}
230
231pub fn fold_program<'new, 'src, F: Fold<'src> + ?Sized>(
237 folder: &mut F,
238 arena: &'new Bump,
239 program: &Program<'_, 'src>,
240) -> Program<'new, 'src> {
241 Program {
242 stmts: folder.fold_stmts(arena, &program.stmts),
243 span: program.span,
244 }
245}
246
247pub fn fold_stmt<'new, 'src, F: Fold<'src> + ?Sized>(
249 folder: &mut F,
250 arena: &'new Bump,
251 stmt: &Stmt<'_, 'src>,
252) -> Stmt<'new, 'src> {
253 let kind = match &stmt.kind {
254 StmtKind::Expression(expr) => {
255 StmtKind::Expression(arena.alloc(folder.fold_expr(arena, expr)))
256 }
257 StmtKind::Echo(exprs) => StmtKind::Echo(fold_exprs(folder, arena, exprs)),
258 StmtKind::Return(expr) => {
259 StmtKind::Return(expr.map(|e| &*arena.alloc(folder.fold_expr(arena, e))))
260 }
261 StmtKind::Block(block) => StmtKind::Block(arena.alloc(folder.fold_block(arena, block))),
262 StmtKind::If(if_stmt) => {
263 let mut elseif_branches =
264 ArenaVec::with_capacity_in(if_stmt.elseif_branches.len(), arena);
265 for branch in if_stmt.elseif_branches.iter() {
266 elseif_branches.push(ElseIfBranch {
267 condition: folder.fold_expr(arena, &branch.condition),
268 body: folder.fold_stmt(arena, &branch.body),
269 span: branch.span,
270 });
271 }
272 let new_if = arena.alloc(IfStmt {
273 condition: folder.fold_expr(arena, &if_stmt.condition),
274 then_branch: arena.alloc(folder.fold_stmt(arena, if_stmt.then_branch)),
275 elseif_branches,
276 else_branch: if_stmt
277 .else_branch
278 .map(|b| &*arena.alloc(folder.fold_stmt(arena, b))),
279 else_kw_span: if_stmt.else_kw_span,
280 uses_alternative: if_stmt.uses_alternative,
281 });
282 StmtKind::If(new_if)
283 }
284 StmtKind::While(w) => {
285 let new_w = arena.alloc(WhileStmt {
286 condition: folder.fold_expr(arena, &w.condition),
287 body: arena.alloc(folder.fold_stmt(arena, w.body)),
288 uses_alternative: w.uses_alternative,
289 });
290 StmtKind::While(new_w)
291 }
292 StmtKind::For(f) => {
293 let new_f = arena.alloc(ForStmt {
294 init: fold_exprs(folder, arena, &f.init),
295 condition: fold_exprs(folder, arena, &f.condition),
296 update: fold_exprs(folder, arena, &f.update),
297 body: arena.alloc(folder.fold_stmt(arena, f.body)),
298 uses_alternative: f.uses_alternative,
299 });
300 StmtKind::For(new_f)
301 }
302 StmtKind::Foreach(fe) => {
303 let new_fe = arena.alloc(ForeachStmt {
304 expr: folder.fold_expr(arena, &fe.expr),
305 key: fe.key.as_ref().map(|k| folder.fold_expr(arena, k)),
306 key_by_ref: fe.key_by_ref,
307 value: folder.fold_expr(arena, &fe.value),
308 by_ref: fe.by_ref,
309 by_ref_span: fe.by_ref_span,
310 body: arena.alloc(folder.fold_stmt(arena, fe.body)),
311 uses_alternative: fe.uses_alternative,
312 });
313 StmtKind::Foreach(new_fe)
314 }
315 StmtKind::DoWhile(dw) => {
316 let new_dw = arena.alloc(DoWhileStmt {
317 body: arena.alloc(folder.fold_stmt(arena, dw.body)),
318 condition: folder.fold_expr(arena, &dw.condition),
319 });
320 StmtKind::DoWhile(new_dw)
321 }
322 StmtKind::Function(func) => {
323 StmtKind::Function(arena.alloc(fold_function_decl(folder, arena, func)))
324 }
325 StmtKind::Break(expr) => {
326 StmtKind::Break(expr.map(|e| &*arena.alloc(folder.fold_expr(arena, e))))
327 }
328 StmtKind::Continue(expr) => {
329 StmtKind::Continue(expr.map(|e| &*arena.alloc(folder.fold_expr(arena, e))))
330 }
331 StmtKind::Switch(sw) => {
332 let mut cases = ArenaVec::with_capacity_in(sw.body.cases.len(), arena);
333 for case in sw.body.cases.iter() {
334 cases.push(SwitchCase {
335 value: case.value.as_ref().map(|v| folder.fold_expr(arena, v)),
336 body: folder.fold_stmts(arena, &case.body),
337 span: case.span,
338 });
339 }
340 let new_sw = arena.alloc(SwitchStmt {
341 expr: folder.fold_expr(arena, &sw.expr),
342 body: SwitchBody {
343 cases,
344 span: sw.body.span,
345 },
346 uses_alternative: sw.uses_alternative,
347 });
348 StmtKind::Switch(new_sw)
349 }
350 StmtKind::Goto(ident) => StmtKind::Goto(*ident),
351 StmtKind::Label(ident) => StmtKind::Label(*ident),
352 StmtKind::Declare(decl) => {
353 let mut directives = ArenaVec::with_capacity_in(decl.directives.len(), arena);
354 for (name, expr) in decl.directives.iter() {
355 directives.push((*name, folder.fold_expr(arena, expr)));
356 }
357 let new_decl = arena.alloc(DeclareStmt {
358 directives,
359 body: decl.body.map(|b| &*arena.alloc(folder.fold_stmt(arena, b))),
360 uses_alternative: decl.uses_alternative,
361 });
362 StmtKind::Declare(new_decl)
363 }
364 StmtKind::Unset(exprs) => StmtKind::Unset(fold_exprs(folder, arena, exprs)),
365 StmtKind::Throw(expr) => StmtKind::Throw(arena.alloc(folder.fold_expr(arena, expr))),
366 StmtKind::TryCatch(tc) => {
367 let mut catches = ArenaVec::with_capacity_in(tc.catches.len(), arena);
368 for catch in tc.catches.iter() {
369 catches.push(folder.fold_catch_clause(arena, catch));
370 }
371 let new_tc = arena.alloc(TryCatchStmt {
372 body: arena.alloc(folder.fold_block(arena, tc.body)),
373 catches,
374 finally: tc
375 .finally
376 .map(|f| &*arena.alloc(folder.fold_block(arena, f))),
377 finally_kw_span: tc.finally_kw_span,
378 });
379 StmtKind::TryCatch(new_tc)
380 }
381 StmtKind::Global(exprs) => StmtKind::Global(fold_exprs(folder, arena, exprs)),
382 StmtKind::Class(class) => {
383 StmtKind::Class(arena.alloc(fold_class_decl(folder, arena, class)))
384 }
385 StmtKind::Interface(iface) => {
386 StmtKind::Interface(arena.alloc(fold_interface_decl(folder, arena, iface)))
387 }
388 StmtKind::Trait(t) => StmtKind::Trait(arena.alloc(fold_trait_decl(folder, arena, t))),
389 StmtKind::Enum(e) => StmtKind::Enum(arena.alloc(fold_enum_decl(folder, arena, e))),
390 StmtKind::Namespace(ns) => {
391 let new_ns = arena.alloc(NamespaceDecl {
392 name: ns.name.as_ref().map(|n| folder.fold_name(arena, n)),
393 body: match &ns.body {
394 NamespaceBody::Braced(block) => {
395 NamespaceBody::Braced(arena.alloc(folder.fold_block(arena, block)))
396 }
397 NamespaceBody::Simple => NamespaceBody::Simple,
398 },
399 });
400 StmtKind::Namespace(new_ns)
401 }
402 StmtKind::Use(use_decl) => {
403 let mut uses = ArenaVec::with_capacity_in(use_decl.uses.len(), arena);
404 for item in use_decl.uses.iter() {
405 uses.push(UseItem {
406 name: folder.fold_name(arena, &item.name),
407 alias: item.alias,
408 kind: item.kind,
409 span: item.span,
410 });
411 }
412 let new_use = arena.alloc(UseDecl {
413 kind: use_decl.kind,
414 uses,
415 });
416 StmtKind::Use(new_use)
417 }
418 StmtKind::Const(items) => {
419 let mut new_items = ArenaVec::with_capacity_in(items.len(), arena);
420 for item in items.iter() {
421 new_items.push(ConstItem {
422 name: item.name,
423 value: folder.fold_expr(arena, &item.value),
424 attributes: fold_attrs(folder, arena, &item.attributes),
425 span: item.span,
426 doc_comment: item.doc_comment.as_ref().map(fold_comment),
427 });
428 }
429 StmtKind::Const(new_items)
430 }
431 StmtKind::StaticVar(vars) => {
432 let mut new_vars = ArenaVec::with_capacity_in(vars.len(), arena);
433 for var in vars.iter() {
434 new_vars.push(StaticVar {
435 name: var.name,
436 default: var.default.as_ref().map(|d| folder.fold_expr(arena, d)),
437 span: var.span,
438 });
439 }
440 StmtKind::StaticVar(new_vars)
441 }
442 StmtKind::HaltCompiler(s) => StmtKind::HaltCompiler(s),
443 StmtKind::Nop => StmtKind::Nop,
444 StmtKind::InlineHtml(s) => StmtKind::InlineHtml(s),
445 StmtKind::Error => StmtKind::Error,
446 };
447 Stmt {
448 kind,
449 span: stmt.span,
450 doc_comment: stmt.doc_comment.map(|c| &*arena.alloc(fold_comment(c))),
451 }
452}
453
454pub fn fold_expr<'new, 'src, F: Fold<'src> + ?Sized>(
456 folder: &mut F,
457 arena: &'new Bump,
458 expr: &Expr<'_, 'src>,
459) -> Expr<'new, 'src> {
460 let kind = match &expr.kind {
461 ExprKind::Int(n) => ExprKind::Int(*n),
462 ExprKind::Float(f) => ExprKind::Float(*f),
463 ExprKind::String(s) => ExprKind::String(fold_byte_str(*s, arena)),
464 ExprKind::InterpolatedString(parts) => {
465 ExprKind::InterpolatedString(fold_string_parts(folder, arena, parts))
466 }
467 ExprKind::Heredoc { label, parts } => ExprKind::Heredoc {
468 label,
469 parts: fold_string_parts(folder, arena, parts),
470 },
471 ExprKind::Nowdoc { label, value } => ExprKind::Nowdoc {
472 label,
473 value: arena.alloc_str(value),
474 },
475 ExprKind::ShellExec(parts) => ExprKind::ShellExec(fold_string_parts(folder, arena, parts)),
476 ExprKind::Bool(b) => ExprKind::Bool(*b),
477 ExprKind::Null => ExprKind::Null,
478 ExprKind::Variable(name) => ExprKind::Variable(fold_name_str(*name, arena)),
479 ExprKind::VariableVariable(inner) => {
480 ExprKind::VariableVariable(arena.alloc(folder.fold_expr(arena, inner)))
481 }
482 ExprKind::Identifier(name) => ExprKind::Identifier(fold_name_str(*name, arena)),
483 ExprKind::Name(name) => ExprKind::Name(folder.fold_name(arena, name)),
484 ExprKind::Assign(assign) => ExprKind::Assign(AssignExpr {
485 target: arena.alloc(folder.fold_expr(arena, assign.target)),
486 op: assign.op,
487 value: arena.alloc(folder.fold_expr(arena, assign.value)),
488 by_ref: assign.by_ref,
489 }),
490 ExprKind::Binary(binary) => ExprKind::Binary(BinaryExpr {
491 left: arena.alloc(folder.fold_expr(arena, binary.left)),
492 op: binary.op,
493 right: arena.alloc(folder.fold_expr(arena, binary.right)),
494 }),
495 ExprKind::UnaryPrefix(u) => ExprKind::UnaryPrefix(UnaryPrefixExpr {
496 op: u.op,
497 operand: arena.alloc(folder.fold_expr(arena, u.operand)),
498 }),
499 ExprKind::UnaryPostfix(u) => ExprKind::UnaryPostfix(UnaryPostfixExpr {
500 operand: arena.alloc(folder.fold_expr(arena, u.operand)),
501 op: u.op,
502 }),
503 ExprKind::Ternary(t) => ExprKind::Ternary(TernaryExpr {
504 condition: arena.alloc(folder.fold_expr(arena, t.condition)),
505 then_expr: t
506 .then_expr
507 .map(|e| &*arena.alloc(folder.fold_expr(arena, e))),
508 else_expr: arena.alloc(folder.fold_expr(arena, t.else_expr)),
509 }),
510 ExprKind::NullCoalesce(nc) => ExprKind::NullCoalesce(NullCoalesceExpr {
511 left: arena.alloc(folder.fold_expr(arena, nc.left)),
512 right: arena.alloc(folder.fold_expr(arena, nc.right)),
513 }),
514 ExprKind::FunctionCall(call) => ExprKind::FunctionCall(FunctionCallExpr {
515 name: arena.alloc(folder.fold_expr(arena, call.name)),
516 args: fold_args(folder, arena, &call.args),
517 }),
518 ExprKind::Array(elements) => {
519 let mut new_elements = ArenaVec::with_capacity_in(elements.len(), arena);
520 for elem in elements.iter() {
521 new_elements.push(ArrayElement {
522 key: elem.key.as_ref().map(|k| folder.fold_expr(arena, k)),
523 kind: match &elem.kind {
524 ArrayElementKind::Value(e) => {
525 ArrayElementKind::Value(folder.fold_expr(arena, e))
526 }
527 ArrayElementKind::Spread(e) => {
528 ArrayElementKind::Spread(folder.fold_expr(arena, e))
529 }
530 ArrayElementKind::ByRef(e) => {
531 ArrayElementKind::ByRef(folder.fold_expr(arena, e))
532 }
533 },
534 span: elem.span,
535 });
536 }
537 ExprKind::Array(new_elements)
538 }
539 ExprKind::ArrayAccess(access) => ExprKind::ArrayAccess(ArrayAccessExpr {
540 array: arena.alloc(folder.fold_expr(arena, access.array)),
541 index: access
542 .index
543 .map(|i| &*arena.alloc(folder.fold_expr(arena, i))),
544 }),
545 ExprKind::Print(e) => ExprKind::Print(arena.alloc(folder.fold_expr(arena, e))),
546 ExprKind::Parenthesized(e) => {
547 ExprKind::Parenthesized(arena.alloc(folder.fold_expr(arena, e)))
548 }
549 ExprKind::Cast(kind, e) => ExprKind::Cast(*kind, arena.alloc(folder.fold_expr(arena, e))),
550 ExprKind::ErrorSuppress(e) => {
551 ExprKind::ErrorSuppress(arena.alloc(folder.fold_expr(arena, e)))
552 }
553 ExprKind::Isset(exprs) => ExprKind::Isset(fold_exprs(folder, arena, exprs)),
554 ExprKind::Empty(e) => ExprKind::Empty(arena.alloc(folder.fold_expr(arena, e))),
555 ExprKind::Include(kind, e) => {
556 ExprKind::Include(*kind, arena.alloc(folder.fold_expr(arena, e)))
557 }
558 ExprKind::Eval(e) => ExprKind::Eval(arena.alloc(folder.fold_expr(arena, e))),
559 ExprKind::Exit(e) => ExprKind::Exit(e.map(|e| &*arena.alloc(folder.fold_expr(arena, e)))),
560 ExprKind::MagicConst(k) => ExprKind::MagicConst(*k),
561 ExprKind::Clone(e) => ExprKind::Clone(arena.alloc(folder.fold_expr(arena, e))),
562 ExprKind::CloneWith(obj, overrides) => ExprKind::CloneWith(
563 arena.alloc(folder.fold_expr(arena, obj)),
564 arena.alloc(folder.fold_expr(arena, overrides)),
565 ),
566 ExprKind::New(new_expr) => ExprKind::New(NewExpr {
567 class: arena.alloc(folder.fold_expr(arena, new_expr.class)),
568 args: fold_args(folder, arena, &new_expr.args),
569 }),
570 ExprKind::PropertyAccess(access) => ExprKind::PropertyAccess(PropertyAccessExpr {
571 object: arena.alloc(folder.fold_expr(arena, access.object)),
572 property: arena.alloc(folder.fold_expr(arena, access.property)),
573 }),
574 ExprKind::NullsafePropertyAccess(access) => {
575 ExprKind::NullsafePropertyAccess(PropertyAccessExpr {
576 object: arena.alloc(folder.fold_expr(arena, access.object)),
577 property: arena.alloc(folder.fold_expr(arena, access.property)),
578 })
579 }
580 ExprKind::MethodCall(call) => ExprKind::MethodCall(arena.alloc(MethodCallExpr {
581 object: arena.alloc(folder.fold_expr(arena, call.object)),
582 method: arena.alloc(folder.fold_expr(arena, call.method)),
583 args: fold_args(folder, arena, &call.args),
584 })),
585 ExprKind::NullsafeMethodCall(call) => {
586 ExprKind::NullsafeMethodCall(arena.alloc(MethodCallExpr {
587 object: arena.alloc(folder.fold_expr(arena, call.object)),
588 method: arena.alloc(folder.fold_expr(arena, call.method)),
589 args: fold_args(folder, arena, &call.args),
590 }))
591 }
592 ExprKind::StaticPropertyAccess(access) => {
593 ExprKind::StaticPropertyAccess(StaticAccessExpr {
594 class: arena.alloc(folder.fold_expr(arena, access.class)),
595 member: arena.alloc(folder.fold_expr(arena, access.member)),
596 })
597 }
598 ExprKind::StaticMethodCall(call) => {
599 ExprKind::StaticMethodCall(arena.alloc(StaticMethodCallExpr {
600 class: arena.alloc(folder.fold_expr(arena, call.class)),
601 method: arena.alloc(folder.fold_expr(arena, call.method)),
602 args: fold_args(folder, arena, &call.args),
603 }))
604 }
605 ExprKind::StaticMethodCallDynamic(call) => {
606 ExprKind::StaticMethodCallDynamic(arena.alloc(StaticMethodCallDynamicExpr {
607 class: arena.alloc(folder.fold_expr(arena, call.class)),
608 method: arena.alloc(folder.fold_expr(arena, call.method)),
609 args: fold_args(folder, arena, &call.args),
610 }))
611 }
612 ExprKind::ClassConstAccess(access) => ExprKind::ClassConstAccess(StaticAccessExpr {
613 class: arena.alloc(folder.fold_expr(arena, access.class)),
614 member: arena.alloc(folder.fold_expr(arena, access.member)),
615 }),
616 ExprKind::ClassConstAccessDynamic { class, member } => ExprKind::ClassConstAccessDynamic {
617 class: arena.alloc(folder.fold_expr(arena, class)),
618 member: arena.alloc(folder.fold_expr(arena, member)),
619 },
620 ExprKind::StaticPropertyAccessDynamic { class, member } => {
621 ExprKind::StaticPropertyAccessDynamic {
622 class: arena.alloc(folder.fold_expr(arena, class)),
623 member: arena.alloc(folder.fold_expr(arena, member)),
624 }
625 }
626 ExprKind::Closure(closure) => {
627 let mut use_vars = ArenaVec::with_capacity_in(closure.use_vars.len(), arena);
628 for var in closure.use_vars.iter() {
629 use_vars.push(folder.fold_closure_use_var(arena, var));
630 }
631 let new_closure = arena.alloc(ClosureExpr {
632 is_static: closure.is_static,
633 by_ref: closure.by_ref,
634 params: fold_params(folder, arena, &closure.params),
635 missing_param_list: closure.missing_param_list,
636 use_vars,
637 return_type: closure
638 .return_type
639 .as_ref()
640 .map(|t| folder.fold_type_hint(arena, t)),
641 body: arena.alloc(folder.fold_block(arena, closure.body)),
642 attributes: fold_attrs(folder, arena, &closure.attributes),
643 });
644 ExprKind::Closure(new_closure)
645 }
646 ExprKind::ArrowFunction(arrow) => {
647 let new_arrow = arena.alloc(ArrowFunctionExpr {
648 is_static: arrow.is_static,
649 by_ref: arrow.by_ref,
650 params: fold_params(folder, arena, &arrow.params),
651 missing_param_list: arrow.missing_param_list,
652 return_type: arrow
653 .return_type
654 .as_ref()
655 .map(|t| folder.fold_type_hint(arena, t)),
656 body: arena.alloc(folder.fold_expr(arena, arrow.body)),
657 attributes: fold_attrs(folder, arena, &arrow.attributes),
658 });
659 ExprKind::ArrowFunction(new_arrow)
660 }
661 ExprKind::Match(match_expr) => ExprKind::Match(MatchExpr {
662 subject: arena.alloc(folder.fold_expr(arena, match_expr.subject)),
663 arms: {
664 let mut arms = ArenaVec::with_capacity_in(match_expr.arms.len(), arena);
665 for arm in match_expr.arms.iter() {
666 arms.push(folder.fold_match_arm(arena, arm));
667 }
668 arms
669 },
670 brace_span: match_expr.brace_span,
671 }),
672 ExprKind::Throw(e) => ExprKind::Throw(arena.alloc(folder.fold_expr(arena, e))),
673 ExprKind::Yield(y) => ExprKind::Yield(YieldExpr {
674 key: y.key.map(|k| &*arena.alloc(folder.fold_expr(arena, k))),
675 value: y.value.map(|v| &*arena.alloc(folder.fold_expr(arena, v))),
676 is_from: y.is_from,
677 }),
678 ExprKind::AnonymousClass(class) => {
679 ExprKind::AnonymousClass(arena.alloc(fold_class_decl(folder, arena, class)))
680 }
681 ExprKind::CallableCreate(cc) => {
682 let kind = match &cc.kind {
683 CallableCreateKind::Function(name) => {
684 CallableCreateKind::Function(arena.alloc(folder.fold_expr(arena, name)))
685 }
686 CallableCreateKind::Method { object, method } => CallableCreateKind::Method {
687 object: arena.alloc(folder.fold_expr(arena, object)),
688 method: arena.alloc(folder.fold_expr(arena, method)),
689 },
690 CallableCreateKind::NullsafeMethod { object, method } => {
691 CallableCreateKind::NullsafeMethod {
692 object: arena.alloc(folder.fold_expr(arena, object)),
693 method: arena.alloc(folder.fold_expr(arena, method)),
694 }
695 }
696 CallableCreateKind::StaticMethod { class, method } => {
697 CallableCreateKind::StaticMethod {
698 class: arena.alloc(folder.fold_expr(arena, class)),
699 method: arena.alloc(folder.fold_expr(arena, method)),
700 }
701 }
702 };
703 ExprKind::CallableCreate(CallableCreateExpr { kind })
704 }
705 ExprKind::Omit => ExprKind::Omit,
706 ExprKind::Error => ExprKind::Error,
707 };
708 Expr {
709 kind,
710 span: expr.span,
711 }
712}
713
714pub fn fold_param<'new, 'src, F: Fold<'src> + ?Sized>(
716 folder: &mut F,
717 arena: &'new Bump,
718 param: &Param<'_, 'src>,
719) -> Param<'new, 'src> {
720 Param {
721 name: param.name,
722 type_hint: param
723 .type_hint
724 .as_ref()
725 .map(|t| folder.fold_type_hint(arena, t)),
726 default: param.default.as_ref().map(|d| folder.fold_expr(arena, d)),
727 by_ref: param.by_ref,
728 variadic: param.variadic,
729 modifiers: param.modifiers,
730 attributes: fold_attrs(folder, arena, ¶m.attributes),
731 hooks: fold_hooks(folder, arena, ¶m.hooks),
732 empty_hook_list: param.empty_hook_list,
733 doc_comment: param.doc_comment,
734 span: param.span,
735 }
736}
737
738pub fn fold_arg<'new, 'src, F: Fold<'src> + ?Sized>(
740 folder: &mut F,
741 arena: &'new Bump,
742 arg: &Arg<'_, 'src>,
743) -> Arg<'new, 'src> {
744 Arg {
745 name: arg.name.as_ref().map(|n| folder.fold_name(arena, n)),
746 kind: match &arg.kind {
747 ArgKind::Value(e) => ArgKind::Value(folder.fold_expr(arena, e)),
748 ArgKind::Spread(e) => ArgKind::Spread(folder.fold_expr(arena, e)),
749 ArgKind::ByRef(e) => ArgKind::ByRef(folder.fold_expr(arena, e)),
750 ArgKind::Placeholder => ArgKind::Placeholder,
751 ArgKind::SpreadPlaceholder => ArgKind::SpreadPlaceholder,
752 },
753 span: arg.span,
754 }
755}
756
757pub fn fold_class_member<'new, 'src, F: Fold<'src> + ?Sized>(
759 folder: &mut F,
760 arena: &'new Bump,
761 member: &ClassMember<'_, 'src>,
762) -> ClassMember<'new, 'src> {
763 let kind = match &member.kind {
764 ClassMemberKind::Property(prop) => {
765 ClassMemberKind::Property(fold_property_decl(folder, arena, prop))
766 }
767 ClassMemberKind::Method(method) => {
768 ClassMemberKind::Method(fold_method_decl(folder, arena, method))
769 }
770 ClassMemberKind::ClassConst(cc) => {
771 ClassMemberKind::ClassConst(fold_class_const_decl(folder, arena, cc))
772 }
773 ClassMemberKind::TraitUse(tu) => {
774 ClassMemberKind::TraitUse(folder.fold_trait_use(arena, tu))
775 }
776 };
777 ClassMember {
778 kind,
779 span: member.span,
780 }
781}
782
783pub fn fold_enum_member<'new, 'src, F: Fold<'src> + ?Sized>(
785 folder: &mut F,
786 arena: &'new Bump,
787 member: &EnumMember<'_, 'src>,
788) -> EnumMember<'new, 'src> {
789 let kind = match &member.kind {
790 EnumMemberKind::Case(case) => EnumMemberKind::Case(EnumCase {
791 name: case.name,
792 value: case.value.as_ref().map(|v| folder.fold_expr(arena, v)),
793 attributes: fold_attrs(folder, arena, &case.attributes),
794 doc_comment: case.doc_comment.as_ref().map(fold_comment),
795 }),
796 EnumMemberKind::Method(method) => {
797 EnumMemberKind::Method(fold_method_decl(folder, arena, method))
798 }
799 EnumMemberKind::ClassConst(cc) => {
800 EnumMemberKind::ClassConst(fold_class_const_decl(folder, arena, cc))
801 }
802 EnumMemberKind::TraitUse(tu) => EnumMemberKind::TraitUse(folder.fold_trait_use(arena, tu)),
803 EnumMemberKind::Property(prop) => {
804 EnumMemberKind::Property(fold_property_decl(folder, arena, prop))
805 }
806 };
807 EnumMember {
808 kind,
809 span: member.span,
810 }
811}
812
813pub fn fold_property_hook<'new, 'src, F: Fold<'src> + ?Sized>(
815 folder: &mut F,
816 arena: &'new Bump,
817 hook: &PropertyHook<'_, 'src>,
818) -> PropertyHook<'new, 'src> {
819 let body = match &hook.body {
820 PropertyHookBody::Block(block) => {
821 PropertyHookBody::Block(arena.alloc(fold_block(folder, arena, block)))
822 }
823 PropertyHookBody::Expression(expr) => {
824 PropertyHookBody::Expression(folder.fold_expr(arena, expr))
825 }
826 PropertyHookBody::Abstract => PropertyHookBody::Abstract,
827 };
828 PropertyHook {
829 kind: hook.kind,
830 body,
831 modifiers: hook.modifiers,
832 by_ref: hook.by_ref,
833 params: fold_params(folder, arena, &hook.params),
834 empty_param_list: hook.empty_param_list,
835 attributes: fold_attrs(folder, arena, &hook.attributes),
836 name_span: hook.name_span,
837 span: hook.span,
838 }
839}
840
841pub fn fold_type_hint<'new, 'src, F: Fold<'src> + ?Sized>(
843 folder: &mut F,
844 arena: &'new Bump,
845 type_hint: &TypeHint<'_, 'src>,
846) -> TypeHint<'new, 'src> {
847 let kind = match &type_hint.kind {
848 TypeHintKind::Named(name) => TypeHintKind::Named(folder.fold_name(arena, name)),
849 TypeHintKind::Keyword(builtin, span) => TypeHintKind::Keyword(*builtin, *span),
850 TypeHintKind::Nullable(inner) => {
851 TypeHintKind::Nullable(arena.alloc(folder.fold_type_hint(arena, inner)))
852 }
853 TypeHintKind::Union(types) => {
854 let mut new_types = ArenaVec::with_capacity_in(types.len(), arena);
855 for t in types.iter() {
856 new_types.push(folder.fold_type_hint(arena, t));
857 }
858 TypeHintKind::Union(new_types)
859 }
860 TypeHintKind::Intersection(types) => {
861 let mut new_types = ArenaVec::with_capacity_in(types.len(), arena);
862 for t in types.iter() {
863 new_types.push(folder.fold_type_hint(arena, t));
864 }
865 TypeHintKind::Intersection(new_types)
866 }
867 };
868 TypeHint {
869 kind,
870 span: type_hint.span,
871 }
872}
873
874pub fn fold_attribute<'new, 'src, F: Fold<'src> + ?Sized>(
876 folder: &mut F,
877 arena: &'new Bump,
878 attribute: &Attribute<'_, 'src>,
879) -> Attribute<'new, 'src> {
880 Attribute {
881 name: folder.fold_name(arena, &attribute.name),
882 args: fold_args(folder, arena, &attribute.args),
883 span: attribute.span,
884 }
885}
886
887pub fn fold_catch_clause<'new, 'src, F: Fold<'src> + ?Sized>(
889 folder: &mut F,
890 arena: &'new Bump,
891 catch: &CatchClause<'_, 'src>,
892) -> CatchClause<'new, 'src> {
893 let mut types = ArenaVec::with_capacity_in(catch.types.len(), arena);
894 for ty in catch.types.iter() {
895 types.push(folder.fold_name(arena, ty));
896 }
897 CatchClause {
898 types,
899 var: catch.var,
900 body: arena.alloc(folder.fold_block(arena, catch.body)),
901 span: catch.span,
902 }
903}
904
905pub fn fold_match_arm<'new, 'src, F: Fold<'src> + ?Sized>(
907 folder: &mut F,
908 arena: &'new Bump,
909 arm: &MatchArm<'_, 'src>,
910) -> MatchArm<'new, 'src> {
911 let conditions = arm.conditions.as_ref().map(|conds| {
912 let mut new_conds = ArenaVec::with_capacity_in(conds.len(), arena);
913 for c in conds.iter() {
914 new_conds.push(folder.fold_expr(arena, c));
915 }
916 new_conds
917 });
918 MatchArm {
919 conditions,
920 body: folder.fold_expr(arena, &arm.body),
921 span: arm.span,
922 }
923}
924
925pub fn fold_trait_use<'new, 'src, F: Fold<'src> + ?Sized>(
927 folder: &mut F,
928 arena: &'new Bump,
929 trait_use: &TraitUseDecl<'_, 'src>,
930) -> TraitUseDecl<'new, 'src> {
931 let mut traits = ArenaVec::with_capacity_in(trait_use.traits.len(), arena);
932 for t in trait_use.traits.iter() {
933 traits.push(folder.fold_name(arena, t));
934 }
935 let mut adaptations = ArenaVec::with_capacity_in(trait_use.adaptations.len(), arena);
936 for a in trait_use.adaptations.iter() {
937 adaptations.push(folder.fold_trait_adaptation(arena, a));
938 }
939 TraitUseDecl {
940 traits,
941 adaptations,
942 adaptations_brace_span: trait_use.adaptations_brace_span,
943 doc_comment: trait_use.doc_comment.as_ref().map(fold_comment),
944 }
945}
946
947pub fn fold_trait_adaptation<'new, 'src, F: Fold<'src> + ?Sized>(
949 folder: &mut F,
950 arena: &'new Bump,
951 adaptation: &TraitAdaptation<'_, 'src>,
952) -> TraitAdaptation<'new, 'src> {
953 let kind = match &adaptation.kind {
954 TraitAdaptationKind::Precedence {
955 trait_name,
956 method,
957 insteadof,
958 } => {
959 let mut new_insteadof = ArenaVec::with_capacity_in(insteadof.len(), arena);
960 for n in insteadof.iter() {
961 new_insteadof.push(folder.fold_name(arena, n));
962 }
963 TraitAdaptationKind::Precedence {
964 trait_name: folder.fold_name(arena, trait_name),
965 method: folder.fold_name(arena, method),
966 insteadof: new_insteadof,
967 }
968 }
969 TraitAdaptationKind::Alias {
970 trait_name,
971 method,
972 new_modifier,
973 is_final,
974 invalid_modifier,
975 new_name,
976 } => TraitAdaptationKind::Alias {
977 trait_name: trait_name.as_ref().map(|n| folder.fold_name(arena, n)),
978 method: folder.fold_name(arena, method),
979 new_modifier: *new_modifier,
980 is_final: *is_final,
981 invalid_modifier: *invalid_modifier,
982 new_name: new_name.as_ref().map(|n| folder.fold_name(arena, n)),
983 },
984 };
985 TraitAdaptation {
986 kind,
987 span: adaptation.span,
988 }
989}
990
991pub fn fold_name<'new, 'src, F: Fold<'src> + ?Sized>(
993 _folder: &mut F,
994 arena: &'new Bump,
995 name: &Name<'_, 'src>,
996) -> Name<'new, 'src> {
997 match name {
998 Name::Simple { value, span } => Name::Simple { value, span: *span },
999 Name::Complex { parts, kind, span } => {
1000 let mut new_parts = ArenaVec::with_capacity_in(parts.len(), arena);
1001 for &part in parts.iter() {
1002 new_parts.push(part);
1003 }
1004 Name::Complex {
1005 parts: new_parts,
1006 kind: *kind,
1007 span: *span,
1008 }
1009 }
1010 Name::Error { span } => Name::Error { span: *span },
1011 }
1012}
1013
1014fn fold_function_decl<'new, 'src, F: Fold<'src> + ?Sized>(
1019 folder: &mut F,
1020 arena: &'new Bump,
1021 func: &FunctionDecl<'_, 'src>,
1022) -> FunctionDecl<'new, 'src> {
1023 FunctionDecl {
1024 name: func.name,
1025 params: fold_params(folder, arena, &func.params),
1026 missing_param_list: func.missing_param_list,
1027 body: arena.alloc(folder.fold_block(arena, func.body)),
1028 return_type: func
1029 .return_type
1030 .as_ref()
1031 .map(|t| folder.fold_type_hint(arena, t)),
1032 by_ref: func.by_ref,
1033 attributes: fold_attrs(folder, arena, &func.attributes),
1034 doc_comment: func.doc_comment.as_ref().map(fold_comment),
1035 }
1036}
1037
1038fn fold_method_decl<'new, 'src, F: Fold<'src> + ?Sized>(
1039 folder: &mut F,
1040 arena: &'new Bump,
1041 method: &MethodDecl<'_, 'src>,
1042) -> MethodDecl<'new, 'src> {
1043 MethodDecl {
1044 name: method.name,
1045 modifiers: method.modifiers,
1046 by_ref: method.by_ref,
1047 params: fold_params(folder, arena, &method.params),
1048 missing_param_list: method.missing_param_list,
1049 return_type: method
1050 .return_type
1051 .as_ref()
1052 .map(|t| folder.fold_type_hint(arena, t)),
1053 body: method
1054 .body
1055 .map(|b| &*arena.alloc(folder.fold_block(arena, b))),
1056 attributes: fold_attrs(folder, arena, &method.attributes),
1057 doc_comment: method.doc_comment.as_ref().map(fold_comment),
1058 }
1059}
1060
1061fn fold_property_decl<'new, 'src, F: Fold<'src> + ?Sized>(
1062 folder: &mut F,
1063 arena: &'new Bump,
1064 prop: &PropertyDecl<'_, 'src>,
1065) -> PropertyDecl<'new, 'src> {
1066 PropertyDecl {
1067 name: prop.name,
1068 modifiers: prop.modifiers,
1069 type_hint: prop
1070 .type_hint
1071 .as_ref()
1072 .map(|t| folder.fold_type_hint(arena, t)),
1073 default: prop.default.as_ref().map(|d| folder.fold_expr(arena, d)),
1074 attributes: fold_attrs(folder, arena, &prop.attributes),
1075 hooks: fold_hooks(folder, arena, &prop.hooks),
1076 empty_hook_list: prop.empty_hook_list,
1077 doc_comment: prop.doc_comment.as_ref().map(fold_comment),
1078 }
1079}
1080
1081fn fold_class_const_decl<'new, 'src, F: Fold<'src> + ?Sized>(
1082 folder: &mut F,
1083 arena: &'new Bump,
1084 cc: &ClassConstDecl<'_, 'src>,
1085) -> ClassConstDecl<'new, 'src> {
1086 ClassConstDecl {
1087 name: cc.name,
1088 modifiers: cc.modifiers,
1089 type_hint: cc
1090 .type_hint
1091 .map(|t| &*arena.alloc(folder.fold_type_hint(arena, t))),
1092 value: folder.fold_expr(arena, &cc.value),
1093 attributes: fold_attrs(folder, arena, &cc.attributes),
1094 doc_comment: cc.doc_comment.as_ref().map(fold_comment),
1095 }
1096}
1097
1098fn fold_class_decl<'new, 'src, F: Fold<'src> + ?Sized>(
1099 folder: &mut F,
1100 arena: &'new Bump,
1101 class: &ClassDecl<'_, 'src>,
1102) -> ClassDecl<'new, 'src> {
1103 let mut members = ArenaVec::with_capacity_in(class.body.members.len(), arena);
1104 for member in class.body.members.iter() {
1105 members.push(folder.fold_class_member(arena, member));
1106 }
1107 ClassDecl {
1108 name: class.name,
1109 modifiers: class.modifiers.clone(),
1110 extends: class.extends.as_ref().map(|n| folder.fold_name(arena, n)),
1111 implements: {
1112 let mut v = ArenaVec::with_capacity_in(class.implements.len(), arena);
1113 for n in class.implements.iter() {
1114 v.push(folder.fold_name(arena, n));
1115 }
1116 v
1117 },
1118 body: ClassBody {
1119 members,
1120 span: class.body.span,
1121 },
1122 attributes: fold_attrs(folder, arena, &class.attributes),
1123 doc_comment: class.doc_comment.as_ref().map(fold_comment),
1124 }
1125}
1126
1127fn fold_interface_decl<'new, 'src, F: Fold<'src> + ?Sized>(
1128 folder: &mut F,
1129 arena: &'new Bump,
1130 iface: &InterfaceDecl<'_, 'src>,
1131) -> InterfaceDecl<'new, 'src> {
1132 let mut extends = ArenaVec::with_capacity_in(iface.extends.len(), arena);
1133 for n in iface.extends.iter() {
1134 extends.push(folder.fold_name(arena, n));
1135 }
1136 let mut members = ArenaVec::with_capacity_in(iface.body.members.len(), arena);
1137 for member in iface.body.members.iter() {
1138 members.push(folder.fold_class_member(arena, member));
1139 }
1140 InterfaceDecl {
1141 name: iface.name,
1142 extends,
1143 body: ClassBody {
1144 members,
1145 span: iface.body.span,
1146 },
1147 attributes: fold_attrs(folder, arena, &iface.attributes),
1148 doc_comment: iface.doc_comment.as_ref().map(fold_comment),
1149 }
1150}
1151
1152fn fold_trait_decl<'new, 'src, F: Fold<'src> + ?Sized>(
1153 folder: &mut F,
1154 arena: &'new Bump,
1155 t: &TraitDecl<'_, 'src>,
1156) -> TraitDecl<'new, 'src> {
1157 let mut members = ArenaVec::with_capacity_in(t.body.members.len(), arena);
1158 for member in t.body.members.iter() {
1159 members.push(folder.fold_class_member(arena, member));
1160 }
1161 TraitDecl {
1162 name: t.name,
1163 body: ClassBody {
1164 members,
1165 span: t.body.span,
1166 },
1167 attributes: fold_attrs(folder, arena, &t.attributes),
1168 doc_comment: t.doc_comment.as_ref().map(fold_comment),
1169 }
1170}
1171
1172fn fold_enum_decl<'new, 'src, F: Fold<'src> + ?Sized>(
1173 folder: &mut F,
1174 arena: &'new Bump,
1175 e: &EnumDecl<'_, 'src>,
1176) -> EnumDecl<'new, 'src> {
1177 let mut members = ArenaVec::with_capacity_in(e.body.members.len(), arena);
1178 for member in e.body.members.iter() {
1179 members.push(folder.fold_enum_member(arena, member));
1180 }
1181 EnumDecl {
1182 name: e.name,
1183 scalar_type: e.scalar_type.as_ref().map(|n| folder.fold_name(arena, n)),
1184 implements: {
1185 let mut v = ArenaVec::with_capacity_in(e.implements.len(), arena);
1186 for n in e.implements.iter() {
1187 v.push(folder.fold_name(arena, n));
1188 }
1189 v
1190 },
1191 body: EnumBody {
1192 members,
1193 span: e.body.span,
1194 },
1195 attributes: fold_attrs(folder, arena, &e.attributes),
1196 doc_comment: e.doc_comment.as_ref().map(fold_comment),
1197 }
1198}
1199
1200pub fn fold_stmts<'new, 'src, F: Fold<'src> + ?Sized>(
1206 folder: &mut F,
1207 arena: &'new Bump,
1208 stmts: &[Stmt<'_, 'src>],
1209) -> ArenaVec<'new, Stmt<'new, 'src>> {
1210 let mut vec = ArenaVec::with_capacity_in(stmts.len(), arena);
1211 for stmt in stmts {
1212 vec.push(folder.fold_stmt(arena, stmt));
1213 }
1214 vec
1215}
1216
1217pub fn fold_block<'new, 'src, F: Fold<'src> + ?Sized>(
1219 folder: &mut F,
1220 arena: &'new Bump,
1221 block: &Block<'_, 'src>,
1222) -> Block<'new, 'src> {
1223 Block {
1224 stmts: folder.fold_stmts(arena, &block.stmts),
1225 span: block.span,
1226 }
1227}
1228
1229fn fold_exprs<'new, 'src, F: Fold<'src> + ?Sized>(
1230 folder: &mut F,
1231 arena: &'new Bump,
1232 exprs: &[Expr<'_, 'src>],
1233) -> ArenaVec<'new, Expr<'new, 'src>> {
1234 let mut vec = ArenaVec::with_capacity_in(exprs.len(), arena);
1235 for expr in exprs {
1236 vec.push(folder.fold_expr(arena, expr));
1237 }
1238 vec
1239}
1240
1241fn fold_args<'new, 'src, F: Fold<'src> + ?Sized>(
1242 folder: &mut F,
1243 arena: &'new Bump,
1244 args: &[Arg<'_, 'src>],
1245) -> ArenaVec<'new, Arg<'new, 'src>> {
1246 let mut vec = ArenaVec::with_capacity_in(args.len(), arena);
1247 for arg in args {
1248 vec.push(folder.fold_arg(arena, arg));
1249 }
1250 vec
1251}
1252
1253fn fold_params<'new, 'src, F: Fold<'src> + ?Sized>(
1254 folder: &mut F,
1255 arena: &'new Bump,
1256 params: &[Param<'_, 'src>],
1257) -> ArenaVec<'new, Param<'new, 'src>> {
1258 let mut vec = ArenaVec::with_capacity_in(params.len(), arena);
1259 for param in params {
1260 vec.push(folder.fold_param(arena, param));
1261 }
1262 vec
1263}
1264
1265fn fold_attrs<'new, 'src, F: Fold<'src> + ?Sized>(
1266 folder: &mut F,
1267 arena: &'new Bump,
1268 attrs: &[Attribute<'_, 'src>],
1269) -> ArenaVec<'new, Attribute<'new, 'src>> {
1270 let mut vec = ArenaVec::with_capacity_in(attrs.len(), arena);
1271 for attr in attrs {
1272 vec.push(folder.fold_attribute(arena, attr));
1273 }
1274 vec
1275}
1276
1277fn fold_hooks<'new, 'src, F: Fold<'src> + ?Sized>(
1278 folder: &mut F,
1279 arena: &'new Bump,
1280 hooks: &[PropertyHook<'_, 'src>],
1281) -> ArenaVec<'new, PropertyHook<'new, 'src>> {
1282 let mut vec = ArenaVec::with_capacity_in(hooks.len(), arena);
1283 for hook in hooks {
1284 vec.push(folder.fold_property_hook(arena, hook));
1285 }
1286 vec
1287}
1288
1289fn fold_string_parts<'new, 'src, F: Fold<'src> + ?Sized>(
1290 folder: &mut F,
1291 arena: &'new Bump,
1292 parts: &[StringPart<'_, 'src>],
1293) -> ArenaVec<'new, StringPart<'new, 'src>> {
1294 let mut vec = ArenaVec::with_capacity_in(parts.len(), arena);
1295 for part in parts {
1296 vec.push(match part {
1297 StringPart::Literal(s) => StringPart::Literal(fold_byte_str(*s, arena)),
1298 StringPart::Expr(e) => StringPart::Expr(folder.fold_expr(arena, e)),
1299 });
1300 }
1301 vec
1302}
1303
1304pub fn fold_byte_str<'new, 'src>(
1311 value: ByteStr<'_, 'src>,
1312 arena: &'new Bump,
1313) -> ByteStr<'new, 'src> {
1314 match value.into_src_str() {
1315 Some(s) => ByteStr::from_source(s),
1316 None => ByteStr::new_in(arena, value.as_bytes()),
1317 }
1318}
1319
1320pub fn fold_name_str<'new, 'src>(
1324 name: NameStr<'_, 'src>,
1325 arena: &'new Bump,
1326) -> NameStr<'new, 'src> {
1327 if let Some(s) = name.into_src_str() {
1328 NameStr::from_source(s)
1329 } else {
1330 NameStr::from_arena(arena.alloc_str(name.as_str()))
1331 }
1332}
1333
1334fn fold_comment<'src>(comment: &Comment<'src>) -> Comment<'src> {
1335 Comment {
1336 kind: comment.kind,
1337 text: comment.text,
1338 span: comment.span,
1339 }
1340}