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 if self.kind == NameKind::FullyQualified {
175 crate::ast::fully_qualified(&self.parts)
176 } else {
177 self.join_parts()
178 }
179 }
180
181 pub fn join_parts(&self) -> String {
183 self.parts.join("\\")
184 }
185}
186
187#[derive(Clone, PartialEq, Eq, Hash)]
195pub struct ByteString(Box<[u8]>);
196
197impl ByteString {
198 pub fn as_bytes(&self) -> &[u8] {
200 &self.0
201 }
202
203 pub fn to_str(&self) -> Option<&str> {
205 std::str::from_utf8(&self.0).ok()
206 }
207
208 pub fn to_string_lossy(&self) -> std::borrow::Cow<'_, str> {
210 String::from_utf8_lossy(&self.0)
211 }
212
213 pub fn into_bytes(self) -> Box<[u8]> {
215 self.0
216 }
217}
218
219impl std::ops::Deref for ByteString {
220 type Target = [u8];
221 fn deref(&self) -> &[u8] {
222 &self.0
223 }
224}
225
226impl From<&str> for ByteString {
227 fn from(s: &str) -> Self {
228 Self(s.as_bytes().into())
229 }
230}
231
232impl From<String> for ByteString {
233 fn from(s: String) -> Self {
234 Self(s.into_bytes().into_boxed_slice())
235 }
236}
237
238impl From<&[u8]> for ByteString {
239 fn from(b: &[u8]) -> Self {
240 Self(b.into())
241 }
242}
243
244impl From<Vec<u8>> for ByteString {
245 fn from(b: Vec<u8>) -> Self {
246 Self(b.into_boxed_slice())
247 }
248}
249
250impl PartialEq<str> for ByteString {
251 fn eq(&self, other: &str) -> bool {
252 &*self.0 == other.as_bytes()
253 }
254}
255
256impl PartialEq<&str> for ByteString {
257 fn eq(&self, other: &&str) -> bool {
258 &*self.0 == other.as_bytes()
259 }
260}
261
262impl std::fmt::Debug for ByteString {
263 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
264 match self.to_str() {
265 Some(s) => std::fmt::Debug::fmt(s, f),
266 None => write!(f, "b{:?}", self.0.escape_ascii().to_string()),
267 }
268 }
269}
270
271#[cfg(feature = "serde")]
272impl Serialize for ByteString {
273 fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
274 crate::ast::serialize_bytes(&self.0, serializer)
275 }
276}
277
278#[derive(Debug, Clone)]
284#[cfg_attr(feature = "serde", derive(Serialize))]
285pub struct Comment {
286 pub kind: CommentKind,
288 pub text: Box<str>,
290 pub span: Span,
292}
293
294#[derive(Debug, Clone)]
303#[cfg_attr(feature = "serde", derive(Serialize))]
304pub struct TypeHint {
305 pub kind: TypeHintKind,
307 pub span: Span,
309}
310
311#[derive(Debug, Clone)]
313#[non_exhaustive]
314pub enum TypeHintKind {
315 Named(Name),
317 Keyword(BuiltinType, Span),
319 Nullable(Box<TypeHint>),
321 Union(Box<[TypeHint]>),
323 Intersection(Box<[TypeHint]>),
325}
326
327#[cfg(feature = "serde")]
328impl Serialize for TypeHintKind {
329 fn serialize<S: serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
330 match self {
331 Self::Named(name) => s.serialize_newtype_variant("TypeHintKind", 0, "Named", name),
332 Self::Nullable(inner) => {
333 s.serialize_newtype_variant("TypeHintKind", 2, "Nullable", inner)
334 }
335 Self::Union(types) => s.serialize_newtype_variant("TypeHintKind", 3, "Union", types),
336 Self::Intersection(types) => {
337 s.serialize_newtype_variant("TypeHintKind", 4, "Intersection", types)
338 }
339 Self::Keyword(builtin, span) => {
340 struct BuiltinNameRepr<'a>(&'a BuiltinType, &'a Span);
341 impl Serialize for BuiltinNameRepr<'_> {
342 fn serialize<S: serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
343 use serde::ser::SerializeStruct;
344 let mut st = s.serialize_struct("Name", 3)?;
345 st.serialize_field("parts", &[self.0.as_str()])?;
346 st.serialize_field("kind", &NameKind::Unqualified)?;
347 st.serialize_field("span", self.1)?;
348 st.end()
349 }
350 }
351 s.serialize_newtype_variant(
352 "TypeHintKind",
353 0,
354 "Named",
355 &BuiltinNameRepr(builtin, span),
356 )
357 }
358 }
359 }
360}
361
362#[derive(Debug, Clone)]
368#[cfg_attr(feature = "serde", derive(Serialize))]
369#[non_exhaustive]
370pub struct Arg {
371 pub name: Option<Name>,
373 pub kind: ArgKind,
375 pub span: Span,
377}
378
379impl Arg {
380 pub fn new(name: Option<Name>, kind: ArgKind, span: Span) -> Self {
383 Self { name, kind, span }
384 }
385}
386
387#[derive(Debug, Clone)]
389#[cfg_attr(feature = "serde", derive(Serialize))]
390#[non_exhaustive]
391pub enum ArgKind {
392 Value(Expr),
394 Spread(Expr),
396 ByRef(Expr),
398 Placeholder,
400 SpreadPlaceholder,
402}
403
404impl Arg {
405 pub fn value(&self) -> Option<&Expr> {
407 match &self.kind {
408 ArgKind::Value(e) | ArgKind::Spread(e) | ArgKind::ByRef(e) => Some(e),
409 ArgKind::Placeholder | ArgKind::SpreadPlaceholder => None,
410 }
411 }
412
413 pub fn value_mut(&mut self) -> Option<&mut Expr> {
415 match &mut self.kind {
416 ArgKind::Value(e) | ArgKind::Spread(e) | ArgKind::ByRef(e) => Some(e),
417 ArgKind::Placeholder | ArgKind::SpreadPlaceholder => None,
418 }
419 }
420
421 pub fn is_spread(&self) -> bool {
423 matches!(self.kind, ArgKind::Spread(_))
424 }
425
426 pub fn is_placeholder(&self) -> bool {
428 matches!(self.kind, ArgKind::Placeholder | ArgKind::SpreadPlaceholder)
429 }
430}
431
432#[derive(Debug, Clone)]
434#[cfg_attr(feature = "serde", derive(Serialize))]
435#[non_exhaustive]
436pub struct Attribute {
437 pub name: Name,
439 pub args: Box<[Arg]>,
441 pub span: Span,
443}
444
445impl Attribute {
446 pub fn new(name: Name, span: Span) -> Self {
449 Self {
450 name,
451 args: Box::new([]),
452 span,
453 }
454 }
455}
456
457#[derive(Debug, Clone)]
463#[cfg_attr(feature = "serde", derive(Serialize))]
464pub struct Program {
465 pub stmts: Box<[Stmt]>,
467 pub span: Span,
469}
470
471#[derive(Debug, Clone)]
477#[cfg_attr(feature = "serde", derive(Serialize))]
478pub struct Stmt {
479 pub kind: StmtKind,
481 pub span: Span,
483 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
485 pub doc_comment: Option<Comment>,
486}
487
488impl Stmt {
489 pub fn leading_doc_comment(&self) -> Option<&Comment> {
493 if let Some(doc) = &self.doc_comment {
494 return Some(doc);
495 }
496 match &self.kind {
497 StmtKind::Function(f) => f.doc_comment.as_ref(),
498 StmtKind::Class(c) => c.doc_comment.as_ref(),
499 StmtKind::Interface(i) => i.doc_comment.as_ref(),
500 StmtKind::Trait(t) => t.doc_comment.as_ref(),
501 StmtKind::Enum(e) => e.doc_comment.as_ref(),
502 StmtKind::Const(items) => items.first().and_then(|i| i.doc_comment.as_ref()),
503 _ => None,
504 }
505 }
506}
507
508#[derive(Debug, Clone)]
510#[cfg_attr(feature = "serde", derive(Serialize))]
511#[cfg_attr(feature = "serde", serde(transparent))]
512pub struct Block {
513 pub stmts: Box<[Stmt]>,
515 #[cfg_attr(feature = "serde", serde(skip))]
517 pub span: Span,
518}
519
520#[derive(Debug, Clone)]
522#[cfg_attr(feature = "serde", derive(Serialize))]
523#[non_exhaustive]
524pub enum StmtKind {
525 Expression(Box<Expr>),
527 Echo(Box<[Expr]>),
529 Return(Option<Box<Expr>>),
531 Block(Box<Block>),
533 If(Box<IfStmt>),
535 While(Box<WhileStmt>),
537 For(Box<ForStmt>),
539 Foreach(Box<ForeachStmt>),
541 DoWhile(Box<DoWhileStmt>),
543 Function(Box<FunctionDecl>),
545 Break(Option<Box<Expr>>),
547 Continue(Option<Box<Expr>>),
549 Switch(Box<SwitchStmt>),
551 Goto(Ident),
553 Label(Ident),
555 Declare(Box<DeclareStmt>),
557 Unset(Box<[Expr]>),
559 Throw(Box<Expr>),
561 TryCatch(Box<TryCatchStmt>),
563 Global(Box<[Expr]>),
565 Class(Box<ClassDecl>),
567 Interface(Box<InterfaceDecl>),
569 Trait(Box<TraitDecl>),
571 Enum(Box<EnumDecl>),
573 Namespace(Box<NamespaceDecl>),
575 Use(Box<UseDecl>),
577 Const(Box<[ConstItem]>),
579 StaticVar(Box<[StaticVar]>),
581 HaltCompiler(Box<str>),
583 Nop,
585 InlineHtml(Box<str>),
587 Error,
589}
590
591#[derive(Debug, Clone)]
593#[cfg_attr(feature = "serde", derive(Serialize))]
594#[non_exhaustive]
595pub struct IfStmt {
596 pub condition: Expr,
598 pub then_branch: Box<Stmt>,
600 pub elseif_branches: Box<[ElseIfBranch]>,
602 pub else_branch: Option<Box<Stmt>>,
604 #[cfg_attr(feature = "serde", serde(skip))]
606 #[doc(hidden)]
607 pub else_kw_span: Option<Span>,
608 #[cfg_attr(feature = "serde", serde(default, skip_serializing_if = "is_false"))]
610 pub uses_alternative: bool,
611}
612
613impl IfStmt {
614 pub fn new(condition: Expr, then_branch: Box<Stmt>) -> Self {
617 Self {
618 condition,
619 then_branch,
620 elseif_branches: Box::new([]),
621 else_branch: None,
622 else_kw_span: None,
623 uses_alternative: false,
624 }
625 }
626}
627
628#[derive(Debug, Clone)]
630#[cfg_attr(feature = "serde", derive(Serialize))]
631pub struct ElseIfBranch {
632 pub condition: Expr,
634 pub body: Stmt,
636 pub span: Span,
638}
639
640#[derive(Debug, Clone)]
642#[cfg_attr(feature = "serde", derive(Serialize))]
643#[non_exhaustive]
644pub struct WhileStmt {
645 pub condition: Expr,
647 pub body: Box<Stmt>,
649 #[cfg_attr(feature = "serde", serde(default, skip_serializing_if = "is_false"))]
651 pub uses_alternative: bool,
652}
653
654impl WhileStmt {
655 pub fn new(condition: Expr, body: Box<Stmt>) -> Self {
658 Self {
659 condition,
660 body,
661 uses_alternative: false,
662 }
663 }
664}
665
666#[derive(Debug, Clone)]
668#[cfg_attr(feature = "serde", derive(Serialize))]
669#[non_exhaustive]
670pub struct ForStmt {
671 pub init: Box<[Expr]>,
673 pub condition: Box<[Expr]>,
675 pub update: Box<[Expr]>,
677 pub body: Box<Stmt>,
679 #[cfg_attr(feature = "serde", serde(default, skip_serializing_if = "is_false"))]
681 pub uses_alternative: bool,
682}
683
684impl ForStmt {
685 pub fn new(body: Box<Stmt>) -> Self {
688 Self {
689 init: Box::new([]),
690 condition: Box::new([]),
691 update: Box::new([]),
692 body,
693 uses_alternative: false,
694 }
695 }
696}
697
698#[derive(Debug, Clone)]
700#[cfg_attr(feature = "serde", derive(Serialize))]
701#[non_exhaustive]
702pub struct ForeachStmt {
703 pub expr: Expr,
705 pub key: Option<Expr>,
707 #[cfg_attr(feature = "serde", serde(default, skip_serializing_if = "is_false"))]
709 pub key_by_ref: bool,
710 pub value: Expr,
712 #[cfg_attr(feature = "serde", serde(default, skip_serializing_if = "is_false"))]
714 pub by_ref: bool,
715 #[cfg_attr(
717 feature = "serde",
718 serde(default, skip_serializing_if = "Option::is_none")
719 )]
720 pub by_ref_span: Option<Span>,
721 pub body: Box<Stmt>,
723 #[cfg_attr(feature = "serde", serde(default, skip_serializing_if = "is_false"))]
725 pub uses_alternative: bool,
726}
727
728impl ForeachStmt {
729 pub fn new(expr: Expr, value: Expr, body: Box<Stmt>) -> Self {
732 Self {
733 expr,
734 key: None,
735 key_by_ref: false,
736 value,
737 by_ref: false,
738 by_ref_span: None,
739 body,
740 uses_alternative: false,
741 }
742 }
743}
744
745#[derive(Debug, Clone)]
747#[cfg_attr(feature = "serde", derive(Serialize))]
748#[non_exhaustive]
749pub struct DoWhileStmt {
750 pub body: Box<Stmt>,
752 pub condition: Expr,
754}
755
756impl DoWhileStmt {
757 pub fn new(body: Box<Stmt>, condition: Expr) -> Self {
760 Self { body, condition }
761 }
762}
763
764#[derive(Debug, Clone)]
766#[cfg_attr(feature = "serde", derive(Serialize))]
767pub struct SwitchBody {
768 pub cases: Box<[SwitchCase]>,
770 #[cfg_attr(feature = "serde", serde(skip))]
772 pub span: Span,
773}
774
775#[derive(Debug, Clone)]
777#[cfg_attr(feature = "serde", derive(Serialize))]
778#[non_exhaustive]
779pub struct SwitchStmt {
780 pub expr: Expr,
782 #[cfg_attr(feature = "serde", serde(flatten))]
784 pub body: SwitchBody,
785 #[cfg_attr(feature = "serde", serde(default, skip_serializing_if = "is_false"))]
787 pub uses_alternative: bool,
788}
789
790impl SwitchStmt {
791 pub fn new(expr: Expr, body: SwitchBody) -> Self {
794 Self {
795 expr,
796 body,
797 uses_alternative: false,
798 }
799 }
800}
801
802#[derive(Debug, Clone)]
804#[cfg_attr(feature = "serde", derive(Serialize))]
805pub struct SwitchCase {
806 pub value: Option<Expr>,
808 pub body: Box<[Stmt]>,
810 pub span: Span,
812}
813
814#[derive(Debug, Clone)]
816#[cfg_attr(feature = "serde", derive(Serialize))]
817#[non_exhaustive]
818pub struct TryCatchStmt {
819 pub body: Box<Block>,
821 pub catches: Box<[CatchClause]>,
823 pub finally: Option<Box<Block>>,
825 #[cfg_attr(feature = "serde", serde(skip))]
827 #[doc(hidden)]
828 pub finally_kw_span: Option<Span>,
829}
830
831impl TryCatchStmt {
832 pub fn new(body: Box<Block>) -> Self {
835 Self {
836 body,
837 catches: Box::new([]),
838 finally: None,
839 finally_kw_span: None,
840 }
841 }
842}
843
844#[derive(Debug, Clone)]
846#[cfg_attr(feature = "serde", derive(Serialize))]
847#[non_exhaustive]
848pub struct CatchClause {
849 pub types: Box<[Name]>,
851 pub var: Option<Ident>,
853 pub body: Box<Block>,
855 pub span: Span,
857}
858
859impl CatchClause {
860 pub fn new(body: Box<Block>, span: Span) -> Self {
863 Self {
864 types: Box::new([]),
865 var: None,
866 body,
867 span,
868 }
869 }
870}
871
872#[derive(Debug, Clone)]
874#[cfg_attr(feature = "serde", derive(Serialize))]
875#[non_exhaustive]
876pub struct NamespaceDecl {
877 pub name: Option<Name>,
879 pub body: NamespaceBody,
881}
882
883impl NamespaceDecl {
884 pub fn new(name: Option<Name>, body: NamespaceBody) -> Self {
887 Self { name, body }
888 }
889}
890
891#[derive(Debug, Clone)]
893#[cfg_attr(feature = "serde", derive(Serialize))]
894#[non_exhaustive]
895pub enum NamespaceBody {
896 Braced(Box<Block>),
898 Simple,
900}
901
902#[derive(Debug, Clone)]
904#[cfg_attr(feature = "serde", derive(Serialize))]
905#[non_exhaustive]
906pub struct DeclareStmt {
907 pub directives: Box<[(Box<str>, Expr)]>,
909 pub body: Option<Box<Stmt>>,
911 #[cfg_attr(feature = "serde", serde(default, skip_serializing_if = "is_false"))]
913 pub uses_alternative: bool,
914}
915
916impl DeclareStmt {
917 pub fn new(directives: Box<[(Box<str>, Expr)]>) -> Self {
920 Self {
921 directives,
922 body: None,
923 uses_alternative: false,
924 }
925 }
926}
927
928#[derive(Debug, Clone)]
930#[cfg_attr(feature = "serde", derive(Serialize))]
931#[non_exhaustive]
932pub struct UseDecl {
933 pub kind: UseKind,
935 pub uses: Box<[UseItem]>,
937}
938
939impl UseDecl {
940 pub fn new(kind: UseKind, uses: Box<[UseItem]>) -> Self {
943 Self { kind, uses }
944 }
945}
946
947#[derive(Debug, Clone)]
949#[cfg_attr(feature = "serde", derive(Serialize))]
950pub struct UseItem {
951 pub name: Name,
953 pub alias: Option<Ident>,
955 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
957 pub kind: Option<UseKind>,
958 pub span: Span,
960}
961
962#[derive(Debug, Clone)]
964#[cfg_attr(feature = "serde", derive(Serialize))]
965pub struct ConstItem {
966 pub name: Ident,
968 pub value: Expr,
970 pub attributes: Box<[Attribute]>,
972 pub span: Span,
974 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
976 pub doc_comment: Option<Comment>,
977}
978
979#[derive(Debug, Clone)]
981#[cfg_attr(feature = "serde", derive(Serialize))]
982pub struct StaticVar {
983 pub name: Ident,
985 pub default: Option<Expr>,
987 pub span: Span,
989}
990
991#[derive(Debug, Clone)]
1001#[cfg_attr(feature = "serde", derive(Serialize))]
1002pub struct Expr {
1003 pub kind: ExprKind,
1005 pub span: Span,
1007}
1008
1009impl Expr {
1010 pub fn name_str(&self) -> Option<&str> {
1012 match &self.kind {
1013 ExprKind::Variable(s) | ExprKind::Identifier(s) => Some(s),
1014 _ => None,
1015 }
1016 }
1017
1018 pub fn into_kind(mut self) -> ExprKind {
1020 std::mem::replace(&mut self.kind, ExprKind::Error)
1021 }
1022}
1023
1024#[derive(Debug, Clone)]
1026#[cfg_attr(feature = "serde", derive(Serialize))]
1027#[non_exhaustive]
1028pub enum ExprKind {
1029 Int(i64),
1031 Float(f64),
1033 String(ByteString),
1035 InterpolatedString(Box<[StringPart]>),
1037 Heredoc {
1039 label: Box<str>,
1041 parts: Box<[StringPart]>,
1043 },
1044 Nowdoc {
1046 label: Box<str>,
1048 value: Box<str>,
1050 },
1051 ShellExec(Box<[StringPart]>),
1053 Bool(bool),
1055 Null,
1057 Variable(Box<str>),
1059 VariableVariable(Box<Expr>),
1061 Identifier(Box<str>),
1063 Name(Name),
1065 Assign(AssignExpr),
1067 Binary(BinaryExpr),
1069 UnaryPrefix(UnaryPrefixExpr),
1071 UnaryPostfix(UnaryPostfixExpr),
1073 Ternary(TernaryExpr),
1075 NullCoalesce(NullCoalesceExpr),
1077 FunctionCall(FunctionCallExpr),
1079 Array(Box<[ArrayElement]>),
1081 ArrayAccess(ArrayAccessExpr),
1083 Print(Box<Expr>),
1085 Parenthesized(Box<Expr>),
1087 Cast(CastKind, Box<Expr>),
1089 ErrorSuppress(Box<Expr>),
1091 Isset(Box<[Expr]>),
1093 Empty(Box<Expr>),
1095 Include(IncludeKind, Box<Expr>),
1097 Eval(Box<Expr>),
1099 Exit(Option<Box<Expr>>),
1101 MagicConst(MagicConstKind),
1103 Clone(Box<Expr>),
1105 CloneWith(Box<Expr>, Box<Expr>),
1107 New(NewExpr),
1109 PropertyAccess(PropertyAccessExpr),
1111 NullsafePropertyAccess(PropertyAccessExpr),
1113 MethodCall(Box<MethodCallExpr>),
1115 NullsafeMethodCall(Box<MethodCallExpr>),
1117 StaticPropertyAccess(StaticAccessExpr),
1119 StaticMethodCall(Box<StaticMethodCallExpr>),
1121 StaticMethodCallDynamic(Box<StaticMethodCallDynamicExpr>),
1123 ClassConstAccess(StaticAccessExpr),
1125 ClassConstAccessDynamic {
1127 class: Box<Expr>,
1129 member: Box<Expr>,
1131 },
1132 StaticPropertyAccessDynamic {
1134 class: Box<Expr>,
1136 member: Box<Expr>,
1138 },
1139 Closure(Box<ClosureExpr>),
1141 ArrowFunction(Box<ArrowFunctionExpr>),
1143 Match(MatchExpr),
1145 Throw(Box<Expr>),
1147 Yield(YieldExpr),
1149 AnonymousClass(Box<ClassDecl>),
1151 CallableCreate(CallableCreateExpr),
1153 Omit,
1155 Error,
1157}
1158
1159impl Drop for Expr {
1173 #[inline(always)]
1174 fn drop(&mut self) {
1175 if owned_is_chain(&self.kind) {
1177 unlink_chain(&mut self.kind);
1178 }
1179 }
1180}
1181
1182#[inline(never)]
1184fn unlink_chain(kind: &mut ExprKind) {
1185 let Some(operand) = owned_chain_operand_mut(kind) else {
1186 return;
1187 };
1188 if !owned_is_chain(&operand.kind) {
1190 return;
1191 }
1192 let mut kind = std::mem::replace(&mut operand.kind, ExprKind::Error);
1195 while let Some(operand) = owned_chain_operand_mut(&mut kind) {
1196 let next = std::mem::replace(&mut operand.kind, ExprKind::Error);
1197 kind = next;
1198 }
1199}
1200
1201struct LinkStack<T: Copy> {
1204 inline: [Option<T>; 8],
1205 len: usize,
1206 spilled: Vec<T>,
1207}
1208
1209impl<T: Copy> LinkStack<T> {
1210 fn new() -> Self {
1211 Self {
1212 inline: [None; 8],
1213 len: 0,
1214 spilled: Vec::new(),
1215 }
1216 }
1217
1218 fn push(&mut self, link: T) {
1219 if self.len < self.inline.len() {
1220 self.inline[self.len] = Some(link);
1221 self.len += 1;
1222 } else {
1223 self.spilled.push(link);
1224 }
1225 }
1226
1227 fn pop(&mut self) -> Option<T> {
1228 if let Some(link) = self.spilled.pop() {
1229 return Some(link);
1230 }
1231 self.len = self.len.checked_sub(1)?;
1232 self.inline[self.len]
1233 }
1234}
1235
1236#[inline]
1239fn arena_is_chain(k: &arena_ast::ExprKind<'_, '_>) -> bool {
1240 matches!(
1241 k,
1242 arena_ast::ExprKind::Assign(_)
1243 | arena_ast::ExprKind::Binary(_)
1244 | arena_ast::ExprKind::UnaryPrefix(_)
1245 | arena_ast::ExprKind::UnaryPostfix(_)
1246 | arena_ast::ExprKind::Ternary(_)
1247 | arena_ast::ExprKind::NullCoalesce(_)
1248 | arena_ast::ExprKind::FunctionCall(_)
1249 | arena_ast::ExprKind::ArrayAccess(_)
1250 | arena_ast::ExprKind::PropertyAccess(_)
1251 | arena_ast::ExprKind::NullsafePropertyAccess(_)
1252 | arena_ast::ExprKind::MethodCall(_)
1253 | arena_ast::ExprKind::NullsafeMethodCall(_)
1254 | arena_ast::ExprKind::StaticPropertyAccess(_)
1255 | arena_ast::ExprKind::ClassConstAccess(_)
1256 | arena_ast::ExprKind::StaticMethodCall(_)
1257 | arena_ast::ExprKind::StaticMethodCallDynamic(_)
1258 | arena_ast::ExprKind::ClassConstAccessDynamic { .. }
1259 | arena_ast::ExprKind::StaticPropertyAccessDynamic { .. }
1260 | arena_ast::ExprKind::CallableCreate(_)
1261 )
1262}
1263
1264#[inline]
1266fn owned_is_chain(k: &ExprKind) -> bool {
1267 matches!(
1268 k,
1269 ExprKind::Assign(_)
1270 | ExprKind::Binary(_)
1271 | ExprKind::UnaryPrefix(_)
1272 | ExprKind::UnaryPostfix(_)
1273 | ExprKind::Ternary(_)
1274 | ExprKind::NullCoalesce(_)
1275 | ExprKind::FunctionCall(_)
1276 | ExprKind::ArrayAccess(_)
1277 | ExprKind::PropertyAccess(_)
1278 | ExprKind::NullsafePropertyAccess(_)
1279 | ExprKind::MethodCall(_)
1280 | ExprKind::NullsafeMethodCall(_)
1281 | ExprKind::StaticPropertyAccess(_)
1282 | ExprKind::ClassConstAccess(_)
1283 | ExprKind::StaticMethodCall(_)
1284 | ExprKind::StaticMethodCallDynamic(_)
1285 | ExprKind::ClassConstAccessDynamic { .. }
1286 | ExprKind::StaticPropertyAccessDynamic { .. }
1287 | ExprKind::CallableCreate(_)
1288 )
1289}
1290
1291#[inline]
1292fn arena_chain_operand<'a, 'arena, 'src>(
1293 k: &'a arena_ast::ExprKind<'arena, 'src>,
1294) -> Option<&'a arena_ast::Expr<'arena, 'src>> {
1295 use arena_ast::{CallableCreateKind as C, ExprKind as K};
1296 match k {
1297 K::Assign(a) => Some(a.target),
1298 K::Binary(b) => Some(b.left),
1299 K::UnaryPrefix(u) => Some(u.operand),
1300 K::UnaryPostfix(u) => Some(u.operand),
1301 K::Ternary(t) => Some(t.condition),
1302 K::NullCoalesce(n) => Some(n.left),
1303 K::FunctionCall(f) => Some(f.name),
1304 K::ArrayAccess(a) => Some(a.array),
1305 K::PropertyAccess(p) | K::NullsafePropertyAccess(p) => Some(p.object),
1306 K::MethodCall(m) | K::NullsafeMethodCall(m) => Some(m.object),
1307 K::StaticPropertyAccess(s) | K::ClassConstAccess(s) => Some(s.class),
1308 K::StaticMethodCall(s) => Some(s.class),
1309 K::StaticMethodCallDynamic(s) => Some(s.class),
1310 K::ClassConstAccessDynamic { class, .. } | K::StaticPropertyAccessDynamic { class, .. } => {
1311 Some(class)
1312 }
1313 K::CallableCreate(c) => Some(match &c.kind {
1314 C::Function(e) => e,
1315 C::Method { object, .. } | C::NullsafeMethod { object, .. } => object,
1316 C::StaticMethod { class, .. } => class,
1317 }),
1318 _ => None,
1319 }
1320}
1321
1322#[inline]
1323fn owned_chain_operand(k: &ExprKind) -> Option<&Expr> {
1324 use CallableCreateKind as C;
1325 match k {
1326 ExprKind::Assign(a) => Some(&a.target),
1327 ExprKind::Binary(b) => Some(&b.left),
1328 ExprKind::UnaryPrefix(u) => Some(&u.operand),
1329 ExprKind::UnaryPostfix(u) => Some(&u.operand),
1330 ExprKind::Ternary(t) => Some(&t.condition),
1331 ExprKind::NullCoalesce(n) => Some(&n.left),
1332 ExprKind::FunctionCall(f) => Some(&f.name),
1333 ExprKind::ArrayAccess(a) => Some(&a.array),
1334 ExprKind::PropertyAccess(p) | ExprKind::NullsafePropertyAccess(p) => Some(&p.object),
1335 ExprKind::MethodCall(m) | ExprKind::NullsafeMethodCall(m) => Some(&m.object),
1336 ExprKind::StaticPropertyAccess(s) | ExprKind::ClassConstAccess(s) => Some(&s.class),
1337 ExprKind::StaticMethodCall(s) => Some(&s.class),
1338 ExprKind::StaticMethodCallDynamic(s) => Some(&s.class),
1339 ExprKind::ClassConstAccessDynamic { class, .. }
1340 | ExprKind::StaticPropertyAccessDynamic { class, .. } => Some(class),
1341 ExprKind::CallableCreate(c) => Some(match &c.kind {
1342 C::Function(e) => e,
1343 C::Method { object, .. } | C::NullsafeMethod { object, .. } => object,
1344 C::StaticMethod { class, .. } => class,
1345 }),
1346 _ => None,
1347 }
1348}
1349
1350#[inline]
1351fn owned_chain_operand_mut(k: &mut ExprKind) -> Option<&mut Expr> {
1352 use CallableCreateKind as C;
1353 match k {
1354 ExprKind::Assign(a) => Some(&mut a.target),
1355 ExprKind::Binary(b) => Some(&mut b.left),
1356 ExprKind::UnaryPrefix(u) => Some(&mut u.operand),
1357 ExprKind::UnaryPostfix(u) => Some(&mut u.operand),
1358 ExprKind::Ternary(t) => Some(&mut t.condition),
1359 ExprKind::NullCoalesce(n) => Some(&mut n.left),
1360 ExprKind::FunctionCall(f) => Some(&mut f.name),
1361 ExprKind::ArrayAccess(a) => Some(&mut a.array),
1362 ExprKind::PropertyAccess(p) | ExprKind::NullsafePropertyAccess(p) => Some(&mut p.object),
1363 ExprKind::MethodCall(m) | ExprKind::NullsafeMethodCall(m) => Some(&mut m.object),
1364 ExprKind::StaticPropertyAccess(s) | ExprKind::ClassConstAccess(s) => Some(&mut s.class),
1365 ExprKind::StaticMethodCall(s) => Some(&mut s.class),
1366 ExprKind::StaticMethodCallDynamic(s) => Some(&mut s.class),
1367 ExprKind::ClassConstAccessDynamic { class, .. }
1368 | ExprKind::StaticPropertyAccessDynamic { class, .. } => Some(class),
1369 ExprKind::CallableCreate(c) => Some(match &mut c.kind {
1370 C::Function(e) => e,
1371 C::Method { object, .. } | C::NullsafeMethod { object, .. } => object,
1372 C::StaticMethod { class, .. } => class,
1373 }),
1374 _ => None,
1375 }
1376}
1377
1378#[derive(Debug, Clone)]
1380#[cfg_attr(feature = "serde", derive(Serialize))]
1381pub struct AssignExpr {
1382 pub target: Box<Expr>,
1384 pub op: AssignOp,
1386 pub value: Box<Expr>,
1388 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "is_false"))]
1390 pub by_ref: bool,
1391}
1392
1393#[derive(Debug, Clone)]
1395#[cfg_attr(feature = "serde", derive(Serialize))]
1396pub struct BinaryExpr {
1397 pub left: Box<Expr>,
1399 pub op: BinaryOp,
1401 pub right: Box<Expr>,
1403}
1404
1405#[derive(Debug, Clone)]
1407#[cfg_attr(feature = "serde", derive(Serialize))]
1408pub struct UnaryPrefixExpr {
1409 pub op: UnaryPrefixOp,
1411 pub operand: Box<Expr>,
1413}
1414
1415#[derive(Debug, Clone)]
1417#[cfg_attr(feature = "serde", derive(Serialize))]
1418pub struct UnaryPostfixExpr {
1419 pub operand: Box<Expr>,
1421 pub op: UnaryPostfixOp,
1423}
1424
1425#[derive(Debug, Clone)]
1427#[cfg_attr(feature = "serde", derive(Serialize))]
1428pub struct TernaryExpr {
1429 pub condition: Box<Expr>,
1431 pub then_expr: Option<Box<Expr>>,
1433 pub else_expr: Box<Expr>,
1435}
1436
1437#[derive(Debug, Clone)]
1439#[cfg_attr(feature = "serde", derive(Serialize))]
1440pub struct NullCoalesceExpr {
1441 pub left: Box<Expr>,
1443 pub right: Box<Expr>,
1445}
1446
1447#[derive(Debug, Clone)]
1449#[cfg_attr(feature = "serde", derive(Serialize))]
1450pub struct FunctionCallExpr {
1451 pub name: Box<Expr>,
1453 pub args: Box<[Arg]>,
1455}
1456
1457#[derive(Debug, Clone)]
1459#[cfg_attr(feature = "serde", derive(Serialize))]
1460pub struct ArrayElement {
1461 pub key: Option<Expr>,
1463 pub kind: ArrayElementKind,
1465 pub span: Span,
1467}
1468
1469#[derive(Debug, Clone)]
1471#[cfg_attr(feature = "serde", derive(Serialize))]
1472#[non_exhaustive]
1473pub enum ArrayElementKind {
1474 Value(Expr),
1476 Spread(Expr),
1478 ByRef(Expr),
1480}
1481
1482impl ArrayElement {
1483 pub fn value(&self) -> &Expr {
1485 match &self.kind {
1486 ArrayElementKind::Value(e)
1487 | ArrayElementKind::Spread(e)
1488 | ArrayElementKind::ByRef(e) => e,
1489 }
1490 }
1491
1492 pub fn value_mut(&mut self) -> &mut Expr {
1494 match &mut self.kind {
1495 ArrayElementKind::Value(e)
1496 | ArrayElementKind::Spread(e)
1497 | ArrayElementKind::ByRef(e) => e,
1498 }
1499 }
1500
1501 pub fn is_spread(&self) -> bool {
1503 matches!(self.kind, ArrayElementKind::Spread(_))
1504 }
1505
1506 pub fn is_by_ref(&self) -> bool {
1508 matches!(self.kind, ArrayElementKind::ByRef(_))
1509 }
1510}
1511
1512#[derive(Debug, Clone)]
1514#[cfg_attr(feature = "serde", derive(Serialize))]
1515pub struct ArrayAccessExpr {
1516 pub array: Box<Expr>,
1518 pub index: Option<Box<Expr>>,
1520}
1521
1522#[derive(Debug, Clone)]
1524#[cfg_attr(feature = "serde", derive(Serialize))]
1525pub struct NewExpr {
1526 pub class: Box<Expr>,
1528 pub args: Box<[Arg]>,
1530}
1531
1532#[derive(Debug, Clone)]
1534#[cfg_attr(feature = "serde", derive(Serialize))]
1535pub struct PropertyAccessExpr {
1536 pub object: Box<Expr>,
1538 pub property: Box<Expr>,
1540}
1541
1542#[derive(Debug, Clone)]
1544#[cfg_attr(feature = "serde", derive(Serialize))]
1545pub struct MethodCallExpr {
1546 pub object: Box<Expr>,
1548 pub method: Box<Expr>,
1550 pub args: Box<[Arg]>,
1552}
1553
1554#[derive(Debug, Clone)]
1556#[cfg_attr(feature = "serde", derive(Serialize))]
1557pub struct StaticAccessExpr {
1558 pub class: Box<Expr>,
1560 pub member: Box<Expr>,
1562}
1563
1564#[derive(Debug, Clone)]
1566#[cfg_attr(feature = "serde", derive(Serialize))]
1567pub struct StaticMethodCallExpr {
1568 pub class: Box<Expr>,
1570 pub method: Box<Expr>,
1572 pub args: Box<[Arg]>,
1574}
1575
1576#[derive(Debug, Clone)]
1578#[cfg_attr(feature = "serde", derive(Serialize))]
1579pub struct StaticMethodCallDynamicExpr {
1580 pub class: Box<Expr>,
1582 pub method: Box<Expr>,
1584 pub args: Box<[Arg]>,
1586}
1587
1588#[derive(Debug, Clone)]
1590#[cfg_attr(feature = "serde", derive(Serialize))]
1591#[non_exhaustive]
1592pub struct ClosureExpr {
1593 pub is_static: bool,
1595 pub by_ref: bool,
1597 pub params: Box<[Param]>,
1599 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "is_false"))]
1601 pub missing_param_list: bool,
1602 pub use_vars: Box<[ClosureUseVar]>,
1604 pub return_type: Option<TypeHint>,
1606 pub body: Box<Block>,
1608 pub attributes: Box<[Attribute]>,
1610}
1611
1612impl ClosureExpr {
1613 pub fn new(body: Box<Block>) -> Self {
1616 Self {
1617 is_static: false,
1618 by_ref: false,
1619 params: Box::new([]),
1620 missing_param_list: false,
1621 use_vars: Box::new([]),
1622 return_type: None,
1623 body,
1624 attributes: Box::new([]),
1625 }
1626 }
1627}
1628
1629#[derive(Debug, Clone)]
1631#[cfg_attr(feature = "serde", derive(Serialize))]
1632pub struct ClosureUseVar {
1633 pub name: Ident,
1635 pub by_ref: bool,
1637 pub span: Span,
1639}
1640
1641#[derive(Debug, Clone)]
1643#[cfg_attr(feature = "serde", derive(Serialize))]
1644#[non_exhaustive]
1645pub struct ArrowFunctionExpr {
1646 pub is_static: bool,
1648 pub by_ref: bool,
1650 pub params: Box<[Param]>,
1652 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "is_false"))]
1654 pub missing_param_list: bool,
1655 pub return_type: Option<TypeHint>,
1657 pub body: Box<Expr>,
1659 pub attributes: Box<[Attribute]>,
1661}
1662
1663impl ArrowFunctionExpr {
1664 pub fn new(body: Box<Expr>) -> Self {
1667 Self {
1668 is_static: false,
1669 by_ref: false,
1670 params: Box::new([]),
1671 missing_param_list: false,
1672 return_type: None,
1673 body,
1674 attributes: Box::new([]),
1675 }
1676 }
1677}
1678
1679#[derive(Debug, Clone)]
1681#[cfg_attr(feature = "serde", derive(Serialize))]
1682#[non_exhaustive]
1683pub struct MatchExpr {
1684 pub subject: Box<Expr>,
1686 pub arms: Box<[MatchArm]>,
1688 #[cfg_attr(feature = "serde", serde(skip))]
1690 #[doc(hidden)]
1691 pub brace_span: Span,
1692}
1693
1694impl MatchExpr {
1695 pub fn new(subject: Box<Expr>, arms: Box<[MatchArm]>, brace_span: Span) -> Self {
1698 Self {
1699 subject,
1700 arms,
1701 brace_span,
1702 }
1703 }
1704}
1705
1706#[derive(Debug, Clone)]
1708#[cfg_attr(feature = "serde", derive(Serialize))]
1709pub struct MatchArm {
1710 pub conditions: Option<Box<[Expr]>>,
1712 pub body: Expr,
1714 pub span: Span,
1716}
1717
1718#[derive(Debug, Clone)]
1720#[cfg_attr(feature = "serde", derive(Serialize))]
1721pub struct YieldExpr {
1722 pub key: Option<Box<Expr>>,
1724 pub value: Option<Box<Expr>>,
1726 pub is_from: bool,
1728}
1729
1730#[derive(Debug, Clone)]
1732#[cfg_attr(feature = "serde", derive(Serialize))]
1733pub struct CallableCreateExpr {
1734 pub kind: CallableCreateKind,
1736}
1737
1738#[derive(Debug, Clone)]
1740#[cfg_attr(feature = "serde", derive(Serialize))]
1741#[non_exhaustive]
1742pub enum CallableCreateKind {
1743 Function(Box<Expr>),
1745 Method {
1747 object: Box<Expr>,
1749 method: Box<Expr>,
1751 },
1752 NullsafeMethod {
1754 object: Box<Expr>,
1756 method: Box<Expr>,
1758 },
1759 StaticMethod {
1761 class: Box<Expr>,
1763 method: Box<Expr>,
1765 },
1766}
1767
1768#[derive(Debug, Clone)]
1770#[cfg_attr(feature = "serde", derive(Serialize))]
1771#[non_exhaustive]
1772pub enum StringPart {
1773 Literal(ByteString),
1775 Expr(Expr),
1777}
1778
1779#[derive(Debug, Clone)]
1785#[cfg_attr(feature = "serde", derive(Serialize))]
1786#[non_exhaustive]
1787pub struct FunctionDecl {
1788 pub name: Ident,
1790 pub params: Box<[Param]>,
1792 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "is_false"))]
1794 pub missing_param_list: bool,
1795 pub body: Box<Block>,
1797 pub return_type: Option<TypeHint>,
1799 pub by_ref: bool,
1801 pub attributes: Box<[Attribute]>,
1803 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
1805 pub doc_comment: Option<Comment>,
1806}
1807
1808impl FunctionDecl {
1809 pub fn new(name: Ident, body: Box<Block>) -> Self {
1812 Self {
1813 name,
1814 params: Box::new([]),
1815 missing_param_list: false,
1816 body,
1817 return_type: None,
1818 by_ref: false,
1819 attributes: Box::new([]),
1820 doc_comment: None,
1821 }
1822 }
1823}
1824
1825#[derive(Debug, Clone)]
1827#[cfg_attr(feature = "serde", derive(Serialize))]
1828#[non_exhaustive]
1829pub struct Param {
1830 pub name: Ident,
1832 pub type_hint: Option<TypeHint>,
1834 pub default: Option<Expr>,
1836 pub by_ref: bool,
1838 pub variadic: bool,
1840 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Modifiers::is_empty"))]
1842 pub modifiers: Modifiers,
1843 pub attributes: Box<[Attribute]>,
1845 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "slice_is_empty"))]
1847 pub hooks: Box<[PropertyHook]>,
1848 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "is_false"))]
1850 pub empty_hook_list: bool,
1851 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
1853 pub doc_comment: Option<Comment>,
1854 pub span: Span,
1856}
1857
1858impl Param {
1859 pub fn new(name: Ident, span: Span) -> Self {
1864 Self {
1865 name,
1866 type_hint: None,
1867 default: None,
1868 by_ref: false,
1869 variadic: false,
1870 modifiers: Modifiers::new(),
1871 attributes: Box::new([]),
1872 hooks: Box::new([]),
1873 empty_hook_list: false,
1874 doc_comment: None,
1875 span,
1876 }
1877 }
1878}
1879
1880#[derive(Debug, Clone)]
1882#[cfg_attr(feature = "serde", derive(Serialize))]
1883pub struct ClassBody {
1884 pub members: Box<[ClassMember]>,
1886 #[cfg_attr(feature = "serde", serde(skip))]
1888 pub span: Span,
1889}
1890
1891#[derive(Debug, Clone)]
1893#[cfg_attr(feature = "serde", derive(Serialize))]
1894#[non_exhaustive]
1895pub struct ClassDecl {
1896 pub name: Option<Ident>,
1898 pub modifiers: ClassModifiers,
1900 pub extends: Option<Name>,
1902 pub implements: Box<[Name]>,
1904 #[cfg_attr(feature = "serde", serde(flatten))]
1906 pub body: ClassBody,
1907 pub attributes: Box<[Attribute]>,
1909 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
1911 pub doc_comment: Option<Comment>,
1912}
1913
1914impl ClassDecl {
1915 pub fn new(name: Option<Ident>, body: ClassBody) -> Self {
1918 Self {
1919 name,
1920 modifiers: ClassModifiers::default(),
1921 extends: None,
1922 implements: Box::new([]),
1923 body,
1924 attributes: Box::new([]),
1925 doc_comment: None,
1926 }
1927 }
1928}
1929
1930#[derive(Debug, Clone)]
1932#[cfg_attr(feature = "serde", derive(Serialize))]
1933pub struct ClassMember {
1934 pub kind: ClassMemberKind,
1936 pub span: Span,
1938}
1939
1940#[derive(Debug, Clone)]
1942#[cfg_attr(feature = "serde", derive(Serialize))]
1943#[non_exhaustive]
1944pub enum ClassMemberKind {
1945 Property(PropertyDecl),
1947 Method(MethodDecl),
1949 ClassConst(ClassConstDecl),
1951 TraitUse(TraitUseDecl),
1953}
1954
1955#[derive(Debug, Clone)]
1957#[cfg_attr(feature = "serde", derive(Serialize))]
1958#[non_exhaustive]
1959pub struct PropertyDecl {
1960 pub name: Ident,
1962 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Modifiers::is_empty"))]
1964 pub modifiers: Modifiers,
1965 pub type_hint: Option<TypeHint>,
1967 pub default: Option<Expr>,
1969 pub attributes: Box<[Attribute]>,
1971 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "slice_is_empty"))]
1973 pub hooks: Box<[PropertyHook]>,
1974 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "is_false"))]
1976 pub empty_hook_list: bool,
1977 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
1979 pub doc_comment: Option<Comment>,
1980}
1981
1982impl PropertyDecl {
1983 pub fn new(name: Ident) -> Self {
1986 Self {
1987 name,
1988 modifiers: Modifiers::new(),
1989 type_hint: None,
1990 default: None,
1991 attributes: Box::new([]),
1992 hooks: Box::new([]),
1993 empty_hook_list: false,
1994 doc_comment: None,
1995 }
1996 }
1997}
1998
1999#[derive(Debug, Clone)]
2001#[cfg_attr(feature = "serde", derive(Serialize))]
2002#[non_exhaustive]
2003pub struct PropertyHook {
2004 pub kind: PropertyHookKind,
2006 pub body: PropertyHookBody,
2008 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Modifiers::is_empty"))]
2010 pub modifiers: Modifiers,
2011 pub by_ref: bool,
2013 pub params: Box<[Param]>,
2015 #[cfg_attr(feature = "serde", serde(default, skip_serializing_if = "is_false"))]
2017 pub empty_param_list: bool,
2018 pub attributes: Box<[Attribute]>,
2020 #[cfg_attr(feature = "serde", serde(skip))]
2022 #[doc(hidden)]
2023 pub name_span: Span,
2024 pub span: Span,
2026}
2027
2028impl PropertyHook {
2029 pub fn new(kind: PropertyHookKind, body: PropertyHookBody, span: Span) -> Self {
2032 Self {
2033 kind,
2034 body,
2035 modifiers: Modifiers::new(),
2036 by_ref: false,
2037 params: Box::new([]),
2038 empty_param_list: false,
2039 attributes: Box::new([]),
2040 name_span: Span::DUMMY,
2041 span,
2042 }
2043 }
2044}
2045
2046#[derive(Debug, Clone)]
2048#[cfg_attr(feature = "serde", derive(Serialize))]
2049#[non_exhaustive]
2050pub enum PropertyHookBody {
2051 Block(Box<Block>),
2053 Expression(Expr),
2055 Abstract,
2057}
2058
2059#[derive(Debug, Clone)]
2061#[cfg_attr(feature = "serde", derive(Serialize))]
2062#[non_exhaustive]
2063pub struct MethodDecl {
2064 pub name: Ident,
2066 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Modifiers::is_empty"))]
2068 pub modifiers: Modifiers,
2069 pub by_ref: bool,
2071 pub params: Box<[Param]>,
2073 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "is_false"))]
2075 pub missing_param_list: bool,
2076 pub return_type: Option<TypeHint>,
2078 pub body: Option<Box<Block>>,
2080 pub attributes: Box<[Attribute]>,
2082 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
2084 pub doc_comment: Option<Comment>,
2085}
2086
2087impl MethodDecl {
2088 pub fn new(name: Ident) -> Self {
2091 Self {
2092 name,
2093 modifiers: Modifiers::new(),
2094 by_ref: false,
2095 params: Box::new([]),
2096 missing_param_list: false,
2097 return_type: None,
2098 body: None,
2099 attributes: Box::new([]),
2100 doc_comment: None,
2101 }
2102 }
2103}
2104
2105#[derive(Debug, Clone)]
2107#[cfg_attr(feature = "serde", derive(Serialize))]
2108#[non_exhaustive]
2109pub struct ClassConstDecl {
2110 pub name: Ident,
2112 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Modifiers::is_empty"))]
2114 pub modifiers: Modifiers,
2115 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
2117 pub type_hint: Option<Box<TypeHint>>,
2118 pub value: Expr,
2120 pub attributes: Box<[Attribute]>,
2122 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
2124 pub doc_comment: Option<Comment>,
2125}
2126
2127impl ClassConstDecl {
2128 pub fn new(name: Ident, value: Expr) -> Self {
2131 Self {
2132 name,
2133 modifiers: Modifiers::new(),
2134 type_hint: None,
2135 value,
2136 attributes: Box::new([]),
2137 doc_comment: None,
2138 }
2139 }
2140}
2141
2142#[derive(Debug, Clone)]
2144#[cfg_attr(feature = "serde", derive(Serialize))]
2145#[non_exhaustive]
2146pub struct TraitUseDecl {
2147 pub traits: Box<[Name]>,
2149 pub adaptations: Box<[TraitAdaptation]>,
2151 #[cfg_attr(feature = "serde", serde(skip))]
2153 #[doc(hidden)]
2154 pub adaptations_brace_span: Option<Span>,
2155 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
2157 pub doc_comment: Option<Comment>,
2158}
2159
2160impl TraitUseDecl {
2161 pub fn new(traits: Box<[Name]>) -> Self {
2164 Self {
2165 traits,
2166 adaptations: Box::new([]),
2167 adaptations_brace_span: None,
2168 doc_comment: None,
2169 }
2170 }
2171}
2172
2173#[derive(Debug, Clone)]
2175#[cfg_attr(feature = "serde", derive(Serialize))]
2176pub struct TraitAdaptation {
2177 pub kind: TraitAdaptationKind,
2179 pub span: Span,
2181}
2182
2183#[derive(Debug, Clone)]
2185#[cfg_attr(feature = "serde", derive(Serialize))]
2186#[non_exhaustive]
2187pub enum TraitAdaptationKind {
2188 Precedence {
2190 trait_name: Name,
2192 method: Name,
2194 insteadof: Box<[Name]>,
2196 },
2197 Alias {
2199 trait_name: Option<Name>,
2201 method: Name,
2203 new_modifier: Option<Visibility>,
2205 #[cfg_attr(feature = "serde", serde(default, skip_serializing_if = "is_false"))]
2207 is_final: bool,
2208 #[cfg_attr(
2210 feature = "serde",
2211 serde(default, skip_serializing_if = "Option::is_none")
2212 )]
2213 invalid_modifier: Option<Ident>,
2214 new_name: Option<Name>,
2216 },
2217}
2218
2219#[derive(Debug, Clone)]
2221#[cfg_attr(feature = "serde", derive(Serialize))]
2222#[non_exhaustive]
2223pub struct InterfaceDecl {
2224 pub name: Ident,
2226 pub extends: Box<[Name]>,
2228 #[cfg_attr(feature = "serde", serde(flatten))]
2230 pub body: ClassBody,
2231 pub attributes: Box<[Attribute]>,
2233 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
2235 pub doc_comment: Option<Comment>,
2236}
2237
2238impl InterfaceDecl {
2239 pub fn new(name: Ident, body: ClassBody) -> Self {
2242 Self {
2243 name,
2244 extends: Box::new([]),
2245 body,
2246 attributes: Box::new([]),
2247 doc_comment: None,
2248 }
2249 }
2250}
2251
2252#[derive(Debug, Clone)]
2254#[cfg_attr(feature = "serde", derive(Serialize))]
2255#[non_exhaustive]
2256pub struct TraitDecl {
2257 pub name: Ident,
2259 #[cfg_attr(feature = "serde", serde(flatten))]
2261 pub body: ClassBody,
2262 pub attributes: Box<[Attribute]>,
2264 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
2266 pub doc_comment: Option<Comment>,
2267}
2268
2269impl TraitDecl {
2270 pub fn new(name: Ident, body: ClassBody) -> Self {
2273 Self {
2274 name,
2275 body,
2276 attributes: Box::new([]),
2277 doc_comment: None,
2278 }
2279 }
2280}
2281
2282#[derive(Debug, Clone)]
2284#[cfg_attr(feature = "serde", derive(Serialize))]
2285pub struct EnumBody {
2286 pub members: Box<[EnumMember]>,
2288 #[cfg_attr(feature = "serde", serde(skip))]
2290 pub span: Span,
2291}
2292
2293#[derive(Debug, Clone)]
2295#[cfg_attr(feature = "serde", derive(Serialize))]
2296#[non_exhaustive]
2297pub struct EnumDecl {
2298 pub name: Ident,
2300 pub scalar_type: Option<Name>,
2302 pub implements: Box<[Name]>,
2304 #[cfg_attr(feature = "serde", serde(flatten))]
2306 pub body: EnumBody,
2307 pub attributes: Box<[Attribute]>,
2309 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
2311 pub doc_comment: Option<Comment>,
2312}
2313
2314impl EnumDecl {
2315 pub fn new(name: Ident, body: EnumBody) -> Self {
2318 Self {
2319 name,
2320 scalar_type: None,
2321 implements: Box::new([]),
2322 body,
2323 attributes: Box::new([]),
2324 doc_comment: None,
2325 }
2326 }
2327}
2328
2329#[derive(Debug, Clone)]
2331#[cfg_attr(feature = "serde", derive(Serialize))]
2332pub struct EnumMember {
2333 pub kind: EnumMemberKind,
2335 pub span: Span,
2337}
2338
2339#[derive(Debug, Clone)]
2341#[cfg_attr(feature = "serde", derive(Serialize))]
2342#[non_exhaustive]
2343pub enum EnumMemberKind {
2344 Case(EnumCase),
2346 Method(MethodDecl),
2348 ClassConst(ClassConstDecl),
2350 TraitUse(TraitUseDecl),
2352 Property(PropertyDecl),
2354}
2355
2356#[derive(Debug, Clone)]
2358#[cfg_attr(feature = "serde", derive(Serialize))]
2359#[non_exhaustive]
2360pub struct EnumCase {
2361 pub name: Ident,
2363 pub value: Option<Expr>,
2365 pub attributes: Box<[Attribute]>,
2367 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
2369 pub doc_comment: Option<Comment>,
2370}
2371
2372impl EnumCase {
2373 pub fn new(name: Ident) -> Self {
2376 Self {
2377 name,
2378 value: None,
2379 attributes: Box::new([]),
2380 doc_comment: None,
2381 }
2382 }
2383}
2384
2385fn owned_ident(ident: arena_ast::Ident<'_>) -> Ident {
2390 match ident.as_str() {
2391 Some(s) => Ident::new(s, ident.span),
2392 None => Ident::error(ident.span),
2393 }
2394}
2395
2396fn owned_name(name: &arena_ast::Name<'_, '_>) -> Name {
2397 match name {
2398 arena_ast::Name::Simple { value, span } => Name {
2399 parts: vec![Box::from(*value)].into_boxed_slice(),
2400 kind: NameKind::Unqualified,
2401 span: *span,
2402 },
2403 arena_ast::Name::Complex { parts, kind, span } => Name {
2404 parts: parts
2405 .iter()
2406 .map(|s| Box::from(*s))
2407 .collect::<Vec<_>>()
2408 .into_boxed_slice(),
2409 kind: *kind,
2410 span: *span,
2411 },
2412 arena_ast::Name::Error { span } => Name {
2413 parts: Box::from([]),
2414 kind: NameKind::Error,
2415 span: *span,
2416 },
2417 }
2418}
2419
2420fn owned_comment(c: &arena_ast::Comment<'_>) -> Comment {
2421 Comment {
2422 kind: c.kind,
2423 text: c.text.into(),
2424 span: c.span,
2425 }
2426}
2427
2428fn owned_opt_comment(c: &Option<arena_ast::Comment<'_>>) -> Option<Comment> {
2429 c.as_ref().map(owned_comment)
2430}
2431
2432fn owned_type_hint(th: &arena_ast::TypeHint<'_, '_>) -> TypeHint {
2433 TypeHint {
2434 kind: owned_type_hint_kind(&th.kind),
2435 span: th.span,
2436 }
2437}
2438
2439fn owned_type_hint_kind(k: &arena_ast::TypeHintKind<'_, '_>) -> TypeHintKind {
2440 match k {
2441 arena_ast::TypeHintKind::Named(n) => TypeHintKind::Named(owned_name(n)),
2442 arena_ast::TypeHintKind::Keyword(b, span) => TypeHintKind::Keyword(*b, *span),
2443 arena_ast::TypeHintKind::Nullable(inner) => {
2444 TypeHintKind::Nullable(Box::new(owned_type_hint(inner)))
2445 }
2446 arena_ast::TypeHintKind::Union(types) => TypeHintKind::Union(
2447 types
2448 .iter()
2449 .map(owned_type_hint)
2450 .collect::<Vec<_>>()
2451 .into_boxed_slice(),
2452 ),
2453 arena_ast::TypeHintKind::Intersection(types) => TypeHintKind::Intersection(
2454 types
2455 .iter()
2456 .map(owned_type_hint)
2457 .collect::<Vec<_>>()
2458 .into_boxed_slice(),
2459 ),
2460 }
2461}
2462
2463fn owned_arg(arg: &arena_ast::Arg<'_, '_>) -> Arg {
2464 Arg {
2465 name: arg.name.as_ref().map(owned_name),
2466 kind: match &arg.kind {
2467 arena_ast::ArgKind::Value(e) => ArgKind::Value(owned_expr(e)),
2468 arena_ast::ArgKind::Spread(e) => ArgKind::Spread(owned_expr(e)),
2469 arena_ast::ArgKind::ByRef(e) => ArgKind::ByRef(owned_expr(e)),
2470 arena_ast::ArgKind::Placeholder => ArgKind::Placeholder,
2471 arena_ast::ArgKind::SpreadPlaceholder => ArgKind::SpreadPlaceholder,
2472 },
2473 span: arg.span,
2474 }
2475}
2476
2477#[inline(never)]
2478fn owned_args(args: &[arena_ast::Arg<'_, '_>]) -> Box<[Arg]> {
2479 args.iter()
2480 .map(owned_arg)
2481 .collect::<Vec<_>>()
2482 .into_boxed_slice()
2483}
2484
2485fn owned_attr(attr: &arena_ast::Attribute<'_, '_>) -> Attribute {
2486 Attribute {
2487 name: owned_name(&attr.name),
2488 args: owned_args(&attr.args),
2489 span: attr.span,
2490 }
2491}
2492
2493fn owned_attrs(attrs: &[arena_ast::Attribute<'_, '_>]) -> Box<[Attribute]> {
2494 attrs
2495 .iter()
2496 .map(owned_attr)
2497 .collect::<Vec<_>>()
2498 .into_boxed_slice()
2499}
2500
2501#[inline(never)]
2502fn owned_string_parts(parts: &[arena_ast::StringPart<'_, '_>]) -> Box<[StringPart]> {
2503 parts
2504 .iter()
2505 .map(|p| match p {
2506 arena_ast::StringPart::Literal(s) => {
2507 StringPart::Literal(ByteString::from(s.as_bytes()))
2508 }
2509 arena_ast::StringPart::Expr(e) => StringPart::Expr(owned_expr(e)),
2510 })
2511 .collect::<Vec<_>>()
2512 .into_boxed_slice()
2513}
2514
2515pub fn to_owned_expr(expr: &arena_ast::Expr<'_, '_>) -> Expr {
2517 owned_expr(expr)
2518}
2519
2520pub fn to_owned_name(name: &arena_ast::Name<'_, '_>) -> Name {
2522 owned_name(name)
2523}
2524
2525pub fn to_owned_type_hint(hint: &arena_ast::TypeHint<'_, '_>) -> TypeHint {
2527 owned_type_hint(hint)
2528}
2529
2530#[inline]
2531fn owned_expr(expr: &arena_ast::Expr<'_, '_>) -> Expr {
2532 if !arena_is_chain(&expr.kind) {
2533 return Expr {
2534 kind: owned_leaf_kind(&expr.kind),
2535 span: expr.span,
2536 };
2537 }
2538 owned_chain_expr(expr)
2539}
2540
2541#[inline(never)]
2544fn owned_chain_expr(expr: &arena_ast::Expr<'_, '_>) -> Expr {
2545 let first = arena_chain_operand(&expr.kind).expect("chain link has an operand");
2546 if !arena_is_chain(&first.kind) {
2547 let operand = Expr {
2549 kind: owned_leaf_kind(&first.kind),
2550 span: first.span,
2551 };
2552 return Expr {
2553 kind: owned_link_kind(&expr.kind, operand),
2554 span: expr.span,
2555 };
2556 }
2557 let mut chain = LinkStack::new();
2558 chain.push(expr);
2559 let mut leaf = first;
2560 while let Some(operand) = arena_chain_operand(&leaf.kind) {
2561 chain.push(leaf);
2562 leaf = operand;
2563 }
2564 let mut converted = Expr {
2565 kind: owned_leaf_kind(&leaf.kind),
2566 span: leaf.span,
2567 };
2568 while let Some(node) = chain.pop() {
2569 converted = Expr {
2570 kind: owned_link_kind(&node.kind, converted),
2571 span: node.span,
2572 };
2573 }
2574 converted
2575}
2576
2577#[inline(never)]
2578fn owned_exprs(exprs: &[arena_ast::Expr<'_, '_>]) -> Box<[Expr]> {
2579 exprs
2580 .iter()
2581 .map(owned_expr)
2582 .collect::<Vec<_>>()
2583 .into_boxed_slice()
2584}
2585
2586fn owned_leaf_kind(k: &arena_ast::ExprKind<'_, '_>) -> ExprKind {
2588 match k {
2589 arena_ast::ExprKind::Int(v) => ExprKind::Int(*v),
2590 arena_ast::ExprKind::Float(v) => ExprKind::Float(*v),
2591 arena_ast::ExprKind::String(s) => ExprKind::String(ByteString::from(s.as_bytes())),
2592 arena_ast::ExprKind::InterpolatedString(parts) => {
2593 ExprKind::InterpolatedString(owned_string_parts(parts))
2594 }
2595 arena_ast::ExprKind::Heredoc { label, parts } => ExprKind::Heredoc {
2596 label: Box::from(*label),
2597 parts: owned_string_parts(parts),
2598 },
2599 arena_ast::ExprKind::Nowdoc { label, value } => ExprKind::Nowdoc {
2600 label: Box::from(*label),
2601 value: Box::from(*value),
2602 },
2603 arena_ast::ExprKind::ShellExec(parts) => ExprKind::ShellExec(owned_string_parts(parts)),
2604 arena_ast::ExprKind::Bool(v) => ExprKind::Bool(*v),
2605 arena_ast::ExprKind::Null => ExprKind::Null,
2606 arena_ast::ExprKind::Variable(s) => ExprKind::Variable(s.as_str().into()),
2607 arena_ast::ExprKind::VariableVariable(inner) => {
2608 ExprKind::VariableVariable(Box::new(owned_expr(inner)))
2609 }
2610 arena_ast::ExprKind::Identifier(s) => ExprKind::Identifier(s.as_str().into()),
2611 arena_ast::ExprKind::Name(name) => ExprKind::Name(owned_name(name)),
2612 arena_ast::ExprKind::Array(elems) => ExprKind::Array(
2613 elems
2614 .iter()
2615 .map(|e| ArrayElement {
2616 key: e.key.as_ref().map(owned_expr),
2617 kind: match &e.kind {
2618 arena_ast::ArrayElementKind::Value(v) => {
2619 ArrayElementKind::Value(owned_expr(v))
2620 }
2621 arena_ast::ArrayElementKind::Spread(v) => {
2622 ArrayElementKind::Spread(owned_expr(v))
2623 }
2624 arena_ast::ArrayElementKind::ByRef(v) => {
2625 ArrayElementKind::ByRef(owned_expr(v))
2626 }
2627 },
2628 span: e.span,
2629 })
2630 .collect::<Vec<_>>()
2631 .into_boxed_slice(),
2632 ),
2633 arena_ast::ExprKind::Print(e) => ExprKind::Print(Box::new(owned_expr(e))),
2634 arena_ast::ExprKind::Parenthesized(e) => ExprKind::Parenthesized(Box::new(owned_expr(e))),
2635 arena_ast::ExprKind::Cast(kind, e) => ExprKind::Cast(*kind, Box::new(owned_expr(e))),
2636 arena_ast::ExprKind::ErrorSuppress(e) => ExprKind::ErrorSuppress(Box::new(owned_expr(e))),
2637 arena_ast::ExprKind::Isset(exprs) => ExprKind::Isset(owned_exprs(exprs)),
2638 arena_ast::ExprKind::Empty(e) => ExprKind::Empty(Box::new(owned_expr(e))),
2639 arena_ast::ExprKind::Include(kind, e) => ExprKind::Include(*kind, Box::new(owned_expr(e))),
2640 arena_ast::ExprKind::Eval(e) => ExprKind::Eval(Box::new(owned_expr(e))),
2641 arena_ast::ExprKind::Exit(e) => ExprKind::Exit(e.map(|e| Box::new(owned_expr(e)))),
2642 arena_ast::ExprKind::MagicConst(m) => ExprKind::MagicConst(*m),
2643 arena_ast::ExprKind::Clone(e) => ExprKind::Clone(Box::new(owned_expr(e))),
2644 arena_ast::ExprKind::CloneWith(obj, props) => {
2645 ExprKind::CloneWith(Box::new(owned_expr(obj)), Box::new(owned_expr(props)))
2646 }
2647 arena_ast::ExprKind::New(n) => ExprKind::New(NewExpr {
2648 class: Box::new(owned_expr(n.class)),
2649 args: owned_args(&n.args),
2650 }),
2651 arena_ast::ExprKind::Closure(c) => ExprKind::Closure(Box::new(ClosureExpr {
2652 is_static: c.is_static,
2653 by_ref: c.by_ref,
2654 params: owned_params(&c.params),
2655 missing_param_list: c.missing_param_list,
2656 use_vars: c
2657 .use_vars
2658 .iter()
2659 .map(|v| ClosureUseVar {
2660 name: owned_ident(v.name),
2661 by_ref: v.by_ref,
2662 span: v.span,
2663 })
2664 .collect::<Vec<_>>()
2665 .into_boxed_slice(),
2666 return_type: c.return_type.as_ref().map(owned_type_hint),
2667 body: Box::new(owned_block(c.body)),
2668 attributes: owned_attrs(&c.attributes),
2669 })),
2670 arena_ast::ExprKind::ArrowFunction(f) => {
2671 ExprKind::ArrowFunction(Box::new(ArrowFunctionExpr {
2672 is_static: f.is_static,
2673 by_ref: f.by_ref,
2674 params: owned_params(&f.params),
2675 missing_param_list: f.missing_param_list,
2676 return_type: f.return_type.as_ref().map(owned_type_hint),
2677 body: Box::new(owned_expr(f.body)),
2678 attributes: owned_attrs(&f.attributes),
2679 }))
2680 }
2681 arena_ast::ExprKind::Match(m) => ExprKind::Match(MatchExpr {
2682 subject: Box::new(owned_expr(m.subject)),
2683 arms: m
2684 .arms
2685 .iter()
2686 .map(|arm| MatchArm {
2687 conditions: arm.conditions.as_ref().map(|conds| owned_exprs(conds)),
2688 body: owned_expr(&arm.body),
2689 span: arm.span,
2690 })
2691 .collect::<Vec<_>>()
2692 .into_boxed_slice(),
2693 brace_span: m.brace_span,
2694 }),
2695 arena_ast::ExprKind::Throw(e) => ExprKind::Throw(Box::new(owned_expr(e))),
2696 arena_ast::ExprKind::Yield(y) => ExprKind::Yield(YieldExpr {
2697 key: y.key.map(|e| Box::new(owned_expr(e))),
2698 value: y.value.map(|e| Box::new(owned_expr(e))),
2699 is_from: y.is_from,
2700 }),
2701 arena_ast::ExprKind::AnonymousClass(cls) => {
2702 ExprKind::AnonymousClass(Box::new(owned_class_decl(cls)))
2703 }
2704 arena_ast::ExprKind::Omit => ExprKind::Omit,
2705 arena_ast::ExprKind::Error => ExprKind::Error,
2706 arena_ast::ExprKind::Assign(_)
2707 | arena_ast::ExprKind::Binary(_)
2708 | arena_ast::ExprKind::UnaryPrefix(_)
2709 | arena_ast::ExprKind::UnaryPostfix(_)
2710 | arena_ast::ExprKind::Ternary(_)
2711 | arena_ast::ExprKind::NullCoalesce(_)
2712 | arena_ast::ExprKind::FunctionCall(_)
2713 | arena_ast::ExprKind::ArrayAccess(_)
2714 | arena_ast::ExprKind::PropertyAccess(_)
2715 | arena_ast::ExprKind::NullsafePropertyAccess(_)
2716 | arena_ast::ExprKind::MethodCall(_)
2717 | arena_ast::ExprKind::NullsafeMethodCall(_)
2718 | arena_ast::ExprKind::StaticPropertyAccess(_)
2719 | arena_ast::ExprKind::ClassConstAccess(_)
2720 | arena_ast::ExprKind::StaticMethodCall(_)
2721 | arena_ast::ExprKind::StaticMethodCallDynamic(_)
2722 | arena_ast::ExprKind::ClassConstAccessDynamic { .. }
2723 | arena_ast::ExprKind::StaticPropertyAccessDynamic { .. }
2724 | arena_ast::ExprKind::CallableCreate(_) => {
2725 unreachable!("chain links are converted by the link function")
2726 }
2727 }
2728}
2729
2730fn owned_link_kind(k: &arena_ast::ExprKind<'_, '_>, operand: Expr) -> ExprKind {
2732 match k {
2733 arena_ast::ExprKind::Assign(a) => ExprKind::Assign(AssignExpr {
2734 target: Box::new(operand),
2735 op: a.op,
2736 value: Box::new(owned_expr(a.value)),
2737 by_ref: a.by_ref,
2738 }),
2739 arena_ast::ExprKind::Binary(b) => ExprKind::Binary(BinaryExpr {
2740 left: Box::new(operand),
2741 op: b.op,
2742 right: Box::new(owned_expr(b.right)),
2743 }),
2744 arena_ast::ExprKind::UnaryPrefix(u) => ExprKind::UnaryPrefix(UnaryPrefixExpr {
2745 op: u.op,
2746 operand: Box::new(operand),
2747 }),
2748 arena_ast::ExprKind::UnaryPostfix(u) => ExprKind::UnaryPostfix(UnaryPostfixExpr {
2749 operand: Box::new(operand),
2750 op: u.op,
2751 }),
2752 arena_ast::ExprKind::Ternary(t) => ExprKind::Ternary(TernaryExpr {
2753 condition: Box::new(operand),
2754 then_expr: t.then_expr.map(|e| Box::new(owned_expr(e))),
2755 else_expr: Box::new(owned_expr(t.else_expr)),
2756 }),
2757 arena_ast::ExprKind::NullCoalesce(n) => ExprKind::NullCoalesce(NullCoalesceExpr {
2758 left: Box::new(operand),
2759 right: Box::new(owned_expr(n.right)),
2760 }),
2761 arena_ast::ExprKind::FunctionCall(f) => ExprKind::FunctionCall(FunctionCallExpr {
2762 name: Box::new(operand),
2763 args: owned_args(&f.args),
2764 }),
2765 arena_ast::ExprKind::ArrayAccess(a) => ExprKind::ArrayAccess(ArrayAccessExpr {
2766 array: Box::new(operand),
2767 index: a.index.map(|e| Box::new(owned_expr(e))),
2768 }),
2769 arena_ast::ExprKind::PropertyAccess(p) => ExprKind::PropertyAccess(PropertyAccessExpr {
2770 object: Box::new(operand),
2771 property: Box::new(owned_expr(p.property)),
2772 }),
2773 arena_ast::ExprKind::NullsafePropertyAccess(p) => {
2774 ExprKind::NullsafePropertyAccess(PropertyAccessExpr {
2775 object: Box::new(operand),
2776 property: Box::new(owned_expr(p.property)),
2777 })
2778 }
2779 arena_ast::ExprKind::MethodCall(m) => ExprKind::MethodCall(Box::new(MethodCallExpr {
2780 object: Box::new(operand),
2781 method: Box::new(owned_expr(m.method)),
2782 args: owned_args(&m.args),
2783 })),
2784 arena_ast::ExprKind::NullsafeMethodCall(m) => {
2785 ExprKind::NullsafeMethodCall(Box::new(MethodCallExpr {
2786 object: Box::new(operand),
2787 method: Box::new(owned_expr(m.method)),
2788 args: owned_args(&m.args),
2789 }))
2790 }
2791 arena_ast::ExprKind::StaticPropertyAccess(s) => {
2792 ExprKind::StaticPropertyAccess(StaticAccessExpr {
2793 class: Box::new(operand),
2794 member: Box::new(owned_expr(s.member)),
2795 })
2796 }
2797 arena_ast::ExprKind::StaticMethodCall(s) => {
2798 ExprKind::StaticMethodCall(Box::new(StaticMethodCallExpr {
2799 class: Box::new(operand),
2800 method: Box::new(owned_expr(s.method)),
2801 args: owned_args(&s.args),
2802 }))
2803 }
2804 arena_ast::ExprKind::StaticMethodCallDynamic(s) => {
2805 ExprKind::StaticMethodCallDynamic(Box::new(StaticMethodCallDynamicExpr {
2806 class: Box::new(operand),
2807 method: Box::new(owned_expr(s.method)),
2808 args: owned_args(&s.args),
2809 }))
2810 }
2811 arena_ast::ExprKind::ClassConstAccess(s) => ExprKind::ClassConstAccess(StaticAccessExpr {
2812 class: Box::new(operand),
2813 member: Box::new(owned_expr(s.member)),
2814 }),
2815 arena_ast::ExprKind::ClassConstAccessDynamic { member, .. } => {
2816 ExprKind::ClassConstAccessDynamic {
2817 class: Box::new(operand),
2818 member: Box::new(owned_expr(member)),
2819 }
2820 }
2821 arena_ast::ExprKind::StaticPropertyAccessDynamic { member, .. } => {
2822 ExprKind::StaticPropertyAccessDynamic {
2823 class: Box::new(operand),
2824 member: Box::new(owned_expr(member)),
2825 }
2826 }
2827 arena_ast::ExprKind::CallableCreate(c) => ExprKind::CallableCreate(CallableCreateExpr {
2828 kind: match &c.kind {
2829 arena_ast::CallableCreateKind::Function(_) => {
2830 CallableCreateKind::Function(Box::new(operand))
2831 }
2832 arena_ast::CallableCreateKind::Method { method, .. } => {
2833 CallableCreateKind::Method {
2834 object: Box::new(operand),
2835 method: Box::new(owned_expr(method)),
2836 }
2837 }
2838 arena_ast::CallableCreateKind::NullsafeMethod { method, .. } => {
2839 CallableCreateKind::NullsafeMethod {
2840 object: Box::new(operand),
2841 method: Box::new(owned_expr(method)),
2842 }
2843 }
2844 arena_ast::CallableCreateKind::StaticMethod { method, .. } => {
2845 CallableCreateKind::StaticMethod {
2846 class: Box::new(operand),
2847 method: Box::new(owned_expr(method)),
2848 }
2849 }
2850 },
2851 }),
2852 _ => unreachable!("not a chain link"),
2853 }
2854}
2855
2856fn owned_param(p: &arena_ast::Param<'_, '_>) -> Param {
2857 Param {
2858 name: owned_ident(p.name),
2859 type_hint: p.type_hint.as_ref().map(owned_type_hint),
2860 default: p.default.as_ref().map(owned_expr),
2861 by_ref: p.by_ref,
2862 variadic: p.variadic,
2863 modifiers: p.modifiers,
2864 attributes: owned_attrs(&p.attributes),
2865 hooks: owned_hooks(&p.hooks),
2866 empty_hook_list: p.empty_hook_list,
2867 doc_comment: p.doc_comment.as_ref().map(owned_comment),
2868 span: p.span,
2869 }
2870}
2871
2872#[inline(never)]
2873fn owned_params(params: &[arena_ast::Param<'_, '_>]) -> Box<[Param]> {
2874 params
2875 .iter()
2876 .map(owned_param)
2877 .collect::<Vec<_>>()
2878 .into_boxed_slice()
2879}
2880
2881fn owned_hook(h: &arena_ast::PropertyHook<'_, '_>) -> PropertyHook {
2882 PropertyHook {
2883 kind: h.kind,
2884 body: match &h.body {
2885 arena_ast::PropertyHookBody::Block(block) => {
2886 PropertyHookBody::Block(Box::new(owned_block(block)))
2887 }
2888 arena_ast::PropertyHookBody::Expression(e) => {
2889 PropertyHookBody::Expression(owned_expr(e))
2890 }
2891 arena_ast::PropertyHookBody::Abstract => PropertyHookBody::Abstract,
2892 },
2893 modifiers: h.modifiers,
2894 by_ref: h.by_ref,
2895 params: owned_params(&h.params),
2896 empty_param_list: h.empty_param_list,
2897 attributes: owned_attrs(&h.attributes),
2898 name_span: h.name_span,
2899 span: h.span,
2900 }
2901}
2902
2903#[inline(never)]
2904fn owned_hooks(hooks: &[arena_ast::PropertyHook<'_, '_>]) -> Box<[PropertyHook]> {
2905 hooks
2906 .iter()
2907 .map(owned_hook)
2908 .collect::<Vec<_>>()
2909 .into_boxed_slice()
2910}
2911
2912fn owned_stmts(stmts: &[arena_ast::Stmt<'_, '_>]) -> Box<[Stmt]> {
2913 stmts
2914 .iter()
2915 .map(owned_stmt)
2916 .collect::<Vec<_>>()
2917 .into_boxed_slice()
2918}
2919
2920pub fn to_owned_stmt(stmt: &arena_ast::Stmt<'_, '_>) -> Stmt {
2922 owned_stmt(stmt)
2923}
2924
2925fn owned_block(block: &arena_ast::Block<'_, '_>) -> Block {
2926 Block {
2927 stmts: owned_stmts(&block.stmts),
2928 span: block.span,
2929 }
2930}
2931
2932fn owned_stmt(stmt: &arena_ast::Stmt<'_, '_>) -> Stmt {
2933 Stmt {
2934 kind: owned_stmt_kind(&stmt.kind),
2935 span: stmt.span,
2936 doc_comment: stmt.doc_comment.map(owned_comment),
2937 }
2938}
2939
2940fn owned_stmt_kind(k: &arena_ast::StmtKind<'_, '_>) -> StmtKind {
2941 match k {
2942 arena_ast::StmtKind::Expression(e) => StmtKind::Expression(Box::new(owned_expr(e))),
2943 arena_ast::StmtKind::Echo(exprs) => StmtKind::Echo(owned_exprs(exprs)),
2944 arena_ast::StmtKind::Return(e) => StmtKind::Return(e.map(|e| Box::new(owned_expr(e)))),
2945 arena_ast::StmtKind::Block(block) => StmtKind::Block(Box::new(owned_block(block))),
2946 arena_ast::StmtKind::If(s) => StmtKind::If(Box::new(IfStmt {
2947 condition: owned_expr(&s.condition),
2948 then_branch: Box::new(owned_stmt(s.then_branch)),
2949 elseif_branches: s
2950 .elseif_branches
2951 .iter()
2952 .map(|b| ElseIfBranch {
2953 condition: owned_expr(&b.condition),
2954 body: owned_stmt(&b.body),
2955 span: b.span,
2956 })
2957 .collect::<Vec<_>>()
2958 .into_boxed_slice(),
2959 else_branch: s.else_branch.map(|b| Box::new(owned_stmt(b))),
2960 else_kw_span: s.else_kw_span,
2961 uses_alternative: s.uses_alternative,
2962 })),
2963 arena_ast::StmtKind::While(s) => StmtKind::While(Box::new(WhileStmt {
2964 condition: owned_expr(&s.condition),
2965 body: Box::new(owned_stmt(s.body)),
2966 uses_alternative: s.uses_alternative,
2967 })),
2968 arena_ast::StmtKind::For(s) => StmtKind::For(Box::new(ForStmt {
2969 init: owned_exprs(&s.init),
2970 condition: owned_exprs(&s.condition),
2971 update: owned_exprs(&s.update),
2972 body: Box::new(owned_stmt(s.body)),
2973 uses_alternative: s.uses_alternative,
2974 })),
2975 arena_ast::StmtKind::Foreach(s) => StmtKind::Foreach(Box::new(ForeachStmt {
2976 expr: owned_expr(&s.expr),
2977 key: s.key.as_ref().map(owned_expr),
2978 key_by_ref: s.key_by_ref,
2979 value: owned_expr(&s.value),
2980 by_ref: s.by_ref,
2981 by_ref_span: s.by_ref_span,
2982 body: Box::new(owned_stmt(s.body)),
2983 uses_alternative: s.uses_alternative,
2984 })),
2985 arena_ast::StmtKind::DoWhile(s) => StmtKind::DoWhile(Box::new(DoWhileStmt {
2986 body: Box::new(owned_stmt(s.body)),
2987 condition: owned_expr(&s.condition),
2988 })),
2989 arena_ast::StmtKind::Function(f) => StmtKind::Function(Box::new(owned_function_decl(f))),
2990 arena_ast::StmtKind::Break(e) => StmtKind::Break(e.map(|e| Box::new(owned_expr(e)))),
2991 arena_ast::StmtKind::Continue(e) => StmtKind::Continue(e.map(|e| Box::new(owned_expr(e)))),
2992 arena_ast::StmtKind::Switch(s) => StmtKind::Switch(Box::new(SwitchStmt {
2993 expr: owned_expr(&s.expr),
2994 body: SwitchBody {
2995 cases: s
2996 .body
2997 .cases
2998 .iter()
2999 .map(|c| SwitchCase {
3000 value: c.value.as_ref().map(owned_expr),
3001 body: owned_stmts(&c.body),
3002 span: c.span,
3003 })
3004 .collect::<Vec<_>>()
3005 .into_boxed_slice(),
3006 span: s.body.span,
3007 },
3008 uses_alternative: s.uses_alternative,
3009 })),
3010 arena_ast::StmtKind::Goto(ident) => StmtKind::Goto(owned_ident(*ident)),
3011 arena_ast::StmtKind::Label(ident) => StmtKind::Label(owned_ident(*ident)),
3012 arena_ast::StmtKind::Declare(d) => StmtKind::Declare(Box::new(DeclareStmt {
3013 directives: d
3014 .directives
3015 .iter()
3016 .map(|(k, v)| (Box::from(*k), owned_expr(v)))
3017 .collect::<Vec<_>>()
3018 .into_boxed_slice(),
3019 body: d.body.map(|b| Box::new(owned_stmt(b))),
3020 uses_alternative: d.uses_alternative,
3021 })),
3022 arena_ast::StmtKind::Unset(exprs) => StmtKind::Unset(owned_exprs(exprs)),
3023 arena_ast::StmtKind::Throw(e) => StmtKind::Throw(Box::new(owned_expr(e))),
3024 arena_ast::StmtKind::TryCatch(t) => StmtKind::TryCatch(Box::new(TryCatchStmt {
3025 body: Box::new(owned_block(t.body)),
3026 catches: t
3027 .catches
3028 .iter()
3029 .map(|c| CatchClause {
3030 types: c
3031 .types
3032 .iter()
3033 .map(owned_name)
3034 .collect::<Vec<_>>()
3035 .into_boxed_slice(),
3036 var: c.var.map(owned_ident),
3037 body: Box::new(owned_block(c.body)),
3038 span: c.span,
3039 })
3040 .collect::<Vec<_>>()
3041 .into_boxed_slice(),
3042 finally: t.finally.map(|f| Box::new(owned_block(f))),
3043 finally_kw_span: t.finally_kw_span,
3044 })),
3045 arena_ast::StmtKind::Global(exprs) => StmtKind::Global(owned_exprs(exprs)),
3046 arena_ast::StmtKind::Class(cls) => StmtKind::Class(Box::new(owned_class_decl(cls))),
3047 arena_ast::StmtKind::Interface(iface) => {
3048 StmtKind::Interface(Box::new(owned_interface_decl(iface)))
3049 }
3050 arena_ast::StmtKind::Trait(tr) => StmtKind::Trait(Box::new(owned_trait_decl(tr))),
3051 arena_ast::StmtKind::Enum(en) => StmtKind::Enum(Box::new(owned_enum_decl(en))),
3052 arena_ast::StmtKind::Namespace(ns) => StmtKind::Namespace(Box::new(NamespaceDecl {
3053 name: ns.name.as_ref().map(owned_name),
3054 body: match &ns.body {
3055 arena_ast::NamespaceBody::Braced(block) => {
3056 NamespaceBody::Braced(Box::new(owned_block(block)))
3057 }
3058 arena_ast::NamespaceBody::Simple => NamespaceBody::Simple,
3059 },
3060 })),
3061 arena_ast::StmtKind::Use(u) => StmtKind::Use(Box::new(UseDecl {
3062 kind: u.kind,
3063 uses: u
3064 .uses
3065 .iter()
3066 .map(|item| UseItem {
3067 name: owned_name(&item.name),
3068 alias: item.alias.map(owned_ident),
3069 kind: item.kind,
3070 span: item.span,
3071 })
3072 .collect::<Vec<_>>()
3073 .into_boxed_slice(),
3074 })),
3075 arena_ast::StmtKind::Const(items) => StmtKind::Const(
3076 items
3077 .iter()
3078 .map(|item| ConstItem {
3079 name: owned_ident(item.name),
3080 value: owned_expr(&item.value),
3081 attributes: owned_attrs(&item.attributes),
3082 span: item.span,
3083 doc_comment: owned_opt_comment(&item.doc_comment),
3084 })
3085 .collect::<Vec<_>>()
3086 .into_boxed_slice(),
3087 ),
3088 arena_ast::StmtKind::StaticVar(vars) => StmtKind::StaticVar(
3089 vars.iter()
3090 .map(|v| StaticVar {
3091 name: owned_ident(v.name),
3092 default: v.default.as_ref().map(owned_expr),
3093 span: v.span,
3094 })
3095 .collect::<Vec<_>>()
3096 .into_boxed_slice(),
3097 ),
3098 arena_ast::StmtKind::HaltCompiler(s) => StmtKind::HaltCompiler(Box::from(*s)),
3099 arena_ast::StmtKind::Nop => StmtKind::Nop,
3100 arena_ast::StmtKind::InlineHtml(s) => StmtKind::InlineHtml(Box::from(*s)),
3101 arena_ast::StmtKind::Error => StmtKind::Error,
3102 }
3103}
3104
3105fn owned_function_decl(f: &arena_ast::FunctionDecl<'_, '_>) -> FunctionDecl {
3106 FunctionDecl {
3107 name: owned_ident(f.name),
3108 params: owned_params(&f.params),
3109 missing_param_list: f.missing_param_list,
3110 body: Box::new(owned_block(f.body)),
3111 return_type: f.return_type.as_ref().map(owned_type_hint),
3112 by_ref: f.by_ref,
3113 attributes: owned_attrs(&f.attributes),
3114 doc_comment: owned_opt_comment(&f.doc_comment),
3115 }
3116}
3117
3118fn owned_property(p: &arena_ast::PropertyDecl<'_, '_>) -> PropertyDecl {
3119 PropertyDecl {
3120 name: owned_ident(p.name),
3121 modifiers: p.modifiers,
3122 type_hint: p.type_hint.as_ref().map(owned_type_hint),
3123 default: p.default.as_ref().map(owned_expr),
3124 attributes: owned_attrs(&p.attributes),
3125 hooks: owned_hooks(&p.hooks),
3126 empty_hook_list: p.empty_hook_list,
3127 doc_comment: owned_opt_comment(&p.doc_comment),
3128 }
3129}
3130
3131fn owned_class_member(m: &arena_ast::ClassMember<'_, '_>) -> ClassMember {
3132 ClassMember {
3133 kind: match &m.kind {
3134 arena_ast::ClassMemberKind::Property(p) => ClassMemberKind::Property(owned_property(p)),
3135 arena_ast::ClassMemberKind::Method(m) => ClassMemberKind::Method(MethodDecl {
3136 name: owned_ident(m.name),
3137 modifiers: m.modifiers,
3138 by_ref: m.by_ref,
3139 params: owned_params(&m.params),
3140 missing_param_list: m.missing_param_list,
3141 return_type: m.return_type.as_ref().map(owned_type_hint),
3142 body: m.body.map(|b| Box::new(owned_block(b))),
3143 attributes: owned_attrs(&m.attributes),
3144 doc_comment: owned_opt_comment(&m.doc_comment),
3145 }),
3146 arena_ast::ClassMemberKind::ClassConst(c) => {
3147 ClassMemberKind::ClassConst(owned_class_const(c))
3148 }
3149 arena_ast::ClassMemberKind::TraitUse(t) => {
3150 ClassMemberKind::TraitUse(owned_trait_use(t))
3151 }
3152 },
3153 span: m.span,
3154 }
3155}
3156
3157fn owned_class_members(members: &[arena_ast::ClassMember<'_, '_>]) -> Box<[ClassMember]> {
3158 members
3159 .iter()
3160 .map(owned_class_member)
3161 .collect::<Vec<_>>()
3162 .into_boxed_slice()
3163}
3164
3165fn owned_class_const(c: &arena_ast::ClassConstDecl<'_, '_>) -> ClassConstDecl {
3166 ClassConstDecl {
3167 name: owned_ident(c.name),
3168 modifiers: c.modifiers,
3169 type_hint: c.type_hint.map(|th| Box::new(owned_type_hint(th))),
3170 value: owned_expr(&c.value),
3171 attributes: owned_attrs(&c.attributes),
3172 doc_comment: owned_opt_comment(&c.doc_comment),
3173 }
3174}
3175
3176fn owned_trait_use(t: &arena_ast::TraitUseDecl<'_, '_>) -> TraitUseDecl {
3177 TraitUseDecl {
3178 traits: t
3179 .traits
3180 .iter()
3181 .map(owned_name)
3182 .collect::<Vec<_>>()
3183 .into_boxed_slice(),
3184 adaptations: t
3185 .adaptations
3186 .iter()
3187 .map(|a| TraitAdaptation {
3188 kind: match &a.kind {
3189 arena_ast::TraitAdaptationKind::Precedence {
3190 trait_name,
3191 method,
3192 insteadof,
3193 } => TraitAdaptationKind::Precedence {
3194 trait_name: owned_name(trait_name),
3195 method: owned_name(method),
3196 insteadof: insteadof
3197 .iter()
3198 .map(owned_name)
3199 .collect::<Vec<_>>()
3200 .into_boxed_slice(),
3201 },
3202 arena_ast::TraitAdaptationKind::Alias {
3203 trait_name,
3204 method,
3205 new_modifier,
3206 is_final,
3207 invalid_modifier,
3208 new_name,
3209 } => TraitAdaptationKind::Alias {
3210 trait_name: trait_name.as_ref().map(owned_name),
3211 method: owned_name(method),
3212 new_modifier: *new_modifier,
3213 is_final: *is_final,
3214 invalid_modifier: (*invalid_modifier).map(owned_ident),
3215 new_name: new_name.as_ref().map(owned_name),
3216 },
3217 },
3218 span: a.span,
3219 })
3220 .collect::<Vec<_>>()
3221 .into_boxed_slice(),
3222 adaptations_brace_span: t.adaptations_brace_span,
3223 doc_comment: owned_opt_comment(&t.doc_comment),
3224 }
3225}
3226
3227fn owned_class_decl(cls: &arena_ast::ClassDecl<'_, '_>) -> ClassDecl {
3228 ClassDecl {
3229 name: cls
3230 .name
3231 .map(|ident| Some(owned_ident(ident)))
3232 .unwrap_or(None),
3233 modifiers: cls.modifiers.clone(),
3234 extends: cls.extends.as_ref().map(owned_name),
3235 implements: cls
3236 .implements
3237 .iter()
3238 .map(owned_name)
3239 .collect::<Vec<_>>()
3240 .into_boxed_slice(),
3241 body: ClassBody {
3242 members: owned_class_members(&cls.body.members),
3243 span: cls.body.span,
3244 },
3245 attributes: owned_attrs(&cls.attributes),
3246 doc_comment: owned_opt_comment(&cls.doc_comment),
3247 }
3248}
3249
3250fn owned_interface_decl(iface: &arena_ast::InterfaceDecl<'_, '_>) -> InterfaceDecl {
3251 InterfaceDecl {
3252 name: owned_ident(iface.name),
3253 extends: iface
3254 .extends
3255 .iter()
3256 .map(owned_name)
3257 .collect::<Vec<_>>()
3258 .into_boxed_slice(),
3259 body: ClassBody {
3260 members: owned_class_members(&iface.body.members),
3261 span: iface.body.span,
3262 },
3263 attributes: owned_attrs(&iface.attributes),
3264 doc_comment: owned_opt_comment(&iface.doc_comment),
3265 }
3266}
3267
3268fn owned_trait_decl(tr: &arena_ast::TraitDecl<'_, '_>) -> TraitDecl {
3269 TraitDecl {
3270 name: owned_ident(tr.name),
3271 body: ClassBody {
3272 members: owned_class_members(&tr.body.members),
3273 span: tr.body.span,
3274 },
3275 attributes: owned_attrs(&tr.attributes),
3276 doc_comment: owned_opt_comment(&tr.doc_comment),
3277 }
3278}
3279
3280fn owned_enum_decl(en: &arena_ast::EnumDecl<'_, '_>) -> EnumDecl {
3281 EnumDecl {
3282 name: owned_ident(en.name),
3283 scalar_type: en.scalar_type.as_ref().map(owned_name),
3284 implements: en
3285 .implements
3286 .iter()
3287 .map(owned_name)
3288 .collect::<Vec<_>>()
3289 .into_boxed_slice(),
3290 body: EnumBody {
3291 members: en
3292 .body
3293 .members
3294 .iter()
3295 .map(|m| EnumMember {
3296 kind: match &m.kind {
3297 arena_ast::EnumMemberKind::Case(c) => EnumMemberKind::Case(EnumCase {
3298 name: owned_ident(c.name),
3299 value: c.value.as_ref().map(owned_expr),
3300 attributes: owned_attrs(&c.attributes),
3301 doc_comment: owned_opt_comment(&c.doc_comment),
3302 }),
3303 arena_ast::EnumMemberKind::Method(m) => {
3304 EnumMemberKind::Method(MethodDecl {
3305 name: owned_ident(m.name),
3306 modifiers: m.modifiers,
3307 by_ref: m.by_ref,
3308 params: owned_params(&m.params),
3309 missing_param_list: m.missing_param_list,
3310 return_type: m.return_type.as_ref().map(owned_type_hint),
3311 body: m.body.map(|b| Box::new(owned_block(b))),
3312 attributes: owned_attrs(&m.attributes),
3313 doc_comment: owned_opt_comment(&m.doc_comment),
3314 })
3315 }
3316 arena_ast::EnumMemberKind::ClassConst(c) => {
3317 EnumMemberKind::ClassConst(owned_class_const(c))
3318 }
3319 arena_ast::EnumMemberKind::TraitUse(t) => {
3320 EnumMemberKind::TraitUse(owned_trait_use(t))
3321 }
3322 arena_ast::EnumMemberKind::Property(p) => {
3323 EnumMemberKind::Property(owned_property(p))
3324 }
3325 },
3326 span: m.span,
3327 })
3328 .collect::<Vec<_>>()
3329 .into_boxed_slice(),
3330 span: en.body.span,
3331 },
3332 attributes: owned_attrs(&en.attributes),
3333 doc_comment: owned_opt_comment(&en.doc_comment),
3334 }
3335}
3336
3337pub fn to_owned_program(program: &arena_ast::Program<'_, '_>) -> Program {
3339 Program {
3340 stmts: owned_stmts(&program.stmts),
3341 span: program.span,
3342 }
3343}
3344
3345#[doc(hidden)]
3359pub fn from_owned_program<'arena>(
3360 arena: &'arena bumpalo::Bump,
3361 program: &Program,
3362) -> arena_ast::Program<'arena, 'arena> {
3363 arena_ast::Program {
3364 stmts: av_stmts(arena, &program.stmts),
3365 span: program.span,
3366 }
3367}
3368
3369#[inline]
3371fn av_str<'a>(arena: &'a bumpalo::Bump, s: &str) -> &'a str {
3372 arena.alloc_str(s)
3373}
3374
3375fn av_ident<'a>(arena: &'a bumpalo::Bump, ident: &Ident) -> arena_ast::Ident<'a> {
3376 match ident.as_str() {
3377 Some(s) => arena_ast::Ident::new(arena.alloc_str(s), ident.span),
3378 None => arena_ast::Ident::error(ident.span),
3379 }
3380}
3381
3382fn av_name<'a>(arena: &'a bumpalo::Bump, name: &Name) -> arena_ast::Name<'a, 'a> {
3383 if name.kind == NameKind::Error {
3384 return arena_ast::Name::Error { span: name.span };
3385 }
3386 if name.parts.len() == 1 && name.kind == NameKind::Unqualified {
3387 return arena_ast::Name::Simple {
3388 value: arena.alloc_str(&name.parts[0]),
3389 span: name.span,
3390 };
3391 }
3392 let mut parts = arena_ast::ArenaVec::with_capacity_in(name.parts.len(), arena);
3393 for p in name.parts.iter() {
3394 parts.push(arena.alloc_str(p) as &str);
3395 }
3396 arena_ast::Name::Complex {
3397 parts,
3398 kind: name.kind,
3399 span: name.span,
3400 }
3401}
3402
3403fn av_type_hint<'a>(arena: &'a bumpalo::Bump, th: &TypeHint) -> arena_ast::TypeHint<'a, 'a> {
3404 arena_ast::TypeHint {
3405 kind: av_type_hint_kind(arena, &th.kind),
3406 span: th.span,
3407 }
3408}
3409
3410fn av_type_hint_kind<'a>(
3411 arena: &'a bumpalo::Bump,
3412 k: &TypeHintKind,
3413) -> arena_ast::TypeHintKind<'a, 'a> {
3414 match k {
3415 TypeHintKind::Named(n) => arena_ast::TypeHintKind::Named(av_name(arena, n)),
3416 TypeHintKind::Keyword(b, span) => arena_ast::TypeHintKind::Keyword(*b, *span),
3417 TypeHintKind::Nullable(inner) => {
3418 arena_ast::TypeHintKind::Nullable(arena.alloc(av_type_hint(arena, inner)))
3419 }
3420 TypeHintKind::Union(types) => {
3421 let mut v = arena_ast::ArenaVec::with_capacity_in(types.len(), arena);
3422 for t in types.iter() {
3423 v.push(av_type_hint(arena, t));
3424 }
3425 arena_ast::TypeHintKind::Union(v)
3426 }
3427 TypeHintKind::Intersection(types) => {
3428 let mut v = arena_ast::ArenaVec::with_capacity_in(types.len(), arena);
3429 for t in types.iter() {
3430 v.push(av_type_hint(arena, t));
3431 }
3432 arena_ast::TypeHintKind::Intersection(v)
3433 }
3434 }
3435}
3436
3437fn av_arg<'a>(arena: &'a bumpalo::Bump, arg: &Arg) -> arena_ast::Arg<'a, 'a> {
3438 arena_ast::Arg {
3439 name: arg.name.as_ref().map(|n| av_name(arena, n)),
3440 kind: match &arg.kind {
3441 ArgKind::Value(e) => arena_ast::ArgKind::Value(av_expr(arena, e)),
3442 ArgKind::Spread(e) => arena_ast::ArgKind::Spread(av_expr(arena, e)),
3443 ArgKind::ByRef(e) => arena_ast::ArgKind::ByRef(av_expr(arena, e)),
3444 ArgKind::Placeholder => arena_ast::ArgKind::Placeholder,
3445 ArgKind::SpreadPlaceholder => arena_ast::ArgKind::SpreadPlaceholder,
3446 },
3447 span: arg.span,
3448 }
3449}
3450
3451#[inline(never)]
3452fn av_args<'a>(
3453 arena: &'a bumpalo::Bump,
3454 args: &[Arg],
3455) -> arena_ast::ArenaVec<'a, arena_ast::Arg<'a, 'a>> {
3456 let mut v = arena_ast::ArenaVec::with_capacity_in(args.len(), arena);
3457 for a in args.iter() {
3458 v.push(av_arg(arena, a));
3459 }
3460 v
3461}
3462
3463fn av_attr<'a>(arena: &'a bumpalo::Bump, attr: &Attribute) -> arena_ast::Attribute<'a, 'a> {
3464 arena_ast::Attribute {
3465 name: av_name(arena, &attr.name),
3466 args: av_args(arena, &attr.args),
3467 span: attr.span,
3468 }
3469}
3470
3471#[inline(never)]
3472fn av_attrs<'a>(
3473 arena: &'a bumpalo::Bump,
3474 attrs: &[Attribute],
3475) -> arena_ast::ArenaVec<'a, arena_ast::Attribute<'a, 'a>> {
3476 let mut v = arena_ast::ArenaVec::with_capacity_in(attrs.len(), arena);
3477 for a in attrs.iter() {
3478 v.push(av_attr(arena, a));
3479 }
3480 v
3481}
3482
3483fn av_comment<'a>(arena: &'a bumpalo::Bump, c: &Comment) -> arena_ast::Comment<'a> {
3484 arena_ast::Comment {
3485 kind: c.kind,
3486 text: arena.alloc_str(&c.text),
3487 span: c.span,
3488 }
3489}
3490
3491fn av_opt_comment<'a>(
3492 arena: &'a bumpalo::Bump,
3493 c: &Option<Comment>,
3494) -> Option<arena_ast::Comment<'a>> {
3495 c.as_ref().map(|c| av_comment(arena, c))
3496}
3497
3498fn av_string_parts<'a>(
3499 arena: &'a bumpalo::Bump,
3500 parts: &[StringPart],
3501) -> arena_ast::ArenaVec<'a, arena_ast::StringPart<'a, 'a>> {
3502 let mut v = arena_ast::ArenaVec::with_capacity_in(parts.len(), arena);
3503 for p in parts.iter() {
3504 v.push(match p {
3505 StringPart::Literal(s) => {
3506 arena_ast::StringPart::Literal(arena_ast::ByteStr::new_in(arena, s.as_bytes()))
3507 }
3508 StringPart::Expr(e) => arena_ast::StringPart::Expr(av_expr(arena, e)),
3509 });
3510 }
3511 v
3512}
3513
3514fn av_expr<'a>(arena: &'a bumpalo::Bump, expr: &Expr) -> arena_ast::Expr<'a, 'a> {
3515 if !owned_is_chain(&expr.kind) {
3516 return arena_ast::Expr {
3517 kind: av_leaf_kind(arena, &expr.kind),
3518 span: expr.span,
3519 };
3520 }
3521 av_chain_expr(arena, expr)
3522}
3523
3524#[inline(never)]
3526fn av_chain_expr<'a>(arena: &'a bumpalo::Bump, expr: &Expr) -> arena_ast::Expr<'a, 'a> {
3527 let first = owned_chain_operand(&expr.kind).expect("chain link has an operand");
3528 if !owned_is_chain(&first.kind) {
3529 let operand = arena_ast::Expr {
3530 kind: av_leaf_kind(arena, &first.kind),
3531 span: first.span,
3532 };
3533 return arena_ast::Expr {
3534 kind: av_link_kind(arena, &expr.kind, operand),
3535 span: expr.span,
3536 };
3537 }
3538 let mut chain = LinkStack::new();
3539 chain.push(expr);
3540 let mut leaf = first;
3541 while let Some(operand) = owned_chain_operand(&leaf.kind) {
3542 chain.push(leaf);
3543 leaf = operand;
3544 }
3545 let mut converted = arena_ast::Expr {
3546 kind: av_leaf_kind(arena, &leaf.kind),
3547 span: leaf.span,
3548 };
3549 while let Some(node) = chain.pop() {
3550 converted = arena_ast::Expr {
3551 kind: av_link_kind(arena, &node.kind, converted),
3552 span: node.span,
3553 };
3554 }
3555 converted
3556}
3557
3558#[inline(never)]
3559fn av_exprs<'a>(
3560 arena: &'a bumpalo::Bump,
3561 exprs: &[Expr],
3562) -> arena_ast::ArenaVec<'a, arena_ast::Expr<'a, 'a>> {
3563 let mut v = arena_ast::ArenaVec::with_capacity_in(exprs.len(), arena);
3564 for e in exprs.iter() {
3565 v.push(av_expr(arena, e));
3566 }
3567 v
3568}
3569
3570fn av_namestr<'a>(arena: &'a bumpalo::Bump, s: &str) -> arena_ast::NameStr<'a, 'a> {
3571 arena_ast::NameStr::from_arena(arena.alloc_str(s))
3572}
3573
3574fn av_leaf_kind<'a>(arena: &'a bumpalo::Bump, k: &ExprKind) -> arena_ast::ExprKind<'a, 'a> {
3576 match k {
3577 ExprKind::Int(v) => arena_ast::ExprKind::Int(*v),
3578 ExprKind::Float(v) => arena_ast::ExprKind::Float(*v),
3579 ExprKind::String(s) => {
3580 arena_ast::ExprKind::String(arena_ast::ByteStr::new_in(arena, s.as_bytes()))
3581 }
3582 ExprKind::InterpolatedString(parts) => {
3583 arena_ast::ExprKind::InterpolatedString(av_string_parts(arena, parts))
3584 }
3585 ExprKind::Heredoc { label, parts } => arena_ast::ExprKind::Heredoc {
3586 label: arena.alloc_str(label),
3587 parts: av_string_parts(arena, parts),
3588 },
3589 ExprKind::Nowdoc { label, value } => arena_ast::ExprKind::Nowdoc {
3590 label: arena.alloc_str(label),
3591 value: arena.alloc_str(value),
3592 },
3593 ExprKind::ShellExec(parts) => arena_ast::ExprKind::ShellExec(av_string_parts(arena, parts)),
3594 ExprKind::Bool(v) => arena_ast::ExprKind::Bool(*v),
3595 ExprKind::Null => arena_ast::ExprKind::Null,
3596 ExprKind::Variable(s) => arena_ast::ExprKind::Variable(av_namestr(arena, s)),
3597 ExprKind::VariableVariable(inner) => {
3598 arena_ast::ExprKind::VariableVariable(arena.alloc(av_expr(arena, inner)))
3599 }
3600 ExprKind::Identifier(s) => arena_ast::ExprKind::Identifier(av_namestr(arena, s)),
3601 ExprKind::Name(name) => arena_ast::ExprKind::Name(av_name(arena, name)),
3602 ExprKind::Array(elems) => {
3603 let mut v = arena_ast::ArenaVec::with_capacity_in(elems.len(), arena);
3604 for e in elems.iter() {
3605 v.push(arena_ast::ArrayElement {
3606 key: e.key.as_ref().map(|k| av_expr(arena, k)),
3607 kind: match &e.kind {
3608 ArrayElementKind::Value(v) => {
3609 arena_ast::ArrayElementKind::Value(av_expr(arena, v))
3610 }
3611 ArrayElementKind::Spread(v) => {
3612 arena_ast::ArrayElementKind::Spread(av_expr(arena, v))
3613 }
3614 ArrayElementKind::ByRef(v) => {
3615 arena_ast::ArrayElementKind::ByRef(av_expr(arena, v))
3616 }
3617 },
3618 span: e.span,
3619 });
3620 }
3621 arena_ast::ExprKind::Array(v)
3622 }
3623 ExprKind::Print(e) => arena_ast::ExprKind::Print(arena.alloc(av_expr(arena, e))),
3624 ExprKind::Parenthesized(e) => {
3625 arena_ast::ExprKind::Parenthesized(arena.alloc(av_expr(arena, e)))
3626 }
3627 ExprKind::Cast(kind, e) => arena_ast::ExprKind::Cast(*kind, arena.alloc(av_expr(arena, e))),
3628 ExprKind::ErrorSuppress(e) => {
3629 arena_ast::ExprKind::ErrorSuppress(arena.alloc(av_expr(arena, e)))
3630 }
3631 ExprKind::Isset(exprs) => arena_ast::ExprKind::Isset(av_exprs(arena, exprs)),
3632 ExprKind::Empty(e) => arena_ast::ExprKind::Empty(arena.alloc(av_expr(arena, e))),
3633 ExprKind::Include(kind, e) => {
3634 arena_ast::ExprKind::Include(*kind, arena.alloc(av_expr(arena, e)))
3635 }
3636 ExprKind::Eval(e) => arena_ast::ExprKind::Eval(arena.alloc(av_expr(arena, e))),
3637 ExprKind::Exit(e) => {
3638 arena_ast::ExprKind::Exit(e.as_ref().map(|e| &*arena.alloc(av_expr(arena, e))))
3639 }
3640 ExprKind::MagicConst(m) => arena_ast::ExprKind::MagicConst(*m),
3641 ExprKind::Clone(e) => arena_ast::ExprKind::Clone(arena.alloc(av_expr(arena, e))),
3642 ExprKind::CloneWith(obj, props) => arena_ast::ExprKind::CloneWith(
3643 arena.alloc(av_expr(arena, obj)),
3644 arena.alloc(av_expr(arena, props)),
3645 ),
3646 ExprKind::New(n) => arena_ast::ExprKind::New(arena_ast::NewExpr {
3647 class: arena.alloc(av_expr(arena, &n.class)),
3648 args: av_args(arena, &n.args),
3649 }),
3650 ExprKind::Closure(c) => arena_ast::ExprKind::Closure(arena.alloc(arena_ast::ClosureExpr {
3651 is_static: c.is_static,
3652 by_ref: c.by_ref,
3653 params: av_params(arena, &c.params),
3654 missing_param_list: c.missing_param_list,
3655 use_vars: {
3656 let mut v = arena_ast::ArenaVec::with_capacity_in(c.use_vars.len(), arena);
3657 for uv in c.use_vars.iter() {
3658 v.push(arena_ast::ClosureUseVar {
3659 name: av_ident(arena, &uv.name),
3660 by_ref: uv.by_ref,
3661 span: uv.span,
3662 });
3663 }
3664 v
3665 },
3666 return_type: c.return_type.as_ref().map(|t| av_type_hint(arena, t)),
3667 body: &*arena.alloc(av_block(arena, &c.body)),
3668 attributes: av_attrs(arena, &c.attributes),
3669 })),
3670 ExprKind::ArrowFunction(f) => {
3671 arena_ast::ExprKind::ArrowFunction(arena.alloc(arena_ast::ArrowFunctionExpr {
3672 is_static: f.is_static,
3673 by_ref: f.by_ref,
3674 params: av_params(arena, &f.params),
3675 missing_param_list: f.missing_param_list,
3676 return_type: f.return_type.as_ref().map(|t| av_type_hint(arena, t)),
3677 body: arena.alloc(av_expr(arena, &f.body)),
3678 attributes: av_attrs(arena, &f.attributes),
3679 }))
3680 }
3681 ExprKind::Match(m) => arena_ast::ExprKind::Match(arena_ast::MatchExpr {
3682 subject: arena.alloc(av_expr(arena, &m.subject)),
3683 arms: {
3684 let mut v = arena_ast::ArenaVec::with_capacity_in(m.arms.len(), arena);
3685 for arm in m.arms.iter() {
3686 v.push(arena_ast::MatchArm {
3687 conditions: arm.conditions.as_ref().map(|conds| av_exprs(arena, conds)),
3688 body: av_expr(arena, &arm.body),
3689 span: arm.span,
3690 });
3691 }
3692 v
3693 },
3694 brace_span: m.brace_span,
3695 }),
3696 ExprKind::Throw(e) => arena_ast::ExprKind::Throw(arena.alloc(av_expr(arena, e))),
3697 ExprKind::Yield(y) => arena_ast::ExprKind::Yield(arena_ast::YieldExpr {
3698 key: y.key.as_ref().map(|e| &*arena.alloc(av_expr(arena, e))),
3699 value: y.value.as_ref().map(|e| &*arena.alloc(av_expr(arena, e))),
3700 is_from: y.is_from,
3701 }),
3702 ExprKind::AnonymousClass(cls) => {
3703 arena_ast::ExprKind::AnonymousClass(arena.alloc(av_class_decl(arena, cls)))
3704 }
3705 ExprKind::Omit => arena_ast::ExprKind::Omit,
3706 ExprKind::Error => arena_ast::ExprKind::Error,
3707 ExprKind::Assign(_)
3708 | ExprKind::Binary(_)
3709 | ExprKind::UnaryPrefix(_)
3710 | ExprKind::UnaryPostfix(_)
3711 | ExprKind::Ternary(_)
3712 | ExprKind::NullCoalesce(_)
3713 | ExprKind::FunctionCall(_)
3714 | ExprKind::ArrayAccess(_)
3715 | ExprKind::PropertyAccess(_)
3716 | ExprKind::NullsafePropertyAccess(_)
3717 | ExprKind::MethodCall(_)
3718 | ExprKind::NullsafeMethodCall(_)
3719 | ExprKind::StaticPropertyAccess(_)
3720 | ExprKind::ClassConstAccess(_)
3721 | ExprKind::StaticMethodCall(_)
3722 | ExprKind::StaticMethodCallDynamic(_)
3723 | ExprKind::ClassConstAccessDynamic { .. }
3724 | ExprKind::StaticPropertyAccessDynamic { .. }
3725 | ExprKind::CallableCreate(_) => {
3726 unreachable!("chain links are converted by the link function")
3727 }
3728 }
3729}
3730
3731fn av_link_kind<'a>(
3733 arena: &'a bumpalo::Bump,
3734 k: &ExprKind,
3735 operand: arena_ast::Expr<'a, 'a>,
3736) -> arena_ast::ExprKind<'a, 'a> {
3737 match k {
3738 ExprKind::Assign(a) => arena_ast::ExprKind::Assign(arena_ast::AssignExpr {
3739 target: arena.alloc(operand),
3740 op: a.op,
3741 value: arena.alloc(av_expr(arena, &a.value)),
3742 by_ref: a.by_ref,
3743 }),
3744 ExprKind::Binary(b) => arena_ast::ExprKind::Binary(arena_ast::BinaryExpr {
3745 left: arena.alloc(operand),
3746 op: b.op,
3747 right: arena.alloc(av_expr(arena, &b.right)),
3748 }),
3749 ExprKind::UnaryPrefix(u) => arena_ast::ExprKind::UnaryPrefix(arena_ast::UnaryPrefixExpr {
3750 op: u.op,
3751 operand: arena.alloc(operand),
3752 }),
3753 ExprKind::UnaryPostfix(u) => {
3754 arena_ast::ExprKind::UnaryPostfix(arena_ast::UnaryPostfixExpr {
3755 operand: arena.alloc(operand),
3756 op: u.op,
3757 })
3758 }
3759 ExprKind::Ternary(t) => arena_ast::ExprKind::Ternary(arena_ast::TernaryExpr {
3760 condition: arena.alloc(operand),
3761 then_expr: t
3762 .then_expr
3763 .as_ref()
3764 .map(|e| &*arena.alloc(av_expr(arena, e))),
3765 else_expr: arena.alloc(av_expr(arena, &t.else_expr)),
3766 }),
3767 ExprKind::NullCoalesce(n) => {
3768 arena_ast::ExprKind::NullCoalesce(arena_ast::NullCoalesceExpr {
3769 left: arena.alloc(operand),
3770 right: arena.alloc(av_expr(arena, &n.right)),
3771 })
3772 }
3773 ExprKind::FunctionCall(f) => {
3774 arena_ast::ExprKind::FunctionCall(arena_ast::FunctionCallExpr {
3775 name: arena.alloc(operand),
3776 args: av_args(arena, &f.args),
3777 })
3778 }
3779 ExprKind::ArrayAccess(a) => arena_ast::ExprKind::ArrayAccess(arena_ast::ArrayAccessExpr {
3780 array: arena.alloc(operand),
3781 index: a.index.as_ref().map(|e| &*arena.alloc(av_expr(arena, e))),
3782 }),
3783 ExprKind::PropertyAccess(p) => {
3784 arena_ast::ExprKind::PropertyAccess(arena_ast::PropertyAccessExpr {
3785 object: arena.alloc(operand),
3786 property: arena.alloc(av_expr(arena, &p.property)),
3787 })
3788 }
3789 ExprKind::NullsafePropertyAccess(p) => {
3790 arena_ast::ExprKind::NullsafePropertyAccess(arena_ast::PropertyAccessExpr {
3791 object: arena.alloc(operand),
3792 property: arena.alloc(av_expr(arena, &p.property)),
3793 })
3794 }
3795 ExprKind::MethodCall(m) => {
3796 arena_ast::ExprKind::MethodCall(arena.alloc(arena_ast::MethodCallExpr {
3797 object: arena.alloc(operand),
3798 method: arena.alloc(av_expr(arena, &m.method)),
3799 args: av_args(arena, &m.args),
3800 }))
3801 }
3802 ExprKind::NullsafeMethodCall(m) => {
3803 arena_ast::ExprKind::NullsafeMethodCall(arena.alloc(arena_ast::MethodCallExpr {
3804 object: arena.alloc(operand),
3805 method: arena.alloc(av_expr(arena, &m.method)),
3806 args: av_args(arena, &m.args),
3807 }))
3808 }
3809 ExprKind::StaticPropertyAccess(s) => {
3810 arena_ast::ExprKind::StaticPropertyAccess(arena_ast::StaticAccessExpr {
3811 class: arena.alloc(operand),
3812 member: arena.alloc(av_expr(arena, &s.member)),
3813 })
3814 }
3815 ExprKind::StaticMethodCall(s) => {
3816 arena_ast::ExprKind::StaticMethodCall(arena.alloc(arena_ast::StaticMethodCallExpr {
3817 class: arena.alloc(operand),
3818 method: arena.alloc(av_expr(arena, &s.method)),
3819 args: av_args(arena, &s.args),
3820 }))
3821 }
3822 ExprKind::StaticMethodCallDynamic(s) => arena_ast::ExprKind::StaticMethodCallDynamic(
3823 arena.alloc(arena_ast::StaticMethodCallDynamicExpr {
3824 class: arena.alloc(operand),
3825 method: arena.alloc(av_expr(arena, &s.method)),
3826 args: av_args(arena, &s.args),
3827 }),
3828 ),
3829 ExprKind::ClassConstAccess(s) => {
3830 arena_ast::ExprKind::ClassConstAccess(arena_ast::StaticAccessExpr {
3831 class: arena.alloc(operand),
3832 member: arena.alloc(av_expr(arena, &s.member)),
3833 })
3834 }
3835 ExprKind::ClassConstAccessDynamic { member, .. } => {
3836 arena_ast::ExprKind::ClassConstAccessDynamic {
3837 class: arena.alloc(operand),
3838 member: arena.alloc(av_expr(arena, member)),
3839 }
3840 }
3841 ExprKind::StaticPropertyAccessDynamic { member, .. } => {
3842 arena_ast::ExprKind::StaticPropertyAccessDynamic {
3843 class: arena.alloc(operand),
3844 member: arena.alloc(av_expr(arena, member)),
3845 }
3846 }
3847 ExprKind::CallableCreate(c) => {
3848 arena_ast::ExprKind::CallableCreate(arena_ast::CallableCreateExpr {
3849 kind: match &c.kind {
3850 CallableCreateKind::Function(_) => {
3851 arena_ast::CallableCreateKind::Function(arena.alloc(operand))
3852 }
3853 CallableCreateKind::Method { method, .. } => {
3854 arena_ast::CallableCreateKind::Method {
3855 object: arena.alloc(operand),
3856 method: arena.alloc(av_expr(arena, method)),
3857 }
3858 }
3859 CallableCreateKind::NullsafeMethod { method, .. } => {
3860 arena_ast::CallableCreateKind::NullsafeMethod {
3861 object: arena.alloc(operand),
3862 method: arena.alloc(av_expr(arena, method)),
3863 }
3864 }
3865 CallableCreateKind::StaticMethod { method, .. } => {
3866 arena_ast::CallableCreateKind::StaticMethod {
3867 class: arena.alloc(operand),
3868 method: arena.alloc(av_expr(arena, method)),
3869 }
3870 }
3871 },
3872 })
3873 }
3874 _ => unreachable!("not a chain link"),
3875 }
3876}
3877
3878fn av_param<'a>(arena: &'a bumpalo::Bump, p: &Param) -> arena_ast::Param<'a, 'a> {
3879 arena_ast::Param {
3880 name: av_ident(arena, &p.name),
3881 type_hint: p.type_hint.as_ref().map(|t| av_type_hint(arena, t)),
3882 default: p.default.as_ref().map(|e| av_expr(arena, e)),
3883 by_ref: p.by_ref,
3884 variadic: p.variadic,
3885 modifiers: p.modifiers,
3886 attributes: av_attrs(arena, &p.attributes),
3887 hooks: av_hooks(arena, &p.hooks),
3888 empty_hook_list: p.empty_hook_list,
3889 doc_comment: av_opt_comment(arena, &p.doc_comment),
3890 span: p.span,
3891 }
3892}
3893
3894#[inline(never)]
3895fn av_params<'a>(
3896 arena: &'a bumpalo::Bump,
3897 params: &[Param],
3898) -> arena_ast::ArenaVec<'a, arena_ast::Param<'a, 'a>> {
3899 let mut v = arena_ast::ArenaVec::with_capacity_in(params.len(), arena);
3900 for p in params.iter() {
3901 v.push(av_param(arena, p));
3902 }
3903 v
3904}
3905
3906fn av_hook<'a>(arena: &'a bumpalo::Bump, h: &PropertyHook) -> arena_ast::PropertyHook<'a, 'a> {
3907 arena_ast::PropertyHook {
3908 kind: h.kind,
3909 body: match &h.body {
3910 PropertyHookBody::Block(block) => {
3911 arena_ast::PropertyHookBody::Block(arena.alloc(av_block(arena, block)))
3912 }
3913 PropertyHookBody::Expression(e) => {
3914 arena_ast::PropertyHookBody::Expression(av_expr(arena, e))
3915 }
3916 PropertyHookBody::Abstract => arena_ast::PropertyHookBody::Abstract,
3917 },
3918 modifiers: h.modifiers,
3919 by_ref: h.by_ref,
3920 params: av_params(arena, &h.params),
3921 empty_param_list: h.empty_param_list,
3922 attributes: av_attrs(arena, &h.attributes),
3923 name_span: h.name_span,
3924 span: h.span,
3925 }
3926}
3927
3928fn av_hooks<'a>(
3929 arena: &'a bumpalo::Bump,
3930 hooks: &[PropertyHook],
3931) -> arena_ast::ArenaVec<'a, arena_ast::PropertyHook<'a, 'a>> {
3932 let mut v = arena_ast::ArenaVec::with_capacity_in(hooks.len(), arena);
3933 for h in hooks.iter() {
3934 v.push(av_hook(arena, h));
3935 }
3936 v
3937}
3938
3939fn av_stmt<'a>(arena: &'a bumpalo::Bump, stmt: &Stmt) -> arena_ast::Stmt<'a, 'a> {
3940 arena_ast::Stmt {
3941 kind: av_stmt_kind(arena, &stmt.kind),
3942 span: stmt.span,
3943 doc_comment: stmt.doc_comment.as_ref().map(|c| {
3944 &*arena.alloc(arena_ast::Comment {
3945 kind: c.kind,
3946 text: arena.alloc_str(&c.text),
3947 span: c.span,
3948 })
3949 }),
3950 }
3951}
3952
3953fn av_stmts<'a>(
3954 arena: &'a bumpalo::Bump,
3955 stmts: &[Stmt],
3956) -> arena_ast::ArenaVec<'a, arena_ast::Stmt<'a, 'a>> {
3957 let mut v = arena_ast::ArenaVec::with_capacity_in(stmts.len(), arena);
3958 for s in stmts.iter() {
3959 v.push(av_stmt(arena, s));
3960 }
3961 v
3962}
3963
3964fn av_block<'a>(arena: &'a bumpalo::Bump, block: &Block) -> arena_ast::Block<'a, 'a> {
3965 arena_ast::Block {
3966 stmts: av_stmts(arena, &block.stmts),
3967 span: block.span,
3968 }
3969}
3970
3971fn av_stmt_kind<'a>(arena: &'a bumpalo::Bump, k: &StmtKind) -> arena_ast::StmtKind<'a, 'a> {
3972 match k {
3973 StmtKind::Expression(e) => arena_ast::StmtKind::Expression(arena.alloc(av_expr(arena, e))),
3974 StmtKind::Echo(exprs) => arena_ast::StmtKind::Echo(av_exprs(arena, exprs)),
3975 StmtKind::Return(e) => {
3976 arena_ast::StmtKind::Return(e.as_ref().map(|e| &*arena.alloc(av_expr(arena, e))))
3977 }
3978 StmtKind::Block(block) => arena_ast::StmtKind::Block(arena.alloc(av_block(arena, block))),
3979 StmtKind::If(s) => arena_ast::StmtKind::If(arena.alloc(av_if_stmt(arena, s))),
3980 StmtKind::While(s) => arena_ast::StmtKind::While(arena.alloc(av_while_stmt(arena, s))),
3981 StmtKind::For(s) => arena_ast::StmtKind::For(arena.alloc(av_for_stmt(arena, s))),
3982 StmtKind::Foreach(s) => {
3983 arena_ast::StmtKind::Foreach(arena.alloc(av_foreach_stmt(arena, s)))
3984 }
3985 StmtKind::DoWhile(s) => {
3986 arena_ast::StmtKind::DoWhile(arena.alloc(av_do_while_stmt(arena, s)))
3987 }
3988 StmtKind::Function(f) => {
3989 arena_ast::StmtKind::Function(arena.alloc(av_function_decl(arena, f)))
3990 }
3991 StmtKind::Break(e) => {
3992 arena_ast::StmtKind::Break(e.as_ref().map(|e| &*arena.alloc(av_expr(arena, e))))
3993 }
3994 StmtKind::Continue(e) => {
3995 arena_ast::StmtKind::Continue(e.as_ref().map(|e| &*arena.alloc(av_expr(arena, e))))
3996 }
3997 StmtKind::Switch(s) => arena_ast::StmtKind::Switch(arena.alloc(av_switch_stmt(arena, s))),
3998 StmtKind::Goto(ident) => arena_ast::StmtKind::Goto(av_ident(arena, ident)),
3999 StmtKind::Label(ident) => arena_ast::StmtKind::Label(av_ident(arena, ident)),
4000 StmtKind::Declare(d) => {
4001 arena_ast::StmtKind::Declare(arena.alloc(av_declare_stmt(arena, d)))
4002 }
4003 StmtKind::Unset(exprs) => arena_ast::StmtKind::Unset(av_exprs(arena, exprs)),
4004 StmtKind::Throw(e) => arena_ast::StmtKind::Throw(arena.alloc(av_expr(arena, e))),
4005 StmtKind::TryCatch(t) => {
4006 arena_ast::StmtKind::TryCatch(arena.alloc(av_try_catch_stmt(arena, t)))
4007 }
4008 StmtKind::Global(exprs) => arena_ast::StmtKind::Global(av_exprs(arena, exprs)),
4009 StmtKind::Class(cls) => arena_ast::StmtKind::Class(arena.alloc(av_class_decl(arena, cls))),
4010 StmtKind::Interface(iface) => {
4011 arena_ast::StmtKind::Interface(arena.alloc(av_interface_decl(arena, iface)))
4012 }
4013 StmtKind::Trait(tr) => arena_ast::StmtKind::Trait(arena.alloc(av_trait_decl(arena, tr))),
4014 StmtKind::Enum(en) => arena_ast::StmtKind::Enum(arena.alloc(av_enum_decl(arena, en))),
4015 StmtKind::Namespace(ns) => {
4016 arena_ast::StmtKind::Namespace(arena.alloc(av_namespace_decl(arena, ns)))
4017 }
4018 StmtKind::Use(u) => arena_ast::StmtKind::Use(arena.alloc(av_use_decl(arena, u))),
4019 StmtKind::Const(items) => arena_ast::StmtKind::Const(av_const_items(arena, items)),
4020 StmtKind::StaticVar(vars) => arena_ast::StmtKind::StaticVar(av_static_vars(arena, vars)),
4021 StmtKind::HaltCompiler(s) => arena_ast::StmtKind::HaltCompiler(av_str(arena, s)),
4022 StmtKind::Nop => arena_ast::StmtKind::Nop,
4023 StmtKind::InlineHtml(s) => arena_ast::StmtKind::InlineHtml(av_str(arena, s)),
4024 StmtKind::Error => arena_ast::StmtKind::Error,
4025 }
4026}
4027
4028#[inline(never)]
4031fn av_if_stmt<'a>(arena: &'a bumpalo::Bump, s: &IfStmt) -> arena_ast::IfStmt<'a, 'a> {
4032 arena_ast::IfStmt {
4033 condition: av_expr(arena, &s.condition),
4034 then_branch: arena.alloc(av_stmt(arena, &s.then_branch)),
4035 elseif_branches: {
4036 let mut v = arena_ast::ArenaVec::with_capacity_in(s.elseif_branches.len(), arena);
4037 for b in s.elseif_branches.iter() {
4038 v.push(arena_ast::ElseIfBranch {
4039 condition: av_expr(arena, &b.condition),
4040 body: av_stmt(arena, &b.body),
4041 span: b.span,
4042 });
4043 }
4044 v
4045 },
4046 else_branch: s
4047 .else_branch
4048 .as_ref()
4049 .map(|b| &*arena.alloc(av_stmt(arena, b))),
4050 else_kw_span: s.else_kw_span,
4051 uses_alternative: s.uses_alternative,
4052 }
4053}
4054
4055#[inline(never)]
4056fn av_while_stmt<'a>(arena: &'a bumpalo::Bump, s: &WhileStmt) -> arena_ast::WhileStmt<'a, 'a> {
4057 arena_ast::WhileStmt {
4058 condition: av_expr(arena, &s.condition),
4059 body: arena.alloc(av_stmt(arena, &s.body)),
4060 uses_alternative: s.uses_alternative,
4061 }
4062}
4063
4064#[inline(never)]
4065fn av_for_stmt<'a>(arena: &'a bumpalo::Bump, s: &ForStmt) -> arena_ast::ForStmt<'a, 'a> {
4066 arena_ast::ForStmt {
4067 init: av_exprs(arena, &s.init),
4068 condition: av_exprs(arena, &s.condition),
4069 update: av_exprs(arena, &s.update),
4070 body: arena.alloc(av_stmt(arena, &s.body)),
4071 uses_alternative: s.uses_alternative,
4072 }
4073}
4074
4075#[inline(never)]
4076fn av_foreach_stmt<'a>(
4077 arena: &'a bumpalo::Bump,
4078 s: &ForeachStmt,
4079) -> arena_ast::ForeachStmt<'a, 'a> {
4080 arena_ast::ForeachStmt {
4081 expr: av_expr(arena, &s.expr),
4082 key: s.key.as_ref().map(|e| av_expr(arena, e)),
4083 key_by_ref: s.key_by_ref,
4084 value: av_expr(arena, &s.value),
4085 by_ref: s.by_ref,
4086 by_ref_span: s.by_ref_span,
4087 body: arena.alloc(av_stmt(arena, &s.body)),
4088 uses_alternative: s.uses_alternative,
4089 }
4090}
4091
4092#[inline(never)]
4093fn av_do_while_stmt<'a>(
4094 arena: &'a bumpalo::Bump,
4095 s: &DoWhileStmt,
4096) -> arena_ast::DoWhileStmt<'a, 'a> {
4097 arena_ast::DoWhileStmt {
4098 body: arena.alloc(av_stmt(arena, &s.body)),
4099 condition: av_expr(arena, &s.condition),
4100 }
4101}
4102
4103#[inline(never)]
4104fn av_switch_stmt<'a>(arena: &'a bumpalo::Bump, s: &SwitchStmt) -> arena_ast::SwitchStmt<'a, 'a> {
4105 arena_ast::SwitchStmt {
4106 expr: av_expr(arena, &s.expr),
4107 body: {
4108 let mut cases = arena_ast::ArenaVec::with_capacity_in(s.body.cases.len(), arena);
4109 for c in s.body.cases.iter() {
4110 cases.push(arena_ast::SwitchCase {
4111 value: c.value.as_ref().map(|vl| av_expr(arena, vl)),
4112 body: av_stmts(arena, &c.body),
4113 span: c.span,
4114 });
4115 }
4116 arena_ast::SwitchBody {
4117 cases,
4118 span: s.body.span,
4119 }
4120 },
4121 uses_alternative: s.uses_alternative,
4122 }
4123}
4124
4125#[inline(never)]
4126fn av_declare_stmt<'a>(
4127 arena: &'a bumpalo::Bump,
4128 d: &DeclareStmt,
4129) -> arena_ast::DeclareStmt<'a, 'a> {
4130 arena_ast::DeclareStmt {
4131 directives: {
4132 let mut v = arena_ast::ArenaVec::with_capacity_in(d.directives.len(), arena);
4133 for (k, val) in d.directives.iter() {
4134 v.push((arena.alloc_str(k) as &str, av_expr(arena, val)));
4135 }
4136 v
4137 },
4138 body: d.body.as_ref().map(|b| &*arena.alloc(av_stmt(arena, b))),
4139 uses_alternative: d.uses_alternative,
4140 }
4141}
4142
4143#[inline(never)]
4144fn av_try_catch_stmt<'a>(
4145 arena: &'a bumpalo::Bump,
4146 t: &TryCatchStmt,
4147) -> arena_ast::TryCatchStmt<'a, 'a> {
4148 arena_ast::TryCatchStmt {
4149 body: arena.alloc(av_block(arena, &t.body)),
4150 catches: {
4151 let mut v = arena_ast::ArenaVec::with_capacity_in(t.catches.len(), arena);
4152 for c in t.catches.iter() {
4153 let mut types = arena_ast::ArenaVec::with_capacity_in(c.types.len(), arena);
4154 for n in c.types.iter() {
4155 types.push(av_name(arena, n));
4156 }
4157 v.push(arena_ast::CatchClause {
4158 types,
4159 var: c.var.as_ref().map(|v| av_ident(arena, v)),
4160 body: arena.alloc(av_block(arena, &c.body)),
4161 span: c.span,
4162 });
4163 }
4164 v
4165 },
4166 finally: t
4167 .finally
4168 .as_deref()
4169 .map(|f| &*arena.alloc(av_block(arena, f))),
4170 finally_kw_span: t.finally_kw_span,
4171 }
4172}
4173
4174#[inline(never)]
4175fn av_namespace_decl<'a>(
4176 arena: &'a bumpalo::Bump,
4177 ns: &NamespaceDecl,
4178) -> arena_ast::NamespaceDecl<'a, 'a> {
4179 arena_ast::NamespaceDecl {
4180 name: ns.name.as_ref().map(|n| av_name(arena, n)),
4181 body: match &ns.body {
4182 NamespaceBody::Braced(block) => {
4183 arena_ast::NamespaceBody::Braced(&*arena.alloc(av_block(arena, block)))
4184 }
4185 NamespaceBody::Simple => arena_ast::NamespaceBody::Simple,
4186 },
4187 }
4188}
4189
4190#[inline(never)]
4191fn av_use_decl<'a>(arena: &'a bumpalo::Bump, u: &UseDecl) -> arena_ast::UseDecl<'a, 'a> {
4192 arena_ast::UseDecl {
4193 kind: u.kind,
4194 uses: {
4195 let mut v = arena_ast::ArenaVec::with_capacity_in(u.uses.len(), arena);
4196 for item in u.uses.iter() {
4197 v.push(arena_ast::UseItem {
4198 name: av_name(arena, &item.name),
4199 alias: item.alias.as_ref().map(|a| av_ident(arena, a)),
4200 kind: item.kind,
4201 span: item.span,
4202 });
4203 }
4204 v
4205 },
4206 }
4207}
4208
4209#[inline(never)]
4210fn av_const_items<'a>(
4211 arena: &'a bumpalo::Bump,
4212 items: &[ConstItem],
4213) -> arena_ast::ArenaVec<'a, arena_ast::ConstItem<'a, 'a>> {
4214 let mut v = arena_ast::ArenaVec::with_capacity_in(items.len(), arena);
4215 for item in items.iter() {
4216 v.push(arena_ast::ConstItem {
4217 name: av_ident(arena, &item.name),
4218 value: av_expr(arena, &item.value),
4219 attributes: av_attrs(arena, &item.attributes),
4220 span: item.span,
4221 doc_comment: av_opt_comment(arena, &item.doc_comment),
4222 });
4223 }
4224 v
4225}
4226
4227#[inline(never)]
4228fn av_static_vars<'a>(
4229 arena: &'a bumpalo::Bump,
4230 vars: &[StaticVar],
4231) -> arena_ast::ArenaVec<'a, arena_ast::StaticVar<'a, 'a>> {
4232 let mut v = arena_ast::ArenaVec::with_capacity_in(vars.len(), arena);
4233 for var in vars.iter() {
4234 v.push(arena_ast::StaticVar {
4235 name: av_ident(arena, &var.name),
4236 default: var.default.as_ref().map(|e| av_expr(arena, e)),
4237 span: var.span,
4238 });
4239 }
4240 v
4241}
4242
4243#[inline(never)]
4244fn av_function_decl<'a>(
4245 arena: &'a bumpalo::Bump,
4246 f: &FunctionDecl,
4247) -> arena_ast::FunctionDecl<'a, 'a> {
4248 arena_ast::FunctionDecl {
4249 name: av_ident(arena, &f.name),
4250 params: av_params(arena, &f.params),
4251 missing_param_list: f.missing_param_list,
4252 body: &*arena.alloc(av_block(arena, &f.body)),
4253 return_type: f.return_type.as_ref().map(|t| av_type_hint(arena, t)),
4254 by_ref: f.by_ref,
4255 attributes: av_attrs(arena, &f.attributes),
4256 doc_comment: av_opt_comment(arena, &f.doc_comment),
4257 }
4258}
4259
4260fn av_property<'a>(arena: &'a bumpalo::Bump, p: &PropertyDecl) -> arena_ast::PropertyDecl<'a, 'a> {
4261 arena_ast::PropertyDecl {
4262 name: av_ident(arena, &p.name),
4263 modifiers: p.modifiers,
4264 type_hint: p.type_hint.as_ref().map(|t| av_type_hint(arena, t)),
4265 default: p.default.as_ref().map(|e| av_expr(arena, e)),
4266 attributes: av_attrs(arena, &p.attributes),
4267 hooks: av_hooks(arena, &p.hooks),
4268 empty_hook_list: p.empty_hook_list,
4269 doc_comment: av_opt_comment(arena, &p.doc_comment),
4270 }
4271}
4272
4273fn av_class_member<'a>(
4274 arena: &'a bumpalo::Bump,
4275 m: &ClassMember,
4276) -> arena_ast::ClassMember<'a, 'a> {
4277 arena_ast::ClassMember {
4278 kind: match &m.kind {
4279 ClassMemberKind::Property(p) => {
4280 arena_ast::ClassMemberKind::Property(av_property(arena, p))
4281 }
4282 ClassMemberKind::Method(m) => {
4283 arena_ast::ClassMemberKind::Method(arena_ast::MethodDecl {
4284 name: av_ident(arena, &m.name),
4285 modifiers: m.modifiers,
4286 by_ref: m.by_ref,
4287 params: av_params(arena, &m.params),
4288 missing_param_list: m.missing_param_list,
4289 return_type: m.return_type.as_ref().map(|t| av_type_hint(arena, t)),
4290 body: m.body.as_deref().map(|b| &*arena.alloc(av_block(arena, b))),
4291 attributes: av_attrs(arena, &m.attributes),
4292 doc_comment: av_opt_comment(arena, &m.doc_comment),
4293 })
4294 }
4295 ClassMemberKind::ClassConst(c) => {
4296 arena_ast::ClassMemberKind::ClassConst(av_class_const(arena, c))
4297 }
4298 ClassMemberKind::TraitUse(t) => {
4299 arena_ast::ClassMemberKind::TraitUse(av_trait_use(arena, t))
4300 }
4301 },
4302 span: m.span,
4303 }
4304}
4305
4306fn av_class_members<'a>(
4307 arena: &'a bumpalo::Bump,
4308 members: &[ClassMember],
4309) -> arena_ast::ArenaVec<'a, arena_ast::ClassMember<'a, 'a>> {
4310 let mut v = arena_ast::ArenaVec::with_capacity_in(members.len(), arena);
4311 for m in members.iter() {
4312 v.push(av_class_member(arena, m));
4313 }
4314 v
4315}
4316
4317fn av_class_const<'a>(
4318 arena: &'a bumpalo::Bump,
4319 c: &ClassConstDecl,
4320) -> arena_ast::ClassConstDecl<'a, 'a> {
4321 arena_ast::ClassConstDecl {
4322 name: av_ident(arena, &c.name),
4323 modifiers: c.modifiers,
4324 type_hint: c
4325 .type_hint
4326 .as_ref()
4327 .map(|th| arena.alloc(av_type_hint(arena, th)) as &_),
4328 value: av_expr(arena, &c.value),
4329 attributes: av_attrs(arena, &c.attributes),
4330 doc_comment: av_opt_comment(arena, &c.doc_comment),
4331 }
4332}
4333
4334fn av_trait_use<'a>(arena: &'a bumpalo::Bump, t: &TraitUseDecl) -> arena_ast::TraitUseDecl<'a, 'a> {
4335 let mut traits = arena_ast::ArenaVec::with_capacity_in(t.traits.len(), arena);
4336 for n in t.traits.iter() {
4337 traits.push(av_name(arena, n));
4338 }
4339 let mut adaptations = arena_ast::ArenaVec::with_capacity_in(t.adaptations.len(), arena);
4340 for a in t.adaptations.iter() {
4341 adaptations.push(arena_ast::TraitAdaptation {
4342 kind: match &a.kind {
4343 TraitAdaptationKind::Precedence {
4344 trait_name,
4345 method,
4346 insteadof,
4347 } => {
4348 let mut instead = arena_ast::ArenaVec::with_capacity_in(insteadof.len(), arena);
4349 for n in insteadof.iter() {
4350 instead.push(av_name(arena, n));
4351 }
4352 arena_ast::TraitAdaptationKind::Precedence {
4353 trait_name: av_name(arena, trait_name),
4354 method: av_name(arena, method),
4355 insteadof: instead,
4356 }
4357 }
4358 TraitAdaptationKind::Alias {
4359 trait_name,
4360 method,
4361 new_modifier,
4362 is_final,
4363 invalid_modifier,
4364 new_name,
4365 } => arena_ast::TraitAdaptationKind::Alias {
4366 trait_name: trait_name.as_ref().map(|n| av_name(arena, n)),
4367 method: av_name(arena, method),
4368 new_modifier: *new_modifier,
4369 is_final: *is_final,
4370 invalid_modifier: invalid_modifier.as_ref().map(|m| av_ident(arena, m)),
4371 new_name: new_name.as_ref().map(|n| av_name(arena, n)),
4372 },
4373 },
4374 span: a.span,
4375 });
4376 }
4377 arena_ast::TraitUseDecl {
4378 traits,
4379 adaptations,
4380 adaptations_brace_span: t.adaptations_brace_span,
4381 doc_comment: av_opt_comment(arena, &t.doc_comment),
4382 }
4383}
4384
4385fn av_class_decl<'a>(arena: &'a bumpalo::Bump, cls: &ClassDecl) -> arena_ast::ClassDecl<'a, 'a> {
4386 let mut implements = arena_ast::ArenaVec::with_capacity_in(cls.implements.len(), arena);
4387 for n in cls.implements.iter() {
4388 implements.push(av_name(arena, n));
4389 }
4390 arena_ast::ClassDecl {
4391 name: cls.name.as_ref().map(|ident| av_ident(arena, ident)),
4392 modifiers: cls.modifiers.clone(),
4393 extends: cls.extends.as_ref().map(|n| av_name(arena, n)),
4394 implements,
4395 body: arena_ast::ClassBody {
4396 members: av_class_members(arena, &cls.body.members),
4397 span: cls.body.span,
4398 },
4399 attributes: av_attrs(arena, &cls.attributes),
4400 doc_comment: av_opt_comment(arena, &cls.doc_comment),
4401 }
4402}
4403
4404#[inline(never)]
4405fn av_interface_decl<'a>(
4406 arena: &'a bumpalo::Bump,
4407 iface: &InterfaceDecl,
4408) -> arena_ast::InterfaceDecl<'a, 'a> {
4409 let mut extends = arena_ast::ArenaVec::with_capacity_in(iface.extends.len(), arena);
4410 for n in iface.extends.iter() {
4411 extends.push(av_name(arena, n));
4412 }
4413 arena_ast::InterfaceDecl {
4414 name: av_ident(arena, &iface.name),
4415 extends,
4416 body: arena_ast::ClassBody {
4417 members: av_class_members(arena, &iface.body.members),
4418 span: iface.body.span,
4419 },
4420 attributes: av_attrs(arena, &iface.attributes),
4421 doc_comment: av_opt_comment(arena, &iface.doc_comment),
4422 }
4423}
4424
4425#[inline(never)]
4426fn av_trait_decl<'a>(arena: &'a bumpalo::Bump, tr: &TraitDecl) -> arena_ast::TraitDecl<'a, 'a> {
4427 arena_ast::TraitDecl {
4428 name: av_ident(arena, &tr.name),
4429 body: arena_ast::ClassBody {
4430 members: av_class_members(arena, &tr.body.members),
4431 span: tr.body.span,
4432 },
4433 attributes: av_attrs(arena, &tr.attributes),
4434 doc_comment: av_opt_comment(arena, &tr.doc_comment),
4435 }
4436}
4437
4438#[inline(never)]
4439fn av_enum_decl<'a>(arena: &'a bumpalo::Bump, en: &EnumDecl) -> arena_ast::EnumDecl<'a, 'a> {
4440 let mut implements = arena_ast::ArenaVec::with_capacity_in(en.implements.len(), arena);
4441 for n in en.implements.iter() {
4442 implements.push(av_name(arena, n));
4443 }
4444 let mut members = arena_ast::ArenaVec::with_capacity_in(en.body.members.len(), arena);
4445 for m in en.body.members.iter() {
4446 members.push(arena_ast::EnumMember {
4447 kind: match &m.kind {
4448 EnumMemberKind::Case(c) => arena_ast::EnumMemberKind::Case(arena_ast::EnumCase {
4449 name: av_ident(arena, &c.name),
4450 value: c.value.as_ref().map(|e| av_expr(arena, e)),
4451 attributes: av_attrs(arena, &c.attributes),
4452 doc_comment: av_opt_comment(arena, &c.doc_comment),
4453 }),
4454 EnumMemberKind::Method(m) => {
4455 arena_ast::EnumMemberKind::Method(arena_ast::MethodDecl {
4456 name: av_ident(arena, &m.name),
4457 modifiers: m.modifiers,
4458 by_ref: m.by_ref,
4459 params: av_params(arena, &m.params),
4460 missing_param_list: m.missing_param_list,
4461 return_type: m.return_type.as_ref().map(|t| av_type_hint(arena, t)),
4462 body: m.body.as_deref().map(|b| &*arena.alloc(av_block(arena, b))),
4463 attributes: av_attrs(arena, &m.attributes),
4464 doc_comment: av_opt_comment(arena, &m.doc_comment),
4465 })
4466 }
4467 EnumMemberKind::ClassConst(c) => {
4468 arena_ast::EnumMemberKind::ClassConst(av_class_const(arena, c))
4469 }
4470 EnumMemberKind::TraitUse(t) => {
4471 arena_ast::EnumMemberKind::TraitUse(av_trait_use(arena, t))
4472 }
4473 EnumMemberKind::Property(p) => {
4474 arena_ast::EnumMemberKind::Property(av_property(arena, p))
4475 }
4476 },
4477 span: m.span,
4478 });
4479 }
4480 arena_ast::EnumDecl {
4481 name: av_ident(arena, &en.name),
4482 scalar_type: en.scalar_type.as_ref().map(|n| av_name(arena, n)),
4483 implements,
4484 body: arena_ast::EnumBody {
4485 members,
4486 span: en.body.span,
4487 },
4488 attributes: av_attrs(arena, &en.attributes),
4489 doc_comment: av_opt_comment(arena, &en.doc_comment),
4490 }
4491}