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