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_trait_adaptation, fold_owned_trait_use, fold_owned_type_hint,
28 FoldOwned,
29};
30pub use visitor::{
31 walk_owned_arg, walk_owned_attribute, walk_owned_catch_clause, walk_owned_class_member,
32 walk_owned_comments, walk_owned_enum_member, walk_owned_expr, walk_owned_match_arm,
33 walk_owned_name, walk_owned_param, walk_owned_program, walk_owned_property_hook,
34 walk_owned_stmt, walk_owned_trait_use, walk_owned_type_hint, OwnedScope, OwnedScopeVisitor,
35 OwnedScopeWalker, OwnedVisitor,
36};
37
38use std::fmt;
39
40use serde::Serialize;
41
42use crate::ast as arena_ast;
43use crate::ast::{
44 AssignOp, BinaryOp, BuiltinType, CastKind, ClassModifiers, CommentKind, IncludeKind,
45 MagicConstKind, NameKind, PropertyHookKind, UnaryPostfixOp, UnaryPrefixOp, UseKind, Visibility,
46};
47use crate::Span;
48
49fn is_false(b: &bool) -> bool {
54 !*b
55}
56
57fn slice_is_empty<T>(v: &[T]) -> bool {
58 v.is_empty()
59}
60
61#[derive(Clone, PartialEq, Eq, Hash, Serialize)]
63#[serde(transparent)]
64pub struct Ident(Option<Box<str>>);
65
66impl Ident {
67 pub const ERROR: Self = Self(None);
69
70 pub fn name(s: impl Into<Box<str>>) -> Self {
72 let s = s.into();
73 debug_assert!(!s.is_empty(), "Ident::name() called with empty string");
74 Self(Some(s))
75 }
76
77 pub fn as_str(&self) -> Option<&str> {
79 self.0.as_deref()
80 }
81
82 pub fn is_error(&self) -> bool {
84 self.0.is_none()
85 }
86
87 pub fn or_error(&self) -> &str {
89 self.0.as_deref().unwrap_or("<error>")
90 }
91}
92
93impl fmt::Debug for Ident {
94 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
95 match &self.0 {
96 Some(s) => f.debug_tuple("Ident").field(s).finish(),
97 None => f.write_str("Ident::ERROR"),
98 }
99 }
100}
101
102impl fmt::Display for Ident {
103 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
104 f.write_str(self.or_error())
105 }
106}
107
108impl PartialEq<&str> for Ident {
109 fn eq(&self, other: &&str) -> bool {
110 self.as_str() == Some(*other)
111 }
112}
113
114#[derive(Debug, Clone, Serialize)]
125pub struct Name {
126 pub parts: Box<[Box<str>]>,
128 pub kind: NameKind,
130 pub span: Span,
132}
133
134#[derive(Debug, Clone, Serialize)]
140pub struct Comment {
141 pub kind: CommentKind,
143 pub text: Box<str>,
145 pub span: Span,
147}
148
149#[derive(Debug, Clone, Serialize)]
158pub struct TypeHint {
159 pub kind: TypeHintKind,
161 pub span: Span,
163}
164
165#[derive(Debug, Clone)]
167#[non_exhaustive]
168pub enum TypeHintKind {
169 Named(Name),
171 Keyword(BuiltinType, Span),
173 Nullable(Box<TypeHint>),
175 Union(Box<[TypeHint]>),
177 Intersection(Box<[TypeHint]>),
179}
180
181impl Serialize for TypeHintKind {
182 fn serialize<S: serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
183 match self {
184 Self::Named(name) => s.serialize_newtype_variant("TypeHintKind", 0, "Named", name),
185 Self::Nullable(inner) => {
186 s.serialize_newtype_variant("TypeHintKind", 2, "Nullable", inner)
187 }
188 Self::Union(types) => s.serialize_newtype_variant("TypeHintKind", 3, "Union", types),
189 Self::Intersection(types) => {
190 s.serialize_newtype_variant("TypeHintKind", 4, "Intersection", types)
191 }
192 Self::Keyword(builtin, span) => {
193 struct BuiltinNameRepr<'a>(&'a BuiltinType, &'a Span);
194 impl Serialize for BuiltinNameRepr<'_> {
195 fn serialize<S: serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
196 use serde::ser::SerializeStruct;
197 let mut st = s.serialize_struct("Name", 3)?;
198 st.serialize_field("parts", &[self.0.as_str()])?;
199 st.serialize_field("kind", &NameKind::Unqualified)?;
200 st.serialize_field("span", self.1)?;
201 st.end()
202 }
203 }
204 s.serialize_newtype_variant(
205 "TypeHintKind",
206 0,
207 "Named",
208 &BuiltinNameRepr(builtin, span),
209 )
210 }
211 }
212 }
213}
214
215#[derive(Debug, Clone, Serialize)]
221pub struct Arg {
222 pub name: Option<Name>,
224 pub value: Option<Expr>,
226 pub unpack: bool,
228 pub by_ref: bool,
230 pub span: Span,
232}
233
234#[derive(Debug, Clone, Serialize)]
236pub struct Attribute {
237 pub name: Name,
239 pub args: Box<[Arg]>,
241 pub span: Span,
243}
244
245#[derive(Debug, Clone, Serialize)]
251pub struct Program {
252 pub stmts: Box<[Stmt]>,
254 pub span: Span,
256}
257
258#[derive(Debug, Clone, Serialize)]
264pub struct Stmt {
265 pub kind: StmtKind,
267 pub span: Span,
269 #[serde(skip_serializing_if = "Option::is_none")]
271 pub doc_comment: Option<Comment>,
272}
273
274impl Stmt {
275 pub fn leading_doc_comment(&self) -> Option<&Comment> {
279 if let Some(doc) = &self.doc_comment {
280 return Some(doc);
281 }
282 match &self.kind {
283 StmtKind::Function(f) => f.doc_comment.as_ref(),
284 StmtKind::Class(c) => c.doc_comment.as_ref(),
285 StmtKind::Interface(i) => i.doc_comment.as_ref(),
286 StmtKind::Trait(t) => t.doc_comment.as_ref(),
287 StmtKind::Enum(e) => e.doc_comment.as_ref(),
288 StmtKind::Const(items) => items.first().and_then(|i| i.doc_comment.as_ref()),
289 _ => None,
290 }
291 }
292}
293
294#[derive(Debug, Clone, Serialize)]
296#[serde(transparent)]
297pub struct Block {
298 pub stmts: Box<[Stmt]>,
300 #[serde(skip)]
302 pub span: Span,
303}
304
305#[derive(Debug, Clone, Serialize)]
307#[non_exhaustive]
308pub enum StmtKind {
309 Expression(Box<Expr>),
311 Echo(Box<[Expr]>),
313 Return(Option<Box<Expr>>),
315 Block(Box<Block>),
317 If(Box<IfStmt>),
319 While(Box<WhileStmt>),
321 For(Box<ForStmt>),
323 Foreach(Box<ForeachStmt>),
325 DoWhile(Box<DoWhileStmt>),
327 Function(Box<FunctionDecl>),
329 Break(Option<Box<Expr>>),
331 Continue(Option<Box<Expr>>),
333 Switch(Box<SwitchStmt>),
335 Goto(Ident),
337 Label(Ident),
339 Declare(Box<DeclareStmt>),
341 Unset(Box<[Expr]>),
343 Throw(Box<Expr>),
345 TryCatch(Box<TryCatchStmt>),
347 Global(Box<[Expr]>),
349 Class(Box<ClassDecl>),
351 Interface(Box<InterfaceDecl>),
353 Trait(Box<TraitDecl>),
355 Enum(Box<EnumDecl>),
357 Namespace(Box<NamespaceDecl>),
359 Use(Box<UseDecl>),
361 Const(Box<[ConstItem]>),
363 StaticVar(Box<[StaticVar]>),
365 HaltCompiler(Box<str>),
367 Nop,
369 InlineHtml(Box<str>),
371 Error,
373}
374
375#[derive(Debug, Clone, Serialize)]
377pub struct IfStmt {
378 pub condition: Expr,
380 pub then_branch: Box<Stmt>,
382 pub elseif_branches: Box<[ElseIfBranch]>,
384 pub else_branch: Option<Box<Stmt>>,
386 #[serde(skip)]
388 pub else_kw_span: Option<Span>,
389 #[serde(default, skip_serializing_if = "is_false")]
391 pub uses_alternative: bool,
392}
393
394#[derive(Debug, Clone, Serialize)]
396pub struct ElseIfBranch {
397 pub condition: Expr,
399 pub body: Stmt,
401 pub span: Span,
403}
404
405#[derive(Debug, Clone, Serialize)]
407pub struct WhileStmt {
408 pub condition: Expr,
410 pub body: Box<Stmt>,
412 #[serde(default, skip_serializing_if = "is_false")]
414 pub uses_alternative: bool,
415}
416
417#[derive(Debug, Clone, Serialize)]
419pub struct ForStmt {
420 pub init: Box<[Expr]>,
422 pub condition: Box<[Expr]>,
424 pub update: Box<[Expr]>,
426 pub body: Box<Stmt>,
428 #[serde(default, skip_serializing_if = "is_false")]
430 pub uses_alternative: bool,
431}
432
433#[derive(Debug, Clone, Serialize)]
435pub struct ForeachStmt {
436 pub expr: Expr,
438 pub key: Option<Expr>,
440 pub value: Expr,
442 pub body: Box<Stmt>,
444 #[serde(default, skip_serializing_if = "is_false")]
446 pub uses_alternative: bool,
447}
448
449#[derive(Debug, Clone, Serialize)]
451pub struct DoWhileStmt {
452 pub body: Box<Stmt>,
454 pub condition: Expr,
456}
457
458#[derive(Debug, Clone, Serialize)]
460pub struct SwitchBody {
461 pub cases: Box<[SwitchCase]>,
463 #[serde(skip)]
465 pub span: Span,
466}
467
468#[derive(Debug, Clone, Serialize)]
470pub struct SwitchStmt {
471 pub expr: Expr,
473 #[serde(flatten)]
475 pub body: SwitchBody,
476 #[serde(default, skip_serializing_if = "is_false")]
478 pub uses_alternative: bool,
479}
480
481#[derive(Debug, Clone, Serialize)]
483pub struct SwitchCase {
484 pub value: Option<Expr>,
486 pub body: Box<[Stmt]>,
488 pub span: Span,
490}
491
492#[derive(Debug, Clone, Serialize)]
494pub struct TryCatchStmt {
495 pub body: Box<Block>,
497 pub catches: Box<[CatchClause]>,
499 pub finally: Option<Box<Block>>,
501 #[serde(skip)]
503 pub finally_kw_span: Option<Span>,
504}
505
506#[derive(Debug, Clone, Serialize)]
508pub struct CatchClause {
509 pub types: Box<[Name]>,
511 pub var: Option<Box<str>>,
513 pub body: Box<Block>,
515 pub span: Span,
517}
518
519#[derive(Debug, Clone, Serialize)]
521pub struct NamespaceDecl {
522 pub name: Option<Name>,
524 pub body: NamespaceBody,
526}
527
528#[derive(Debug, Clone, Serialize)]
530#[non_exhaustive]
531pub enum NamespaceBody {
532 Braced(Box<Block>),
534 Simple,
536}
537
538#[derive(Debug, Clone, Serialize)]
540pub struct DeclareStmt {
541 pub directives: Box<[(Box<str>, Expr)]>,
543 pub body: Option<Box<Stmt>>,
545 #[serde(default, skip_serializing_if = "is_false")]
547 pub uses_alternative: bool,
548}
549
550#[derive(Debug, Clone, Serialize)]
552pub struct UseDecl {
553 pub kind: UseKind,
555 pub uses: Box<[UseItem]>,
557}
558
559#[derive(Debug, Clone, Serialize)]
561pub struct UseItem {
562 pub name: Name,
564 pub alias: Option<Box<str>>,
566 #[serde(skip_serializing_if = "Option::is_none")]
568 pub kind: Option<UseKind>,
569 pub span: Span,
571}
572
573#[derive(Debug, Clone, Serialize)]
575pub struct ConstItem {
576 pub name: Ident,
578 pub value: Expr,
580 pub attributes: Box<[Attribute]>,
582 pub span: Span,
584 #[serde(skip_serializing_if = "Option::is_none")]
586 pub doc_comment: Option<Comment>,
587}
588
589#[derive(Debug, Clone, Serialize)]
591pub struct StaticVar {
592 pub name: Ident,
594 pub default: Option<Expr>,
596 pub span: Span,
598}
599
600#[derive(Debug, Clone, Serialize)]
606pub struct Expr {
607 pub kind: ExprKind,
609 pub span: Span,
611}
612
613#[derive(Debug, Clone, Serialize)]
615#[non_exhaustive]
616pub enum ExprKind {
617 Int(i64),
619 Float(f64),
621 String(Box<str>),
623 InterpolatedString(Box<[StringPart]>),
625 Heredoc {
627 label: Box<str>,
629 parts: Box<[StringPart]>,
631 },
632 Nowdoc {
634 label: Box<str>,
636 value: Box<str>,
638 },
639 ShellExec(Box<[StringPart]>),
641 Bool(bool),
643 Null,
645 Variable(Box<str>),
647 VariableVariable(Box<Expr>),
649 Identifier(Box<str>),
651 Assign(AssignExpr),
653 Binary(BinaryExpr),
655 UnaryPrefix(UnaryPrefixExpr),
657 UnaryPostfix(UnaryPostfixExpr),
659 Ternary(TernaryExpr),
661 NullCoalesce(NullCoalesceExpr),
663 FunctionCall(FunctionCallExpr),
665 Array(Box<[ArrayElement]>),
667 ArrayAccess(ArrayAccessExpr),
669 Print(Box<Expr>),
671 Parenthesized(Box<Expr>),
673 Cast(CastKind, Box<Expr>),
675 ErrorSuppress(Box<Expr>),
677 Isset(Box<[Expr]>),
679 Empty(Box<Expr>),
681 Include(IncludeKind, Box<Expr>),
683 Eval(Box<Expr>),
685 Exit(Option<Box<Expr>>),
687 MagicConst(MagicConstKind),
689 Clone(Box<Expr>),
691 CloneWith(Box<Expr>, Box<Expr>),
693 New(NewExpr),
695 PropertyAccess(PropertyAccessExpr),
697 NullsafePropertyAccess(PropertyAccessExpr),
699 MethodCall(Box<MethodCallExpr>),
701 NullsafeMethodCall(Box<MethodCallExpr>),
703 StaticPropertyAccess(StaticAccessExpr),
705 StaticMethodCall(Box<StaticMethodCallExpr>),
707 StaticMethodCallDynamic(Box<StaticMethodCallDynamicExpr>),
709 ClassConstAccess(StaticAccessExpr),
711 ClassConstAccessDynamic {
713 class: Box<Expr>,
715 member: Box<Expr>,
717 },
718 StaticPropertyAccessDynamic {
720 class: Box<Expr>,
722 member: Box<Expr>,
724 },
725 Closure(Box<ClosureExpr>),
727 ArrowFunction(Box<ArrowFunctionExpr>),
729 Match(MatchExpr),
731 Throw(Box<Expr>),
733 Yield(YieldExpr),
735 AnonymousClass(Box<ClassDecl>),
737 CallableCreate(CallableCreateExpr),
739 Omit,
741 Error,
743}
744
745impl Drop for Expr {
759 #[inline(always)]
760 fn drop(&mut self) {
761 if owned_is_chain(&self.kind) {
763 unlink_chain(&mut self.kind);
764 }
765 }
766}
767
768#[inline(never)]
770fn unlink_chain(kind: &mut ExprKind) {
771 let Some(operand) = owned_chain_operand_mut(kind) else {
772 return;
773 };
774 if !owned_is_chain(&operand.kind) {
776 return;
777 }
778 let mut kind = std::mem::replace(&mut operand.kind, ExprKind::Error);
781 while let Some(operand) = owned_chain_operand_mut(&mut kind) {
782 let next = std::mem::replace(&mut operand.kind, ExprKind::Error);
783 kind = next;
784 }
785}
786
787struct LinkStack<T: Copy> {
790 inline: [Option<T>; 8],
791 len: usize,
792 spilled: Vec<T>,
793}
794
795impl<T: Copy> LinkStack<T> {
796 fn new() -> Self {
797 Self {
798 inline: [None; 8],
799 len: 0,
800 spilled: Vec::new(),
801 }
802 }
803
804 fn push(&mut self, link: T) {
805 if self.len < self.inline.len() {
806 self.inline[self.len] = Some(link);
807 self.len += 1;
808 } else {
809 self.spilled.push(link);
810 }
811 }
812
813 fn pop(&mut self) -> Option<T> {
814 if let Some(link) = self.spilled.pop() {
815 return Some(link);
816 }
817 self.len = self.len.checked_sub(1)?;
818 self.inline[self.len]
819 }
820}
821
822#[inline]
825fn arena_is_chain(k: &arena_ast::ExprKind<'_, '_>) -> bool {
826 matches!(
827 k,
828 arena_ast::ExprKind::Assign(_)
829 | arena_ast::ExprKind::Binary(_)
830 | arena_ast::ExprKind::UnaryPostfix(_)
831 | arena_ast::ExprKind::Ternary(_)
832 | arena_ast::ExprKind::NullCoalesce(_)
833 | arena_ast::ExprKind::FunctionCall(_)
834 | arena_ast::ExprKind::ArrayAccess(_)
835 | arena_ast::ExprKind::PropertyAccess(_)
836 | arena_ast::ExprKind::NullsafePropertyAccess(_)
837 | arena_ast::ExprKind::MethodCall(_)
838 | arena_ast::ExprKind::NullsafeMethodCall(_)
839 | arena_ast::ExprKind::StaticPropertyAccess(_)
840 | arena_ast::ExprKind::ClassConstAccess(_)
841 | arena_ast::ExprKind::StaticMethodCall(_)
842 | arena_ast::ExprKind::StaticMethodCallDynamic(_)
843 | arena_ast::ExprKind::ClassConstAccessDynamic { .. }
844 | arena_ast::ExprKind::StaticPropertyAccessDynamic { .. }
845 | arena_ast::ExprKind::CallableCreate(_)
846 )
847}
848
849#[inline]
851fn owned_is_chain(k: &ExprKind) -> bool {
852 matches!(
853 k,
854 ExprKind::Assign(_)
855 | ExprKind::Binary(_)
856 | ExprKind::UnaryPostfix(_)
857 | ExprKind::Ternary(_)
858 | ExprKind::NullCoalesce(_)
859 | ExprKind::FunctionCall(_)
860 | ExprKind::ArrayAccess(_)
861 | ExprKind::PropertyAccess(_)
862 | ExprKind::NullsafePropertyAccess(_)
863 | ExprKind::MethodCall(_)
864 | ExprKind::NullsafeMethodCall(_)
865 | ExprKind::StaticPropertyAccess(_)
866 | ExprKind::ClassConstAccess(_)
867 | ExprKind::StaticMethodCall(_)
868 | ExprKind::StaticMethodCallDynamic(_)
869 | ExprKind::ClassConstAccessDynamic { .. }
870 | ExprKind::StaticPropertyAccessDynamic { .. }
871 | ExprKind::CallableCreate(_)
872 )
873}
874
875#[inline]
876fn arena_chain_operand<'a, 'arena, 'src>(
877 k: &'a arena_ast::ExprKind<'arena, 'src>,
878) -> Option<&'a arena_ast::Expr<'arena, 'src>> {
879 use arena_ast::{CallableCreateKind as C, ExprKind as K};
880 match k {
881 K::Assign(a) => Some(a.target),
882 K::Binary(b) => Some(b.left),
883 K::UnaryPostfix(u) => Some(u.operand),
884 K::Ternary(t) => Some(t.condition),
885 K::NullCoalesce(n) => Some(n.left),
886 K::FunctionCall(f) => Some(f.name),
887 K::ArrayAccess(a) => Some(a.array),
888 K::PropertyAccess(p) | K::NullsafePropertyAccess(p) => Some(p.object),
889 K::MethodCall(m) | K::NullsafeMethodCall(m) => Some(m.object),
890 K::StaticPropertyAccess(s) | K::ClassConstAccess(s) => Some(s.class),
891 K::StaticMethodCall(s) => Some(s.class),
892 K::StaticMethodCallDynamic(s) => Some(s.class),
893 K::ClassConstAccessDynamic { class, .. } | K::StaticPropertyAccessDynamic { class, .. } => {
894 Some(class)
895 }
896 K::CallableCreate(c) => Some(match &c.kind {
897 C::Function(e) => e,
898 C::Method { object, .. } | C::NullsafeMethod { object, .. } => object,
899 C::StaticMethod { class, .. } => class,
900 }),
901 _ => None,
902 }
903}
904
905#[inline]
906fn owned_chain_operand(k: &ExprKind) -> Option<&Expr> {
907 use CallableCreateKind as C;
908 match k {
909 ExprKind::Assign(a) => Some(&a.target),
910 ExprKind::Binary(b) => Some(&b.left),
911 ExprKind::UnaryPostfix(u) => Some(&u.operand),
912 ExprKind::Ternary(t) => Some(&t.condition),
913 ExprKind::NullCoalesce(n) => Some(&n.left),
914 ExprKind::FunctionCall(f) => Some(&f.name),
915 ExprKind::ArrayAccess(a) => Some(&a.array),
916 ExprKind::PropertyAccess(p) | ExprKind::NullsafePropertyAccess(p) => Some(&p.object),
917 ExprKind::MethodCall(m) | ExprKind::NullsafeMethodCall(m) => Some(&m.object),
918 ExprKind::StaticPropertyAccess(s) | ExprKind::ClassConstAccess(s) => Some(&s.class),
919 ExprKind::StaticMethodCall(s) => Some(&s.class),
920 ExprKind::StaticMethodCallDynamic(s) => Some(&s.class),
921 ExprKind::ClassConstAccessDynamic { class, .. }
922 | ExprKind::StaticPropertyAccessDynamic { class, .. } => Some(class),
923 ExprKind::CallableCreate(c) => Some(match &c.kind {
924 C::Function(e) => e,
925 C::Method { object, .. } | C::NullsafeMethod { object, .. } => object,
926 C::StaticMethod { class, .. } => class,
927 }),
928 _ => None,
929 }
930}
931
932#[inline]
933fn owned_chain_operand_mut(k: &mut ExprKind) -> Option<&mut Expr> {
934 use CallableCreateKind as C;
935 match k {
936 ExprKind::Assign(a) => Some(&mut a.target),
937 ExprKind::Binary(b) => Some(&mut b.left),
938 ExprKind::UnaryPostfix(u) => Some(&mut u.operand),
939 ExprKind::Ternary(t) => Some(&mut t.condition),
940 ExprKind::NullCoalesce(n) => Some(&mut n.left),
941 ExprKind::FunctionCall(f) => Some(&mut f.name),
942 ExprKind::ArrayAccess(a) => Some(&mut a.array),
943 ExprKind::PropertyAccess(p) | ExprKind::NullsafePropertyAccess(p) => Some(&mut p.object),
944 ExprKind::MethodCall(m) | ExprKind::NullsafeMethodCall(m) => Some(&mut m.object),
945 ExprKind::StaticPropertyAccess(s) | ExprKind::ClassConstAccess(s) => Some(&mut s.class),
946 ExprKind::StaticMethodCall(s) => Some(&mut s.class),
947 ExprKind::StaticMethodCallDynamic(s) => Some(&mut s.class),
948 ExprKind::ClassConstAccessDynamic { class, .. }
949 | ExprKind::StaticPropertyAccessDynamic { class, .. } => Some(class),
950 ExprKind::CallableCreate(c) => Some(match &mut c.kind {
951 C::Function(e) => e,
952 C::Method { object, .. } | C::NullsafeMethod { object, .. } => object,
953 C::StaticMethod { class, .. } => class,
954 }),
955 _ => None,
956 }
957}
958
959#[derive(Debug, Clone, Serialize)]
961pub struct AssignExpr {
962 pub target: Box<Expr>,
964 pub op: AssignOp,
966 pub value: Box<Expr>,
968 #[serde(skip_serializing_if = "is_false")]
970 pub by_ref: bool,
971}
972
973#[derive(Debug, Clone, Serialize)]
975pub struct BinaryExpr {
976 pub left: Box<Expr>,
978 pub op: BinaryOp,
980 pub right: Box<Expr>,
982}
983
984#[derive(Debug, Clone, Serialize)]
986pub struct UnaryPrefixExpr {
987 pub op: UnaryPrefixOp,
989 pub operand: Box<Expr>,
991}
992
993#[derive(Debug, Clone, Serialize)]
995pub struct UnaryPostfixExpr {
996 pub operand: Box<Expr>,
998 pub op: UnaryPostfixOp,
1000}
1001
1002#[derive(Debug, Clone, Serialize)]
1004pub struct TernaryExpr {
1005 pub condition: Box<Expr>,
1007 pub then_expr: Option<Box<Expr>>,
1009 pub else_expr: Box<Expr>,
1011}
1012
1013#[derive(Debug, Clone, Serialize)]
1015pub struct NullCoalesceExpr {
1016 pub left: Box<Expr>,
1018 pub right: Box<Expr>,
1020}
1021
1022#[derive(Debug, Clone, Serialize)]
1024pub struct FunctionCallExpr {
1025 pub name: Box<Expr>,
1027 pub args: Box<[Arg]>,
1029}
1030
1031#[derive(Debug, Clone, Serialize)]
1033pub struct ArrayElement {
1034 pub key: Option<Expr>,
1036 pub value: Expr,
1038 pub unpack: bool,
1040 #[serde(skip_serializing_if = "is_false")]
1042 pub by_ref: bool,
1043 pub span: Span,
1045}
1046
1047#[derive(Debug, Clone, Serialize)]
1049pub struct ArrayAccessExpr {
1050 pub array: Box<Expr>,
1052 pub index: Option<Box<Expr>>,
1054}
1055
1056#[derive(Debug, Clone, Serialize)]
1058pub struct NewExpr {
1059 pub class: Box<Expr>,
1061 pub args: Box<[Arg]>,
1063}
1064
1065#[derive(Debug, Clone, Serialize)]
1067pub struct PropertyAccessExpr {
1068 pub object: Box<Expr>,
1070 pub property: Box<Expr>,
1072}
1073
1074#[derive(Debug, Clone, Serialize)]
1076pub struct MethodCallExpr {
1077 pub object: Box<Expr>,
1079 pub method: Box<Expr>,
1081 pub args: Box<[Arg]>,
1083}
1084
1085#[derive(Debug, Clone, Serialize)]
1087pub struct StaticAccessExpr {
1088 pub class: Box<Expr>,
1090 pub member: Box<Expr>,
1092}
1093
1094#[derive(Debug, Clone, Serialize)]
1096pub struct StaticMethodCallExpr {
1097 pub class: Box<Expr>,
1099 pub method: Box<Expr>,
1101 pub args: Box<[Arg]>,
1103}
1104
1105#[derive(Debug, Clone, Serialize)]
1107pub struct StaticMethodCallDynamicExpr {
1108 pub class: Box<Expr>,
1110 pub method: Box<Expr>,
1112 pub args: Box<[Arg]>,
1114}
1115
1116#[derive(Debug, Clone, Serialize)]
1118pub struct ClosureExpr {
1119 pub is_static: bool,
1121 pub by_ref: bool,
1123 pub params: Box<[Param]>,
1125 pub use_vars: Box<[ClosureUseVar]>,
1127 pub return_type: Option<TypeHint>,
1129 pub body: Box<Block>,
1131 pub attributes: Box<[Attribute]>,
1133}
1134
1135#[derive(Debug, Clone, Serialize)]
1137pub struct ClosureUseVar {
1138 pub name: Box<str>,
1140 pub by_ref: bool,
1142 pub span: Span,
1144}
1145
1146#[derive(Debug, Clone, Serialize)]
1148pub struct ArrowFunctionExpr {
1149 pub is_static: bool,
1151 pub by_ref: bool,
1153 pub params: Box<[Param]>,
1155 pub return_type: Option<TypeHint>,
1157 pub body: Box<Expr>,
1159 pub attributes: Box<[Attribute]>,
1161}
1162
1163#[derive(Debug, Clone, Serialize)]
1165pub struct MatchExpr {
1166 pub subject: Box<Expr>,
1168 pub arms: Box<[MatchArm]>,
1170 #[serde(skip)]
1172 pub brace_span: Span,
1173}
1174
1175#[derive(Debug, Clone, Serialize)]
1177pub struct MatchArm {
1178 pub conditions: Option<Box<[Expr]>>,
1180 pub body: Expr,
1182 pub span: Span,
1184}
1185
1186#[derive(Debug, Clone, Serialize)]
1188pub struct YieldExpr {
1189 pub key: Option<Box<Expr>>,
1191 pub value: Option<Box<Expr>>,
1193 pub is_from: bool,
1195}
1196
1197#[derive(Debug, Clone, Serialize)]
1199pub struct CallableCreateExpr {
1200 pub kind: CallableCreateKind,
1202}
1203
1204#[derive(Debug, Clone, Serialize)]
1206#[non_exhaustive]
1207pub enum CallableCreateKind {
1208 Function(Box<Expr>),
1210 Method {
1212 object: Box<Expr>,
1214 method: Box<Expr>,
1216 },
1217 NullsafeMethod {
1219 object: Box<Expr>,
1221 method: Box<Expr>,
1223 },
1224 StaticMethod {
1226 class: Box<Expr>,
1228 method: Box<Expr>,
1230 },
1231}
1232
1233#[derive(Debug, Clone, Serialize)]
1235#[non_exhaustive]
1236pub enum StringPart {
1237 Literal(Box<str>),
1239 Expr(Expr),
1241}
1242
1243#[derive(Debug, Clone, Serialize)]
1249pub struct FunctionDecl {
1250 pub name: Ident,
1252 pub params: Box<[Param]>,
1254 pub body: Box<Block>,
1256 pub return_type: Option<TypeHint>,
1258 pub by_ref: bool,
1260 pub attributes: Box<[Attribute]>,
1262 #[serde(skip_serializing_if = "Option::is_none")]
1264 pub doc_comment: Option<Comment>,
1265}
1266
1267#[derive(Debug, Clone, Serialize)]
1269#[non_exhaustive]
1270pub struct Param {
1271 pub name: Ident,
1273 pub type_hint: Option<TypeHint>,
1275 pub default: Option<Expr>,
1277 pub by_ref: bool,
1279 pub variadic: bool,
1281 pub is_readonly: bool,
1283 pub is_final: bool,
1285 pub visibility: Option<Visibility>,
1287 pub set_visibility: Option<Visibility>,
1289 pub attributes: Box<[Attribute]>,
1291 #[serde(skip_serializing_if = "slice_is_empty")]
1293 pub hooks: Box<[PropertyHook]>,
1294 #[serde(skip_serializing_if = "Option::is_none")]
1296 pub doc_comment: Option<Comment>,
1297 pub span: Span,
1299}
1300
1301impl Param {
1302 pub fn new(name: Ident, span: Span) -> Self {
1307 Self {
1308 name,
1309 type_hint: None,
1310 default: None,
1311 by_ref: false,
1312 variadic: false,
1313 is_readonly: false,
1314 is_final: false,
1315 visibility: None,
1316 set_visibility: None,
1317 attributes: Box::new([]),
1318 hooks: Box::new([]),
1319 doc_comment: None,
1320 span,
1321 }
1322 }
1323}
1324
1325#[derive(Debug, Clone, Serialize)]
1327pub struct ClassBody {
1328 pub members: Box<[ClassMember]>,
1330 #[serde(skip)]
1332 pub span: Span,
1333}
1334
1335#[derive(Debug, Clone, Serialize)]
1337pub struct ClassDecl {
1338 pub name: Option<Ident>,
1340 pub modifiers: ClassModifiers,
1342 pub extends: Option<Name>,
1344 pub implements: Box<[Name]>,
1346 #[serde(flatten)]
1348 pub body: ClassBody,
1349 pub attributes: Box<[Attribute]>,
1351 #[serde(skip_serializing_if = "Option::is_none")]
1353 pub doc_comment: Option<Comment>,
1354}
1355
1356#[derive(Debug, Clone, Serialize)]
1358pub struct ClassMember {
1359 pub kind: ClassMemberKind,
1361 pub span: Span,
1363}
1364
1365#[derive(Debug, Clone, Serialize)]
1367#[non_exhaustive]
1368pub enum ClassMemberKind {
1369 Property(PropertyDecl),
1371 Method(MethodDecl),
1373 ClassConst(ClassConstDecl),
1375 TraitUse(TraitUseDecl),
1377}
1378
1379#[derive(Debug, Clone, Serialize)]
1381pub struct PropertyDecl {
1382 pub name: Ident,
1384 pub visibility: Option<Visibility>,
1386 pub set_visibility: Option<Visibility>,
1388 pub is_static: bool,
1390 pub is_readonly: bool,
1392 pub type_hint: Option<TypeHint>,
1394 pub default: Option<Expr>,
1396 pub attributes: Box<[Attribute]>,
1398 #[serde(skip_serializing_if = "slice_is_empty")]
1400 pub hooks: Box<[PropertyHook]>,
1401 #[serde(skip_serializing_if = "Option::is_none")]
1403 pub doc_comment: Option<Comment>,
1404}
1405
1406#[derive(Debug, Clone, Serialize)]
1408pub struct PropertyHook {
1409 pub kind: PropertyHookKind,
1411 pub body: PropertyHookBody,
1413 pub is_final: bool,
1415 pub by_ref: bool,
1417 pub params: Box<[Param]>,
1419 pub attributes: Box<[Attribute]>,
1421 pub span: Span,
1423}
1424
1425#[derive(Debug, Clone, Serialize)]
1427#[non_exhaustive]
1428pub enum PropertyHookBody {
1429 Block(Box<Block>),
1431 Expression(Expr),
1433 Abstract,
1435}
1436
1437#[derive(Debug, Clone, Serialize)]
1439#[non_exhaustive]
1440pub struct MethodDecl {
1441 pub name: Ident,
1443 pub visibility: Option<Visibility>,
1445 pub is_static: bool,
1447 pub is_abstract: bool,
1449 pub is_final: bool,
1451 pub by_ref: bool,
1453 pub params: Box<[Param]>,
1455 pub return_type: Option<TypeHint>,
1457 pub body: Option<Box<Block>>,
1459 pub attributes: Box<[Attribute]>,
1461 #[serde(skip_serializing_if = "Option::is_none")]
1463 pub doc_comment: Option<Comment>,
1464}
1465
1466impl MethodDecl {
1467 pub fn new(name: Ident) -> Self {
1470 Self {
1471 name,
1472 visibility: None,
1473 is_static: false,
1474 is_abstract: false,
1475 is_final: false,
1476 by_ref: false,
1477 params: Box::new([]),
1478 return_type: None,
1479 body: None,
1480 attributes: Box::new([]),
1481 doc_comment: None,
1482 }
1483 }
1484}
1485
1486#[derive(Debug, Clone, Serialize)]
1488pub struct ClassConstDecl {
1489 pub name: Ident,
1491 pub visibility: Option<Visibility>,
1493 pub is_final: bool,
1495 #[serde(skip_serializing_if = "Option::is_none")]
1497 pub type_hint: Option<Box<TypeHint>>,
1498 pub value: Expr,
1500 pub attributes: Box<[Attribute]>,
1502 #[serde(skip_serializing_if = "Option::is_none")]
1504 pub doc_comment: Option<Comment>,
1505}
1506
1507#[derive(Debug, Clone, Serialize)]
1509pub struct TraitUseDecl {
1510 pub traits: Box<[Name]>,
1512 pub adaptations: Box<[TraitAdaptation]>,
1514 #[serde(skip)]
1516 pub adaptations_brace_span: Option<Span>,
1517 #[serde(skip_serializing_if = "Option::is_none")]
1519 pub doc_comment: Option<Comment>,
1520}
1521
1522#[derive(Debug, Clone, Serialize)]
1524pub struct TraitAdaptation {
1525 pub kind: TraitAdaptationKind,
1527 pub span: Span,
1529}
1530
1531#[derive(Debug, Clone, Serialize)]
1533#[non_exhaustive]
1534pub enum TraitAdaptationKind {
1535 Precedence {
1537 trait_name: Name,
1539 method: Name,
1541 insteadof: Box<[Name]>,
1543 },
1544 Alias {
1546 trait_name: Option<Name>,
1548 method: Name,
1550 new_modifier: Option<Visibility>,
1552 new_name: Option<Name>,
1554 },
1555}
1556
1557#[derive(Debug, Clone, Serialize)]
1559pub struct InterfaceDecl {
1560 pub name: Ident,
1562 pub extends: Box<[Name]>,
1564 #[serde(flatten)]
1566 pub body: ClassBody,
1567 pub attributes: Box<[Attribute]>,
1569 #[serde(skip_serializing_if = "Option::is_none")]
1571 pub doc_comment: Option<Comment>,
1572}
1573
1574#[derive(Debug, Clone, Serialize)]
1576pub struct TraitDecl {
1577 pub name: Ident,
1579 #[serde(flatten)]
1581 pub body: ClassBody,
1582 pub attributes: Box<[Attribute]>,
1584 #[serde(skip_serializing_if = "Option::is_none")]
1586 pub doc_comment: Option<Comment>,
1587}
1588
1589#[derive(Debug, Clone, Serialize)]
1591pub struct EnumBody {
1592 pub members: Box<[EnumMember]>,
1594 #[serde(skip)]
1596 pub span: Span,
1597}
1598
1599#[derive(Debug, Clone, Serialize)]
1601pub struct EnumDecl {
1602 pub name: Ident,
1604 pub scalar_type: Option<Name>,
1606 pub implements: Box<[Name]>,
1608 #[serde(flatten)]
1610 pub body: EnumBody,
1611 pub attributes: Box<[Attribute]>,
1613 #[serde(skip_serializing_if = "Option::is_none")]
1615 pub doc_comment: Option<Comment>,
1616}
1617
1618#[derive(Debug, Clone, Serialize)]
1620pub struct EnumMember {
1621 pub kind: EnumMemberKind,
1623 pub span: Span,
1625}
1626
1627#[derive(Debug, Clone, Serialize)]
1629#[non_exhaustive]
1630pub enum EnumMemberKind {
1631 Case(EnumCase),
1633 Method(MethodDecl),
1635 ClassConst(ClassConstDecl),
1637 TraitUse(TraitUseDecl),
1639}
1640
1641#[derive(Debug, Clone, Serialize)]
1643pub struct EnumCase {
1644 pub name: Ident,
1646 pub value: Option<Expr>,
1648 pub attributes: Box<[Attribute]>,
1650 #[serde(skip_serializing_if = "Option::is_none")]
1652 pub doc_comment: Option<Comment>,
1653}
1654
1655fn owned_ident(ident: arena_ast::Ident<'_>) -> Ident {
1660 ident.as_str().map_or(Ident::ERROR, Ident::name)
1661}
1662
1663fn owned_name(name: &arena_ast::Name<'_, '_>) -> Name {
1664 match name {
1665 arena_ast::Name::Simple { value, span } => Name {
1666 parts: vec![Box::from(*value)].into_boxed_slice(),
1667 kind: NameKind::Unqualified,
1668 span: *span,
1669 },
1670 arena_ast::Name::Complex { parts, kind, span } => Name {
1671 parts: parts
1672 .iter()
1673 .map(|s| Box::from(*s))
1674 .collect::<Vec<_>>()
1675 .into_boxed_slice(),
1676 kind: *kind,
1677 span: *span,
1678 },
1679 arena_ast::Name::Error { span } => Name {
1680 parts: Box::from([]),
1681 kind: NameKind::Error,
1682 span: *span,
1683 },
1684 }
1685}
1686
1687fn owned_comment(c: &arena_ast::Comment<'_>) -> Comment {
1688 Comment {
1689 kind: c.kind,
1690 text: c.text.into(),
1691 span: c.span,
1692 }
1693}
1694
1695fn owned_opt_comment(c: &Option<arena_ast::Comment<'_>>) -> Option<Comment> {
1696 c.as_ref().map(owned_comment)
1697}
1698
1699fn owned_type_hint(th: &arena_ast::TypeHint<'_, '_>) -> TypeHint {
1700 TypeHint {
1701 kind: owned_type_hint_kind(&th.kind),
1702 span: th.span,
1703 }
1704}
1705
1706fn owned_type_hint_kind(k: &arena_ast::TypeHintKind<'_, '_>) -> TypeHintKind {
1707 match k {
1708 arena_ast::TypeHintKind::Named(n) => TypeHintKind::Named(owned_name(n)),
1709 arena_ast::TypeHintKind::Keyword(b, span) => TypeHintKind::Keyword(*b, *span),
1710 arena_ast::TypeHintKind::Nullable(inner) => {
1711 TypeHintKind::Nullable(Box::new(owned_type_hint(inner)))
1712 }
1713 arena_ast::TypeHintKind::Union(types) => TypeHintKind::Union(
1714 types
1715 .iter()
1716 .map(owned_type_hint)
1717 .collect::<Vec<_>>()
1718 .into_boxed_slice(),
1719 ),
1720 arena_ast::TypeHintKind::Intersection(types) => TypeHintKind::Intersection(
1721 types
1722 .iter()
1723 .map(owned_type_hint)
1724 .collect::<Vec<_>>()
1725 .into_boxed_slice(),
1726 ),
1727 }
1728}
1729
1730fn owned_arg(arg: &arena_ast::Arg<'_, '_>) -> Arg {
1731 Arg {
1732 name: arg.name.as_ref().map(owned_name),
1733 value: arg.value.as_ref().map(owned_expr),
1734 unpack: arg.unpack,
1735 by_ref: arg.by_ref,
1736 span: arg.span,
1737 }
1738}
1739
1740#[inline(never)]
1741fn owned_args(args: &[arena_ast::Arg<'_, '_>]) -> Box<[Arg]> {
1742 args.iter()
1743 .map(owned_arg)
1744 .collect::<Vec<_>>()
1745 .into_boxed_slice()
1746}
1747
1748fn owned_attr(attr: &arena_ast::Attribute<'_, '_>) -> Attribute {
1749 Attribute {
1750 name: owned_name(&attr.name),
1751 args: owned_args(&attr.args),
1752 span: attr.span,
1753 }
1754}
1755
1756fn owned_attrs(attrs: &[arena_ast::Attribute<'_, '_>]) -> Box<[Attribute]> {
1757 attrs
1758 .iter()
1759 .map(owned_attr)
1760 .collect::<Vec<_>>()
1761 .into_boxed_slice()
1762}
1763
1764#[inline(never)]
1765fn owned_string_parts(parts: &[arena_ast::StringPart<'_, '_>]) -> Box<[StringPart]> {
1766 parts
1767 .iter()
1768 .map(|p| match p {
1769 arena_ast::StringPart::Literal(s) => StringPart::Literal(Box::from(*s)),
1770 arena_ast::StringPart::Expr(e) => StringPart::Expr(owned_expr(e)),
1771 })
1772 .collect::<Vec<_>>()
1773 .into_boxed_slice()
1774}
1775
1776pub fn to_owned_expr(expr: &arena_ast::Expr<'_, '_>) -> Expr {
1778 owned_expr(expr)
1779}
1780
1781pub fn to_owned_name(name: &arena_ast::Name<'_, '_>) -> Name {
1783 owned_name(name)
1784}
1785
1786pub fn to_owned_type_hint(hint: &arena_ast::TypeHint<'_, '_>) -> TypeHint {
1788 owned_type_hint(hint)
1789}
1790
1791#[inline]
1792fn owned_expr(expr: &arena_ast::Expr<'_, '_>) -> Expr {
1793 if !arena_is_chain(&expr.kind) {
1794 return Expr {
1795 kind: owned_leaf_kind(&expr.kind),
1796 span: expr.span,
1797 };
1798 }
1799 owned_chain_expr(expr)
1800}
1801
1802#[inline(never)]
1805fn owned_chain_expr(expr: &arena_ast::Expr<'_, '_>) -> Expr {
1806 let first = arena_chain_operand(&expr.kind).expect("chain link has an operand");
1807 if !arena_is_chain(&first.kind) {
1808 let operand = Expr {
1810 kind: owned_leaf_kind(&first.kind),
1811 span: first.span,
1812 };
1813 return Expr {
1814 kind: owned_link_kind(&expr.kind, operand),
1815 span: expr.span,
1816 };
1817 }
1818 let mut chain = LinkStack::new();
1819 chain.push(expr);
1820 let mut leaf = first;
1821 while let Some(operand) = arena_chain_operand(&leaf.kind) {
1822 chain.push(leaf);
1823 leaf = operand;
1824 }
1825 let mut converted = Expr {
1826 kind: owned_leaf_kind(&leaf.kind),
1827 span: leaf.span,
1828 };
1829 while let Some(node) = chain.pop() {
1830 converted = Expr {
1831 kind: owned_link_kind(&node.kind, converted),
1832 span: node.span,
1833 };
1834 }
1835 converted
1836}
1837
1838#[inline(never)]
1839fn owned_exprs(exprs: &[arena_ast::Expr<'_, '_>]) -> Box<[Expr]> {
1840 exprs
1841 .iter()
1842 .map(owned_expr)
1843 .collect::<Vec<_>>()
1844 .into_boxed_slice()
1845}
1846
1847fn owned_leaf_kind(k: &arena_ast::ExprKind<'_, '_>) -> ExprKind {
1849 match k {
1850 arena_ast::ExprKind::Int(v) => ExprKind::Int(*v),
1851 arena_ast::ExprKind::Float(v) => ExprKind::Float(*v),
1852 arena_ast::ExprKind::String(s) => ExprKind::String(Box::from(s.as_str())),
1853 arena_ast::ExprKind::InterpolatedString(parts) => {
1854 ExprKind::InterpolatedString(owned_string_parts(parts))
1855 }
1856 arena_ast::ExprKind::Heredoc { label, parts } => ExprKind::Heredoc {
1857 label: Box::from(*label),
1858 parts: owned_string_parts(parts),
1859 },
1860 arena_ast::ExprKind::Nowdoc { label, value } => ExprKind::Nowdoc {
1861 label: Box::from(*label),
1862 value: Box::from(*value),
1863 },
1864 arena_ast::ExprKind::ShellExec(parts) => ExprKind::ShellExec(owned_string_parts(parts)),
1865 arena_ast::ExprKind::Bool(v) => ExprKind::Bool(*v),
1866 arena_ast::ExprKind::Null => ExprKind::Null,
1867 arena_ast::ExprKind::Variable(s) => ExprKind::Variable(s.as_str().into()),
1868 arena_ast::ExprKind::VariableVariable(inner) => {
1869 ExprKind::VariableVariable(Box::new(owned_expr(inner)))
1870 }
1871 arena_ast::ExprKind::Identifier(s) => ExprKind::Identifier(s.as_str().into()),
1872 arena_ast::ExprKind::UnaryPrefix(u) => ExprKind::UnaryPrefix(UnaryPrefixExpr {
1873 op: u.op,
1874 operand: Box::new(owned_expr(u.operand)),
1875 }),
1876 arena_ast::ExprKind::Array(elems) => ExprKind::Array(
1877 elems
1878 .iter()
1879 .map(|e| ArrayElement {
1880 key: e.key.as_ref().map(owned_expr),
1881 value: owned_expr(&e.value),
1882 unpack: e.unpack,
1883 by_ref: e.by_ref,
1884 span: e.span,
1885 })
1886 .collect::<Vec<_>>()
1887 .into_boxed_slice(),
1888 ),
1889 arena_ast::ExprKind::Print(e) => ExprKind::Print(Box::new(owned_expr(e))),
1890 arena_ast::ExprKind::Parenthesized(e) => ExprKind::Parenthesized(Box::new(owned_expr(e))),
1891 arena_ast::ExprKind::Cast(kind, e) => ExprKind::Cast(*kind, Box::new(owned_expr(e))),
1892 arena_ast::ExprKind::ErrorSuppress(e) => ExprKind::ErrorSuppress(Box::new(owned_expr(e))),
1893 arena_ast::ExprKind::Isset(exprs) => ExprKind::Isset(owned_exprs(exprs)),
1894 arena_ast::ExprKind::Empty(e) => ExprKind::Empty(Box::new(owned_expr(e))),
1895 arena_ast::ExprKind::Include(kind, e) => ExprKind::Include(*kind, Box::new(owned_expr(e))),
1896 arena_ast::ExprKind::Eval(e) => ExprKind::Eval(Box::new(owned_expr(e))),
1897 arena_ast::ExprKind::Exit(e) => ExprKind::Exit(e.map(|e| Box::new(owned_expr(e)))),
1898 arena_ast::ExprKind::MagicConst(m) => ExprKind::MagicConst(*m),
1899 arena_ast::ExprKind::Clone(e) => ExprKind::Clone(Box::new(owned_expr(e))),
1900 arena_ast::ExprKind::CloneWith(obj, props) => {
1901 ExprKind::CloneWith(Box::new(owned_expr(obj)), Box::new(owned_expr(props)))
1902 }
1903 arena_ast::ExprKind::New(n) => ExprKind::New(NewExpr {
1904 class: Box::new(owned_expr(n.class)),
1905 args: owned_args(&n.args),
1906 }),
1907 arena_ast::ExprKind::Closure(c) => ExprKind::Closure(Box::new(ClosureExpr {
1908 is_static: c.is_static,
1909 by_ref: c.by_ref,
1910 params: owned_params(&c.params),
1911 use_vars: c
1912 .use_vars
1913 .iter()
1914 .map(|v| ClosureUseVar {
1915 name: v.name.into(),
1916 by_ref: v.by_ref,
1917 span: v.span,
1918 })
1919 .collect::<Vec<_>>()
1920 .into_boxed_slice(),
1921 return_type: c.return_type.as_ref().map(owned_type_hint),
1922 body: Box::new(owned_block(c.body)),
1923 attributes: owned_attrs(&c.attributes),
1924 })),
1925 arena_ast::ExprKind::ArrowFunction(f) => {
1926 ExprKind::ArrowFunction(Box::new(ArrowFunctionExpr {
1927 is_static: f.is_static,
1928 by_ref: f.by_ref,
1929 params: owned_params(&f.params),
1930 return_type: f.return_type.as_ref().map(owned_type_hint),
1931 body: Box::new(owned_expr(f.body)),
1932 attributes: owned_attrs(&f.attributes),
1933 }))
1934 }
1935 arena_ast::ExprKind::Match(m) => ExprKind::Match(MatchExpr {
1936 subject: Box::new(owned_expr(m.subject)),
1937 arms: m
1938 .arms
1939 .iter()
1940 .map(|arm| MatchArm {
1941 conditions: arm.conditions.as_ref().map(|conds| owned_exprs(conds)),
1942 body: owned_expr(&arm.body),
1943 span: arm.span,
1944 })
1945 .collect::<Vec<_>>()
1946 .into_boxed_slice(),
1947 brace_span: m.brace_span,
1948 }),
1949 arena_ast::ExprKind::Throw(e) => ExprKind::Throw(Box::new(owned_expr(e))),
1950 arena_ast::ExprKind::Yield(y) => ExprKind::Yield(YieldExpr {
1951 key: y.key.map(|e| Box::new(owned_expr(e))),
1952 value: y.value.map(|e| Box::new(owned_expr(e))),
1953 is_from: y.is_from,
1954 }),
1955 arena_ast::ExprKind::AnonymousClass(cls) => {
1956 ExprKind::AnonymousClass(Box::new(owned_class_decl(cls)))
1957 }
1958 arena_ast::ExprKind::Omit => ExprKind::Omit,
1959 arena_ast::ExprKind::Error => ExprKind::Error,
1960 arena_ast::ExprKind::Assign(_)
1961 | arena_ast::ExprKind::Binary(_)
1962 | arena_ast::ExprKind::UnaryPostfix(_)
1963 | arena_ast::ExprKind::Ternary(_)
1964 | arena_ast::ExprKind::NullCoalesce(_)
1965 | arena_ast::ExprKind::FunctionCall(_)
1966 | arena_ast::ExprKind::ArrayAccess(_)
1967 | arena_ast::ExprKind::PropertyAccess(_)
1968 | arena_ast::ExprKind::NullsafePropertyAccess(_)
1969 | arena_ast::ExprKind::MethodCall(_)
1970 | arena_ast::ExprKind::NullsafeMethodCall(_)
1971 | arena_ast::ExprKind::StaticPropertyAccess(_)
1972 | arena_ast::ExprKind::ClassConstAccess(_)
1973 | arena_ast::ExprKind::StaticMethodCall(_)
1974 | arena_ast::ExprKind::StaticMethodCallDynamic(_)
1975 | arena_ast::ExprKind::ClassConstAccessDynamic { .. }
1976 | arena_ast::ExprKind::StaticPropertyAccessDynamic { .. }
1977 | arena_ast::ExprKind::CallableCreate(_) => {
1978 unreachable!("chain links are converted by the link function")
1979 }
1980 }
1981}
1982
1983fn owned_link_kind(k: &arena_ast::ExprKind<'_, '_>, operand: Expr) -> ExprKind {
1985 match k {
1986 arena_ast::ExprKind::Assign(a) => ExprKind::Assign(AssignExpr {
1987 target: Box::new(operand),
1988 op: a.op,
1989 value: Box::new(owned_expr(a.value)),
1990 by_ref: a.by_ref,
1991 }),
1992 arena_ast::ExprKind::Binary(b) => ExprKind::Binary(BinaryExpr {
1993 left: Box::new(operand),
1994 op: b.op,
1995 right: Box::new(owned_expr(b.right)),
1996 }),
1997 arena_ast::ExprKind::UnaryPostfix(u) => ExprKind::UnaryPostfix(UnaryPostfixExpr {
1998 operand: Box::new(operand),
1999 op: u.op,
2000 }),
2001 arena_ast::ExprKind::Ternary(t) => ExprKind::Ternary(TernaryExpr {
2002 condition: Box::new(operand),
2003 then_expr: t.then_expr.map(|e| Box::new(owned_expr(e))),
2004 else_expr: Box::new(owned_expr(t.else_expr)),
2005 }),
2006 arena_ast::ExprKind::NullCoalesce(n) => ExprKind::NullCoalesce(NullCoalesceExpr {
2007 left: Box::new(operand),
2008 right: Box::new(owned_expr(n.right)),
2009 }),
2010 arena_ast::ExprKind::FunctionCall(f) => ExprKind::FunctionCall(FunctionCallExpr {
2011 name: Box::new(operand),
2012 args: owned_args(&f.args),
2013 }),
2014 arena_ast::ExprKind::ArrayAccess(a) => ExprKind::ArrayAccess(ArrayAccessExpr {
2015 array: Box::new(operand),
2016 index: a.index.map(|e| Box::new(owned_expr(e))),
2017 }),
2018 arena_ast::ExprKind::PropertyAccess(p) => ExprKind::PropertyAccess(PropertyAccessExpr {
2019 object: Box::new(operand),
2020 property: Box::new(owned_expr(p.property)),
2021 }),
2022 arena_ast::ExprKind::NullsafePropertyAccess(p) => {
2023 ExprKind::NullsafePropertyAccess(PropertyAccessExpr {
2024 object: Box::new(operand),
2025 property: Box::new(owned_expr(p.property)),
2026 })
2027 }
2028 arena_ast::ExprKind::MethodCall(m) => ExprKind::MethodCall(Box::new(MethodCallExpr {
2029 object: Box::new(operand),
2030 method: Box::new(owned_expr(m.method)),
2031 args: owned_args(&m.args),
2032 })),
2033 arena_ast::ExprKind::NullsafeMethodCall(m) => {
2034 ExprKind::NullsafeMethodCall(Box::new(MethodCallExpr {
2035 object: Box::new(operand),
2036 method: Box::new(owned_expr(m.method)),
2037 args: owned_args(&m.args),
2038 }))
2039 }
2040 arena_ast::ExprKind::StaticPropertyAccess(s) => {
2041 ExprKind::StaticPropertyAccess(StaticAccessExpr {
2042 class: Box::new(operand),
2043 member: Box::new(owned_expr(s.member)),
2044 })
2045 }
2046 arena_ast::ExprKind::StaticMethodCall(s) => {
2047 ExprKind::StaticMethodCall(Box::new(StaticMethodCallExpr {
2048 class: Box::new(operand),
2049 method: Box::new(owned_expr(s.method)),
2050 args: owned_args(&s.args),
2051 }))
2052 }
2053 arena_ast::ExprKind::StaticMethodCallDynamic(s) => {
2054 ExprKind::StaticMethodCallDynamic(Box::new(StaticMethodCallDynamicExpr {
2055 class: Box::new(operand),
2056 method: Box::new(owned_expr(s.method)),
2057 args: owned_args(&s.args),
2058 }))
2059 }
2060 arena_ast::ExprKind::ClassConstAccess(s) => ExprKind::ClassConstAccess(StaticAccessExpr {
2061 class: Box::new(operand),
2062 member: Box::new(owned_expr(s.member)),
2063 }),
2064 arena_ast::ExprKind::ClassConstAccessDynamic { member, .. } => {
2065 ExprKind::ClassConstAccessDynamic {
2066 class: Box::new(operand),
2067 member: Box::new(owned_expr(member)),
2068 }
2069 }
2070 arena_ast::ExprKind::StaticPropertyAccessDynamic { member, .. } => {
2071 ExprKind::StaticPropertyAccessDynamic {
2072 class: Box::new(operand),
2073 member: Box::new(owned_expr(member)),
2074 }
2075 }
2076 arena_ast::ExprKind::CallableCreate(c) => ExprKind::CallableCreate(CallableCreateExpr {
2077 kind: match &c.kind {
2078 arena_ast::CallableCreateKind::Function(_) => {
2079 CallableCreateKind::Function(Box::new(operand))
2080 }
2081 arena_ast::CallableCreateKind::Method { method, .. } => {
2082 CallableCreateKind::Method {
2083 object: Box::new(operand),
2084 method: Box::new(owned_expr(method)),
2085 }
2086 }
2087 arena_ast::CallableCreateKind::NullsafeMethod { method, .. } => {
2088 CallableCreateKind::NullsafeMethod {
2089 object: Box::new(operand),
2090 method: Box::new(owned_expr(method)),
2091 }
2092 }
2093 arena_ast::CallableCreateKind::StaticMethod { method, .. } => {
2094 CallableCreateKind::StaticMethod {
2095 class: Box::new(operand),
2096 method: Box::new(owned_expr(method)),
2097 }
2098 }
2099 },
2100 }),
2101 _ => unreachable!("not a chain link"),
2102 }
2103}
2104
2105fn owned_param(p: &arena_ast::Param<'_, '_>) -> Param {
2106 Param {
2107 name: owned_ident(p.name),
2108 type_hint: p.type_hint.as_ref().map(owned_type_hint),
2109 default: p.default.as_ref().map(owned_expr),
2110 by_ref: p.by_ref,
2111 variadic: p.variadic,
2112 is_readonly: p.is_readonly,
2113 is_final: p.is_final,
2114 visibility: p.visibility,
2115 set_visibility: p.set_visibility,
2116 attributes: owned_attrs(&p.attributes),
2117 hooks: owned_hooks(&p.hooks),
2118 doc_comment: p.doc_comment.as_ref().map(owned_comment),
2119 span: p.span,
2120 }
2121}
2122
2123#[inline(never)]
2124fn owned_params(params: &[arena_ast::Param<'_, '_>]) -> Box<[Param]> {
2125 params
2126 .iter()
2127 .map(owned_param)
2128 .collect::<Vec<_>>()
2129 .into_boxed_slice()
2130}
2131
2132fn owned_hook(h: &arena_ast::PropertyHook<'_, '_>) -> PropertyHook {
2133 PropertyHook {
2134 kind: h.kind,
2135 body: match &h.body {
2136 arena_ast::PropertyHookBody::Block(block) => {
2137 PropertyHookBody::Block(Box::new(owned_block(block)))
2138 }
2139 arena_ast::PropertyHookBody::Expression(e) => {
2140 PropertyHookBody::Expression(owned_expr(e))
2141 }
2142 arena_ast::PropertyHookBody::Abstract => PropertyHookBody::Abstract,
2143 },
2144 is_final: h.is_final,
2145 by_ref: h.by_ref,
2146 params: owned_params(&h.params),
2147 attributes: owned_attrs(&h.attributes),
2148 span: h.span,
2149 }
2150}
2151
2152#[inline(never)]
2153fn owned_hooks(hooks: &[arena_ast::PropertyHook<'_, '_>]) -> Box<[PropertyHook]> {
2154 hooks
2155 .iter()
2156 .map(owned_hook)
2157 .collect::<Vec<_>>()
2158 .into_boxed_slice()
2159}
2160
2161fn owned_stmts(stmts: &[arena_ast::Stmt<'_, '_>]) -> Box<[Stmt]> {
2162 stmts
2163 .iter()
2164 .map(owned_stmt)
2165 .collect::<Vec<_>>()
2166 .into_boxed_slice()
2167}
2168
2169pub fn to_owned_stmt(stmt: &arena_ast::Stmt<'_, '_>) -> Stmt {
2171 owned_stmt(stmt)
2172}
2173
2174fn owned_block(block: &arena_ast::Block<'_, '_>) -> Block {
2175 Block {
2176 stmts: owned_stmts(&block.stmts),
2177 span: block.span,
2178 }
2179}
2180
2181fn owned_stmt(stmt: &arena_ast::Stmt<'_, '_>) -> Stmt {
2182 Stmt {
2183 kind: owned_stmt_kind(&stmt.kind),
2184 span: stmt.span,
2185 doc_comment: stmt.doc_comment.map(owned_comment),
2186 }
2187}
2188
2189fn owned_stmt_kind(k: &arena_ast::StmtKind<'_, '_>) -> StmtKind {
2190 match k {
2191 arena_ast::StmtKind::Expression(e) => StmtKind::Expression(Box::new(owned_expr(e))),
2192 arena_ast::StmtKind::Echo(exprs) => StmtKind::Echo(owned_exprs(exprs)),
2193 arena_ast::StmtKind::Return(e) => StmtKind::Return(e.map(|e| Box::new(owned_expr(e)))),
2194 arena_ast::StmtKind::Block(block) => StmtKind::Block(Box::new(owned_block(block))),
2195 arena_ast::StmtKind::If(s) => StmtKind::If(Box::new(IfStmt {
2196 condition: owned_expr(&s.condition),
2197 then_branch: Box::new(owned_stmt(s.then_branch)),
2198 elseif_branches: s
2199 .elseif_branches
2200 .iter()
2201 .map(|b| ElseIfBranch {
2202 condition: owned_expr(&b.condition),
2203 body: owned_stmt(&b.body),
2204 span: b.span,
2205 })
2206 .collect::<Vec<_>>()
2207 .into_boxed_slice(),
2208 else_branch: s.else_branch.map(|b| Box::new(owned_stmt(b))),
2209 else_kw_span: s.else_kw_span,
2210 uses_alternative: s.uses_alternative,
2211 })),
2212 arena_ast::StmtKind::While(s) => StmtKind::While(Box::new(WhileStmt {
2213 condition: owned_expr(&s.condition),
2214 body: Box::new(owned_stmt(s.body)),
2215 uses_alternative: s.uses_alternative,
2216 })),
2217 arena_ast::StmtKind::For(s) => StmtKind::For(Box::new(ForStmt {
2218 init: owned_exprs(&s.init),
2219 condition: owned_exprs(&s.condition),
2220 update: owned_exprs(&s.update),
2221 body: Box::new(owned_stmt(s.body)),
2222 uses_alternative: s.uses_alternative,
2223 })),
2224 arena_ast::StmtKind::Foreach(s) => StmtKind::Foreach(Box::new(ForeachStmt {
2225 expr: owned_expr(&s.expr),
2226 key: s.key.as_ref().map(owned_expr),
2227 value: owned_expr(&s.value),
2228 body: Box::new(owned_stmt(s.body)),
2229 uses_alternative: s.uses_alternative,
2230 })),
2231 arena_ast::StmtKind::DoWhile(s) => StmtKind::DoWhile(Box::new(DoWhileStmt {
2232 body: Box::new(owned_stmt(s.body)),
2233 condition: owned_expr(&s.condition),
2234 })),
2235 arena_ast::StmtKind::Function(f) => StmtKind::Function(Box::new(owned_function_decl(f))),
2236 arena_ast::StmtKind::Break(e) => StmtKind::Break(e.map(|e| Box::new(owned_expr(e)))),
2237 arena_ast::StmtKind::Continue(e) => StmtKind::Continue(e.map(|e| Box::new(owned_expr(e)))),
2238 arena_ast::StmtKind::Switch(s) => StmtKind::Switch(Box::new(SwitchStmt {
2239 expr: owned_expr(&s.expr),
2240 body: SwitchBody {
2241 cases: s
2242 .body
2243 .cases
2244 .iter()
2245 .map(|c| SwitchCase {
2246 value: c.value.as_ref().map(owned_expr),
2247 body: owned_stmts(&c.body),
2248 span: c.span,
2249 })
2250 .collect::<Vec<_>>()
2251 .into_boxed_slice(),
2252 span: s.body.span,
2253 },
2254 uses_alternative: s.uses_alternative,
2255 })),
2256 arena_ast::StmtKind::Goto(ident) => StmtKind::Goto(owned_ident(*ident)),
2257 arena_ast::StmtKind::Label(ident) => StmtKind::Label(owned_ident(*ident)),
2258 arena_ast::StmtKind::Declare(d) => StmtKind::Declare(Box::new(DeclareStmt {
2259 directives: d
2260 .directives
2261 .iter()
2262 .map(|(k, v)| (Box::from(*k), owned_expr(v)))
2263 .collect::<Vec<_>>()
2264 .into_boxed_slice(),
2265 body: d.body.map(|b| Box::new(owned_stmt(b))),
2266 uses_alternative: d.uses_alternative,
2267 })),
2268 arena_ast::StmtKind::Unset(exprs) => StmtKind::Unset(owned_exprs(exprs)),
2269 arena_ast::StmtKind::Throw(e) => StmtKind::Throw(Box::new(owned_expr(e))),
2270 arena_ast::StmtKind::TryCatch(t) => StmtKind::TryCatch(Box::new(TryCatchStmt {
2271 body: Box::new(owned_block(t.body)),
2272 catches: t
2273 .catches
2274 .iter()
2275 .map(|c| CatchClause {
2276 types: c
2277 .types
2278 .iter()
2279 .map(owned_name)
2280 .collect::<Vec<_>>()
2281 .into_boxed_slice(),
2282 var: c.var.map(Box::from),
2283 body: Box::new(owned_block(c.body)),
2284 span: c.span,
2285 })
2286 .collect::<Vec<_>>()
2287 .into_boxed_slice(),
2288 finally: t.finally.map(|f| Box::new(owned_block(f))),
2289 finally_kw_span: t.finally_kw_span,
2290 })),
2291 arena_ast::StmtKind::Global(exprs) => StmtKind::Global(owned_exprs(exprs)),
2292 arena_ast::StmtKind::Class(cls) => StmtKind::Class(Box::new(owned_class_decl(cls))),
2293 arena_ast::StmtKind::Interface(iface) => {
2294 StmtKind::Interface(Box::new(owned_interface_decl(iface)))
2295 }
2296 arena_ast::StmtKind::Trait(tr) => StmtKind::Trait(Box::new(owned_trait_decl(tr))),
2297 arena_ast::StmtKind::Enum(en) => StmtKind::Enum(Box::new(owned_enum_decl(en))),
2298 arena_ast::StmtKind::Namespace(ns) => StmtKind::Namespace(Box::new(NamespaceDecl {
2299 name: ns.name.as_ref().map(owned_name),
2300 body: match &ns.body {
2301 arena_ast::NamespaceBody::Braced(block) => {
2302 NamespaceBody::Braced(Box::new(owned_block(block)))
2303 }
2304 arena_ast::NamespaceBody::Simple => NamespaceBody::Simple,
2305 },
2306 })),
2307 arena_ast::StmtKind::Use(u) => StmtKind::Use(Box::new(UseDecl {
2308 kind: u.kind,
2309 uses: u
2310 .uses
2311 .iter()
2312 .map(|item| UseItem {
2313 name: owned_name(&item.name),
2314 alias: item.alias.map(Box::from),
2315 kind: item.kind,
2316 span: item.span,
2317 })
2318 .collect::<Vec<_>>()
2319 .into_boxed_slice(),
2320 })),
2321 arena_ast::StmtKind::Const(items) => StmtKind::Const(
2322 items
2323 .iter()
2324 .map(|item| ConstItem {
2325 name: owned_ident(item.name),
2326 value: owned_expr(&item.value),
2327 attributes: owned_attrs(&item.attributes),
2328 span: item.span,
2329 doc_comment: owned_opt_comment(&item.doc_comment),
2330 })
2331 .collect::<Vec<_>>()
2332 .into_boxed_slice(),
2333 ),
2334 arena_ast::StmtKind::StaticVar(vars) => StmtKind::StaticVar(
2335 vars.iter()
2336 .map(|v| StaticVar {
2337 name: owned_ident(v.name),
2338 default: v.default.as_ref().map(owned_expr),
2339 span: v.span,
2340 })
2341 .collect::<Vec<_>>()
2342 .into_boxed_slice(),
2343 ),
2344 arena_ast::StmtKind::HaltCompiler(s) => StmtKind::HaltCompiler(Box::from(*s)),
2345 arena_ast::StmtKind::Nop => StmtKind::Nop,
2346 arena_ast::StmtKind::InlineHtml(s) => StmtKind::InlineHtml(Box::from(*s)),
2347 arena_ast::StmtKind::Error => StmtKind::Error,
2348 }
2349}
2350
2351fn owned_function_decl(f: &arena_ast::FunctionDecl<'_, '_>) -> FunctionDecl {
2352 FunctionDecl {
2353 name: owned_ident(f.name),
2354 params: owned_params(&f.params),
2355 body: Box::new(owned_block(f.body)),
2356 return_type: f.return_type.as_ref().map(owned_type_hint),
2357 by_ref: f.by_ref,
2358 attributes: owned_attrs(&f.attributes),
2359 doc_comment: owned_opt_comment(&f.doc_comment),
2360 }
2361}
2362
2363fn owned_class_member(m: &arena_ast::ClassMember<'_, '_>) -> ClassMember {
2364 ClassMember {
2365 kind: match &m.kind {
2366 arena_ast::ClassMemberKind::Property(p) => ClassMemberKind::Property(PropertyDecl {
2367 name: owned_ident(p.name),
2368 visibility: p.visibility,
2369 set_visibility: p.set_visibility,
2370 is_static: p.is_static,
2371 is_readonly: p.is_readonly,
2372 type_hint: p.type_hint.as_ref().map(owned_type_hint),
2373 default: p.default.as_ref().map(owned_expr),
2374 attributes: owned_attrs(&p.attributes),
2375 hooks: owned_hooks(&p.hooks),
2376 doc_comment: owned_opt_comment(&p.doc_comment),
2377 }),
2378 arena_ast::ClassMemberKind::Method(m) => ClassMemberKind::Method(MethodDecl {
2379 name: owned_ident(m.name),
2380 visibility: m.visibility,
2381 is_static: m.is_static,
2382 is_abstract: m.is_abstract,
2383 is_final: m.is_final,
2384 by_ref: m.by_ref,
2385 params: owned_params(&m.params),
2386 return_type: m.return_type.as_ref().map(owned_type_hint),
2387 body: m.body.map(|b| Box::new(owned_block(b))),
2388 attributes: owned_attrs(&m.attributes),
2389 doc_comment: owned_opt_comment(&m.doc_comment),
2390 }),
2391 arena_ast::ClassMemberKind::ClassConst(c) => {
2392 ClassMemberKind::ClassConst(owned_class_const(c))
2393 }
2394 arena_ast::ClassMemberKind::TraitUse(t) => {
2395 ClassMemberKind::TraitUse(owned_trait_use(t))
2396 }
2397 },
2398 span: m.span,
2399 }
2400}
2401
2402fn owned_class_members(members: &[arena_ast::ClassMember<'_, '_>]) -> Box<[ClassMember]> {
2403 members
2404 .iter()
2405 .map(owned_class_member)
2406 .collect::<Vec<_>>()
2407 .into_boxed_slice()
2408}
2409
2410fn owned_class_const(c: &arena_ast::ClassConstDecl<'_, '_>) -> ClassConstDecl {
2411 ClassConstDecl {
2412 name: owned_ident(c.name),
2413 visibility: c.visibility,
2414 is_final: c.is_final,
2415 type_hint: c.type_hint.map(|th| Box::new(owned_type_hint(th))),
2416 value: owned_expr(&c.value),
2417 attributes: owned_attrs(&c.attributes),
2418 doc_comment: owned_opt_comment(&c.doc_comment),
2419 }
2420}
2421
2422fn owned_trait_use(t: &arena_ast::TraitUseDecl<'_, '_>) -> TraitUseDecl {
2423 TraitUseDecl {
2424 traits: t
2425 .traits
2426 .iter()
2427 .map(owned_name)
2428 .collect::<Vec<_>>()
2429 .into_boxed_slice(),
2430 adaptations: t
2431 .adaptations
2432 .iter()
2433 .map(|a| TraitAdaptation {
2434 kind: match &a.kind {
2435 arena_ast::TraitAdaptationKind::Precedence {
2436 trait_name,
2437 method,
2438 insteadof,
2439 } => TraitAdaptationKind::Precedence {
2440 trait_name: owned_name(trait_name),
2441 method: owned_name(method),
2442 insteadof: insteadof
2443 .iter()
2444 .map(owned_name)
2445 .collect::<Vec<_>>()
2446 .into_boxed_slice(),
2447 },
2448 arena_ast::TraitAdaptationKind::Alias {
2449 trait_name,
2450 method,
2451 new_modifier,
2452 new_name,
2453 } => TraitAdaptationKind::Alias {
2454 trait_name: trait_name.as_ref().map(owned_name),
2455 method: owned_name(method),
2456 new_modifier: *new_modifier,
2457 new_name: new_name.as_ref().map(owned_name),
2458 },
2459 },
2460 span: a.span,
2461 })
2462 .collect::<Vec<_>>()
2463 .into_boxed_slice(),
2464 adaptations_brace_span: t.adaptations_brace_span,
2465 doc_comment: owned_opt_comment(&t.doc_comment),
2466 }
2467}
2468
2469fn owned_class_decl(cls: &arena_ast::ClassDecl<'_, '_>) -> ClassDecl {
2470 ClassDecl {
2471 name: cls
2472 .name
2473 .map(|ident| Some(owned_ident(ident)))
2474 .unwrap_or(None),
2475 modifiers: cls.modifiers.clone(),
2476 extends: cls.extends.as_ref().map(owned_name),
2477 implements: cls
2478 .implements
2479 .iter()
2480 .map(owned_name)
2481 .collect::<Vec<_>>()
2482 .into_boxed_slice(),
2483 body: ClassBody {
2484 members: owned_class_members(&cls.body.members),
2485 span: cls.body.span,
2486 },
2487 attributes: owned_attrs(&cls.attributes),
2488 doc_comment: owned_opt_comment(&cls.doc_comment),
2489 }
2490}
2491
2492fn owned_interface_decl(iface: &arena_ast::InterfaceDecl<'_, '_>) -> InterfaceDecl {
2493 InterfaceDecl {
2494 name: owned_ident(iface.name),
2495 extends: iface
2496 .extends
2497 .iter()
2498 .map(owned_name)
2499 .collect::<Vec<_>>()
2500 .into_boxed_slice(),
2501 body: ClassBody {
2502 members: owned_class_members(&iface.body.members),
2503 span: iface.body.span,
2504 },
2505 attributes: owned_attrs(&iface.attributes),
2506 doc_comment: owned_opt_comment(&iface.doc_comment),
2507 }
2508}
2509
2510fn owned_trait_decl(tr: &arena_ast::TraitDecl<'_, '_>) -> TraitDecl {
2511 TraitDecl {
2512 name: owned_ident(tr.name),
2513 body: ClassBody {
2514 members: owned_class_members(&tr.body.members),
2515 span: tr.body.span,
2516 },
2517 attributes: owned_attrs(&tr.attributes),
2518 doc_comment: owned_opt_comment(&tr.doc_comment),
2519 }
2520}
2521
2522fn owned_enum_decl(en: &arena_ast::EnumDecl<'_, '_>) -> EnumDecl {
2523 EnumDecl {
2524 name: owned_ident(en.name),
2525 scalar_type: en.scalar_type.as_ref().map(owned_name),
2526 implements: en
2527 .implements
2528 .iter()
2529 .map(owned_name)
2530 .collect::<Vec<_>>()
2531 .into_boxed_slice(),
2532 body: EnumBody {
2533 members: en
2534 .body
2535 .members
2536 .iter()
2537 .map(|m| EnumMember {
2538 kind: match &m.kind {
2539 arena_ast::EnumMemberKind::Case(c) => EnumMemberKind::Case(EnumCase {
2540 name: owned_ident(c.name),
2541 value: c.value.as_ref().map(owned_expr),
2542 attributes: owned_attrs(&c.attributes),
2543 doc_comment: owned_opt_comment(&c.doc_comment),
2544 }),
2545 arena_ast::EnumMemberKind::Method(m) => {
2546 EnumMemberKind::Method(MethodDecl {
2547 name: owned_ident(m.name),
2548 visibility: m.visibility,
2549 is_static: m.is_static,
2550 is_abstract: m.is_abstract,
2551 is_final: m.is_final,
2552 by_ref: m.by_ref,
2553 params: owned_params(&m.params),
2554 return_type: m.return_type.as_ref().map(owned_type_hint),
2555 body: m.body.map(|b| Box::new(owned_block(b))),
2556 attributes: owned_attrs(&m.attributes),
2557 doc_comment: owned_opt_comment(&m.doc_comment),
2558 })
2559 }
2560 arena_ast::EnumMemberKind::ClassConst(c) => {
2561 EnumMemberKind::ClassConst(owned_class_const(c))
2562 }
2563 arena_ast::EnumMemberKind::TraitUse(t) => {
2564 EnumMemberKind::TraitUse(owned_trait_use(t))
2565 }
2566 },
2567 span: m.span,
2568 })
2569 .collect::<Vec<_>>()
2570 .into_boxed_slice(),
2571 span: en.body.span,
2572 },
2573 attributes: owned_attrs(&en.attributes),
2574 doc_comment: owned_opt_comment(&en.doc_comment),
2575 }
2576}
2577
2578pub fn to_owned_program(program: &arena_ast::Program<'_, '_>) -> Program {
2580 Program {
2581 stmts: owned_stmts(&program.stmts),
2582 span: program.span,
2583 }
2584}
2585
2586#[doc(hidden)]
2600pub fn from_owned_program<'arena>(
2601 arena: &'arena bumpalo::Bump,
2602 program: &Program,
2603) -> arena_ast::Program<'arena, 'arena> {
2604 arena_ast::Program {
2605 stmts: av_stmts(arena, &program.stmts),
2606 span: program.span,
2607 }
2608}
2609
2610#[inline]
2612fn av_str<'a>(arena: &'a bumpalo::Bump, s: &str) -> &'a str {
2613 arena.alloc_str(s)
2614}
2615
2616fn av_ident<'a>(arena: &'a bumpalo::Bump, ident: &Ident) -> arena_ast::Ident<'a> {
2617 match ident.as_str() {
2618 Some(s) => arena_ast::Ident::name(arena.alloc_str(s)),
2619 None => arena_ast::Ident::ERROR,
2620 }
2621}
2622
2623fn av_name<'a>(arena: &'a bumpalo::Bump, name: &Name) -> arena_ast::Name<'a, 'a> {
2624 if name.kind == NameKind::Error {
2625 return arena_ast::Name::Error { span: name.span };
2626 }
2627 if name.parts.len() == 1 && name.kind == NameKind::Unqualified {
2628 return arena_ast::Name::Simple {
2629 value: arena.alloc_str(&name.parts[0]),
2630 span: name.span,
2631 };
2632 }
2633 let mut parts = arena_ast::ArenaVec::with_capacity_in(name.parts.len(), arena);
2634 for p in name.parts.iter() {
2635 parts.push(arena.alloc_str(p) as &str);
2636 }
2637 arena_ast::Name::Complex {
2638 parts,
2639 kind: name.kind,
2640 span: name.span,
2641 }
2642}
2643
2644fn av_type_hint<'a>(arena: &'a bumpalo::Bump, th: &TypeHint) -> arena_ast::TypeHint<'a, 'a> {
2645 arena_ast::TypeHint {
2646 kind: av_type_hint_kind(arena, &th.kind),
2647 span: th.span,
2648 }
2649}
2650
2651fn av_type_hint_kind<'a>(
2652 arena: &'a bumpalo::Bump,
2653 k: &TypeHintKind,
2654) -> arena_ast::TypeHintKind<'a, 'a> {
2655 match k {
2656 TypeHintKind::Named(n) => arena_ast::TypeHintKind::Named(av_name(arena, n)),
2657 TypeHintKind::Keyword(b, span) => arena_ast::TypeHintKind::Keyword(*b, *span),
2658 TypeHintKind::Nullable(inner) => {
2659 arena_ast::TypeHintKind::Nullable(arena.alloc(av_type_hint(arena, inner)))
2660 }
2661 TypeHintKind::Union(types) => {
2662 let mut v = arena_ast::ArenaVec::with_capacity_in(types.len(), arena);
2663 for t in types.iter() {
2664 v.push(av_type_hint(arena, t));
2665 }
2666 arena_ast::TypeHintKind::Union(v)
2667 }
2668 TypeHintKind::Intersection(types) => {
2669 let mut v = arena_ast::ArenaVec::with_capacity_in(types.len(), arena);
2670 for t in types.iter() {
2671 v.push(av_type_hint(arena, t));
2672 }
2673 arena_ast::TypeHintKind::Intersection(v)
2674 }
2675 }
2676}
2677
2678fn av_arg<'a>(arena: &'a bumpalo::Bump, arg: &Arg) -> arena_ast::Arg<'a, 'a> {
2679 arena_ast::Arg {
2680 name: arg.name.as_ref().map(|n| av_name(arena, n)),
2681 value: arg.value.as_ref().map(|v| av_expr(arena, v)),
2682 unpack: arg.unpack,
2683 by_ref: arg.by_ref,
2684 span: arg.span,
2685 }
2686}
2687
2688#[inline(never)]
2689fn av_args<'a>(
2690 arena: &'a bumpalo::Bump,
2691 args: &[Arg],
2692) -> arena_ast::ArenaVec<'a, arena_ast::Arg<'a, 'a>> {
2693 let mut v = arena_ast::ArenaVec::with_capacity_in(args.len(), arena);
2694 for a in args.iter() {
2695 v.push(av_arg(arena, a));
2696 }
2697 v
2698}
2699
2700fn av_attr<'a>(arena: &'a bumpalo::Bump, attr: &Attribute) -> arena_ast::Attribute<'a, 'a> {
2701 arena_ast::Attribute {
2702 name: av_name(arena, &attr.name),
2703 args: av_args(arena, &attr.args),
2704 span: attr.span,
2705 }
2706}
2707
2708#[inline(never)]
2709fn av_attrs<'a>(
2710 arena: &'a bumpalo::Bump,
2711 attrs: &[Attribute],
2712) -> arena_ast::ArenaVec<'a, arena_ast::Attribute<'a, 'a>> {
2713 let mut v = arena_ast::ArenaVec::with_capacity_in(attrs.len(), arena);
2714 for a in attrs.iter() {
2715 v.push(av_attr(arena, a));
2716 }
2717 v
2718}
2719
2720fn av_comment<'a>(arena: &'a bumpalo::Bump, c: &Comment) -> arena_ast::Comment<'a> {
2721 arena_ast::Comment {
2722 kind: c.kind,
2723 text: arena.alloc_str(&c.text),
2724 span: c.span,
2725 }
2726}
2727
2728fn av_opt_comment<'a>(
2729 arena: &'a bumpalo::Bump,
2730 c: &Option<Comment>,
2731) -> Option<arena_ast::Comment<'a>> {
2732 c.as_ref().map(|c| av_comment(arena, c))
2733}
2734
2735fn av_string_parts<'a>(
2736 arena: &'a bumpalo::Bump,
2737 parts: &[StringPart],
2738) -> arena_ast::ArenaVec<'a, arena_ast::StringPart<'a, 'a>> {
2739 let mut v = arena_ast::ArenaVec::with_capacity_in(parts.len(), arena);
2740 for p in parts.iter() {
2741 v.push(match p {
2742 StringPart::Literal(s) => arena_ast::StringPart::Literal(arena.alloc_str(s)),
2743 StringPart::Expr(e) => arena_ast::StringPart::Expr(av_expr(arena, e)),
2744 });
2745 }
2746 v
2747}
2748
2749fn av_expr<'a>(arena: &'a bumpalo::Bump, expr: &Expr) -> arena_ast::Expr<'a, 'a> {
2750 if !owned_is_chain(&expr.kind) {
2751 return arena_ast::Expr {
2752 kind: av_leaf_kind(arena, &expr.kind),
2753 span: expr.span,
2754 };
2755 }
2756 av_chain_expr(arena, expr)
2757}
2758
2759#[inline(never)]
2761fn av_chain_expr<'a>(arena: &'a bumpalo::Bump, expr: &Expr) -> arena_ast::Expr<'a, 'a> {
2762 let first = owned_chain_operand(&expr.kind).expect("chain link has an operand");
2763 if !owned_is_chain(&first.kind) {
2764 let operand = arena_ast::Expr {
2765 kind: av_leaf_kind(arena, &first.kind),
2766 span: first.span,
2767 };
2768 return arena_ast::Expr {
2769 kind: av_link_kind(arena, &expr.kind, operand),
2770 span: expr.span,
2771 };
2772 }
2773 let mut chain = LinkStack::new();
2774 chain.push(expr);
2775 let mut leaf = first;
2776 while let Some(operand) = owned_chain_operand(&leaf.kind) {
2777 chain.push(leaf);
2778 leaf = operand;
2779 }
2780 let mut converted = arena_ast::Expr {
2781 kind: av_leaf_kind(arena, &leaf.kind),
2782 span: leaf.span,
2783 };
2784 while let Some(node) = chain.pop() {
2785 converted = arena_ast::Expr {
2786 kind: av_link_kind(arena, &node.kind, converted),
2787 span: node.span,
2788 };
2789 }
2790 converted
2791}
2792
2793#[inline(never)]
2794fn av_exprs<'a>(
2795 arena: &'a bumpalo::Bump,
2796 exprs: &[Expr],
2797) -> arena_ast::ArenaVec<'a, arena_ast::Expr<'a, 'a>> {
2798 let mut v = arena_ast::ArenaVec::with_capacity_in(exprs.len(), arena);
2799 for e in exprs.iter() {
2800 v.push(av_expr(arena, e));
2801 }
2802 v
2803}
2804
2805fn av_namestr<'a>(arena: &'a bumpalo::Bump, s: &str) -> arena_ast::NameStr<'a, 'a> {
2806 arena_ast::NameStr::__arena(arena.alloc_str(s))
2807}
2808
2809fn av_leaf_kind<'a>(arena: &'a bumpalo::Bump, k: &ExprKind) -> arena_ast::ExprKind<'a, 'a> {
2811 match k {
2812 ExprKind::Int(v) => arena_ast::ExprKind::Int(*v),
2813 ExprKind::Float(v) => arena_ast::ExprKind::Float(*v),
2814 ExprKind::String(s) => arena_ast::ExprKind::String(av_namestr(arena, s)),
2815 ExprKind::InterpolatedString(parts) => {
2816 arena_ast::ExprKind::InterpolatedString(av_string_parts(arena, parts))
2817 }
2818 ExprKind::Heredoc { label, parts } => arena_ast::ExprKind::Heredoc {
2819 label: arena.alloc_str(label),
2820 parts: av_string_parts(arena, parts),
2821 },
2822 ExprKind::Nowdoc { label, value } => arena_ast::ExprKind::Nowdoc {
2823 label: arena.alloc_str(label),
2824 value: arena.alloc_str(value),
2825 },
2826 ExprKind::ShellExec(parts) => arena_ast::ExprKind::ShellExec(av_string_parts(arena, parts)),
2827 ExprKind::Bool(v) => arena_ast::ExprKind::Bool(*v),
2828 ExprKind::Null => arena_ast::ExprKind::Null,
2829 ExprKind::Variable(s) => arena_ast::ExprKind::Variable(av_namestr(arena, s)),
2830 ExprKind::VariableVariable(inner) => {
2831 arena_ast::ExprKind::VariableVariable(arena.alloc(av_expr(arena, inner)))
2832 }
2833 ExprKind::Identifier(s) => arena_ast::ExprKind::Identifier(av_namestr(arena, s)),
2834 ExprKind::UnaryPrefix(u) => arena_ast::ExprKind::UnaryPrefix(arena_ast::UnaryPrefixExpr {
2835 op: u.op,
2836 operand: arena.alloc(av_expr(arena, &u.operand)),
2837 }),
2838 ExprKind::Array(elems) => {
2839 let mut v = arena_ast::ArenaVec::with_capacity_in(elems.len(), arena);
2840 for e in elems.iter() {
2841 v.push(arena_ast::ArrayElement {
2842 key: e.key.as_ref().map(|k| av_expr(arena, k)),
2843 value: av_expr(arena, &e.value),
2844 unpack: e.unpack,
2845 by_ref: e.by_ref,
2846 span: e.span,
2847 });
2848 }
2849 arena_ast::ExprKind::Array(v)
2850 }
2851 ExprKind::Print(e) => arena_ast::ExprKind::Print(arena.alloc(av_expr(arena, e))),
2852 ExprKind::Parenthesized(e) => {
2853 arena_ast::ExprKind::Parenthesized(arena.alloc(av_expr(arena, e)))
2854 }
2855 ExprKind::Cast(kind, e) => arena_ast::ExprKind::Cast(*kind, arena.alloc(av_expr(arena, e))),
2856 ExprKind::ErrorSuppress(e) => {
2857 arena_ast::ExprKind::ErrorSuppress(arena.alloc(av_expr(arena, e)))
2858 }
2859 ExprKind::Isset(exprs) => arena_ast::ExprKind::Isset(av_exprs(arena, exprs)),
2860 ExprKind::Empty(e) => arena_ast::ExprKind::Empty(arena.alloc(av_expr(arena, e))),
2861 ExprKind::Include(kind, e) => {
2862 arena_ast::ExprKind::Include(*kind, arena.alloc(av_expr(arena, e)))
2863 }
2864 ExprKind::Eval(e) => arena_ast::ExprKind::Eval(arena.alloc(av_expr(arena, e))),
2865 ExprKind::Exit(e) => {
2866 arena_ast::ExprKind::Exit(e.as_ref().map(|e| &*arena.alloc(av_expr(arena, e))))
2867 }
2868 ExprKind::MagicConst(m) => arena_ast::ExprKind::MagicConst(*m),
2869 ExprKind::Clone(e) => arena_ast::ExprKind::Clone(arena.alloc(av_expr(arena, e))),
2870 ExprKind::CloneWith(obj, props) => arena_ast::ExprKind::CloneWith(
2871 arena.alloc(av_expr(arena, obj)),
2872 arena.alloc(av_expr(arena, props)),
2873 ),
2874 ExprKind::New(n) => arena_ast::ExprKind::New(arena_ast::NewExpr {
2875 class: arena.alloc(av_expr(arena, &n.class)),
2876 args: av_args(arena, &n.args),
2877 }),
2878 ExprKind::Closure(c) => arena_ast::ExprKind::Closure(arena.alloc(arena_ast::ClosureExpr {
2879 is_static: c.is_static,
2880 by_ref: c.by_ref,
2881 params: av_params(arena, &c.params),
2882 use_vars: {
2883 let mut v = arena_ast::ArenaVec::with_capacity_in(c.use_vars.len(), arena);
2884 for uv in c.use_vars.iter() {
2885 v.push(arena_ast::ClosureUseVar {
2886 name: arena.alloc_str(&uv.name),
2887 by_ref: uv.by_ref,
2888 span: uv.span,
2889 });
2890 }
2891 v
2892 },
2893 return_type: c.return_type.as_ref().map(|t| av_type_hint(arena, t)),
2894 body: &*arena.alloc(av_block(arena, &c.body)),
2895 attributes: av_attrs(arena, &c.attributes),
2896 })),
2897 ExprKind::ArrowFunction(f) => {
2898 arena_ast::ExprKind::ArrowFunction(arena.alloc(arena_ast::ArrowFunctionExpr {
2899 is_static: f.is_static,
2900 by_ref: f.by_ref,
2901 params: av_params(arena, &f.params),
2902 return_type: f.return_type.as_ref().map(|t| av_type_hint(arena, t)),
2903 body: arena.alloc(av_expr(arena, &f.body)),
2904 attributes: av_attrs(arena, &f.attributes),
2905 }))
2906 }
2907 ExprKind::Match(m) => arena_ast::ExprKind::Match(arena_ast::MatchExpr {
2908 subject: arena.alloc(av_expr(arena, &m.subject)),
2909 arms: {
2910 let mut v = arena_ast::ArenaVec::with_capacity_in(m.arms.len(), arena);
2911 for arm in m.arms.iter() {
2912 v.push(arena_ast::MatchArm {
2913 conditions: arm.conditions.as_ref().map(|conds| av_exprs(arena, conds)),
2914 body: av_expr(arena, &arm.body),
2915 span: arm.span,
2916 });
2917 }
2918 v
2919 },
2920 brace_span: m.brace_span,
2921 }),
2922 ExprKind::Throw(e) => arena_ast::ExprKind::Throw(arena.alloc(av_expr(arena, e))),
2923 ExprKind::Yield(y) => arena_ast::ExprKind::Yield(arena_ast::YieldExpr {
2924 key: y.key.as_ref().map(|e| &*arena.alloc(av_expr(arena, e))),
2925 value: y.value.as_ref().map(|e| &*arena.alloc(av_expr(arena, e))),
2926 is_from: y.is_from,
2927 }),
2928 ExprKind::AnonymousClass(cls) => {
2929 arena_ast::ExprKind::AnonymousClass(arena.alloc(av_class_decl(arena, cls)))
2930 }
2931 ExprKind::Omit => arena_ast::ExprKind::Omit,
2932 ExprKind::Error => arena_ast::ExprKind::Error,
2933 ExprKind::Assign(_)
2934 | ExprKind::Binary(_)
2935 | ExprKind::UnaryPostfix(_)
2936 | ExprKind::Ternary(_)
2937 | ExprKind::NullCoalesce(_)
2938 | ExprKind::FunctionCall(_)
2939 | ExprKind::ArrayAccess(_)
2940 | ExprKind::PropertyAccess(_)
2941 | ExprKind::NullsafePropertyAccess(_)
2942 | ExprKind::MethodCall(_)
2943 | ExprKind::NullsafeMethodCall(_)
2944 | ExprKind::StaticPropertyAccess(_)
2945 | ExprKind::ClassConstAccess(_)
2946 | ExprKind::StaticMethodCall(_)
2947 | ExprKind::StaticMethodCallDynamic(_)
2948 | ExprKind::ClassConstAccessDynamic { .. }
2949 | ExprKind::StaticPropertyAccessDynamic { .. }
2950 | ExprKind::CallableCreate(_) => {
2951 unreachable!("chain links are converted by the link function")
2952 }
2953 }
2954}
2955
2956fn av_link_kind<'a>(
2958 arena: &'a bumpalo::Bump,
2959 k: &ExprKind,
2960 operand: arena_ast::Expr<'a, 'a>,
2961) -> arena_ast::ExprKind<'a, 'a> {
2962 match k {
2963 ExprKind::Assign(a) => arena_ast::ExprKind::Assign(arena_ast::AssignExpr {
2964 target: arena.alloc(operand),
2965 op: a.op,
2966 value: arena.alloc(av_expr(arena, &a.value)),
2967 by_ref: a.by_ref,
2968 }),
2969 ExprKind::Binary(b) => arena_ast::ExprKind::Binary(arena_ast::BinaryExpr {
2970 left: arena.alloc(operand),
2971 op: b.op,
2972 right: arena.alloc(av_expr(arena, &b.right)),
2973 }),
2974 ExprKind::UnaryPostfix(u) => {
2975 arena_ast::ExprKind::UnaryPostfix(arena_ast::UnaryPostfixExpr {
2976 operand: arena.alloc(operand),
2977 op: u.op,
2978 })
2979 }
2980 ExprKind::Ternary(t) => arena_ast::ExprKind::Ternary(arena_ast::TernaryExpr {
2981 condition: arena.alloc(operand),
2982 then_expr: t
2983 .then_expr
2984 .as_ref()
2985 .map(|e| &*arena.alloc(av_expr(arena, e))),
2986 else_expr: arena.alloc(av_expr(arena, &t.else_expr)),
2987 }),
2988 ExprKind::NullCoalesce(n) => {
2989 arena_ast::ExprKind::NullCoalesce(arena_ast::NullCoalesceExpr {
2990 left: arena.alloc(operand),
2991 right: arena.alloc(av_expr(arena, &n.right)),
2992 })
2993 }
2994 ExprKind::FunctionCall(f) => {
2995 arena_ast::ExprKind::FunctionCall(arena_ast::FunctionCallExpr {
2996 name: arena.alloc(operand),
2997 args: av_args(arena, &f.args),
2998 })
2999 }
3000 ExprKind::ArrayAccess(a) => arena_ast::ExprKind::ArrayAccess(arena_ast::ArrayAccessExpr {
3001 array: arena.alloc(operand),
3002 index: a.index.as_ref().map(|e| &*arena.alloc(av_expr(arena, e))),
3003 }),
3004 ExprKind::PropertyAccess(p) => {
3005 arena_ast::ExprKind::PropertyAccess(arena_ast::PropertyAccessExpr {
3006 object: arena.alloc(operand),
3007 property: arena.alloc(av_expr(arena, &p.property)),
3008 })
3009 }
3010 ExprKind::NullsafePropertyAccess(p) => {
3011 arena_ast::ExprKind::NullsafePropertyAccess(arena_ast::PropertyAccessExpr {
3012 object: arena.alloc(operand),
3013 property: arena.alloc(av_expr(arena, &p.property)),
3014 })
3015 }
3016 ExprKind::MethodCall(m) => {
3017 arena_ast::ExprKind::MethodCall(arena.alloc(arena_ast::MethodCallExpr {
3018 object: arena.alloc(operand),
3019 method: arena.alloc(av_expr(arena, &m.method)),
3020 args: av_args(arena, &m.args),
3021 }))
3022 }
3023 ExprKind::NullsafeMethodCall(m) => {
3024 arena_ast::ExprKind::NullsafeMethodCall(arena.alloc(arena_ast::MethodCallExpr {
3025 object: arena.alloc(operand),
3026 method: arena.alloc(av_expr(arena, &m.method)),
3027 args: av_args(arena, &m.args),
3028 }))
3029 }
3030 ExprKind::StaticPropertyAccess(s) => {
3031 arena_ast::ExprKind::StaticPropertyAccess(arena_ast::StaticAccessExpr {
3032 class: arena.alloc(operand),
3033 member: arena.alloc(av_expr(arena, &s.member)),
3034 })
3035 }
3036 ExprKind::StaticMethodCall(s) => {
3037 arena_ast::ExprKind::StaticMethodCall(arena.alloc(arena_ast::StaticMethodCallExpr {
3038 class: arena.alloc(operand),
3039 method: arena.alloc(av_expr(arena, &s.method)),
3040 args: av_args(arena, &s.args),
3041 }))
3042 }
3043 ExprKind::StaticMethodCallDynamic(s) => arena_ast::ExprKind::StaticMethodCallDynamic(
3044 arena.alloc(arena_ast::StaticMethodCallDynamicExpr {
3045 class: arena.alloc(operand),
3046 method: arena.alloc(av_expr(arena, &s.method)),
3047 args: av_args(arena, &s.args),
3048 }),
3049 ),
3050 ExprKind::ClassConstAccess(s) => {
3051 arena_ast::ExprKind::ClassConstAccess(arena_ast::StaticAccessExpr {
3052 class: arena.alloc(operand),
3053 member: arena.alloc(av_expr(arena, &s.member)),
3054 })
3055 }
3056 ExprKind::ClassConstAccessDynamic { member, .. } => {
3057 arena_ast::ExprKind::ClassConstAccessDynamic {
3058 class: arena.alloc(operand),
3059 member: arena.alloc(av_expr(arena, member)),
3060 }
3061 }
3062 ExprKind::StaticPropertyAccessDynamic { member, .. } => {
3063 arena_ast::ExprKind::StaticPropertyAccessDynamic {
3064 class: arena.alloc(operand),
3065 member: arena.alloc(av_expr(arena, member)),
3066 }
3067 }
3068 ExprKind::CallableCreate(c) => {
3069 arena_ast::ExprKind::CallableCreate(arena_ast::CallableCreateExpr {
3070 kind: match &c.kind {
3071 CallableCreateKind::Function(_) => {
3072 arena_ast::CallableCreateKind::Function(arena.alloc(operand))
3073 }
3074 CallableCreateKind::Method { method, .. } => {
3075 arena_ast::CallableCreateKind::Method {
3076 object: arena.alloc(operand),
3077 method: arena.alloc(av_expr(arena, method)),
3078 }
3079 }
3080 CallableCreateKind::NullsafeMethod { method, .. } => {
3081 arena_ast::CallableCreateKind::NullsafeMethod {
3082 object: arena.alloc(operand),
3083 method: arena.alloc(av_expr(arena, method)),
3084 }
3085 }
3086 CallableCreateKind::StaticMethod { method, .. } => {
3087 arena_ast::CallableCreateKind::StaticMethod {
3088 class: arena.alloc(operand),
3089 method: arena.alloc(av_expr(arena, method)),
3090 }
3091 }
3092 },
3093 })
3094 }
3095 _ => unreachable!("not a chain link"),
3096 }
3097}
3098
3099fn av_param<'a>(arena: &'a bumpalo::Bump, p: &Param) -> arena_ast::Param<'a, 'a> {
3100 arena_ast::Param {
3101 name: av_ident(arena, &p.name),
3102 type_hint: p.type_hint.as_ref().map(|t| av_type_hint(arena, t)),
3103 default: p.default.as_ref().map(|e| av_expr(arena, e)),
3104 by_ref: p.by_ref,
3105 variadic: p.variadic,
3106 is_readonly: p.is_readonly,
3107 is_final: p.is_final,
3108 visibility: p.visibility,
3109 set_visibility: p.set_visibility,
3110 attributes: av_attrs(arena, &p.attributes),
3111 hooks: av_hooks(arena, &p.hooks),
3112 doc_comment: av_opt_comment(arena, &p.doc_comment),
3113 span: p.span,
3114 }
3115}
3116
3117#[inline(never)]
3118fn av_params<'a>(
3119 arena: &'a bumpalo::Bump,
3120 params: &[Param],
3121) -> arena_ast::ArenaVec<'a, arena_ast::Param<'a, 'a>> {
3122 let mut v = arena_ast::ArenaVec::with_capacity_in(params.len(), arena);
3123 for p in params.iter() {
3124 v.push(av_param(arena, p));
3125 }
3126 v
3127}
3128
3129fn av_hook<'a>(arena: &'a bumpalo::Bump, h: &PropertyHook) -> arena_ast::PropertyHook<'a, 'a> {
3130 arena_ast::PropertyHook {
3131 kind: h.kind,
3132 body: match &h.body {
3133 PropertyHookBody::Block(block) => {
3134 arena_ast::PropertyHookBody::Block(arena.alloc(av_block(arena, block)))
3135 }
3136 PropertyHookBody::Expression(e) => {
3137 arena_ast::PropertyHookBody::Expression(av_expr(arena, e))
3138 }
3139 PropertyHookBody::Abstract => arena_ast::PropertyHookBody::Abstract,
3140 },
3141 is_final: h.is_final,
3142 by_ref: h.by_ref,
3143 params: av_params(arena, &h.params),
3144 attributes: av_attrs(arena, &h.attributes),
3145 span: h.span,
3146 }
3147}
3148
3149fn av_hooks<'a>(
3150 arena: &'a bumpalo::Bump,
3151 hooks: &[PropertyHook],
3152) -> arena_ast::ArenaVec<'a, arena_ast::PropertyHook<'a, 'a>> {
3153 let mut v = arena_ast::ArenaVec::with_capacity_in(hooks.len(), arena);
3154 for h in hooks.iter() {
3155 v.push(av_hook(arena, h));
3156 }
3157 v
3158}
3159
3160fn av_stmt<'a>(arena: &'a bumpalo::Bump, stmt: &Stmt) -> arena_ast::Stmt<'a, 'a> {
3161 arena_ast::Stmt {
3162 kind: av_stmt_kind(arena, &stmt.kind),
3163 span: stmt.span,
3164 doc_comment: stmt.doc_comment.as_ref().map(|c| {
3165 &*arena.alloc(arena_ast::Comment {
3166 kind: c.kind,
3167 text: arena.alloc_str(&c.text),
3168 span: c.span,
3169 })
3170 }),
3171 }
3172}
3173
3174fn av_stmts<'a>(
3175 arena: &'a bumpalo::Bump,
3176 stmts: &[Stmt],
3177) -> arena_ast::ArenaVec<'a, arena_ast::Stmt<'a, 'a>> {
3178 let mut v = arena_ast::ArenaVec::with_capacity_in(stmts.len(), arena);
3179 for s in stmts.iter() {
3180 v.push(av_stmt(arena, s));
3181 }
3182 v
3183}
3184
3185fn av_block<'a>(arena: &'a bumpalo::Bump, block: &Block) -> arena_ast::Block<'a, 'a> {
3186 arena_ast::Block {
3187 stmts: av_stmts(arena, &block.stmts),
3188 span: block.span,
3189 }
3190}
3191
3192fn av_stmt_kind<'a>(arena: &'a bumpalo::Bump, k: &StmtKind) -> arena_ast::StmtKind<'a, 'a> {
3193 match k {
3194 StmtKind::Expression(e) => arena_ast::StmtKind::Expression(arena.alloc(av_expr(arena, e))),
3195 StmtKind::Echo(exprs) => arena_ast::StmtKind::Echo(av_exprs(arena, exprs)),
3196 StmtKind::Return(e) => {
3197 arena_ast::StmtKind::Return(e.as_ref().map(|e| &*arena.alloc(av_expr(arena, e))))
3198 }
3199 StmtKind::Block(block) => arena_ast::StmtKind::Block(arena.alloc(av_block(arena, block))),
3200 StmtKind::If(s) => arena_ast::StmtKind::If(arena.alloc(av_if_stmt(arena, s))),
3201 StmtKind::While(s) => arena_ast::StmtKind::While(arena.alloc(av_while_stmt(arena, s))),
3202 StmtKind::For(s) => arena_ast::StmtKind::For(arena.alloc(av_for_stmt(arena, s))),
3203 StmtKind::Foreach(s) => {
3204 arena_ast::StmtKind::Foreach(arena.alloc(av_foreach_stmt(arena, s)))
3205 }
3206 StmtKind::DoWhile(s) => {
3207 arena_ast::StmtKind::DoWhile(arena.alloc(av_do_while_stmt(arena, s)))
3208 }
3209 StmtKind::Function(f) => {
3210 arena_ast::StmtKind::Function(arena.alloc(av_function_decl(arena, f)))
3211 }
3212 StmtKind::Break(e) => {
3213 arena_ast::StmtKind::Break(e.as_ref().map(|e| &*arena.alloc(av_expr(arena, e))))
3214 }
3215 StmtKind::Continue(e) => {
3216 arena_ast::StmtKind::Continue(e.as_ref().map(|e| &*arena.alloc(av_expr(arena, e))))
3217 }
3218 StmtKind::Switch(s) => arena_ast::StmtKind::Switch(arena.alloc(av_switch_stmt(arena, s))),
3219 StmtKind::Goto(ident) => arena_ast::StmtKind::Goto(av_ident(arena, ident)),
3220 StmtKind::Label(ident) => arena_ast::StmtKind::Label(av_ident(arena, ident)),
3221 StmtKind::Declare(d) => {
3222 arena_ast::StmtKind::Declare(arena.alloc(av_declare_stmt(arena, d)))
3223 }
3224 StmtKind::Unset(exprs) => arena_ast::StmtKind::Unset(av_exprs(arena, exprs)),
3225 StmtKind::Throw(e) => arena_ast::StmtKind::Throw(arena.alloc(av_expr(arena, e))),
3226 StmtKind::TryCatch(t) => {
3227 arena_ast::StmtKind::TryCatch(arena.alloc(av_try_catch_stmt(arena, t)))
3228 }
3229 StmtKind::Global(exprs) => arena_ast::StmtKind::Global(av_exprs(arena, exprs)),
3230 StmtKind::Class(cls) => arena_ast::StmtKind::Class(arena.alloc(av_class_decl(arena, cls))),
3231 StmtKind::Interface(iface) => {
3232 arena_ast::StmtKind::Interface(arena.alloc(av_interface_decl(arena, iface)))
3233 }
3234 StmtKind::Trait(tr) => arena_ast::StmtKind::Trait(arena.alloc(av_trait_decl(arena, tr))),
3235 StmtKind::Enum(en) => arena_ast::StmtKind::Enum(arena.alloc(av_enum_decl(arena, en))),
3236 StmtKind::Namespace(ns) => {
3237 arena_ast::StmtKind::Namespace(arena.alloc(av_namespace_decl(arena, ns)))
3238 }
3239 StmtKind::Use(u) => arena_ast::StmtKind::Use(arena.alloc(av_use_decl(arena, u))),
3240 StmtKind::Const(items) => arena_ast::StmtKind::Const(av_const_items(arena, items)),
3241 StmtKind::StaticVar(vars) => arena_ast::StmtKind::StaticVar(av_static_vars(arena, vars)),
3242 StmtKind::HaltCompiler(s) => arena_ast::StmtKind::HaltCompiler(av_str(arena, s)),
3243 StmtKind::Nop => arena_ast::StmtKind::Nop,
3244 StmtKind::InlineHtml(s) => arena_ast::StmtKind::InlineHtml(av_str(arena, s)),
3245 StmtKind::Error => arena_ast::StmtKind::Error,
3246 }
3247}
3248
3249#[inline(never)]
3252fn av_if_stmt<'a>(arena: &'a bumpalo::Bump, s: &IfStmt) -> arena_ast::IfStmt<'a, 'a> {
3253 arena_ast::IfStmt {
3254 condition: av_expr(arena, &s.condition),
3255 then_branch: arena.alloc(av_stmt(arena, &s.then_branch)),
3256 elseif_branches: {
3257 let mut v = arena_ast::ArenaVec::with_capacity_in(s.elseif_branches.len(), arena);
3258 for b in s.elseif_branches.iter() {
3259 v.push(arena_ast::ElseIfBranch {
3260 condition: av_expr(arena, &b.condition),
3261 body: av_stmt(arena, &b.body),
3262 span: b.span,
3263 });
3264 }
3265 v
3266 },
3267 else_branch: s
3268 .else_branch
3269 .as_ref()
3270 .map(|b| &*arena.alloc(av_stmt(arena, b))),
3271 else_kw_span: s.else_kw_span,
3272 uses_alternative: s.uses_alternative,
3273 }
3274}
3275
3276#[inline(never)]
3277fn av_while_stmt<'a>(arena: &'a bumpalo::Bump, s: &WhileStmt) -> arena_ast::WhileStmt<'a, 'a> {
3278 arena_ast::WhileStmt {
3279 condition: av_expr(arena, &s.condition),
3280 body: arena.alloc(av_stmt(arena, &s.body)),
3281 uses_alternative: s.uses_alternative,
3282 }
3283}
3284
3285#[inline(never)]
3286fn av_for_stmt<'a>(arena: &'a bumpalo::Bump, s: &ForStmt) -> arena_ast::ForStmt<'a, 'a> {
3287 arena_ast::ForStmt {
3288 init: av_exprs(arena, &s.init),
3289 condition: av_exprs(arena, &s.condition),
3290 update: av_exprs(arena, &s.update),
3291 body: arena.alloc(av_stmt(arena, &s.body)),
3292 uses_alternative: s.uses_alternative,
3293 }
3294}
3295
3296#[inline(never)]
3297fn av_foreach_stmt<'a>(
3298 arena: &'a bumpalo::Bump,
3299 s: &ForeachStmt,
3300) -> arena_ast::ForeachStmt<'a, 'a> {
3301 arena_ast::ForeachStmt {
3302 expr: av_expr(arena, &s.expr),
3303 key: s.key.as_ref().map(|e| av_expr(arena, e)),
3304 value: av_expr(arena, &s.value),
3305 body: arena.alloc(av_stmt(arena, &s.body)),
3306 uses_alternative: s.uses_alternative,
3307 }
3308}
3309
3310#[inline(never)]
3311fn av_do_while_stmt<'a>(
3312 arena: &'a bumpalo::Bump,
3313 s: &DoWhileStmt,
3314) -> arena_ast::DoWhileStmt<'a, 'a> {
3315 arena_ast::DoWhileStmt {
3316 body: arena.alloc(av_stmt(arena, &s.body)),
3317 condition: av_expr(arena, &s.condition),
3318 }
3319}
3320
3321#[inline(never)]
3322fn av_switch_stmt<'a>(arena: &'a bumpalo::Bump, s: &SwitchStmt) -> arena_ast::SwitchStmt<'a, 'a> {
3323 arena_ast::SwitchStmt {
3324 expr: av_expr(arena, &s.expr),
3325 body: {
3326 let mut cases = arena_ast::ArenaVec::with_capacity_in(s.body.cases.len(), arena);
3327 for c in s.body.cases.iter() {
3328 cases.push(arena_ast::SwitchCase {
3329 value: c.value.as_ref().map(|vl| av_expr(arena, vl)),
3330 body: av_stmts(arena, &c.body),
3331 span: c.span,
3332 });
3333 }
3334 arena_ast::SwitchBody {
3335 cases,
3336 span: s.body.span,
3337 }
3338 },
3339 uses_alternative: s.uses_alternative,
3340 }
3341}
3342
3343#[inline(never)]
3344fn av_declare_stmt<'a>(
3345 arena: &'a bumpalo::Bump,
3346 d: &DeclareStmt,
3347) -> arena_ast::DeclareStmt<'a, 'a> {
3348 arena_ast::DeclareStmt {
3349 directives: {
3350 let mut v = arena_ast::ArenaVec::with_capacity_in(d.directives.len(), arena);
3351 for (k, val) in d.directives.iter() {
3352 v.push((arena.alloc_str(k) as &str, av_expr(arena, val)));
3353 }
3354 v
3355 },
3356 body: d.body.as_ref().map(|b| &*arena.alloc(av_stmt(arena, b))),
3357 uses_alternative: d.uses_alternative,
3358 }
3359}
3360
3361#[inline(never)]
3362fn av_try_catch_stmt<'a>(
3363 arena: &'a bumpalo::Bump,
3364 t: &TryCatchStmt,
3365) -> arena_ast::TryCatchStmt<'a, 'a> {
3366 arena_ast::TryCatchStmt {
3367 body: arena.alloc(av_block(arena, &t.body)),
3368 catches: {
3369 let mut v = arena_ast::ArenaVec::with_capacity_in(t.catches.len(), arena);
3370 for c in t.catches.iter() {
3371 let mut types = arena_ast::ArenaVec::with_capacity_in(c.types.len(), arena);
3372 for n in c.types.iter() {
3373 types.push(av_name(arena, n));
3374 }
3375 v.push(arena_ast::CatchClause {
3376 types,
3377 var: c.var.as_deref().map(|s| av_str(arena, s)),
3378 body: arena.alloc(av_block(arena, &c.body)),
3379 span: c.span,
3380 });
3381 }
3382 v
3383 },
3384 finally: t
3385 .finally
3386 .as_deref()
3387 .map(|f| &*arena.alloc(av_block(arena, f))),
3388 finally_kw_span: t.finally_kw_span,
3389 }
3390}
3391
3392#[inline(never)]
3393fn av_namespace_decl<'a>(
3394 arena: &'a bumpalo::Bump,
3395 ns: &NamespaceDecl,
3396) -> arena_ast::NamespaceDecl<'a, 'a> {
3397 arena_ast::NamespaceDecl {
3398 name: ns.name.as_ref().map(|n| av_name(arena, n)),
3399 body: match &ns.body {
3400 NamespaceBody::Braced(block) => {
3401 arena_ast::NamespaceBody::Braced(&*arena.alloc(av_block(arena, block)))
3402 }
3403 NamespaceBody::Simple => arena_ast::NamespaceBody::Simple,
3404 },
3405 }
3406}
3407
3408#[inline(never)]
3409fn av_use_decl<'a>(arena: &'a bumpalo::Bump, u: &UseDecl) -> arena_ast::UseDecl<'a, 'a> {
3410 arena_ast::UseDecl {
3411 kind: u.kind,
3412 uses: {
3413 let mut v = arena_ast::ArenaVec::with_capacity_in(u.uses.len(), arena);
3414 for item in u.uses.iter() {
3415 v.push(arena_ast::UseItem {
3416 name: av_name(arena, &item.name),
3417 alias: item.alias.as_deref().map(|s| av_str(arena, s)),
3418 kind: item.kind,
3419 span: item.span,
3420 });
3421 }
3422 v
3423 },
3424 }
3425}
3426
3427#[inline(never)]
3428fn av_const_items<'a>(
3429 arena: &'a bumpalo::Bump,
3430 items: &[ConstItem],
3431) -> arena_ast::ArenaVec<'a, arena_ast::ConstItem<'a, 'a>> {
3432 let mut v = arena_ast::ArenaVec::with_capacity_in(items.len(), arena);
3433 for item in items.iter() {
3434 v.push(arena_ast::ConstItem {
3435 name: av_ident(arena, &item.name),
3436 value: av_expr(arena, &item.value),
3437 attributes: av_attrs(arena, &item.attributes),
3438 span: item.span,
3439 doc_comment: av_opt_comment(arena, &item.doc_comment),
3440 });
3441 }
3442 v
3443}
3444
3445#[inline(never)]
3446fn av_static_vars<'a>(
3447 arena: &'a bumpalo::Bump,
3448 vars: &[StaticVar],
3449) -> arena_ast::ArenaVec<'a, arena_ast::StaticVar<'a, 'a>> {
3450 let mut v = arena_ast::ArenaVec::with_capacity_in(vars.len(), arena);
3451 for var in vars.iter() {
3452 v.push(arena_ast::StaticVar {
3453 name: av_ident(arena, &var.name),
3454 default: var.default.as_ref().map(|e| av_expr(arena, e)),
3455 span: var.span,
3456 });
3457 }
3458 v
3459}
3460
3461#[inline(never)]
3462fn av_function_decl<'a>(
3463 arena: &'a bumpalo::Bump,
3464 f: &FunctionDecl,
3465) -> arena_ast::FunctionDecl<'a, 'a> {
3466 arena_ast::FunctionDecl {
3467 name: av_ident(arena, &f.name),
3468 params: av_params(arena, &f.params),
3469 body: &*arena.alloc(av_block(arena, &f.body)),
3470 return_type: f.return_type.as_ref().map(|t| av_type_hint(arena, t)),
3471 by_ref: f.by_ref,
3472 attributes: av_attrs(arena, &f.attributes),
3473 doc_comment: av_opt_comment(arena, &f.doc_comment),
3474 }
3475}
3476
3477fn av_class_member<'a>(
3478 arena: &'a bumpalo::Bump,
3479 m: &ClassMember,
3480) -> arena_ast::ClassMember<'a, 'a> {
3481 arena_ast::ClassMember {
3482 kind: match &m.kind {
3483 ClassMemberKind::Property(p) => {
3484 arena_ast::ClassMemberKind::Property(arena_ast::PropertyDecl {
3485 name: av_ident(arena, &p.name),
3486 visibility: p.visibility,
3487 set_visibility: p.set_visibility,
3488 is_static: p.is_static,
3489 is_readonly: p.is_readonly,
3490 type_hint: p.type_hint.as_ref().map(|t| av_type_hint(arena, t)),
3491 default: p.default.as_ref().map(|e| av_expr(arena, e)),
3492 attributes: av_attrs(arena, &p.attributes),
3493 hooks: av_hooks(arena, &p.hooks),
3494 doc_comment: av_opt_comment(arena, &p.doc_comment),
3495 })
3496 }
3497 ClassMemberKind::Method(m) => {
3498 arena_ast::ClassMemberKind::Method(arena_ast::MethodDecl {
3499 name: av_ident(arena, &m.name),
3500 visibility: m.visibility,
3501 is_static: m.is_static,
3502 is_abstract: m.is_abstract,
3503 is_final: m.is_final,
3504 by_ref: m.by_ref,
3505 params: av_params(arena, &m.params),
3506 return_type: m.return_type.as_ref().map(|t| av_type_hint(arena, t)),
3507 body: m.body.as_deref().map(|b| &*arena.alloc(av_block(arena, b))),
3508 attributes: av_attrs(arena, &m.attributes),
3509 doc_comment: av_opt_comment(arena, &m.doc_comment),
3510 })
3511 }
3512 ClassMemberKind::ClassConst(c) => {
3513 arena_ast::ClassMemberKind::ClassConst(av_class_const(arena, c))
3514 }
3515 ClassMemberKind::TraitUse(t) => {
3516 arena_ast::ClassMemberKind::TraitUse(av_trait_use(arena, t))
3517 }
3518 },
3519 span: m.span,
3520 }
3521}
3522
3523fn av_class_members<'a>(
3524 arena: &'a bumpalo::Bump,
3525 members: &[ClassMember],
3526) -> arena_ast::ArenaVec<'a, arena_ast::ClassMember<'a, 'a>> {
3527 let mut v = arena_ast::ArenaVec::with_capacity_in(members.len(), arena);
3528 for m in members.iter() {
3529 v.push(av_class_member(arena, m));
3530 }
3531 v
3532}
3533
3534fn av_class_const<'a>(
3535 arena: &'a bumpalo::Bump,
3536 c: &ClassConstDecl,
3537) -> arena_ast::ClassConstDecl<'a, 'a> {
3538 arena_ast::ClassConstDecl {
3539 name: av_ident(arena, &c.name),
3540 visibility: c.visibility,
3541 is_final: c.is_final,
3542 type_hint: c
3543 .type_hint
3544 .as_ref()
3545 .map(|th| arena.alloc(av_type_hint(arena, th)) as &_),
3546 value: av_expr(arena, &c.value),
3547 attributes: av_attrs(arena, &c.attributes),
3548 doc_comment: av_opt_comment(arena, &c.doc_comment),
3549 }
3550}
3551
3552fn av_trait_use<'a>(arena: &'a bumpalo::Bump, t: &TraitUseDecl) -> arena_ast::TraitUseDecl<'a, 'a> {
3553 let mut traits = arena_ast::ArenaVec::with_capacity_in(t.traits.len(), arena);
3554 for n in t.traits.iter() {
3555 traits.push(av_name(arena, n));
3556 }
3557 let mut adaptations = arena_ast::ArenaVec::with_capacity_in(t.adaptations.len(), arena);
3558 for a in t.adaptations.iter() {
3559 adaptations.push(arena_ast::TraitAdaptation {
3560 kind: match &a.kind {
3561 TraitAdaptationKind::Precedence {
3562 trait_name,
3563 method,
3564 insteadof,
3565 } => {
3566 let mut instead = arena_ast::ArenaVec::with_capacity_in(insteadof.len(), arena);
3567 for n in insteadof.iter() {
3568 instead.push(av_name(arena, n));
3569 }
3570 arena_ast::TraitAdaptationKind::Precedence {
3571 trait_name: av_name(arena, trait_name),
3572 method: av_name(arena, method),
3573 insteadof: instead,
3574 }
3575 }
3576 TraitAdaptationKind::Alias {
3577 trait_name,
3578 method,
3579 new_modifier,
3580 new_name,
3581 } => arena_ast::TraitAdaptationKind::Alias {
3582 trait_name: trait_name.as_ref().map(|n| av_name(arena, n)),
3583 method: av_name(arena, method),
3584 new_modifier: *new_modifier,
3585 new_name: new_name.as_ref().map(|n| av_name(arena, n)),
3586 },
3587 },
3588 span: a.span,
3589 });
3590 }
3591 arena_ast::TraitUseDecl {
3592 traits,
3593 adaptations,
3594 adaptations_brace_span: t.adaptations_brace_span,
3595 doc_comment: av_opt_comment(arena, &t.doc_comment),
3596 }
3597}
3598
3599fn av_class_decl<'a>(arena: &'a bumpalo::Bump, cls: &ClassDecl) -> arena_ast::ClassDecl<'a, 'a> {
3600 let mut implements = arena_ast::ArenaVec::with_capacity_in(cls.implements.len(), arena);
3601 for n in cls.implements.iter() {
3602 implements.push(av_name(arena, n));
3603 }
3604 arena_ast::ClassDecl {
3605 name: cls.name.as_ref().map(|ident| av_ident(arena, ident)),
3606 modifiers: cls.modifiers.clone(),
3607 extends: cls.extends.as_ref().map(|n| av_name(arena, n)),
3608 implements,
3609 body: arena_ast::ClassBody {
3610 members: av_class_members(arena, &cls.body.members),
3611 span: cls.body.span,
3612 },
3613 attributes: av_attrs(arena, &cls.attributes),
3614 doc_comment: av_opt_comment(arena, &cls.doc_comment),
3615 }
3616}
3617
3618#[inline(never)]
3619fn av_interface_decl<'a>(
3620 arena: &'a bumpalo::Bump,
3621 iface: &InterfaceDecl,
3622) -> arena_ast::InterfaceDecl<'a, 'a> {
3623 let mut extends = arena_ast::ArenaVec::with_capacity_in(iface.extends.len(), arena);
3624 for n in iface.extends.iter() {
3625 extends.push(av_name(arena, n));
3626 }
3627 arena_ast::InterfaceDecl {
3628 name: av_ident(arena, &iface.name),
3629 extends,
3630 body: arena_ast::ClassBody {
3631 members: av_class_members(arena, &iface.body.members),
3632 span: iface.body.span,
3633 },
3634 attributes: av_attrs(arena, &iface.attributes),
3635 doc_comment: av_opt_comment(arena, &iface.doc_comment),
3636 }
3637}
3638
3639#[inline(never)]
3640fn av_trait_decl<'a>(arena: &'a bumpalo::Bump, tr: &TraitDecl) -> arena_ast::TraitDecl<'a, 'a> {
3641 arena_ast::TraitDecl {
3642 name: av_ident(arena, &tr.name),
3643 body: arena_ast::ClassBody {
3644 members: av_class_members(arena, &tr.body.members),
3645 span: tr.body.span,
3646 },
3647 attributes: av_attrs(arena, &tr.attributes),
3648 doc_comment: av_opt_comment(arena, &tr.doc_comment),
3649 }
3650}
3651
3652#[inline(never)]
3653fn av_enum_decl<'a>(arena: &'a bumpalo::Bump, en: &EnumDecl) -> arena_ast::EnumDecl<'a, 'a> {
3654 let mut implements = arena_ast::ArenaVec::with_capacity_in(en.implements.len(), arena);
3655 for n in en.implements.iter() {
3656 implements.push(av_name(arena, n));
3657 }
3658 let mut members = arena_ast::ArenaVec::with_capacity_in(en.body.members.len(), arena);
3659 for m in en.body.members.iter() {
3660 members.push(arena_ast::EnumMember {
3661 kind: match &m.kind {
3662 EnumMemberKind::Case(c) => arena_ast::EnumMemberKind::Case(arena_ast::EnumCase {
3663 name: av_ident(arena, &c.name),
3664 value: c.value.as_ref().map(|e| av_expr(arena, e)),
3665 attributes: av_attrs(arena, &c.attributes),
3666 doc_comment: av_opt_comment(arena, &c.doc_comment),
3667 }),
3668 EnumMemberKind::Method(m) => {
3669 arena_ast::EnumMemberKind::Method(arena_ast::MethodDecl {
3670 name: av_ident(arena, &m.name),
3671 visibility: m.visibility,
3672 is_static: m.is_static,
3673 is_abstract: m.is_abstract,
3674 is_final: m.is_final,
3675 by_ref: m.by_ref,
3676 params: av_params(arena, &m.params),
3677 return_type: m.return_type.as_ref().map(|t| av_type_hint(arena, t)),
3678 body: m.body.as_deref().map(|b| &*arena.alloc(av_block(arena, b))),
3679 attributes: av_attrs(arena, &m.attributes),
3680 doc_comment: av_opt_comment(arena, &m.doc_comment),
3681 })
3682 }
3683 EnumMemberKind::ClassConst(c) => {
3684 arena_ast::EnumMemberKind::ClassConst(av_class_const(arena, c))
3685 }
3686 EnumMemberKind::TraitUse(t) => {
3687 arena_ast::EnumMemberKind::TraitUse(av_trait_use(arena, t))
3688 }
3689 },
3690 span: m.span,
3691 });
3692 }
3693 arena_ast::EnumDecl {
3694 name: av_ident(arena, &en.name),
3695 scalar_type: en.scalar_type.as_ref().map(|n| av_name(arena, n)),
3696 implements,
3697 body: arena_ast::EnumBody {
3698 members,
3699 span: en.body.span,
3700 },
3701 attributes: av_attrs(arena, &en.attributes),
3702 doc_comment: av_opt_comment(arena, &en.doc_comment),
3703 }
3704}