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}
804
805#[derive(Debug, Clone, Serialize)]
806pub struct TraitAdaptation {
807 pub kind: TraitAdaptationKind,
808 pub span: Span,
809}
810
811#[derive(Debug, Clone, Serialize)]
812pub enum TraitAdaptationKind {
813 Precedence {
814 trait_name: Name,
815 method: Name,
816 insteadof: Box<[Name]>,
817 },
818 Alias {
819 trait_name: Option<Name>,
820 method: Name,
821 new_modifier: Option<Visibility>,
822 new_name: Option<Name>,
823 },
824}
825
826#[derive(Debug, Clone, Serialize)]
827pub struct InterfaceDecl {
828 pub name: Ident,
829 pub extends: Box<[Name]>,
830 #[serde(flatten)]
831 pub body: ClassBody,
832 pub attributes: Box<[Attribute]>,
833 #[serde(skip_serializing_if = "Option::is_none")]
834 pub doc_comment: Option<Comment>,
835}
836
837#[derive(Debug, Clone, Serialize)]
838pub struct TraitDecl {
839 pub name: Ident,
840 #[serde(flatten)]
841 pub body: ClassBody,
842 pub attributes: Box<[Attribute]>,
843 #[serde(skip_serializing_if = "Option::is_none")]
844 pub doc_comment: Option<Comment>,
845}
846
847#[derive(Debug, Clone, Serialize)]
848pub struct EnumBody {
849 pub members: Box<[EnumMember]>,
850 #[serde(skip)]
851 pub span: Span,
852}
853
854#[derive(Debug, Clone, Serialize)]
855pub struct EnumDecl {
856 pub name: Ident,
857 pub scalar_type: Option<Name>,
858 pub implements: Box<[Name]>,
859 #[serde(flatten)]
860 pub body: EnumBody,
861 pub attributes: Box<[Attribute]>,
862 #[serde(skip_serializing_if = "Option::is_none")]
863 pub doc_comment: Option<Comment>,
864}
865
866#[derive(Debug, Clone, Serialize)]
867pub struct EnumMember {
868 pub kind: EnumMemberKind,
869 pub span: Span,
870}
871
872#[derive(Debug, Clone, Serialize)]
873pub enum EnumMemberKind {
874 Case(EnumCase),
875 Method(MethodDecl),
876 ClassConst(ClassConstDecl),
877 TraitUse(TraitUseDecl),
878}
879
880#[derive(Debug, Clone, Serialize)]
881pub struct EnumCase {
882 pub name: Ident,
883 pub value: Option<Expr>,
884 pub attributes: Box<[Attribute]>,
885 #[serde(skip_serializing_if = "Option::is_none")]
886 pub doc_comment: Option<Comment>,
887}
888
889fn owned_ident(ident: arena_ast::Ident<'_>) -> Ident {
894 ident.as_str().map(|s| s.into())
895}
896
897fn owned_name(name: &arena_ast::Name<'_, '_>) -> Name {
898 match name {
899 arena_ast::Name::Simple { value, span } => Name {
900 parts: vec![Box::from(*value)].into_boxed_slice(),
901 kind: NameKind::Unqualified,
902 span: *span,
903 },
904 arena_ast::Name::Complex { parts, kind, span } => Name {
905 parts: parts
906 .iter()
907 .map(|s| Box::from(*s))
908 .collect::<Vec<_>>()
909 .into_boxed_slice(),
910 kind: *kind,
911 span: *span,
912 },
913 arena_ast::Name::Error { span } => Name {
914 parts: Box::from([]),
915 kind: NameKind::Error,
916 span: *span,
917 },
918 }
919}
920
921fn owned_comment(c: &arena_ast::Comment<'_>) -> Comment {
922 Comment {
923 kind: c.kind,
924 text: c.text.into(),
925 span: c.span,
926 }
927}
928
929fn owned_opt_comment(c: &Option<arena_ast::Comment<'_>>) -> Option<Comment> {
930 c.as_ref().map(owned_comment)
931}
932
933fn owned_type_hint(th: &arena_ast::TypeHint<'_, '_>) -> TypeHint {
934 TypeHint {
935 kind: owned_type_hint_kind(&th.kind),
936 span: th.span,
937 }
938}
939
940fn owned_type_hint_kind(k: &arena_ast::TypeHintKind<'_, '_>) -> TypeHintKind {
941 match k {
942 arena_ast::TypeHintKind::Named(n) => TypeHintKind::Named(owned_name(n)),
943 arena_ast::TypeHintKind::Keyword(b, span) => TypeHintKind::Keyword(*b, *span),
944 arena_ast::TypeHintKind::Nullable(inner) => {
945 TypeHintKind::Nullable(Box::new(owned_type_hint(inner)))
946 }
947 arena_ast::TypeHintKind::Union(types) => TypeHintKind::Union(
948 types
949 .iter()
950 .map(owned_type_hint)
951 .collect::<Vec<_>>()
952 .into_boxed_slice(),
953 ),
954 arena_ast::TypeHintKind::Intersection(types) => TypeHintKind::Intersection(
955 types
956 .iter()
957 .map(owned_type_hint)
958 .collect::<Vec<_>>()
959 .into_boxed_slice(),
960 ),
961 }
962}
963
964fn owned_arg(arg: &arena_ast::Arg<'_, '_>) -> Arg {
965 Arg {
966 name: arg.name.as_ref().map(owned_name),
967 value: arg.value.as_ref().map(owned_expr),
968 unpack: arg.unpack,
969 by_ref: arg.by_ref,
970 span: arg.span,
971 }
972}
973
974fn owned_args(args: &[arena_ast::Arg<'_, '_>]) -> Box<[Arg]> {
975 args.iter()
976 .map(owned_arg)
977 .collect::<Vec<_>>()
978 .into_boxed_slice()
979}
980
981fn owned_attr(attr: &arena_ast::Attribute<'_, '_>) -> Attribute {
982 Attribute {
983 name: owned_name(&attr.name),
984 args: owned_args(&attr.args),
985 span: attr.span,
986 }
987}
988
989fn owned_attrs(attrs: &[arena_ast::Attribute<'_, '_>]) -> Box<[Attribute]> {
990 attrs
991 .iter()
992 .map(owned_attr)
993 .collect::<Vec<_>>()
994 .into_boxed_slice()
995}
996
997fn owned_string_parts(parts: &[arena_ast::StringPart<'_, '_>]) -> Box<[StringPart]> {
998 parts
999 .iter()
1000 .map(|p| match p {
1001 arena_ast::StringPart::Literal(s) => StringPart::Literal(Box::from(*s)),
1002 arena_ast::StringPart::Expr(e) => StringPart::Expr(owned_expr(e)),
1003 })
1004 .collect::<Vec<_>>()
1005 .into_boxed_slice()
1006}
1007
1008pub fn to_owned_expr(expr: &arena_ast::Expr<'_, '_>) -> Expr {
1010 owned_expr(expr)
1011}
1012
1013pub fn to_owned_name(name: &arena_ast::Name<'_, '_>) -> Name {
1015 owned_name(name)
1016}
1017
1018pub fn to_owned_type_hint(hint: &arena_ast::TypeHint<'_, '_>) -> TypeHint {
1020 owned_type_hint(hint)
1021}
1022
1023fn owned_expr(expr: &arena_ast::Expr<'_, '_>) -> Expr {
1024 Expr {
1025 kind: owned_expr_kind(&expr.kind),
1026 span: expr.span,
1027 }
1028}
1029
1030fn owned_exprs(exprs: &[arena_ast::Expr<'_, '_>]) -> Box<[Expr]> {
1031 exprs
1032 .iter()
1033 .map(owned_expr)
1034 .collect::<Vec<_>>()
1035 .into_boxed_slice()
1036}
1037
1038fn owned_expr_kind(k: &arena_ast::ExprKind<'_, '_>) -> ExprKind {
1039 match k {
1040 arena_ast::ExprKind::Int(v) => ExprKind::Int(*v),
1041 arena_ast::ExprKind::Float(v) => ExprKind::Float(*v),
1042 arena_ast::ExprKind::String(s) => ExprKind::String(Box::from(*s)),
1043 arena_ast::ExprKind::InterpolatedString(parts) => {
1044 ExprKind::InterpolatedString(owned_string_parts(parts))
1045 }
1046 arena_ast::ExprKind::Heredoc { label, parts } => ExprKind::Heredoc {
1047 label: Box::from(*label),
1048 parts: owned_string_parts(parts),
1049 },
1050 arena_ast::ExprKind::Nowdoc { label, value } => ExprKind::Nowdoc {
1051 label: Box::from(*label),
1052 value: Box::from(*value),
1053 },
1054 arena_ast::ExprKind::ShellExec(parts) => ExprKind::ShellExec(owned_string_parts(parts)),
1055 arena_ast::ExprKind::Bool(v) => ExprKind::Bool(*v),
1056 arena_ast::ExprKind::Null => ExprKind::Null,
1057 arena_ast::ExprKind::Variable(s) => ExprKind::Variable(s.as_str().into()),
1058 arena_ast::ExprKind::VariableVariable(inner) => {
1059 ExprKind::VariableVariable(Box::new(owned_expr(inner)))
1060 }
1061 arena_ast::ExprKind::Identifier(s) => ExprKind::Identifier(s.as_str().into()),
1062 arena_ast::ExprKind::Assign(a) => ExprKind::Assign(AssignExpr {
1063 target: Box::new(owned_expr(a.target)),
1064 op: a.op,
1065 value: Box::new(owned_expr(a.value)),
1066 by_ref: a.by_ref,
1067 }),
1068 arena_ast::ExprKind::Binary(b) => ExprKind::Binary(BinaryExpr {
1069 left: Box::new(owned_expr(b.left)),
1070 op: b.op,
1071 right: Box::new(owned_expr(b.right)),
1072 }),
1073 arena_ast::ExprKind::UnaryPrefix(u) => ExprKind::UnaryPrefix(UnaryPrefixExpr {
1074 op: u.op,
1075 operand: Box::new(owned_expr(u.operand)),
1076 }),
1077 arena_ast::ExprKind::UnaryPostfix(u) => ExprKind::UnaryPostfix(UnaryPostfixExpr {
1078 operand: Box::new(owned_expr(u.operand)),
1079 op: u.op,
1080 }),
1081 arena_ast::ExprKind::Ternary(t) => ExprKind::Ternary(TernaryExpr {
1082 condition: Box::new(owned_expr(t.condition)),
1083 then_expr: t.then_expr.map(|e| Box::new(owned_expr(e))),
1084 else_expr: Box::new(owned_expr(t.else_expr)),
1085 }),
1086 arena_ast::ExprKind::NullCoalesce(n) => ExprKind::NullCoalesce(NullCoalesceExpr {
1087 left: Box::new(owned_expr(n.left)),
1088 right: Box::new(owned_expr(n.right)),
1089 }),
1090 arena_ast::ExprKind::FunctionCall(f) => ExprKind::FunctionCall(FunctionCallExpr {
1091 name: Box::new(owned_expr(f.name)),
1092 args: owned_args(&f.args),
1093 }),
1094 arena_ast::ExprKind::Array(elems) => ExprKind::Array(
1095 elems
1096 .iter()
1097 .map(|e| ArrayElement {
1098 key: e.key.as_ref().map(owned_expr),
1099 value: owned_expr(&e.value),
1100 unpack: e.unpack,
1101 by_ref: e.by_ref,
1102 span: e.span,
1103 })
1104 .collect::<Vec<_>>()
1105 .into_boxed_slice(),
1106 ),
1107 arena_ast::ExprKind::ArrayAccess(a) => ExprKind::ArrayAccess(ArrayAccessExpr {
1108 array: Box::new(owned_expr(a.array)),
1109 index: a.index.map(|e| Box::new(owned_expr(e))),
1110 }),
1111 arena_ast::ExprKind::Print(e) => ExprKind::Print(Box::new(owned_expr(e))),
1112 arena_ast::ExprKind::Parenthesized(e) => ExprKind::Parenthesized(Box::new(owned_expr(e))),
1113 arena_ast::ExprKind::Cast(kind, e) => ExprKind::Cast(*kind, Box::new(owned_expr(e))),
1114 arena_ast::ExprKind::ErrorSuppress(e) => ExprKind::ErrorSuppress(Box::new(owned_expr(e))),
1115 arena_ast::ExprKind::Isset(exprs) => ExprKind::Isset(owned_exprs(exprs)),
1116 arena_ast::ExprKind::Empty(e) => ExprKind::Empty(Box::new(owned_expr(e))),
1117 arena_ast::ExprKind::Include(kind, e) => ExprKind::Include(*kind, Box::new(owned_expr(e))),
1118 arena_ast::ExprKind::Eval(e) => ExprKind::Eval(Box::new(owned_expr(e))),
1119 arena_ast::ExprKind::Exit(e) => ExprKind::Exit(e.map(|e| Box::new(owned_expr(e)))),
1120 arena_ast::ExprKind::MagicConst(m) => ExprKind::MagicConst(*m),
1121 arena_ast::ExprKind::Clone(e) => ExprKind::Clone(Box::new(owned_expr(e))),
1122 arena_ast::ExprKind::CloneWith(obj, props) => {
1123 ExprKind::CloneWith(Box::new(owned_expr(obj)), Box::new(owned_expr(props)))
1124 }
1125 arena_ast::ExprKind::New(n) => ExprKind::New(NewExpr {
1126 class: Box::new(owned_expr(n.class)),
1127 args: owned_args(&n.args),
1128 }),
1129 arena_ast::ExprKind::PropertyAccess(p) => ExprKind::PropertyAccess(PropertyAccessExpr {
1130 object: Box::new(owned_expr(p.object)),
1131 property: Box::new(owned_expr(p.property)),
1132 }),
1133 arena_ast::ExprKind::NullsafePropertyAccess(p) => {
1134 ExprKind::NullsafePropertyAccess(PropertyAccessExpr {
1135 object: Box::new(owned_expr(p.object)),
1136 property: Box::new(owned_expr(p.property)),
1137 })
1138 }
1139 arena_ast::ExprKind::MethodCall(m) => ExprKind::MethodCall(Box::new(MethodCallExpr {
1140 object: Box::new(owned_expr(m.object)),
1141 method: Box::new(owned_expr(m.method)),
1142 args: owned_args(&m.args),
1143 })),
1144 arena_ast::ExprKind::NullsafeMethodCall(m) => {
1145 ExprKind::NullsafeMethodCall(Box::new(MethodCallExpr {
1146 object: Box::new(owned_expr(m.object)),
1147 method: Box::new(owned_expr(m.method)),
1148 args: owned_args(&m.args),
1149 }))
1150 }
1151 arena_ast::ExprKind::StaticPropertyAccess(s) => {
1152 ExprKind::StaticPropertyAccess(StaticAccessExpr {
1153 class: Box::new(owned_expr(s.class)),
1154 member: Box::new(owned_expr(s.member)),
1155 })
1156 }
1157 arena_ast::ExprKind::StaticMethodCall(s) => {
1158 ExprKind::StaticMethodCall(Box::new(StaticMethodCallExpr {
1159 class: Box::new(owned_expr(s.class)),
1160 method: Box::new(owned_expr(s.method)),
1161 args: owned_args(&s.args),
1162 }))
1163 }
1164 arena_ast::ExprKind::StaticDynMethodCall(s) => {
1165 ExprKind::StaticDynMethodCall(Box::new(StaticDynMethodCallExpr {
1166 class: Box::new(owned_expr(s.class)),
1167 method: Box::new(owned_expr(s.method)),
1168 args: owned_args(&s.args),
1169 }))
1170 }
1171 arena_ast::ExprKind::ClassConstAccess(s) => ExprKind::ClassConstAccess(StaticAccessExpr {
1172 class: Box::new(owned_expr(s.class)),
1173 member: Box::new(owned_expr(s.member)),
1174 }),
1175 arena_ast::ExprKind::ClassConstAccessDynamic { class, member } => {
1176 ExprKind::ClassConstAccessDynamic {
1177 class: Box::new(owned_expr(class)),
1178 member: Box::new(owned_expr(member)),
1179 }
1180 }
1181 arena_ast::ExprKind::StaticPropertyAccessDynamic { class, member } => {
1182 ExprKind::StaticPropertyAccessDynamic {
1183 class: Box::new(owned_expr(class)),
1184 member: Box::new(owned_expr(member)),
1185 }
1186 }
1187 arena_ast::ExprKind::Closure(c) => ExprKind::Closure(Box::new(ClosureExpr {
1188 is_static: c.is_static,
1189 by_ref: c.by_ref,
1190 params: owned_params(&c.params),
1191 use_vars: c
1192 .use_vars
1193 .iter()
1194 .map(|v| ClosureUseVar {
1195 name: v.name.into(),
1196 by_ref: v.by_ref,
1197 span: v.span,
1198 })
1199 .collect::<Vec<_>>()
1200 .into_boxed_slice(),
1201 return_type: c.return_type.as_ref().map(owned_type_hint),
1202 body: Box::new(owned_block(c.body)),
1203 attributes: owned_attrs(&c.attributes),
1204 })),
1205 arena_ast::ExprKind::ArrowFunction(f) => {
1206 ExprKind::ArrowFunction(Box::new(ArrowFunctionExpr {
1207 is_static: f.is_static,
1208 by_ref: f.by_ref,
1209 params: owned_params(&f.params),
1210 return_type: f.return_type.as_ref().map(owned_type_hint),
1211 body: Box::new(owned_expr(f.body)),
1212 attributes: owned_attrs(&f.attributes),
1213 }))
1214 }
1215 arena_ast::ExprKind::Match(m) => ExprKind::Match(MatchExpr {
1216 subject: Box::new(owned_expr(m.subject)),
1217 arms: m
1218 .arms
1219 .iter()
1220 .map(|arm| MatchArm {
1221 conditions: arm.conditions.as_ref().map(|conds| owned_exprs(conds)),
1222 body: owned_expr(&arm.body),
1223 span: arm.span,
1224 })
1225 .collect::<Vec<_>>()
1226 .into_boxed_slice(),
1227 brace_start: m.brace_start,
1228 }),
1229 arena_ast::ExprKind::ThrowExpr(e) => ExprKind::ThrowExpr(Box::new(owned_expr(e))),
1230 arena_ast::ExprKind::Yield(y) => ExprKind::Yield(YieldExpr {
1231 key: y.key.map(|e| Box::new(owned_expr(e))),
1232 value: y.value.map(|e| Box::new(owned_expr(e))),
1233 is_from: y.is_from,
1234 }),
1235 arena_ast::ExprKind::AnonymousClass(cls) => {
1236 ExprKind::AnonymousClass(Box::new(owned_class_decl(cls)))
1237 }
1238 arena_ast::ExprKind::CallableCreate(c) => ExprKind::CallableCreate(CallableCreateExpr {
1239 kind: match &c.kind {
1240 arena_ast::CallableCreateKind::Function(e) => {
1241 CallableCreateKind::Function(Box::new(owned_expr(e)))
1242 }
1243 arena_ast::CallableCreateKind::Method { object, method } => {
1244 CallableCreateKind::Method {
1245 object: Box::new(owned_expr(object)),
1246 method: Box::new(owned_expr(method)),
1247 }
1248 }
1249 arena_ast::CallableCreateKind::NullsafeMethod { object, method } => {
1250 CallableCreateKind::NullsafeMethod {
1251 object: Box::new(owned_expr(object)),
1252 method: Box::new(owned_expr(method)),
1253 }
1254 }
1255 arena_ast::CallableCreateKind::StaticMethod { class, method } => {
1256 CallableCreateKind::StaticMethod {
1257 class: Box::new(owned_expr(class)),
1258 method: Box::new(owned_expr(method)),
1259 }
1260 }
1261 },
1262 }),
1263 arena_ast::ExprKind::Omit => ExprKind::Omit,
1264 arena_ast::ExprKind::Error => ExprKind::Error,
1265 }
1266}
1267
1268fn owned_param(p: &arena_ast::Param<'_, '_>) -> Param {
1269 Param {
1270 name: owned_ident(p.name),
1271 type_hint: p.type_hint.as_ref().map(owned_type_hint),
1272 default: p.default.as_ref().map(owned_expr),
1273 by_ref: p.by_ref,
1274 variadic: p.variadic,
1275 is_readonly: p.is_readonly,
1276 is_final: p.is_final,
1277 visibility: p.visibility,
1278 set_visibility: p.set_visibility,
1279 attributes: owned_attrs(&p.attributes),
1280 hooks: owned_hooks(&p.hooks),
1281 span: p.span,
1282 }
1283}
1284
1285fn owned_params(params: &[arena_ast::Param<'_, '_>]) -> Box<[Param]> {
1286 params
1287 .iter()
1288 .map(owned_param)
1289 .collect::<Vec<_>>()
1290 .into_boxed_slice()
1291}
1292
1293fn owned_hook(h: &arena_ast::PropertyHook<'_, '_>) -> PropertyHook {
1294 PropertyHook {
1295 kind: h.kind,
1296 body: match &h.body {
1297 arena_ast::PropertyHookBody::Block(block) => {
1298 PropertyHookBody::Block(Box::new(owned_block(block)))
1299 }
1300 arena_ast::PropertyHookBody::Expression(e) => {
1301 PropertyHookBody::Expression(owned_expr(e))
1302 }
1303 arena_ast::PropertyHookBody::Abstract => PropertyHookBody::Abstract,
1304 },
1305 is_final: h.is_final,
1306 by_ref: h.by_ref,
1307 params: owned_params(&h.params),
1308 attributes: owned_attrs(&h.attributes),
1309 span: h.span,
1310 }
1311}
1312
1313fn owned_hooks(hooks: &[arena_ast::PropertyHook<'_, '_>]) -> Box<[PropertyHook]> {
1314 hooks
1315 .iter()
1316 .map(owned_hook)
1317 .collect::<Vec<_>>()
1318 .into_boxed_slice()
1319}
1320
1321fn owned_stmts(stmts: &[arena_ast::Stmt<'_, '_>]) -> Box<[Stmt]> {
1322 stmts
1323 .iter()
1324 .map(owned_stmt)
1325 .collect::<Vec<_>>()
1326 .into_boxed_slice()
1327}
1328
1329pub fn to_owned_stmt(stmt: &arena_ast::Stmt<'_, '_>) -> Stmt {
1331 owned_stmt(stmt)
1332}
1333
1334fn owned_block(block: &arena_ast::Block<'_, '_>) -> Block {
1335 Block {
1336 stmts: owned_stmts(&block.stmts),
1337 span: block.span,
1338 }
1339}
1340
1341fn owned_stmt(stmt: &arena_ast::Stmt<'_, '_>) -> Stmt {
1342 Stmt {
1343 kind: owned_stmt_kind(&stmt.kind),
1344 span: stmt.span,
1345 doc_comment: stmt.doc_comment.map(owned_comment),
1346 }
1347}
1348
1349fn owned_stmt_kind(k: &arena_ast::StmtKind<'_, '_>) -> StmtKind {
1350 match k {
1351 arena_ast::StmtKind::Expression(e) => StmtKind::Expression(Box::new(owned_expr(e))),
1352 arena_ast::StmtKind::Echo(exprs) => StmtKind::Echo(owned_exprs(exprs)),
1353 arena_ast::StmtKind::Return(e) => StmtKind::Return(e.map(|e| Box::new(owned_expr(e)))),
1354 arena_ast::StmtKind::Block(block) => StmtKind::Block(Box::new(owned_block(block))),
1355 arena_ast::StmtKind::If(s) => StmtKind::If(Box::new(IfStmt {
1356 condition: owned_expr(&s.condition),
1357 then_branch: Box::new(owned_stmt(s.then_branch)),
1358 elseif_branches: s
1359 .elseif_branches
1360 .iter()
1361 .map(|b| ElseIfBranch {
1362 condition: owned_expr(&b.condition),
1363 body: owned_stmt(&b.body),
1364 span: b.span,
1365 })
1366 .collect::<Vec<_>>()
1367 .into_boxed_slice(),
1368 else_branch: s.else_branch.map(|b| Box::new(owned_stmt(b))),
1369 else_kw_start: s.else_kw_start,
1370 uses_alternative: s.uses_alternative,
1371 })),
1372 arena_ast::StmtKind::While(s) => StmtKind::While(Box::new(WhileStmt {
1373 condition: owned_expr(&s.condition),
1374 body: Box::new(owned_stmt(s.body)),
1375 uses_alternative: s.uses_alternative,
1376 })),
1377 arena_ast::StmtKind::For(s) => StmtKind::For(Box::new(ForStmt {
1378 init: owned_exprs(&s.init),
1379 condition: owned_exprs(&s.condition),
1380 update: owned_exprs(&s.update),
1381 body: Box::new(owned_stmt(s.body)),
1382 uses_alternative: s.uses_alternative,
1383 })),
1384 arena_ast::StmtKind::Foreach(s) => StmtKind::Foreach(Box::new(ForeachStmt {
1385 expr: owned_expr(&s.expr),
1386 key: s.key.as_ref().map(owned_expr),
1387 value: owned_expr(&s.value),
1388 body: Box::new(owned_stmt(s.body)),
1389 uses_alternative: s.uses_alternative,
1390 })),
1391 arena_ast::StmtKind::DoWhile(s) => StmtKind::DoWhile(Box::new(DoWhileStmt {
1392 body: Box::new(owned_stmt(s.body)),
1393 condition: owned_expr(&s.condition),
1394 })),
1395 arena_ast::StmtKind::Function(f) => StmtKind::Function(Box::new(owned_function_decl(f))),
1396 arena_ast::StmtKind::Break(e) => StmtKind::Break(e.map(|e| Box::new(owned_expr(e)))),
1397 arena_ast::StmtKind::Continue(e) => StmtKind::Continue(e.map(|e| Box::new(owned_expr(e)))),
1398 arena_ast::StmtKind::Switch(s) => StmtKind::Switch(Box::new(SwitchStmt {
1399 expr: owned_expr(&s.expr),
1400 body: SwitchBody {
1401 cases: s
1402 .body
1403 .cases
1404 .iter()
1405 .map(|c| SwitchCase {
1406 value: c.value.as_ref().map(owned_expr),
1407 body: owned_stmts(&c.body),
1408 span: c.span,
1409 })
1410 .collect::<Vec<_>>()
1411 .into_boxed_slice(),
1412 span: s.body.span,
1413 },
1414 uses_alternative: s.uses_alternative,
1415 })),
1416 arena_ast::StmtKind::Goto(ident) => StmtKind::Goto(owned_ident(*ident)),
1417 arena_ast::StmtKind::Label(s) => StmtKind::Label(Box::from(*s)),
1418 arena_ast::StmtKind::Declare(d) => StmtKind::Declare(Box::new(DeclareStmt {
1419 directives: d
1420 .directives
1421 .iter()
1422 .map(|(k, v)| (Box::from(*k), owned_expr(v)))
1423 .collect::<Vec<_>>()
1424 .into_boxed_slice(),
1425 body: d.body.map(|b| Box::new(owned_stmt(b))),
1426 uses_alternative: d.uses_alternative,
1427 })),
1428 arena_ast::StmtKind::Unset(exprs) => StmtKind::Unset(owned_exprs(exprs)),
1429 arena_ast::StmtKind::Throw(e) => StmtKind::Throw(Box::new(owned_expr(e))),
1430 arena_ast::StmtKind::TryCatch(t) => StmtKind::TryCatch(Box::new(TryCatchStmt {
1431 body: Box::new(owned_block(t.body)),
1432 catches: t
1433 .catches
1434 .iter()
1435 .map(|c| CatchClause {
1436 types: c
1437 .types
1438 .iter()
1439 .map(owned_name)
1440 .collect::<Vec<_>>()
1441 .into_boxed_slice(),
1442 var: c.var.map(Box::from),
1443 body: Box::new(owned_block(c.body)),
1444 span: c.span,
1445 })
1446 .collect::<Vec<_>>()
1447 .into_boxed_slice(),
1448 finally: t.finally.map(|f| Box::new(owned_block(f))),
1449 finally_kw_start: t.finally_kw_start,
1450 })),
1451 arena_ast::StmtKind::Global(exprs) => StmtKind::Global(owned_exprs(exprs)),
1452 arena_ast::StmtKind::Class(cls) => StmtKind::Class(Box::new(owned_class_decl(cls))),
1453 arena_ast::StmtKind::Interface(iface) => {
1454 StmtKind::Interface(Box::new(owned_interface_decl(iface)))
1455 }
1456 arena_ast::StmtKind::Trait(tr) => StmtKind::Trait(Box::new(owned_trait_decl(tr))),
1457 arena_ast::StmtKind::Enum(en) => StmtKind::Enum(Box::new(owned_enum_decl(en))),
1458 arena_ast::StmtKind::Namespace(ns) => StmtKind::Namespace(Box::new(NamespaceDecl {
1459 name: ns.name.as_ref().map(owned_name),
1460 body: match &ns.body {
1461 arena_ast::NamespaceBody::Braced(block) => {
1462 NamespaceBody::Braced(Box::new(owned_block(block)))
1463 }
1464 arena_ast::NamespaceBody::Simple => NamespaceBody::Simple,
1465 },
1466 })),
1467 arena_ast::StmtKind::Use(u) => StmtKind::Use(Box::new(UseDecl {
1468 kind: u.kind,
1469 uses: u
1470 .uses
1471 .iter()
1472 .map(|item| UseItem {
1473 name: owned_name(&item.name),
1474 alias: item.alias.map(Box::from),
1475 kind: item.kind,
1476 span: item.span,
1477 })
1478 .collect::<Vec<_>>()
1479 .into_boxed_slice(),
1480 })),
1481 arena_ast::StmtKind::Const(items) => StmtKind::Const(
1482 items
1483 .iter()
1484 .map(|item| ConstItem {
1485 name: owned_ident(item.name),
1486 value: owned_expr(&item.value),
1487 attributes: owned_attrs(&item.attributes),
1488 span: item.span,
1489 doc_comment: owned_opt_comment(&item.doc_comment),
1490 })
1491 .collect::<Vec<_>>()
1492 .into_boxed_slice(),
1493 ),
1494 arena_ast::StmtKind::StaticVar(vars) => StmtKind::StaticVar(
1495 vars.iter()
1496 .map(|v| StaticVar {
1497 name: owned_ident(v.name),
1498 default: v.default.as_ref().map(owned_expr),
1499 span: v.span,
1500 })
1501 .collect::<Vec<_>>()
1502 .into_boxed_slice(),
1503 ),
1504 arena_ast::StmtKind::HaltCompiler(s) => StmtKind::HaltCompiler(Box::from(*s)),
1505 arena_ast::StmtKind::Nop => StmtKind::Nop,
1506 arena_ast::StmtKind::InlineHtml(s) => StmtKind::InlineHtml(Box::from(*s)),
1507 arena_ast::StmtKind::Error => StmtKind::Error,
1508 }
1509}
1510
1511fn owned_function_decl(f: &arena_ast::FunctionDecl<'_, '_>) -> FunctionDecl {
1512 FunctionDecl {
1513 name: owned_ident(f.name),
1514 params: owned_params(&f.params),
1515 body: Box::new(owned_block(f.body)),
1516 return_type: f.return_type.as_ref().map(owned_type_hint),
1517 by_ref: f.by_ref,
1518 attributes: owned_attrs(&f.attributes),
1519 doc_comment: owned_opt_comment(&f.doc_comment),
1520 }
1521}
1522
1523fn owned_class_member(m: &arena_ast::ClassMember<'_, '_>) -> ClassMember {
1524 ClassMember {
1525 kind: match &m.kind {
1526 arena_ast::ClassMemberKind::Property(p) => ClassMemberKind::Property(PropertyDecl {
1527 name: owned_ident(p.name),
1528 visibility: p.visibility,
1529 set_visibility: p.set_visibility,
1530 is_static: p.is_static,
1531 is_readonly: p.is_readonly,
1532 type_hint: p.type_hint.as_ref().map(owned_type_hint),
1533 default: p.default.as_ref().map(owned_expr),
1534 attributes: owned_attrs(&p.attributes),
1535 hooks: owned_hooks(&p.hooks),
1536 doc_comment: owned_opt_comment(&p.doc_comment),
1537 }),
1538 arena_ast::ClassMemberKind::Method(m) => ClassMemberKind::Method(MethodDecl {
1539 name: owned_ident(m.name),
1540 visibility: m.visibility,
1541 is_static: m.is_static,
1542 is_abstract: m.is_abstract,
1543 is_final: m.is_final,
1544 by_ref: m.by_ref,
1545 params: owned_params(&m.params),
1546 return_type: m.return_type.as_ref().map(owned_type_hint),
1547 body: m.body.map(|b| Box::new(owned_block(b))),
1548 attributes: owned_attrs(&m.attributes),
1549 doc_comment: owned_opt_comment(&m.doc_comment),
1550 }),
1551 arena_ast::ClassMemberKind::ClassConst(c) => {
1552 ClassMemberKind::ClassConst(owned_class_const(c))
1553 }
1554 arena_ast::ClassMemberKind::TraitUse(t) => {
1555 ClassMemberKind::TraitUse(owned_trait_use(t))
1556 }
1557 },
1558 span: m.span,
1559 }
1560}
1561
1562fn owned_class_members(members: &[arena_ast::ClassMember<'_, '_>]) -> Box<[ClassMember]> {
1563 members
1564 .iter()
1565 .map(owned_class_member)
1566 .collect::<Vec<_>>()
1567 .into_boxed_slice()
1568}
1569
1570fn owned_class_const(c: &arena_ast::ClassConstDecl<'_, '_>) -> ClassConstDecl {
1571 ClassConstDecl {
1572 name: owned_ident(c.name),
1573 visibility: c.visibility,
1574 is_final: c.is_final,
1575 type_hint: c.type_hint.map(|th| Box::new(owned_type_hint(th))),
1576 value: owned_expr(&c.value),
1577 attributes: owned_attrs(&c.attributes),
1578 doc_comment: owned_opt_comment(&c.doc_comment),
1579 }
1580}
1581
1582fn owned_trait_use(t: &arena_ast::TraitUseDecl<'_, '_>) -> TraitUseDecl {
1583 TraitUseDecl {
1584 traits: t
1585 .traits
1586 .iter()
1587 .map(owned_name)
1588 .collect::<Vec<_>>()
1589 .into_boxed_slice(),
1590 adaptations: t
1591 .adaptations
1592 .iter()
1593 .map(|a| TraitAdaptation {
1594 kind: match &a.kind {
1595 arena_ast::TraitAdaptationKind::Precedence {
1596 trait_name,
1597 method,
1598 insteadof,
1599 } => TraitAdaptationKind::Precedence {
1600 trait_name: owned_name(trait_name),
1601 method: owned_name(method),
1602 insteadof: insteadof
1603 .iter()
1604 .map(owned_name)
1605 .collect::<Vec<_>>()
1606 .into_boxed_slice(),
1607 },
1608 arena_ast::TraitAdaptationKind::Alias {
1609 trait_name,
1610 method,
1611 new_modifier,
1612 new_name,
1613 } => TraitAdaptationKind::Alias {
1614 trait_name: trait_name.as_ref().map(owned_name),
1615 method: owned_name(method),
1616 new_modifier: *new_modifier,
1617 new_name: new_name.as_ref().map(owned_name),
1618 },
1619 },
1620 span: a.span,
1621 })
1622 .collect::<Vec<_>>()
1623 .into_boxed_slice(),
1624 adaptations_brace_start: t.adaptations_brace_start,
1625 }
1626}
1627
1628fn owned_class_decl(cls: &arena_ast::ClassDecl<'_, '_>) -> ClassDecl {
1629 ClassDecl {
1630 name: cls
1631 .name
1632 .map(|ident| Some(owned_ident(ident)))
1633 .unwrap_or(None),
1634 modifiers: cls.modifiers.clone(),
1635 extends: cls.extends.as_ref().map(owned_name),
1636 implements: cls
1637 .implements
1638 .iter()
1639 .map(owned_name)
1640 .collect::<Vec<_>>()
1641 .into_boxed_slice(),
1642 body: ClassBody {
1643 members: owned_class_members(&cls.body.members),
1644 span: cls.body.span,
1645 },
1646 attributes: owned_attrs(&cls.attributes),
1647 doc_comment: owned_opt_comment(&cls.doc_comment),
1648 }
1649}
1650
1651fn owned_interface_decl(iface: &arena_ast::InterfaceDecl<'_, '_>) -> InterfaceDecl {
1652 InterfaceDecl {
1653 name: owned_ident(iface.name),
1654 extends: iface
1655 .extends
1656 .iter()
1657 .map(owned_name)
1658 .collect::<Vec<_>>()
1659 .into_boxed_slice(),
1660 body: ClassBody {
1661 members: owned_class_members(&iface.body.members),
1662 span: iface.body.span,
1663 },
1664 attributes: owned_attrs(&iface.attributes),
1665 doc_comment: owned_opt_comment(&iface.doc_comment),
1666 }
1667}
1668
1669fn owned_trait_decl(tr: &arena_ast::TraitDecl<'_, '_>) -> TraitDecl {
1670 TraitDecl {
1671 name: owned_ident(tr.name),
1672 body: ClassBody {
1673 members: owned_class_members(&tr.body.members),
1674 span: tr.body.span,
1675 },
1676 attributes: owned_attrs(&tr.attributes),
1677 doc_comment: owned_opt_comment(&tr.doc_comment),
1678 }
1679}
1680
1681fn owned_enum_decl(en: &arena_ast::EnumDecl<'_, '_>) -> EnumDecl {
1682 EnumDecl {
1683 name: owned_ident(en.name),
1684 scalar_type: en.scalar_type.as_ref().map(owned_name),
1685 implements: en
1686 .implements
1687 .iter()
1688 .map(owned_name)
1689 .collect::<Vec<_>>()
1690 .into_boxed_slice(),
1691 body: EnumBody {
1692 members: en
1693 .body
1694 .members
1695 .iter()
1696 .map(|m| EnumMember {
1697 kind: match &m.kind {
1698 arena_ast::EnumMemberKind::Case(c) => EnumMemberKind::Case(EnumCase {
1699 name: owned_ident(c.name),
1700 value: c.value.as_ref().map(owned_expr),
1701 attributes: owned_attrs(&c.attributes),
1702 doc_comment: owned_opt_comment(&c.doc_comment),
1703 }),
1704 arena_ast::EnumMemberKind::Method(m) => {
1705 EnumMemberKind::Method(MethodDecl {
1706 name: owned_ident(m.name),
1707 visibility: m.visibility,
1708 is_static: m.is_static,
1709 is_abstract: m.is_abstract,
1710 is_final: m.is_final,
1711 by_ref: m.by_ref,
1712 params: owned_params(&m.params),
1713 return_type: m.return_type.as_ref().map(owned_type_hint),
1714 body: m.body.map(|b| Box::new(owned_block(b))),
1715 attributes: owned_attrs(&m.attributes),
1716 doc_comment: owned_opt_comment(&m.doc_comment),
1717 })
1718 }
1719 arena_ast::EnumMemberKind::ClassConst(c) => {
1720 EnumMemberKind::ClassConst(owned_class_const(c))
1721 }
1722 arena_ast::EnumMemberKind::TraitUse(t) => {
1723 EnumMemberKind::TraitUse(owned_trait_use(t))
1724 }
1725 },
1726 span: m.span,
1727 })
1728 .collect::<Vec<_>>()
1729 .into_boxed_slice(),
1730 span: en.body.span,
1731 },
1732 attributes: owned_attrs(&en.attributes),
1733 doc_comment: owned_opt_comment(&en.doc_comment),
1734 }
1735}
1736
1737pub fn to_owned_program(program: &arena_ast::Program<'_, '_>) -> Program {
1739 Program {
1740 stmts: owned_stmts(&program.stmts),
1741 span: program.span,
1742 }
1743}
1744
1745pub fn from_owned_program<'arena>(
1759 arena: &'arena bumpalo::Bump,
1760 program: &Program,
1761) -> arena_ast::Program<'arena, 'arena> {
1762 arena_ast::Program {
1763 stmts: av_stmts(arena, &program.stmts),
1764 span: program.span,
1765 }
1766}
1767
1768#[inline]
1770fn av_str<'a>(arena: &'a bumpalo::Bump, s: &str) -> &'a str {
1771 arena.alloc_str(s)
1772}
1773
1774fn av_ident<'a>(arena: &'a bumpalo::Bump, ident: &Ident) -> arena_ast::Ident<'a> {
1775 match ident {
1776 Some(s) => arena_ast::Ident::name(arena.alloc_str(s)),
1777 None => arena_ast::Ident::ERROR,
1778 }
1779}
1780
1781fn av_name<'a>(arena: &'a bumpalo::Bump, name: &Name) -> arena_ast::Name<'a, 'a> {
1782 if name.kind == NameKind::Error {
1783 return arena_ast::Name::Error { span: name.span };
1784 }
1785 if name.parts.len() == 1 && name.kind == NameKind::Unqualified {
1786 return arena_ast::Name::Simple {
1787 value: arena.alloc_str(&name.parts[0]),
1788 span: name.span,
1789 };
1790 }
1791 let mut parts = arena_ast::ArenaVec::with_capacity_in(name.parts.len(), arena);
1792 for p in name.parts.iter() {
1793 parts.push(arena.alloc_str(p) as &str);
1794 }
1795 arena_ast::Name::Complex {
1796 parts,
1797 kind: name.kind,
1798 span: name.span,
1799 }
1800}
1801
1802fn av_type_hint<'a>(arena: &'a bumpalo::Bump, th: &TypeHint) -> arena_ast::TypeHint<'a, 'a> {
1803 arena_ast::TypeHint {
1804 kind: av_type_hint_kind(arena, &th.kind),
1805 span: th.span,
1806 }
1807}
1808
1809fn av_type_hint_kind<'a>(
1810 arena: &'a bumpalo::Bump,
1811 k: &TypeHintKind,
1812) -> arena_ast::TypeHintKind<'a, 'a> {
1813 match k {
1814 TypeHintKind::Named(n) => arena_ast::TypeHintKind::Named(av_name(arena, n)),
1815 TypeHintKind::Keyword(b, span) => arena_ast::TypeHintKind::Keyword(*b, *span),
1816 TypeHintKind::Nullable(inner) => {
1817 arena_ast::TypeHintKind::Nullable(arena.alloc(av_type_hint(arena, inner)))
1818 }
1819 TypeHintKind::Union(types) => {
1820 let mut v = arena_ast::ArenaVec::with_capacity_in(types.len(), arena);
1821 for t in types.iter() {
1822 v.push(av_type_hint(arena, t));
1823 }
1824 arena_ast::TypeHintKind::Union(v)
1825 }
1826 TypeHintKind::Intersection(types) => {
1827 let mut v = arena_ast::ArenaVec::with_capacity_in(types.len(), arena);
1828 for t in types.iter() {
1829 v.push(av_type_hint(arena, t));
1830 }
1831 arena_ast::TypeHintKind::Intersection(v)
1832 }
1833 }
1834}
1835
1836fn av_arg<'a>(arena: &'a bumpalo::Bump, arg: &Arg) -> arena_ast::Arg<'a, 'a> {
1837 arena_ast::Arg {
1838 name: arg.name.as_ref().map(|n| av_name(arena, n)),
1839 value: arg.value.as_ref().map(|v| av_expr(arena, v)),
1840 unpack: arg.unpack,
1841 by_ref: arg.by_ref,
1842 span: arg.span,
1843 }
1844}
1845
1846fn av_args<'a>(
1847 arena: &'a bumpalo::Bump,
1848 args: &[Arg],
1849) -> arena_ast::ArenaVec<'a, arena_ast::Arg<'a, 'a>> {
1850 let mut v = arena_ast::ArenaVec::with_capacity_in(args.len(), arena);
1851 for a in args.iter() {
1852 v.push(av_arg(arena, a));
1853 }
1854 v
1855}
1856
1857fn av_attr<'a>(arena: &'a bumpalo::Bump, attr: &Attribute) -> arena_ast::Attribute<'a, 'a> {
1858 arena_ast::Attribute {
1859 name: av_name(arena, &attr.name),
1860 args: av_args(arena, &attr.args),
1861 span: attr.span,
1862 }
1863}
1864
1865fn av_attrs<'a>(
1866 arena: &'a bumpalo::Bump,
1867 attrs: &[Attribute],
1868) -> arena_ast::ArenaVec<'a, arena_ast::Attribute<'a, 'a>> {
1869 let mut v = arena_ast::ArenaVec::with_capacity_in(attrs.len(), arena);
1870 for a in attrs.iter() {
1871 v.push(av_attr(arena, a));
1872 }
1873 v
1874}
1875
1876fn av_comment<'a>(arena: &'a bumpalo::Bump, c: &Comment) -> arena_ast::Comment<'a> {
1877 arena_ast::Comment {
1878 kind: c.kind,
1879 text: arena.alloc_str(&c.text),
1880 span: c.span,
1881 }
1882}
1883
1884fn av_opt_comment<'a>(
1885 arena: &'a bumpalo::Bump,
1886 c: &Option<Comment>,
1887) -> Option<arena_ast::Comment<'a>> {
1888 c.as_ref().map(|c| av_comment(arena, c))
1889}
1890
1891fn av_string_parts<'a>(
1892 arena: &'a bumpalo::Bump,
1893 parts: &[StringPart],
1894) -> arena_ast::ArenaVec<'a, arena_ast::StringPart<'a, 'a>> {
1895 let mut v = arena_ast::ArenaVec::with_capacity_in(parts.len(), arena);
1896 for p in parts.iter() {
1897 v.push(match p {
1898 StringPart::Literal(s) => arena_ast::StringPart::Literal(arena.alloc_str(s)),
1899 StringPart::Expr(e) => arena_ast::StringPart::Expr(av_expr(arena, e)),
1900 });
1901 }
1902 v
1903}
1904
1905fn av_expr<'a>(arena: &'a bumpalo::Bump, expr: &Expr) -> arena_ast::Expr<'a, 'a> {
1906 arena_ast::Expr {
1907 kind: av_expr_kind(arena, &expr.kind),
1908 span: expr.span,
1909 }
1910}
1911
1912fn av_exprs<'a>(
1913 arena: &'a bumpalo::Bump,
1914 exprs: &[Expr],
1915) -> arena_ast::ArenaVec<'a, arena_ast::Expr<'a, 'a>> {
1916 let mut v = arena_ast::ArenaVec::with_capacity_in(exprs.len(), arena);
1917 for e in exprs.iter() {
1918 v.push(av_expr(arena, e));
1919 }
1920 v
1921}
1922
1923fn av_namestr<'a>(arena: &'a bumpalo::Bump, s: &str) -> arena_ast::NameStr<'a, 'a> {
1924 arena_ast::NameStr::__arena(arena.alloc_str(s))
1925}
1926
1927fn av_expr_kind<'a>(arena: &'a bumpalo::Bump, k: &ExprKind) -> arena_ast::ExprKind<'a, 'a> {
1928 match k {
1929 ExprKind::Int(v) => arena_ast::ExprKind::Int(*v),
1930 ExprKind::Float(v) => arena_ast::ExprKind::Float(*v),
1931 ExprKind::String(s) => arena_ast::ExprKind::String(arena.alloc_str(s)),
1932 ExprKind::InterpolatedString(parts) => {
1933 arena_ast::ExprKind::InterpolatedString(av_string_parts(arena, parts))
1934 }
1935 ExprKind::Heredoc { label, parts } => arena_ast::ExprKind::Heredoc {
1936 label: arena.alloc_str(label),
1937 parts: av_string_parts(arena, parts),
1938 },
1939 ExprKind::Nowdoc { label, value } => arena_ast::ExprKind::Nowdoc {
1940 label: arena.alloc_str(label),
1941 value: arena.alloc_str(value),
1942 },
1943 ExprKind::ShellExec(parts) => arena_ast::ExprKind::ShellExec(av_string_parts(arena, parts)),
1944 ExprKind::Bool(v) => arena_ast::ExprKind::Bool(*v),
1945 ExprKind::Null => arena_ast::ExprKind::Null,
1946 ExprKind::Variable(s) => arena_ast::ExprKind::Variable(av_namestr(arena, s)),
1947 ExprKind::VariableVariable(inner) => {
1948 arena_ast::ExprKind::VariableVariable(arena.alloc(av_expr(arena, inner)))
1949 }
1950 ExprKind::Identifier(s) => arena_ast::ExprKind::Identifier(av_namestr(arena, s)),
1951 ExprKind::Assign(a) => arena_ast::ExprKind::Assign(arena_ast::AssignExpr {
1952 target: arena.alloc(av_expr(arena, &a.target)),
1953 op: a.op,
1954 value: arena.alloc(av_expr(arena, &a.value)),
1955 by_ref: a.by_ref,
1956 }),
1957 ExprKind::Binary(b) => arena_ast::ExprKind::Binary(arena_ast::BinaryExpr {
1958 left: arena.alloc(av_expr(arena, &b.left)),
1959 op: b.op,
1960 right: arena.alloc(av_expr(arena, &b.right)),
1961 }),
1962 ExprKind::UnaryPrefix(u) => arena_ast::ExprKind::UnaryPrefix(arena_ast::UnaryPrefixExpr {
1963 op: u.op,
1964 operand: arena.alloc(av_expr(arena, &u.operand)),
1965 }),
1966 ExprKind::UnaryPostfix(u) => {
1967 arena_ast::ExprKind::UnaryPostfix(arena_ast::UnaryPostfixExpr {
1968 operand: arena.alloc(av_expr(arena, &u.operand)),
1969 op: u.op,
1970 })
1971 }
1972 ExprKind::Ternary(t) => arena_ast::ExprKind::Ternary(arena_ast::TernaryExpr {
1973 condition: arena.alloc(av_expr(arena, &t.condition)),
1974 then_expr: t
1975 .then_expr
1976 .as_ref()
1977 .map(|e| &*arena.alloc(av_expr(arena, e))),
1978 else_expr: arena.alloc(av_expr(arena, &t.else_expr)),
1979 }),
1980 ExprKind::NullCoalesce(n) => {
1981 arena_ast::ExprKind::NullCoalesce(arena_ast::NullCoalesceExpr {
1982 left: arena.alloc(av_expr(arena, &n.left)),
1983 right: arena.alloc(av_expr(arena, &n.right)),
1984 })
1985 }
1986 ExprKind::FunctionCall(f) => {
1987 arena_ast::ExprKind::FunctionCall(arena_ast::FunctionCallExpr {
1988 name: arena.alloc(av_expr(arena, &f.name)),
1989 args: av_args(arena, &f.args),
1990 })
1991 }
1992 ExprKind::Array(elems) => {
1993 let mut v = arena_ast::ArenaVec::with_capacity_in(elems.len(), arena);
1994 for e in elems.iter() {
1995 v.push(arena_ast::ArrayElement {
1996 key: e.key.as_ref().map(|k| av_expr(arena, k)),
1997 value: av_expr(arena, &e.value),
1998 unpack: e.unpack,
1999 by_ref: e.by_ref,
2000 span: e.span,
2001 });
2002 }
2003 arena_ast::ExprKind::Array(v)
2004 }
2005 ExprKind::ArrayAccess(a) => arena_ast::ExprKind::ArrayAccess(arena_ast::ArrayAccessExpr {
2006 array: arena.alloc(av_expr(arena, &a.array)),
2007 index: a.index.as_ref().map(|e| &*arena.alloc(av_expr(arena, e))),
2008 }),
2009 ExprKind::Print(e) => arena_ast::ExprKind::Print(arena.alloc(av_expr(arena, e))),
2010 ExprKind::Parenthesized(e) => {
2011 arena_ast::ExprKind::Parenthesized(arena.alloc(av_expr(arena, e)))
2012 }
2013 ExprKind::Cast(kind, e) => arena_ast::ExprKind::Cast(*kind, arena.alloc(av_expr(arena, e))),
2014 ExprKind::ErrorSuppress(e) => {
2015 arena_ast::ExprKind::ErrorSuppress(arena.alloc(av_expr(arena, e)))
2016 }
2017 ExprKind::Isset(exprs) => arena_ast::ExprKind::Isset(av_exprs(arena, exprs)),
2018 ExprKind::Empty(e) => arena_ast::ExprKind::Empty(arena.alloc(av_expr(arena, e))),
2019 ExprKind::Include(kind, e) => {
2020 arena_ast::ExprKind::Include(*kind, arena.alloc(av_expr(arena, e)))
2021 }
2022 ExprKind::Eval(e) => arena_ast::ExprKind::Eval(arena.alloc(av_expr(arena, e))),
2023 ExprKind::Exit(e) => {
2024 arena_ast::ExprKind::Exit(e.as_ref().map(|e| &*arena.alloc(av_expr(arena, e))))
2025 }
2026 ExprKind::MagicConst(m) => arena_ast::ExprKind::MagicConst(*m),
2027 ExprKind::Clone(e) => arena_ast::ExprKind::Clone(arena.alloc(av_expr(arena, e))),
2028 ExprKind::CloneWith(obj, props) => arena_ast::ExprKind::CloneWith(
2029 arena.alloc(av_expr(arena, obj)),
2030 arena.alloc(av_expr(arena, props)),
2031 ),
2032 ExprKind::New(n) => arena_ast::ExprKind::New(arena_ast::NewExpr {
2033 class: arena.alloc(av_expr(arena, &n.class)),
2034 args: av_args(arena, &n.args),
2035 }),
2036 ExprKind::PropertyAccess(p) => {
2037 arena_ast::ExprKind::PropertyAccess(arena_ast::PropertyAccessExpr {
2038 object: arena.alloc(av_expr(arena, &p.object)),
2039 property: arena.alloc(av_expr(arena, &p.property)),
2040 })
2041 }
2042 ExprKind::NullsafePropertyAccess(p) => {
2043 arena_ast::ExprKind::NullsafePropertyAccess(arena_ast::PropertyAccessExpr {
2044 object: arena.alloc(av_expr(arena, &p.object)),
2045 property: arena.alloc(av_expr(arena, &p.property)),
2046 })
2047 }
2048 ExprKind::MethodCall(m) => {
2049 arena_ast::ExprKind::MethodCall(arena.alloc(arena_ast::MethodCallExpr {
2050 object: arena.alloc(av_expr(arena, &m.object)),
2051 method: arena.alloc(av_expr(arena, &m.method)),
2052 args: av_args(arena, &m.args),
2053 }))
2054 }
2055 ExprKind::NullsafeMethodCall(m) => {
2056 arena_ast::ExprKind::NullsafeMethodCall(arena.alloc(arena_ast::MethodCallExpr {
2057 object: arena.alloc(av_expr(arena, &m.object)),
2058 method: arena.alloc(av_expr(arena, &m.method)),
2059 args: av_args(arena, &m.args),
2060 }))
2061 }
2062 ExprKind::StaticPropertyAccess(s) => {
2063 arena_ast::ExprKind::StaticPropertyAccess(arena_ast::StaticAccessExpr {
2064 class: arena.alloc(av_expr(arena, &s.class)),
2065 member: arena.alloc(av_expr(arena, &s.member)),
2066 })
2067 }
2068 ExprKind::StaticMethodCall(s) => {
2069 arena_ast::ExprKind::StaticMethodCall(arena.alloc(arena_ast::StaticMethodCallExpr {
2070 class: arena.alloc(av_expr(arena, &s.class)),
2071 method: arena.alloc(av_expr(arena, &s.method)),
2072 args: av_args(arena, &s.args),
2073 }))
2074 }
2075 ExprKind::StaticDynMethodCall(s) => arena_ast::ExprKind::StaticDynMethodCall(arena.alloc(
2076 arena_ast::StaticDynMethodCallExpr {
2077 class: arena.alloc(av_expr(arena, &s.class)),
2078 method: arena.alloc(av_expr(arena, &s.method)),
2079 args: av_args(arena, &s.args),
2080 },
2081 )),
2082 ExprKind::ClassConstAccess(s) => {
2083 arena_ast::ExprKind::ClassConstAccess(arena_ast::StaticAccessExpr {
2084 class: arena.alloc(av_expr(arena, &s.class)),
2085 member: arena.alloc(av_expr(arena, &s.member)),
2086 })
2087 }
2088 ExprKind::ClassConstAccessDynamic { class, member } => {
2089 arena_ast::ExprKind::ClassConstAccessDynamic {
2090 class: arena.alloc(av_expr(arena, class)),
2091 member: arena.alloc(av_expr(arena, member)),
2092 }
2093 }
2094 ExprKind::StaticPropertyAccessDynamic { class, member } => {
2095 arena_ast::ExprKind::StaticPropertyAccessDynamic {
2096 class: arena.alloc(av_expr(arena, class)),
2097 member: arena.alloc(av_expr(arena, member)),
2098 }
2099 }
2100 ExprKind::Closure(c) => arena_ast::ExprKind::Closure(arena.alloc(arena_ast::ClosureExpr {
2101 is_static: c.is_static,
2102 by_ref: c.by_ref,
2103 params: av_params(arena, &c.params),
2104 use_vars: {
2105 let mut v = arena_ast::ArenaVec::with_capacity_in(c.use_vars.len(), arena);
2106 for uv in c.use_vars.iter() {
2107 v.push(arena_ast::ClosureUseVar {
2108 name: arena.alloc_str(&uv.name),
2109 by_ref: uv.by_ref,
2110 span: uv.span,
2111 });
2112 }
2113 v
2114 },
2115 return_type: c.return_type.as_ref().map(|t| av_type_hint(arena, t)),
2116 body: &*arena.alloc(av_block(arena, &c.body)),
2117 attributes: av_attrs(arena, &c.attributes),
2118 })),
2119 ExprKind::ArrowFunction(f) => {
2120 arena_ast::ExprKind::ArrowFunction(arena.alloc(arena_ast::ArrowFunctionExpr {
2121 is_static: f.is_static,
2122 by_ref: f.by_ref,
2123 params: av_params(arena, &f.params),
2124 return_type: f.return_type.as_ref().map(|t| av_type_hint(arena, t)),
2125 body: arena.alloc(av_expr(arena, &f.body)),
2126 attributes: av_attrs(arena, &f.attributes),
2127 }))
2128 }
2129 ExprKind::Match(m) => arena_ast::ExprKind::Match(arena_ast::MatchExpr {
2130 subject: arena.alloc(av_expr(arena, &m.subject)),
2131 arms: {
2132 let mut v = arena_ast::ArenaVec::with_capacity_in(m.arms.len(), arena);
2133 for arm in m.arms.iter() {
2134 v.push(arena_ast::MatchArm {
2135 conditions: arm.conditions.as_ref().map(|conds| av_exprs(arena, conds)),
2136 body: av_expr(arena, &arm.body),
2137 span: arm.span,
2138 });
2139 }
2140 v
2141 },
2142 brace_start: m.brace_start,
2143 }),
2144 ExprKind::ThrowExpr(e) => arena_ast::ExprKind::ThrowExpr(arena.alloc(av_expr(arena, e))),
2145 ExprKind::Yield(y) => arena_ast::ExprKind::Yield(arena_ast::YieldExpr {
2146 key: y.key.as_ref().map(|e| &*arena.alloc(av_expr(arena, e))),
2147 value: y.value.as_ref().map(|e| &*arena.alloc(av_expr(arena, e))),
2148 is_from: y.is_from,
2149 }),
2150 ExprKind::AnonymousClass(cls) => {
2151 arena_ast::ExprKind::AnonymousClass(arena.alloc(av_class_decl(arena, cls)))
2152 }
2153 ExprKind::CallableCreate(c) => {
2154 arena_ast::ExprKind::CallableCreate(arena_ast::CallableCreateExpr {
2155 kind: match &c.kind {
2156 CallableCreateKind::Function(e) => {
2157 arena_ast::CallableCreateKind::Function(arena.alloc(av_expr(arena, e)))
2158 }
2159 CallableCreateKind::Method { object, method } => {
2160 arena_ast::CallableCreateKind::Method {
2161 object: arena.alloc(av_expr(arena, object)),
2162 method: arena.alloc(av_expr(arena, method)),
2163 }
2164 }
2165 CallableCreateKind::NullsafeMethod { object, method } => {
2166 arena_ast::CallableCreateKind::NullsafeMethod {
2167 object: arena.alloc(av_expr(arena, object)),
2168 method: arena.alloc(av_expr(arena, method)),
2169 }
2170 }
2171 CallableCreateKind::StaticMethod { class, method } => {
2172 arena_ast::CallableCreateKind::StaticMethod {
2173 class: arena.alloc(av_expr(arena, class)),
2174 method: arena.alloc(av_expr(arena, method)),
2175 }
2176 }
2177 },
2178 })
2179 }
2180 ExprKind::Omit => arena_ast::ExprKind::Omit,
2181 ExprKind::Error => arena_ast::ExprKind::Error,
2182 }
2183}
2184
2185fn av_param<'a>(arena: &'a bumpalo::Bump, p: &Param) -> arena_ast::Param<'a, 'a> {
2186 arena_ast::Param {
2187 name: av_ident(arena, &p.name),
2188 type_hint: p.type_hint.as_ref().map(|t| av_type_hint(arena, t)),
2189 default: p.default.as_ref().map(|e| av_expr(arena, e)),
2190 by_ref: p.by_ref,
2191 variadic: p.variadic,
2192 is_readonly: p.is_readonly,
2193 is_final: p.is_final,
2194 visibility: p.visibility,
2195 set_visibility: p.set_visibility,
2196 attributes: av_attrs(arena, &p.attributes),
2197 hooks: av_hooks(arena, &p.hooks),
2198 span: p.span,
2199 }
2200}
2201
2202fn av_params<'a>(
2203 arena: &'a bumpalo::Bump,
2204 params: &[Param],
2205) -> arena_ast::ArenaVec<'a, arena_ast::Param<'a, 'a>> {
2206 let mut v = arena_ast::ArenaVec::with_capacity_in(params.len(), arena);
2207 for p in params.iter() {
2208 v.push(av_param(arena, p));
2209 }
2210 v
2211}
2212
2213fn av_hook<'a>(arena: &'a bumpalo::Bump, h: &PropertyHook) -> arena_ast::PropertyHook<'a, 'a> {
2214 arena_ast::PropertyHook {
2215 kind: h.kind,
2216 body: match &h.body {
2217 PropertyHookBody::Block(block) => {
2218 arena_ast::PropertyHookBody::Block(arena.alloc(av_block(arena, block)))
2219 }
2220 PropertyHookBody::Expression(e) => {
2221 arena_ast::PropertyHookBody::Expression(av_expr(arena, e))
2222 }
2223 PropertyHookBody::Abstract => arena_ast::PropertyHookBody::Abstract,
2224 },
2225 is_final: h.is_final,
2226 by_ref: h.by_ref,
2227 params: av_params(arena, &h.params),
2228 attributes: av_attrs(arena, &h.attributes),
2229 span: h.span,
2230 }
2231}
2232
2233fn av_hooks<'a>(
2234 arena: &'a bumpalo::Bump,
2235 hooks: &[PropertyHook],
2236) -> arena_ast::ArenaVec<'a, arena_ast::PropertyHook<'a, 'a>> {
2237 let mut v = arena_ast::ArenaVec::with_capacity_in(hooks.len(), arena);
2238 for h in hooks.iter() {
2239 v.push(av_hook(arena, h));
2240 }
2241 v
2242}
2243
2244fn av_stmt<'a>(arena: &'a bumpalo::Bump, stmt: &Stmt) -> arena_ast::Stmt<'a, 'a> {
2245 arena_ast::Stmt {
2246 kind: av_stmt_kind(arena, &stmt.kind),
2247 span: stmt.span,
2248 doc_comment: stmt.doc_comment.as_ref().map(|c| {
2249 &*arena.alloc(arena_ast::Comment {
2250 kind: c.kind,
2251 text: arena.alloc_str(&c.text),
2252 span: c.span,
2253 })
2254 }),
2255 }
2256}
2257
2258fn av_stmts<'a>(
2259 arena: &'a bumpalo::Bump,
2260 stmts: &[Stmt],
2261) -> arena_ast::ArenaVec<'a, arena_ast::Stmt<'a, 'a>> {
2262 let mut v = arena_ast::ArenaVec::with_capacity_in(stmts.len(), arena);
2263 for s in stmts.iter() {
2264 v.push(av_stmt(arena, s));
2265 }
2266 v
2267}
2268
2269fn av_block<'a>(arena: &'a bumpalo::Bump, block: &Block) -> arena_ast::Block<'a, 'a> {
2270 arena_ast::Block {
2271 stmts: av_stmts(arena, &block.stmts),
2272 span: block.span,
2273 }
2274}
2275
2276fn av_stmt_kind<'a>(arena: &'a bumpalo::Bump, k: &StmtKind) -> arena_ast::StmtKind<'a, 'a> {
2277 match k {
2278 StmtKind::Expression(e) => arena_ast::StmtKind::Expression(arena.alloc(av_expr(arena, e))),
2279 StmtKind::Echo(exprs) => arena_ast::StmtKind::Echo(av_exprs(arena, exprs)),
2280 StmtKind::Return(e) => {
2281 arena_ast::StmtKind::Return(e.as_ref().map(|e| &*arena.alloc(av_expr(arena, e))))
2282 }
2283 StmtKind::Block(block) => arena_ast::StmtKind::Block(arena.alloc(av_block(arena, block))),
2284 StmtKind::If(s) => arena_ast::StmtKind::If(
2285 arena.alloc(arena_ast::IfStmt {
2286 condition: av_expr(arena, &s.condition),
2287 then_branch: arena.alloc(av_stmt(arena, &s.then_branch)),
2288 elseif_branches: {
2289 let mut v =
2290 arena_ast::ArenaVec::with_capacity_in(s.elseif_branches.len(), arena);
2291 for b in s.elseif_branches.iter() {
2292 v.push(arena_ast::ElseIfBranch {
2293 condition: av_expr(arena, &b.condition),
2294 body: av_stmt(arena, &b.body),
2295 span: b.span,
2296 });
2297 }
2298 v
2299 },
2300 else_branch: s
2301 .else_branch
2302 .as_ref()
2303 .map(|b| &*arena.alloc(av_stmt(arena, b))),
2304 else_kw_start: s.else_kw_start,
2305 uses_alternative: s.uses_alternative,
2306 }),
2307 ),
2308 StmtKind::While(s) => arena_ast::StmtKind::While(arena.alloc(arena_ast::WhileStmt {
2309 condition: av_expr(arena, &s.condition),
2310 body: arena.alloc(av_stmt(arena, &s.body)),
2311 uses_alternative: s.uses_alternative,
2312 })),
2313 StmtKind::For(s) => arena_ast::StmtKind::For(arena.alloc(arena_ast::ForStmt {
2314 init: av_exprs(arena, &s.init),
2315 condition: av_exprs(arena, &s.condition),
2316 update: av_exprs(arena, &s.update),
2317 body: arena.alloc(av_stmt(arena, &s.body)),
2318 uses_alternative: s.uses_alternative,
2319 })),
2320 StmtKind::Foreach(s) => arena_ast::StmtKind::Foreach(arena.alloc(arena_ast::ForeachStmt {
2321 expr: av_expr(arena, &s.expr),
2322 key: s.key.as_ref().map(|e| av_expr(arena, e)),
2323 value: av_expr(arena, &s.value),
2324 body: arena.alloc(av_stmt(arena, &s.body)),
2325 uses_alternative: s.uses_alternative,
2326 })),
2327 StmtKind::DoWhile(s) => arena_ast::StmtKind::DoWhile(arena.alloc(arena_ast::DoWhileStmt {
2328 body: arena.alloc(av_stmt(arena, &s.body)),
2329 condition: av_expr(arena, &s.condition),
2330 })),
2331 StmtKind::Function(f) => {
2332 arena_ast::StmtKind::Function(arena.alloc(av_function_decl(arena, f)))
2333 }
2334 StmtKind::Break(e) => {
2335 arena_ast::StmtKind::Break(e.as_ref().map(|e| &*arena.alloc(av_expr(arena, e))))
2336 }
2337 StmtKind::Continue(e) => {
2338 arena_ast::StmtKind::Continue(e.as_ref().map(|e| &*arena.alloc(av_expr(arena, e))))
2339 }
2340 StmtKind::Switch(s) => arena_ast::StmtKind::Switch(arena.alloc(arena_ast::SwitchStmt {
2341 expr: av_expr(arena, &s.expr),
2342 body: {
2343 let mut cases = arena_ast::ArenaVec::with_capacity_in(s.body.cases.len(), arena);
2344 for c in s.body.cases.iter() {
2345 cases.push(arena_ast::SwitchCase {
2346 value: c.value.as_ref().map(|vl| av_expr(arena, vl)),
2347 body: av_stmts(arena, &c.body),
2348 span: c.span,
2349 });
2350 }
2351 arena_ast::SwitchBody {
2352 cases,
2353 span: s.body.span,
2354 }
2355 },
2356 uses_alternative: s.uses_alternative,
2357 })),
2358 StmtKind::Goto(ident) => arena_ast::StmtKind::Goto(av_ident(arena, ident)),
2359 StmtKind::Label(s) => arena_ast::StmtKind::Label(av_str(arena, s)),
2360 StmtKind::Declare(d) => arena_ast::StmtKind::Declare(arena.alloc(arena_ast::DeclareStmt {
2361 directives: {
2362 let mut v = arena_ast::ArenaVec::with_capacity_in(d.directives.len(), arena);
2363 for (k, val) in d.directives.iter() {
2364 v.push((arena.alloc_str(k) as &str, av_expr(arena, val)));
2365 }
2366 v
2367 },
2368 body: d.body.as_ref().map(|b| &*arena.alloc(av_stmt(arena, b))),
2369 uses_alternative: d.uses_alternative,
2370 })),
2371 StmtKind::Unset(exprs) => arena_ast::StmtKind::Unset(av_exprs(arena, exprs)),
2372 StmtKind::Throw(e) => arena_ast::StmtKind::Throw(arena.alloc(av_expr(arena, e))),
2373 StmtKind::TryCatch(t) => arena_ast::StmtKind::TryCatch(
2374 arena.alloc(arena_ast::TryCatchStmt {
2375 body: arena.alloc(av_block(arena, &t.body)),
2376 catches: {
2377 let mut v = arena_ast::ArenaVec::with_capacity_in(t.catches.len(), arena);
2378 for c in t.catches.iter() {
2379 let mut types = arena_ast::ArenaVec::with_capacity_in(c.types.len(), arena);
2380 for n in c.types.iter() {
2381 types.push(av_name(arena, n));
2382 }
2383 v.push(arena_ast::CatchClause {
2384 types,
2385 var: c.var.as_deref().map(|s| av_str(arena, s)),
2386 body: arena.alloc(av_block(arena, &c.body)),
2387 span: c.span,
2388 });
2389 }
2390 v
2391 },
2392 finally: t
2393 .finally
2394 .as_deref()
2395 .map(|f| &*arena.alloc(av_block(arena, f))),
2396 finally_kw_start: t.finally_kw_start,
2397 }),
2398 ),
2399 StmtKind::Global(exprs) => arena_ast::StmtKind::Global(av_exprs(arena, exprs)),
2400 StmtKind::Class(cls) => arena_ast::StmtKind::Class(arena.alloc(av_class_decl(arena, cls))),
2401 StmtKind::Interface(iface) => {
2402 arena_ast::StmtKind::Interface(arena.alloc(av_interface_decl(arena, iface)))
2403 }
2404 StmtKind::Trait(tr) => arena_ast::StmtKind::Trait(arena.alloc(av_trait_decl(arena, tr))),
2405 StmtKind::Enum(en) => arena_ast::StmtKind::Enum(arena.alloc(av_enum_decl(arena, en))),
2406 StmtKind::Namespace(ns) => {
2407 arena_ast::StmtKind::Namespace(arena.alloc(arena_ast::NamespaceDecl {
2408 name: ns.name.as_ref().map(|n| av_name(arena, n)),
2409 body: match &ns.body {
2410 NamespaceBody::Braced(block) => {
2411 arena_ast::NamespaceBody::Braced(&*arena.alloc(av_block(arena, block)))
2412 }
2413 NamespaceBody::Simple => arena_ast::NamespaceBody::Simple,
2414 },
2415 }))
2416 }
2417 StmtKind::Use(u) => arena_ast::StmtKind::Use(arena.alloc(arena_ast::UseDecl {
2418 kind: u.kind,
2419 uses: {
2420 let mut v = arena_ast::ArenaVec::with_capacity_in(u.uses.len(), arena);
2421 for item in u.uses.iter() {
2422 v.push(arena_ast::UseItem {
2423 name: av_name(arena, &item.name),
2424 alias: item.alias.as_deref().map(|s| av_str(arena, s)),
2425 kind: item.kind,
2426 span: item.span,
2427 });
2428 }
2429 v
2430 },
2431 })),
2432 StmtKind::Const(items) => {
2433 let mut v = arena_ast::ArenaVec::with_capacity_in(items.len(), arena);
2434 for item in items.iter() {
2435 v.push(arena_ast::ConstItem {
2436 name: av_ident(arena, &item.name),
2437 value: av_expr(arena, &item.value),
2438 attributes: av_attrs(arena, &item.attributes),
2439 span: item.span,
2440 doc_comment: av_opt_comment(arena, &item.doc_comment),
2441 });
2442 }
2443 arena_ast::StmtKind::Const(v)
2444 }
2445 StmtKind::StaticVar(vars) => {
2446 let mut v = arena_ast::ArenaVec::with_capacity_in(vars.len(), arena);
2447 for var in vars.iter() {
2448 v.push(arena_ast::StaticVar {
2449 name: av_ident(arena, &var.name),
2450 default: var.default.as_ref().map(|e| av_expr(arena, e)),
2451 span: var.span,
2452 });
2453 }
2454 arena_ast::StmtKind::StaticVar(v)
2455 }
2456 StmtKind::HaltCompiler(s) => arena_ast::StmtKind::HaltCompiler(av_str(arena, s)),
2457 StmtKind::Nop => arena_ast::StmtKind::Nop,
2458 StmtKind::InlineHtml(s) => arena_ast::StmtKind::InlineHtml(av_str(arena, s)),
2459 StmtKind::Error => arena_ast::StmtKind::Error,
2460 }
2461}
2462
2463fn av_function_decl<'a>(
2464 arena: &'a bumpalo::Bump,
2465 f: &FunctionDecl,
2466) -> arena_ast::FunctionDecl<'a, 'a> {
2467 arena_ast::FunctionDecl {
2468 name: av_ident(arena, &f.name),
2469 params: av_params(arena, &f.params),
2470 body: &*arena.alloc(av_block(arena, &f.body)),
2471 return_type: f.return_type.as_ref().map(|t| av_type_hint(arena, t)),
2472 by_ref: f.by_ref,
2473 attributes: av_attrs(arena, &f.attributes),
2474 doc_comment: av_opt_comment(arena, &f.doc_comment),
2475 }
2476}
2477
2478fn av_class_member<'a>(
2479 arena: &'a bumpalo::Bump,
2480 m: &ClassMember,
2481) -> arena_ast::ClassMember<'a, 'a> {
2482 arena_ast::ClassMember {
2483 kind: match &m.kind {
2484 ClassMemberKind::Property(p) => {
2485 arena_ast::ClassMemberKind::Property(arena_ast::PropertyDecl {
2486 name: av_ident(arena, &p.name),
2487 visibility: p.visibility,
2488 set_visibility: p.set_visibility,
2489 is_static: p.is_static,
2490 is_readonly: p.is_readonly,
2491 type_hint: p.type_hint.as_ref().map(|t| av_type_hint(arena, t)),
2492 default: p.default.as_ref().map(|e| av_expr(arena, e)),
2493 attributes: av_attrs(arena, &p.attributes),
2494 hooks: av_hooks(arena, &p.hooks),
2495 doc_comment: av_opt_comment(arena, &p.doc_comment),
2496 })
2497 }
2498 ClassMemberKind::Method(m) => {
2499 arena_ast::ClassMemberKind::Method(arena_ast::MethodDecl {
2500 name: av_ident(arena, &m.name),
2501 visibility: m.visibility,
2502 is_static: m.is_static,
2503 is_abstract: m.is_abstract,
2504 is_final: m.is_final,
2505 by_ref: m.by_ref,
2506 params: av_params(arena, &m.params),
2507 return_type: m.return_type.as_ref().map(|t| av_type_hint(arena, t)),
2508 body: m.body.as_deref().map(|b| &*arena.alloc(av_block(arena, b))),
2509 attributes: av_attrs(arena, &m.attributes),
2510 doc_comment: av_opt_comment(arena, &m.doc_comment),
2511 })
2512 }
2513 ClassMemberKind::ClassConst(c) => {
2514 arena_ast::ClassMemberKind::ClassConst(av_class_const(arena, c))
2515 }
2516 ClassMemberKind::TraitUse(t) => {
2517 arena_ast::ClassMemberKind::TraitUse(av_trait_use(arena, t))
2518 }
2519 },
2520 span: m.span,
2521 }
2522}
2523
2524fn av_class_members<'a>(
2525 arena: &'a bumpalo::Bump,
2526 members: &[ClassMember],
2527) -> arena_ast::ArenaVec<'a, arena_ast::ClassMember<'a, 'a>> {
2528 let mut v = arena_ast::ArenaVec::with_capacity_in(members.len(), arena);
2529 for m in members.iter() {
2530 v.push(av_class_member(arena, m));
2531 }
2532 v
2533}
2534
2535fn av_class_const<'a>(
2536 arena: &'a bumpalo::Bump,
2537 c: &ClassConstDecl,
2538) -> arena_ast::ClassConstDecl<'a, 'a> {
2539 arena_ast::ClassConstDecl {
2540 name: av_ident(arena, &c.name),
2541 visibility: c.visibility,
2542 is_final: c.is_final,
2543 type_hint: c
2544 .type_hint
2545 .as_ref()
2546 .map(|th| arena.alloc(av_type_hint(arena, th)) as &_),
2547 value: av_expr(arena, &c.value),
2548 attributes: av_attrs(arena, &c.attributes),
2549 doc_comment: av_opt_comment(arena, &c.doc_comment),
2550 }
2551}
2552
2553fn av_trait_use<'a>(arena: &'a bumpalo::Bump, t: &TraitUseDecl) -> arena_ast::TraitUseDecl<'a, 'a> {
2554 let mut traits = arena_ast::ArenaVec::with_capacity_in(t.traits.len(), arena);
2555 for n in t.traits.iter() {
2556 traits.push(av_name(arena, n));
2557 }
2558 let mut adaptations = arena_ast::ArenaVec::with_capacity_in(t.adaptations.len(), arena);
2559 for a in t.adaptations.iter() {
2560 adaptations.push(arena_ast::TraitAdaptation {
2561 kind: match &a.kind {
2562 TraitAdaptationKind::Precedence {
2563 trait_name,
2564 method,
2565 insteadof,
2566 } => {
2567 let mut instead = arena_ast::ArenaVec::with_capacity_in(insteadof.len(), arena);
2568 for n in insteadof.iter() {
2569 instead.push(av_name(arena, n));
2570 }
2571 arena_ast::TraitAdaptationKind::Precedence {
2572 trait_name: av_name(arena, trait_name),
2573 method: av_name(arena, method),
2574 insteadof: instead,
2575 }
2576 }
2577 TraitAdaptationKind::Alias {
2578 trait_name,
2579 method,
2580 new_modifier,
2581 new_name,
2582 } => arena_ast::TraitAdaptationKind::Alias {
2583 trait_name: trait_name.as_ref().map(|n| av_name(arena, n)),
2584 method: av_name(arena, method),
2585 new_modifier: *new_modifier,
2586 new_name: new_name.as_ref().map(|n| av_name(arena, n)),
2587 },
2588 },
2589 span: a.span,
2590 });
2591 }
2592 arena_ast::TraitUseDecl {
2593 traits,
2594 adaptations,
2595 adaptations_brace_start: t.adaptations_brace_start,
2596 }
2597}
2598
2599fn av_class_decl<'a>(arena: &'a bumpalo::Bump, cls: &ClassDecl) -> arena_ast::ClassDecl<'a, 'a> {
2600 let mut implements = arena_ast::ArenaVec::with_capacity_in(cls.implements.len(), arena);
2601 for n in cls.implements.iter() {
2602 implements.push(av_name(arena, n));
2603 }
2604 arena_ast::ClassDecl {
2605 name: cls.name.as_ref().map(|ident| av_ident(arena, ident)),
2606 modifiers: cls.modifiers.clone(),
2607 extends: cls.extends.as_ref().map(|n| av_name(arena, n)),
2608 implements,
2609 body: arena_ast::ClassBody {
2610 members: av_class_members(arena, &cls.body.members),
2611 span: cls.body.span,
2612 },
2613 attributes: av_attrs(arena, &cls.attributes),
2614 doc_comment: av_opt_comment(arena, &cls.doc_comment),
2615 }
2616}
2617
2618fn av_interface_decl<'a>(
2619 arena: &'a bumpalo::Bump,
2620 iface: &InterfaceDecl,
2621) -> arena_ast::InterfaceDecl<'a, 'a> {
2622 let mut extends = arena_ast::ArenaVec::with_capacity_in(iface.extends.len(), arena);
2623 for n in iface.extends.iter() {
2624 extends.push(av_name(arena, n));
2625 }
2626 arena_ast::InterfaceDecl {
2627 name: av_ident(arena, &iface.name),
2628 extends,
2629 body: arena_ast::ClassBody {
2630 members: av_class_members(arena, &iface.body.members),
2631 span: iface.body.span,
2632 },
2633 attributes: av_attrs(arena, &iface.attributes),
2634 doc_comment: av_opt_comment(arena, &iface.doc_comment),
2635 }
2636}
2637
2638fn av_trait_decl<'a>(arena: &'a bumpalo::Bump, tr: &TraitDecl) -> arena_ast::TraitDecl<'a, 'a> {
2639 arena_ast::TraitDecl {
2640 name: av_ident(arena, &tr.name),
2641 body: arena_ast::ClassBody {
2642 members: av_class_members(arena, &tr.body.members),
2643 span: tr.body.span,
2644 },
2645 attributes: av_attrs(arena, &tr.attributes),
2646 doc_comment: av_opt_comment(arena, &tr.doc_comment),
2647 }
2648}
2649
2650fn av_enum_decl<'a>(arena: &'a bumpalo::Bump, en: &EnumDecl) -> arena_ast::EnumDecl<'a, 'a> {
2651 let mut implements = arena_ast::ArenaVec::with_capacity_in(en.implements.len(), arena);
2652 for n in en.implements.iter() {
2653 implements.push(av_name(arena, n));
2654 }
2655 let mut members = arena_ast::ArenaVec::with_capacity_in(en.body.members.len(), arena);
2656 for m in en.body.members.iter() {
2657 members.push(arena_ast::EnumMember {
2658 kind: match &m.kind {
2659 EnumMemberKind::Case(c) => arena_ast::EnumMemberKind::Case(arena_ast::EnumCase {
2660 name: av_ident(arena, &c.name),
2661 value: c.value.as_ref().map(|e| av_expr(arena, e)),
2662 attributes: av_attrs(arena, &c.attributes),
2663 doc_comment: av_opt_comment(arena, &c.doc_comment),
2664 }),
2665 EnumMemberKind::Method(m) => {
2666 arena_ast::EnumMemberKind::Method(arena_ast::MethodDecl {
2667 name: av_ident(arena, &m.name),
2668 visibility: m.visibility,
2669 is_static: m.is_static,
2670 is_abstract: m.is_abstract,
2671 is_final: m.is_final,
2672 by_ref: m.by_ref,
2673 params: av_params(arena, &m.params),
2674 return_type: m.return_type.as_ref().map(|t| av_type_hint(arena, t)),
2675 body: m.body.as_deref().map(|b| &*arena.alloc(av_block(arena, b))),
2676 attributes: av_attrs(arena, &m.attributes),
2677 doc_comment: av_opt_comment(arena, &m.doc_comment),
2678 })
2679 }
2680 EnumMemberKind::ClassConst(c) => {
2681 arena_ast::EnumMemberKind::ClassConst(av_class_const(arena, c))
2682 }
2683 EnumMemberKind::TraitUse(t) => {
2684 arena_ast::EnumMemberKind::TraitUse(av_trait_use(arena, t))
2685 }
2686 },
2687 span: m.span,
2688 });
2689 }
2690 arena_ast::EnumDecl {
2691 name: av_ident(arena, &en.name),
2692 scalar_type: en.scalar_type.as_ref().map(|n| av_name(arena, n)),
2693 implements,
2694 body: arena_ast::EnumBody {
2695 members,
2696 span: en.body.span,
2697 },
2698 attributes: av_attrs(arena, &en.attributes),
2699 doc_comment: av_opt_comment(arena, &en.doc_comment),
2700 }
2701}