1pub mod fold;
21pub mod visitor;
22
23pub use fold::{
24 fold_owned_arg, fold_owned_attribute, fold_owned_block, fold_owned_catch_clause,
25 fold_owned_class_member, fold_owned_closure_use_var, fold_owned_enum_member, fold_owned_expr,
26 fold_owned_match_arm, fold_owned_name, fold_owned_param, fold_owned_program,
27 fold_owned_property_hook, fold_owned_stmt, fold_owned_trait_adaptation, fold_owned_trait_use,
28 fold_owned_type_hint, OwnedFold,
29};
30pub use visitor::{
31 walk_owned_arg, walk_owned_attribute, walk_owned_block, walk_owned_catch_clause,
32 walk_owned_class_member, walk_owned_comments, walk_owned_enum_member, walk_owned_expr,
33 walk_owned_match_arm, walk_owned_name, walk_owned_param, walk_owned_program,
34 walk_owned_property_hook, walk_owned_stmt, walk_owned_trait_adaptation, walk_owned_trait_use,
35 walk_owned_type_hint, OwnedScope, OwnedScopeVisitor, 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, Modifiers, NameKind, PropertyHookKind, UnaryPostfixOp, UnaryPrefixOp, UseKind,
47 Visibility,
48};
49use crate::Span;
50
51#[cfg(feature = "serde")]
56fn is_false(b: &bool) -> bool {
57 !*b
58}
59
60#[cfg(feature = "serde")]
61fn slice_is_empty<T>(v: &[T]) -> bool {
62 v.is_empty()
63}
64
65#[derive(Clone, PartialEq, Eq, Hash)]
67pub struct Ident {
68 name: Option<Box<str>>,
69 pub span: Span,
71}
72
73impl Ident {
74 pub fn new(name: impl Into<Box<str>>, span: Span) -> Self {
76 let name = name.into();
77 debug_assert!(!name.is_empty(), "Ident::new() called with empty name");
78 Self {
79 name: Some(name),
80 span,
81 }
82 }
83
84 pub const fn error(span: Span) -> Self {
86 Self { name: None, span }
87 }
88
89 pub fn as_str(&self) -> Option<&str> {
91 self.name.as_deref()
92 }
93
94 pub fn is_error(&self) -> bool {
96 self.name.is_none()
97 }
98
99 pub fn or_error(&self) -> &str {
101 self.name.as_deref().unwrap_or("<error>")
102 }
103}
104
105impl fmt::Debug for Ident {
106 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
107 match &self.name {
108 Some(s) => write!(f, "Ident({:?}, {:?})", s, self.span),
109 None => write!(f, "Ident::error({:?})", self.span),
110 }
111 }
112}
113
114impl fmt::Display for Ident {
115 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
116 f.write_str(self.or_error())
117 }
118}
119
120#[cfg(feature = "serde")]
121impl Serialize for Ident {
122 fn serialize<S: serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
123 use serde::ser::SerializeStruct;
124 let Some(name) = &self.name else {
125 return s.serialize_none();
126 };
127 let mut st = s.serialize_struct("Ident", 2)?;
128 st.serialize_field("name", name)?;
129 st.serialize_field("span", &self.span)?;
130 st.end()
131 }
132}
133
134impl PartialEq<&str> for Ident {
135 fn eq(&self, other: &&str) -> bool {
136 self.as_str() == Some(*other)
137 }
138}
139
140#[derive(Debug, Clone)]
151#[cfg_attr(feature = "serde", derive(Serialize))]
152pub struct Name {
153 pub parts: Box<[Box<str>]>,
155 pub kind: NameKind,
157 pub span: Span,
159}
160
161impl Name {
162 pub fn span(&self) -> Span {
164 self.span
165 }
166
167 pub fn kind(&self) -> NameKind {
169 self.kind
170 }
171
172 pub fn to_string_repr(&self) -> String {
174 let joined = self.join_parts();
175 if self.kind == NameKind::FullyQualified {
176 format!("\\{joined}")
177 } else {
178 joined
179 }
180 }
181
182 pub fn join_parts(&self) -> String {
184 self.parts.join("\\")
185 }
186}
187
188#[derive(Clone, PartialEq, Eq, Hash)]
196pub struct ByteString(Box<[u8]>);
197
198impl ByteString {
199 pub fn as_bytes(&self) -> &[u8] {
201 &self.0
202 }
203
204 pub fn to_str(&self) -> Option<&str> {
206 std::str::from_utf8(&self.0).ok()
207 }
208
209 pub fn to_string_lossy(&self) -> std::borrow::Cow<'_, str> {
211 String::from_utf8_lossy(&self.0)
212 }
213
214 pub fn into_bytes(self) -> Box<[u8]> {
216 self.0
217 }
218}
219
220impl std::ops::Deref for ByteString {
221 type Target = [u8];
222 fn deref(&self) -> &[u8] {
223 &self.0
224 }
225}
226
227impl From<&str> for ByteString {
228 fn from(s: &str) -> Self {
229 Self(s.as_bytes().into())
230 }
231}
232
233impl From<String> for ByteString {
234 fn from(s: String) -> Self {
235 Self(s.into_bytes().into_boxed_slice())
236 }
237}
238
239impl From<&[u8]> for ByteString {
240 fn from(b: &[u8]) -> Self {
241 Self(b.into())
242 }
243}
244
245impl From<Vec<u8>> for ByteString {
246 fn from(b: Vec<u8>) -> Self {
247 Self(b.into_boxed_slice())
248 }
249}
250
251impl PartialEq<str> for ByteString {
252 fn eq(&self, other: &str) -> bool {
253 &*self.0 == other.as_bytes()
254 }
255}
256
257impl PartialEq<&str> for ByteString {
258 fn eq(&self, other: &&str) -> bool {
259 &*self.0 == other.as_bytes()
260 }
261}
262
263impl std::fmt::Debug for ByteString {
264 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
265 match self.to_str() {
266 Some(s) => std::fmt::Debug::fmt(s, f),
267 None => write!(f, "b{:?}", self.0.escape_ascii().to_string()),
268 }
269 }
270}
271
272#[cfg(feature = "serde")]
273impl Serialize for ByteString {
274 fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
275 crate::ast::serialize_bytes(&self.0, serializer)
276 }
277}
278
279#[derive(Debug, Clone)]
285#[cfg_attr(feature = "serde", derive(Serialize))]
286pub struct Comment {
287 pub kind: CommentKind,
289 pub text: Box<str>,
291 pub span: Span,
293}
294
295#[derive(Debug, Clone)]
304#[cfg_attr(feature = "serde", derive(Serialize))]
305pub struct TypeHint {
306 pub kind: TypeHintKind,
308 pub span: Span,
310}
311
312#[derive(Debug, Clone)]
314#[non_exhaustive]
315pub enum TypeHintKind {
316 Named(Name),
318 Keyword(BuiltinType, Span),
320 Nullable(Box<TypeHint>),
322 Union(Box<[TypeHint]>),
324 Intersection(Box<[TypeHint]>),
326}
327
328#[cfg(feature = "serde")]
329impl Serialize for TypeHintKind {
330 fn serialize<S: serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
331 match self {
332 Self::Named(name) => s.serialize_newtype_variant("TypeHintKind", 0, "Named", name),
333 Self::Nullable(inner) => {
334 s.serialize_newtype_variant("TypeHintKind", 2, "Nullable", inner)
335 }
336 Self::Union(types) => s.serialize_newtype_variant("TypeHintKind", 3, "Union", types),
337 Self::Intersection(types) => {
338 s.serialize_newtype_variant("TypeHintKind", 4, "Intersection", types)
339 }
340 Self::Keyword(builtin, span) => {
341 struct BuiltinNameRepr<'a>(&'a BuiltinType, &'a Span);
342 impl Serialize for BuiltinNameRepr<'_> {
343 fn serialize<S: serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
344 use serde::ser::SerializeStruct;
345 let mut st = s.serialize_struct("Name", 3)?;
346 st.serialize_field("parts", &[self.0.as_str()])?;
347 st.serialize_field("kind", &NameKind::Unqualified)?;
348 st.serialize_field("span", self.1)?;
349 st.end()
350 }
351 }
352 s.serialize_newtype_variant(
353 "TypeHintKind",
354 0,
355 "Named",
356 &BuiltinNameRepr(builtin, span),
357 )
358 }
359 }
360 }
361}
362
363#[derive(Debug, Clone)]
369#[cfg_attr(feature = "serde", derive(Serialize))]
370#[non_exhaustive]
371pub struct Arg {
372 pub name: Option<Name>,
374 pub kind: ArgKind,
376 pub span: Span,
378}
379
380impl Arg {
381 pub fn new(name: Option<Name>, kind: ArgKind, span: Span) -> Self {
384 Self { name, kind, span }
385 }
386}
387
388#[derive(Debug, Clone)]
390#[cfg_attr(feature = "serde", derive(Serialize))]
391#[non_exhaustive]
392pub enum ArgKind {
393 Value(Expr),
395 Spread(Expr),
397 ByRef(Expr),
399 Placeholder,
401 SpreadPlaceholder,
403}
404
405impl Arg {
406 pub fn value(&self) -> Option<&Expr> {
408 match &self.kind {
409 ArgKind::Value(e) | ArgKind::Spread(e) | ArgKind::ByRef(e) => Some(e),
410 ArgKind::Placeholder | ArgKind::SpreadPlaceholder => None,
411 }
412 }
413
414 pub fn value_mut(&mut self) -> Option<&mut Expr> {
416 match &mut self.kind {
417 ArgKind::Value(e) | ArgKind::Spread(e) | ArgKind::ByRef(e) => Some(e),
418 ArgKind::Placeholder | ArgKind::SpreadPlaceholder => None,
419 }
420 }
421
422 pub fn is_spread(&self) -> bool {
424 matches!(self.kind, ArgKind::Spread(_))
425 }
426
427 pub fn is_placeholder(&self) -> bool {
429 matches!(self.kind, ArgKind::Placeholder | ArgKind::SpreadPlaceholder)
430 }
431}
432
433#[derive(Debug, Clone)]
435#[cfg_attr(feature = "serde", derive(Serialize))]
436#[non_exhaustive]
437pub struct Attribute {
438 pub name: Name,
440 pub args: Box<[Arg]>,
442 pub span: Span,
444}
445
446impl Attribute {
447 pub fn new(name: Name, span: Span) -> Self {
450 Self {
451 name,
452 args: Box::new([]),
453 span,
454 }
455 }
456}
457
458#[derive(Debug, Clone)]
464#[cfg_attr(feature = "serde", derive(Serialize))]
465pub struct Program {
466 pub stmts: Box<[Stmt]>,
468 pub span: Span,
470}
471
472#[derive(Debug, Clone)]
478#[cfg_attr(feature = "serde", derive(Serialize))]
479pub struct Stmt {
480 pub kind: StmtKind,
482 pub span: Span,
484 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
486 pub doc_comment: Option<Comment>,
487}
488
489impl Stmt {
490 pub fn leading_doc_comment(&self) -> Option<&Comment> {
494 if let Some(doc) = &self.doc_comment {
495 return Some(doc);
496 }
497 match &self.kind {
498 StmtKind::Function(f) => f.doc_comment.as_ref(),
499 StmtKind::Class(c) => c.doc_comment.as_ref(),
500 StmtKind::Interface(i) => i.doc_comment.as_ref(),
501 StmtKind::Trait(t) => t.doc_comment.as_ref(),
502 StmtKind::Enum(e) => e.doc_comment.as_ref(),
503 StmtKind::Const(items) => items.first().and_then(|i| i.doc_comment.as_ref()),
504 _ => None,
505 }
506 }
507}
508
509#[derive(Debug, Clone)]
511#[cfg_attr(feature = "serde", derive(Serialize))]
512#[cfg_attr(feature = "serde", serde(transparent))]
513pub struct Block {
514 pub stmts: Box<[Stmt]>,
516 #[cfg_attr(feature = "serde", serde(skip))]
518 pub span: Span,
519}
520
521#[derive(Debug, Clone)]
523#[cfg_attr(feature = "serde", derive(Serialize))]
524#[non_exhaustive]
525pub enum StmtKind {
526 Expression(Box<Expr>),
528 Echo(Box<[Expr]>),
530 Return(Option<Box<Expr>>),
532 Block(Box<Block>),
534 If(Box<IfStmt>),
536 While(Box<WhileStmt>),
538 For(Box<ForStmt>),
540 Foreach(Box<ForeachStmt>),
542 DoWhile(Box<DoWhileStmt>),
544 Function(Box<FunctionDecl>),
546 Break(Option<Box<Expr>>),
548 Continue(Option<Box<Expr>>),
550 Switch(Box<SwitchStmt>),
552 Goto(Ident),
554 Label(Ident),
556 Declare(Box<DeclareStmt>),
558 Unset(Box<[Expr]>),
560 Throw(Box<Expr>),
562 TryCatch(Box<TryCatchStmt>),
564 Global(Box<[Expr]>),
566 Class(Box<ClassDecl>),
568 Interface(Box<InterfaceDecl>),
570 Trait(Box<TraitDecl>),
572 Enum(Box<EnumDecl>),
574 Namespace(Box<NamespaceDecl>),
576 Use(Box<UseDecl>),
578 Const(Box<[ConstItem]>),
580 StaticVar(Box<[StaticVar]>),
582 HaltCompiler(Box<str>),
584 Nop,
586 InlineHtml(Box<str>),
588 Error,
590}
591
592#[derive(Debug, Clone)]
594#[cfg_attr(feature = "serde", derive(Serialize))]
595#[non_exhaustive]
596pub struct IfStmt {
597 pub condition: Expr,
599 pub then_branch: Box<Stmt>,
601 pub elseif_branches: Box<[ElseIfBranch]>,
603 pub else_branch: Option<Box<Stmt>>,
605 #[cfg_attr(feature = "serde", serde(skip))]
607 #[doc(hidden)]
608 pub else_kw_span: Option<Span>,
609 #[cfg_attr(feature = "serde", serde(default, skip_serializing_if = "is_false"))]
611 pub uses_alternative: bool,
612}
613
614impl IfStmt {
615 pub fn new(condition: Expr, then_branch: Box<Stmt>) -> Self {
618 Self {
619 condition,
620 then_branch,
621 elseif_branches: Box::new([]),
622 else_branch: None,
623 else_kw_span: None,
624 uses_alternative: false,
625 }
626 }
627}
628
629#[derive(Debug, Clone)]
631#[cfg_attr(feature = "serde", derive(Serialize))]
632pub struct ElseIfBranch {
633 pub condition: Expr,
635 pub body: Stmt,
637 pub span: Span,
639}
640
641#[derive(Debug, Clone)]
643#[cfg_attr(feature = "serde", derive(Serialize))]
644#[non_exhaustive]
645pub struct WhileStmt {
646 pub condition: Expr,
648 pub body: Box<Stmt>,
650 #[cfg_attr(feature = "serde", serde(default, skip_serializing_if = "is_false"))]
652 pub uses_alternative: bool,
653}
654
655impl WhileStmt {
656 pub fn new(condition: Expr, body: Box<Stmt>) -> Self {
659 Self {
660 condition,
661 body,
662 uses_alternative: false,
663 }
664 }
665}
666
667#[derive(Debug, Clone)]
669#[cfg_attr(feature = "serde", derive(Serialize))]
670#[non_exhaustive]
671pub struct ForStmt {
672 pub init: Box<[Expr]>,
674 pub condition: Box<[Expr]>,
676 pub update: Box<[Expr]>,
678 pub body: Box<Stmt>,
680 #[cfg_attr(feature = "serde", serde(default, skip_serializing_if = "is_false"))]
682 pub uses_alternative: bool,
683}
684
685impl ForStmt {
686 pub fn new(body: Box<Stmt>) -> Self {
689 Self {
690 init: Box::new([]),
691 condition: Box::new([]),
692 update: Box::new([]),
693 body,
694 uses_alternative: false,
695 }
696 }
697}
698
699#[derive(Debug, Clone)]
701#[cfg_attr(feature = "serde", derive(Serialize))]
702#[non_exhaustive]
703pub struct ForeachStmt {
704 pub expr: Expr,
706 pub key: Option<Expr>,
708 pub value: Expr,
710 #[cfg_attr(feature = "serde", serde(default, skip_serializing_if = "is_false"))]
712 pub by_ref: bool,
713 pub body: Box<Stmt>,
715 #[cfg_attr(feature = "serde", serde(default, skip_serializing_if = "is_false"))]
717 pub uses_alternative: bool,
718}
719
720impl ForeachStmt {
721 pub fn new(expr: Expr, value: Expr, body: Box<Stmt>) -> Self {
724 Self {
725 expr,
726 key: None,
727 value,
728 by_ref: false,
729 body,
730 uses_alternative: false,
731 }
732 }
733}
734
735#[derive(Debug, Clone)]
737#[cfg_attr(feature = "serde", derive(Serialize))]
738#[non_exhaustive]
739pub struct DoWhileStmt {
740 pub body: Box<Stmt>,
742 pub condition: Expr,
744}
745
746impl DoWhileStmt {
747 pub fn new(body: Box<Stmt>, condition: Expr) -> Self {
750 Self { body, condition }
751 }
752}
753
754#[derive(Debug, Clone)]
756#[cfg_attr(feature = "serde", derive(Serialize))]
757pub struct SwitchBody {
758 pub cases: Box<[SwitchCase]>,
760 #[cfg_attr(feature = "serde", serde(skip))]
762 pub span: Span,
763}
764
765#[derive(Debug, Clone)]
767#[cfg_attr(feature = "serde", derive(Serialize))]
768#[non_exhaustive]
769pub struct SwitchStmt {
770 pub expr: Expr,
772 #[cfg_attr(feature = "serde", serde(flatten))]
774 pub body: SwitchBody,
775 #[cfg_attr(feature = "serde", serde(default, skip_serializing_if = "is_false"))]
777 pub uses_alternative: bool,
778}
779
780impl SwitchStmt {
781 pub fn new(expr: Expr, body: SwitchBody) -> Self {
784 Self {
785 expr,
786 body,
787 uses_alternative: false,
788 }
789 }
790}
791
792#[derive(Debug, Clone)]
794#[cfg_attr(feature = "serde", derive(Serialize))]
795pub struct SwitchCase {
796 pub value: Option<Expr>,
798 pub body: Box<[Stmt]>,
800 pub span: Span,
802}
803
804#[derive(Debug, Clone)]
806#[cfg_attr(feature = "serde", derive(Serialize))]
807#[non_exhaustive]
808pub struct TryCatchStmt {
809 pub body: Box<Block>,
811 pub catches: Box<[CatchClause]>,
813 pub finally: Option<Box<Block>>,
815 #[cfg_attr(feature = "serde", serde(skip))]
817 #[doc(hidden)]
818 pub finally_kw_span: Option<Span>,
819}
820
821impl TryCatchStmt {
822 pub fn new(body: Box<Block>) -> Self {
825 Self {
826 body,
827 catches: Box::new([]),
828 finally: None,
829 finally_kw_span: None,
830 }
831 }
832}
833
834#[derive(Debug, Clone)]
836#[cfg_attr(feature = "serde", derive(Serialize))]
837#[non_exhaustive]
838pub struct CatchClause {
839 pub types: Box<[Name]>,
841 pub var: Option<Ident>,
843 pub body: Box<Block>,
845 pub span: Span,
847}
848
849impl CatchClause {
850 pub fn new(body: Box<Block>, span: Span) -> Self {
853 Self {
854 types: Box::new([]),
855 var: None,
856 body,
857 span,
858 }
859 }
860}
861
862#[derive(Debug, Clone)]
864#[cfg_attr(feature = "serde", derive(Serialize))]
865#[non_exhaustive]
866pub struct NamespaceDecl {
867 pub name: Option<Name>,
869 pub body: NamespaceBody,
871}
872
873impl NamespaceDecl {
874 pub fn new(name: Option<Name>, body: NamespaceBody) -> Self {
877 Self { name, body }
878 }
879}
880
881#[derive(Debug, Clone)]
883#[cfg_attr(feature = "serde", derive(Serialize))]
884#[non_exhaustive]
885pub enum NamespaceBody {
886 Braced(Box<Block>),
888 Simple,
890}
891
892#[derive(Debug, Clone)]
894#[cfg_attr(feature = "serde", derive(Serialize))]
895#[non_exhaustive]
896pub struct DeclareStmt {
897 pub directives: Box<[(Box<str>, Expr)]>,
899 pub body: Option<Box<Stmt>>,
901 #[cfg_attr(feature = "serde", serde(default, skip_serializing_if = "is_false"))]
903 pub uses_alternative: bool,
904}
905
906impl DeclareStmt {
907 pub fn new(directives: Box<[(Box<str>, Expr)]>) -> Self {
910 Self {
911 directives,
912 body: None,
913 uses_alternative: false,
914 }
915 }
916}
917
918#[derive(Debug, Clone)]
920#[cfg_attr(feature = "serde", derive(Serialize))]
921#[non_exhaustive]
922pub struct UseDecl {
923 pub kind: UseKind,
925 pub uses: Box<[UseItem]>,
927}
928
929impl UseDecl {
930 pub fn new(kind: UseKind, uses: Box<[UseItem]>) -> Self {
933 Self { kind, uses }
934 }
935}
936
937#[derive(Debug, Clone)]
939#[cfg_attr(feature = "serde", derive(Serialize))]
940pub struct UseItem {
941 pub name: Name,
943 pub alias: Option<Ident>,
945 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
947 pub kind: Option<UseKind>,
948 pub span: Span,
950}
951
952#[derive(Debug, Clone)]
954#[cfg_attr(feature = "serde", derive(Serialize))]
955pub struct ConstItem {
956 pub name: Ident,
958 pub value: Expr,
960 pub attributes: Box<[Attribute]>,
962 pub span: Span,
964 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
966 pub doc_comment: Option<Comment>,
967}
968
969#[derive(Debug, Clone)]
971#[cfg_attr(feature = "serde", derive(Serialize))]
972pub struct StaticVar {
973 pub name: Ident,
975 pub default: Option<Expr>,
977 pub span: Span,
979}
980
981#[derive(Debug, Clone)]
991#[cfg_attr(feature = "serde", derive(Serialize))]
992pub struct Expr {
993 pub kind: ExprKind,
995 pub span: Span,
997}
998
999impl Expr {
1000 pub fn name_str(&self) -> Option<&str> {
1002 match &self.kind {
1003 ExprKind::Variable(s) | ExprKind::Identifier(s) => Some(s),
1004 _ => None,
1005 }
1006 }
1007
1008 pub fn into_kind(mut self) -> ExprKind {
1010 std::mem::replace(&mut self.kind, ExprKind::Error)
1011 }
1012}
1013
1014#[derive(Debug, Clone)]
1016#[cfg_attr(feature = "serde", derive(Serialize))]
1017#[non_exhaustive]
1018pub enum ExprKind {
1019 Int(i64),
1021 Float(f64),
1023 String(ByteString),
1025 InterpolatedString(Box<[StringPart]>),
1027 Heredoc {
1029 label: Box<str>,
1031 parts: Box<[StringPart]>,
1033 },
1034 Nowdoc {
1036 label: Box<str>,
1038 value: Box<str>,
1040 },
1041 ShellExec(Box<[StringPart]>),
1043 Bool(bool),
1045 Null,
1047 Variable(Box<str>),
1049 VariableVariable(Box<Expr>),
1051 Identifier(Box<str>),
1053 Name(Name),
1055 Assign(AssignExpr),
1057 Binary(BinaryExpr),
1059 UnaryPrefix(UnaryPrefixExpr),
1061 UnaryPostfix(UnaryPostfixExpr),
1063 Ternary(TernaryExpr),
1065 NullCoalesce(NullCoalesceExpr),
1067 FunctionCall(FunctionCallExpr),
1069 Array(Box<[ArrayElement]>),
1071 ArrayAccess(ArrayAccessExpr),
1073 Print(Box<Expr>),
1075 Parenthesized(Box<Expr>),
1077 Cast(CastKind, Box<Expr>),
1079 ErrorSuppress(Box<Expr>),
1081 Isset(Box<[Expr]>),
1083 Empty(Box<Expr>),
1085 Include(IncludeKind, Box<Expr>),
1087 Eval(Box<Expr>),
1089 Exit(Option<Box<Expr>>),
1091 MagicConst(MagicConstKind),
1093 Clone(Box<Expr>),
1095 CloneWith(Box<Expr>, Box<Expr>),
1097 New(NewExpr),
1099 PropertyAccess(PropertyAccessExpr),
1101 NullsafePropertyAccess(PropertyAccessExpr),
1103 MethodCall(Box<MethodCallExpr>),
1105 NullsafeMethodCall(Box<MethodCallExpr>),
1107 StaticPropertyAccess(StaticAccessExpr),
1109 StaticMethodCall(Box<StaticMethodCallExpr>),
1111 StaticMethodCallDynamic(Box<StaticMethodCallDynamicExpr>),
1113 ClassConstAccess(StaticAccessExpr),
1115 ClassConstAccessDynamic {
1117 class: Box<Expr>,
1119 member: Box<Expr>,
1121 },
1122 StaticPropertyAccessDynamic {
1124 class: Box<Expr>,
1126 member: Box<Expr>,
1128 },
1129 Closure(Box<ClosureExpr>),
1131 ArrowFunction(Box<ArrowFunctionExpr>),
1133 Match(MatchExpr),
1135 Throw(Box<Expr>),
1137 Yield(YieldExpr),
1139 AnonymousClass(Box<ClassDecl>),
1141 CallableCreate(CallableCreateExpr),
1143 Omit,
1145 Error,
1147}
1148
1149impl Drop for Expr {
1163 #[inline(always)]
1164 fn drop(&mut self) {
1165 if owned_is_chain(&self.kind) {
1167 unlink_chain(&mut self.kind);
1168 }
1169 }
1170}
1171
1172#[inline(never)]
1174fn unlink_chain(kind: &mut ExprKind) {
1175 let Some(operand) = owned_chain_operand_mut(kind) else {
1176 return;
1177 };
1178 if !owned_is_chain(&operand.kind) {
1180 return;
1181 }
1182 let mut kind = std::mem::replace(&mut operand.kind, ExprKind::Error);
1185 while let Some(operand) = owned_chain_operand_mut(&mut kind) {
1186 let next = std::mem::replace(&mut operand.kind, ExprKind::Error);
1187 kind = next;
1188 }
1189}
1190
1191struct LinkStack<T: Copy> {
1194 inline: [Option<T>; 8],
1195 len: usize,
1196 spilled: Vec<T>,
1197}
1198
1199impl<T: Copy> LinkStack<T> {
1200 fn new() -> Self {
1201 Self {
1202 inline: [None; 8],
1203 len: 0,
1204 spilled: Vec::new(),
1205 }
1206 }
1207
1208 fn push(&mut self, link: T) {
1209 if self.len < self.inline.len() {
1210 self.inline[self.len] = Some(link);
1211 self.len += 1;
1212 } else {
1213 self.spilled.push(link);
1214 }
1215 }
1216
1217 fn pop(&mut self) -> Option<T> {
1218 if let Some(link) = self.spilled.pop() {
1219 return Some(link);
1220 }
1221 self.len = self.len.checked_sub(1)?;
1222 self.inline[self.len]
1223 }
1224}
1225
1226#[inline]
1229fn arena_is_chain(k: &arena_ast::ExprKind<'_, '_>) -> bool {
1230 matches!(
1231 k,
1232 arena_ast::ExprKind::Assign(_)
1233 | arena_ast::ExprKind::Binary(_)
1234 | arena_ast::ExprKind::UnaryPrefix(_)
1235 | arena_ast::ExprKind::UnaryPostfix(_)
1236 | arena_ast::ExprKind::Ternary(_)
1237 | arena_ast::ExprKind::NullCoalesce(_)
1238 | arena_ast::ExprKind::FunctionCall(_)
1239 | arena_ast::ExprKind::ArrayAccess(_)
1240 | arena_ast::ExprKind::PropertyAccess(_)
1241 | arena_ast::ExprKind::NullsafePropertyAccess(_)
1242 | arena_ast::ExprKind::MethodCall(_)
1243 | arena_ast::ExprKind::NullsafeMethodCall(_)
1244 | arena_ast::ExprKind::StaticPropertyAccess(_)
1245 | arena_ast::ExprKind::ClassConstAccess(_)
1246 | arena_ast::ExprKind::StaticMethodCall(_)
1247 | arena_ast::ExprKind::StaticMethodCallDynamic(_)
1248 | arena_ast::ExprKind::ClassConstAccessDynamic { .. }
1249 | arena_ast::ExprKind::StaticPropertyAccessDynamic { .. }
1250 | arena_ast::ExprKind::CallableCreate(_)
1251 )
1252}
1253
1254#[inline]
1256fn owned_is_chain(k: &ExprKind) -> bool {
1257 matches!(
1258 k,
1259 ExprKind::Assign(_)
1260 | ExprKind::Binary(_)
1261 | ExprKind::UnaryPrefix(_)
1262 | ExprKind::UnaryPostfix(_)
1263 | ExprKind::Ternary(_)
1264 | ExprKind::NullCoalesce(_)
1265 | ExprKind::FunctionCall(_)
1266 | ExprKind::ArrayAccess(_)
1267 | ExprKind::PropertyAccess(_)
1268 | ExprKind::NullsafePropertyAccess(_)
1269 | ExprKind::MethodCall(_)
1270 | ExprKind::NullsafeMethodCall(_)
1271 | ExprKind::StaticPropertyAccess(_)
1272 | ExprKind::ClassConstAccess(_)
1273 | ExprKind::StaticMethodCall(_)
1274 | ExprKind::StaticMethodCallDynamic(_)
1275 | ExprKind::ClassConstAccessDynamic { .. }
1276 | ExprKind::StaticPropertyAccessDynamic { .. }
1277 | ExprKind::CallableCreate(_)
1278 )
1279}
1280
1281#[inline]
1282fn arena_chain_operand<'a, 'arena, 'src>(
1283 k: &'a arena_ast::ExprKind<'arena, 'src>,
1284) -> Option<&'a arena_ast::Expr<'arena, 'src>> {
1285 use arena_ast::{CallableCreateKind as C, ExprKind as K};
1286 match k {
1287 K::Assign(a) => Some(a.target),
1288 K::Binary(b) => Some(b.left),
1289 K::UnaryPrefix(u) => Some(u.operand),
1290 K::UnaryPostfix(u) => Some(u.operand),
1291 K::Ternary(t) => Some(t.condition),
1292 K::NullCoalesce(n) => Some(n.left),
1293 K::FunctionCall(f) => Some(f.name),
1294 K::ArrayAccess(a) => Some(a.array),
1295 K::PropertyAccess(p) | K::NullsafePropertyAccess(p) => Some(p.object),
1296 K::MethodCall(m) | K::NullsafeMethodCall(m) => Some(m.object),
1297 K::StaticPropertyAccess(s) | K::ClassConstAccess(s) => Some(s.class),
1298 K::StaticMethodCall(s) => Some(s.class),
1299 K::StaticMethodCallDynamic(s) => Some(s.class),
1300 K::ClassConstAccessDynamic { class, .. } | K::StaticPropertyAccessDynamic { class, .. } => {
1301 Some(class)
1302 }
1303 K::CallableCreate(c) => Some(match &c.kind {
1304 C::Function(e) => e,
1305 C::Method { object, .. } | C::NullsafeMethod { object, .. } => object,
1306 C::StaticMethod { class, .. } => class,
1307 }),
1308 _ => None,
1309 }
1310}
1311
1312#[inline]
1313fn owned_chain_operand(k: &ExprKind) -> Option<&Expr> {
1314 use CallableCreateKind as C;
1315 match k {
1316 ExprKind::Assign(a) => Some(&a.target),
1317 ExprKind::Binary(b) => Some(&b.left),
1318 ExprKind::UnaryPrefix(u) => Some(&u.operand),
1319 ExprKind::UnaryPostfix(u) => Some(&u.operand),
1320 ExprKind::Ternary(t) => Some(&t.condition),
1321 ExprKind::NullCoalesce(n) => Some(&n.left),
1322 ExprKind::FunctionCall(f) => Some(&f.name),
1323 ExprKind::ArrayAccess(a) => Some(&a.array),
1324 ExprKind::PropertyAccess(p) | ExprKind::NullsafePropertyAccess(p) => Some(&p.object),
1325 ExprKind::MethodCall(m) | ExprKind::NullsafeMethodCall(m) => Some(&m.object),
1326 ExprKind::StaticPropertyAccess(s) | ExprKind::ClassConstAccess(s) => Some(&s.class),
1327 ExprKind::StaticMethodCall(s) => Some(&s.class),
1328 ExprKind::StaticMethodCallDynamic(s) => Some(&s.class),
1329 ExprKind::ClassConstAccessDynamic { class, .. }
1330 | ExprKind::StaticPropertyAccessDynamic { class, .. } => Some(class),
1331 ExprKind::CallableCreate(c) => Some(match &c.kind {
1332 C::Function(e) => e,
1333 C::Method { object, .. } | C::NullsafeMethod { object, .. } => object,
1334 C::StaticMethod { class, .. } => class,
1335 }),
1336 _ => None,
1337 }
1338}
1339
1340#[inline]
1341fn owned_chain_operand_mut(k: &mut ExprKind) -> Option<&mut Expr> {
1342 use CallableCreateKind as C;
1343 match k {
1344 ExprKind::Assign(a) => Some(&mut a.target),
1345 ExprKind::Binary(b) => Some(&mut b.left),
1346 ExprKind::UnaryPrefix(u) => Some(&mut u.operand),
1347 ExprKind::UnaryPostfix(u) => Some(&mut u.operand),
1348 ExprKind::Ternary(t) => Some(&mut t.condition),
1349 ExprKind::NullCoalesce(n) => Some(&mut n.left),
1350 ExprKind::FunctionCall(f) => Some(&mut f.name),
1351 ExprKind::ArrayAccess(a) => Some(&mut a.array),
1352 ExprKind::PropertyAccess(p) | ExprKind::NullsafePropertyAccess(p) => Some(&mut p.object),
1353 ExprKind::MethodCall(m) | ExprKind::NullsafeMethodCall(m) => Some(&mut m.object),
1354 ExprKind::StaticPropertyAccess(s) | ExprKind::ClassConstAccess(s) => Some(&mut s.class),
1355 ExprKind::StaticMethodCall(s) => Some(&mut s.class),
1356 ExprKind::StaticMethodCallDynamic(s) => Some(&mut s.class),
1357 ExprKind::ClassConstAccessDynamic { class, .. }
1358 | ExprKind::StaticPropertyAccessDynamic { class, .. } => Some(class),
1359 ExprKind::CallableCreate(c) => Some(match &mut c.kind {
1360 C::Function(e) => e,
1361 C::Method { object, .. } | C::NullsafeMethod { object, .. } => object,
1362 C::StaticMethod { class, .. } => class,
1363 }),
1364 _ => None,
1365 }
1366}
1367
1368#[derive(Debug, Clone)]
1370#[cfg_attr(feature = "serde", derive(Serialize))]
1371pub struct AssignExpr {
1372 pub target: Box<Expr>,
1374 pub op: AssignOp,
1376 pub value: Box<Expr>,
1378 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "is_false"))]
1380 pub by_ref: bool,
1381}
1382
1383#[derive(Debug, Clone)]
1385#[cfg_attr(feature = "serde", derive(Serialize))]
1386pub struct BinaryExpr {
1387 pub left: Box<Expr>,
1389 pub op: BinaryOp,
1391 pub right: Box<Expr>,
1393}
1394
1395#[derive(Debug, Clone)]
1397#[cfg_attr(feature = "serde", derive(Serialize))]
1398pub struct UnaryPrefixExpr {
1399 pub op: UnaryPrefixOp,
1401 pub operand: Box<Expr>,
1403}
1404
1405#[derive(Debug, Clone)]
1407#[cfg_attr(feature = "serde", derive(Serialize))]
1408pub struct UnaryPostfixExpr {
1409 pub operand: Box<Expr>,
1411 pub op: UnaryPostfixOp,
1413}
1414
1415#[derive(Debug, Clone)]
1417#[cfg_attr(feature = "serde", derive(Serialize))]
1418pub struct TernaryExpr {
1419 pub condition: Box<Expr>,
1421 pub then_expr: Option<Box<Expr>>,
1423 pub else_expr: Box<Expr>,
1425}
1426
1427#[derive(Debug, Clone)]
1429#[cfg_attr(feature = "serde", derive(Serialize))]
1430pub struct NullCoalesceExpr {
1431 pub left: Box<Expr>,
1433 pub right: Box<Expr>,
1435}
1436
1437#[derive(Debug, Clone)]
1439#[cfg_attr(feature = "serde", derive(Serialize))]
1440pub struct FunctionCallExpr {
1441 pub name: Box<Expr>,
1443 pub args: Box<[Arg]>,
1445}
1446
1447#[derive(Debug, Clone)]
1449#[cfg_attr(feature = "serde", derive(Serialize))]
1450pub struct ArrayElement {
1451 pub key: Option<Expr>,
1453 pub kind: ArrayElementKind,
1455 pub span: Span,
1457}
1458
1459#[derive(Debug, Clone)]
1461#[cfg_attr(feature = "serde", derive(Serialize))]
1462#[non_exhaustive]
1463pub enum ArrayElementKind {
1464 Value(Expr),
1466 Spread(Expr),
1468 ByRef(Expr),
1470}
1471
1472impl ArrayElement {
1473 pub fn value(&self) -> &Expr {
1475 match &self.kind {
1476 ArrayElementKind::Value(e)
1477 | ArrayElementKind::Spread(e)
1478 | ArrayElementKind::ByRef(e) => e,
1479 }
1480 }
1481
1482 pub fn value_mut(&mut self) -> &mut Expr {
1484 match &mut self.kind {
1485 ArrayElementKind::Value(e)
1486 | ArrayElementKind::Spread(e)
1487 | ArrayElementKind::ByRef(e) => e,
1488 }
1489 }
1490
1491 pub fn is_spread(&self) -> bool {
1493 matches!(self.kind, ArrayElementKind::Spread(_))
1494 }
1495
1496 pub fn is_by_ref(&self) -> bool {
1498 matches!(self.kind, ArrayElementKind::ByRef(_))
1499 }
1500}
1501
1502#[derive(Debug, Clone)]
1504#[cfg_attr(feature = "serde", derive(Serialize))]
1505pub struct ArrayAccessExpr {
1506 pub array: Box<Expr>,
1508 pub index: Option<Box<Expr>>,
1510}
1511
1512#[derive(Debug, Clone)]
1514#[cfg_attr(feature = "serde", derive(Serialize))]
1515pub struct NewExpr {
1516 pub class: Box<Expr>,
1518 pub args: Box<[Arg]>,
1520}
1521
1522#[derive(Debug, Clone)]
1524#[cfg_attr(feature = "serde", derive(Serialize))]
1525pub struct PropertyAccessExpr {
1526 pub object: Box<Expr>,
1528 pub property: Box<Expr>,
1530}
1531
1532#[derive(Debug, Clone)]
1534#[cfg_attr(feature = "serde", derive(Serialize))]
1535pub struct MethodCallExpr {
1536 pub object: Box<Expr>,
1538 pub method: Box<Expr>,
1540 pub args: Box<[Arg]>,
1542}
1543
1544#[derive(Debug, Clone)]
1546#[cfg_attr(feature = "serde", derive(Serialize))]
1547pub struct StaticAccessExpr {
1548 pub class: Box<Expr>,
1550 pub member: Box<Expr>,
1552}
1553
1554#[derive(Debug, Clone)]
1556#[cfg_attr(feature = "serde", derive(Serialize))]
1557pub struct StaticMethodCallExpr {
1558 pub class: Box<Expr>,
1560 pub method: Box<Expr>,
1562 pub args: Box<[Arg]>,
1564}
1565
1566#[derive(Debug, Clone)]
1568#[cfg_attr(feature = "serde", derive(Serialize))]
1569pub struct StaticMethodCallDynamicExpr {
1570 pub class: Box<Expr>,
1572 pub method: Box<Expr>,
1574 pub args: Box<[Arg]>,
1576}
1577
1578#[derive(Debug, Clone)]
1580#[cfg_attr(feature = "serde", derive(Serialize))]
1581#[non_exhaustive]
1582pub struct ClosureExpr {
1583 pub is_static: bool,
1585 pub by_ref: bool,
1587 pub params: Box<[Param]>,
1589 pub use_vars: Box<[ClosureUseVar]>,
1591 pub return_type: Option<TypeHint>,
1593 pub body: Box<Block>,
1595 pub attributes: Box<[Attribute]>,
1597}
1598
1599impl ClosureExpr {
1600 pub fn new(body: Box<Block>) -> Self {
1603 Self {
1604 is_static: false,
1605 by_ref: false,
1606 params: Box::new([]),
1607 use_vars: Box::new([]),
1608 return_type: None,
1609 body,
1610 attributes: Box::new([]),
1611 }
1612 }
1613}
1614
1615#[derive(Debug, Clone)]
1617#[cfg_attr(feature = "serde", derive(Serialize))]
1618pub struct ClosureUseVar {
1619 pub name: Ident,
1621 pub by_ref: bool,
1623 pub span: Span,
1625}
1626
1627#[derive(Debug, Clone)]
1629#[cfg_attr(feature = "serde", derive(Serialize))]
1630#[non_exhaustive]
1631pub struct ArrowFunctionExpr {
1632 pub is_static: bool,
1634 pub by_ref: bool,
1636 pub params: Box<[Param]>,
1638 pub return_type: Option<TypeHint>,
1640 pub body: Box<Expr>,
1642 pub attributes: Box<[Attribute]>,
1644}
1645
1646impl ArrowFunctionExpr {
1647 pub fn new(body: Box<Expr>) -> Self {
1650 Self {
1651 is_static: false,
1652 by_ref: false,
1653 params: Box::new([]),
1654 return_type: None,
1655 body,
1656 attributes: Box::new([]),
1657 }
1658 }
1659}
1660
1661#[derive(Debug, Clone)]
1663#[cfg_attr(feature = "serde", derive(Serialize))]
1664#[non_exhaustive]
1665pub struct MatchExpr {
1666 pub subject: Box<Expr>,
1668 pub arms: Box<[MatchArm]>,
1670 #[cfg_attr(feature = "serde", serde(skip))]
1672 #[doc(hidden)]
1673 pub brace_span: Span,
1674}
1675
1676impl MatchExpr {
1677 pub fn new(subject: Box<Expr>, arms: Box<[MatchArm]>, brace_span: Span) -> Self {
1680 Self {
1681 subject,
1682 arms,
1683 brace_span,
1684 }
1685 }
1686}
1687
1688#[derive(Debug, Clone)]
1690#[cfg_attr(feature = "serde", derive(Serialize))]
1691pub struct MatchArm {
1692 pub conditions: Option<Box<[Expr]>>,
1694 pub body: Expr,
1696 pub span: Span,
1698}
1699
1700#[derive(Debug, Clone)]
1702#[cfg_attr(feature = "serde", derive(Serialize))]
1703pub struct YieldExpr {
1704 pub key: Option<Box<Expr>>,
1706 pub value: Option<Box<Expr>>,
1708 pub is_from: bool,
1710}
1711
1712#[derive(Debug, Clone)]
1714#[cfg_attr(feature = "serde", derive(Serialize))]
1715pub struct CallableCreateExpr {
1716 pub kind: CallableCreateKind,
1718}
1719
1720#[derive(Debug, Clone)]
1722#[cfg_attr(feature = "serde", derive(Serialize))]
1723#[non_exhaustive]
1724pub enum CallableCreateKind {
1725 Function(Box<Expr>),
1727 Method {
1729 object: Box<Expr>,
1731 method: Box<Expr>,
1733 },
1734 NullsafeMethod {
1736 object: Box<Expr>,
1738 method: Box<Expr>,
1740 },
1741 StaticMethod {
1743 class: Box<Expr>,
1745 method: Box<Expr>,
1747 },
1748}
1749
1750#[derive(Debug, Clone)]
1752#[cfg_attr(feature = "serde", derive(Serialize))]
1753#[non_exhaustive]
1754pub enum StringPart {
1755 Literal(ByteString),
1757 Expr(Expr),
1759}
1760
1761#[derive(Debug, Clone)]
1767#[cfg_attr(feature = "serde", derive(Serialize))]
1768#[non_exhaustive]
1769pub struct FunctionDecl {
1770 pub name: Ident,
1772 pub params: Box<[Param]>,
1774 pub body: Box<Block>,
1776 pub return_type: Option<TypeHint>,
1778 pub by_ref: bool,
1780 pub attributes: Box<[Attribute]>,
1782 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
1784 pub doc_comment: Option<Comment>,
1785}
1786
1787impl FunctionDecl {
1788 pub fn new(name: Ident, body: Box<Block>) -> Self {
1791 Self {
1792 name,
1793 params: Box::new([]),
1794 body,
1795 return_type: None,
1796 by_ref: false,
1797 attributes: Box::new([]),
1798 doc_comment: None,
1799 }
1800 }
1801}
1802
1803#[derive(Debug, Clone)]
1805#[cfg_attr(feature = "serde", derive(Serialize))]
1806#[non_exhaustive]
1807pub struct Param {
1808 pub name: Ident,
1810 pub type_hint: Option<TypeHint>,
1812 pub default: Option<Expr>,
1814 pub by_ref: bool,
1816 pub variadic: bool,
1818 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Modifiers::is_empty"))]
1820 pub modifiers: Modifiers,
1821 pub attributes: Box<[Attribute]>,
1823 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "slice_is_empty"))]
1825 pub hooks: Box<[PropertyHook]>,
1826 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
1828 pub doc_comment: Option<Comment>,
1829 pub span: Span,
1831}
1832
1833impl Param {
1834 pub fn new(name: Ident, span: Span) -> Self {
1839 Self {
1840 name,
1841 type_hint: None,
1842 default: None,
1843 by_ref: false,
1844 variadic: false,
1845 modifiers: Modifiers::new(),
1846 attributes: Box::new([]),
1847 hooks: Box::new([]),
1848 doc_comment: None,
1849 span,
1850 }
1851 }
1852}
1853
1854#[derive(Debug, Clone)]
1856#[cfg_attr(feature = "serde", derive(Serialize))]
1857pub struct ClassBody {
1858 pub members: Box<[ClassMember]>,
1860 #[cfg_attr(feature = "serde", serde(skip))]
1862 pub span: Span,
1863}
1864
1865#[derive(Debug, Clone)]
1867#[cfg_attr(feature = "serde", derive(Serialize))]
1868#[non_exhaustive]
1869pub struct ClassDecl {
1870 pub name: Option<Ident>,
1872 pub modifiers: ClassModifiers,
1874 pub extends: Option<Name>,
1876 pub implements: Box<[Name]>,
1878 #[cfg_attr(feature = "serde", serde(flatten))]
1880 pub body: ClassBody,
1881 pub attributes: Box<[Attribute]>,
1883 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
1885 pub doc_comment: Option<Comment>,
1886}
1887
1888impl ClassDecl {
1889 pub fn new(name: Option<Ident>, body: ClassBody) -> Self {
1892 Self {
1893 name,
1894 modifiers: ClassModifiers::default(),
1895 extends: None,
1896 implements: Box::new([]),
1897 body,
1898 attributes: Box::new([]),
1899 doc_comment: None,
1900 }
1901 }
1902}
1903
1904#[derive(Debug, Clone)]
1906#[cfg_attr(feature = "serde", derive(Serialize))]
1907pub struct ClassMember {
1908 pub kind: ClassMemberKind,
1910 pub span: Span,
1912}
1913
1914#[derive(Debug, Clone)]
1916#[cfg_attr(feature = "serde", derive(Serialize))]
1917#[non_exhaustive]
1918pub enum ClassMemberKind {
1919 Property(PropertyDecl),
1921 Method(MethodDecl),
1923 ClassConst(ClassConstDecl),
1925 TraitUse(TraitUseDecl),
1927}
1928
1929#[derive(Debug, Clone)]
1931#[cfg_attr(feature = "serde", derive(Serialize))]
1932#[non_exhaustive]
1933pub struct PropertyDecl {
1934 pub name: Ident,
1936 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Modifiers::is_empty"))]
1938 pub modifiers: Modifiers,
1939 pub type_hint: Option<TypeHint>,
1941 pub default: Option<Expr>,
1943 pub attributes: Box<[Attribute]>,
1945 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "slice_is_empty"))]
1947 pub hooks: Box<[PropertyHook]>,
1948 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
1950 pub doc_comment: Option<Comment>,
1951}
1952
1953impl PropertyDecl {
1954 pub fn new(name: Ident) -> Self {
1957 Self {
1958 name,
1959 modifiers: Modifiers::new(),
1960 type_hint: None,
1961 default: None,
1962 attributes: Box::new([]),
1963 hooks: Box::new([]),
1964 doc_comment: None,
1965 }
1966 }
1967}
1968
1969#[derive(Debug, Clone)]
1971#[cfg_attr(feature = "serde", derive(Serialize))]
1972#[non_exhaustive]
1973pub struct PropertyHook {
1974 pub kind: PropertyHookKind,
1976 pub body: PropertyHookBody,
1978 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Modifiers::is_empty"))]
1980 pub modifiers: Modifiers,
1981 pub by_ref: bool,
1983 pub params: Box<[Param]>,
1985 pub attributes: Box<[Attribute]>,
1987 pub span: Span,
1989}
1990
1991impl PropertyHook {
1992 pub fn new(kind: PropertyHookKind, body: PropertyHookBody, span: Span) -> Self {
1995 Self {
1996 kind,
1997 body,
1998 modifiers: Modifiers::new(),
1999 by_ref: false,
2000 params: Box::new([]),
2001 attributes: Box::new([]),
2002 span,
2003 }
2004 }
2005}
2006
2007#[derive(Debug, Clone)]
2009#[cfg_attr(feature = "serde", derive(Serialize))]
2010#[non_exhaustive]
2011pub enum PropertyHookBody {
2012 Block(Box<Block>),
2014 Expression(Expr),
2016 Abstract,
2018}
2019
2020#[derive(Debug, Clone)]
2022#[cfg_attr(feature = "serde", derive(Serialize))]
2023#[non_exhaustive]
2024pub struct MethodDecl {
2025 pub name: Ident,
2027 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Modifiers::is_empty"))]
2029 pub modifiers: Modifiers,
2030 pub by_ref: bool,
2032 pub params: Box<[Param]>,
2034 pub return_type: Option<TypeHint>,
2036 pub body: Option<Box<Block>>,
2038 pub attributes: Box<[Attribute]>,
2040 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
2042 pub doc_comment: Option<Comment>,
2043}
2044
2045impl MethodDecl {
2046 pub fn new(name: Ident) -> Self {
2049 Self {
2050 name,
2051 modifiers: Modifiers::new(),
2052 by_ref: false,
2053 params: Box::new([]),
2054 return_type: None,
2055 body: None,
2056 attributes: Box::new([]),
2057 doc_comment: None,
2058 }
2059 }
2060}
2061
2062#[derive(Debug, Clone)]
2064#[cfg_attr(feature = "serde", derive(Serialize))]
2065#[non_exhaustive]
2066pub struct ClassConstDecl {
2067 pub name: Ident,
2069 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Modifiers::is_empty"))]
2071 pub modifiers: Modifiers,
2072 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
2074 pub type_hint: Option<Box<TypeHint>>,
2075 pub value: Expr,
2077 pub attributes: Box<[Attribute]>,
2079 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
2081 pub doc_comment: Option<Comment>,
2082}
2083
2084impl ClassConstDecl {
2085 pub fn new(name: Ident, value: Expr) -> Self {
2088 Self {
2089 name,
2090 modifiers: Modifiers::new(),
2091 type_hint: None,
2092 value,
2093 attributes: Box::new([]),
2094 doc_comment: None,
2095 }
2096 }
2097}
2098
2099#[derive(Debug, Clone)]
2101#[cfg_attr(feature = "serde", derive(Serialize))]
2102#[non_exhaustive]
2103pub struct TraitUseDecl {
2104 pub traits: Box<[Name]>,
2106 pub adaptations: Box<[TraitAdaptation]>,
2108 #[cfg_attr(feature = "serde", serde(skip))]
2110 #[doc(hidden)]
2111 pub adaptations_brace_span: Option<Span>,
2112 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
2114 pub doc_comment: Option<Comment>,
2115}
2116
2117impl TraitUseDecl {
2118 pub fn new(traits: Box<[Name]>) -> Self {
2121 Self {
2122 traits,
2123 adaptations: Box::new([]),
2124 adaptations_brace_span: None,
2125 doc_comment: None,
2126 }
2127 }
2128}
2129
2130#[derive(Debug, Clone)]
2132#[cfg_attr(feature = "serde", derive(Serialize))]
2133pub struct TraitAdaptation {
2134 pub kind: TraitAdaptationKind,
2136 pub span: Span,
2138}
2139
2140#[derive(Debug, Clone)]
2142#[cfg_attr(feature = "serde", derive(Serialize))]
2143#[non_exhaustive]
2144pub enum TraitAdaptationKind {
2145 Precedence {
2147 trait_name: Name,
2149 method: Name,
2151 insteadof: Box<[Name]>,
2153 },
2154 Alias {
2156 trait_name: Option<Name>,
2158 method: Name,
2160 new_modifier: Option<Visibility>,
2162 #[cfg_attr(feature = "serde", serde(default, skip_serializing_if = "is_false"))]
2164 is_final: bool,
2165 new_name: Option<Name>,
2167 },
2168}
2169
2170#[derive(Debug, Clone)]
2172#[cfg_attr(feature = "serde", derive(Serialize))]
2173#[non_exhaustive]
2174pub struct InterfaceDecl {
2175 pub name: Ident,
2177 pub extends: Box<[Name]>,
2179 #[cfg_attr(feature = "serde", serde(flatten))]
2181 pub body: ClassBody,
2182 pub attributes: Box<[Attribute]>,
2184 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
2186 pub doc_comment: Option<Comment>,
2187}
2188
2189impl InterfaceDecl {
2190 pub fn new(name: Ident, body: ClassBody) -> Self {
2193 Self {
2194 name,
2195 extends: Box::new([]),
2196 body,
2197 attributes: Box::new([]),
2198 doc_comment: None,
2199 }
2200 }
2201}
2202
2203#[derive(Debug, Clone)]
2205#[cfg_attr(feature = "serde", derive(Serialize))]
2206#[non_exhaustive]
2207pub struct TraitDecl {
2208 pub name: Ident,
2210 #[cfg_attr(feature = "serde", serde(flatten))]
2212 pub body: ClassBody,
2213 pub attributes: Box<[Attribute]>,
2215 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
2217 pub doc_comment: Option<Comment>,
2218}
2219
2220impl TraitDecl {
2221 pub fn new(name: Ident, body: ClassBody) -> Self {
2224 Self {
2225 name,
2226 body,
2227 attributes: Box::new([]),
2228 doc_comment: None,
2229 }
2230 }
2231}
2232
2233#[derive(Debug, Clone)]
2235#[cfg_attr(feature = "serde", derive(Serialize))]
2236pub struct EnumBody {
2237 pub members: Box<[EnumMember]>,
2239 #[cfg_attr(feature = "serde", serde(skip))]
2241 pub span: Span,
2242}
2243
2244#[derive(Debug, Clone)]
2246#[cfg_attr(feature = "serde", derive(Serialize))]
2247#[non_exhaustive]
2248pub struct EnumDecl {
2249 pub name: Ident,
2251 pub scalar_type: Option<Name>,
2253 pub implements: Box<[Name]>,
2255 #[cfg_attr(feature = "serde", serde(flatten))]
2257 pub body: EnumBody,
2258 pub attributes: Box<[Attribute]>,
2260 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
2262 pub doc_comment: Option<Comment>,
2263}
2264
2265impl EnumDecl {
2266 pub fn new(name: Ident, body: EnumBody) -> Self {
2269 Self {
2270 name,
2271 scalar_type: None,
2272 implements: Box::new([]),
2273 body,
2274 attributes: Box::new([]),
2275 doc_comment: None,
2276 }
2277 }
2278}
2279
2280#[derive(Debug, Clone)]
2282#[cfg_attr(feature = "serde", derive(Serialize))]
2283pub struct EnumMember {
2284 pub kind: EnumMemberKind,
2286 pub span: Span,
2288}
2289
2290#[derive(Debug, Clone)]
2292#[cfg_attr(feature = "serde", derive(Serialize))]
2293#[non_exhaustive]
2294pub enum EnumMemberKind {
2295 Case(EnumCase),
2297 Method(MethodDecl),
2299 ClassConst(ClassConstDecl),
2301 TraitUse(TraitUseDecl),
2303}
2304
2305#[derive(Debug, Clone)]
2307#[cfg_attr(feature = "serde", derive(Serialize))]
2308#[non_exhaustive]
2309pub struct EnumCase {
2310 pub name: Ident,
2312 pub value: Option<Expr>,
2314 pub attributes: Box<[Attribute]>,
2316 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
2318 pub doc_comment: Option<Comment>,
2319}
2320
2321impl EnumCase {
2322 pub fn new(name: Ident) -> Self {
2325 Self {
2326 name,
2327 value: None,
2328 attributes: Box::new([]),
2329 doc_comment: None,
2330 }
2331 }
2332}
2333
2334fn owned_ident(ident: arena_ast::Ident<'_>) -> Ident {
2339 match ident.as_str() {
2340 Some(s) => Ident::new(s, ident.span),
2341 None => Ident::error(ident.span),
2342 }
2343}
2344
2345fn owned_name(name: &arena_ast::Name<'_, '_>) -> Name {
2346 match name {
2347 arena_ast::Name::Simple { value, span } => Name {
2348 parts: vec![Box::from(*value)].into_boxed_slice(),
2349 kind: NameKind::Unqualified,
2350 span: *span,
2351 },
2352 arena_ast::Name::Complex { parts, kind, span } => Name {
2353 parts: parts
2354 .iter()
2355 .map(|s| Box::from(*s))
2356 .collect::<Vec<_>>()
2357 .into_boxed_slice(),
2358 kind: *kind,
2359 span: *span,
2360 },
2361 arena_ast::Name::Error { span } => Name {
2362 parts: Box::from([]),
2363 kind: NameKind::Error,
2364 span: *span,
2365 },
2366 }
2367}
2368
2369fn owned_comment(c: &arena_ast::Comment<'_>) -> Comment {
2370 Comment {
2371 kind: c.kind,
2372 text: c.text.into(),
2373 span: c.span,
2374 }
2375}
2376
2377fn owned_opt_comment(c: &Option<arena_ast::Comment<'_>>) -> Option<Comment> {
2378 c.as_ref().map(owned_comment)
2379}
2380
2381fn owned_type_hint(th: &arena_ast::TypeHint<'_, '_>) -> TypeHint {
2382 TypeHint {
2383 kind: owned_type_hint_kind(&th.kind),
2384 span: th.span,
2385 }
2386}
2387
2388fn owned_type_hint_kind(k: &arena_ast::TypeHintKind<'_, '_>) -> TypeHintKind {
2389 match k {
2390 arena_ast::TypeHintKind::Named(n) => TypeHintKind::Named(owned_name(n)),
2391 arena_ast::TypeHintKind::Keyword(b, span) => TypeHintKind::Keyword(*b, *span),
2392 arena_ast::TypeHintKind::Nullable(inner) => {
2393 TypeHintKind::Nullable(Box::new(owned_type_hint(inner)))
2394 }
2395 arena_ast::TypeHintKind::Union(types) => TypeHintKind::Union(
2396 types
2397 .iter()
2398 .map(owned_type_hint)
2399 .collect::<Vec<_>>()
2400 .into_boxed_slice(),
2401 ),
2402 arena_ast::TypeHintKind::Intersection(types) => TypeHintKind::Intersection(
2403 types
2404 .iter()
2405 .map(owned_type_hint)
2406 .collect::<Vec<_>>()
2407 .into_boxed_slice(),
2408 ),
2409 }
2410}
2411
2412fn owned_arg(arg: &arena_ast::Arg<'_, '_>) -> Arg {
2413 Arg {
2414 name: arg.name.as_ref().map(owned_name),
2415 kind: match &arg.kind {
2416 arena_ast::ArgKind::Value(e) => ArgKind::Value(owned_expr(e)),
2417 arena_ast::ArgKind::Spread(e) => ArgKind::Spread(owned_expr(e)),
2418 arena_ast::ArgKind::ByRef(e) => ArgKind::ByRef(owned_expr(e)),
2419 arena_ast::ArgKind::Placeholder => ArgKind::Placeholder,
2420 arena_ast::ArgKind::SpreadPlaceholder => ArgKind::SpreadPlaceholder,
2421 },
2422 span: arg.span,
2423 }
2424}
2425
2426#[inline(never)]
2427fn owned_args(args: &[arena_ast::Arg<'_, '_>]) -> Box<[Arg]> {
2428 args.iter()
2429 .map(owned_arg)
2430 .collect::<Vec<_>>()
2431 .into_boxed_slice()
2432}
2433
2434fn owned_attr(attr: &arena_ast::Attribute<'_, '_>) -> Attribute {
2435 Attribute {
2436 name: owned_name(&attr.name),
2437 args: owned_args(&attr.args),
2438 span: attr.span,
2439 }
2440}
2441
2442fn owned_attrs(attrs: &[arena_ast::Attribute<'_, '_>]) -> Box<[Attribute]> {
2443 attrs
2444 .iter()
2445 .map(owned_attr)
2446 .collect::<Vec<_>>()
2447 .into_boxed_slice()
2448}
2449
2450#[inline(never)]
2451fn owned_string_parts(parts: &[arena_ast::StringPart<'_, '_>]) -> Box<[StringPart]> {
2452 parts
2453 .iter()
2454 .map(|p| match p {
2455 arena_ast::StringPart::Literal(s) => {
2456 StringPart::Literal(ByteString::from(s.as_bytes()))
2457 }
2458 arena_ast::StringPart::Expr(e) => StringPart::Expr(owned_expr(e)),
2459 })
2460 .collect::<Vec<_>>()
2461 .into_boxed_slice()
2462}
2463
2464pub fn to_owned_expr(expr: &arena_ast::Expr<'_, '_>) -> Expr {
2466 owned_expr(expr)
2467}
2468
2469pub fn to_owned_name(name: &arena_ast::Name<'_, '_>) -> Name {
2471 owned_name(name)
2472}
2473
2474pub fn to_owned_type_hint(hint: &arena_ast::TypeHint<'_, '_>) -> TypeHint {
2476 owned_type_hint(hint)
2477}
2478
2479#[inline]
2480fn owned_expr(expr: &arena_ast::Expr<'_, '_>) -> Expr {
2481 if !arena_is_chain(&expr.kind) {
2482 return Expr {
2483 kind: owned_leaf_kind(&expr.kind),
2484 span: expr.span,
2485 };
2486 }
2487 owned_chain_expr(expr)
2488}
2489
2490#[inline(never)]
2493fn owned_chain_expr(expr: &arena_ast::Expr<'_, '_>) -> Expr {
2494 let first = arena_chain_operand(&expr.kind).expect("chain link has an operand");
2495 if !arena_is_chain(&first.kind) {
2496 let operand = Expr {
2498 kind: owned_leaf_kind(&first.kind),
2499 span: first.span,
2500 };
2501 return Expr {
2502 kind: owned_link_kind(&expr.kind, operand),
2503 span: expr.span,
2504 };
2505 }
2506 let mut chain = LinkStack::new();
2507 chain.push(expr);
2508 let mut leaf = first;
2509 while let Some(operand) = arena_chain_operand(&leaf.kind) {
2510 chain.push(leaf);
2511 leaf = operand;
2512 }
2513 let mut converted = Expr {
2514 kind: owned_leaf_kind(&leaf.kind),
2515 span: leaf.span,
2516 };
2517 while let Some(node) = chain.pop() {
2518 converted = Expr {
2519 kind: owned_link_kind(&node.kind, converted),
2520 span: node.span,
2521 };
2522 }
2523 converted
2524}
2525
2526#[inline(never)]
2527fn owned_exprs(exprs: &[arena_ast::Expr<'_, '_>]) -> Box<[Expr]> {
2528 exprs
2529 .iter()
2530 .map(owned_expr)
2531 .collect::<Vec<_>>()
2532 .into_boxed_slice()
2533}
2534
2535fn owned_leaf_kind(k: &arena_ast::ExprKind<'_, '_>) -> ExprKind {
2537 match k {
2538 arena_ast::ExprKind::Int(v) => ExprKind::Int(*v),
2539 arena_ast::ExprKind::Float(v) => ExprKind::Float(*v),
2540 arena_ast::ExprKind::String(s) => ExprKind::String(ByteString::from(s.as_bytes())),
2541 arena_ast::ExprKind::InterpolatedString(parts) => {
2542 ExprKind::InterpolatedString(owned_string_parts(parts))
2543 }
2544 arena_ast::ExprKind::Heredoc { label, parts } => ExprKind::Heredoc {
2545 label: Box::from(*label),
2546 parts: owned_string_parts(parts),
2547 },
2548 arena_ast::ExprKind::Nowdoc { label, value } => ExprKind::Nowdoc {
2549 label: Box::from(*label),
2550 value: Box::from(*value),
2551 },
2552 arena_ast::ExprKind::ShellExec(parts) => ExprKind::ShellExec(owned_string_parts(parts)),
2553 arena_ast::ExprKind::Bool(v) => ExprKind::Bool(*v),
2554 arena_ast::ExprKind::Null => ExprKind::Null,
2555 arena_ast::ExprKind::Variable(s) => ExprKind::Variable(s.as_str().into()),
2556 arena_ast::ExprKind::VariableVariable(inner) => {
2557 ExprKind::VariableVariable(Box::new(owned_expr(inner)))
2558 }
2559 arena_ast::ExprKind::Identifier(s) => ExprKind::Identifier(s.as_str().into()),
2560 arena_ast::ExprKind::Name(name) => ExprKind::Name(owned_name(name)),
2561 arena_ast::ExprKind::Array(elems) => ExprKind::Array(
2562 elems
2563 .iter()
2564 .map(|e| ArrayElement {
2565 key: e.key.as_ref().map(owned_expr),
2566 kind: match &e.kind {
2567 arena_ast::ArrayElementKind::Value(v) => {
2568 ArrayElementKind::Value(owned_expr(v))
2569 }
2570 arena_ast::ArrayElementKind::Spread(v) => {
2571 ArrayElementKind::Spread(owned_expr(v))
2572 }
2573 arena_ast::ArrayElementKind::ByRef(v) => {
2574 ArrayElementKind::ByRef(owned_expr(v))
2575 }
2576 },
2577 span: e.span,
2578 })
2579 .collect::<Vec<_>>()
2580 .into_boxed_slice(),
2581 ),
2582 arena_ast::ExprKind::Print(e) => ExprKind::Print(Box::new(owned_expr(e))),
2583 arena_ast::ExprKind::Parenthesized(e) => ExprKind::Parenthesized(Box::new(owned_expr(e))),
2584 arena_ast::ExprKind::Cast(kind, e) => ExprKind::Cast(*kind, Box::new(owned_expr(e))),
2585 arena_ast::ExprKind::ErrorSuppress(e) => ExprKind::ErrorSuppress(Box::new(owned_expr(e))),
2586 arena_ast::ExprKind::Isset(exprs) => ExprKind::Isset(owned_exprs(exprs)),
2587 arena_ast::ExprKind::Empty(e) => ExprKind::Empty(Box::new(owned_expr(e))),
2588 arena_ast::ExprKind::Include(kind, e) => ExprKind::Include(*kind, Box::new(owned_expr(e))),
2589 arena_ast::ExprKind::Eval(e) => ExprKind::Eval(Box::new(owned_expr(e))),
2590 arena_ast::ExprKind::Exit(e) => ExprKind::Exit(e.map(|e| Box::new(owned_expr(e)))),
2591 arena_ast::ExprKind::MagicConst(m) => ExprKind::MagicConst(*m),
2592 arena_ast::ExprKind::Clone(e) => ExprKind::Clone(Box::new(owned_expr(e))),
2593 arena_ast::ExprKind::CloneWith(obj, props) => {
2594 ExprKind::CloneWith(Box::new(owned_expr(obj)), Box::new(owned_expr(props)))
2595 }
2596 arena_ast::ExprKind::New(n) => ExprKind::New(NewExpr {
2597 class: Box::new(owned_expr(n.class)),
2598 args: owned_args(&n.args),
2599 }),
2600 arena_ast::ExprKind::Closure(c) => ExprKind::Closure(Box::new(ClosureExpr {
2601 is_static: c.is_static,
2602 by_ref: c.by_ref,
2603 params: owned_params(&c.params),
2604 use_vars: c
2605 .use_vars
2606 .iter()
2607 .map(|v| ClosureUseVar {
2608 name: owned_ident(v.name),
2609 by_ref: v.by_ref,
2610 span: v.span,
2611 })
2612 .collect::<Vec<_>>()
2613 .into_boxed_slice(),
2614 return_type: c.return_type.as_ref().map(owned_type_hint),
2615 body: Box::new(owned_block(c.body)),
2616 attributes: owned_attrs(&c.attributes),
2617 })),
2618 arena_ast::ExprKind::ArrowFunction(f) => {
2619 ExprKind::ArrowFunction(Box::new(ArrowFunctionExpr {
2620 is_static: f.is_static,
2621 by_ref: f.by_ref,
2622 params: owned_params(&f.params),
2623 return_type: f.return_type.as_ref().map(owned_type_hint),
2624 body: Box::new(owned_expr(f.body)),
2625 attributes: owned_attrs(&f.attributes),
2626 }))
2627 }
2628 arena_ast::ExprKind::Match(m) => ExprKind::Match(MatchExpr {
2629 subject: Box::new(owned_expr(m.subject)),
2630 arms: m
2631 .arms
2632 .iter()
2633 .map(|arm| MatchArm {
2634 conditions: arm.conditions.as_ref().map(|conds| owned_exprs(conds)),
2635 body: owned_expr(&arm.body),
2636 span: arm.span,
2637 })
2638 .collect::<Vec<_>>()
2639 .into_boxed_slice(),
2640 brace_span: m.brace_span,
2641 }),
2642 arena_ast::ExprKind::Throw(e) => ExprKind::Throw(Box::new(owned_expr(e))),
2643 arena_ast::ExprKind::Yield(y) => ExprKind::Yield(YieldExpr {
2644 key: y.key.map(|e| Box::new(owned_expr(e))),
2645 value: y.value.map(|e| Box::new(owned_expr(e))),
2646 is_from: y.is_from,
2647 }),
2648 arena_ast::ExprKind::AnonymousClass(cls) => {
2649 ExprKind::AnonymousClass(Box::new(owned_class_decl(cls)))
2650 }
2651 arena_ast::ExprKind::Omit => ExprKind::Omit,
2652 arena_ast::ExprKind::Error => ExprKind::Error,
2653 arena_ast::ExprKind::Assign(_)
2654 | arena_ast::ExprKind::Binary(_)
2655 | arena_ast::ExprKind::UnaryPrefix(_)
2656 | arena_ast::ExprKind::UnaryPostfix(_)
2657 | arena_ast::ExprKind::Ternary(_)
2658 | arena_ast::ExprKind::NullCoalesce(_)
2659 | arena_ast::ExprKind::FunctionCall(_)
2660 | arena_ast::ExprKind::ArrayAccess(_)
2661 | arena_ast::ExprKind::PropertyAccess(_)
2662 | arena_ast::ExprKind::NullsafePropertyAccess(_)
2663 | arena_ast::ExprKind::MethodCall(_)
2664 | arena_ast::ExprKind::NullsafeMethodCall(_)
2665 | arena_ast::ExprKind::StaticPropertyAccess(_)
2666 | arena_ast::ExprKind::ClassConstAccess(_)
2667 | arena_ast::ExprKind::StaticMethodCall(_)
2668 | arena_ast::ExprKind::StaticMethodCallDynamic(_)
2669 | arena_ast::ExprKind::ClassConstAccessDynamic { .. }
2670 | arena_ast::ExprKind::StaticPropertyAccessDynamic { .. }
2671 | arena_ast::ExprKind::CallableCreate(_) => {
2672 unreachable!("chain links are converted by the link function")
2673 }
2674 }
2675}
2676
2677fn owned_link_kind(k: &arena_ast::ExprKind<'_, '_>, operand: Expr) -> ExprKind {
2679 match k {
2680 arena_ast::ExprKind::Assign(a) => ExprKind::Assign(AssignExpr {
2681 target: Box::new(operand),
2682 op: a.op,
2683 value: Box::new(owned_expr(a.value)),
2684 by_ref: a.by_ref,
2685 }),
2686 arena_ast::ExprKind::Binary(b) => ExprKind::Binary(BinaryExpr {
2687 left: Box::new(operand),
2688 op: b.op,
2689 right: Box::new(owned_expr(b.right)),
2690 }),
2691 arena_ast::ExprKind::UnaryPrefix(u) => ExprKind::UnaryPrefix(UnaryPrefixExpr {
2692 op: u.op,
2693 operand: Box::new(operand),
2694 }),
2695 arena_ast::ExprKind::UnaryPostfix(u) => ExprKind::UnaryPostfix(UnaryPostfixExpr {
2696 operand: Box::new(operand),
2697 op: u.op,
2698 }),
2699 arena_ast::ExprKind::Ternary(t) => ExprKind::Ternary(TernaryExpr {
2700 condition: Box::new(operand),
2701 then_expr: t.then_expr.map(|e| Box::new(owned_expr(e))),
2702 else_expr: Box::new(owned_expr(t.else_expr)),
2703 }),
2704 arena_ast::ExprKind::NullCoalesce(n) => ExprKind::NullCoalesce(NullCoalesceExpr {
2705 left: Box::new(operand),
2706 right: Box::new(owned_expr(n.right)),
2707 }),
2708 arena_ast::ExprKind::FunctionCall(f) => ExprKind::FunctionCall(FunctionCallExpr {
2709 name: Box::new(operand),
2710 args: owned_args(&f.args),
2711 }),
2712 arena_ast::ExprKind::ArrayAccess(a) => ExprKind::ArrayAccess(ArrayAccessExpr {
2713 array: Box::new(operand),
2714 index: a.index.map(|e| Box::new(owned_expr(e))),
2715 }),
2716 arena_ast::ExprKind::PropertyAccess(p) => ExprKind::PropertyAccess(PropertyAccessExpr {
2717 object: Box::new(operand),
2718 property: Box::new(owned_expr(p.property)),
2719 }),
2720 arena_ast::ExprKind::NullsafePropertyAccess(p) => {
2721 ExprKind::NullsafePropertyAccess(PropertyAccessExpr {
2722 object: Box::new(operand),
2723 property: Box::new(owned_expr(p.property)),
2724 })
2725 }
2726 arena_ast::ExprKind::MethodCall(m) => ExprKind::MethodCall(Box::new(MethodCallExpr {
2727 object: Box::new(operand),
2728 method: Box::new(owned_expr(m.method)),
2729 args: owned_args(&m.args),
2730 })),
2731 arena_ast::ExprKind::NullsafeMethodCall(m) => {
2732 ExprKind::NullsafeMethodCall(Box::new(MethodCallExpr {
2733 object: Box::new(operand),
2734 method: Box::new(owned_expr(m.method)),
2735 args: owned_args(&m.args),
2736 }))
2737 }
2738 arena_ast::ExprKind::StaticPropertyAccess(s) => {
2739 ExprKind::StaticPropertyAccess(StaticAccessExpr {
2740 class: Box::new(operand),
2741 member: Box::new(owned_expr(s.member)),
2742 })
2743 }
2744 arena_ast::ExprKind::StaticMethodCall(s) => {
2745 ExprKind::StaticMethodCall(Box::new(StaticMethodCallExpr {
2746 class: Box::new(operand),
2747 method: Box::new(owned_expr(s.method)),
2748 args: owned_args(&s.args),
2749 }))
2750 }
2751 arena_ast::ExprKind::StaticMethodCallDynamic(s) => {
2752 ExprKind::StaticMethodCallDynamic(Box::new(StaticMethodCallDynamicExpr {
2753 class: Box::new(operand),
2754 method: Box::new(owned_expr(s.method)),
2755 args: owned_args(&s.args),
2756 }))
2757 }
2758 arena_ast::ExprKind::ClassConstAccess(s) => ExprKind::ClassConstAccess(StaticAccessExpr {
2759 class: Box::new(operand),
2760 member: Box::new(owned_expr(s.member)),
2761 }),
2762 arena_ast::ExprKind::ClassConstAccessDynamic { member, .. } => {
2763 ExprKind::ClassConstAccessDynamic {
2764 class: Box::new(operand),
2765 member: Box::new(owned_expr(member)),
2766 }
2767 }
2768 arena_ast::ExprKind::StaticPropertyAccessDynamic { member, .. } => {
2769 ExprKind::StaticPropertyAccessDynamic {
2770 class: Box::new(operand),
2771 member: Box::new(owned_expr(member)),
2772 }
2773 }
2774 arena_ast::ExprKind::CallableCreate(c) => ExprKind::CallableCreate(CallableCreateExpr {
2775 kind: match &c.kind {
2776 arena_ast::CallableCreateKind::Function(_) => {
2777 CallableCreateKind::Function(Box::new(operand))
2778 }
2779 arena_ast::CallableCreateKind::Method { method, .. } => {
2780 CallableCreateKind::Method {
2781 object: Box::new(operand),
2782 method: Box::new(owned_expr(method)),
2783 }
2784 }
2785 arena_ast::CallableCreateKind::NullsafeMethod { method, .. } => {
2786 CallableCreateKind::NullsafeMethod {
2787 object: Box::new(operand),
2788 method: Box::new(owned_expr(method)),
2789 }
2790 }
2791 arena_ast::CallableCreateKind::StaticMethod { method, .. } => {
2792 CallableCreateKind::StaticMethod {
2793 class: Box::new(operand),
2794 method: Box::new(owned_expr(method)),
2795 }
2796 }
2797 },
2798 }),
2799 _ => unreachable!("not a chain link"),
2800 }
2801}
2802
2803fn owned_param(p: &arena_ast::Param<'_, '_>) -> Param {
2804 Param {
2805 name: owned_ident(p.name),
2806 type_hint: p.type_hint.as_ref().map(owned_type_hint),
2807 default: p.default.as_ref().map(owned_expr),
2808 by_ref: p.by_ref,
2809 variadic: p.variadic,
2810 modifiers: p.modifiers,
2811 attributes: owned_attrs(&p.attributes),
2812 hooks: owned_hooks(&p.hooks),
2813 doc_comment: p.doc_comment.as_ref().map(owned_comment),
2814 span: p.span,
2815 }
2816}
2817
2818#[inline(never)]
2819fn owned_params(params: &[arena_ast::Param<'_, '_>]) -> Box<[Param]> {
2820 params
2821 .iter()
2822 .map(owned_param)
2823 .collect::<Vec<_>>()
2824 .into_boxed_slice()
2825}
2826
2827fn owned_hook(h: &arena_ast::PropertyHook<'_, '_>) -> PropertyHook {
2828 PropertyHook {
2829 kind: h.kind,
2830 body: match &h.body {
2831 arena_ast::PropertyHookBody::Block(block) => {
2832 PropertyHookBody::Block(Box::new(owned_block(block)))
2833 }
2834 arena_ast::PropertyHookBody::Expression(e) => {
2835 PropertyHookBody::Expression(owned_expr(e))
2836 }
2837 arena_ast::PropertyHookBody::Abstract => PropertyHookBody::Abstract,
2838 },
2839 modifiers: h.modifiers,
2840 by_ref: h.by_ref,
2841 params: owned_params(&h.params),
2842 attributes: owned_attrs(&h.attributes),
2843 span: h.span,
2844 }
2845}
2846
2847#[inline(never)]
2848fn owned_hooks(hooks: &[arena_ast::PropertyHook<'_, '_>]) -> Box<[PropertyHook]> {
2849 hooks
2850 .iter()
2851 .map(owned_hook)
2852 .collect::<Vec<_>>()
2853 .into_boxed_slice()
2854}
2855
2856fn owned_stmts(stmts: &[arena_ast::Stmt<'_, '_>]) -> Box<[Stmt]> {
2857 stmts
2858 .iter()
2859 .map(owned_stmt)
2860 .collect::<Vec<_>>()
2861 .into_boxed_slice()
2862}
2863
2864pub fn to_owned_stmt(stmt: &arena_ast::Stmt<'_, '_>) -> Stmt {
2866 owned_stmt(stmt)
2867}
2868
2869fn owned_block(block: &arena_ast::Block<'_, '_>) -> Block {
2870 Block {
2871 stmts: owned_stmts(&block.stmts),
2872 span: block.span,
2873 }
2874}
2875
2876fn owned_stmt(stmt: &arena_ast::Stmt<'_, '_>) -> Stmt {
2877 Stmt {
2878 kind: owned_stmt_kind(&stmt.kind),
2879 span: stmt.span,
2880 doc_comment: stmt.doc_comment.map(owned_comment),
2881 }
2882}
2883
2884fn owned_stmt_kind(k: &arena_ast::StmtKind<'_, '_>) -> StmtKind {
2885 match k {
2886 arena_ast::StmtKind::Expression(e) => StmtKind::Expression(Box::new(owned_expr(e))),
2887 arena_ast::StmtKind::Echo(exprs) => StmtKind::Echo(owned_exprs(exprs)),
2888 arena_ast::StmtKind::Return(e) => StmtKind::Return(e.map(|e| Box::new(owned_expr(e)))),
2889 arena_ast::StmtKind::Block(block) => StmtKind::Block(Box::new(owned_block(block))),
2890 arena_ast::StmtKind::If(s) => StmtKind::If(Box::new(IfStmt {
2891 condition: owned_expr(&s.condition),
2892 then_branch: Box::new(owned_stmt(s.then_branch)),
2893 elseif_branches: s
2894 .elseif_branches
2895 .iter()
2896 .map(|b| ElseIfBranch {
2897 condition: owned_expr(&b.condition),
2898 body: owned_stmt(&b.body),
2899 span: b.span,
2900 })
2901 .collect::<Vec<_>>()
2902 .into_boxed_slice(),
2903 else_branch: s.else_branch.map(|b| Box::new(owned_stmt(b))),
2904 else_kw_span: s.else_kw_span,
2905 uses_alternative: s.uses_alternative,
2906 })),
2907 arena_ast::StmtKind::While(s) => StmtKind::While(Box::new(WhileStmt {
2908 condition: owned_expr(&s.condition),
2909 body: Box::new(owned_stmt(s.body)),
2910 uses_alternative: s.uses_alternative,
2911 })),
2912 arena_ast::StmtKind::For(s) => StmtKind::For(Box::new(ForStmt {
2913 init: owned_exprs(&s.init),
2914 condition: owned_exprs(&s.condition),
2915 update: owned_exprs(&s.update),
2916 body: Box::new(owned_stmt(s.body)),
2917 uses_alternative: s.uses_alternative,
2918 })),
2919 arena_ast::StmtKind::Foreach(s) => StmtKind::Foreach(Box::new(ForeachStmt {
2920 expr: owned_expr(&s.expr),
2921 key: s.key.as_ref().map(owned_expr),
2922 value: owned_expr(&s.value),
2923 by_ref: s.by_ref,
2924 body: Box::new(owned_stmt(s.body)),
2925 uses_alternative: s.uses_alternative,
2926 })),
2927 arena_ast::StmtKind::DoWhile(s) => StmtKind::DoWhile(Box::new(DoWhileStmt {
2928 body: Box::new(owned_stmt(s.body)),
2929 condition: owned_expr(&s.condition),
2930 })),
2931 arena_ast::StmtKind::Function(f) => StmtKind::Function(Box::new(owned_function_decl(f))),
2932 arena_ast::StmtKind::Break(e) => StmtKind::Break(e.map(|e| Box::new(owned_expr(e)))),
2933 arena_ast::StmtKind::Continue(e) => StmtKind::Continue(e.map(|e| Box::new(owned_expr(e)))),
2934 arena_ast::StmtKind::Switch(s) => StmtKind::Switch(Box::new(SwitchStmt {
2935 expr: owned_expr(&s.expr),
2936 body: SwitchBody {
2937 cases: s
2938 .body
2939 .cases
2940 .iter()
2941 .map(|c| SwitchCase {
2942 value: c.value.as_ref().map(owned_expr),
2943 body: owned_stmts(&c.body),
2944 span: c.span,
2945 })
2946 .collect::<Vec<_>>()
2947 .into_boxed_slice(),
2948 span: s.body.span,
2949 },
2950 uses_alternative: s.uses_alternative,
2951 })),
2952 arena_ast::StmtKind::Goto(ident) => StmtKind::Goto(owned_ident(*ident)),
2953 arena_ast::StmtKind::Label(ident) => StmtKind::Label(owned_ident(*ident)),
2954 arena_ast::StmtKind::Declare(d) => StmtKind::Declare(Box::new(DeclareStmt {
2955 directives: d
2956 .directives
2957 .iter()
2958 .map(|(k, v)| (Box::from(*k), owned_expr(v)))
2959 .collect::<Vec<_>>()
2960 .into_boxed_slice(),
2961 body: d.body.map(|b| Box::new(owned_stmt(b))),
2962 uses_alternative: d.uses_alternative,
2963 })),
2964 arena_ast::StmtKind::Unset(exprs) => StmtKind::Unset(owned_exprs(exprs)),
2965 arena_ast::StmtKind::Throw(e) => StmtKind::Throw(Box::new(owned_expr(e))),
2966 arena_ast::StmtKind::TryCatch(t) => StmtKind::TryCatch(Box::new(TryCatchStmt {
2967 body: Box::new(owned_block(t.body)),
2968 catches: t
2969 .catches
2970 .iter()
2971 .map(|c| CatchClause {
2972 types: c
2973 .types
2974 .iter()
2975 .map(owned_name)
2976 .collect::<Vec<_>>()
2977 .into_boxed_slice(),
2978 var: c.var.map(owned_ident),
2979 body: Box::new(owned_block(c.body)),
2980 span: c.span,
2981 })
2982 .collect::<Vec<_>>()
2983 .into_boxed_slice(),
2984 finally: t.finally.map(|f| Box::new(owned_block(f))),
2985 finally_kw_span: t.finally_kw_span,
2986 })),
2987 arena_ast::StmtKind::Global(exprs) => StmtKind::Global(owned_exprs(exprs)),
2988 arena_ast::StmtKind::Class(cls) => StmtKind::Class(Box::new(owned_class_decl(cls))),
2989 arena_ast::StmtKind::Interface(iface) => {
2990 StmtKind::Interface(Box::new(owned_interface_decl(iface)))
2991 }
2992 arena_ast::StmtKind::Trait(tr) => StmtKind::Trait(Box::new(owned_trait_decl(tr))),
2993 arena_ast::StmtKind::Enum(en) => StmtKind::Enum(Box::new(owned_enum_decl(en))),
2994 arena_ast::StmtKind::Namespace(ns) => StmtKind::Namespace(Box::new(NamespaceDecl {
2995 name: ns.name.as_ref().map(owned_name),
2996 body: match &ns.body {
2997 arena_ast::NamespaceBody::Braced(block) => {
2998 NamespaceBody::Braced(Box::new(owned_block(block)))
2999 }
3000 arena_ast::NamespaceBody::Simple => NamespaceBody::Simple,
3001 },
3002 })),
3003 arena_ast::StmtKind::Use(u) => StmtKind::Use(Box::new(UseDecl {
3004 kind: u.kind,
3005 uses: u
3006 .uses
3007 .iter()
3008 .map(|item| UseItem {
3009 name: owned_name(&item.name),
3010 alias: item.alias.map(owned_ident),
3011 kind: item.kind,
3012 span: item.span,
3013 })
3014 .collect::<Vec<_>>()
3015 .into_boxed_slice(),
3016 })),
3017 arena_ast::StmtKind::Const(items) => StmtKind::Const(
3018 items
3019 .iter()
3020 .map(|item| ConstItem {
3021 name: owned_ident(item.name),
3022 value: owned_expr(&item.value),
3023 attributes: owned_attrs(&item.attributes),
3024 span: item.span,
3025 doc_comment: owned_opt_comment(&item.doc_comment),
3026 })
3027 .collect::<Vec<_>>()
3028 .into_boxed_slice(),
3029 ),
3030 arena_ast::StmtKind::StaticVar(vars) => StmtKind::StaticVar(
3031 vars.iter()
3032 .map(|v| StaticVar {
3033 name: owned_ident(v.name),
3034 default: v.default.as_ref().map(owned_expr),
3035 span: v.span,
3036 })
3037 .collect::<Vec<_>>()
3038 .into_boxed_slice(),
3039 ),
3040 arena_ast::StmtKind::HaltCompiler(s) => StmtKind::HaltCompiler(Box::from(*s)),
3041 arena_ast::StmtKind::Nop => StmtKind::Nop,
3042 arena_ast::StmtKind::InlineHtml(s) => StmtKind::InlineHtml(Box::from(*s)),
3043 arena_ast::StmtKind::Error => StmtKind::Error,
3044 }
3045}
3046
3047fn owned_function_decl(f: &arena_ast::FunctionDecl<'_, '_>) -> FunctionDecl {
3048 FunctionDecl {
3049 name: owned_ident(f.name),
3050 params: owned_params(&f.params),
3051 body: Box::new(owned_block(f.body)),
3052 return_type: f.return_type.as_ref().map(owned_type_hint),
3053 by_ref: f.by_ref,
3054 attributes: owned_attrs(&f.attributes),
3055 doc_comment: owned_opt_comment(&f.doc_comment),
3056 }
3057}
3058
3059fn owned_class_member(m: &arena_ast::ClassMember<'_, '_>) -> ClassMember {
3060 ClassMember {
3061 kind: match &m.kind {
3062 arena_ast::ClassMemberKind::Property(p) => ClassMemberKind::Property(PropertyDecl {
3063 name: owned_ident(p.name),
3064 modifiers: p.modifiers,
3065 type_hint: p.type_hint.as_ref().map(owned_type_hint),
3066 default: p.default.as_ref().map(owned_expr),
3067 attributes: owned_attrs(&p.attributes),
3068 hooks: owned_hooks(&p.hooks),
3069 doc_comment: owned_opt_comment(&p.doc_comment),
3070 }),
3071 arena_ast::ClassMemberKind::Method(m) => ClassMemberKind::Method(MethodDecl {
3072 name: owned_ident(m.name),
3073 modifiers: m.modifiers,
3074 by_ref: m.by_ref,
3075 params: owned_params(&m.params),
3076 return_type: m.return_type.as_ref().map(owned_type_hint),
3077 body: m.body.map(|b| Box::new(owned_block(b))),
3078 attributes: owned_attrs(&m.attributes),
3079 doc_comment: owned_opt_comment(&m.doc_comment),
3080 }),
3081 arena_ast::ClassMemberKind::ClassConst(c) => {
3082 ClassMemberKind::ClassConst(owned_class_const(c))
3083 }
3084 arena_ast::ClassMemberKind::TraitUse(t) => {
3085 ClassMemberKind::TraitUse(owned_trait_use(t))
3086 }
3087 },
3088 span: m.span,
3089 }
3090}
3091
3092fn owned_class_members(members: &[arena_ast::ClassMember<'_, '_>]) -> Box<[ClassMember]> {
3093 members
3094 .iter()
3095 .map(owned_class_member)
3096 .collect::<Vec<_>>()
3097 .into_boxed_slice()
3098}
3099
3100fn owned_class_const(c: &arena_ast::ClassConstDecl<'_, '_>) -> ClassConstDecl {
3101 ClassConstDecl {
3102 name: owned_ident(c.name),
3103 modifiers: c.modifiers,
3104 type_hint: c.type_hint.map(|th| Box::new(owned_type_hint(th))),
3105 value: owned_expr(&c.value),
3106 attributes: owned_attrs(&c.attributes),
3107 doc_comment: owned_opt_comment(&c.doc_comment),
3108 }
3109}
3110
3111fn owned_trait_use(t: &arena_ast::TraitUseDecl<'_, '_>) -> TraitUseDecl {
3112 TraitUseDecl {
3113 traits: t
3114 .traits
3115 .iter()
3116 .map(owned_name)
3117 .collect::<Vec<_>>()
3118 .into_boxed_slice(),
3119 adaptations: t
3120 .adaptations
3121 .iter()
3122 .map(|a| TraitAdaptation {
3123 kind: match &a.kind {
3124 arena_ast::TraitAdaptationKind::Precedence {
3125 trait_name,
3126 method,
3127 insteadof,
3128 } => TraitAdaptationKind::Precedence {
3129 trait_name: owned_name(trait_name),
3130 method: owned_name(method),
3131 insteadof: insteadof
3132 .iter()
3133 .map(owned_name)
3134 .collect::<Vec<_>>()
3135 .into_boxed_slice(),
3136 },
3137 arena_ast::TraitAdaptationKind::Alias {
3138 trait_name,
3139 method,
3140 new_modifier,
3141 is_final,
3142 new_name,
3143 } => TraitAdaptationKind::Alias {
3144 trait_name: trait_name.as_ref().map(owned_name),
3145 method: owned_name(method),
3146 new_modifier: *new_modifier,
3147 is_final: *is_final,
3148 new_name: new_name.as_ref().map(owned_name),
3149 },
3150 },
3151 span: a.span,
3152 })
3153 .collect::<Vec<_>>()
3154 .into_boxed_slice(),
3155 adaptations_brace_span: t.adaptations_brace_span,
3156 doc_comment: owned_opt_comment(&t.doc_comment),
3157 }
3158}
3159
3160fn owned_class_decl(cls: &arena_ast::ClassDecl<'_, '_>) -> ClassDecl {
3161 ClassDecl {
3162 name: cls
3163 .name
3164 .map(|ident| Some(owned_ident(ident)))
3165 .unwrap_or(None),
3166 modifiers: cls.modifiers.clone(),
3167 extends: cls.extends.as_ref().map(owned_name),
3168 implements: cls
3169 .implements
3170 .iter()
3171 .map(owned_name)
3172 .collect::<Vec<_>>()
3173 .into_boxed_slice(),
3174 body: ClassBody {
3175 members: owned_class_members(&cls.body.members),
3176 span: cls.body.span,
3177 },
3178 attributes: owned_attrs(&cls.attributes),
3179 doc_comment: owned_opt_comment(&cls.doc_comment),
3180 }
3181}
3182
3183fn owned_interface_decl(iface: &arena_ast::InterfaceDecl<'_, '_>) -> InterfaceDecl {
3184 InterfaceDecl {
3185 name: owned_ident(iface.name),
3186 extends: iface
3187 .extends
3188 .iter()
3189 .map(owned_name)
3190 .collect::<Vec<_>>()
3191 .into_boxed_slice(),
3192 body: ClassBody {
3193 members: owned_class_members(&iface.body.members),
3194 span: iface.body.span,
3195 },
3196 attributes: owned_attrs(&iface.attributes),
3197 doc_comment: owned_opt_comment(&iface.doc_comment),
3198 }
3199}
3200
3201fn owned_trait_decl(tr: &arena_ast::TraitDecl<'_, '_>) -> TraitDecl {
3202 TraitDecl {
3203 name: owned_ident(tr.name),
3204 body: ClassBody {
3205 members: owned_class_members(&tr.body.members),
3206 span: tr.body.span,
3207 },
3208 attributes: owned_attrs(&tr.attributes),
3209 doc_comment: owned_opt_comment(&tr.doc_comment),
3210 }
3211}
3212
3213fn owned_enum_decl(en: &arena_ast::EnumDecl<'_, '_>) -> EnumDecl {
3214 EnumDecl {
3215 name: owned_ident(en.name),
3216 scalar_type: en.scalar_type.as_ref().map(owned_name),
3217 implements: en
3218 .implements
3219 .iter()
3220 .map(owned_name)
3221 .collect::<Vec<_>>()
3222 .into_boxed_slice(),
3223 body: EnumBody {
3224 members: en
3225 .body
3226 .members
3227 .iter()
3228 .map(|m| EnumMember {
3229 kind: match &m.kind {
3230 arena_ast::EnumMemberKind::Case(c) => EnumMemberKind::Case(EnumCase {
3231 name: owned_ident(c.name),
3232 value: c.value.as_ref().map(owned_expr),
3233 attributes: owned_attrs(&c.attributes),
3234 doc_comment: owned_opt_comment(&c.doc_comment),
3235 }),
3236 arena_ast::EnumMemberKind::Method(m) => {
3237 EnumMemberKind::Method(MethodDecl {
3238 name: owned_ident(m.name),
3239 modifiers: m.modifiers,
3240 by_ref: m.by_ref,
3241 params: owned_params(&m.params),
3242 return_type: m.return_type.as_ref().map(owned_type_hint),
3243 body: m.body.map(|b| Box::new(owned_block(b))),
3244 attributes: owned_attrs(&m.attributes),
3245 doc_comment: owned_opt_comment(&m.doc_comment),
3246 })
3247 }
3248 arena_ast::EnumMemberKind::ClassConst(c) => {
3249 EnumMemberKind::ClassConst(owned_class_const(c))
3250 }
3251 arena_ast::EnumMemberKind::TraitUse(t) => {
3252 EnumMemberKind::TraitUse(owned_trait_use(t))
3253 }
3254 },
3255 span: m.span,
3256 })
3257 .collect::<Vec<_>>()
3258 .into_boxed_slice(),
3259 span: en.body.span,
3260 },
3261 attributes: owned_attrs(&en.attributes),
3262 doc_comment: owned_opt_comment(&en.doc_comment),
3263 }
3264}
3265
3266pub fn to_owned_program(program: &arena_ast::Program<'_, '_>) -> Program {
3268 Program {
3269 stmts: owned_stmts(&program.stmts),
3270 span: program.span,
3271 }
3272}
3273
3274#[doc(hidden)]
3288pub fn from_owned_program<'arena>(
3289 arena: &'arena bumpalo::Bump,
3290 program: &Program,
3291) -> arena_ast::Program<'arena, 'arena> {
3292 arena_ast::Program {
3293 stmts: av_stmts(arena, &program.stmts),
3294 span: program.span,
3295 }
3296}
3297
3298#[inline]
3300fn av_str<'a>(arena: &'a bumpalo::Bump, s: &str) -> &'a str {
3301 arena.alloc_str(s)
3302}
3303
3304fn av_ident<'a>(arena: &'a bumpalo::Bump, ident: &Ident) -> arena_ast::Ident<'a> {
3305 match ident.as_str() {
3306 Some(s) => arena_ast::Ident::new(arena.alloc_str(s), ident.span),
3307 None => arena_ast::Ident::error(ident.span),
3308 }
3309}
3310
3311fn av_name<'a>(arena: &'a bumpalo::Bump, name: &Name) -> arena_ast::Name<'a, 'a> {
3312 if name.kind == NameKind::Error {
3313 return arena_ast::Name::Error { span: name.span };
3314 }
3315 if name.parts.len() == 1 && name.kind == NameKind::Unqualified {
3316 return arena_ast::Name::Simple {
3317 value: arena.alloc_str(&name.parts[0]),
3318 span: name.span,
3319 };
3320 }
3321 let mut parts = arena_ast::ArenaVec::with_capacity_in(name.parts.len(), arena);
3322 for p in name.parts.iter() {
3323 parts.push(arena.alloc_str(p) as &str);
3324 }
3325 arena_ast::Name::Complex {
3326 parts,
3327 kind: name.kind,
3328 span: name.span,
3329 }
3330}
3331
3332fn av_type_hint<'a>(arena: &'a bumpalo::Bump, th: &TypeHint) -> arena_ast::TypeHint<'a, 'a> {
3333 arena_ast::TypeHint {
3334 kind: av_type_hint_kind(arena, &th.kind),
3335 span: th.span,
3336 }
3337}
3338
3339fn av_type_hint_kind<'a>(
3340 arena: &'a bumpalo::Bump,
3341 k: &TypeHintKind,
3342) -> arena_ast::TypeHintKind<'a, 'a> {
3343 match k {
3344 TypeHintKind::Named(n) => arena_ast::TypeHintKind::Named(av_name(arena, n)),
3345 TypeHintKind::Keyword(b, span) => arena_ast::TypeHintKind::Keyword(*b, *span),
3346 TypeHintKind::Nullable(inner) => {
3347 arena_ast::TypeHintKind::Nullable(arena.alloc(av_type_hint(arena, inner)))
3348 }
3349 TypeHintKind::Union(types) => {
3350 let mut v = arena_ast::ArenaVec::with_capacity_in(types.len(), arena);
3351 for t in types.iter() {
3352 v.push(av_type_hint(arena, t));
3353 }
3354 arena_ast::TypeHintKind::Union(v)
3355 }
3356 TypeHintKind::Intersection(types) => {
3357 let mut v = arena_ast::ArenaVec::with_capacity_in(types.len(), arena);
3358 for t in types.iter() {
3359 v.push(av_type_hint(arena, t));
3360 }
3361 arena_ast::TypeHintKind::Intersection(v)
3362 }
3363 }
3364}
3365
3366fn av_arg<'a>(arena: &'a bumpalo::Bump, arg: &Arg) -> arena_ast::Arg<'a, 'a> {
3367 arena_ast::Arg {
3368 name: arg.name.as_ref().map(|n| av_name(arena, n)),
3369 kind: match &arg.kind {
3370 ArgKind::Value(e) => arena_ast::ArgKind::Value(av_expr(arena, e)),
3371 ArgKind::Spread(e) => arena_ast::ArgKind::Spread(av_expr(arena, e)),
3372 ArgKind::ByRef(e) => arena_ast::ArgKind::ByRef(av_expr(arena, e)),
3373 ArgKind::Placeholder => arena_ast::ArgKind::Placeholder,
3374 ArgKind::SpreadPlaceholder => arena_ast::ArgKind::SpreadPlaceholder,
3375 },
3376 span: arg.span,
3377 }
3378}
3379
3380#[inline(never)]
3381fn av_args<'a>(
3382 arena: &'a bumpalo::Bump,
3383 args: &[Arg],
3384) -> arena_ast::ArenaVec<'a, arena_ast::Arg<'a, 'a>> {
3385 let mut v = arena_ast::ArenaVec::with_capacity_in(args.len(), arena);
3386 for a in args.iter() {
3387 v.push(av_arg(arena, a));
3388 }
3389 v
3390}
3391
3392fn av_attr<'a>(arena: &'a bumpalo::Bump, attr: &Attribute) -> arena_ast::Attribute<'a, 'a> {
3393 arena_ast::Attribute {
3394 name: av_name(arena, &attr.name),
3395 args: av_args(arena, &attr.args),
3396 span: attr.span,
3397 }
3398}
3399
3400#[inline(never)]
3401fn av_attrs<'a>(
3402 arena: &'a bumpalo::Bump,
3403 attrs: &[Attribute],
3404) -> arena_ast::ArenaVec<'a, arena_ast::Attribute<'a, 'a>> {
3405 let mut v = arena_ast::ArenaVec::with_capacity_in(attrs.len(), arena);
3406 for a in attrs.iter() {
3407 v.push(av_attr(arena, a));
3408 }
3409 v
3410}
3411
3412fn av_comment<'a>(arena: &'a bumpalo::Bump, c: &Comment) -> arena_ast::Comment<'a> {
3413 arena_ast::Comment {
3414 kind: c.kind,
3415 text: arena.alloc_str(&c.text),
3416 span: c.span,
3417 }
3418}
3419
3420fn av_opt_comment<'a>(
3421 arena: &'a bumpalo::Bump,
3422 c: &Option<Comment>,
3423) -> Option<arena_ast::Comment<'a>> {
3424 c.as_ref().map(|c| av_comment(arena, c))
3425}
3426
3427fn av_string_parts<'a>(
3428 arena: &'a bumpalo::Bump,
3429 parts: &[StringPart],
3430) -> arena_ast::ArenaVec<'a, arena_ast::StringPart<'a, 'a>> {
3431 let mut v = arena_ast::ArenaVec::with_capacity_in(parts.len(), arena);
3432 for p in parts.iter() {
3433 v.push(match p {
3434 StringPart::Literal(s) => {
3435 arena_ast::StringPart::Literal(arena_ast::ByteStr::new_in(arena, s.as_bytes()))
3436 }
3437 StringPart::Expr(e) => arena_ast::StringPart::Expr(av_expr(arena, e)),
3438 });
3439 }
3440 v
3441}
3442
3443fn av_expr<'a>(arena: &'a bumpalo::Bump, expr: &Expr) -> arena_ast::Expr<'a, 'a> {
3444 if !owned_is_chain(&expr.kind) {
3445 return arena_ast::Expr {
3446 kind: av_leaf_kind(arena, &expr.kind),
3447 span: expr.span,
3448 };
3449 }
3450 av_chain_expr(arena, expr)
3451}
3452
3453#[inline(never)]
3455fn av_chain_expr<'a>(arena: &'a bumpalo::Bump, expr: &Expr) -> arena_ast::Expr<'a, 'a> {
3456 let first = owned_chain_operand(&expr.kind).expect("chain link has an operand");
3457 if !owned_is_chain(&first.kind) {
3458 let operand = arena_ast::Expr {
3459 kind: av_leaf_kind(arena, &first.kind),
3460 span: first.span,
3461 };
3462 return arena_ast::Expr {
3463 kind: av_link_kind(arena, &expr.kind, operand),
3464 span: expr.span,
3465 };
3466 }
3467 let mut chain = LinkStack::new();
3468 chain.push(expr);
3469 let mut leaf = first;
3470 while let Some(operand) = owned_chain_operand(&leaf.kind) {
3471 chain.push(leaf);
3472 leaf = operand;
3473 }
3474 let mut converted = arena_ast::Expr {
3475 kind: av_leaf_kind(arena, &leaf.kind),
3476 span: leaf.span,
3477 };
3478 while let Some(node) = chain.pop() {
3479 converted = arena_ast::Expr {
3480 kind: av_link_kind(arena, &node.kind, converted),
3481 span: node.span,
3482 };
3483 }
3484 converted
3485}
3486
3487#[inline(never)]
3488fn av_exprs<'a>(
3489 arena: &'a bumpalo::Bump,
3490 exprs: &[Expr],
3491) -> arena_ast::ArenaVec<'a, arena_ast::Expr<'a, 'a>> {
3492 let mut v = arena_ast::ArenaVec::with_capacity_in(exprs.len(), arena);
3493 for e in exprs.iter() {
3494 v.push(av_expr(arena, e));
3495 }
3496 v
3497}
3498
3499fn av_namestr<'a>(arena: &'a bumpalo::Bump, s: &str) -> arena_ast::NameStr<'a, 'a> {
3500 arena_ast::NameStr::from_arena(arena.alloc_str(s))
3501}
3502
3503fn av_leaf_kind<'a>(arena: &'a bumpalo::Bump, k: &ExprKind) -> arena_ast::ExprKind<'a, 'a> {
3505 match k {
3506 ExprKind::Int(v) => arena_ast::ExprKind::Int(*v),
3507 ExprKind::Float(v) => arena_ast::ExprKind::Float(*v),
3508 ExprKind::String(s) => {
3509 arena_ast::ExprKind::String(arena_ast::ByteStr::new_in(arena, s.as_bytes()))
3510 }
3511 ExprKind::InterpolatedString(parts) => {
3512 arena_ast::ExprKind::InterpolatedString(av_string_parts(arena, parts))
3513 }
3514 ExprKind::Heredoc { label, parts } => arena_ast::ExprKind::Heredoc {
3515 label: arena.alloc_str(label),
3516 parts: av_string_parts(arena, parts),
3517 },
3518 ExprKind::Nowdoc { label, value } => arena_ast::ExprKind::Nowdoc {
3519 label: arena.alloc_str(label),
3520 value: arena.alloc_str(value),
3521 },
3522 ExprKind::ShellExec(parts) => arena_ast::ExprKind::ShellExec(av_string_parts(arena, parts)),
3523 ExprKind::Bool(v) => arena_ast::ExprKind::Bool(*v),
3524 ExprKind::Null => arena_ast::ExprKind::Null,
3525 ExprKind::Variable(s) => arena_ast::ExprKind::Variable(av_namestr(arena, s)),
3526 ExprKind::VariableVariable(inner) => {
3527 arena_ast::ExprKind::VariableVariable(arena.alloc(av_expr(arena, inner)))
3528 }
3529 ExprKind::Identifier(s) => arena_ast::ExprKind::Identifier(av_namestr(arena, s)),
3530 ExprKind::Name(name) => arena_ast::ExprKind::Name(av_name(arena, name)),
3531 ExprKind::Array(elems) => {
3532 let mut v = arena_ast::ArenaVec::with_capacity_in(elems.len(), arena);
3533 for e in elems.iter() {
3534 v.push(arena_ast::ArrayElement {
3535 key: e.key.as_ref().map(|k| av_expr(arena, k)),
3536 kind: match &e.kind {
3537 ArrayElementKind::Value(v) => {
3538 arena_ast::ArrayElementKind::Value(av_expr(arena, v))
3539 }
3540 ArrayElementKind::Spread(v) => {
3541 arena_ast::ArrayElementKind::Spread(av_expr(arena, v))
3542 }
3543 ArrayElementKind::ByRef(v) => {
3544 arena_ast::ArrayElementKind::ByRef(av_expr(arena, v))
3545 }
3546 },
3547 span: e.span,
3548 });
3549 }
3550 arena_ast::ExprKind::Array(v)
3551 }
3552 ExprKind::Print(e) => arena_ast::ExprKind::Print(arena.alloc(av_expr(arena, e))),
3553 ExprKind::Parenthesized(e) => {
3554 arena_ast::ExprKind::Parenthesized(arena.alloc(av_expr(arena, e)))
3555 }
3556 ExprKind::Cast(kind, e) => arena_ast::ExprKind::Cast(*kind, arena.alloc(av_expr(arena, e))),
3557 ExprKind::ErrorSuppress(e) => {
3558 arena_ast::ExprKind::ErrorSuppress(arena.alloc(av_expr(arena, e)))
3559 }
3560 ExprKind::Isset(exprs) => arena_ast::ExprKind::Isset(av_exprs(arena, exprs)),
3561 ExprKind::Empty(e) => arena_ast::ExprKind::Empty(arena.alloc(av_expr(arena, e))),
3562 ExprKind::Include(kind, e) => {
3563 arena_ast::ExprKind::Include(*kind, arena.alloc(av_expr(arena, e)))
3564 }
3565 ExprKind::Eval(e) => arena_ast::ExprKind::Eval(arena.alloc(av_expr(arena, e))),
3566 ExprKind::Exit(e) => {
3567 arena_ast::ExprKind::Exit(e.as_ref().map(|e| &*arena.alloc(av_expr(arena, e))))
3568 }
3569 ExprKind::MagicConst(m) => arena_ast::ExprKind::MagicConst(*m),
3570 ExprKind::Clone(e) => arena_ast::ExprKind::Clone(arena.alloc(av_expr(arena, e))),
3571 ExprKind::CloneWith(obj, props) => arena_ast::ExprKind::CloneWith(
3572 arena.alloc(av_expr(arena, obj)),
3573 arena.alloc(av_expr(arena, props)),
3574 ),
3575 ExprKind::New(n) => arena_ast::ExprKind::New(arena_ast::NewExpr {
3576 class: arena.alloc(av_expr(arena, &n.class)),
3577 args: av_args(arena, &n.args),
3578 }),
3579 ExprKind::Closure(c) => arena_ast::ExprKind::Closure(arena.alloc(arena_ast::ClosureExpr {
3580 is_static: c.is_static,
3581 by_ref: c.by_ref,
3582 params: av_params(arena, &c.params),
3583 use_vars: {
3584 let mut v = arena_ast::ArenaVec::with_capacity_in(c.use_vars.len(), arena);
3585 for uv in c.use_vars.iter() {
3586 v.push(arena_ast::ClosureUseVar {
3587 name: av_ident(arena, &uv.name),
3588 by_ref: uv.by_ref,
3589 span: uv.span,
3590 });
3591 }
3592 v
3593 },
3594 return_type: c.return_type.as_ref().map(|t| av_type_hint(arena, t)),
3595 body: &*arena.alloc(av_block(arena, &c.body)),
3596 attributes: av_attrs(arena, &c.attributes),
3597 })),
3598 ExprKind::ArrowFunction(f) => {
3599 arena_ast::ExprKind::ArrowFunction(arena.alloc(arena_ast::ArrowFunctionExpr {
3600 is_static: f.is_static,
3601 by_ref: f.by_ref,
3602 params: av_params(arena, &f.params),
3603 return_type: f.return_type.as_ref().map(|t| av_type_hint(arena, t)),
3604 body: arena.alloc(av_expr(arena, &f.body)),
3605 attributes: av_attrs(arena, &f.attributes),
3606 }))
3607 }
3608 ExprKind::Match(m) => arena_ast::ExprKind::Match(arena_ast::MatchExpr {
3609 subject: arena.alloc(av_expr(arena, &m.subject)),
3610 arms: {
3611 let mut v = arena_ast::ArenaVec::with_capacity_in(m.arms.len(), arena);
3612 for arm in m.arms.iter() {
3613 v.push(arena_ast::MatchArm {
3614 conditions: arm.conditions.as_ref().map(|conds| av_exprs(arena, conds)),
3615 body: av_expr(arena, &arm.body),
3616 span: arm.span,
3617 });
3618 }
3619 v
3620 },
3621 brace_span: m.brace_span,
3622 }),
3623 ExprKind::Throw(e) => arena_ast::ExprKind::Throw(arena.alloc(av_expr(arena, e))),
3624 ExprKind::Yield(y) => arena_ast::ExprKind::Yield(arena_ast::YieldExpr {
3625 key: y.key.as_ref().map(|e| &*arena.alloc(av_expr(arena, e))),
3626 value: y.value.as_ref().map(|e| &*arena.alloc(av_expr(arena, e))),
3627 is_from: y.is_from,
3628 }),
3629 ExprKind::AnonymousClass(cls) => {
3630 arena_ast::ExprKind::AnonymousClass(arena.alloc(av_class_decl(arena, cls)))
3631 }
3632 ExprKind::Omit => arena_ast::ExprKind::Omit,
3633 ExprKind::Error => arena_ast::ExprKind::Error,
3634 ExprKind::Assign(_)
3635 | ExprKind::Binary(_)
3636 | ExprKind::UnaryPrefix(_)
3637 | ExprKind::UnaryPostfix(_)
3638 | ExprKind::Ternary(_)
3639 | ExprKind::NullCoalesce(_)
3640 | ExprKind::FunctionCall(_)
3641 | ExprKind::ArrayAccess(_)
3642 | ExprKind::PropertyAccess(_)
3643 | ExprKind::NullsafePropertyAccess(_)
3644 | ExprKind::MethodCall(_)
3645 | ExprKind::NullsafeMethodCall(_)
3646 | ExprKind::StaticPropertyAccess(_)
3647 | ExprKind::ClassConstAccess(_)
3648 | ExprKind::StaticMethodCall(_)
3649 | ExprKind::StaticMethodCallDynamic(_)
3650 | ExprKind::ClassConstAccessDynamic { .. }
3651 | ExprKind::StaticPropertyAccessDynamic { .. }
3652 | ExprKind::CallableCreate(_) => {
3653 unreachable!("chain links are converted by the link function")
3654 }
3655 }
3656}
3657
3658fn av_link_kind<'a>(
3660 arena: &'a bumpalo::Bump,
3661 k: &ExprKind,
3662 operand: arena_ast::Expr<'a, 'a>,
3663) -> arena_ast::ExprKind<'a, 'a> {
3664 match k {
3665 ExprKind::Assign(a) => arena_ast::ExprKind::Assign(arena_ast::AssignExpr {
3666 target: arena.alloc(operand),
3667 op: a.op,
3668 value: arena.alloc(av_expr(arena, &a.value)),
3669 by_ref: a.by_ref,
3670 }),
3671 ExprKind::Binary(b) => arena_ast::ExprKind::Binary(arena_ast::BinaryExpr {
3672 left: arena.alloc(operand),
3673 op: b.op,
3674 right: arena.alloc(av_expr(arena, &b.right)),
3675 }),
3676 ExprKind::UnaryPrefix(u) => arena_ast::ExprKind::UnaryPrefix(arena_ast::UnaryPrefixExpr {
3677 op: u.op,
3678 operand: arena.alloc(operand),
3679 }),
3680 ExprKind::UnaryPostfix(u) => {
3681 arena_ast::ExprKind::UnaryPostfix(arena_ast::UnaryPostfixExpr {
3682 operand: arena.alloc(operand),
3683 op: u.op,
3684 })
3685 }
3686 ExprKind::Ternary(t) => arena_ast::ExprKind::Ternary(arena_ast::TernaryExpr {
3687 condition: arena.alloc(operand),
3688 then_expr: t
3689 .then_expr
3690 .as_ref()
3691 .map(|e| &*arena.alloc(av_expr(arena, e))),
3692 else_expr: arena.alloc(av_expr(arena, &t.else_expr)),
3693 }),
3694 ExprKind::NullCoalesce(n) => {
3695 arena_ast::ExprKind::NullCoalesce(arena_ast::NullCoalesceExpr {
3696 left: arena.alloc(operand),
3697 right: arena.alloc(av_expr(arena, &n.right)),
3698 })
3699 }
3700 ExprKind::FunctionCall(f) => {
3701 arena_ast::ExprKind::FunctionCall(arena_ast::FunctionCallExpr {
3702 name: arena.alloc(operand),
3703 args: av_args(arena, &f.args),
3704 })
3705 }
3706 ExprKind::ArrayAccess(a) => arena_ast::ExprKind::ArrayAccess(arena_ast::ArrayAccessExpr {
3707 array: arena.alloc(operand),
3708 index: a.index.as_ref().map(|e| &*arena.alloc(av_expr(arena, e))),
3709 }),
3710 ExprKind::PropertyAccess(p) => {
3711 arena_ast::ExprKind::PropertyAccess(arena_ast::PropertyAccessExpr {
3712 object: arena.alloc(operand),
3713 property: arena.alloc(av_expr(arena, &p.property)),
3714 })
3715 }
3716 ExprKind::NullsafePropertyAccess(p) => {
3717 arena_ast::ExprKind::NullsafePropertyAccess(arena_ast::PropertyAccessExpr {
3718 object: arena.alloc(operand),
3719 property: arena.alloc(av_expr(arena, &p.property)),
3720 })
3721 }
3722 ExprKind::MethodCall(m) => {
3723 arena_ast::ExprKind::MethodCall(arena.alloc(arena_ast::MethodCallExpr {
3724 object: arena.alloc(operand),
3725 method: arena.alloc(av_expr(arena, &m.method)),
3726 args: av_args(arena, &m.args),
3727 }))
3728 }
3729 ExprKind::NullsafeMethodCall(m) => {
3730 arena_ast::ExprKind::NullsafeMethodCall(arena.alloc(arena_ast::MethodCallExpr {
3731 object: arena.alloc(operand),
3732 method: arena.alloc(av_expr(arena, &m.method)),
3733 args: av_args(arena, &m.args),
3734 }))
3735 }
3736 ExprKind::StaticPropertyAccess(s) => {
3737 arena_ast::ExprKind::StaticPropertyAccess(arena_ast::StaticAccessExpr {
3738 class: arena.alloc(operand),
3739 member: arena.alloc(av_expr(arena, &s.member)),
3740 })
3741 }
3742 ExprKind::StaticMethodCall(s) => {
3743 arena_ast::ExprKind::StaticMethodCall(arena.alloc(arena_ast::StaticMethodCallExpr {
3744 class: arena.alloc(operand),
3745 method: arena.alloc(av_expr(arena, &s.method)),
3746 args: av_args(arena, &s.args),
3747 }))
3748 }
3749 ExprKind::StaticMethodCallDynamic(s) => arena_ast::ExprKind::StaticMethodCallDynamic(
3750 arena.alloc(arena_ast::StaticMethodCallDynamicExpr {
3751 class: arena.alloc(operand),
3752 method: arena.alloc(av_expr(arena, &s.method)),
3753 args: av_args(arena, &s.args),
3754 }),
3755 ),
3756 ExprKind::ClassConstAccess(s) => {
3757 arena_ast::ExprKind::ClassConstAccess(arena_ast::StaticAccessExpr {
3758 class: arena.alloc(operand),
3759 member: arena.alloc(av_expr(arena, &s.member)),
3760 })
3761 }
3762 ExprKind::ClassConstAccessDynamic { member, .. } => {
3763 arena_ast::ExprKind::ClassConstAccessDynamic {
3764 class: arena.alloc(operand),
3765 member: arena.alloc(av_expr(arena, member)),
3766 }
3767 }
3768 ExprKind::StaticPropertyAccessDynamic { member, .. } => {
3769 arena_ast::ExprKind::StaticPropertyAccessDynamic {
3770 class: arena.alloc(operand),
3771 member: arena.alloc(av_expr(arena, member)),
3772 }
3773 }
3774 ExprKind::CallableCreate(c) => {
3775 arena_ast::ExprKind::CallableCreate(arena_ast::CallableCreateExpr {
3776 kind: match &c.kind {
3777 CallableCreateKind::Function(_) => {
3778 arena_ast::CallableCreateKind::Function(arena.alloc(operand))
3779 }
3780 CallableCreateKind::Method { method, .. } => {
3781 arena_ast::CallableCreateKind::Method {
3782 object: arena.alloc(operand),
3783 method: arena.alloc(av_expr(arena, method)),
3784 }
3785 }
3786 CallableCreateKind::NullsafeMethod { method, .. } => {
3787 arena_ast::CallableCreateKind::NullsafeMethod {
3788 object: arena.alloc(operand),
3789 method: arena.alloc(av_expr(arena, method)),
3790 }
3791 }
3792 CallableCreateKind::StaticMethod { method, .. } => {
3793 arena_ast::CallableCreateKind::StaticMethod {
3794 class: arena.alloc(operand),
3795 method: arena.alloc(av_expr(arena, method)),
3796 }
3797 }
3798 },
3799 })
3800 }
3801 _ => unreachable!("not a chain link"),
3802 }
3803}
3804
3805fn av_param<'a>(arena: &'a bumpalo::Bump, p: &Param) -> arena_ast::Param<'a, 'a> {
3806 arena_ast::Param {
3807 name: av_ident(arena, &p.name),
3808 type_hint: p.type_hint.as_ref().map(|t| av_type_hint(arena, t)),
3809 default: p.default.as_ref().map(|e| av_expr(arena, e)),
3810 by_ref: p.by_ref,
3811 variadic: p.variadic,
3812 modifiers: p.modifiers,
3813 attributes: av_attrs(arena, &p.attributes),
3814 hooks: av_hooks(arena, &p.hooks),
3815 doc_comment: av_opt_comment(arena, &p.doc_comment),
3816 span: p.span,
3817 }
3818}
3819
3820#[inline(never)]
3821fn av_params<'a>(
3822 arena: &'a bumpalo::Bump,
3823 params: &[Param],
3824) -> arena_ast::ArenaVec<'a, arena_ast::Param<'a, 'a>> {
3825 let mut v = arena_ast::ArenaVec::with_capacity_in(params.len(), arena);
3826 for p in params.iter() {
3827 v.push(av_param(arena, p));
3828 }
3829 v
3830}
3831
3832fn av_hook<'a>(arena: &'a bumpalo::Bump, h: &PropertyHook) -> arena_ast::PropertyHook<'a, 'a> {
3833 arena_ast::PropertyHook {
3834 kind: h.kind,
3835 body: match &h.body {
3836 PropertyHookBody::Block(block) => {
3837 arena_ast::PropertyHookBody::Block(arena.alloc(av_block(arena, block)))
3838 }
3839 PropertyHookBody::Expression(e) => {
3840 arena_ast::PropertyHookBody::Expression(av_expr(arena, e))
3841 }
3842 PropertyHookBody::Abstract => arena_ast::PropertyHookBody::Abstract,
3843 },
3844 modifiers: h.modifiers,
3845 by_ref: h.by_ref,
3846 params: av_params(arena, &h.params),
3847 attributes: av_attrs(arena, &h.attributes),
3848 span: h.span,
3849 }
3850}
3851
3852fn av_hooks<'a>(
3853 arena: &'a bumpalo::Bump,
3854 hooks: &[PropertyHook],
3855) -> arena_ast::ArenaVec<'a, arena_ast::PropertyHook<'a, 'a>> {
3856 let mut v = arena_ast::ArenaVec::with_capacity_in(hooks.len(), arena);
3857 for h in hooks.iter() {
3858 v.push(av_hook(arena, h));
3859 }
3860 v
3861}
3862
3863fn av_stmt<'a>(arena: &'a bumpalo::Bump, stmt: &Stmt) -> arena_ast::Stmt<'a, 'a> {
3864 arena_ast::Stmt {
3865 kind: av_stmt_kind(arena, &stmt.kind),
3866 span: stmt.span,
3867 doc_comment: stmt.doc_comment.as_ref().map(|c| {
3868 &*arena.alloc(arena_ast::Comment {
3869 kind: c.kind,
3870 text: arena.alloc_str(&c.text),
3871 span: c.span,
3872 })
3873 }),
3874 }
3875}
3876
3877fn av_stmts<'a>(
3878 arena: &'a bumpalo::Bump,
3879 stmts: &[Stmt],
3880) -> arena_ast::ArenaVec<'a, arena_ast::Stmt<'a, 'a>> {
3881 let mut v = arena_ast::ArenaVec::with_capacity_in(stmts.len(), arena);
3882 for s in stmts.iter() {
3883 v.push(av_stmt(arena, s));
3884 }
3885 v
3886}
3887
3888fn av_block<'a>(arena: &'a bumpalo::Bump, block: &Block) -> arena_ast::Block<'a, 'a> {
3889 arena_ast::Block {
3890 stmts: av_stmts(arena, &block.stmts),
3891 span: block.span,
3892 }
3893}
3894
3895fn av_stmt_kind<'a>(arena: &'a bumpalo::Bump, k: &StmtKind) -> arena_ast::StmtKind<'a, 'a> {
3896 match k {
3897 StmtKind::Expression(e) => arena_ast::StmtKind::Expression(arena.alloc(av_expr(arena, e))),
3898 StmtKind::Echo(exprs) => arena_ast::StmtKind::Echo(av_exprs(arena, exprs)),
3899 StmtKind::Return(e) => {
3900 arena_ast::StmtKind::Return(e.as_ref().map(|e| &*arena.alloc(av_expr(arena, e))))
3901 }
3902 StmtKind::Block(block) => arena_ast::StmtKind::Block(arena.alloc(av_block(arena, block))),
3903 StmtKind::If(s) => arena_ast::StmtKind::If(arena.alloc(av_if_stmt(arena, s))),
3904 StmtKind::While(s) => arena_ast::StmtKind::While(arena.alloc(av_while_stmt(arena, s))),
3905 StmtKind::For(s) => arena_ast::StmtKind::For(arena.alloc(av_for_stmt(arena, s))),
3906 StmtKind::Foreach(s) => {
3907 arena_ast::StmtKind::Foreach(arena.alloc(av_foreach_stmt(arena, s)))
3908 }
3909 StmtKind::DoWhile(s) => {
3910 arena_ast::StmtKind::DoWhile(arena.alloc(av_do_while_stmt(arena, s)))
3911 }
3912 StmtKind::Function(f) => {
3913 arena_ast::StmtKind::Function(arena.alloc(av_function_decl(arena, f)))
3914 }
3915 StmtKind::Break(e) => {
3916 arena_ast::StmtKind::Break(e.as_ref().map(|e| &*arena.alloc(av_expr(arena, e))))
3917 }
3918 StmtKind::Continue(e) => {
3919 arena_ast::StmtKind::Continue(e.as_ref().map(|e| &*arena.alloc(av_expr(arena, e))))
3920 }
3921 StmtKind::Switch(s) => arena_ast::StmtKind::Switch(arena.alloc(av_switch_stmt(arena, s))),
3922 StmtKind::Goto(ident) => arena_ast::StmtKind::Goto(av_ident(arena, ident)),
3923 StmtKind::Label(ident) => arena_ast::StmtKind::Label(av_ident(arena, ident)),
3924 StmtKind::Declare(d) => {
3925 arena_ast::StmtKind::Declare(arena.alloc(av_declare_stmt(arena, d)))
3926 }
3927 StmtKind::Unset(exprs) => arena_ast::StmtKind::Unset(av_exprs(arena, exprs)),
3928 StmtKind::Throw(e) => arena_ast::StmtKind::Throw(arena.alloc(av_expr(arena, e))),
3929 StmtKind::TryCatch(t) => {
3930 arena_ast::StmtKind::TryCatch(arena.alloc(av_try_catch_stmt(arena, t)))
3931 }
3932 StmtKind::Global(exprs) => arena_ast::StmtKind::Global(av_exprs(arena, exprs)),
3933 StmtKind::Class(cls) => arena_ast::StmtKind::Class(arena.alloc(av_class_decl(arena, cls))),
3934 StmtKind::Interface(iface) => {
3935 arena_ast::StmtKind::Interface(arena.alloc(av_interface_decl(arena, iface)))
3936 }
3937 StmtKind::Trait(tr) => arena_ast::StmtKind::Trait(arena.alloc(av_trait_decl(arena, tr))),
3938 StmtKind::Enum(en) => arena_ast::StmtKind::Enum(arena.alloc(av_enum_decl(arena, en))),
3939 StmtKind::Namespace(ns) => {
3940 arena_ast::StmtKind::Namespace(arena.alloc(av_namespace_decl(arena, ns)))
3941 }
3942 StmtKind::Use(u) => arena_ast::StmtKind::Use(arena.alloc(av_use_decl(arena, u))),
3943 StmtKind::Const(items) => arena_ast::StmtKind::Const(av_const_items(arena, items)),
3944 StmtKind::StaticVar(vars) => arena_ast::StmtKind::StaticVar(av_static_vars(arena, vars)),
3945 StmtKind::HaltCompiler(s) => arena_ast::StmtKind::HaltCompiler(av_str(arena, s)),
3946 StmtKind::Nop => arena_ast::StmtKind::Nop,
3947 StmtKind::InlineHtml(s) => arena_ast::StmtKind::InlineHtml(av_str(arena, s)),
3948 StmtKind::Error => arena_ast::StmtKind::Error,
3949 }
3950}
3951
3952#[inline(never)]
3955fn av_if_stmt<'a>(arena: &'a bumpalo::Bump, s: &IfStmt) -> arena_ast::IfStmt<'a, 'a> {
3956 arena_ast::IfStmt {
3957 condition: av_expr(arena, &s.condition),
3958 then_branch: arena.alloc(av_stmt(arena, &s.then_branch)),
3959 elseif_branches: {
3960 let mut v = arena_ast::ArenaVec::with_capacity_in(s.elseif_branches.len(), arena);
3961 for b in s.elseif_branches.iter() {
3962 v.push(arena_ast::ElseIfBranch {
3963 condition: av_expr(arena, &b.condition),
3964 body: av_stmt(arena, &b.body),
3965 span: b.span,
3966 });
3967 }
3968 v
3969 },
3970 else_branch: s
3971 .else_branch
3972 .as_ref()
3973 .map(|b| &*arena.alloc(av_stmt(arena, b))),
3974 else_kw_span: s.else_kw_span,
3975 uses_alternative: s.uses_alternative,
3976 }
3977}
3978
3979#[inline(never)]
3980fn av_while_stmt<'a>(arena: &'a bumpalo::Bump, s: &WhileStmt) -> arena_ast::WhileStmt<'a, 'a> {
3981 arena_ast::WhileStmt {
3982 condition: av_expr(arena, &s.condition),
3983 body: arena.alloc(av_stmt(arena, &s.body)),
3984 uses_alternative: s.uses_alternative,
3985 }
3986}
3987
3988#[inline(never)]
3989fn av_for_stmt<'a>(arena: &'a bumpalo::Bump, s: &ForStmt) -> arena_ast::ForStmt<'a, 'a> {
3990 arena_ast::ForStmt {
3991 init: av_exprs(arena, &s.init),
3992 condition: av_exprs(arena, &s.condition),
3993 update: av_exprs(arena, &s.update),
3994 body: arena.alloc(av_stmt(arena, &s.body)),
3995 uses_alternative: s.uses_alternative,
3996 }
3997}
3998
3999#[inline(never)]
4000fn av_foreach_stmt<'a>(
4001 arena: &'a bumpalo::Bump,
4002 s: &ForeachStmt,
4003) -> arena_ast::ForeachStmt<'a, 'a> {
4004 arena_ast::ForeachStmt {
4005 expr: av_expr(arena, &s.expr),
4006 key: s.key.as_ref().map(|e| av_expr(arena, e)),
4007 value: av_expr(arena, &s.value),
4008 by_ref: s.by_ref,
4009 body: arena.alloc(av_stmt(arena, &s.body)),
4010 uses_alternative: s.uses_alternative,
4011 }
4012}
4013
4014#[inline(never)]
4015fn av_do_while_stmt<'a>(
4016 arena: &'a bumpalo::Bump,
4017 s: &DoWhileStmt,
4018) -> arena_ast::DoWhileStmt<'a, 'a> {
4019 arena_ast::DoWhileStmt {
4020 body: arena.alloc(av_stmt(arena, &s.body)),
4021 condition: av_expr(arena, &s.condition),
4022 }
4023}
4024
4025#[inline(never)]
4026fn av_switch_stmt<'a>(arena: &'a bumpalo::Bump, s: &SwitchStmt) -> arena_ast::SwitchStmt<'a, 'a> {
4027 arena_ast::SwitchStmt {
4028 expr: av_expr(arena, &s.expr),
4029 body: {
4030 let mut cases = arena_ast::ArenaVec::with_capacity_in(s.body.cases.len(), arena);
4031 for c in s.body.cases.iter() {
4032 cases.push(arena_ast::SwitchCase {
4033 value: c.value.as_ref().map(|vl| av_expr(arena, vl)),
4034 body: av_stmts(arena, &c.body),
4035 span: c.span,
4036 });
4037 }
4038 arena_ast::SwitchBody {
4039 cases,
4040 span: s.body.span,
4041 }
4042 },
4043 uses_alternative: s.uses_alternative,
4044 }
4045}
4046
4047#[inline(never)]
4048fn av_declare_stmt<'a>(
4049 arena: &'a bumpalo::Bump,
4050 d: &DeclareStmt,
4051) -> arena_ast::DeclareStmt<'a, 'a> {
4052 arena_ast::DeclareStmt {
4053 directives: {
4054 let mut v = arena_ast::ArenaVec::with_capacity_in(d.directives.len(), arena);
4055 for (k, val) in d.directives.iter() {
4056 v.push((arena.alloc_str(k) as &str, av_expr(arena, val)));
4057 }
4058 v
4059 },
4060 body: d.body.as_ref().map(|b| &*arena.alloc(av_stmt(arena, b))),
4061 uses_alternative: d.uses_alternative,
4062 }
4063}
4064
4065#[inline(never)]
4066fn av_try_catch_stmt<'a>(
4067 arena: &'a bumpalo::Bump,
4068 t: &TryCatchStmt,
4069) -> arena_ast::TryCatchStmt<'a, 'a> {
4070 arena_ast::TryCatchStmt {
4071 body: arena.alloc(av_block(arena, &t.body)),
4072 catches: {
4073 let mut v = arena_ast::ArenaVec::with_capacity_in(t.catches.len(), arena);
4074 for c in t.catches.iter() {
4075 let mut types = arena_ast::ArenaVec::with_capacity_in(c.types.len(), arena);
4076 for n in c.types.iter() {
4077 types.push(av_name(arena, n));
4078 }
4079 v.push(arena_ast::CatchClause {
4080 types,
4081 var: c.var.as_ref().map(|v| av_ident(arena, v)),
4082 body: arena.alloc(av_block(arena, &c.body)),
4083 span: c.span,
4084 });
4085 }
4086 v
4087 },
4088 finally: t
4089 .finally
4090 .as_deref()
4091 .map(|f| &*arena.alloc(av_block(arena, f))),
4092 finally_kw_span: t.finally_kw_span,
4093 }
4094}
4095
4096#[inline(never)]
4097fn av_namespace_decl<'a>(
4098 arena: &'a bumpalo::Bump,
4099 ns: &NamespaceDecl,
4100) -> arena_ast::NamespaceDecl<'a, 'a> {
4101 arena_ast::NamespaceDecl {
4102 name: ns.name.as_ref().map(|n| av_name(arena, n)),
4103 body: match &ns.body {
4104 NamespaceBody::Braced(block) => {
4105 arena_ast::NamespaceBody::Braced(&*arena.alloc(av_block(arena, block)))
4106 }
4107 NamespaceBody::Simple => arena_ast::NamespaceBody::Simple,
4108 },
4109 }
4110}
4111
4112#[inline(never)]
4113fn av_use_decl<'a>(arena: &'a bumpalo::Bump, u: &UseDecl) -> arena_ast::UseDecl<'a, 'a> {
4114 arena_ast::UseDecl {
4115 kind: u.kind,
4116 uses: {
4117 let mut v = arena_ast::ArenaVec::with_capacity_in(u.uses.len(), arena);
4118 for item in u.uses.iter() {
4119 v.push(arena_ast::UseItem {
4120 name: av_name(arena, &item.name),
4121 alias: item.alias.as_ref().map(|a| av_ident(arena, a)),
4122 kind: item.kind,
4123 span: item.span,
4124 });
4125 }
4126 v
4127 },
4128 }
4129}
4130
4131#[inline(never)]
4132fn av_const_items<'a>(
4133 arena: &'a bumpalo::Bump,
4134 items: &[ConstItem],
4135) -> arena_ast::ArenaVec<'a, arena_ast::ConstItem<'a, 'a>> {
4136 let mut v = arena_ast::ArenaVec::with_capacity_in(items.len(), arena);
4137 for item in items.iter() {
4138 v.push(arena_ast::ConstItem {
4139 name: av_ident(arena, &item.name),
4140 value: av_expr(arena, &item.value),
4141 attributes: av_attrs(arena, &item.attributes),
4142 span: item.span,
4143 doc_comment: av_opt_comment(arena, &item.doc_comment),
4144 });
4145 }
4146 v
4147}
4148
4149#[inline(never)]
4150fn av_static_vars<'a>(
4151 arena: &'a bumpalo::Bump,
4152 vars: &[StaticVar],
4153) -> arena_ast::ArenaVec<'a, arena_ast::StaticVar<'a, 'a>> {
4154 let mut v = arena_ast::ArenaVec::with_capacity_in(vars.len(), arena);
4155 for var in vars.iter() {
4156 v.push(arena_ast::StaticVar {
4157 name: av_ident(arena, &var.name),
4158 default: var.default.as_ref().map(|e| av_expr(arena, e)),
4159 span: var.span,
4160 });
4161 }
4162 v
4163}
4164
4165#[inline(never)]
4166fn av_function_decl<'a>(
4167 arena: &'a bumpalo::Bump,
4168 f: &FunctionDecl,
4169) -> arena_ast::FunctionDecl<'a, 'a> {
4170 arena_ast::FunctionDecl {
4171 name: av_ident(arena, &f.name),
4172 params: av_params(arena, &f.params),
4173 body: &*arena.alloc(av_block(arena, &f.body)),
4174 return_type: f.return_type.as_ref().map(|t| av_type_hint(arena, t)),
4175 by_ref: f.by_ref,
4176 attributes: av_attrs(arena, &f.attributes),
4177 doc_comment: av_opt_comment(arena, &f.doc_comment),
4178 }
4179}
4180
4181fn av_class_member<'a>(
4182 arena: &'a bumpalo::Bump,
4183 m: &ClassMember,
4184) -> arena_ast::ClassMember<'a, 'a> {
4185 arena_ast::ClassMember {
4186 kind: match &m.kind {
4187 ClassMemberKind::Property(p) => {
4188 arena_ast::ClassMemberKind::Property(arena_ast::PropertyDecl {
4189 name: av_ident(arena, &p.name),
4190 modifiers: p.modifiers,
4191 type_hint: p.type_hint.as_ref().map(|t| av_type_hint(arena, t)),
4192 default: p.default.as_ref().map(|e| av_expr(arena, e)),
4193 attributes: av_attrs(arena, &p.attributes),
4194 hooks: av_hooks(arena, &p.hooks),
4195 doc_comment: av_opt_comment(arena, &p.doc_comment),
4196 })
4197 }
4198 ClassMemberKind::Method(m) => {
4199 arena_ast::ClassMemberKind::Method(arena_ast::MethodDecl {
4200 name: av_ident(arena, &m.name),
4201 modifiers: m.modifiers,
4202 by_ref: m.by_ref,
4203 params: av_params(arena, &m.params),
4204 return_type: m.return_type.as_ref().map(|t| av_type_hint(arena, t)),
4205 body: m.body.as_deref().map(|b| &*arena.alloc(av_block(arena, b))),
4206 attributes: av_attrs(arena, &m.attributes),
4207 doc_comment: av_opt_comment(arena, &m.doc_comment),
4208 })
4209 }
4210 ClassMemberKind::ClassConst(c) => {
4211 arena_ast::ClassMemberKind::ClassConst(av_class_const(arena, c))
4212 }
4213 ClassMemberKind::TraitUse(t) => {
4214 arena_ast::ClassMemberKind::TraitUse(av_trait_use(arena, t))
4215 }
4216 },
4217 span: m.span,
4218 }
4219}
4220
4221fn av_class_members<'a>(
4222 arena: &'a bumpalo::Bump,
4223 members: &[ClassMember],
4224) -> arena_ast::ArenaVec<'a, arena_ast::ClassMember<'a, 'a>> {
4225 let mut v = arena_ast::ArenaVec::with_capacity_in(members.len(), arena);
4226 for m in members.iter() {
4227 v.push(av_class_member(arena, m));
4228 }
4229 v
4230}
4231
4232fn av_class_const<'a>(
4233 arena: &'a bumpalo::Bump,
4234 c: &ClassConstDecl,
4235) -> arena_ast::ClassConstDecl<'a, 'a> {
4236 arena_ast::ClassConstDecl {
4237 name: av_ident(arena, &c.name),
4238 modifiers: c.modifiers,
4239 type_hint: c
4240 .type_hint
4241 .as_ref()
4242 .map(|th| arena.alloc(av_type_hint(arena, th)) as &_),
4243 value: av_expr(arena, &c.value),
4244 attributes: av_attrs(arena, &c.attributes),
4245 doc_comment: av_opt_comment(arena, &c.doc_comment),
4246 }
4247}
4248
4249fn av_trait_use<'a>(arena: &'a bumpalo::Bump, t: &TraitUseDecl) -> arena_ast::TraitUseDecl<'a, 'a> {
4250 let mut traits = arena_ast::ArenaVec::with_capacity_in(t.traits.len(), arena);
4251 for n in t.traits.iter() {
4252 traits.push(av_name(arena, n));
4253 }
4254 let mut adaptations = arena_ast::ArenaVec::with_capacity_in(t.adaptations.len(), arena);
4255 for a in t.adaptations.iter() {
4256 adaptations.push(arena_ast::TraitAdaptation {
4257 kind: match &a.kind {
4258 TraitAdaptationKind::Precedence {
4259 trait_name,
4260 method,
4261 insteadof,
4262 } => {
4263 let mut instead = arena_ast::ArenaVec::with_capacity_in(insteadof.len(), arena);
4264 for n in insteadof.iter() {
4265 instead.push(av_name(arena, n));
4266 }
4267 arena_ast::TraitAdaptationKind::Precedence {
4268 trait_name: av_name(arena, trait_name),
4269 method: av_name(arena, method),
4270 insteadof: instead,
4271 }
4272 }
4273 TraitAdaptationKind::Alias {
4274 trait_name,
4275 method,
4276 new_modifier,
4277 is_final,
4278 new_name,
4279 } => arena_ast::TraitAdaptationKind::Alias {
4280 trait_name: trait_name.as_ref().map(|n| av_name(arena, n)),
4281 method: av_name(arena, method),
4282 new_modifier: *new_modifier,
4283 is_final: *is_final,
4284 new_name: new_name.as_ref().map(|n| av_name(arena, n)),
4285 },
4286 },
4287 span: a.span,
4288 });
4289 }
4290 arena_ast::TraitUseDecl {
4291 traits,
4292 adaptations,
4293 adaptations_brace_span: t.adaptations_brace_span,
4294 doc_comment: av_opt_comment(arena, &t.doc_comment),
4295 }
4296}
4297
4298fn av_class_decl<'a>(arena: &'a bumpalo::Bump, cls: &ClassDecl) -> arena_ast::ClassDecl<'a, 'a> {
4299 let mut implements = arena_ast::ArenaVec::with_capacity_in(cls.implements.len(), arena);
4300 for n in cls.implements.iter() {
4301 implements.push(av_name(arena, n));
4302 }
4303 arena_ast::ClassDecl {
4304 name: cls.name.as_ref().map(|ident| av_ident(arena, ident)),
4305 modifiers: cls.modifiers.clone(),
4306 extends: cls.extends.as_ref().map(|n| av_name(arena, n)),
4307 implements,
4308 body: arena_ast::ClassBody {
4309 members: av_class_members(arena, &cls.body.members),
4310 span: cls.body.span,
4311 },
4312 attributes: av_attrs(arena, &cls.attributes),
4313 doc_comment: av_opt_comment(arena, &cls.doc_comment),
4314 }
4315}
4316
4317#[inline(never)]
4318fn av_interface_decl<'a>(
4319 arena: &'a bumpalo::Bump,
4320 iface: &InterfaceDecl,
4321) -> arena_ast::InterfaceDecl<'a, 'a> {
4322 let mut extends = arena_ast::ArenaVec::with_capacity_in(iface.extends.len(), arena);
4323 for n in iface.extends.iter() {
4324 extends.push(av_name(arena, n));
4325 }
4326 arena_ast::InterfaceDecl {
4327 name: av_ident(arena, &iface.name),
4328 extends,
4329 body: arena_ast::ClassBody {
4330 members: av_class_members(arena, &iface.body.members),
4331 span: iface.body.span,
4332 },
4333 attributes: av_attrs(arena, &iface.attributes),
4334 doc_comment: av_opt_comment(arena, &iface.doc_comment),
4335 }
4336}
4337
4338#[inline(never)]
4339fn av_trait_decl<'a>(arena: &'a bumpalo::Bump, tr: &TraitDecl) -> arena_ast::TraitDecl<'a, 'a> {
4340 arena_ast::TraitDecl {
4341 name: av_ident(arena, &tr.name),
4342 body: arena_ast::ClassBody {
4343 members: av_class_members(arena, &tr.body.members),
4344 span: tr.body.span,
4345 },
4346 attributes: av_attrs(arena, &tr.attributes),
4347 doc_comment: av_opt_comment(arena, &tr.doc_comment),
4348 }
4349}
4350
4351#[inline(never)]
4352fn av_enum_decl<'a>(arena: &'a bumpalo::Bump, en: &EnumDecl) -> arena_ast::EnumDecl<'a, 'a> {
4353 let mut implements = arena_ast::ArenaVec::with_capacity_in(en.implements.len(), arena);
4354 for n in en.implements.iter() {
4355 implements.push(av_name(arena, n));
4356 }
4357 let mut members = arena_ast::ArenaVec::with_capacity_in(en.body.members.len(), arena);
4358 for m in en.body.members.iter() {
4359 members.push(arena_ast::EnumMember {
4360 kind: match &m.kind {
4361 EnumMemberKind::Case(c) => arena_ast::EnumMemberKind::Case(arena_ast::EnumCase {
4362 name: av_ident(arena, &c.name),
4363 value: c.value.as_ref().map(|e| av_expr(arena, e)),
4364 attributes: av_attrs(arena, &c.attributes),
4365 doc_comment: av_opt_comment(arena, &c.doc_comment),
4366 }),
4367 EnumMemberKind::Method(m) => {
4368 arena_ast::EnumMemberKind::Method(arena_ast::MethodDecl {
4369 name: av_ident(arena, &m.name),
4370 modifiers: m.modifiers,
4371 by_ref: m.by_ref,
4372 params: av_params(arena, &m.params),
4373 return_type: m.return_type.as_ref().map(|t| av_type_hint(arena, t)),
4374 body: m.body.as_deref().map(|b| &*arena.alloc(av_block(arena, b))),
4375 attributes: av_attrs(arena, &m.attributes),
4376 doc_comment: av_opt_comment(arena, &m.doc_comment),
4377 })
4378 }
4379 EnumMemberKind::ClassConst(c) => {
4380 arena_ast::EnumMemberKind::ClassConst(av_class_const(arena, c))
4381 }
4382 EnumMemberKind::TraitUse(t) => {
4383 arena_ast::EnumMemberKind::TraitUse(av_trait_use(arena, t))
4384 }
4385 },
4386 span: m.span,
4387 });
4388 }
4389 arena_ast::EnumDecl {
4390 name: av_ident(arena, &en.name),
4391 scalar_type: en.scalar_type.as_ref().map(|n| av_name(arena, n)),
4392 implements,
4393 body: arena_ast::EnumBody {
4394 members,
4395 span: en.body.span,
4396 },
4397 attributes: av_attrs(arena, &en.attributes),
4398 doc_comment: av_opt_comment(arena, &en.doc_comment),
4399 }
4400}