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