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