1pub mod fold;
21pub mod visitor;
22
23pub use fold::{
24 fold_owned_arg, fold_owned_attribute, fold_owned_catch_clause, fold_owned_class_member,
25 fold_owned_closure_use_var, fold_owned_enum_member, fold_owned_expr, fold_owned_match_arm,
26 fold_owned_name, fold_owned_param, fold_owned_program, fold_owned_property_hook,
27 fold_owned_stmt, fold_owned_type_hint, FoldOwned,
28};
29pub use visitor::{
30 walk_owned_arg, walk_owned_attribute, walk_owned_catch_clause, walk_owned_class_member,
31 walk_owned_comments, walk_owned_enum_member, walk_owned_expr, walk_owned_match_arm,
32 walk_owned_name, walk_owned_param, walk_owned_program, walk_owned_property_hook,
33 walk_owned_stmt, walk_owned_trait_use, walk_owned_type_hint, OwnedScope, OwnedScopeVisitor,
34 OwnedScopeWalker, OwnedVisitor,
35};
36
37use serde::Serialize;
38
39use crate::ast as arena_ast;
40use crate::ast::{
41 AssignOp, BinaryOp, BuiltinType, CastKind, ClassModifiers, CommentKind, IncludeKind,
42 MagicConstKind, NameKind, PropertyHookKind, UnaryPostfixOp, UnaryPrefixOp, UseKind, Visibility,
43};
44use crate::Span;
45
46fn is_false(b: &bool) -> bool {
51 !*b
52}
53
54fn slice_is_empty<T>(v: &[T]) -> bool {
55 v.is_empty()
56}
57
58pub type Ident = Option<Box<str>>;
70
71#[derive(Debug, Clone, Serialize)]
81pub struct Name {
82 pub parts: Box<[Box<str>]>,
83 pub kind: NameKind,
84 pub span: Span,
85}
86
87#[derive(Debug, Clone, Serialize)]
92pub struct Comment {
93 pub kind: CommentKind,
94 pub text: Box<str>,
95 pub span: Span,
96}
97
98#[derive(Debug, Clone, Serialize)]
106pub struct TypeHint {
107 pub kind: TypeHintKind,
108 pub span: Span,
109}
110
111#[derive(Debug, Clone)]
112pub enum TypeHintKind {
113 Named(Name),
114 Keyword(BuiltinType, Span),
116 Nullable(Box<TypeHint>),
117 Union(Box<[TypeHint]>),
118 Intersection(Box<[TypeHint]>),
119}
120
121impl Serialize for TypeHintKind {
122 fn serialize<S: serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
123 match self {
124 Self::Named(name) => s.serialize_newtype_variant("TypeHintKind", 0, "Named", name),
125 Self::Nullable(inner) => {
126 s.serialize_newtype_variant("TypeHintKind", 2, "Nullable", inner)
127 }
128 Self::Union(types) => s.serialize_newtype_variant("TypeHintKind", 3, "Union", types),
129 Self::Intersection(types) => {
130 s.serialize_newtype_variant("TypeHintKind", 4, "Intersection", types)
131 }
132 Self::Keyword(builtin, span) => {
133 struct BuiltinNameRepr<'a>(&'a BuiltinType, &'a Span);
134 impl Serialize for BuiltinNameRepr<'_> {
135 fn serialize<S: serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
136 use serde::ser::SerializeStruct;
137 let mut st = s.serialize_struct("Name", 3)?;
138 st.serialize_field("parts", &[self.0.as_str()])?;
139 st.serialize_field("kind", &NameKind::Unqualified)?;
140 st.serialize_field("span", self.1)?;
141 st.end()
142 }
143 }
144 s.serialize_newtype_variant(
145 "TypeHintKind",
146 0,
147 "Named",
148 &BuiltinNameRepr(builtin, span),
149 )
150 }
151 }
152 }
153}
154
155#[derive(Debug, Clone, Serialize)]
160pub struct Arg {
161 pub name: Option<Name>,
162 pub value: Option<Expr>,
164 pub unpack: bool,
165 pub by_ref: bool,
166 pub span: Span,
167}
168
169#[derive(Debug, Clone, Serialize)]
170pub struct Attribute {
171 pub name: Name,
172 pub args: Box<[Arg]>,
173 pub span: Span,
174}
175
176#[derive(Debug, Clone, Serialize)]
181pub struct Program {
182 pub stmts: Box<[Stmt]>,
183 pub span: Span,
184}
185
186#[derive(Debug, Clone, Serialize)]
191pub struct Stmt {
192 pub kind: StmtKind,
193 pub span: Span,
194 #[serde(skip_serializing_if = "Option::is_none")]
195 pub doc_comment: Option<Comment>,
196}
197
198impl Stmt {
199 pub fn leading_doc_comment(&self) -> Option<&Comment> {
203 if let Some(doc) = &self.doc_comment {
204 return Some(doc);
205 }
206 match &self.kind {
207 StmtKind::Function(f) => f.doc_comment.as_ref(),
208 StmtKind::Class(c) => c.doc_comment.as_ref(),
209 StmtKind::Interface(i) => i.doc_comment.as_ref(),
210 StmtKind::Trait(t) => t.doc_comment.as_ref(),
211 StmtKind::Enum(e) => e.doc_comment.as_ref(),
212 StmtKind::Const(items) => items.first().and_then(|i| i.doc_comment.as_ref()),
213 _ => None,
214 }
215 }
216}
217
218#[derive(Debug, Clone, Serialize)]
220#[serde(transparent)]
221pub struct Block {
222 pub stmts: Box<[Stmt]>,
223 #[serde(skip)]
224 pub span: Span,
225}
226
227#[derive(Debug, Clone, Serialize)]
228pub enum StmtKind {
229 Expression(Box<Expr>),
230 Echo(Box<[Expr]>),
231 Return(Option<Box<Expr>>),
232 Block(Box<Block>),
233 If(Box<IfStmt>),
234 While(Box<WhileStmt>),
235 For(Box<ForStmt>),
236 Foreach(Box<ForeachStmt>),
237 DoWhile(Box<DoWhileStmt>),
238 Function(Box<FunctionDecl>),
239 Break(Option<Box<Expr>>),
240 Continue(Option<Box<Expr>>),
241 Switch(Box<SwitchStmt>),
242 Goto(Ident),
243 Label(Box<str>),
244 Declare(Box<DeclareStmt>),
245 Unset(Box<[Expr]>),
246 Throw(Box<Expr>),
247 TryCatch(Box<TryCatchStmt>),
248 Global(Box<[Expr]>),
249 Class(Box<ClassDecl>),
250 Interface(Box<InterfaceDecl>),
251 Trait(Box<TraitDecl>),
252 Enum(Box<EnumDecl>),
253 Namespace(Box<NamespaceDecl>),
254 Use(Box<UseDecl>),
255 Const(Box<[ConstItem]>),
256 StaticVar(Box<[StaticVar]>),
257 HaltCompiler(Box<str>),
258 Nop,
259 InlineHtml(Box<str>),
260 Error,
261}
262
263#[derive(Debug, Clone, Serialize)]
264pub struct IfStmt {
265 pub condition: Expr,
266 pub then_branch: Box<Stmt>,
267 pub elseif_branches: Box<[ElseIfBranch]>,
268 pub else_branch: Option<Box<Stmt>>,
269 #[serde(skip)]
270 pub else_kw_start: Option<u32>,
271 #[serde(default, skip_serializing_if = "is_false")]
272 pub uses_alternative: bool,
273}
274
275#[derive(Debug, Clone, Serialize)]
276pub struct ElseIfBranch {
277 pub condition: Expr,
278 pub body: Stmt,
279 pub span: Span,
280}
281
282#[derive(Debug, Clone, Serialize)]
283pub struct WhileStmt {
284 pub condition: Expr,
285 pub body: Box<Stmt>,
286 #[serde(default, skip_serializing_if = "is_false")]
287 pub uses_alternative: bool,
288}
289
290#[derive(Debug, Clone, Serialize)]
291pub struct ForStmt {
292 pub init: Box<[Expr]>,
293 pub condition: Box<[Expr]>,
294 pub update: Box<[Expr]>,
295 pub body: Box<Stmt>,
296 #[serde(default, skip_serializing_if = "is_false")]
297 pub uses_alternative: bool,
298}
299
300#[derive(Debug, Clone, Serialize)]
301pub struct ForeachStmt {
302 pub expr: Expr,
303 pub key: Option<Expr>,
304 pub value: Expr,
305 pub body: Box<Stmt>,
306 #[serde(default, skip_serializing_if = "is_false")]
307 pub uses_alternative: bool,
308}
309
310#[derive(Debug, Clone, Serialize)]
311pub struct DoWhileStmt {
312 pub body: Box<Stmt>,
313 pub condition: Expr,
314}
315
316#[derive(Debug, Clone, Serialize)]
317pub struct SwitchBody {
318 pub cases: Box<[SwitchCase]>,
319 #[serde(skip)]
320 pub span: Span,
321}
322
323#[derive(Debug, Clone, Serialize)]
324pub struct SwitchStmt {
325 pub expr: Expr,
326 #[serde(flatten)]
327 pub body: SwitchBody,
328 #[serde(default, skip_serializing_if = "is_false")]
329 pub uses_alternative: bool,
330}
331
332#[derive(Debug, Clone, Serialize)]
333pub struct SwitchCase {
334 pub value: Option<Expr>,
335 pub body: Box<[Stmt]>,
336 pub span: Span,
337}
338
339#[derive(Debug, Clone, Serialize)]
340pub struct TryCatchStmt {
341 pub body: Box<Block>,
342 pub catches: Box<[CatchClause]>,
343 pub finally: Option<Box<Block>>,
344 #[serde(skip)]
345 pub finally_kw_start: Option<u32>,
346}
347
348#[derive(Debug, Clone, Serialize)]
349pub struct CatchClause {
350 pub types: Box<[Name]>,
351 pub var: Option<Box<str>>,
352 pub body: Box<Block>,
353 pub span: Span,
354}
355
356#[derive(Debug, Clone, Serialize)]
357pub struct NamespaceDecl {
358 pub name: Option<Name>,
359 pub body: NamespaceBody,
360}
361
362#[derive(Debug, Clone, Serialize)]
363pub enum NamespaceBody {
364 Braced(Box<Block>),
365 Simple,
366}
367
368#[derive(Debug, Clone, Serialize)]
369pub struct DeclareStmt {
370 pub directives: Box<[(Box<str>, Expr)]>,
371 pub body: Option<Box<Stmt>>,
372 #[serde(default, skip_serializing_if = "is_false")]
373 pub uses_alternative: bool,
374}
375
376#[derive(Debug, Clone, Serialize)]
377pub struct UseDecl {
378 pub kind: UseKind,
379 pub uses: Box<[UseItem]>,
380}
381
382#[derive(Debug, Clone, Serialize)]
383pub struct UseItem {
384 pub name: Name,
385 pub alias: Option<Box<str>>,
386 #[serde(skip_serializing_if = "Option::is_none")]
387 pub kind: Option<UseKind>,
388 pub span: Span,
389}
390
391#[derive(Debug, Clone, Serialize)]
392pub struct ConstItem {
393 pub name: Ident,
394 pub value: Expr,
395 pub attributes: Box<[Attribute]>,
396 pub span: Span,
397 #[serde(skip_serializing_if = "Option::is_none")]
398 pub doc_comment: Option<Comment>,
399}
400
401#[derive(Debug, Clone, Serialize)]
402pub struct StaticVar {
403 pub name: Ident,
404 pub default: Option<Expr>,
405 pub span: Span,
406}
407
408#[derive(Debug, Clone, Serialize)]
413pub struct Expr {
414 pub kind: ExprKind,
415 pub span: Span,
416}
417
418#[derive(Debug, Clone, Serialize)]
419pub enum ExprKind {
420 Int(i64),
421 Float(f64),
422 String(Box<str>),
423 InterpolatedString(Box<[StringPart]>),
424 Heredoc {
425 label: Box<str>,
426 parts: Box<[StringPart]>,
427 },
428 Nowdoc {
429 label: Box<str>,
430 value: Box<str>,
431 },
432 ShellExec(Box<[StringPart]>),
433 Bool(bool),
434 Null,
435 Variable(Box<str>),
436 VariableVariable(Box<Expr>),
437 Identifier(Box<str>),
438 Assign(AssignExpr),
439 Binary(BinaryExpr),
440 UnaryPrefix(UnaryPrefixExpr),
441 UnaryPostfix(UnaryPostfixExpr),
442 Ternary(TernaryExpr),
443 NullCoalesce(NullCoalesceExpr),
444 FunctionCall(FunctionCallExpr),
445 Array(Box<[ArrayElement]>),
446 ArrayAccess(ArrayAccessExpr),
447 Print(Box<Expr>),
448 Parenthesized(Box<Expr>),
449 Cast(CastKind, Box<Expr>),
450 ErrorSuppress(Box<Expr>),
451 Isset(Box<[Expr]>),
452 Empty(Box<Expr>),
453 Include(IncludeKind, Box<Expr>),
454 Eval(Box<Expr>),
455 Exit(Option<Box<Expr>>),
456 MagicConst(MagicConstKind),
457 Clone(Box<Expr>),
458 CloneWith(Box<Expr>, Box<Expr>),
459 New(NewExpr),
460 PropertyAccess(PropertyAccessExpr),
461 NullsafePropertyAccess(PropertyAccessExpr),
462 MethodCall(Box<MethodCallExpr>),
463 NullsafeMethodCall(Box<MethodCallExpr>),
464 StaticPropertyAccess(StaticAccessExpr),
465 StaticMethodCall(Box<StaticMethodCallExpr>),
466 StaticDynMethodCall(Box<StaticDynMethodCallExpr>),
467 ClassConstAccess(StaticAccessExpr),
468 ClassConstAccessDynamic {
469 class: Box<Expr>,
470 member: Box<Expr>,
471 },
472 StaticPropertyAccessDynamic {
473 class: Box<Expr>,
474 member: Box<Expr>,
475 },
476 Closure(Box<ClosureExpr>),
477 ArrowFunction(Box<ArrowFunctionExpr>),
478 Match(MatchExpr),
479 ThrowExpr(Box<Expr>),
480 Yield(YieldExpr),
481 AnonymousClass(Box<ClassDecl>),
482 CallableCreate(CallableCreateExpr),
483 Omit,
484 Error,
485}
486
487#[derive(Debug, Clone, Serialize)]
488pub struct AssignExpr {
489 pub target: Box<Expr>,
490 pub op: AssignOp,
491 pub value: Box<Expr>,
492 #[serde(skip_serializing_if = "is_false")]
493 pub by_ref: bool,
494}
495
496#[derive(Debug, Clone, Serialize)]
497pub struct BinaryExpr {
498 pub left: Box<Expr>,
499 pub op: BinaryOp,
500 pub right: Box<Expr>,
501}
502
503#[derive(Debug, Clone, Serialize)]
504pub struct UnaryPrefixExpr {
505 pub op: UnaryPrefixOp,
506 pub operand: Box<Expr>,
507}
508
509#[derive(Debug, Clone, Serialize)]
510pub struct UnaryPostfixExpr {
511 pub operand: Box<Expr>,
512 pub op: UnaryPostfixOp,
513}
514
515#[derive(Debug, Clone, Serialize)]
516pub struct TernaryExpr {
517 pub condition: Box<Expr>,
518 pub then_expr: Option<Box<Expr>>,
519 pub else_expr: Box<Expr>,
520}
521
522#[derive(Debug, Clone, Serialize)]
523pub struct NullCoalesceExpr {
524 pub left: Box<Expr>,
525 pub right: Box<Expr>,
526}
527
528#[derive(Debug, Clone, Serialize)]
529pub struct FunctionCallExpr {
530 pub name: Box<Expr>,
531 pub args: Box<[Arg]>,
532}
533
534#[derive(Debug, Clone, Serialize)]
535pub struct ArrayElement {
536 pub key: Option<Expr>,
537 pub value: Expr,
538 pub unpack: bool,
539 #[serde(skip_serializing_if = "is_false")]
540 pub by_ref: bool,
541 pub span: Span,
542}
543
544#[derive(Debug, Clone, Serialize)]
545pub struct ArrayAccessExpr {
546 pub array: Box<Expr>,
547 pub index: Option<Box<Expr>>,
548}
549
550#[derive(Debug, Clone, Serialize)]
551pub struct NewExpr {
552 pub class: Box<Expr>,
553 pub args: Box<[Arg]>,
554}
555
556#[derive(Debug, Clone, Serialize)]
557pub struct PropertyAccessExpr {
558 pub object: Box<Expr>,
559 pub property: Box<Expr>,
560}
561
562#[derive(Debug, Clone, Serialize)]
563pub struct MethodCallExpr {
564 pub object: Box<Expr>,
565 pub method: Box<Expr>,
566 pub args: Box<[Arg]>,
567}
568
569#[derive(Debug, Clone, Serialize)]
570pub struct StaticAccessExpr {
571 pub class: Box<Expr>,
572 pub member: Box<Expr>,
573}
574
575#[derive(Debug, Clone, Serialize)]
576pub struct StaticMethodCallExpr {
577 pub class: Box<Expr>,
578 pub method: Box<Expr>,
579 pub args: Box<[Arg]>,
580}
581
582#[derive(Debug, Clone, Serialize)]
583pub struct StaticDynMethodCallExpr {
584 pub class: Box<Expr>,
585 pub method: Box<Expr>,
586 pub args: Box<[Arg]>,
587}
588
589#[derive(Debug, Clone, Serialize)]
590pub struct ClosureExpr {
591 pub is_static: bool,
592 pub by_ref: bool,
593 pub params: Box<[Param]>,
594 pub use_vars: Box<[ClosureUseVar]>,
595 pub return_type: Option<TypeHint>,
596 pub body: Box<Block>,
597 pub attributes: Box<[Attribute]>,
598}
599
600#[derive(Debug, Clone, Serialize)]
601pub struct ClosureUseVar {
602 pub name: Box<str>,
603 pub by_ref: bool,
604 pub span: Span,
605}
606
607#[derive(Debug, Clone, Serialize)]
608pub struct ArrowFunctionExpr {
609 pub is_static: bool,
610 pub by_ref: bool,
611 pub params: Box<[Param]>,
612 pub return_type: Option<TypeHint>,
613 pub body: Box<Expr>,
614 pub attributes: Box<[Attribute]>,
615}
616
617#[derive(Debug, Clone, Serialize)]
618pub struct MatchExpr {
619 pub subject: Box<Expr>,
620 pub arms: Box<[MatchArm]>,
621 #[serde(skip)]
622 pub brace_start: u32,
623}
624
625#[derive(Debug, Clone, Serialize)]
626pub struct MatchArm {
627 pub conditions: Option<Box<[Expr]>>,
628 pub body: Expr,
629 pub span: Span,
630}
631
632#[derive(Debug, Clone, Serialize)]
633pub struct YieldExpr {
634 pub key: Option<Box<Expr>>,
635 pub value: Option<Box<Expr>>,
636 pub is_from: bool,
637}
638
639#[derive(Debug, Clone, Serialize)]
640pub struct CallableCreateExpr {
641 pub kind: CallableCreateKind,
642}
643
644#[derive(Debug, Clone, Serialize)]
645pub enum CallableCreateKind {
646 Function(Box<Expr>),
647 Method {
648 object: Box<Expr>,
649 method: Box<Expr>,
650 },
651 NullsafeMethod {
652 object: Box<Expr>,
653 method: Box<Expr>,
654 },
655 StaticMethod {
656 class: Box<Expr>,
657 method: Box<Expr>,
658 },
659}
660
661#[derive(Debug, Clone, Serialize)]
662pub enum StringPart {
663 Literal(Box<str>),
664 Expr(Expr),
665}
666
667#[derive(Debug, Clone, Serialize)]
672pub struct FunctionDecl {
673 pub name: Ident,
674 pub params: Box<[Param]>,
675 pub body: Box<Block>,
676 pub return_type: Option<TypeHint>,
677 pub by_ref: bool,
678 pub attributes: Box<[Attribute]>,
679 #[serde(skip_serializing_if = "Option::is_none")]
680 pub doc_comment: Option<Comment>,
681}
682
683#[derive(Debug, Clone, Serialize)]
684pub struct Param {
685 pub name: Ident,
686 pub type_hint: Option<TypeHint>,
687 pub default: Option<Expr>,
688 pub by_ref: bool,
689 pub variadic: bool,
690 pub is_readonly: bool,
691 pub is_final: bool,
692 pub visibility: Option<Visibility>,
693 pub set_visibility: Option<Visibility>,
694 pub attributes: Box<[Attribute]>,
695 #[serde(skip_serializing_if = "slice_is_empty")]
696 pub hooks: Box<[PropertyHook]>,
697 pub span: Span,
698}
699
700#[derive(Debug, Clone, Serialize)]
701pub struct ClassBody {
702 pub members: Box<[ClassMember]>,
703 #[serde(skip)]
704 pub span: Span,
705}
706
707#[derive(Debug, Clone, Serialize)]
708pub struct ClassDecl {
709 pub name: Option<Ident>,
710 pub modifiers: ClassModifiers,
711 pub extends: Option<Name>,
712 pub implements: Box<[Name]>,
713 #[serde(flatten)]
714 pub body: ClassBody,
715 pub attributes: Box<[Attribute]>,
716 #[serde(skip_serializing_if = "Option::is_none")]
717 pub doc_comment: Option<Comment>,
718}
719
720#[derive(Debug, Clone, Serialize)]
721pub struct ClassMember {
722 pub kind: ClassMemberKind,
723 pub span: Span,
724}
725
726#[derive(Debug, Clone, Serialize)]
727pub enum ClassMemberKind {
728 Property(PropertyDecl),
729 Method(MethodDecl),
730 ClassConst(ClassConstDecl),
731 TraitUse(TraitUseDecl),
732}
733
734#[derive(Debug, Clone, Serialize)]
735pub struct PropertyDecl {
736 pub name: Ident,
737 pub visibility: Option<Visibility>,
738 pub set_visibility: Option<Visibility>,
739 pub is_static: bool,
740 pub is_readonly: bool,
741 pub type_hint: Option<TypeHint>,
742 pub default: Option<Expr>,
743 pub attributes: Box<[Attribute]>,
744 #[serde(skip_serializing_if = "slice_is_empty")]
745 pub hooks: Box<[PropertyHook]>,
746 #[serde(skip_serializing_if = "Option::is_none")]
747 pub doc_comment: Option<Comment>,
748}
749
750#[derive(Debug, Clone, Serialize)]
751pub struct PropertyHook {
752 pub kind: PropertyHookKind,
753 pub body: PropertyHookBody,
754 pub is_final: bool,
755 pub by_ref: bool,
756 pub params: Box<[Param]>,
757 pub attributes: Box<[Attribute]>,
758 pub span: Span,
759}
760
761#[derive(Debug, Clone, Serialize)]
762pub enum PropertyHookBody {
763 Block(Box<Block>),
764 Expression(Expr),
765 Abstract,
766}
767
768#[derive(Debug, Clone, Serialize)]
769pub struct MethodDecl {
770 pub name: Ident,
771 pub visibility: Option<Visibility>,
772 pub is_static: bool,
773 pub is_abstract: bool,
774 pub is_final: bool,
775 pub by_ref: bool,
776 pub params: Box<[Param]>,
777 pub return_type: Option<TypeHint>,
778 pub body: Option<Box<Block>>,
779 pub attributes: Box<[Attribute]>,
780 #[serde(skip_serializing_if = "Option::is_none")]
781 pub doc_comment: Option<Comment>,
782}
783
784#[derive(Debug, Clone, Serialize)]
785pub struct ClassConstDecl {
786 pub name: Ident,
787 pub visibility: Option<Visibility>,
788 pub is_final: bool,
789 #[serde(skip_serializing_if = "Option::is_none")]
790 pub type_hint: Option<Box<TypeHint>>,
791 pub value: Expr,
792 pub attributes: Box<[Attribute]>,
793 #[serde(skip_serializing_if = "Option::is_none")]
794 pub doc_comment: Option<Comment>,
795}
796
797#[derive(Debug, Clone, Serialize)]
798pub struct TraitUseDecl {
799 pub traits: Box<[Name]>,
800 pub adaptations: Box<[TraitAdaptation]>,
801 #[serde(skip)]
802 pub adaptations_brace_start: Option<u32>,
803 #[serde(skip_serializing_if = "Option::is_none")]
804 pub doc_comment: Option<Comment>,
805}
806
807#[derive(Debug, Clone, Serialize)]
808pub struct TraitAdaptation {
809 pub kind: TraitAdaptationKind,
810 pub span: Span,
811}
812
813#[derive(Debug, Clone, Serialize)]
814pub enum TraitAdaptationKind {
815 Precedence {
816 trait_name: Name,
817 method: Name,
818 insteadof: Box<[Name]>,
819 },
820 Alias {
821 trait_name: Option<Name>,
822 method: Name,
823 new_modifier: Option<Visibility>,
824 new_name: Option<Name>,
825 },
826}
827
828#[derive(Debug, Clone, Serialize)]
829pub struct InterfaceDecl {
830 pub name: Ident,
831 pub extends: Box<[Name]>,
832 #[serde(flatten)]
833 pub body: ClassBody,
834 pub attributes: Box<[Attribute]>,
835 #[serde(skip_serializing_if = "Option::is_none")]
836 pub doc_comment: Option<Comment>,
837}
838
839#[derive(Debug, Clone, Serialize)]
840pub struct TraitDecl {
841 pub name: Ident,
842 #[serde(flatten)]
843 pub body: ClassBody,
844 pub attributes: Box<[Attribute]>,
845 #[serde(skip_serializing_if = "Option::is_none")]
846 pub doc_comment: Option<Comment>,
847}
848
849#[derive(Debug, Clone, Serialize)]
850pub struct EnumBody {
851 pub members: Box<[EnumMember]>,
852 #[serde(skip)]
853 pub span: Span,
854}
855
856#[derive(Debug, Clone, Serialize)]
857pub struct EnumDecl {
858 pub name: Ident,
859 pub scalar_type: Option<Name>,
860 pub implements: Box<[Name]>,
861 #[serde(flatten)]
862 pub body: EnumBody,
863 pub attributes: Box<[Attribute]>,
864 #[serde(skip_serializing_if = "Option::is_none")]
865 pub doc_comment: Option<Comment>,
866}
867
868#[derive(Debug, Clone, Serialize)]
869pub struct EnumMember {
870 pub kind: EnumMemberKind,
871 pub span: Span,
872}
873
874#[derive(Debug, Clone, Serialize)]
875pub enum EnumMemberKind {
876 Case(EnumCase),
877 Method(MethodDecl),
878 ClassConst(ClassConstDecl),
879 TraitUse(TraitUseDecl),
880}
881
882#[derive(Debug, Clone, Serialize)]
883pub struct EnumCase {
884 pub name: Ident,
885 pub value: Option<Expr>,
886 pub attributes: Box<[Attribute]>,
887 #[serde(skip_serializing_if = "Option::is_none")]
888 pub doc_comment: Option<Comment>,
889}
890
891fn owned_ident(ident: arena_ast::Ident<'_>) -> Ident {
896 ident.as_str().map(|s| s.into())
897}
898
899fn owned_name(name: &arena_ast::Name<'_, '_>) -> Name {
900 match name {
901 arena_ast::Name::Simple { value, span } => Name {
902 parts: vec![Box::from(*value)].into_boxed_slice(),
903 kind: NameKind::Unqualified,
904 span: *span,
905 },
906 arena_ast::Name::Complex { parts, kind, span } => Name {
907 parts: parts
908 .iter()
909 .map(|s| Box::from(*s))
910 .collect::<Vec<_>>()
911 .into_boxed_slice(),
912 kind: *kind,
913 span: *span,
914 },
915 arena_ast::Name::Error { span } => Name {
916 parts: Box::from([]),
917 kind: NameKind::Error,
918 span: *span,
919 },
920 }
921}
922
923fn owned_comment(c: &arena_ast::Comment<'_>) -> Comment {
924 Comment {
925 kind: c.kind,
926 text: c.text.into(),
927 span: c.span,
928 }
929}
930
931fn owned_opt_comment(c: &Option<arena_ast::Comment<'_>>) -> Option<Comment> {
932 c.as_ref().map(owned_comment)
933}
934
935fn owned_type_hint(th: &arena_ast::TypeHint<'_, '_>) -> TypeHint {
936 TypeHint {
937 kind: owned_type_hint_kind(&th.kind),
938 span: th.span,
939 }
940}
941
942fn owned_type_hint_kind(k: &arena_ast::TypeHintKind<'_, '_>) -> TypeHintKind {
943 match k {
944 arena_ast::TypeHintKind::Named(n) => TypeHintKind::Named(owned_name(n)),
945 arena_ast::TypeHintKind::Keyword(b, span) => TypeHintKind::Keyword(*b, *span),
946 arena_ast::TypeHintKind::Nullable(inner) => {
947 TypeHintKind::Nullable(Box::new(owned_type_hint(inner)))
948 }
949 arena_ast::TypeHintKind::Union(types) => TypeHintKind::Union(
950 types
951 .iter()
952 .map(owned_type_hint)
953 .collect::<Vec<_>>()
954 .into_boxed_slice(),
955 ),
956 arena_ast::TypeHintKind::Intersection(types) => TypeHintKind::Intersection(
957 types
958 .iter()
959 .map(owned_type_hint)
960 .collect::<Vec<_>>()
961 .into_boxed_slice(),
962 ),
963 }
964}
965
966fn owned_arg(arg: &arena_ast::Arg<'_, '_>) -> Arg {
967 Arg {
968 name: arg.name.as_ref().map(owned_name),
969 value: arg.value.as_ref().map(owned_expr),
970 unpack: arg.unpack,
971 by_ref: arg.by_ref,
972 span: arg.span,
973 }
974}
975
976fn owned_args(args: &[arena_ast::Arg<'_, '_>]) -> Box<[Arg]> {
977 args.iter()
978 .map(owned_arg)
979 .collect::<Vec<_>>()
980 .into_boxed_slice()
981}
982
983fn owned_attr(attr: &arena_ast::Attribute<'_, '_>) -> Attribute {
984 Attribute {
985 name: owned_name(&attr.name),
986 args: owned_args(&attr.args),
987 span: attr.span,
988 }
989}
990
991fn owned_attrs(attrs: &[arena_ast::Attribute<'_, '_>]) -> Box<[Attribute]> {
992 attrs
993 .iter()
994 .map(owned_attr)
995 .collect::<Vec<_>>()
996 .into_boxed_slice()
997}
998
999fn owned_string_parts(parts: &[arena_ast::StringPart<'_, '_>]) -> Box<[StringPart]> {
1000 parts
1001 .iter()
1002 .map(|p| match p {
1003 arena_ast::StringPart::Literal(s) => StringPart::Literal(Box::from(*s)),
1004 arena_ast::StringPart::Expr(e) => StringPart::Expr(owned_expr(e)),
1005 })
1006 .collect::<Vec<_>>()
1007 .into_boxed_slice()
1008}
1009
1010pub fn to_owned_expr(expr: &arena_ast::Expr<'_, '_>) -> Expr {
1012 owned_expr(expr)
1013}
1014
1015pub fn to_owned_name(name: &arena_ast::Name<'_, '_>) -> Name {
1017 owned_name(name)
1018}
1019
1020pub fn to_owned_type_hint(hint: &arena_ast::TypeHint<'_, '_>) -> TypeHint {
1022 owned_type_hint(hint)
1023}
1024
1025fn owned_expr(expr: &arena_ast::Expr<'_, '_>) -> Expr {
1026 Expr {
1027 kind: owned_expr_kind(&expr.kind),
1028 span: expr.span,
1029 }
1030}
1031
1032fn owned_exprs(exprs: &[arena_ast::Expr<'_, '_>]) -> Box<[Expr]> {
1033 exprs
1034 .iter()
1035 .map(owned_expr)
1036 .collect::<Vec<_>>()
1037 .into_boxed_slice()
1038}
1039
1040fn owned_expr_kind(k: &arena_ast::ExprKind<'_, '_>) -> ExprKind {
1041 match k {
1042 arena_ast::ExprKind::Int(v) => ExprKind::Int(*v),
1043 arena_ast::ExprKind::Float(v) => ExprKind::Float(*v),
1044 arena_ast::ExprKind::String(s) => ExprKind::String(Box::from(*s)),
1045 arena_ast::ExprKind::InterpolatedString(parts) => {
1046 ExprKind::InterpolatedString(owned_string_parts(parts))
1047 }
1048 arena_ast::ExprKind::Heredoc { label, parts } => ExprKind::Heredoc {
1049 label: Box::from(*label),
1050 parts: owned_string_parts(parts),
1051 },
1052 arena_ast::ExprKind::Nowdoc { label, value } => ExprKind::Nowdoc {
1053 label: Box::from(*label),
1054 value: Box::from(*value),
1055 },
1056 arena_ast::ExprKind::ShellExec(parts) => ExprKind::ShellExec(owned_string_parts(parts)),
1057 arena_ast::ExprKind::Bool(v) => ExprKind::Bool(*v),
1058 arena_ast::ExprKind::Null => ExprKind::Null,
1059 arena_ast::ExprKind::Variable(s) => ExprKind::Variable(s.as_str().into()),
1060 arena_ast::ExprKind::VariableVariable(inner) => {
1061 ExprKind::VariableVariable(Box::new(owned_expr(inner)))
1062 }
1063 arena_ast::ExprKind::Identifier(s) => ExprKind::Identifier(s.as_str().into()),
1064 arena_ast::ExprKind::Assign(a) => ExprKind::Assign(AssignExpr {
1065 target: Box::new(owned_expr(a.target)),
1066 op: a.op,
1067 value: Box::new(owned_expr(a.value)),
1068 by_ref: a.by_ref,
1069 }),
1070 arena_ast::ExprKind::Binary(b) => ExprKind::Binary(BinaryExpr {
1071 left: Box::new(owned_expr(b.left)),
1072 op: b.op,
1073 right: Box::new(owned_expr(b.right)),
1074 }),
1075 arena_ast::ExprKind::UnaryPrefix(u) => ExprKind::UnaryPrefix(UnaryPrefixExpr {
1076 op: u.op,
1077 operand: Box::new(owned_expr(u.operand)),
1078 }),
1079 arena_ast::ExprKind::UnaryPostfix(u) => ExprKind::UnaryPostfix(UnaryPostfixExpr {
1080 operand: Box::new(owned_expr(u.operand)),
1081 op: u.op,
1082 }),
1083 arena_ast::ExprKind::Ternary(t) => ExprKind::Ternary(TernaryExpr {
1084 condition: Box::new(owned_expr(t.condition)),
1085 then_expr: t.then_expr.map(|e| Box::new(owned_expr(e))),
1086 else_expr: Box::new(owned_expr(t.else_expr)),
1087 }),
1088 arena_ast::ExprKind::NullCoalesce(n) => ExprKind::NullCoalesce(NullCoalesceExpr {
1089 left: Box::new(owned_expr(n.left)),
1090 right: Box::new(owned_expr(n.right)),
1091 }),
1092 arena_ast::ExprKind::FunctionCall(f) => ExprKind::FunctionCall(FunctionCallExpr {
1093 name: Box::new(owned_expr(f.name)),
1094 args: owned_args(&f.args),
1095 }),
1096 arena_ast::ExprKind::Array(elems) => ExprKind::Array(
1097 elems
1098 .iter()
1099 .map(|e| ArrayElement {
1100 key: e.key.as_ref().map(owned_expr),
1101 value: owned_expr(&e.value),
1102 unpack: e.unpack,
1103 by_ref: e.by_ref,
1104 span: e.span,
1105 })
1106 .collect::<Vec<_>>()
1107 .into_boxed_slice(),
1108 ),
1109 arena_ast::ExprKind::ArrayAccess(a) => ExprKind::ArrayAccess(ArrayAccessExpr {
1110 array: Box::new(owned_expr(a.array)),
1111 index: a.index.map(|e| Box::new(owned_expr(e))),
1112 }),
1113 arena_ast::ExprKind::Print(e) => ExprKind::Print(Box::new(owned_expr(e))),
1114 arena_ast::ExprKind::Parenthesized(e) => ExprKind::Parenthesized(Box::new(owned_expr(e))),
1115 arena_ast::ExprKind::Cast(kind, e) => ExprKind::Cast(*kind, Box::new(owned_expr(e))),
1116 arena_ast::ExprKind::ErrorSuppress(e) => ExprKind::ErrorSuppress(Box::new(owned_expr(e))),
1117 arena_ast::ExprKind::Isset(exprs) => ExprKind::Isset(owned_exprs(exprs)),
1118 arena_ast::ExprKind::Empty(e) => ExprKind::Empty(Box::new(owned_expr(e))),
1119 arena_ast::ExprKind::Include(kind, e) => ExprKind::Include(*kind, Box::new(owned_expr(e))),
1120 arena_ast::ExprKind::Eval(e) => ExprKind::Eval(Box::new(owned_expr(e))),
1121 arena_ast::ExprKind::Exit(e) => ExprKind::Exit(e.map(|e| Box::new(owned_expr(e)))),
1122 arena_ast::ExprKind::MagicConst(m) => ExprKind::MagicConst(*m),
1123 arena_ast::ExprKind::Clone(e) => ExprKind::Clone(Box::new(owned_expr(e))),
1124 arena_ast::ExprKind::CloneWith(obj, props) => {
1125 ExprKind::CloneWith(Box::new(owned_expr(obj)), Box::new(owned_expr(props)))
1126 }
1127 arena_ast::ExprKind::New(n) => ExprKind::New(NewExpr {
1128 class: Box::new(owned_expr(n.class)),
1129 args: owned_args(&n.args),
1130 }),
1131 arena_ast::ExprKind::PropertyAccess(p) => ExprKind::PropertyAccess(PropertyAccessExpr {
1132 object: Box::new(owned_expr(p.object)),
1133 property: Box::new(owned_expr(p.property)),
1134 }),
1135 arena_ast::ExprKind::NullsafePropertyAccess(p) => {
1136 ExprKind::NullsafePropertyAccess(PropertyAccessExpr {
1137 object: Box::new(owned_expr(p.object)),
1138 property: Box::new(owned_expr(p.property)),
1139 })
1140 }
1141 arena_ast::ExprKind::MethodCall(m) => ExprKind::MethodCall(Box::new(MethodCallExpr {
1142 object: Box::new(owned_expr(m.object)),
1143 method: Box::new(owned_expr(m.method)),
1144 args: owned_args(&m.args),
1145 })),
1146 arena_ast::ExprKind::NullsafeMethodCall(m) => {
1147 ExprKind::NullsafeMethodCall(Box::new(MethodCallExpr {
1148 object: Box::new(owned_expr(m.object)),
1149 method: Box::new(owned_expr(m.method)),
1150 args: owned_args(&m.args),
1151 }))
1152 }
1153 arena_ast::ExprKind::StaticPropertyAccess(s) => {
1154 ExprKind::StaticPropertyAccess(StaticAccessExpr {
1155 class: Box::new(owned_expr(s.class)),
1156 member: Box::new(owned_expr(s.member)),
1157 })
1158 }
1159 arena_ast::ExprKind::StaticMethodCall(s) => {
1160 ExprKind::StaticMethodCall(Box::new(StaticMethodCallExpr {
1161 class: Box::new(owned_expr(s.class)),
1162 method: Box::new(owned_expr(s.method)),
1163 args: owned_args(&s.args),
1164 }))
1165 }
1166 arena_ast::ExprKind::StaticDynMethodCall(s) => {
1167 ExprKind::StaticDynMethodCall(Box::new(StaticDynMethodCallExpr {
1168 class: Box::new(owned_expr(s.class)),
1169 method: Box::new(owned_expr(s.method)),
1170 args: owned_args(&s.args),
1171 }))
1172 }
1173 arena_ast::ExprKind::ClassConstAccess(s) => ExprKind::ClassConstAccess(StaticAccessExpr {
1174 class: Box::new(owned_expr(s.class)),
1175 member: Box::new(owned_expr(s.member)),
1176 }),
1177 arena_ast::ExprKind::ClassConstAccessDynamic { class, member } => {
1178 ExprKind::ClassConstAccessDynamic {
1179 class: Box::new(owned_expr(class)),
1180 member: Box::new(owned_expr(member)),
1181 }
1182 }
1183 arena_ast::ExprKind::StaticPropertyAccessDynamic { class, member } => {
1184 ExprKind::StaticPropertyAccessDynamic {
1185 class: Box::new(owned_expr(class)),
1186 member: Box::new(owned_expr(member)),
1187 }
1188 }
1189 arena_ast::ExprKind::Closure(c) => ExprKind::Closure(Box::new(ClosureExpr {
1190 is_static: c.is_static,
1191 by_ref: c.by_ref,
1192 params: owned_params(&c.params),
1193 use_vars: c
1194 .use_vars
1195 .iter()
1196 .map(|v| ClosureUseVar {
1197 name: v.name.into(),
1198 by_ref: v.by_ref,
1199 span: v.span,
1200 })
1201 .collect::<Vec<_>>()
1202 .into_boxed_slice(),
1203 return_type: c.return_type.as_ref().map(owned_type_hint),
1204 body: Box::new(owned_block(c.body)),
1205 attributes: owned_attrs(&c.attributes),
1206 })),
1207 arena_ast::ExprKind::ArrowFunction(f) => {
1208 ExprKind::ArrowFunction(Box::new(ArrowFunctionExpr {
1209 is_static: f.is_static,
1210 by_ref: f.by_ref,
1211 params: owned_params(&f.params),
1212 return_type: f.return_type.as_ref().map(owned_type_hint),
1213 body: Box::new(owned_expr(f.body)),
1214 attributes: owned_attrs(&f.attributes),
1215 }))
1216 }
1217 arena_ast::ExprKind::Match(m) => ExprKind::Match(MatchExpr {
1218 subject: Box::new(owned_expr(m.subject)),
1219 arms: m
1220 .arms
1221 .iter()
1222 .map(|arm| MatchArm {
1223 conditions: arm.conditions.as_ref().map(|conds| owned_exprs(conds)),
1224 body: owned_expr(&arm.body),
1225 span: arm.span,
1226 })
1227 .collect::<Vec<_>>()
1228 .into_boxed_slice(),
1229 brace_start: m.brace_start,
1230 }),
1231 arena_ast::ExprKind::ThrowExpr(e) => ExprKind::ThrowExpr(Box::new(owned_expr(e))),
1232 arena_ast::ExprKind::Yield(y) => ExprKind::Yield(YieldExpr {
1233 key: y.key.map(|e| Box::new(owned_expr(e))),
1234 value: y.value.map(|e| Box::new(owned_expr(e))),
1235 is_from: y.is_from,
1236 }),
1237 arena_ast::ExprKind::AnonymousClass(cls) => {
1238 ExprKind::AnonymousClass(Box::new(owned_class_decl(cls)))
1239 }
1240 arena_ast::ExprKind::CallableCreate(c) => ExprKind::CallableCreate(CallableCreateExpr {
1241 kind: match &c.kind {
1242 arena_ast::CallableCreateKind::Function(e) => {
1243 CallableCreateKind::Function(Box::new(owned_expr(e)))
1244 }
1245 arena_ast::CallableCreateKind::Method { object, method } => {
1246 CallableCreateKind::Method {
1247 object: Box::new(owned_expr(object)),
1248 method: Box::new(owned_expr(method)),
1249 }
1250 }
1251 arena_ast::CallableCreateKind::NullsafeMethod { object, method } => {
1252 CallableCreateKind::NullsafeMethod {
1253 object: Box::new(owned_expr(object)),
1254 method: Box::new(owned_expr(method)),
1255 }
1256 }
1257 arena_ast::CallableCreateKind::StaticMethod { class, method } => {
1258 CallableCreateKind::StaticMethod {
1259 class: Box::new(owned_expr(class)),
1260 method: Box::new(owned_expr(method)),
1261 }
1262 }
1263 },
1264 }),
1265 arena_ast::ExprKind::Omit => ExprKind::Omit,
1266 arena_ast::ExprKind::Error => ExprKind::Error,
1267 }
1268}
1269
1270fn owned_param(p: &arena_ast::Param<'_, '_>) -> Param {
1271 Param {
1272 name: owned_ident(p.name),
1273 type_hint: p.type_hint.as_ref().map(owned_type_hint),
1274 default: p.default.as_ref().map(owned_expr),
1275 by_ref: p.by_ref,
1276 variadic: p.variadic,
1277 is_readonly: p.is_readonly,
1278 is_final: p.is_final,
1279 visibility: p.visibility,
1280 set_visibility: p.set_visibility,
1281 attributes: owned_attrs(&p.attributes),
1282 hooks: owned_hooks(&p.hooks),
1283 span: p.span,
1284 }
1285}
1286
1287fn owned_params(params: &[arena_ast::Param<'_, '_>]) -> Box<[Param]> {
1288 params
1289 .iter()
1290 .map(owned_param)
1291 .collect::<Vec<_>>()
1292 .into_boxed_slice()
1293}
1294
1295fn owned_hook(h: &arena_ast::PropertyHook<'_, '_>) -> PropertyHook {
1296 PropertyHook {
1297 kind: h.kind,
1298 body: match &h.body {
1299 arena_ast::PropertyHookBody::Block(block) => {
1300 PropertyHookBody::Block(Box::new(owned_block(block)))
1301 }
1302 arena_ast::PropertyHookBody::Expression(e) => {
1303 PropertyHookBody::Expression(owned_expr(e))
1304 }
1305 arena_ast::PropertyHookBody::Abstract => PropertyHookBody::Abstract,
1306 },
1307 is_final: h.is_final,
1308 by_ref: h.by_ref,
1309 params: owned_params(&h.params),
1310 attributes: owned_attrs(&h.attributes),
1311 span: h.span,
1312 }
1313}
1314
1315fn owned_hooks(hooks: &[arena_ast::PropertyHook<'_, '_>]) -> Box<[PropertyHook]> {
1316 hooks
1317 .iter()
1318 .map(owned_hook)
1319 .collect::<Vec<_>>()
1320 .into_boxed_slice()
1321}
1322
1323fn owned_stmts(stmts: &[arena_ast::Stmt<'_, '_>]) -> Box<[Stmt]> {
1324 stmts
1325 .iter()
1326 .map(owned_stmt)
1327 .collect::<Vec<_>>()
1328 .into_boxed_slice()
1329}
1330
1331pub fn to_owned_stmt(stmt: &arena_ast::Stmt<'_, '_>) -> Stmt {
1333 owned_stmt(stmt)
1334}
1335
1336fn owned_block(block: &arena_ast::Block<'_, '_>) -> Block {
1337 Block {
1338 stmts: owned_stmts(&block.stmts),
1339 span: block.span,
1340 }
1341}
1342
1343fn owned_stmt(stmt: &arena_ast::Stmt<'_, '_>) -> Stmt {
1344 Stmt {
1345 kind: owned_stmt_kind(&stmt.kind),
1346 span: stmt.span,
1347 doc_comment: stmt.doc_comment.map(owned_comment),
1348 }
1349}
1350
1351fn owned_stmt_kind(k: &arena_ast::StmtKind<'_, '_>) -> StmtKind {
1352 match k {
1353 arena_ast::StmtKind::Expression(e) => StmtKind::Expression(Box::new(owned_expr(e))),
1354 arena_ast::StmtKind::Echo(exprs) => StmtKind::Echo(owned_exprs(exprs)),
1355 arena_ast::StmtKind::Return(e) => StmtKind::Return(e.map(|e| Box::new(owned_expr(e)))),
1356 arena_ast::StmtKind::Block(block) => StmtKind::Block(Box::new(owned_block(block))),
1357 arena_ast::StmtKind::If(s) => StmtKind::If(Box::new(IfStmt {
1358 condition: owned_expr(&s.condition),
1359 then_branch: Box::new(owned_stmt(s.then_branch)),
1360 elseif_branches: s
1361 .elseif_branches
1362 .iter()
1363 .map(|b| ElseIfBranch {
1364 condition: owned_expr(&b.condition),
1365 body: owned_stmt(&b.body),
1366 span: b.span,
1367 })
1368 .collect::<Vec<_>>()
1369 .into_boxed_slice(),
1370 else_branch: s.else_branch.map(|b| Box::new(owned_stmt(b))),
1371 else_kw_start: s.else_kw_start,
1372 uses_alternative: s.uses_alternative,
1373 })),
1374 arena_ast::StmtKind::While(s) => StmtKind::While(Box::new(WhileStmt {
1375 condition: owned_expr(&s.condition),
1376 body: Box::new(owned_stmt(s.body)),
1377 uses_alternative: s.uses_alternative,
1378 })),
1379 arena_ast::StmtKind::For(s) => StmtKind::For(Box::new(ForStmt {
1380 init: owned_exprs(&s.init),
1381 condition: owned_exprs(&s.condition),
1382 update: owned_exprs(&s.update),
1383 body: Box::new(owned_stmt(s.body)),
1384 uses_alternative: s.uses_alternative,
1385 })),
1386 arena_ast::StmtKind::Foreach(s) => StmtKind::Foreach(Box::new(ForeachStmt {
1387 expr: owned_expr(&s.expr),
1388 key: s.key.as_ref().map(owned_expr),
1389 value: owned_expr(&s.value),
1390 body: Box::new(owned_stmt(s.body)),
1391 uses_alternative: s.uses_alternative,
1392 })),
1393 arena_ast::StmtKind::DoWhile(s) => StmtKind::DoWhile(Box::new(DoWhileStmt {
1394 body: Box::new(owned_stmt(s.body)),
1395 condition: owned_expr(&s.condition),
1396 })),
1397 arena_ast::StmtKind::Function(f) => StmtKind::Function(Box::new(owned_function_decl(f))),
1398 arena_ast::StmtKind::Break(e) => StmtKind::Break(e.map(|e| Box::new(owned_expr(e)))),
1399 arena_ast::StmtKind::Continue(e) => StmtKind::Continue(e.map(|e| Box::new(owned_expr(e)))),
1400 arena_ast::StmtKind::Switch(s) => StmtKind::Switch(Box::new(SwitchStmt {
1401 expr: owned_expr(&s.expr),
1402 body: SwitchBody {
1403 cases: s
1404 .body
1405 .cases
1406 .iter()
1407 .map(|c| SwitchCase {
1408 value: c.value.as_ref().map(owned_expr),
1409 body: owned_stmts(&c.body),
1410 span: c.span,
1411 })
1412 .collect::<Vec<_>>()
1413 .into_boxed_slice(),
1414 span: s.body.span,
1415 },
1416 uses_alternative: s.uses_alternative,
1417 })),
1418 arena_ast::StmtKind::Goto(ident) => StmtKind::Goto(owned_ident(*ident)),
1419 arena_ast::StmtKind::Label(s) => StmtKind::Label(Box::from(*s)),
1420 arena_ast::StmtKind::Declare(d) => StmtKind::Declare(Box::new(DeclareStmt {
1421 directives: d
1422 .directives
1423 .iter()
1424 .map(|(k, v)| (Box::from(*k), owned_expr(v)))
1425 .collect::<Vec<_>>()
1426 .into_boxed_slice(),
1427 body: d.body.map(|b| Box::new(owned_stmt(b))),
1428 uses_alternative: d.uses_alternative,
1429 })),
1430 arena_ast::StmtKind::Unset(exprs) => StmtKind::Unset(owned_exprs(exprs)),
1431 arena_ast::StmtKind::Throw(e) => StmtKind::Throw(Box::new(owned_expr(e))),
1432 arena_ast::StmtKind::TryCatch(t) => StmtKind::TryCatch(Box::new(TryCatchStmt {
1433 body: Box::new(owned_block(t.body)),
1434 catches: t
1435 .catches
1436 .iter()
1437 .map(|c| CatchClause {
1438 types: c
1439 .types
1440 .iter()
1441 .map(owned_name)
1442 .collect::<Vec<_>>()
1443 .into_boxed_slice(),
1444 var: c.var.map(Box::from),
1445 body: Box::new(owned_block(c.body)),
1446 span: c.span,
1447 })
1448 .collect::<Vec<_>>()
1449 .into_boxed_slice(),
1450 finally: t.finally.map(|f| Box::new(owned_block(f))),
1451 finally_kw_start: t.finally_kw_start,
1452 })),
1453 arena_ast::StmtKind::Global(exprs) => StmtKind::Global(owned_exprs(exprs)),
1454 arena_ast::StmtKind::Class(cls) => StmtKind::Class(Box::new(owned_class_decl(cls))),
1455 arena_ast::StmtKind::Interface(iface) => {
1456 StmtKind::Interface(Box::new(owned_interface_decl(iface)))
1457 }
1458 arena_ast::StmtKind::Trait(tr) => StmtKind::Trait(Box::new(owned_trait_decl(tr))),
1459 arena_ast::StmtKind::Enum(en) => StmtKind::Enum(Box::new(owned_enum_decl(en))),
1460 arena_ast::StmtKind::Namespace(ns) => StmtKind::Namespace(Box::new(NamespaceDecl {
1461 name: ns.name.as_ref().map(owned_name),
1462 body: match &ns.body {
1463 arena_ast::NamespaceBody::Braced(block) => {
1464 NamespaceBody::Braced(Box::new(owned_block(block)))
1465 }
1466 arena_ast::NamespaceBody::Simple => NamespaceBody::Simple,
1467 },
1468 })),
1469 arena_ast::StmtKind::Use(u) => StmtKind::Use(Box::new(UseDecl {
1470 kind: u.kind,
1471 uses: u
1472 .uses
1473 .iter()
1474 .map(|item| UseItem {
1475 name: owned_name(&item.name),
1476 alias: item.alias.map(Box::from),
1477 kind: item.kind,
1478 span: item.span,
1479 })
1480 .collect::<Vec<_>>()
1481 .into_boxed_slice(),
1482 })),
1483 arena_ast::StmtKind::Const(items) => StmtKind::Const(
1484 items
1485 .iter()
1486 .map(|item| ConstItem {
1487 name: owned_ident(item.name),
1488 value: owned_expr(&item.value),
1489 attributes: owned_attrs(&item.attributes),
1490 span: item.span,
1491 doc_comment: owned_opt_comment(&item.doc_comment),
1492 })
1493 .collect::<Vec<_>>()
1494 .into_boxed_slice(),
1495 ),
1496 arena_ast::StmtKind::StaticVar(vars) => StmtKind::StaticVar(
1497 vars.iter()
1498 .map(|v| StaticVar {
1499 name: owned_ident(v.name),
1500 default: v.default.as_ref().map(owned_expr),
1501 span: v.span,
1502 })
1503 .collect::<Vec<_>>()
1504 .into_boxed_slice(),
1505 ),
1506 arena_ast::StmtKind::HaltCompiler(s) => StmtKind::HaltCompiler(Box::from(*s)),
1507 arena_ast::StmtKind::Nop => StmtKind::Nop,
1508 arena_ast::StmtKind::InlineHtml(s) => StmtKind::InlineHtml(Box::from(*s)),
1509 arena_ast::StmtKind::Error => StmtKind::Error,
1510 }
1511}
1512
1513fn owned_function_decl(f: &arena_ast::FunctionDecl<'_, '_>) -> FunctionDecl {
1514 FunctionDecl {
1515 name: owned_ident(f.name),
1516 params: owned_params(&f.params),
1517 body: Box::new(owned_block(f.body)),
1518 return_type: f.return_type.as_ref().map(owned_type_hint),
1519 by_ref: f.by_ref,
1520 attributes: owned_attrs(&f.attributes),
1521 doc_comment: owned_opt_comment(&f.doc_comment),
1522 }
1523}
1524
1525fn owned_class_member(m: &arena_ast::ClassMember<'_, '_>) -> ClassMember {
1526 ClassMember {
1527 kind: match &m.kind {
1528 arena_ast::ClassMemberKind::Property(p) => ClassMemberKind::Property(PropertyDecl {
1529 name: owned_ident(p.name),
1530 visibility: p.visibility,
1531 set_visibility: p.set_visibility,
1532 is_static: p.is_static,
1533 is_readonly: p.is_readonly,
1534 type_hint: p.type_hint.as_ref().map(owned_type_hint),
1535 default: p.default.as_ref().map(owned_expr),
1536 attributes: owned_attrs(&p.attributes),
1537 hooks: owned_hooks(&p.hooks),
1538 doc_comment: owned_opt_comment(&p.doc_comment),
1539 }),
1540 arena_ast::ClassMemberKind::Method(m) => ClassMemberKind::Method(MethodDecl {
1541 name: owned_ident(m.name),
1542 visibility: m.visibility,
1543 is_static: m.is_static,
1544 is_abstract: m.is_abstract,
1545 is_final: m.is_final,
1546 by_ref: m.by_ref,
1547 params: owned_params(&m.params),
1548 return_type: m.return_type.as_ref().map(owned_type_hint),
1549 body: m.body.map(|b| Box::new(owned_block(b))),
1550 attributes: owned_attrs(&m.attributes),
1551 doc_comment: owned_opt_comment(&m.doc_comment),
1552 }),
1553 arena_ast::ClassMemberKind::ClassConst(c) => {
1554 ClassMemberKind::ClassConst(owned_class_const(c))
1555 }
1556 arena_ast::ClassMemberKind::TraitUse(t) => {
1557 ClassMemberKind::TraitUse(owned_trait_use(t))
1558 }
1559 },
1560 span: m.span,
1561 }
1562}
1563
1564fn owned_class_members(members: &[arena_ast::ClassMember<'_, '_>]) -> Box<[ClassMember]> {
1565 members
1566 .iter()
1567 .map(owned_class_member)
1568 .collect::<Vec<_>>()
1569 .into_boxed_slice()
1570}
1571
1572fn owned_class_const(c: &arena_ast::ClassConstDecl<'_, '_>) -> ClassConstDecl {
1573 ClassConstDecl {
1574 name: owned_ident(c.name),
1575 visibility: c.visibility,
1576 is_final: c.is_final,
1577 type_hint: c.type_hint.map(|th| Box::new(owned_type_hint(th))),
1578 value: owned_expr(&c.value),
1579 attributes: owned_attrs(&c.attributes),
1580 doc_comment: owned_opt_comment(&c.doc_comment),
1581 }
1582}
1583
1584fn owned_trait_use(t: &arena_ast::TraitUseDecl<'_, '_>) -> TraitUseDecl {
1585 TraitUseDecl {
1586 traits: t
1587 .traits
1588 .iter()
1589 .map(owned_name)
1590 .collect::<Vec<_>>()
1591 .into_boxed_slice(),
1592 adaptations: t
1593 .adaptations
1594 .iter()
1595 .map(|a| TraitAdaptation {
1596 kind: match &a.kind {
1597 arena_ast::TraitAdaptationKind::Precedence {
1598 trait_name,
1599 method,
1600 insteadof,
1601 } => TraitAdaptationKind::Precedence {
1602 trait_name: owned_name(trait_name),
1603 method: owned_name(method),
1604 insteadof: insteadof
1605 .iter()
1606 .map(owned_name)
1607 .collect::<Vec<_>>()
1608 .into_boxed_slice(),
1609 },
1610 arena_ast::TraitAdaptationKind::Alias {
1611 trait_name,
1612 method,
1613 new_modifier,
1614 new_name,
1615 } => TraitAdaptationKind::Alias {
1616 trait_name: trait_name.as_ref().map(owned_name),
1617 method: owned_name(method),
1618 new_modifier: *new_modifier,
1619 new_name: new_name.as_ref().map(owned_name),
1620 },
1621 },
1622 span: a.span,
1623 })
1624 .collect::<Vec<_>>()
1625 .into_boxed_slice(),
1626 adaptations_brace_start: t.adaptations_brace_start,
1627 doc_comment: owned_opt_comment(&t.doc_comment),
1628 }
1629}
1630
1631fn owned_class_decl(cls: &arena_ast::ClassDecl<'_, '_>) -> ClassDecl {
1632 ClassDecl {
1633 name: cls
1634 .name
1635 .map(|ident| Some(owned_ident(ident)))
1636 .unwrap_or(None),
1637 modifiers: cls.modifiers.clone(),
1638 extends: cls.extends.as_ref().map(owned_name),
1639 implements: cls
1640 .implements
1641 .iter()
1642 .map(owned_name)
1643 .collect::<Vec<_>>()
1644 .into_boxed_slice(),
1645 body: ClassBody {
1646 members: owned_class_members(&cls.body.members),
1647 span: cls.body.span,
1648 },
1649 attributes: owned_attrs(&cls.attributes),
1650 doc_comment: owned_opt_comment(&cls.doc_comment),
1651 }
1652}
1653
1654fn owned_interface_decl(iface: &arena_ast::InterfaceDecl<'_, '_>) -> InterfaceDecl {
1655 InterfaceDecl {
1656 name: owned_ident(iface.name),
1657 extends: iface
1658 .extends
1659 .iter()
1660 .map(owned_name)
1661 .collect::<Vec<_>>()
1662 .into_boxed_slice(),
1663 body: ClassBody {
1664 members: owned_class_members(&iface.body.members),
1665 span: iface.body.span,
1666 },
1667 attributes: owned_attrs(&iface.attributes),
1668 doc_comment: owned_opt_comment(&iface.doc_comment),
1669 }
1670}
1671
1672fn owned_trait_decl(tr: &arena_ast::TraitDecl<'_, '_>) -> TraitDecl {
1673 TraitDecl {
1674 name: owned_ident(tr.name),
1675 body: ClassBody {
1676 members: owned_class_members(&tr.body.members),
1677 span: tr.body.span,
1678 },
1679 attributes: owned_attrs(&tr.attributes),
1680 doc_comment: owned_opt_comment(&tr.doc_comment),
1681 }
1682}
1683
1684fn owned_enum_decl(en: &arena_ast::EnumDecl<'_, '_>) -> EnumDecl {
1685 EnumDecl {
1686 name: owned_ident(en.name),
1687 scalar_type: en.scalar_type.as_ref().map(owned_name),
1688 implements: en
1689 .implements
1690 .iter()
1691 .map(owned_name)
1692 .collect::<Vec<_>>()
1693 .into_boxed_slice(),
1694 body: EnumBody {
1695 members: en
1696 .body
1697 .members
1698 .iter()
1699 .map(|m| EnumMember {
1700 kind: match &m.kind {
1701 arena_ast::EnumMemberKind::Case(c) => EnumMemberKind::Case(EnumCase {
1702 name: owned_ident(c.name),
1703 value: c.value.as_ref().map(owned_expr),
1704 attributes: owned_attrs(&c.attributes),
1705 doc_comment: owned_opt_comment(&c.doc_comment),
1706 }),
1707 arena_ast::EnumMemberKind::Method(m) => {
1708 EnumMemberKind::Method(MethodDecl {
1709 name: owned_ident(m.name),
1710 visibility: m.visibility,
1711 is_static: m.is_static,
1712 is_abstract: m.is_abstract,
1713 is_final: m.is_final,
1714 by_ref: m.by_ref,
1715 params: owned_params(&m.params),
1716 return_type: m.return_type.as_ref().map(owned_type_hint),
1717 body: m.body.map(|b| Box::new(owned_block(b))),
1718 attributes: owned_attrs(&m.attributes),
1719 doc_comment: owned_opt_comment(&m.doc_comment),
1720 })
1721 }
1722 arena_ast::EnumMemberKind::ClassConst(c) => {
1723 EnumMemberKind::ClassConst(owned_class_const(c))
1724 }
1725 arena_ast::EnumMemberKind::TraitUse(t) => {
1726 EnumMemberKind::TraitUse(owned_trait_use(t))
1727 }
1728 },
1729 span: m.span,
1730 })
1731 .collect::<Vec<_>>()
1732 .into_boxed_slice(),
1733 span: en.body.span,
1734 },
1735 attributes: owned_attrs(&en.attributes),
1736 doc_comment: owned_opt_comment(&en.doc_comment),
1737 }
1738}
1739
1740pub fn to_owned_program(program: &arena_ast::Program<'_, '_>) -> Program {
1742 Program {
1743 stmts: owned_stmts(&program.stmts),
1744 span: program.span,
1745 }
1746}
1747
1748pub fn from_owned_program<'arena>(
1762 arena: &'arena bumpalo::Bump,
1763 program: &Program,
1764) -> arena_ast::Program<'arena, 'arena> {
1765 arena_ast::Program {
1766 stmts: av_stmts(arena, &program.stmts),
1767 span: program.span,
1768 }
1769}
1770
1771#[inline]
1773fn av_str<'a>(arena: &'a bumpalo::Bump, s: &str) -> &'a str {
1774 arena.alloc_str(s)
1775}
1776
1777fn av_ident<'a>(arena: &'a bumpalo::Bump, ident: &Ident) -> arena_ast::Ident<'a> {
1778 match ident {
1779 Some(s) => arena_ast::Ident::name(arena.alloc_str(s)),
1780 None => arena_ast::Ident::ERROR,
1781 }
1782}
1783
1784fn av_name<'a>(arena: &'a bumpalo::Bump, name: &Name) -> arena_ast::Name<'a, 'a> {
1785 if name.kind == NameKind::Error {
1786 return arena_ast::Name::Error { span: name.span };
1787 }
1788 if name.parts.len() == 1 && name.kind == NameKind::Unqualified {
1789 return arena_ast::Name::Simple {
1790 value: arena.alloc_str(&name.parts[0]),
1791 span: name.span,
1792 };
1793 }
1794 let mut parts = arena_ast::ArenaVec::with_capacity_in(name.parts.len(), arena);
1795 for p in name.parts.iter() {
1796 parts.push(arena.alloc_str(p) as &str);
1797 }
1798 arena_ast::Name::Complex {
1799 parts,
1800 kind: name.kind,
1801 span: name.span,
1802 }
1803}
1804
1805fn av_type_hint<'a>(arena: &'a bumpalo::Bump, th: &TypeHint) -> arena_ast::TypeHint<'a, 'a> {
1806 arena_ast::TypeHint {
1807 kind: av_type_hint_kind(arena, &th.kind),
1808 span: th.span,
1809 }
1810}
1811
1812fn av_type_hint_kind<'a>(
1813 arena: &'a bumpalo::Bump,
1814 k: &TypeHintKind,
1815) -> arena_ast::TypeHintKind<'a, 'a> {
1816 match k {
1817 TypeHintKind::Named(n) => arena_ast::TypeHintKind::Named(av_name(arena, n)),
1818 TypeHintKind::Keyword(b, span) => arena_ast::TypeHintKind::Keyword(*b, *span),
1819 TypeHintKind::Nullable(inner) => {
1820 arena_ast::TypeHintKind::Nullable(arena.alloc(av_type_hint(arena, inner)))
1821 }
1822 TypeHintKind::Union(types) => {
1823 let mut v = arena_ast::ArenaVec::with_capacity_in(types.len(), arena);
1824 for t in types.iter() {
1825 v.push(av_type_hint(arena, t));
1826 }
1827 arena_ast::TypeHintKind::Union(v)
1828 }
1829 TypeHintKind::Intersection(types) => {
1830 let mut v = arena_ast::ArenaVec::with_capacity_in(types.len(), arena);
1831 for t in types.iter() {
1832 v.push(av_type_hint(arena, t));
1833 }
1834 arena_ast::TypeHintKind::Intersection(v)
1835 }
1836 }
1837}
1838
1839fn av_arg<'a>(arena: &'a bumpalo::Bump, arg: &Arg) -> arena_ast::Arg<'a, 'a> {
1840 arena_ast::Arg {
1841 name: arg.name.as_ref().map(|n| av_name(arena, n)),
1842 value: arg.value.as_ref().map(|v| av_expr(arena, v)),
1843 unpack: arg.unpack,
1844 by_ref: arg.by_ref,
1845 span: arg.span,
1846 }
1847}
1848
1849fn av_args<'a>(
1850 arena: &'a bumpalo::Bump,
1851 args: &[Arg],
1852) -> arena_ast::ArenaVec<'a, arena_ast::Arg<'a, 'a>> {
1853 let mut v = arena_ast::ArenaVec::with_capacity_in(args.len(), arena);
1854 for a in args.iter() {
1855 v.push(av_arg(arena, a));
1856 }
1857 v
1858}
1859
1860fn av_attr<'a>(arena: &'a bumpalo::Bump, attr: &Attribute) -> arena_ast::Attribute<'a, 'a> {
1861 arena_ast::Attribute {
1862 name: av_name(arena, &attr.name),
1863 args: av_args(arena, &attr.args),
1864 span: attr.span,
1865 }
1866}
1867
1868fn av_attrs<'a>(
1869 arena: &'a bumpalo::Bump,
1870 attrs: &[Attribute],
1871) -> arena_ast::ArenaVec<'a, arena_ast::Attribute<'a, 'a>> {
1872 let mut v = arena_ast::ArenaVec::with_capacity_in(attrs.len(), arena);
1873 for a in attrs.iter() {
1874 v.push(av_attr(arena, a));
1875 }
1876 v
1877}
1878
1879fn av_comment<'a>(arena: &'a bumpalo::Bump, c: &Comment) -> arena_ast::Comment<'a> {
1880 arena_ast::Comment {
1881 kind: c.kind,
1882 text: arena.alloc_str(&c.text),
1883 span: c.span,
1884 }
1885}
1886
1887fn av_opt_comment<'a>(
1888 arena: &'a bumpalo::Bump,
1889 c: &Option<Comment>,
1890) -> Option<arena_ast::Comment<'a>> {
1891 c.as_ref().map(|c| av_comment(arena, c))
1892}
1893
1894fn av_string_parts<'a>(
1895 arena: &'a bumpalo::Bump,
1896 parts: &[StringPart],
1897) -> arena_ast::ArenaVec<'a, arena_ast::StringPart<'a, 'a>> {
1898 let mut v = arena_ast::ArenaVec::with_capacity_in(parts.len(), arena);
1899 for p in parts.iter() {
1900 v.push(match p {
1901 StringPart::Literal(s) => arena_ast::StringPart::Literal(arena.alloc_str(s)),
1902 StringPart::Expr(e) => arena_ast::StringPart::Expr(av_expr(arena, e)),
1903 });
1904 }
1905 v
1906}
1907
1908fn av_expr<'a>(arena: &'a bumpalo::Bump, expr: &Expr) -> arena_ast::Expr<'a, 'a> {
1909 arena_ast::Expr {
1910 kind: av_expr_kind(arena, &expr.kind),
1911 span: expr.span,
1912 }
1913}
1914
1915fn av_exprs<'a>(
1916 arena: &'a bumpalo::Bump,
1917 exprs: &[Expr],
1918) -> arena_ast::ArenaVec<'a, arena_ast::Expr<'a, 'a>> {
1919 let mut v = arena_ast::ArenaVec::with_capacity_in(exprs.len(), arena);
1920 for e in exprs.iter() {
1921 v.push(av_expr(arena, e));
1922 }
1923 v
1924}
1925
1926fn av_namestr<'a>(arena: &'a bumpalo::Bump, s: &str) -> arena_ast::NameStr<'a, 'a> {
1927 arena_ast::NameStr::__arena(arena.alloc_str(s))
1928}
1929
1930fn av_expr_kind<'a>(arena: &'a bumpalo::Bump, k: &ExprKind) -> arena_ast::ExprKind<'a, 'a> {
1931 match k {
1932 ExprKind::Int(v) => arena_ast::ExprKind::Int(*v),
1933 ExprKind::Float(v) => arena_ast::ExprKind::Float(*v),
1934 ExprKind::String(s) => arena_ast::ExprKind::String(arena.alloc_str(s)),
1935 ExprKind::InterpolatedString(parts) => {
1936 arena_ast::ExprKind::InterpolatedString(av_string_parts(arena, parts))
1937 }
1938 ExprKind::Heredoc { label, parts } => arena_ast::ExprKind::Heredoc {
1939 label: arena.alloc_str(label),
1940 parts: av_string_parts(arena, parts),
1941 },
1942 ExprKind::Nowdoc { label, value } => arena_ast::ExprKind::Nowdoc {
1943 label: arena.alloc_str(label),
1944 value: arena.alloc_str(value),
1945 },
1946 ExprKind::ShellExec(parts) => arena_ast::ExprKind::ShellExec(av_string_parts(arena, parts)),
1947 ExprKind::Bool(v) => arena_ast::ExprKind::Bool(*v),
1948 ExprKind::Null => arena_ast::ExprKind::Null,
1949 ExprKind::Variable(s) => arena_ast::ExprKind::Variable(av_namestr(arena, s)),
1950 ExprKind::VariableVariable(inner) => {
1951 arena_ast::ExprKind::VariableVariable(arena.alloc(av_expr(arena, inner)))
1952 }
1953 ExprKind::Identifier(s) => arena_ast::ExprKind::Identifier(av_namestr(arena, s)),
1954 ExprKind::Assign(a) => arena_ast::ExprKind::Assign(arena_ast::AssignExpr {
1955 target: arena.alloc(av_expr(arena, &a.target)),
1956 op: a.op,
1957 value: arena.alloc(av_expr(arena, &a.value)),
1958 by_ref: a.by_ref,
1959 }),
1960 ExprKind::Binary(b) => arena_ast::ExprKind::Binary(arena_ast::BinaryExpr {
1961 left: arena.alloc(av_expr(arena, &b.left)),
1962 op: b.op,
1963 right: arena.alloc(av_expr(arena, &b.right)),
1964 }),
1965 ExprKind::UnaryPrefix(u) => arena_ast::ExprKind::UnaryPrefix(arena_ast::UnaryPrefixExpr {
1966 op: u.op,
1967 operand: arena.alloc(av_expr(arena, &u.operand)),
1968 }),
1969 ExprKind::UnaryPostfix(u) => {
1970 arena_ast::ExprKind::UnaryPostfix(arena_ast::UnaryPostfixExpr {
1971 operand: arena.alloc(av_expr(arena, &u.operand)),
1972 op: u.op,
1973 })
1974 }
1975 ExprKind::Ternary(t) => arena_ast::ExprKind::Ternary(arena_ast::TernaryExpr {
1976 condition: arena.alloc(av_expr(arena, &t.condition)),
1977 then_expr: t
1978 .then_expr
1979 .as_ref()
1980 .map(|e| &*arena.alloc(av_expr(arena, e))),
1981 else_expr: arena.alloc(av_expr(arena, &t.else_expr)),
1982 }),
1983 ExprKind::NullCoalesce(n) => {
1984 arena_ast::ExprKind::NullCoalesce(arena_ast::NullCoalesceExpr {
1985 left: arena.alloc(av_expr(arena, &n.left)),
1986 right: arena.alloc(av_expr(arena, &n.right)),
1987 })
1988 }
1989 ExprKind::FunctionCall(f) => {
1990 arena_ast::ExprKind::FunctionCall(arena_ast::FunctionCallExpr {
1991 name: arena.alloc(av_expr(arena, &f.name)),
1992 args: av_args(arena, &f.args),
1993 })
1994 }
1995 ExprKind::Array(elems) => {
1996 let mut v = arena_ast::ArenaVec::with_capacity_in(elems.len(), arena);
1997 for e in elems.iter() {
1998 v.push(arena_ast::ArrayElement {
1999 key: e.key.as_ref().map(|k| av_expr(arena, k)),
2000 value: av_expr(arena, &e.value),
2001 unpack: e.unpack,
2002 by_ref: e.by_ref,
2003 span: e.span,
2004 });
2005 }
2006 arena_ast::ExprKind::Array(v)
2007 }
2008 ExprKind::ArrayAccess(a) => arena_ast::ExprKind::ArrayAccess(arena_ast::ArrayAccessExpr {
2009 array: arena.alloc(av_expr(arena, &a.array)),
2010 index: a.index.as_ref().map(|e| &*arena.alloc(av_expr(arena, e))),
2011 }),
2012 ExprKind::Print(e) => arena_ast::ExprKind::Print(arena.alloc(av_expr(arena, e))),
2013 ExprKind::Parenthesized(e) => {
2014 arena_ast::ExprKind::Parenthesized(arena.alloc(av_expr(arena, e)))
2015 }
2016 ExprKind::Cast(kind, e) => arena_ast::ExprKind::Cast(*kind, arena.alloc(av_expr(arena, e))),
2017 ExprKind::ErrorSuppress(e) => {
2018 arena_ast::ExprKind::ErrorSuppress(arena.alloc(av_expr(arena, e)))
2019 }
2020 ExprKind::Isset(exprs) => arena_ast::ExprKind::Isset(av_exprs(arena, exprs)),
2021 ExprKind::Empty(e) => arena_ast::ExprKind::Empty(arena.alloc(av_expr(arena, e))),
2022 ExprKind::Include(kind, e) => {
2023 arena_ast::ExprKind::Include(*kind, arena.alloc(av_expr(arena, e)))
2024 }
2025 ExprKind::Eval(e) => arena_ast::ExprKind::Eval(arena.alloc(av_expr(arena, e))),
2026 ExprKind::Exit(e) => {
2027 arena_ast::ExprKind::Exit(e.as_ref().map(|e| &*arena.alloc(av_expr(arena, e))))
2028 }
2029 ExprKind::MagicConst(m) => arena_ast::ExprKind::MagicConst(*m),
2030 ExprKind::Clone(e) => arena_ast::ExprKind::Clone(arena.alloc(av_expr(arena, e))),
2031 ExprKind::CloneWith(obj, props) => arena_ast::ExprKind::CloneWith(
2032 arena.alloc(av_expr(arena, obj)),
2033 arena.alloc(av_expr(arena, props)),
2034 ),
2035 ExprKind::New(n) => arena_ast::ExprKind::New(arena_ast::NewExpr {
2036 class: arena.alloc(av_expr(arena, &n.class)),
2037 args: av_args(arena, &n.args),
2038 }),
2039 ExprKind::PropertyAccess(p) => {
2040 arena_ast::ExprKind::PropertyAccess(arena_ast::PropertyAccessExpr {
2041 object: arena.alloc(av_expr(arena, &p.object)),
2042 property: arena.alloc(av_expr(arena, &p.property)),
2043 })
2044 }
2045 ExprKind::NullsafePropertyAccess(p) => {
2046 arena_ast::ExprKind::NullsafePropertyAccess(arena_ast::PropertyAccessExpr {
2047 object: arena.alloc(av_expr(arena, &p.object)),
2048 property: arena.alloc(av_expr(arena, &p.property)),
2049 })
2050 }
2051 ExprKind::MethodCall(m) => {
2052 arena_ast::ExprKind::MethodCall(arena.alloc(arena_ast::MethodCallExpr {
2053 object: arena.alloc(av_expr(arena, &m.object)),
2054 method: arena.alloc(av_expr(arena, &m.method)),
2055 args: av_args(arena, &m.args),
2056 }))
2057 }
2058 ExprKind::NullsafeMethodCall(m) => {
2059 arena_ast::ExprKind::NullsafeMethodCall(arena.alloc(arena_ast::MethodCallExpr {
2060 object: arena.alloc(av_expr(arena, &m.object)),
2061 method: arena.alloc(av_expr(arena, &m.method)),
2062 args: av_args(arena, &m.args),
2063 }))
2064 }
2065 ExprKind::StaticPropertyAccess(s) => {
2066 arena_ast::ExprKind::StaticPropertyAccess(arena_ast::StaticAccessExpr {
2067 class: arena.alloc(av_expr(arena, &s.class)),
2068 member: arena.alloc(av_expr(arena, &s.member)),
2069 })
2070 }
2071 ExprKind::StaticMethodCall(s) => {
2072 arena_ast::ExprKind::StaticMethodCall(arena.alloc(arena_ast::StaticMethodCallExpr {
2073 class: arena.alloc(av_expr(arena, &s.class)),
2074 method: arena.alloc(av_expr(arena, &s.method)),
2075 args: av_args(arena, &s.args),
2076 }))
2077 }
2078 ExprKind::StaticDynMethodCall(s) => arena_ast::ExprKind::StaticDynMethodCall(arena.alloc(
2079 arena_ast::StaticDynMethodCallExpr {
2080 class: arena.alloc(av_expr(arena, &s.class)),
2081 method: arena.alloc(av_expr(arena, &s.method)),
2082 args: av_args(arena, &s.args),
2083 },
2084 )),
2085 ExprKind::ClassConstAccess(s) => {
2086 arena_ast::ExprKind::ClassConstAccess(arena_ast::StaticAccessExpr {
2087 class: arena.alloc(av_expr(arena, &s.class)),
2088 member: arena.alloc(av_expr(arena, &s.member)),
2089 })
2090 }
2091 ExprKind::ClassConstAccessDynamic { class, member } => {
2092 arena_ast::ExprKind::ClassConstAccessDynamic {
2093 class: arena.alloc(av_expr(arena, class)),
2094 member: arena.alloc(av_expr(arena, member)),
2095 }
2096 }
2097 ExprKind::StaticPropertyAccessDynamic { class, member } => {
2098 arena_ast::ExprKind::StaticPropertyAccessDynamic {
2099 class: arena.alloc(av_expr(arena, class)),
2100 member: arena.alloc(av_expr(arena, member)),
2101 }
2102 }
2103 ExprKind::Closure(c) => arena_ast::ExprKind::Closure(arena.alloc(arena_ast::ClosureExpr {
2104 is_static: c.is_static,
2105 by_ref: c.by_ref,
2106 params: av_params(arena, &c.params),
2107 use_vars: {
2108 let mut v = arena_ast::ArenaVec::with_capacity_in(c.use_vars.len(), arena);
2109 for uv in c.use_vars.iter() {
2110 v.push(arena_ast::ClosureUseVar {
2111 name: arena.alloc_str(&uv.name),
2112 by_ref: uv.by_ref,
2113 span: uv.span,
2114 });
2115 }
2116 v
2117 },
2118 return_type: c.return_type.as_ref().map(|t| av_type_hint(arena, t)),
2119 body: &*arena.alloc(av_block(arena, &c.body)),
2120 attributes: av_attrs(arena, &c.attributes),
2121 })),
2122 ExprKind::ArrowFunction(f) => {
2123 arena_ast::ExprKind::ArrowFunction(arena.alloc(arena_ast::ArrowFunctionExpr {
2124 is_static: f.is_static,
2125 by_ref: f.by_ref,
2126 params: av_params(arena, &f.params),
2127 return_type: f.return_type.as_ref().map(|t| av_type_hint(arena, t)),
2128 body: arena.alloc(av_expr(arena, &f.body)),
2129 attributes: av_attrs(arena, &f.attributes),
2130 }))
2131 }
2132 ExprKind::Match(m) => arena_ast::ExprKind::Match(arena_ast::MatchExpr {
2133 subject: arena.alloc(av_expr(arena, &m.subject)),
2134 arms: {
2135 let mut v = arena_ast::ArenaVec::with_capacity_in(m.arms.len(), arena);
2136 for arm in m.arms.iter() {
2137 v.push(arena_ast::MatchArm {
2138 conditions: arm.conditions.as_ref().map(|conds| av_exprs(arena, conds)),
2139 body: av_expr(arena, &arm.body),
2140 span: arm.span,
2141 });
2142 }
2143 v
2144 },
2145 brace_start: m.brace_start,
2146 }),
2147 ExprKind::ThrowExpr(e) => arena_ast::ExprKind::ThrowExpr(arena.alloc(av_expr(arena, e))),
2148 ExprKind::Yield(y) => arena_ast::ExprKind::Yield(arena_ast::YieldExpr {
2149 key: y.key.as_ref().map(|e| &*arena.alloc(av_expr(arena, e))),
2150 value: y.value.as_ref().map(|e| &*arena.alloc(av_expr(arena, e))),
2151 is_from: y.is_from,
2152 }),
2153 ExprKind::AnonymousClass(cls) => {
2154 arena_ast::ExprKind::AnonymousClass(arena.alloc(av_class_decl(arena, cls)))
2155 }
2156 ExprKind::CallableCreate(c) => {
2157 arena_ast::ExprKind::CallableCreate(arena_ast::CallableCreateExpr {
2158 kind: match &c.kind {
2159 CallableCreateKind::Function(e) => {
2160 arena_ast::CallableCreateKind::Function(arena.alloc(av_expr(arena, e)))
2161 }
2162 CallableCreateKind::Method { object, method } => {
2163 arena_ast::CallableCreateKind::Method {
2164 object: arena.alloc(av_expr(arena, object)),
2165 method: arena.alloc(av_expr(arena, method)),
2166 }
2167 }
2168 CallableCreateKind::NullsafeMethod { object, method } => {
2169 arena_ast::CallableCreateKind::NullsafeMethod {
2170 object: arena.alloc(av_expr(arena, object)),
2171 method: arena.alloc(av_expr(arena, method)),
2172 }
2173 }
2174 CallableCreateKind::StaticMethod { class, method } => {
2175 arena_ast::CallableCreateKind::StaticMethod {
2176 class: arena.alloc(av_expr(arena, class)),
2177 method: arena.alloc(av_expr(arena, method)),
2178 }
2179 }
2180 },
2181 })
2182 }
2183 ExprKind::Omit => arena_ast::ExprKind::Omit,
2184 ExprKind::Error => arena_ast::ExprKind::Error,
2185 }
2186}
2187
2188fn av_param<'a>(arena: &'a bumpalo::Bump, p: &Param) -> arena_ast::Param<'a, 'a> {
2189 arena_ast::Param {
2190 name: av_ident(arena, &p.name),
2191 type_hint: p.type_hint.as_ref().map(|t| av_type_hint(arena, t)),
2192 default: p.default.as_ref().map(|e| av_expr(arena, e)),
2193 by_ref: p.by_ref,
2194 variadic: p.variadic,
2195 is_readonly: p.is_readonly,
2196 is_final: p.is_final,
2197 visibility: p.visibility,
2198 set_visibility: p.set_visibility,
2199 attributes: av_attrs(arena, &p.attributes),
2200 hooks: av_hooks(arena, &p.hooks),
2201 span: p.span,
2202 }
2203}
2204
2205fn av_params<'a>(
2206 arena: &'a bumpalo::Bump,
2207 params: &[Param],
2208) -> arena_ast::ArenaVec<'a, arena_ast::Param<'a, 'a>> {
2209 let mut v = arena_ast::ArenaVec::with_capacity_in(params.len(), arena);
2210 for p in params.iter() {
2211 v.push(av_param(arena, p));
2212 }
2213 v
2214}
2215
2216fn av_hook<'a>(arena: &'a bumpalo::Bump, h: &PropertyHook) -> arena_ast::PropertyHook<'a, 'a> {
2217 arena_ast::PropertyHook {
2218 kind: h.kind,
2219 body: match &h.body {
2220 PropertyHookBody::Block(block) => {
2221 arena_ast::PropertyHookBody::Block(arena.alloc(av_block(arena, block)))
2222 }
2223 PropertyHookBody::Expression(e) => {
2224 arena_ast::PropertyHookBody::Expression(av_expr(arena, e))
2225 }
2226 PropertyHookBody::Abstract => arena_ast::PropertyHookBody::Abstract,
2227 },
2228 is_final: h.is_final,
2229 by_ref: h.by_ref,
2230 params: av_params(arena, &h.params),
2231 attributes: av_attrs(arena, &h.attributes),
2232 span: h.span,
2233 }
2234}
2235
2236fn av_hooks<'a>(
2237 arena: &'a bumpalo::Bump,
2238 hooks: &[PropertyHook],
2239) -> arena_ast::ArenaVec<'a, arena_ast::PropertyHook<'a, 'a>> {
2240 let mut v = arena_ast::ArenaVec::with_capacity_in(hooks.len(), arena);
2241 for h in hooks.iter() {
2242 v.push(av_hook(arena, h));
2243 }
2244 v
2245}
2246
2247fn av_stmt<'a>(arena: &'a bumpalo::Bump, stmt: &Stmt) -> arena_ast::Stmt<'a, 'a> {
2248 arena_ast::Stmt {
2249 kind: av_stmt_kind(arena, &stmt.kind),
2250 span: stmt.span,
2251 doc_comment: stmt.doc_comment.as_ref().map(|c| {
2252 &*arena.alloc(arena_ast::Comment {
2253 kind: c.kind,
2254 text: arena.alloc_str(&c.text),
2255 span: c.span,
2256 })
2257 }),
2258 }
2259}
2260
2261fn av_stmts<'a>(
2262 arena: &'a bumpalo::Bump,
2263 stmts: &[Stmt],
2264) -> arena_ast::ArenaVec<'a, arena_ast::Stmt<'a, 'a>> {
2265 let mut v = arena_ast::ArenaVec::with_capacity_in(stmts.len(), arena);
2266 for s in stmts.iter() {
2267 v.push(av_stmt(arena, s));
2268 }
2269 v
2270}
2271
2272fn av_block<'a>(arena: &'a bumpalo::Bump, block: &Block) -> arena_ast::Block<'a, 'a> {
2273 arena_ast::Block {
2274 stmts: av_stmts(arena, &block.stmts),
2275 span: block.span,
2276 }
2277}
2278
2279fn av_stmt_kind<'a>(arena: &'a bumpalo::Bump, k: &StmtKind) -> arena_ast::StmtKind<'a, 'a> {
2280 match k {
2281 StmtKind::Expression(e) => arena_ast::StmtKind::Expression(arena.alloc(av_expr(arena, e))),
2282 StmtKind::Echo(exprs) => arena_ast::StmtKind::Echo(av_exprs(arena, exprs)),
2283 StmtKind::Return(e) => {
2284 arena_ast::StmtKind::Return(e.as_ref().map(|e| &*arena.alloc(av_expr(arena, e))))
2285 }
2286 StmtKind::Block(block) => arena_ast::StmtKind::Block(arena.alloc(av_block(arena, block))),
2287 StmtKind::If(s) => arena_ast::StmtKind::If(
2288 arena.alloc(arena_ast::IfStmt {
2289 condition: av_expr(arena, &s.condition),
2290 then_branch: arena.alloc(av_stmt(arena, &s.then_branch)),
2291 elseif_branches: {
2292 let mut v =
2293 arena_ast::ArenaVec::with_capacity_in(s.elseif_branches.len(), arena);
2294 for b in s.elseif_branches.iter() {
2295 v.push(arena_ast::ElseIfBranch {
2296 condition: av_expr(arena, &b.condition),
2297 body: av_stmt(arena, &b.body),
2298 span: b.span,
2299 });
2300 }
2301 v
2302 },
2303 else_branch: s
2304 .else_branch
2305 .as_ref()
2306 .map(|b| &*arena.alloc(av_stmt(arena, b))),
2307 else_kw_start: s.else_kw_start,
2308 uses_alternative: s.uses_alternative,
2309 }),
2310 ),
2311 StmtKind::While(s) => arena_ast::StmtKind::While(arena.alloc(arena_ast::WhileStmt {
2312 condition: av_expr(arena, &s.condition),
2313 body: arena.alloc(av_stmt(arena, &s.body)),
2314 uses_alternative: s.uses_alternative,
2315 })),
2316 StmtKind::For(s) => arena_ast::StmtKind::For(arena.alloc(arena_ast::ForStmt {
2317 init: av_exprs(arena, &s.init),
2318 condition: av_exprs(arena, &s.condition),
2319 update: av_exprs(arena, &s.update),
2320 body: arena.alloc(av_stmt(arena, &s.body)),
2321 uses_alternative: s.uses_alternative,
2322 })),
2323 StmtKind::Foreach(s) => arena_ast::StmtKind::Foreach(arena.alloc(arena_ast::ForeachStmt {
2324 expr: av_expr(arena, &s.expr),
2325 key: s.key.as_ref().map(|e| av_expr(arena, e)),
2326 value: av_expr(arena, &s.value),
2327 body: arena.alloc(av_stmt(arena, &s.body)),
2328 uses_alternative: s.uses_alternative,
2329 })),
2330 StmtKind::DoWhile(s) => arena_ast::StmtKind::DoWhile(arena.alloc(arena_ast::DoWhileStmt {
2331 body: arena.alloc(av_stmt(arena, &s.body)),
2332 condition: av_expr(arena, &s.condition),
2333 })),
2334 StmtKind::Function(f) => {
2335 arena_ast::StmtKind::Function(arena.alloc(av_function_decl(arena, f)))
2336 }
2337 StmtKind::Break(e) => {
2338 arena_ast::StmtKind::Break(e.as_ref().map(|e| &*arena.alloc(av_expr(arena, e))))
2339 }
2340 StmtKind::Continue(e) => {
2341 arena_ast::StmtKind::Continue(e.as_ref().map(|e| &*arena.alloc(av_expr(arena, e))))
2342 }
2343 StmtKind::Switch(s) => arena_ast::StmtKind::Switch(arena.alloc(arena_ast::SwitchStmt {
2344 expr: av_expr(arena, &s.expr),
2345 body: {
2346 let mut cases = arena_ast::ArenaVec::with_capacity_in(s.body.cases.len(), arena);
2347 for c in s.body.cases.iter() {
2348 cases.push(arena_ast::SwitchCase {
2349 value: c.value.as_ref().map(|vl| av_expr(arena, vl)),
2350 body: av_stmts(arena, &c.body),
2351 span: c.span,
2352 });
2353 }
2354 arena_ast::SwitchBody {
2355 cases,
2356 span: s.body.span,
2357 }
2358 },
2359 uses_alternative: s.uses_alternative,
2360 })),
2361 StmtKind::Goto(ident) => arena_ast::StmtKind::Goto(av_ident(arena, ident)),
2362 StmtKind::Label(s) => arena_ast::StmtKind::Label(av_str(arena, s)),
2363 StmtKind::Declare(d) => arena_ast::StmtKind::Declare(arena.alloc(arena_ast::DeclareStmt {
2364 directives: {
2365 let mut v = arena_ast::ArenaVec::with_capacity_in(d.directives.len(), arena);
2366 for (k, val) in d.directives.iter() {
2367 v.push((arena.alloc_str(k) as &str, av_expr(arena, val)));
2368 }
2369 v
2370 },
2371 body: d.body.as_ref().map(|b| &*arena.alloc(av_stmt(arena, b))),
2372 uses_alternative: d.uses_alternative,
2373 })),
2374 StmtKind::Unset(exprs) => arena_ast::StmtKind::Unset(av_exprs(arena, exprs)),
2375 StmtKind::Throw(e) => arena_ast::StmtKind::Throw(arena.alloc(av_expr(arena, e))),
2376 StmtKind::TryCatch(t) => arena_ast::StmtKind::TryCatch(
2377 arena.alloc(arena_ast::TryCatchStmt {
2378 body: arena.alloc(av_block(arena, &t.body)),
2379 catches: {
2380 let mut v = arena_ast::ArenaVec::with_capacity_in(t.catches.len(), arena);
2381 for c in t.catches.iter() {
2382 let mut types = arena_ast::ArenaVec::with_capacity_in(c.types.len(), arena);
2383 for n in c.types.iter() {
2384 types.push(av_name(arena, n));
2385 }
2386 v.push(arena_ast::CatchClause {
2387 types,
2388 var: c.var.as_deref().map(|s| av_str(arena, s)),
2389 body: arena.alloc(av_block(arena, &c.body)),
2390 span: c.span,
2391 });
2392 }
2393 v
2394 },
2395 finally: t
2396 .finally
2397 .as_deref()
2398 .map(|f| &*arena.alloc(av_block(arena, f))),
2399 finally_kw_start: t.finally_kw_start,
2400 }),
2401 ),
2402 StmtKind::Global(exprs) => arena_ast::StmtKind::Global(av_exprs(arena, exprs)),
2403 StmtKind::Class(cls) => arena_ast::StmtKind::Class(arena.alloc(av_class_decl(arena, cls))),
2404 StmtKind::Interface(iface) => {
2405 arena_ast::StmtKind::Interface(arena.alloc(av_interface_decl(arena, iface)))
2406 }
2407 StmtKind::Trait(tr) => arena_ast::StmtKind::Trait(arena.alloc(av_trait_decl(arena, tr))),
2408 StmtKind::Enum(en) => arena_ast::StmtKind::Enum(arena.alloc(av_enum_decl(arena, en))),
2409 StmtKind::Namespace(ns) => {
2410 arena_ast::StmtKind::Namespace(arena.alloc(arena_ast::NamespaceDecl {
2411 name: ns.name.as_ref().map(|n| av_name(arena, n)),
2412 body: match &ns.body {
2413 NamespaceBody::Braced(block) => {
2414 arena_ast::NamespaceBody::Braced(&*arena.alloc(av_block(arena, block)))
2415 }
2416 NamespaceBody::Simple => arena_ast::NamespaceBody::Simple,
2417 },
2418 }))
2419 }
2420 StmtKind::Use(u) => arena_ast::StmtKind::Use(arena.alloc(arena_ast::UseDecl {
2421 kind: u.kind,
2422 uses: {
2423 let mut v = arena_ast::ArenaVec::with_capacity_in(u.uses.len(), arena);
2424 for item in u.uses.iter() {
2425 v.push(arena_ast::UseItem {
2426 name: av_name(arena, &item.name),
2427 alias: item.alias.as_deref().map(|s| av_str(arena, s)),
2428 kind: item.kind,
2429 span: item.span,
2430 });
2431 }
2432 v
2433 },
2434 })),
2435 StmtKind::Const(items) => {
2436 let mut v = arena_ast::ArenaVec::with_capacity_in(items.len(), arena);
2437 for item in items.iter() {
2438 v.push(arena_ast::ConstItem {
2439 name: av_ident(arena, &item.name),
2440 value: av_expr(arena, &item.value),
2441 attributes: av_attrs(arena, &item.attributes),
2442 span: item.span,
2443 doc_comment: av_opt_comment(arena, &item.doc_comment),
2444 });
2445 }
2446 arena_ast::StmtKind::Const(v)
2447 }
2448 StmtKind::StaticVar(vars) => {
2449 let mut v = arena_ast::ArenaVec::with_capacity_in(vars.len(), arena);
2450 for var in vars.iter() {
2451 v.push(arena_ast::StaticVar {
2452 name: av_ident(arena, &var.name),
2453 default: var.default.as_ref().map(|e| av_expr(arena, e)),
2454 span: var.span,
2455 });
2456 }
2457 arena_ast::StmtKind::StaticVar(v)
2458 }
2459 StmtKind::HaltCompiler(s) => arena_ast::StmtKind::HaltCompiler(av_str(arena, s)),
2460 StmtKind::Nop => arena_ast::StmtKind::Nop,
2461 StmtKind::InlineHtml(s) => arena_ast::StmtKind::InlineHtml(av_str(arena, s)),
2462 StmtKind::Error => arena_ast::StmtKind::Error,
2463 }
2464}
2465
2466fn av_function_decl<'a>(
2467 arena: &'a bumpalo::Bump,
2468 f: &FunctionDecl,
2469) -> arena_ast::FunctionDecl<'a, 'a> {
2470 arena_ast::FunctionDecl {
2471 name: av_ident(arena, &f.name),
2472 params: av_params(arena, &f.params),
2473 body: &*arena.alloc(av_block(arena, &f.body)),
2474 return_type: f.return_type.as_ref().map(|t| av_type_hint(arena, t)),
2475 by_ref: f.by_ref,
2476 attributes: av_attrs(arena, &f.attributes),
2477 doc_comment: av_opt_comment(arena, &f.doc_comment),
2478 }
2479}
2480
2481fn av_class_member<'a>(
2482 arena: &'a bumpalo::Bump,
2483 m: &ClassMember,
2484) -> arena_ast::ClassMember<'a, 'a> {
2485 arena_ast::ClassMember {
2486 kind: match &m.kind {
2487 ClassMemberKind::Property(p) => {
2488 arena_ast::ClassMemberKind::Property(arena_ast::PropertyDecl {
2489 name: av_ident(arena, &p.name),
2490 visibility: p.visibility,
2491 set_visibility: p.set_visibility,
2492 is_static: p.is_static,
2493 is_readonly: p.is_readonly,
2494 type_hint: p.type_hint.as_ref().map(|t| av_type_hint(arena, t)),
2495 default: p.default.as_ref().map(|e| av_expr(arena, e)),
2496 attributes: av_attrs(arena, &p.attributes),
2497 hooks: av_hooks(arena, &p.hooks),
2498 doc_comment: av_opt_comment(arena, &p.doc_comment),
2499 })
2500 }
2501 ClassMemberKind::Method(m) => {
2502 arena_ast::ClassMemberKind::Method(arena_ast::MethodDecl {
2503 name: av_ident(arena, &m.name),
2504 visibility: m.visibility,
2505 is_static: m.is_static,
2506 is_abstract: m.is_abstract,
2507 is_final: m.is_final,
2508 by_ref: m.by_ref,
2509 params: av_params(arena, &m.params),
2510 return_type: m.return_type.as_ref().map(|t| av_type_hint(arena, t)),
2511 body: m.body.as_deref().map(|b| &*arena.alloc(av_block(arena, b))),
2512 attributes: av_attrs(arena, &m.attributes),
2513 doc_comment: av_opt_comment(arena, &m.doc_comment),
2514 })
2515 }
2516 ClassMemberKind::ClassConst(c) => {
2517 arena_ast::ClassMemberKind::ClassConst(av_class_const(arena, c))
2518 }
2519 ClassMemberKind::TraitUse(t) => {
2520 arena_ast::ClassMemberKind::TraitUse(av_trait_use(arena, t))
2521 }
2522 },
2523 span: m.span,
2524 }
2525}
2526
2527fn av_class_members<'a>(
2528 arena: &'a bumpalo::Bump,
2529 members: &[ClassMember],
2530) -> arena_ast::ArenaVec<'a, arena_ast::ClassMember<'a, 'a>> {
2531 let mut v = arena_ast::ArenaVec::with_capacity_in(members.len(), arena);
2532 for m in members.iter() {
2533 v.push(av_class_member(arena, m));
2534 }
2535 v
2536}
2537
2538fn av_class_const<'a>(
2539 arena: &'a bumpalo::Bump,
2540 c: &ClassConstDecl,
2541) -> arena_ast::ClassConstDecl<'a, 'a> {
2542 arena_ast::ClassConstDecl {
2543 name: av_ident(arena, &c.name),
2544 visibility: c.visibility,
2545 is_final: c.is_final,
2546 type_hint: c
2547 .type_hint
2548 .as_ref()
2549 .map(|th| arena.alloc(av_type_hint(arena, th)) as &_),
2550 value: av_expr(arena, &c.value),
2551 attributes: av_attrs(arena, &c.attributes),
2552 doc_comment: av_opt_comment(arena, &c.doc_comment),
2553 }
2554}
2555
2556fn av_trait_use<'a>(arena: &'a bumpalo::Bump, t: &TraitUseDecl) -> arena_ast::TraitUseDecl<'a, 'a> {
2557 let mut traits = arena_ast::ArenaVec::with_capacity_in(t.traits.len(), arena);
2558 for n in t.traits.iter() {
2559 traits.push(av_name(arena, n));
2560 }
2561 let mut adaptations = arena_ast::ArenaVec::with_capacity_in(t.adaptations.len(), arena);
2562 for a in t.adaptations.iter() {
2563 adaptations.push(arena_ast::TraitAdaptation {
2564 kind: match &a.kind {
2565 TraitAdaptationKind::Precedence {
2566 trait_name,
2567 method,
2568 insteadof,
2569 } => {
2570 let mut instead = arena_ast::ArenaVec::with_capacity_in(insteadof.len(), arena);
2571 for n in insteadof.iter() {
2572 instead.push(av_name(arena, n));
2573 }
2574 arena_ast::TraitAdaptationKind::Precedence {
2575 trait_name: av_name(arena, trait_name),
2576 method: av_name(arena, method),
2577 insteadof: instead,
2578 }
2579 }
2580 TraitAdaptationKind::Alias {
2581 trait_name,
2582 method,
2583 new_modifier,
2584 new_name,
2585 } => arena_ast::TraitAdaptationKind::Alias {
2586 trait_name: trait_name.as_ref().map(|n| av_name(arena, n)),
2587 method: av_name(arena, method),
2588 new_modifier: *new_modifier,
2589 new_name: new_name.as_ref().map(|n| av_name(arena, n)),
2590 },
2591 },
2592 span: a.span,
2593 });
2594 }
2595 arena_ast::TraitUseDecl {
2596 traits,
2597 adaptations,
2598 adaptations_brace_start: t.adaptations_brace_start,
2599 doc_comment: av_opt_comment(arena, &t.doc_comment),
2600 }
2601}
2602
2603fn av_class_decl<'a>(arena: &'a bumpalo::Bump, cls: &ClassDecl) -> arena_ast::ClassDecl<'a, 'a> {
2604 let mut implements = arena_ast::ArenaVec::with_capacity_in(cls.implements.len(), arena);
2605 for n in cls.implements.iter() {
2606 implements.push(av_name(arena, n));
2607 }
2608 arena_ast::ClassDecl {
2609 name: cls.name.as_ref().map(|ident| av_ident(arena, ident)),
2610 modifiers: cls.modifiers.clone(),
2611 extends: cls.extends.as_ref().map(|n| av_name(arena, n)),
2612 implements,
2613 body: arena_ast::ClassBody {
2614 members: av_class_members(arena, &cls.body.members),
2615 span: cls.body.span,
2616 },
2617 attributes: av_attrs(arena, &cls.attributes),
2618 doc_comment: av_opt_comment(arena, &cls.doc_comment),
2619 }
2620}
2621
2622fn av_interface_decl<'a>(
2623 arena: &'a bumpalo::Bump,
2624 iface: &InterfaceDecl,
2625) -> arena_ast::InterfaceDecl<'a, 'a> {
2626 let mut extends = arena_ast::ArenaVec::with_capacity_in(iface.extends.len(), arena);
2627 for n in iface.extends.iter() {
2628 extends.push(av_name(arena, n));
2629 }
2630 arena_ast::InterfaceDecl {
2631 name: av_ident(arena, &iface.name),
2632 extends,
2633 body: arena_ast::ClassBody {
2634 members: av_class_members(arena, &iface.body.members),
2635 span: iface.body.span,
2636 },
2637 attributes: av_attrs(arena, &iface.attributes),
2638 doc_comment: av_opt_comment(arena, &iface.doc_comment),
2639 }
2640}
2641
2642fn av_trait_decl<'a>(arena: &'a bumpalo::Bump, tr: &TraitDecl) -> arena_ast::TraitDecl<'a, 'a> {
2643 arena_ast::TraitDecl {
2644 name: av_ident(arena, &tr.name),
2645 body: arena_ast::ClassBody {
2646 members: av_class_members(arena, &tr.body.members),
2647 span: tr.body.span,
2648 },
2649 attributes: av_attrs(arena, &tr.attributes),
2650 doc_comment: av_opt_comment(arena, &tr.doc_comment),
2651 }
2652}
2653
2654fn av_enum_decl<'a>(arena: &'a bumpalo::Bump, en: &EnumDecl) -> arena_ast::EnumDecl<'a, 'a> {
2655 let mut implements = arena_ast::ArenaVec::with_capacity_in(en.implements.len(), arena);
2656 for n in en.implements.iter() {
2657 implements.push(av_name(arena, n));
2658 }
2659 let mut members = arena_ast::ArenaVec::with_capacity_in(en.body.members.len(), arena);
2660 for m in en.body.members.iter() {
2661 members.push(arena_ast::EnumMember {
2662 kind: match &m.kind {
2663 EnumMemberKind::Case(c) => arena_ast::EnumMemberKind::Case(arena_ast::EnumCase {
2664 name: av_ident(arena, &c.name),
2665 value: c.value.as_ref().map(|e| av_expr(arena, e)),
2666 attributes: av_attrs(arena, &c.attributes),
2667 doc_comment: av_opt_comment(arena, &c.doc_comment),
2668 }),
2669 EnumMemberKind::Method(m) => {
2670 arena_ast::EnumMemberKind::Method(arena_ast::MethodDecl {
2671 name: av_ident(arena, &m.name),
2672 visibility: m.visibility,
2673 is_static: m.is_static,
2674 is_abstract: m.is_abstract,
2675 is_final: m.is_final,
2676 by_ref: m.by_ref,
2677 params: av_params(arena, &m.params),
2678 return_type: m.return_type.as_ref().map(|t| av_type_hint(arena, t)),
2679 body: m.body.as_deref().map(|b| &*arena.alloc(av_block(arena, b))),
2680 attributes: av_attrs(arena, &m.attributes),
2681 doc_comment: av_opt_comment(arena, &m.doc_comment),
2682 })
2683 }
2684 EnumMemberKind::ClassConst(c) => {
2685 arena_ast::EnumMemberKind::ClassConst(av_class_const(arena, c))
2686 }
2687 EnumMemberKind::TraitUse(t) => {
2688 arena_ast::EnumMemberKind::TraitUse(av_trait_use(arena, t))
2689 }
2690 },
2691 span: m.span,
2692 });
2693 }
2694 arena_ast::EnumDecl {
2695 name: av_ident(arena, &en.name),
2696 scalar_type: en.scalar_type.as_ref().map(|n| av_name(arena, n)),
2697 implements,
2698 body: arena_ast::EnumBody {
2699 members,
2700 span: en.body.span,
2701 },
2702 attributes: av_attrs(arena, &en.attributes),
2703 doc_comment: av_opt_comment(arena, &en.doc_comment),
2704 }
2705}