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