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