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