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 pub value: Expr,
709 #[cfg_attr(feature = "serde", serde(default, skip_serializing_if = "is_false"))]
711 pub by_ref: bool,
712 #[cfg_attr(
714 feature = "serde",
715 serde(default, skip_serializing_if = "Option::is_none")
716 )]
717 pub by_ref_span: Option<Span>,
718 pub body: Box<Stmt>,
720 #[cfg_attr(feature = "serde", serde(default, skip_serializing_if = "is_false"))]
722 pub uses_alternative: bool,
723}
724
725impl ForeachStmt {
726 pub fn new(expr: Expr, value: Expr, body: Box<Stmt>) -> Self {
729 Self {
730 expr,
731 key: None,
732 value,
733 by_ref: false,
734 by_ref_span: None,
735 body,
736 uses_alternative: false,
737 }
738 }
739}
740
741#[derive(Debug, Clone)]
743#[cfg_attr(feature = "serde", derive(Serialize))]
744#[non_exhaustive]
745pub struct DoWhileStmt {
746 pub body: Box<Stmt>,
748 pub condition: Expr,
750}
751
752impl DoWhileStmt {
753 pub fn new(body: Box<Stmt>, condition: Expr) -> Self {
756 Self { body, condition }
757 }
758}
759
760#[derive(Debug, Clone)]
762#[cfg_attr(feature = "serde", derive(Serialize))]
763pub struct SwitchBody {
764 pub cases: Box<[SwitchCase]>,
766 #[cfg_attr(feature = "serde", serde(skip))]
768 pub span: Span,
769}
770
771#[derive(Debug, Clone)]
773#[cfg_attr(feature = "serde", derive(Serialize))]
774#[non_exhaustive]
775pub struct SwitchStmt {
776 pub expr: Expr,
778 #[cfg_attr(feature = "serde", serde(flatten))]
780 pub body: SwitchBody,
781 #[cfg_attr(feature = "serde", serde(default, skip_serializing_if = "is_false"))]
783 pub uses_alternative: bool,
784}
785
786impl SwitchStmt {
787 pub fn new(expr: Expr, body: SwitchBody) -> Self {
790 Self {
791 expr,
792 body,
793 uses_alternative: false,
794 }
795 }
796}
797
798#[derive(Debug, Clone)]
800#[cfg_attr(feature = "serde", derive(Serialize))]
801pub struct SwitchCase {
802 pub value: Option<Expr>,
804 pub body: Box<[Stmt]>,
806 pub span: Span,
808}
809
810#[derive(Debug, Clone)]
812#[cfg_attr(feature = "serde", derive(Serialize))]
813#[non_exhaustive]
814pub struct TryCatchStmt {
815 pub body: Box<Block>,
817 pub catches: Box<[CatchClause]>,
819 pub finally: Option<Box<Block>>,
821 #[cfg_attr(feature = "serde", serde(skip))]
823 #[doc(hidden)]
824 pub finally_kw_span: Option<Span>,
825}
826
827impl TryCatchStmt {
828 pub fn new(body: Box<Block>) -> Self {
831 Self {
832 body,
833 catches: Box::new([]),
834 finally: None,
835 finally_kw_span: None,
836 }
837 }
838}
839
840#[derive(Debug, Clone)]
842#[cfg_attr(feature = "serde", derive(Serialize))]
843#[non_exhaustive]
844pub struct CatchClause {
845 pub types: Box<[Name]>,
847 pub var: Option<Ident>,
849 pub body: Box<Block>,
851 pub span: Span,
853}
854
855impl CatchClause {
856 pub fn new(body: Box<Block>, span: Span) -> Self {
859 Self {
860 types: Box::new([]),
861 var: None,
862 body,
863 span,
864 }
865 }
866}
867
868#[derive(Debug, Clone)]
870#[cfg_attr(feature = "serde", derive(Serialize))]
871#[non_exhaustive]
872pub struct NamespaceDecl {
873 pub name: Option<Name>,
875 pub body: NamespaceBody,
877}
878
879impl NamespaceDecl {
880 pub fn new(name: Option<Name>, body: NamespaceBody) -> Self {
883 Self { name, body }
884 }
885}
886
887#[derive(Debug, Clone)]
889#[cfg_attr(feature = "serde", derive(Serialize))]
890#[non_exhaustive]
891pub enum NamespaceBody {
892 Braced(Box<Block>),
894 Simple,
896}
897
898#[derive(Debug, Clone)]
900#[cfg_attr(feature = "serde", derive(Serialize))]
901#[non_exhaustive]
902pub struct DeclareStmt {
903 pub directives: Box<[(Box<str>, Expr)]>,
905 pub body: Option<Box<Stmt>>,
907 #[cfg_attr(feature = "serde", serde(default, skip_serializing_if = "is_false"))]
909 pub uses_alternative: bool,
910}
911
912impl DeclareStmt {
913 pub fn new(directives: Box<[(Box<str>, Expr)]>) -> Self {
916 Self {
917 directives,
918 body: None,
919 uses_alternative: false,
920 }
921 }
922}
923
924#[derive(Debug, Clone)]
926#[cfg_attr(feature = "serde", derive(Serialize))]
927#[non_exhaustive]
928pub struct UseDecl {
929 pub kind: UseKind,
931 pub uses: Box<[UseItem]>,
933}
934
935impl UseDecl {
936 pub fn new(kind: UseKind, uses: Box<[UseItem]>) -> Self {
939 Self { kind, uses }
940 }
941}
942
943#[derive(Debug, Clone)]
945#[cfg_attr(feature = "serde", derive(Serialize))]
946pub struct UseItem {
947 pub name: Name,
949 pub alias: Option<Ident>,
951 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
953 pub kind: Option<UseKind>,
954 pub span: Span,
956}
957
958#[derive(Debug, Clone)]
960#[cfg_attr(feature = "serde", derive(Serialize))]
961pub struct ConstItem {
962 pub name: Ident,
964 pub value: Expr,
966 pub attributes: Box<[Attribute]>,
968 pub span: Span,
970 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
972 pub doc_comment: Option<Comment>,
973}
974
975#[derive(Debug, Clone)]
977#[cfg_attr(feature = "serde", derive(Serialize))]
978pub struct StaticVar {
979 pub name: Ident,
981 pub default: Option<Expr>,
983 pub span: Span,
985}
986
987#[derive(Debug, Clone)]
997#[cfg_attr(feature = "serde", derive(Serialize))]
998pub struct Expr {
999 pub kind: ExprKind,
1001 pub span: Span,
1003}
1004
1005impl Expr {
1006 pub fn name_str(&self) -> Option<&str> {
1008 match &self.kind {
1009 ExprKind::Variable(s) | ExprKind::Identifier(s) => Some(s),
1010 _ => None,
1011 }
1012 }
1013
1014 pub fn into_kind(mut self) -> ExprKind {
1016 std::mem::replace(&mut self.kind, ExprKind::Error)
1017 }
1018}
1019
1020#[derive(Debug, Clone)]
1022#[cfg_attr(feature = "serde", derive(Serialize))]
1023#[non_exhaustive]
1024pub enum ExprKind {
1025 Int(i64),
1027 Float(f64),
1029 String(ByteString),
1031 InterpolatedString(Box<[StringPart]>),
1033 Heredoc {
1035 label: Box<str>,
1037 parts: Box<[StringPart]>,
1039 },
1040 Nowdoc {
1042 label: Box<str>,
1044 value: Box<str>,
1046 },
1047 ShellExec(Box<[StringPart]>),
1049 Bool(bool),
1051 Null,
1053 Variable(Box<str>),
1055 VariableVariable(Box<Expr>),
1057 Identifier(Box<str>),
1059 Name(Name),
1061 Assign(AssignExpr),
1063 Binary(BinaryExpr),
1065 UnaryPrefix(UnaryPrefixExpr),
1067 UnaryPostfix(UnaryPostfixExpr),
1069 Ternary(TernaryExpr),
1071 NullCoalesce(NullCoalesceExpr),
1073 FunctionCall(FunctionCallExpr),
1075 Array(Box<[ArrayElement]>),
1077 ArrayAccess(ArrayAccessExpr),
1079 Print(Box<Expr>),
1081 Parenthesized(Box<Expr>),
1083 Cast(CastKind, Box<Expr>),
1085 ErrorSuppress(Box<Expr>),
1087 Isset(Box<[Expr]>),
1089 Empty(Box<Expr>),
1091 Include(IncludeKind, Box<Expr>),
1093 Eval(Box<Expr>),
1095 Exit(Option<Box<Expr>>),
1097 MagicConst(MagicConstKind),
1099 Clone(Box<Expr>),
1101 CloneWith(Box<Expr>, Box<Expr>),
1103 New(NewExpr),
1105 PropertyAccess(PropertyAccessExpr),
1107 NullsafePropertyAccess(PropertyAccessExpr),
1109 MethodCall(Box<MethodCallExpr>),
1111 NullsafeMethodCall(Box<MethodCallExpr>),
1113 StaticPropertyAccess(StaticAccessExpr),
1115 StaticMethodCall(Box<StaticMethodCallExpr>),
1117 StaticMethodCallDynamic(Box<StaticMethodCallDynamicExpr>),
1119 ClassConstAccess(StaticAccessExpr),
1121 ClassConstAccessDynamic {
1123 class: Box<Expr>,
1125 member: Box<Expr>,
1127 },
1128 StaticPropertyAccessDynamic {
1130 class: Box<Expr>,
1132 member: Box<Expr>,
1134 },
1135 Closure(Box<ClosureExpr>),
1137 ArrowFunction(Box<ArrowFunctionExpr>),
1139 Match(MatchExpr),
1141 Throw(Box<Expr>),
1143 Yield(YieldExpr),
1145 AnonymousClass(Box<ClassDecl>),
1147 CallableCreate(CallableCreateExpr),
1149 Omit,
1151 Error,
1153}
1154
1155impl Drop for Expr {
1169 #[inline(always)]
1170 fn drop(&mut self) {
1171 if owned_is_chain(&self.kind) {
1173 unlink_chain(&mut self.kind);
1174 }
1175 }
1176}
1177
1178#[inline(never)]
1180fn unlink_chain(kind: &mut ExprKind) {
1181 let Some(operand) = owned_chain_operand_mut(kind) else {
1182 return;
1183 };
1184 if !owned_is_chain(&operand.kind) {
1186 return;
1187 }
1188 let mut kind = std::mem::replace(&mut operand.kind, ExprKind::Error);
1191 while let Some(operand) = owned_chain_operand_mut(&mut kind) {
1192 let next = std::mem::replace(&mut operand.kind, ExprKind::Error);
1193 kind = next;
1194 }
1195}
1196
1197struct LinkStack<T: Copy> {
1200 inline: [Option<T>; 8],
1201 len: usize,
1202 spilled: Vec<T>,
1203}
1204
1205impl<T: Copy> LinkStack<T> {
1206 fn new() -> Self {
1207 Self {
1208 inline: [None; 8],
1209 len: 0,
1210 spilled: Vec::new(),
1211 }
1212 }
1213
1214 fn push(&mut self, link: T) {
1215 if self.len < self.inline.len() {
1216 self.inline[self.len] = Some(link);
1217 self.len += 1;
1218 } else {
1219 self.spilled.push(link);
1220 }
1221 }
1222
1223 fn pop(&mut self) -> Option<T> {
1224 if let Some(link) = self.spilled.pop() {
1225 return Some(link);
1226 }
1227 self.len = self.len.checked_sub(1)?;
1228 self.inline[self.len]
1229 }
1230}
1231
1232#[inline]
1235fn arena_is_chain(k: &arena_ast::ExprKind<'_, '_>) -> bool {
1236 matches!(
1237 k,
1238 arena_ast::ExprKind::Assign(_)
1239 | arena_ast::ExprKind::Binary(_)
1240 | arena_ast::ExprKind::UnaryPrefix(_)
1241 | arena_ast::ExprKind::UnaryPostfix(_)
1242 | arena_ast::ExprKind::Ternary(_)
1243 | arena_ast::ExprKind::NullCoalesce(_)
1244 | arena_ast::ExprKind::FunctionCall(_)
1245 | arena_ast::ExprKind::ArrayAccess(_)
1246 | arena_ast::ExprKind::PropertyAccess(_)
1247 | arena_ast::ExprKind::NullsafePropertyAccess(_)
1248 | arena_ast::ExprKind::MethodCall(_)
1249 | arena_ast::ExprKind::NullsafeMethodCall(_)
1250 | arena_ast::ExprKind::StaticPropertyAccess(_)
1251 | arena_ast::ExprKind::ClassConstAccess(_)
1252 | arena_ast::ExprKind::StaticMethodCall(_)
1253 | arena_ast::ExprKind::StaticMethodCallDynamic(_)
1254 | arena_ast::ExprKind::ClassConstAccessDynamic { .. }
1255 | arena_ast::ExprKind::StaticPropertyAccessDynamic { .. }
1256 | arena_ast::ExprKind::CallableCreate(_)
1257 )
1258}
1259
1260#[inline]
1262fn owned_is_chain(k: &ExprKind) -> bool {
1263 matches!(
1264 k,
1265 ExprKind::Assign(_)
1266 | ExprKind::Binary(_)
1267 | ExprKind::UnaryPrefix(_)
1268 | ExprKind::UnaryPostfix(_)
1269 | ExprKind::Ternary(_)
1270 | ExprKind::NullCoalesce(_)
1271 | ExprKind::FunctionCall(_)
1272 | ExprKind::ArrayAccess(_)
1273 | ExprKind::PropertyAccess(_)
1274 | ExprKind::NullsafePropertyAccess(_)
1275 | ExprKind::MethodCall(_)
1276 | ExprKind::NullsafeMethodCall(_)
1277 | ExprKind::StaticPropertyAccess(_)
1278 | ExprKind::ClassConstAccess(_)
1279 | ExprKind::StaticMethodCall(_)
1280 | ExprKind::StaticMethodCallDynamic(_)
1281 | ExprKind::ClassConstAccessDynamic { .. }
1282 | ExprKind::StaticPropertyAccessDynamic { .. }
1283 | ExprKind::CallableCreate(_)
1284 )
1285}
1286
1287#[inline]
1288fn arena_chain_operand<'a, 'arena, 'src>(
1289 k: &'a arena_ast::ExprKind<'arena, 'src>,
1290) -> Option<&'a arena_ast::Expr<'arena, 'src>> {
1291 use arena_ast::{CallableCreateKind as C, ExprKind as K};
1292 match k {
1293 K::Assign(a) => Some(a.target),
1294 K::Binary(b) => Some(b.left),
1295 K::UnaryPrefix(u) => Some(u.operand),
1296 K::UnaryPostfix(u) => Some(u.operand),
1297 K::Ternary(t) => Some(t.condition),
1298 K::NullCoalesce(n) => Some(n.left),
1299 K::FunctionCall(f) => Some(f.name),
1300 K::ArrayAccess(a) => Some(a.array),
1301 K::PropertyAccess(p) | K::NullsafePropertyAccess(p) => Some(p.object),
1302 K::MethodCall(m) | K::NullsafeMethodCall(m) => Some(m.object),
1303 K::StaticPropertyAccess(s) | K::ClassConstAccess(s) => Some(s.class),
1304 K::StaticMethodCall(s) => Some(s.class),
1305 K::StaticMethodCallDynamic(s) => Some(s.class),
1306 K::ClassConstAccessDynamic { class, .. } | K::StaticPropertyAccessDynamic { class, .. } => {
1307 Some(class)
1308 }
1309 K::CallableCreate(c) => Some(match &c.kind {
1310 C::Function(e) => e,
1311 C::Method { object, .. } | C::NullsafeMethod { object, .. } => object,
1312 C::StaticMethod { class, .. } => class,
1313 }),
1314 _ => None,
1315 }
1316}
1317
1318#[inline]
1319fn owned_chain_operand(k: &ExprKind) -> Option<&Expr> {
1320 use CallableCreateKind as C;
1321 match k {
1322 ExprKind::Assign(a) => Some(&a.target),
1323 ExprKind::Binary(b) => Some(&b.left),
1324 ExprKind::UnaryPrefix(u) => Some(&u.operand),
1325 ExprKind::UnaryPostfix(u) => Some(&u.operand),
1326 ExprKind::Ternary(t) => Some(&t.condition),
1327 ExprKind::NullCoalesce(n) => Some(&n.left),
1328 ExprKind::FunctionCall(f) => Some(&f.name),
1329 ExprKind::ArrayAccess(a) => Some(&a.array),
1330 ExprKind::PropertyAccess(p) | ExprKind::NullsafePropertyAccess(p) => Some(&p.object),
1331 ExprKind::MethodCall(m) | ExprKind::NullsafeMethodCall(m) => Some(&m.object),
1332 ExprKind::StaticPropertyAccess(s) | ExprKind::ClassConstAccess(s) => Some(&s.class),
1333 ExprKind::StaticMethodCall(s) => Some(&s.class),
1334 ExprKind::StaticMethodCallDynamic(s) => Some(&s.class),
1335 ExprKind::ClassConstAccessDynamic { class, .. }
1336 | ExprKind::StaticPropertyAccessDynamic { class, .. } => Some(class),
1337 ExprKind::CallableCreate(c) => Some(match &c.kind {
1338 C::Function(e) => e,
1339 C::Method { object, .. } | C::NullsafeMethod { object, .. } => object,
1340 C::StaticMethod { class, .. } => class,
1341 }),
1342 _ => None,
1343 }
1344}
1345
1346#[inline]
1347fn owned_chain_operand_mut(k: &mut ExprKind) -> Option<&mut Expr> {
1348 use CallableCreateKind as C;
1349 match k {
1350 ExprKind::Assign(a) => Some(&mut a.target),
1351 ExprKind::Binary(b) => Some(&mut b.left),
1352 ExprKind::UnaryPrefix(u) => Some(&mut u.operand),
1353 ExprKind::UnaryPostfix(u) => Some(&mut u.operand),
1354 ExprKind::Ternary(t) => Some(&mut t.condition),
1355 ExprKind::NullCoalesce(n) => Some(&mut n.left),
1356 ExprKind::FunctionCall(f) => Some(&mut f.name),
1357 ExprKind::ArrayAccess(a) => Some(&mut a.array),
1358 ExprKind::PropertyAccess(p) | ExprKind::NullsafePropertyAccess(p) => Some(&mut p.object),
1359 ExprKind::MethodCall(m) | ExprKind::NullsafeMethodCall(m) => Some(&mut m.object),
1360 ExprKind::StaticPropertyAccess(s) | ExprKind::ClassConstAccess(s) => Some(&mut s.class),
1361 ExprKind::StaticMethodCall(s) => Some(&mut s.class),
1362 ExprKind::StaticMethodCallDynamic(s) => Some(&mut s.class),
1363 ExprKind::ClassConstAccessDynamic { class, .. }
1364 | ExprKind::StaticPropertyAccessDynamic { class, .. } => Some(class),
1365 ExprKind::CallableCreate(c) => Some(match &mut c.kind {
1366 C::Function(e) => e,
1367 C::Method { object, .. } | C::NullsafeMethod { object, .. } => object,
1368 C::StaticMethod { class, .. } => class,
1369 }),
1370 _ => None,
1371 }
1372}
1373
1374#[derive(Debug, Clone)]
1376#[cfg_attr(feature = "serde", derive(Serialize))]
1377pub struct AssignExpr {
1378 pub target: Box<Expr>,
1380 pub op: AssignOp,
1382 pub value: Box<Expr>,
1384 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "is_false"))]
1386 pub by_ref: bool,
1387}
1388
1389#[derive(Debug, Clone)]
1391#[cfg_attr(feature = "serde", derive(Serialize))]
1392pub struct BinaryExpr {
1393 pub left: Box<Expr>,
1395 pub op: BinaryOp,
1397 pub right: Box<Expr>,
1399}
1400
1401#[derive(Debug, Clone)]
1403#[cfg_attr(feature = "serde", derive(Serialize))]
1404pub struct UnaryPrefixExpr {
1405 pub op: UnaryPrefixOp,
1407 pub operand: Box<Expr>,
1409}
1410
1411#[derive(Debug, Clone)]
1413#[cfg_attr(feature = "serde", derive(Serialize))]
1414pub struct UnaryPostfixExpr {
1415 pub operand: Box<Expr>,
1417 pub op: UnaryPostfixOp,
1419}
1420
1421#[derive(Debug, Clone)]
1423#[cfg_attr(feature = "serde", derive(Serialize))]
1424pub struct TernaryExpr {
1425 pub condition: Box<Expr>,
1427 pub then_expr: Option<Box<Expr>>,
1429 pub else_expr: Box<Expr>,
1431}
1432
1433#[derive(Debug, Clone)]
1435#[cfg_attr(feature = "serde", derive(Serialize))]
1436pub struct NullCoalesceExpr {
1437 pub left: Box<Expr>,
1439 pub right: Box<Expr>,
1441}
1442
1443#[derive(Debug, Clone)]
1445#[cfg_attr(feature = "serde", derive(Serialize))]
1446pub struct FunctionCallExpr {
1447 pub name: Box<Expr>,
1449 pub args: Box<[Arg]>,
1451}
1452
1453#[derive(Debug, Clone)]
1455#[cfg_attr(feature = "serde", derive(Serialize))]
1456pub struct ArrayElement {
1457 pub key: Option<Expr>,
1459 pub kind: ArrayElementKind,
1461 pub span: Span,
1463}
1464
1465#[derive(Debug, Clone)]
1467#[cfg_attr(feature = "serde", derive(Serialize))]
1468#[non_exhaustive]
1469pub enum ArrayElementKind {
1470 Value(Expr),
1472 Spread(Expr),
1474 ByRef(Expr),
1476}
1477
1478impl ArrayElement {
1479 pub fn value(&self) -> &Expr {
1481 match &self.kind {
1482 ArrayElementKind::Value(e)
1483 | ArrayElementKind::Spread(e)
1484 | ArrayElementKind::ByRef(e) => e,
1485 }
1486 }
1487
1488 pub fn value_mut(&mut self) -> &mut Expr {
1490 match &mut self.kind {
1491 ArrayElementKind::Value(e)
1492 | ArrayElementKind::Spread(e)
1493 | ArrayElementKind::ByRef(e) => e,
1494 }
1495 }
1496
1497 pub fn is_spread(&self) -> bool {
1499 matches!(self.kind, ArrayElementKind::Spread(_))
1500 }
1501
1502 pub fn is_by_ref(&self) -> bool {
1504 matches!(self.kind, ArrayElementKind::ByRef(_))
1505 }
1506}
1507
1508#[derive(Debug, Clone)]
1510#[cfg_attr(feature = "serde", derive(Serialize))]
1511pub struct ArrayAccessExpr {
1512 pub array: Box<Expr>,
1514 pub index: Option<Box<Expr>>,
1516}
1517
1518#[derive(Debug, Clone)]
1520#[cfg_attr(feature = "serde", derive(Serialize))]
1521pub struct NewExpr {
1522 pub class: Box<Expr>,
1524 pub args: Box<[Arg]>,
1526}
1527
1528#[derive(Debug, Clone)]
1530#[cfg_attr(feature = "serde", derive(Serialize))]
1531pub struct PropertyAccessExpr {
1532 pub object: Box<Expr>,
1534 pub property: Box<Expr>,
1536}
1537
1538#[derive(Debug, Clone)]
1540#[cfg_attr(feature = "serde", derive(Serialize))]
1541pub struct MethodCallExpr {
1542 pub object: Box<Expr>,
1544 pub method: Box<Expr>,
1546 pub args: Box<[Arg]>,
1548}
1549
1550#[derive(Debug, Clone)]
1552#[cfg_attr(feature = "serde", derive(Serialize))]
1553pub struct StaticAccessExpr {
1554 pub class: Box<Expr>,
1556 pub member: Box<Expr>,
1558}
1559
1560#[derive(Debug, Clone)]
1562#[cfg_attr(feature = "serde", derive(Serialize))]
1563pub struct StaticMethodCallExpr {
1564 pub class: Box<Expr>,
1566 pub method: Box<Expr>,
1568 pub args: Box<[Arg]>,
1570}
1571
1572#[derive(Debug, Clone)]
1574#[cfg_attr(feature = "serde", derive(Serialize))]
1575pub struct StaticMethodCallDynamicExpr {
1576 pub class: Box<Expr>,
1578 pub method: Box<Expr>,
1580 pub args: Box<[Arg]>,
1582}
1583
1584#[derive(Debug, Clone)]
1586#[cfg_attr(feature = "serde", derive(Serialize))]
1587#[non_exhaustive]
1588pub struct ClosureExpr {
1589 pub is_static: bool,
1591 pub by_ref: bool,
1593 pub params: Box<[Param]>,
1595 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "is_false"))]
1597 pub missing_param_list: bool,
1598 pub use_vars: Box<[ClosureUseVar]>,
1600 pub return_type: Option<TypeHint>,
1602 pub body: Box<Block>,
1604 pub attributes: Box<[Attribute]>,
1606}
1607
1608impl ClosureExpr {
1609 pub fn new(body: Box<Block>) -> Self {
1612 Self {
1613 is_static: false,
1614 by_ref: false,
1615 params: Box::new([]),
1616 missing_param_list: false,
1617 use_vars: Box::new([]),
1618 return_type: None,
1619 body,
1620 attributes: Box::new([]),
1621 }
1622 }
1623}
1624
1625#[derive(Debug, Clone)]
1627#[cfg_attr(feature = "serde", derive(Serialize))]
1628pub struct ClosureUseVar {
1629 pub name: Ident,
1631 pub by_ref: bool,
1633 pub span: Span,
1635}
1636
1637#[derive(Debug, Clone)]
1639#[cfg_attr(feature = "serde", derive(Serialize))]
1640#[non_exhaustive]
1641pub struct ArrowFunctionExpr {
1642 pub is_static: bool,
1644 pub by_ref: bool,
1646 pub params: Box<[Param]>,
1648 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "is_false"))]
1650 pub missing_param_list: bool,
1651 pub return_type: Option<TypeHint>,
1653 pub body: Box<Expr>,
1655 pub attributes: Box<[Attribute]>,
1657}
1658
1659impl ArrowFunctionExpr {
1660 pub fn new(body: Box<Expr>) -> Self {
1663 Self {
1664 is_static: false,
1665 by_ref: false,
1666 params: Box::new([]),
1667 missing_param_list: false,
1668 return_type: None,
1669 body,
1670 attributes: Box::new([]),
1671 }
1672 }
1673}
1674
1675#[derive(Debug, Clone)]
1677#[cfg_attr(feature = "serde", derive(Serialize))]
1678#[non_exhaustive]
1679pub struct MatchExpr {
1680 pub subject: Box<Expr>,
1682 pub arms: Box<[MatchArm]>,
1684 #[cfg_attr(feature = "serde", serde(skip))]
1686 #[doc(hidden)]
1687 pub brace_span: Span,
1688}
1689
1690impl MatchExpr {
1691 pub fn new(subject: Box<Expr>, arms: Box<[MatchArm]>, brace_span: Span) -> Self {
1694 Self {
1695 subject,
1696 arms,
1697 brace_span,
1698 }
1699 }
1700}
1701
1702#[derive(Debug, Clone)]
1704#[cfg_attr(feature = "serde", derive(Serialize))]
1705pub struct MatchArm {
1706 pub conditions: Option<Box<[Expr]>>,
1708 pub body: Expr,
1710 pub span: Span,
1712}
1713
1714#[derive(Debug, Clone)]
1716#[cfg_attr(feature = "serde", derive(Serialize))]
1717pub struct YieldExpr {
1718 pub key: Option<Box<Expr>>,
1720 pub value: Option<Box<Expr>>,
1722 pub is_from: bool,
1724}
1725
1726#[derive(Debug, Clone)]
1728#[cfg_attr(feature = "serde", derive(Serialize))]
1729pub struct CallableCreateExpr {
1730 pub kind: CallableCreateKind,
1732}
1733
1734#[derive(Debug, Clone)]
1736#[cfg_attr(feature = "serde", derive(Serialize))]
1737#[non_exhaustive]
1738pub enum CallableCreateKind {
1739 Function(Box<Expr>),
1741 Method {
1743 object: Box<Expr>,
1745 method: Box<Expr>,
1747 },
1748 NullsafeMethod {
1750 object: Box<Expr>,
1752 method: Box<Expr>,
1754 },
1755 StaticMethod {
1757 class: Box<Expr>,
1759 method: Box<Expr>,
1761 },
1762}
1763
1764#[derive(Debug, Clone)]
1766#[cfg_attr(feature = "serde", derive(Serialize))]
1767#[non_exhaustive]
1768pub enum StringPart {
1769 Literal(ByteString),
1771 Expr(Expr),
1773}
1774
1775#[derive(Debug, Clone)]
1781#[cfg_attr(feature = "serde", derive(Serialize))]
1782#[non_exhaustive]
1783pub struct FunctionDecl {
1784 pub name: Ident,
1786 pub params: Box<[Param]>,
1788 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "is_false"))]
1790 pub missing_param_list: bool,
1791 pub body: Box<Block>,
1793 pub return_type: Option<TypeHint>,
1795 pub by_ref: bool,
1797 pub attributes: Box<[Attribute]>,
1799 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
1801 pub doc_comment: Option<Comment>,
1802}
1803
1804impl FunctionDecl {
1805 pub fn new(name: Ident, body: Box<Block>) -> Self {
1808 Self {
1809 name,
1810 params: Box::new([]),
1811 missing_param_list: false,
1812 body,
1813 return_type: None,
1814 by_ref: false,
1815 attributes: Box::new([]),
1816 doc_comment: None,
1817 }
1818 }
1819}
1820
1821#[derive(Debug, Clone)]
1823#[cfg_attr(feature = "serde", derive(Serialize))]
1824#[non_exhaustive]
1825pub struct Param {
1826 pub name: Ident,
1828 pub type_hint: Option<TypeHint>,
1830 pub default: Option<Expr>,
1832 pub by_ref: bool,
1834 pub variadic: bool,
1836 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Modifiers::is_empty"))]
1838 pub modifiers: Modifiers,
1839 pub attributes: Box<[Attribute]>,
1841 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "slice_is_empty"))]
1843 pub hooks: Box<[PropertyHook]>,
1844 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "is_false"))]
1846 pub empty_hook_list: bool,
1847 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
1849 pub doc_comment: Option<Comment>,
1850 pub span: Span,
1852}
1853
1854impl Param {
1855 pub fn new(name: Ident, span: Span) -> Self {
1860 Self {
1861 name,
1862 type_hint: None,
1863 default: None,
1864 by_ref: false,
1865 variadic: false,
1866 modifiers: Modifiers::new(),
1867 attributes: Box::new([]),
1868 hooks: Box::new([]),
1869 empty_hook_list: false,
1870 doc_comment: None,
1871 span,
1872 }
1873 }
1874}
1875
1876#[derive(Debug, Clone)]
1878#[cfg_attr(feature = "serde", derive(Serialize))]
1879pub struct ClassBody {
1880 pub members: Box<[ClassMember]>,
1882 #[cfg_attr(feature = "serde", serde(skip))]
1884 pub span: Span,
1885}
1886
1887#[derive(Debug, Clone)]
1889#[cfg_attr(feature = "serde", derive(Serialize))]
1890#[non_exhaustive]
1891pub struct ClassDecl {
1892 pub name: Option<Ident>,
1894 pub modifiers: ClassModifiers,
1896 pub extends: Option<Name>,
1898 pub implements: Box<[Name]>,
1900 #[cfg_attr(feature = "serde", serde(flatten))]
1902 pub body: ClassBody,
1903 pub attributes: Box<[Attribute]>,
1905 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
1907 pub doc_comment: Option<Comment>,
1908}
1909
1910impl ClassDecl {
1911 pub fn new(name: Option<Ident>, body: ClassBody) -> Self {
1914 Self {
1915 name,
1916 modifiers: ClassModifiers::default(),
1917 extends: None,
1918 implements: Box::new([]),
1919 body,
1920 attributes: Box::new([]),
1921 doc_comment: None,
1922 }
1923 }
1924}
1925
1926#[derive(Debug, Clone)]
1928#[cfg_attr(feature = "serde", derive(Serialize))]
1929pub struct ClassMember {
1930 pub kind: ClassMemberKind,
1932 pub span: Span,
1934}
1935
1936#[derive(Debug, Clone)]
1938#[cfg_attr(feature = "serde", derive(Serialize))]
1939#[non_exhaustive]
1940pub enum ClassMemberKind {
1941 Property(PropertyDecl),
1943 Method(MethodDecl),
1945 ClassConst(ClassConstDecl),
1947 TraitUse(TraitUseDecl),
1949}
1950
1951#[derive(Debug, Clone)]
1953#[cfg_attr(feature = "serde", derive(Serialize))]
1954#[non_exhaustive]
1955pub struct PropertyDecl {
1956 pub name: Ident,
1958 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Modifiers::is_empty"))]
1960 pub modifiers: Modifiers,
1961 pub type_hint: Option<TypeHint>,
1963 pub default: Option<Expr>,
1965 pub attributes: Box<[Attribute]>,
1967 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "slice_is_empty"))]
1969 pub hooks: Box<[PropertyHook]>,
1970 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "is_false"))]
1972 pub empty_hook_list: bool,
1973 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
1975 pub doc_comment: Option<Comment>,
1976}
1977
1978impl PropertyDecl {
1979 pub fn new(name: Ident) -> Self {
1982 Self {
1983 name,
1984 modifiers: Modifiers::new(),
1985 type_hint: None,
1986 default: None,
1987 attributes: Box::new([]),
1988 hooks: Box::new([]),
1989 empty_hook_list: false,
1990 doc_comment: None,
1991 }
1992 }
1993}
1994
1995#[derive(Debug, Clone)]
1997#[cfg_attr(feature = "serde", derive(Serialize))]
1998#[non_exhaustive]
1999pub struct PropertyHook {
2000 pub kind: PropertyHookKind,
2002 pub body: PropertyHookBody,
2004 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Modifiers::is_empty"))]
2006 pub modifiers: Modifiers,
2007 pub by_ref: bool,
2009 pub params: Box<[Param]>,
2011 pub attributes: Box<[Attribute]>,
2013 pub span: Span,
2015}
2016
2017impl PropertyHook {
2018 pub fn new(kind: PropertyHookKind, body: PropertyHookBody, span: Span) -> Self {
2021 Self {
2022 kind,
2023 body,
2024 modifiers: Modifiers::new(),
2025 by_ref: false,
2026 params: Box::new([]),
2027 attributes: Box::new([]),
2028 span,
2029 }
2030 }
2031}
2032
2033#[derive(Debug, Clone)]
2035#[cfg_attr(feature = "serde", derive(Serialize))]
2036#[non_exhaustive]
2037pub enum PropertyHookBody {
2038 Block(Box<Block>),
2040 Expression(Expr),
2042 Abstract,
2044}
2045
2046#[derive(Debug, Clone)]
2048#[cfg_attr(feature = "serde", derive(Serialize))]
2049#[non_exhaustive]
2050pub struct MethodDecl {
2051 pub name: Ident,
2053 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Modifiers::is_empty"))]
2055 pub modifiers: Modifiers,
2056 pub by_ref: bool,
2058 pub params: Box<[Param]>,
2060 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "is_false"))]
2062 pub missing_param_list: bool,
2063 pub return_type: Option<TypeHint>,
2065 pub body: Option<Box<Block>>,
2067 pub attributes: Box<[Attribute]>,
2069 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
2071 pub doc_comment: Option<Comment>,
2072}
2073
2074impl MethodDecl {
2075 pub fn new(name: Ident) -> Self {
2078 Self {
2079 name,
2080 modifiers: Modifiers::new(),
2081 by_ref: false,
2082 params: Box::new([]),
2083 missing_param_list: false,
2084 return_type: None,
2085 body: None,
2086 attributes: Box::new([]),
2087 doc_comment: None,
2088 }
2089 }
2090}
2091
2092#[derive(Debug, Clone)]
2094#[cfg_attr(feature = "serde", derive(Serialize))]
2095#[non_exhaustive]
2096pub struct ClassConstDecl {
2097 pub name: Ident,
2099 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Modifiers::is_empty"))]
2101 pub modifiers: Modifiers,
2102 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
2104 pub type_hint: Option<Box<TypeHint>>,
2105 pub value: Expr,
2107 pub attributes: Box<[Attribute]>,
2109 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
2111 pub doc_comment: Option<Comment>,
2112}
2113
2114impl ClassConstDecl {
2115 pub fn new(name: Ident, value: Expr) -> Self {
2118 Self {
2119 name,
2120 modifiers: Modifiers::new(),
2121 type_hint: None,
2122 value,
2123 attributes: Box::new([]),
2124 doc_comment: None,
2125 }
2126 }
2127}
2128
2129#[derive(Debug, Clone)]
2131#[cfg_attr(feature = "serde", derive(Serialize))]
2132#[non_exhaustive]
2133pub struct TraitUseDecl {
2134 pub traits: Box<[Name]>,
2136 pub adaptations: Box<[TraitAdaptation]>,
2138 #[cfg_attr(feature = "serde", serde(skip))]
2140 #[doc(hidden)]
2141 pub adaptations_brace_span: Option<Span>,
2142 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
2144 pub doc_comment: Option<Comment>,
2145}
2146
2147impl TraitUseDecl {
2148 pub fn new(traits: Box<[Name]>) -> Self {
2151 Self {
2152 traits,
2153 adaptations: Box::new([]),
2154 adaptations_brace_span: None,
2155 doc_comment: None,
2156 }
2157 }
2158}
2159
2160#[derive(Debug, Clone)]
2162#[cfg_attr(feature = "serde", derive(Serialize))]
2163pub struct TraitAdaptation {
2164 pub kind: TraitAdaptationKind,
2166 pub span: Span,
2168}
2169
2170#[derive(Debug, Clone)]
2172#[cfg_attr(feature = "serde", derive(Serialize))]
2173#[non_exhaustive]
2174pub enum TraitAdaptationKind {
2175 Precedence {
2177 trait_name: Name,
2179 method: Name,
2181 insteadof: Box<[Name]>,
2183 },
2184 Alias {
2186 trait_name: Option<Name>,
2188 method: Name,
2190 new_modifier: Option<Visibility>,
2192 #[cfg_attr(feature = "serde", serde(default, skip_serializing_if = "is_false"))]
2194 is_final: bool,
2195 new_name: Option<Name>,
2197 },
2198}
2199
2200#[derive(Debug, Clone)]
2202#[cfg_attr(feature = "serde", derive(Serialize))]
2203#[non_exhaustive]
2204pub struct InterfaceDecl {
2205 pub name: Ident,
2207 pub extends: Box<[Name]>,
2209 #[cfg_attr(feature = "serde", serde(flatten))]
2211 pub body: ClassBody,
2212 pub attributes: Box<[Attribute]>,
2214 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
2216 pub doc_comment: Option<Comment>,
2217}
2218
2219impl InterfaceDecl {
2220 pub fn new(name: Ident, body: ClassBody) -> Self {
2223 Self {
2224 name,
2225 extends: Box::new([]),
2226 body,
2227 attributes: Box::new([]),
2228 doc_comment: None,
2229 }
2230 }
2231}
2232
2233#[derive(Debug, Clone)]
2235#[cfg_attr(feature = "serde", derive(Serialize))]
2236#[non_exhaustive]
2237pub struct TraitDecl {
2238 pub name: Ident,
2240 #[cfg_attr(feature = "serde", serde(flatten))]
2242 pub body: ClassBody,
2243 pub attributes: Box<[Attribute]>,
2245 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
2247 pub doc_comment: Option<Comment>,
2248}
2249
2250impl TraitDecl {
2251 pub fn new(name: Ident, body: ClassBody) -> Self {
2254 Self {
2255 name,
2256 body,
2257 attributes: Box::new([]),
2258 doc_comment: None,
2259 }
2260 }
2261}
2262
2263#[derive(Debug, Clone)]
2265#[cfg_attr(feature = "serde", derive(Serialize))]
2266pub struct EnumBody {
2267 pub members: Box<[EnumMember]>,
2269 #[cfg_attr(feature = "serde", serde(skip))]
2271 pub span: Span,
2272}
2273
2274#[derive(Debug, Clone)]
2276#[cfg_attr(feature = "serde", derive(Serialize))]
2277#[non_exhaustive]
2278pub struct EnumDecl {
2279 pub name: Ident,
2281 pub scalar_type: Option<Name>,
2283 pub implements: Box<[Name]>,
2285 #[cfg_attr(feature = "serde", serde(flatten))]
2287 pub body: EnumBody,
2288 pub attributes: Box<[Attribute]>,
2290 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
2292 pub doc_comment: Option<Comment>,
2293}
2294
2295impl EnumDecl {
2296 pub fn new(name: Ident, body: EnumBody) -> Self {
2299 Self {
2300 name,
2301 scalar_type: None,
2302 implements: Box::new([]),
2303 body,
2304 attributes: Box::new([]),
2305 doc_comment: None,
2306 }
2307 }
2308}
2309
2310#[derive(Debug, Clone)]
2312#[cfg_attr(feature = "serde", derive(Serialize))]
2313pub struct EnumMember {
2314 pub kind: EnumMemberKind,
2316 pub span: Span,
2318}
2319
2320#[derive(Debug, Clone)]
2322#[cfg_attr(feature = "serde", derive(Serialize))]
2323#[non_exhaustive]
2324pub enum EnumMemberKind {
2325 Case(EnumCase),
2327 Method(MethodDecl),
2329 ClassConst(ClassConstDecl),
2331 TraitUse(TraitUseDecl),
2333 Property(PropertyDecl),
2335}
2336
2337#[derive(Debug, Clone)]
2339#[cfg_attr(feature = "serde", derive(Serialize))]
2340#[non_exhaustive]
2341pub struct EnumCase {
2342 pub name: Ident,
2344 pub value: Option<Expr>,
2346 pub attributes: Box<[Attribute]>,
2348 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
2350 pub doc_comment: Option<Comment>,
2351}
2352
2353impl EnumCase {
2354 pub fn new(name: Ident) -> Self {
2357 Self {
2358 name,
2359 value: None,
2360 attributes: Box::new([]),
2361 doc_comment: None,
2362 }
2363 }
2364}
2365
2366fn owned_ident(ident: arena_ast::Ident<'_>) -> Ident {
2371 match ident.as_str() {
2372 Some(s) => Ident::new(s, ident.span),
2373 None => Ident::error(ident.span),
2374 }
2375}
2376
2377fn owned_name(name: &arena_ast::Name<'_, '_>) -> Name {
2378 match name {
2379 arena_ast::Name::Simple { value, span } => Name {
2380 parts: vec![Box::from(*value)].into_boxed_slice(),
2381 kind: NameKind::Unqualified,
2382 span: *span,
2383 },
2384 arena_ast::Name::Complex { parts, kind, span } => Name {
2385 parts: parts
2386 .iter()
2387 .map(|s| Box::from(*s))
2388 .collect::<Vec<_>>()
2389 .into_boxed_slice(),
2390 kind: *kind,
2391 span: *span,
2392 },
2393 arena_ast::Name::Error { span } => Name {
2394 parts: Box::from([]),
2395 kind: NameKind::Error,
2396 span: *span,
2397 },
2398 }
2399}
2400
2401fn owned_comment(c: &arena_ast::Comment<'_>) -> Comment {
2402 Comment {
2403 kind: c.kind,
2404 text: c.text.into(),
2405 span: c.span,
2406 }
2407}
2408
2409fn owned_opt_comment(c: &Option<arena_ast::Comment<'_>>) -> Option<Comment> {
2410 c.as_ref().map(owned_comment)
2411}
2412
2413fn owned_type_hint(th: &arena_ast::TypeHint<'_, '_>) -> TypeHint {
2414 TypeHint {
2415 kind: owned_type_hint_kind(&th.kind),
2416 span: th.span,
2417 }
2418}
2419
2420fn owned_type_hint_kind(k: &arena_ast::TypeHintKind<'_, '_>) -> TypeHintKind {
2421 match k {
2422 arena_ast::TypeHintKind::Named(n) => TypeHintKind::Named(owned_name(n)),
2423 arena_ast::TypeHintKind::Keyword(b, span) => TypeHintKind::Keyword(*b, *span),
2424 arena_ast::TypeHintKind::Nullable(inner) => {
2425 TypeHintKind::Nullable(Box::new(owned_type_hint(inner)))
2426 }
2427 arena_ast::TypeHintKind::Union(types) => TypeHintKind::Union(
2428 types
2429 .iter()
2430 .map(owned_type_hint)
2431 .collect::<Vec<_>>()
2432 .into_boxed_slice(),
2433 ),
2434 arena_ast::TypeHintKind::Intersection(types) => TypeHintKind::Intersection(
2435 types
2436 .iter()
2437 .map(owned_type_hint)
2438 .collect::<Vec<_>>()
2439 .into_boxed_slice(),
2440 ),
2441 }
2442}
2443
2444fn owned_arg(arg: &arena_ast::Arg<'_, '_>) -> Arg {
2445 Arg {
2446 name: arg.name.as_ref().map(owned_name),
2447 kind: match &arg.kind {
2448 arena_ast::ArgKind::Value(e) => ArgKind::Value(owned_expr(e)),
2449 arena_ast::ArgKind::Spread(e) => ArgKind::Spread(owned_expr(e)),
2450 arena_ast::ArgKind::ByRef(e) => ArgKind::ByRef(owned_expr(e)),
2451 arena_ast::ArgKind::Placeholder => ArgKind::Placeholder,
2452 arena_ast::ArgKind::SpreadPlaceholder => ArgKind::SpreadPlaceholder,
2453 },
2454 span: arg.span,
2455 }
2456}
2457
2458#[inline(never)]
2459fn owned_args(args: &[arena_ast::Arg<'_, '_>]) -> Box<[Arg]> {
2460 args.iter()
2461 .map(owned_arg)
2462 .collect::<Vec<_>>()
2463 .into_boxed_slice()
2464}
2465
2466fn owned_attr(attr: &arena_ast::Attribute<'_, '_>) -> Attribute {
2467 Attribute {
2468 name: owned_name(&attr.name),
2469 args: owned_args(&attr.args),
2470 span: attr.span,
2471 }
2472}
2473
2474fn owned_attrs(attrs: &[arena_ast::Attribute<'_, '_>]) -> Box<[Attribute]> {
2475 attrs
2476 .iter()
2477 .map(owned_attr)
2478 .collect::<Vec<_>>()
2479 .into_boxed_slice()
2480}
2481
2482#[inline(never)]
2483fn owned_string_parts(parts: &[arena_ast::StringPart<'_, '_>]) -> Box<[StringPart]> {
2484 parts
2485 .iter()
2486 .map(|p| match p {
2487 arena_ast::StringPart::Literal(s) => {
2488 StringPart::Literal(ByteString::from(s.as_bytes()))
2489 }
2490 arena_ast::StringPart::Expr(e) => StringPart::Expr(owned_expr(e)),
2491 })
2492 .collect::<Vec<_>>()
2493 .into_boxed_slice()
2494}
2495
2496pub fn to_owned_expr(expr: &arena_ast::Expr<'_, '_>) -> Expr {
2498 owned_expr(expr)
2499}
2500
2501pub fn to_owned_name(name: &arena_ast::Name<'_, '_>) -> Name {
2503 owned_name(name)
2504}
2505
2506pub fn to_owned_type_hint(hint: &arena_ast::TypeHint<'_, '_>) -> TypeHint {
2508 owned_type_hint(hint)
2509}
2510
2511#[inline]
2512fn owned_expr(expr: &arena_ast::Expr<'_, '_>) -> Expr {
2513 if !arena_is_chain(&expr.kind) {
2514 return Expr {
2515 kind: owned_leaf_kind(&expr.kind),
2516 span: expr.span,
2517 };
2518 }
2519 owned_chain_expr(expr)
2520}
2521
2522#[inline(never)]
2525fn owned_chain_expr(expr: &arena_ast::Expr<'_, '_>) -> Expr {
2526 let first = arena_chain_operand(&expr.kind).expect("chain link has an operand");
2527 if !arena_is_chain(&first.kind) {
2528 let operand = Expr {
2530 kind: owned_leaf_kind(&first.kind),
2531 span: first.span,
2532 };
2533 return Expr {
2534 kind: owned_link_kind(&expr.kind, operand),
2535 span: expr.span,
2536 };
2537 }
2538 let mut chain = LinkStack::new();
2539 chain.push(expr);
2540 let mut leaf = first;
2541 while let Some(operand) = arena_chain_operand(&leaf.kind) {
2542 chain.push(leaf);
2543 leaf = operand;
2544 }
2545 let mut converted = Expr {
2546 kind: owned_leaf_kind(&leaf.kind),
2547 span: leaf.span,
2548 };
2549 while let Some(node) = chain.pop() {
2550 converted = Expr {
2551 kind: owned_link_kind(&node.kind, converted),
2552 span: node.span,
2553 };
2554 }
2555 converted
2556}
2557
2558#[inline(never)]
2559fn owned_exprs(exprs: &[arena_ast::Expr<'_, '_>]) -> Box<[Expr]> {
2560 exprs
2561 .iter()
2562 .map(owned_expr)
2563 .collect::<Vec<_>>()
2564 .into_boxed_slice()
2565}
2566
2567fn owned_leaf_kind(k: &arena_ast::ExprKind<'_, '_>) -> ExprKind {
2569 match k {
2570 arena_ast::ExprKind::Int(v) => ExprKind::Int(*v),
2571 arena_ast::ExprKind::Float(v) => ExprKind::Float(*v),
2572 arena_ast::ExprKind::String(s) => ExprKind::String(ByteString::from(s.as_bytes())),
2573 arena_ast::ExprKind::InterpolatedString(parts) => {
2574 ExprKind::InterpolatedString(owned_string_parts(parts))
2575 }
2576 arena_ast::ExprKind::Heredoc { label, parts } => ExprKind::Heredoc {
2577 label: Box::from(*label),
2578 parts: owned_string_parts(parts),
2579 },
2580 arena_ast::ExprKind::Nowdoc { label, value } => ExprKind::Nowdoc {
2581 label: Box::from(*label),
2582 value: Box::from(*value),
2583 },
2584 arena_ast::ExprKind::ShellExec(parts) => ExprKind::ShellExec(owned_string_parts(parts)),
2585 arena_ast::ExprKind::Bool(v) => ExprKind::Bool(*v),
2586 arena_ast::ExprKind::Null => ExprKind::Null,
2587 arena_ast::ExprKind::Variable(s) => ExprKind::Variable(s.as_str().into()),
2588 arena_ast::ExprKind::VariableVariable(inner) => {
2589 ExprKind::VariableVariable(Box::new(owned_expr(inner)))
2590 }
2591 arena_ast::ExprKind::Identifier(s) => ExprKind::Identifier(s.as_str().into()),
2592 arena_ast::ExprKind::Name(name) => ExprKind::Name(owned_name(name)),
2593 arena_ast::ExprKind::Array(elems) => ExprKind::Array(
2594 elems
2595 .iter()
2596 .map(|e| ArrayElement {
2597 key: e.key.as_ref().map(owned_expr),
2598 kind: match &e.kind {
2599 arena_ast::ArrayElementKind::Value(v) => {
2600 ArrayElementKind::Value(owned_expr(v))
2601 }
2602 arena_ast::ArrayElementKind::Spread(v) => {
2603 ArrayElementKind::Spread(owned_expr(v))
2604 }
2605 arena_ast::ArrayElementKind::ByRef(v) => {
2606 ArrayElementKind::ByRef(owned_expr(v))
2607 }
2608 },
2609 span: e.span,
2610 })
2611 .collect::<Vec<_>>()
2612 .into_boxed_slice(),
2613 ),
2614 arena_ast::ExprKind::Print(e) => ExprKind::Print(Box::new(owned_expr(e))),
2615 arena_ast::ExprKind::Parenthesized(e) => ExprKind::Parenthesized(Box::new(owned_expr(e))),
2616 arena_ast::ExprKind::Cast(kind, e) => ExprKind::Cast(*kind, Box::new(owned_expr(e))),
2617 arena_ast::ExprKind::ErrorSuppress(e) => ExprKind::ErrorSuppress(Box::new(owned_expr(e))),
2618 arena_ast::ExprKind::Isset(exprs) => ExprKind::Isset(owned_exprs(exprs)),
2619 arena_ast::ExprKind::Empty(e) => ExprKind::Empty(Box::new(owned_expr(e))),
2620 arena_ast::ExprKind::Include(kind, e) => ExprKind::Include(*kind, Box::new(owned_expr(e))),
2621 arena_ast::ExprKind::Eval(e) => ExprKind::Eval(Box::new(owned_expr(e))),
2622 arena_ast::ExprKind::Exit(e) => ExprKind::Exit(e.map(|e| Box::new(owned_expr(e)))),
2623 arena_ast::ExprKind::MagicConst(m) => ExprKind::MagicConst(*m),
2624 arena_ast::ExprKind::Clone(e) => ExprKind::Clone(Box::new(owned_expr(e))),
2625 arena_ast::ExprKind::CloneWith(obj, props) => {
2626 ExprKind::CloneWith(Box::new(owned_expr(obj)), Box::new(owned_expr(props)))
2627 }
2628 arena_ast::ExprKind::New(n) => ExprKind::New(NewExpr {
2629 class: Box::new(owned_expr(n.class)),
2630 args: owned_args(&n.args),
2631 }),
2632 arena_ast::ExprKind::Closure(c) => ExprKind::Closure(Box::new(ClosureExpr {
2633 is_static: c.is_static,
2634 by_ref: c.by_ref,
2635 params: owned_params(&c.params),
2636 missing_param_list: c.missing_param_list,
2637 use_vars: c
2638 .use_vars
2639 .iter()
2640 .map(|v| ClosureUseVar {
2641 name: owned_ident(v.name),
2642 by_ref: v.by_ref,
2643 span: v.span,
2644 })
2645 .collect::<Vec<_>>()
2646 .into_boxed_slice(),
2647 return_type: c.return_type.as_ref().map(owned_type_hint),
2648 body: Box::new(owned_block(c.body)),
2649 attributes: owned_attrs(&c.attributes),
2650 })),
2651 arena_ast::ExprKind::ArrowFunction(f) => {
2652 ExprKind::ArrowFunction(Box::new(ArrowFunctionExpr {
2653 is_static: f.is_static,
2654 by_ref: f.by_ref,
2655 params: owned_params(&f.params),
2656 missing_param_list: f.missing_param_list,
2657 return_type: f.return_type.as_ref().map(owned_type_hint),
2658 body: Box::new(owned_expr(f.body)),
2659 attributes: owned_attrs(&f.attributes),
2660 }))
2661 }
2662 arena_ast::ExprKind::Match(m) => ExprKind::Match(MatchExpr {
2663 subject: Box::new(owned_expr(m.subject)),
2664 arms: m
2665 .arms
2666 .iter()
2667 .map(|arm| MatchArm {
2668 conditions: arm.conditions.as_ref().map(|conds| owned_exprs(conds)),
2669 body: owned_expr(&arm.body),
2670 span: arm.span,
2671 })
2672 .collect::<Vec<_>>()
2673 .into_boxed_slice(),
2674 brace_span: m.brace_span,
2675 }),
2676 arena_ast::ExprKind::Throw(e) => ExprKind::Throw(Box::new(owned_expr(e))),
2677 arena_ast::ExprKind::Yield(y) => ExprKind::Yield(YieldExpr {
2678 key: y.key.map(|e| Box::new(owned_expr(e))),
2679 value: y.value.map(|e| Box::new(owned_expr(e))),
2680 is_from: y.is_from,
2681 }),
2682 arena_ast::ExprKind::AnonymousClass(cls) => {
2683 ExprKind::AnonymousClass(Box::new(owned_class_decl(cls)))
2684 }
2685 arena_ast::ExprKind::Omit => ExprKind::Omit,
2686 arena_ast::ExprKind::Error => ExprKind::Error,
2687 arena_ast::ExprKind::Assign(_)
2688 | arena_ast::ExprKind::Binary(_)
2689 | arena_ast::ExprKind::UnaryPrefix(_)
2690 | arena_ast::ExprKind::UnaryPostfix(_)
2691 | arena_ast::ExprKind::Ternary(_)
2692 | arena_ast::ExprKind::NullCoalesce(_)
2693 | arena_ast::ExprKind::FunctionCall(_)
2694 | arena_ast::ExprKind::ArrayAccess(_)
2695 | arena_ast::ExprKind::PropertyAccess(_)
2696 | arena_ast::ExprKind::NullsafePropertyAccess(_)
2697 | arena_ast::ExprKind::MethodCall(_)
2698 | arena_ast::ExprKind::NullsafeMethodCall(_)
2699 | arena_ast::ExprKind::StaticPropertyAccess(_)
2700 | arena_ast::ExprKind::ClassConstAccess(_)
2701 | arena_ast::ExprKind::StaticMethodCall(_)
2702 | arena_ast::ExprKind::StaticMethodCallDynamic(_)
2703 | arena_ast::ExprKind::ClassConstAccessDynamic { .. }
2704 | arena_ast::ExprKind::StaticPropertyAccessDynamic { .. }
2705 | arena_ast::ExprKind::CallableCreate(_) => {
2706 unreachable!("chain links are converted by the link function")
2707 }
2708 }
2709}
2710
2711fn owned_link_kind(k: &arena_ast::ExprKind<'_, '_>, operand: Expr) -> ExprKind {
2713 match k {
2714 arena_ast::ExprKind::Assign(a) => ExprKind::Assign(AssignExpr {
2715 target: Box::new(operand),
2716 op: a.op,
2717 value: Box::new(owned_expr(a.value)),
2718 by_ref: a.by_ref,
2719 }),
2720 arena_ast::ExprKind::Binary(b) => ExprKind::Binary(BinaryExpr {
2721 left: Box::new(operand),
2722 op: b.op,
2723 right: Box::new(owned_expr(b.right)),
2724 }),
2725 arena_ast::ExprKind::UnaryPrefix(u) => ExprKind::UnaryPrefix(UnaryPrefixExpr {
2726 op: u.op,
2727 operand: Box::new(operand),
2728 }),
2729 arena_ast::ExprKind::UnaryPostfix(u) => ExprKind::UnaryPostfix(UnaryPostfixExpr {
2730 operand: Box::new(operand),
2731 op: u.op,
2732 }),
2733 arena_ast::ExprKind::Ternary(t) => ExprKind::Ternary(TernaryExpr {
2734 condition: Box::new(operand),
2735 then_expr: t.then_expr.map(|e| Box::new(owned_expr(e))),
2736 else_expr: Box::new(owned_expr(t.else_expr)),
2737 }),
2738 arena_ast::ExprKind::NullCoalesce(n) => ExprKind::NullCoalesce(NullCoalesceExpr {
2739 left: Box::new(operand),
2740 right: Box::new(owned_expr(n.right)),
2741 }),
2742 arena_ast::ExprKind::FunctionCall(f) => ExprKind::FunctionCall(FunctionCallExpr {
2743 name: Box::new(operand),
2744 args: owned_args(&f.args),
2745 }),
2746 arena_ast::ExprKind::ArrayAccess(a) => ExprKind::ArrayAccess(ArrayAccessExpr {
2747 array: Box::new(operand),
2748 index: a.index.map(|e| Box::new(owned_expr(e))),
2749 }),
2750 arena_ast::ExprKind::PropertyAccess(p) => ExprKind::PropertyAccess(PropertyAccessExpr {
2751 object: Box::new(operand),
2752 property: Box::new(owned_expr(p.property)),
2753 }),
2754 arena_ast::ExprKind::NullsafePropertyAccess(p) => {
2755 ExprKind::NullsafePropertyAccess(PropertyAccessExpr {
2756 object: Box::new(operand),
2757 property: Box::new(owned_expr(p.property)),
2758 })
2759 }
2760 arena_ast::ExprKind::MethodCall(m) => ExprKind::MethodCall(Box::new(MethodCallExpr {
2761 object: Box::new(operand),
2762 method: Box::new(owned_expr(m.method)),
2763 args: owned_args(&m.args),
2764 })),
2765 arena_ast::ExprKind::NullsafeMethodCall(m) => {
2766 ExprKind::NullsafeMethodCall(Box::new(MethodCallExpr {
2767 object: Box::new(operand),
2768 method: Box::new(owned_expr(m.method)),
2769 args: owned_args(&m.args),
2770 }))
2771 }
2772 arena_ast::ExprKind::StaticPropertyAccess(s) => {
2773 ExprKind::StaticPropertyAccess(StaticAccessExpr {
2774 class: Box::new(operand),
2775 member: Box::new(owned_expr(s.member)),
2776 })
2777 }
2778 arena_ast::ExprKind::StaticMethodCall(s) => {
2779 ExprKind::StaticMethodCall(Box::new(StaticMethodCallExpr {
2780 class: Box::new(operand),
2781 method: Box::new(owned_expr(s.method)),
2782 args: owned_args(&s.args),
2783 }))
2784 }
2785 arena_ast::ExprKind::StaticMethodCallDynamic(s) => {
2786 ExprKind::StaticMethodCallDynamic(Box::new(StaticMethodCallDynamicExpr {
2787 class: Box::new(operand),
2788 method: Box::new(owned_expr(s.method)),
2789 args: owned_args(&s.args),
2790 }))
2791 }
2792 arena_ast::ExprKind::ClassConstAccess(s) => ExprKind::ClassConstAccess(StaticAccessExpr {
2793 class: Box::new(operand),
2794 member: Box::new(owned_expr(s.member)),
2795 }),
2796 arena_ast::ExprKind::ClassConstAccessDynamic { member, .. } => {
2797 ExprKind::ClassConstAccessDynamic {
2798 class: Box::new(operand),
2799 member: Box::new(owned_expr(member)),
2800 }
2801 }
2802 arena_ast::ExprKind::StaticPropertyAccessDynamic { member, .. } => {
2803 ExprKind::StaticPropertyAccessDynamic {
2804 class: Box::new(operand),
2805 member: Box::new(owned_expr(member)),
2806 }
2807 }
2808 arena_ast::ExprKind::CallableCreate(c) => ExprKind::CallableCreate(CallableCreateExpr {
2809 kind: match &c.kind {
2810 arena_ast::CallableCreateKind::Function(_) => {
2811 CallableCreateKind::Function(Box::new(operand))
2812 }
2813 arena_ast::CallableCreateKind::Method { method, .. } => {
2814 CallableCreateKind::Method {
2815 object: Box::new(operand),
2816 method: Box::new(owned_expr(method)),
2817 }
2818 }
2819 arena_ast::CallableCreateKind::NullsafeMethod { method, .. } => {
2820 CallableCreateKind::NullsafeMethod {
2821 object: Box::new(operand),
2822 method: Box::new(owned_expr(method)),
2823 }
2824 }
2825 arena_ast::CallableCreateKind::StaticMethod { method, .. } => {
2826 CallableCreateKind::StaticMethod {
2827 class: Box::new(operand),
2828 method: Box::new(owned_expr(method)),
2829 }
2830 }
2831 },
2832 }),
2833 _ => unreachable!("not a chain link"),
2834 }
2835}
2836
2837fn owned_param(p: &arena_ast::Param<'_, '_>) -> Param {
2838 Param {
2839 name: owned_ident(p.name),
2840 type_hint: p.type_hint.as_ref().map(owned_type_hint),
2841 default: p.default.as_ref().map(owned_expr),
2842 by_ref: p.by_ref,
2843 variadic: p.variadic,
2844 modifiers: p.modifiers,
2845 attributes: owned_attrs(&p.attributes),
2846 hooks: owned_hooks(&p.hooks),
2847 empty_hook_list: p.empty_hook_list,
2848 doc_comment: p.doc_comment.as_ref().map(owned_comment),
2849 span: p.span,
2850 }
2851}
2852
2853#[inline(never)]
2854fn owned_params(params: &[arena_ast::Param<'_, '_>]) -> Box<[Param]> {
2855 params
2856 .iter()
2857 .map(owned_param)
2858 .collect::<Vec<_>>()
2859 .into_boxed_slice()
2860}
2861
2862fn owned_hook(h: &arena_ast::PropertyHook<'_, '_>) -> PropertyHook {
2863 PropertyHook {
2864 kind: h.kind,
2865 body: match &h.body {
2866 arena_ast::PropertyHookBody::Block(block) => {
2867 PropertyHookBody::Block(Box::new(owned_block(block)))
2868 }
2869 arena_ast::PropertyHookBody::Expression(e) => {
2870 PropertyHookBody::Expression(owned_expr(e))
2871 }
2872 arena_ast::PropertyHookBody::Abstract => PropertyHookBody::Abstract,
2873 },
2874 modifiers: h.modifiers,
2875 by_ref: h.by_ref,
2876 params: owned_params(&h.params),
2877 attributes: owned_attrs(&h.attributes),
2878 span: h.span,
2879 }
2880}
2881
2882#[inline(never)]
2883fn owned_hooks(hooks: &[arena_ast::PropertyHook<'_, '_>]) -> Box<[PropertyHook]> {
2884 hooks
2885 .iter()
2886 .map(owned_hook)
2887 .collect::<Vec<_>>()
2888 .into_boxed_slice()
2889}
2890
2891fn owned_stmts(stmts: &[arena_ast::Stmt<'_, '_>]) -> Box<[Stmt]> {
2892 stmts
2893 .iter()
2894 .map(owned_stmt)
2895 .collect::<Vec<_>>()
2896 .into_boxed_slice()
2897}
2898
2899pub fn to_owned_stmt(stmt: &arena_ast::Stmt<'_, '_>) -> Stmt {
2901 owned_stmt(stmt)
2902}
2903
2904fn owned_block(block: &arena_ast::Block<'_, '_>) -> Block {
2905 Block {
2906 stmts: owned_stmts(&block.stmts),
2907 span: block.span,
2908 }
2909}
2910
2911fn owned_stmt(stmt: &arena_ast::Stmt<'_, '_>) -> Stmt {
2912 Stmt {
2913 kind: owned_stmt_kind(&stmt.kind),
2914 span: stmt.span,
2915 doc_comment: stmt.doc_comment.map(owned_comment),
2916 }
2917}
2918
2919fn owned_stmt_kind(k: &arena_ast::StmtKind<'_, '_>) -> StmtKind {
2920 match k {
2921 arena_ast::StmtKind::Expression(e) => StmtKind::Expression(Box::new(owned_expr(e))),
2922 arena_ast::StmtKind::Echo(exprs) => StmtKind::Echo(owned_exprs(exprs)),
2923 arena_ast::StmtKind::Return(e) => StmtKind::Return(e.map(|e| Box::new(owned_expr(e)))),
2924 arena_ast::StmtKind::Block(block) => StmtKind::Block(Box::new(owned_block(block))),
2925 arena_ast::StmtKind::If(s) => StmtKind::If(Box::new(IfStmt {
2926 condition: owned_expr(&s.condition),
2927 then_branch: Box::new(owned_stmt(s.then_branch)),
2928 elseif_branches: s
2929 .elseif_branches
2930 .iter()
2931 .map(|b| ElseIfBranch {
2932 condition: owned_expr(&b.condition),
2933 body: owned_stmt(&b.body),
2934 span: b.span,
2935 })
2936 .collect::<Vec<_>>()
2937 .into_boxed_slice(),
2938 else_branch: s.else_branch.map(|b| Box::new(owned_stmt(b))),
2939 else_kw_span: s.else_kw_span,
2940 uses_alternative: s.uses_alternative,
2941 })),
2942 arena_ast::StmtKind::While(s) => StmtKind::While(Box::new(WhileStmt {
2943 condition: owned_expr(&s.condition),
2944 body: Box::new(owned_stmt(s.body)),
2945 uses_alternative: s.uses_alternative,
2946 })),
2947 arena_ast::StmtKind::For(s) => StmtKind::For(Box::new(ForStmt {
2948 init: owned_exprs(&s.init),
2949 condition: owned_exprs(&s.condition),
2950 update: owned_exprs(&s.update),
2951 body: Box::new(owned_stmt(s.body)),
2952 uses_alternative: s.uses_alternative,
2953 })),
2954 arena_ast::StmtKind::Foreach(s) => StmtKind::Foreach(Box::new(ForeachStmt {
2955 expr: owned_expr(&s.expr),
2956 key: s.key.as_ref().map(owned_expr),
2957 value: owned_expr(&s.value),
2958 by_ref: s.by_ref,
2959 by_ref_span: s.by_ref_span,
2960 body: Box::new(owned_stmt(s.body)),
2961 uses_alternative: s.uses_alternative,
2962 })),
2963 arena_ast::StmtKind::DoWhile(s) => StmtKind::DoWhile(Box::new(DoWhileStmt {
2964 body: Box::new(owned_stmt(s.body)),
2965 condition: owned_expr(&s.condition),
2966 })),
2967 arena_ast::StmtKind::Function(f) => StmtKind::Function(Box::new(owned_function_decl(f))),
2968 arena_ast::StmtKind::Break(e) => StmtKind::Break(e.map(|e| Box::new(owned_expr(e)))),
2969 arena_ast::StmtKind::Continue(e) => StmtKind::Continue(e.map(|e| Box::new(owned_expr(e)))),
2970 arena_ast::StmtKind::Switch(s) => StmtKind::Switch(Box::new(SwitchStmt {
2971 expr: owned_expr(&s.expr),
2972 body: SwitchBody {
2973 cases: s
2974 .body
2975 .cases
2976 .iter()
2977 .map(|c| SwitchCase {
2978 value: c.value.as_ref().map(owned_expr),
2979 body: owned_stmts(&c.body),
2980 span: c.span,
2981 })
2982 .collect::<Vec<_>>()
2983 .into_boxed_slice(),
2984 span: s.body.span,
2985 },
2986 uses_alternative: s.uses_alternative,
2987 })),
2988 arena_ast::StmtKind::Goto(ident) => StmtKind::Goto(owned_ident(*ident)),
2989 arena_ast::StmtKind::Label(ident) => StmtKind::Label(owned_ident(*ident)),
2990 arena_ast::StmtKind::Declare(d) => StmtKind::Declare(Box::new(DeclareStmt {
2991 directives: d
2992 .directives
2993 .iter()
2994 .map(|(k, v)| (Box::from(*k), owned_expr(v)))
2995 .collect::<Vec<_>>()
2996 .into_boxed_slice(),
2997 body: d.body.map(|b| Box::new(owned_stmt(b))),
2998 uses_alternative: d.uses_alternative,
2999 })),
3000 arena_ast::StmtKind::Unset(exprs) => StmtKind::Unset(owned_exprs(exprs)),
3001 arena_ast::StmtKind::Throw(e) => StmtKind::Throw(Box::new(owned_expr(e))),
3002 arena_ast::StmtKind::TryCatch(t) => StmtKind::TryCatch(Box::new(TryCatchStmt {
3003 body: Box::new(owned_block(t.body)),
3004 catches: t
3005 .catches
3006 .iter()
3007 .map(|c| CatchClause {
3008 types: c
3009 .types
3010 .iter()
3011 .map(owned_name)
3012 .collect::<Vec<_>>()
3013 .into_boxed_slice(),
3014 var: c.var.map(owned_ident),
3015 body: Box::new(owned_block(c.body)),
3016 span: c.span,
3017 })
3018 .collect::<Vec<_>>()
3019 .into_boxed_slice(),
3020 finally: t.finally.map(|f| Box::new(owned_block(f))),
3021 finally_kw_span: t.finally_kw_span,
3022 })),
3023 arena_ast::StmtKind::Global(exprs) => StmtKind::Global(owned_exprs(exprs)),
3024 arena_ast::StmtKind::Class(cls) => StmtKind::Class(Box::new(owned_class_decl(cls))),
3025 arena_ast::StmtKind::Interface(iface) => {
3026 StmtKind::Interface(Box::new(owned_interface_decl(iface)))
3027 }
3028 arena_ast::StmtKind::Trait(tr) => StmtKind::Trait(Box::new(owned_trait_decl(tr))),
3029 arena_ast::StmtKind::Enum(en) => StmtKind::Enum(Box::new(owned_enum_decl(en))),
3030 arena_ast::StmtKind::Namespace(ns) => StmtKind::Namespace(Box::new(NamespaceDecl {
3031 name: ns.name.as_ref().map(owned_name),
3032 body: match &ns.body {
3033 arena_ast::NamespaceBody::Braced(block) => {
3034 NamespaceBody::Braced(Box::new(owned_block(block)))
3035 }
3036 arena_ast::NamespaceBody::Simple => NamespaceBody::Simple,
3037 },
3038 })),
3039 arena_ast::StmtKind::Use(u) => StmtKind::Use(Box::new(UseDecl {
3040 kind: u.kind,
3041 uses: u
3042 .uses
3043 .iter()
3044 .map(|item| UseItem {
3045 name: owned_name(&item.name),
3046 alias: item.alias.map(owned_ident),
3047 kind: item.kind,
3048 span: item.span,
3049 })
3050 .collect::<Vec<_>>()
3051 .into_boxed_slice(),
3052 })),
3053 arena_ast::StmtKind::Const(items) => StmtKind::Const(
3054 items
3055 .iter()
3056 .map(|item| ConstItem {
3057 name: owned_ident(item.name),
3058 value: owned_expr(&item.value),
3059 attributes: owned_attrs(&item.attributes),
3060 span: item.span,
3061 doc_comment: owned_opt_comment(&item.doc_comment),
3062 })
3063 .collect::<Vec<_>>()
3064 .into_boxed_slice(),
3065 ),
3066 arena_ast::StmtKind::StaticVar(vars) => StmtKind::StaticVar(
3067 vars.iter()
3068 .map(|v| StaticVar {
3069 name: owned_ident(v.name),
3070 default: v.default.as_ref().map(owned_expr),
3071 span: v.span,
3072 })
3073 .collect::<Vec<_>>()
3074 .into_boxed_slice(),
3075 ),
3076 arena_ast::StmtKind::HaltCompiler(s) => StmtKind::HaltCompiler(Box::from(*s)),
3077 arena_ast::StmtKind::Nop => StmtKind::Nop,
3078 arena_ast::StmtKind::InlineHtml(s) => StmtKind::InlineHtml(Box::from(*s)),
3079 arena_ast::StmtKind::Error => StmtKind::Error,
3080 }
3081}
3082
3083fn owned_function_decl(f: &arena_ast::FunctionDecl<'_, '_>) -> FunctionDecl {
3084 FunctionDecl {
3085 name: owned_ident(f.name),
3086 params: owned_params(&f.params),
3087 missing_param_list: f.missing_param_list,
3088 body: Box::new(owned_block(f.body)),
3089 return_type: f.return_type.as_ref().map(owned_type_hint),
3090 by_ref: f.by_ref,
3091 attributes: owned_attrs(&f.attributes),
3092 doc_comment: owned_opt_comment(&f.doc_comment),
3093 }
3094}
3095
3096fn owned_property(p: &arena_ast::PropertyDecl<'_, '_>) -> PropertyDecl {
3097 PropertyDecl {
3098 name: owned_ident(p.name),
3099 modifiers: p.modifiers,
3100 type_hint: p.type_hint.as_ref().map(owned_type_hint),
3101 default: p.default.as_ref().map(owned_expr),
3102 attributes: owned_attrs(&p.attributes),
3103 hooks: owned_hooks(&p.hooks),
3104 empty_hook_list: p.empty_hook_list,
3105 doc_comment: owned_opt_comment(&p.doc_comment),
3106 }
3107}
3108
3109fn owned_class_member(m: &arena_ast::ClassMember<'_, '_>) -> ClassMember {
3110 ClassMember {
3111 kind: match &m.kind {
3112 arena_ast::ClassMemberKind::Property(p) => ClassMemberKind::Property(owned_property(p)),
3113 arena_ast::ClassMemberKind::Method(m) => ClassMemberKind::Method(MethodDecl {
3114 name: owned_ident(m.name),
3115 modifiers: m.modifiers,
3116 by_ref: m.by_ref,
3117 params: owned_params(&m.params),
3118 missing_param_list: m.missing_param_list,
3119 return_type: m.return_type.as_ref().map(owned_type_hint),
3120 body: m.body.map(|b| Box::new(owned_block(b))),
3121 attributes: owned_attrs(&m.attributes),
3122 doc_comment: owned_opt_comment(&m.doc_comment),
3123 }),
3124 arena_ast::ClassMemberKind::ClassConst(c) => {
3125 ClassMemberKind::ClassConst(owned_class_const(c))
3126 }
3127 arena_ast::ClassMemberKind::TraitUse(t) => {
3128 ClassMemberKind::TraitUse(owned_trait_use(t))
3129 }
3130 },
3131 span: m.span,
3132 }
3133}
3134
3135fn owned_class_members(members: &[arena_ast::ClassMember<'_, '_>]) -> Box<[ClassMember]> {
3136 members
3137 .iter()
3138 .map(owned_class_member)
3139 .collect::<Vec<_>>()
3140 .into_boxed_slice()
3141}
3142
3143fn owned_class_const(c: &arena_ast::ClassConstDecl<'_, '_>) -> ClassConstDecl {
3144 ClassConstDecl {
3145 name: owned_ident(c.name),
3146 modifiers: c.modifiers,
3147 type_hint: c.type_hint.map(|th| Box::new(owned_type_hint(th))),
3148 value: owned_expr(&c.value),
3149 attributes: owned_attrs(&c.attributes),
3150 doc_comment: owned_opt_comment(&c.doc_comment),
3151 }
3152}
3153
3154fn owned_trait_use(t: &arena_ast::TraitUseDecl<'_, '_>) -> TraitUseDecl {
3155 TraitUseDecl {
3156 traits: t
3157 .traits
3158 .iter()
3159 .map(owned_name)
3160 .collect::<Vec<_>>()
3161 .into_boxed_slice(),
3162 adaptations: t
3163 .adaptations
3164 .iter()
3165 .map(|a| TraitAdaptation {
3166 kind: match &a.kind {
3167 arena_ast::TraitAdaptationKind::Precedence {
3168 trait_name,
3169 method,
3170 insteadof,
3171 } => TraitAdaptationKind::Precedence {
3172 trait_name: owned_name(trait_name),
3173 method: owned_name(method),
3174 insteadof: insteadof
3175 .iter()
3176 .map(owned_name)
3177 .collect::<Vec<_>>()
3178 .into_boxed_slice(),
3179 },
3180 arena_ast::TraitAdaptationKind::Alias {
3181 trait_name,
3182 method,
3183 new_modifier,
3184 is_final,
3185 new_name,
3186 } => TraitAdaptationKind::Alias {
3187 trait_name: trait_name.as_ref().map(owned_name),
3188 method: owned_name(method),
3189 new_modifier: *new_modifier,
3190 is_final: *is_final,
3191 new_name: new_name.as_ref().map(owned_name),
3192 },
3193 },
3194 span: a.span,
3195 })
3196 .collect::<Vec<_>>()
3197 .into_boxed_slice(),
3198 adaptations_brace_span: t.adaptations_brace_span,
3199 doc_comment: owned_opt_comment(&t.doc_comment),
3200 }
3201}
3202
3203fn owned_class_decl(cls: &arena_ast::ClassDecl<'_, '_>) -> ClassDecl {
3204 ClassDecl {
3205 name: cls
3206 .name
3207 .map(|ident| Some(owned_ident(ident)))
3208 .unwrap_or(None),
3209 modifiers: cls.modifiers.clone(),
3210 extends: cls.extends.as_ref().map(owned_name),
3211 implements: cls
3212 .implements
3213 .iter()
3214 .map(owned_name)
3215 .collect::<Vec<_>>()
3216 .into_boxed_slice(),
3217 body: ClassBody {
3218 members: owned_class_members(&cls.body.members),
3219 span: cls.body.span,
3220 },
3221 attributes: owned_attrs(&cls.attributes),
3222 doc_comment: owned_opt_comment(&cls.doc_comment),
3223 }
3224}
3225
3226fn owned_interface_decl(iface: &arena_ast::InterfaceDecl<'_, '_>) -> InterfaceDecl {
3227 InterfaceDecl {
3228 name: owned_ident(iface.name),
3229 extends: iface
3230 .extends
3231 .iter()
3232 .map(owned_name)
3233 .collect::<Vec<_>>()
3234 .into_boxed_slice(),
3235 body: ClassBody {
3236 members: owned_class_members(&iface.body.members),
3237 span: iface.body.span,
3238 },
3239 attributes: owned_attrs(&iface.attributes),
3240 doc_comment: owned_opt_comment(&iface.doc_comment),
3241 }
3242}
3243
3244fn owned_trait_decl(tr: &arena_ast::TraitDecl<'_, '_>) -> TraitDecl {
3245 TraitDecl {
3246 name: owned_ident(tr.name),
3247 body: ClassBody {
3248 members: owned_class_members(&tr.body.members),
3249 span: tr.body.span,
3250 },
3251 attributes: owned_attrs(&tr.attributes),
3252 doc_comment: owned_opt_comment(&tr.doc_comment),
3253 }
3254}
3255
3256fn owned_enum_decl(en: &arena_ast::EnumDecl<'_, '_>) -> EnumDecl {
3257 EnumDecl {
3258 name: owned_ident(en.name),
3259 scalar_type: en.scalar_type.as_ref().map(owned_name),
3260 implements: en
3261 .implements
3262 .iter()
3263 .map(owned_name)
3264 .collect::<Vec<_>>()
3265 .into_boxed_slice(),
3266 body: EnumBody {
3267 members: en
3268 .body
3269 .members
3270 .iter()
3271 .map(|m| EnumMember {
3272 kind: match &m.kind {
3273 arena_ast::EnumMemberKind::Case(c) => EnumMemberKind::Case(EnumCase {
3274 name: owned_ident(c.name),
3275 value: c.value.as_ref().map(owned_expr),
3276 attributes: owned_attrs(&c.attributes),
3277 doc_comment: owned_opt_comment(&c.doc_comment),
3278 }),
3279 arena_ast::EnumMemberKind::Method(m) => {
3280 EnumMemberKind::Method(MethodDecl {
3281 name: owned_ident(m.name),
3282 modifiers: m.modifiers,
3283 by_ref: m.by_ref,
3284 params: owned_params(&m.params),
3285 missing_param_list: m.missing_param_list,
3286 return_type: m.return_type.as_ref().map(owned_type_hint),
3287 body: m.body.map(|b| Box::new(owned_block(b))),
3288 attributes: owned_attrs(&m.attributes),
3289 doc_comment: owned_opt_comment(&m.doc_comment),
3290 })
3291 }
3292 arena_ast::EnumMemberKind::ClassConst(c) => {
3293 EnumMemberKind::ClassConst(owned_class_const(c))
3294 }
3295 arena_ast::EnumMemberKind::TraitUse(t) => {
3296 EnumMemberKind::TraitUse(owned_trait_use(t))
3297 }
3298 arena_ast::EnumMemberKind::Property(p) => {
3299 EnumMemberKind::Property(owned_property(p))
3300 }
3301 },
3302 span: m.span,
3303 })
3304 .collect::<Vec<_>>()
3305 .into_boxed_slice(),
3306 span: en.body.span,
3307 },
3308 attributes: owned_attrs(&en.attributes),
3309 doc_comment: owned_opt_comment(&en.doc_comment),
3310 }
3311}
3312
3313pub fn to_owned_program(program: &arena_ast::Program<'_, '_>) -> Program {
3315 Program {
3316 stmts: owned_stmts(&program.stmts),
3317 span: program.span,
3318 }
3319}
3320
3321#[doc(hidden)]
3335pub fn from_owned_program<'arena>(
3336 arena: &'arena bumpalo::Bump,
3337 program: &Program,
3338) -> arena_ast::Program<'arena, 'arena> {
3339 arena_ast::Program {
3340 stmts: av_stmts(arena, &program.stmts),
3341 span: program.span,
3342 }
3343}
3344
3345#[inline]
3347fn av_str<'a>(arena: &'a bumpalo::Bump, s: &str) -> &'a str {
3348 arena.alloc_str(s)
3349}
3350
3351fn av_ident<'a>(arena: &'a bumpalo::Bump, ident: &Ident) -> arena_ast::Ident<'a> {
3352 match ident.as_str() {
3353 Some(s) => arena_ast::Ident::new(arena.alloc_str(s), ident.span),
3354 None => arena_ast::Ident::error(ident.span),
3355 }
3356}
3357
3358fn av_name<'a>(arena: &'a bumpalo::Bump, name: &Name) -> arena_ast::Name<'a, 'a> {
3359 if name.kind == NameKind::Error {
3360 return arena_ast::Name::Error { span: name.span };
3361 }
3362 if name.parts.len() == 1 && name.kind == NameKind::Unqualified {
3363 return arena_ast::Name::Simple {
3364 value: arena.alloc_str(&name.parts[0]),
3365 span: name.span,
3366 };
3367 }
3368 let mut parts = arena_ast::ArenaVec::with_capacity_in(name.parts.len(), arena);
3369 for p in name.parts.iter() {
3370 parts.push(arena.alloc_str(p) as &str);
3371 }
3372 arena_ast::Name::Complex {
3373 parts,
3374 kind: name.kind,
3375 span: name.span,
3376 }
3377}
3378
3379fn av_type_hint<'a>(arena: &'a bumpalo::Bump, th: &TypeHint) -> arena_ast::TypeHint<'a, 'a> {
3380 arena_ast::TypeHint {
3381 kind: av_type_hint_kind(arena, &th.kind),
3382 span: th.span,
3383 }
3384}
3385
3386fn av_type_hint_kind<'a>(
3387 arena: &'a bumpalo::Bump,
3388 k: &TypeHintKind,
3389) -> arena_ast::TypeHintKind<'a, 'a> {
3390 match k {
3391 TypeHintKind::Named(n) => arena_ast::TypeHintKind::Named(av_name(arena, n)),
3392 TypeHintKind::Keyword(b, span) => arena_ast::TypeHintKind::Keyword(*b, *span),
3393 TypeHintKind::Nullable(inner) => {
3394 arena_ast::TypeHintKind::Nullable(arena.alloc(av_type_hint(arena, inner)))
3395 }
3396 TypeHintKind::Union(types) => {
3397 let mut v = arena_ast::ArenaVec::with_capacity_in(types.len(), arena);
3398 for t in types.iter() {
3399 v.push(av_type_hint(arena, t));
3400 }
3401 arena_ast::TypeHintKind::Union(v)
3402 }
3403 TypeHintKind::Intersection(types) => {
3404 let mut v = arena_ast::ArenaVec::with_capacity_in(types.len(), arena);
3405 for t in types.iter() {
3406 v.push(av_type_hint(arena, t));
3407 }
3408 arena_ast::TypeHintKind::Intersection(v)
3409 }
3410 }
3411}
3412
3413fn av_arg<'a>(arena: &'a bumpalo::Bump, arg: &Arg) -> arena_ast::Arg<'a, 'a> {
3414 arena_ast::Arg {
3415 name: arg.name.as_ref().map(|n| av_name(arena, n)),
3416 kind: match &arg.kind {
3417 ArgKind::Value(e) => arena_ast::ArgKind::Value(av_expr(arena, e)),
3418 ArgKind::Spread(e) => arena_ast::ArgKind::Spread(av_expr(arena, e)),
3419 ArgKind::ByRef(e) => arena_ast::ArgKind::ByRef(av_expr(arena, e)),
3420 ArgKind::Placeholder => arena_ast::ArgKind::Placeholder,
3421 ArgKind::SpreadPlaceholder => arena_ast::ArgKind::SpreadPlaceholder,
3422 },
3423 span: arg.span,
3424 }
3425}
3426
3427#[inline(never)]
3428fn av_args<'a>(
3429 arena: &'a bumpalo::Bump,
3430 args: &[Arg],
3431) -> arena_ast::ArenaVec<'a, arena_ast::Arg<'a, 'a>> {
3432 let mut v = arena_ast::ArenaVec::with_capacity_in(args.len(), arena);
3433 for a in args.iter() {
3434 v.push(av_arg(arena, a));
3435 }
3436 v
3437}
3438
3439fn av_attr<'a>(arena: &'a bumpalo::Bump, attr: &Attribute) -> arena_ast::Attribute<'a, 'a> {
3440 arena_ast::Attribute {
3441 name: av_name(arena, &attr.name),
3442 args: av_args(arena, &attr.args),
3443 span: attr.span,
3444 }
3445}
3446
3447#[inline(never)]
3448fn av_attrs<'a>(
3449 arena: &'a bumpalo::Bump,
3450 attrs: &[Attribute],
3451) -> arena_ast::ArenaVec<'a, arena_ast::Attribute<'a, 'a>> {
3452 let mut v = arena_ast::ArenaVec::with_capacity_in(attrs.len(), arena);
3453 for a in attrs.iter() {
3454 v.push(av_attr(arena, a));
3455 }
3456 v
3457}
3458
3459fn av_comment<'a>(arena: &'a bumpalo::Bump, c: &Comment) -> arena_ast::Comment<'a> {
3460 arena_ast::Comment {
3461 kind: c.kind,
3462 text: arena.alloc_str(&c.text),
3463 span: c.span,
3464 }
3465}
3466
3467fn av_opt_comment<'a>(
3468 arena: &'a bumpalo::Bump,
3469 c: &Option<Comment>,
3470) -> Option<arena_ast::Comment<'a>> {
3471 c.as_ref().map(|c| av_comment(arena, c))
3472}
3473
3474fn av_string_parts<'a>(
3475 arena: &'a bumpalo::Bump,
3476 parts: &[StringPart],
3477) -> arena_ast::ArenaVec<'a, arena_ast::StringPart<'a, 'a>> {
3478 let mut v = arena_ast::ArenaVec::with_capacity_in(parts.len(), arena);
3479 for p in parts.iter() {
3480 v.push(match p {
3481 StringPart::Literal(s) => {
3482 arena_ast::StringPart::Literal(arena_ast::ByteStr::new_in(arena, s.as_bytes()))
3483 }
3484 StringPart::Expr(e) => arena_ast::StringPart::Expr(av_expr(arena, e)),
3485 });
3486 }
3487 v
3488}
3489
3490fn av_expr<'a>(arena: &'a bumpalo::Bump, expr: &Expr) -> arena_ast::Expr<'a, 'a> {
3491 if !owned_is_chain(&expr.kind) {
3492 return arena_ast::Expr {
3493 kind: av_leaf_kind(arena, &expr.kind),
3494 span: expr.span,
3495 };
3496 }
3497 av_chain_expr(arena, expr)
3498}
3499
3500#[inline(never)]
3502fn av_chain_expr<'a>(arena: &'a bumpalo::Bump, expr: &Expr) -> arena_ast::Expr<'a, 'a> {
3503 let first = owned_chain_operand(&expr.kind).expect("chain link has an operand");
3504 if !owned_is_chain(&first.kind) {
3505 let operand = arena_ast::Expr {
3506 kind: av_leaf_kind(arena, &first.kind),
3507 span: first.span,
3508 };
3509 return arena_ast::Expr {
3510 kind: av_link_kind(arena, &expr.kind, operand),
3511 span: expr.span,
3512 };
3513 }
3514 let mut chain = LinkStack::new();
3515 chain.push(expr);
3516 let mut leaf = first;
3517 while let Some(operand) = owned_chain_operand(&leaf.kind) {
3518 chain.push(leaf);
3519 leaf = operand;
3520 }
3521 let mut converted = arena_ast::Expr {
3522 kind: av_leaf_kind(arena, &leaf.kind),
3523 span: leaf.span,
3524 };
3525 while let Some(node) = chain.pop() {
3526 converted = arena_ast::Expr {
3527 kind: av_link_kind(arena, &node.kind, converted),
3528 span: node.span,
3529 };
3530 }
3531 converted
3532}
3533
3534#[inline(never)]
3535fn av_exprs<'a>(
3536 arena: &'a bumpalo::Bump,
3537 exprs: &[Expr],
3538) -> arena_ast::ArenaVec<'a, arena_ast::Expr<'a, 'a>> {
3539 let mut v = arena_ast::ArenaVec::with_capacity_in(exprs.len(), arena);
3540 for e in exprs.iter() {
3541 v.push(av_expr(arena, e));
3542 }
3543 v
3544}
3545
3546fn av_namestr<'a>(arena: &'a bumpalo::Bump, s: &str) -> arena_ast::NameStr<'a, 'a> {
3547 arena_ast::NameStr::from_arena(arena.alloc_str(s))
3548}
3549
3550fn av_leaf_kind<'a>(arena: &'a bumpalo::Bump, k: &ExprKind) -> arena_ast::ExprKind<'a, 'a> {
3552 match k {
3553 ExprKind::Int(v) => arena_ast::ExprKind::Int(*v),
3554 ExprKind::Float(v) => arena_ast::ExprKind::Float(*v),
3555 ExprKind::String(s) => {
3556 arena_ast::ExprKind::String(arena_ast::ByteStr::new_in(arena, s.as_bytes()))
3557 }
3558 ExprKind::InterpolatedString(parts) => {
3559 arena_ast::ExprKind::InterpolatedString(av_string_parts(arena, parts))
3560 }
3561 ExprKind::Heredoc { label, parts } => arena_ast::ExprKind::Heredoc {
3562 label: arena.alloc_str(label),
3563 parts: av_string_parts(arena, parts),
3564 },
3565 ExprKind::Nowdoc { label, value } => arena_ast::ExprKind::Nowdoc {
3566 label: arena.alloc_str(label),
3567 value: arena.alloc_str(value),
3568 },
3569 ExprKind::ShellExec(parts) => arena_ast::ExprKind::ShellExec(av_string_parts(arena, parts)),
3570 ExprKind::Bool(v) => arena_ast::ExprKind::Bool(*v),
3571 ExprKind::Null => arena_ast::ExprKind::Null,
3572 ExprKind::Variable(s) => arena_ast::ExprKind::Variable(av_namestr(arena, s)),
3573 ExprKind::VariableVariable(inner) => {
3574 arena_ast::ExprKind::VariableVariable(arena.alloc(av_expr(arena, inner)))
3575 }
3576 ExprKind::Identifier(s) => arena_ast::ExprKind::Identifier(av_namestr(arena, s)),
3577 ExprKind::Name(name) => arena_ast::ExprKind::Name(av_name(arena, name)),
3578 ExprKind::Array(elems) => {
3579 let mut v = arena_ast::ArenaVec::with_capacity_in(elems.len(), arena);
3580 for e in elems.iter() {
3581 v.push(arena_ast::ArrayElement {
3582 key: e.key.as_ref().map(|k| av_expr(arena, k)),
3583 kind: match &e.kind {
3584 ArrayElementKind::Value(v) => {
3585 arena_ast::ArrayElementKind::Value(av_expr(arena, v))
3586 }
3587 ArrayElementKind::Spread(v) => {
3588 arena_ast::ArrayElementKind::Spread(av_expr(arena, v))
3589 }
3590 ArrayElementKind::ByRef(v) => {
3591 arena_ast::ArrayElementKind::ByRef(av_expr(arena, v))
3592 }
3593 },
3594 span: e.span,
3595 });
3596 }
3597 arena_ast::ExprKind::Array(v)
3598 }
3599 ExprKind::Print(e) => arena_ast::ExprKind::Print(arena.alloc(av_expr(arena, e))),
3600 ExprKind::Parenthesized(e) => {
3601 arena_ast::ExprKind::Parenthesized(arena.alloc(av_expr(arena, e)))
3602 }
3603 ExprKind::Cast(kind, e) => arena_ast::ExprKind::Cast(*kind, arena.alloc(av_expr(arena, e))),
3604 ExprKind::ErrorSuppress(e) => {
3605 arena_ast::ExprKind::ErrorSuppress(arena.alloc(av_expr(arena, e)))
3606 }
3607 ExprKind::Isset(exprs) => arena_ast::ExprKind::Isset(av_exprs(arena, exprs)),
3608 ExprKind::Empty(e) => arena_ast::ExprKind::Empty(arena.alloc(av_expr(arena, e))),
3609 ExprKind::Include(kind, e) => {
3610 arena_ast::ExprKind::Include(*kind, arena.alloc(av_expr(arena, e)))
3611 }
3612 ExprKind::Eval(e) => arena_ast::ExprKind::Eval(arena.alloc(av_expr(arena, e))),
3613 ExprKind::Exit(e) => {
3614 arena_ast::ExprKind::Exit(e.as_ref().map(|e| &*arena.alloc(av_expr(arena, e))))
3615 }
3616 ExprKind::MagicConst(m) => arena_ast::ExprKind::MagicConst(*m),
3617 ExprKind::Clone(e) => arena_ast::ExprKind::Clone(arena.alloc(av_expr(arena, e))),
3618 ExprKind::CloneWith(obj, props) => arena_ast::ExprKind::CloneWith(
3619 arena.alloc(av_expr(arena, obj)),
3620 arena.alloc(av_expr(arena, props)),
3621 ),
3622 ExprKind::New(n) => arena_ast::ExprKind::New(arena_ast::NewExpr {
3623 class: arena.alloc(av_expr(arena, &n.class)),
3624 args: av_args(arena, &n.args),
3625 }),
3626 ExprKind::Closure(c) => arena_ast::ExprKind::Closure(arena.alloc(arena_ast::ClosureExpr {
3627 is_static: c.is_static,
3628 by_ref: c.by_ref,
3629 params: av_params(arena, &c.params),
3630 missing_param_list: c.missing_param_list,
3631 use_vars: {
3632 let mut v = arena_ast::ArenaVec::with_capacity_in(c.use_vars.len(), arena);
3633 for uv in c.use_vars.iter() {
3634 v.push(arena_ast::ClosureUseVar {
3635 name: av_ident(arena, &uv.name),
3636 by_ref: uv.by_ref,
3637 span: uv.span,
3638 });
3639 }
3640 v
3641 },
3642 return_type: c.return_type.as_ref().map(|t| av_type_hint(arena, t)),
3643 body: &*arena.alloc(av_block(arena, &c.body)),
3644 attributes: av_attrs(arena, &c.attributes),
3645 })),
3646 ExprKind::ArrowFunction(f) => {
3647 arena_ast::ExprKind::ArrowFunction(arena.alloc(arena_ast::ArrowFunctionExpr {
3648 is_static: f.is_static,
3649 by_ref: f.by_ref,
3650 params: av_params(arena, &f.params),
3651 missing_param_list: f.missing_param_list,
3652 return_type: f.return_type.as_ref().map(|t| av_type_hint(arena, t)),
3653 body: arena.alloc(av_expr(arena, &f.body)),
3654 attributes: av_attrs(arena, &f.attributes),
3655 }))
3656 }
3657 ExprKind::Match(m) => arena_ast::ExprKind::Match(arena_ast::MatchExpr {
3658 subject: arena.alloc(av_expr(arena, &m.subject)),
3659 arms: {
3660 let mut v = arena_ast::ArenaVec::with_capacity_in(m.arms.len(), arena);
3661 for arm in m.arms.iter() {
3662 v.push(arena_ast::MatchArm {
3663 conditions: arm.conditions.as_ref().map(|conds| av_exprs(arena, conds)),
3664 body: av_expr(arena, &arm.body),
3665 span: arm.span,
3666 });
3667 }
3668 v
3669 },
3670 brace_span: m.brace_span,
3671 }),
3672 ExprKind::Throw(e) => arena_ast::ExprKind::Throw(arena.alloc(av_expr(arena, e))),
3673 ExprKind::Yield(y) => arena_ast::ExprKind::Yield(arena_ast::YieldExpr {
3674 key: y.key.as_ref().map(|e| &*arena.alloc(av_expr(arena, e))),
3675 value: y.value.as_ref().map(|e| &*arena.alloc(av_expr(arena, e))),
3676 is_from: y.is_from,
3677 }),
3678 ExprKind::AnonymousClass(cls) => {
3679 arena_ast::ExprKind::AnonymousClass(arena.alloc(av_class_decl(arena, cls)))
3680 }
3681 ExprKind::Omit => arena_ast::ExprKind::Omit,
3682 ExprKind::Error => arena_ast::ExprKind::Error,
3683 ExprKind::Assign(_)
3684 | ExprKind::Binary(_)
3685 | ExprKind::UnaryPrefix(_)
3686 | ExprKind::UnaryPostfix(_)
3687 | ExprKind::Ternary(_)
3688 | ExprKind::NullCoalesce(_)
3689 | ExprKind::FunctionCall(_)
3690 | ExprKind::ArrayAccess(_)
3691 | ExprKind::PropertyAccess(_)
3692 | ExprKind::NullsafePropertyAccess(_)
3693 | ExprKind::MethodCall(_)
3694 | ExprKind::NullsafeMethodCall(_)
3695 | ExprKind::StaticPropertyAccess(_)
3696 | ExprKind::ClassConstAccess(_)
3697 | ExprKind::StaticMethodCall(_)
3698 | ExprKind::StaticMethodCallDynamic(_)
3699 | ExprKind::ClassConstAccessDynamic { .. }
3700 | ExprKind::StaticPropertyAccessDynamic { .. }
3701 | ExprKind::CallableCreate(_) => {
3702 unreachable!("chain links are converted by the link function")
3703 }
3704 }
3705}
3706
3707fn av_link_kind<'a>(
3709 arena: &'a bumpalo::Bump,
3710 k: &ExprKind,
3711 operand: arena_ast::Expr<'a, 'a>,
3712) -> arena_ast::ExprKind<'a, 'a> {
3713 match k {
3714 ExprKind::Assign(a) => arena_ast::ExprKind::Assign(arena_ast::AssignExpr {
3715 target: arena.alloc(operand),
3716 op: a.op,
3717 value: arena.alloc(av_expr(arena, &a.value)),
3718 by_ref: a.by_ref,
3719 }),
3720 ExprKind::Binary(b) => arena_ast::ExprKind::Binary(arena_ast::BinaryExpr {
3721 left: arena.alloc(operand),
3722 op: b.op,
3723 right: arena.alloc(av_expr(arena, &b.right)),
3724 }),
3725 ExprKind::UnaryPrefix(u) => arena_ast::ExprKind::UnaryPrefix(arena_ast::UnaryPrefixExpr {
3726 op: u.op,
3727 operand: arena.alloc(operand),
3728 }),
3729 ExprKind::UnaryPostfix(u) => {
3730 arena_ast::ExprKind::UnaryPostfix(arena_ast::UnaryPostfixExpr {
3731 operand: arena.alloc(operand),
3732 op: u.op,
3733 })
3734 }
3735 ExprKind::Ternary(t) => arena_ast::ExprKind::Ternary(arena_ast::TernaryExpr {
3736 condition: arena.alloc(operand),
3737 then_expr: t
3738 .then_expr
3739 .as_ref()
3740 .map(|e| &*arena.alloc(av_expr(arena, e))),
3741 else_expr: arena.alloc(av_expr(arena, &t.else_expr)),
3742 }),
3743 ExprKind::NullCoalesce(n) => {
3744 arena_ast::ExprKind::NullCoalesce(arena_ast::NullCoalesceExpr {
3745 left: arena.alloc(operand),
3746 right: arena.alloc(av_expr(arena, &n.right)),
3747 })
3748 }
3749 ExprKind::FunctionCall(f) => {
3750 arena_ast::ExprKind::FunctionCall(arena_ast::FunctionCallExpr {
3751 name: arena.alloc(operand),
3752 args: av_args(arena, &f.args),
3753 })
3754 }
3755 ExprKind::ArrayAccess(a) => arena_ast::ExprKind::ArrayAccess(arena_ast::ArrayAccessExpr {
3756 array: arena.alloc(operand),
3757 index: a.index.as_ref().map(|e| &*arena.alloc(av_expr(arena, e))),
3758 }),
3759 ExprKind::PropertyAccess(p) => {
3760 arena_ast::ExprKind::PropertyAccess(arena_ast::PropertyAccessExpr {
3761 object: arena.alloc(operand),
3762 property: arena.alloc(av_expr(arena, &p.property)),
3763 })
3764 }
3765 ExprKind::NullsafePropertyAccess(p) => {
3766 arena_ast::ExprKind::NullsafePropertyAccess(arena_ast::PropertyAccessExpr {
3767 object: arena.alloc(operand),
3768 property: arena.alloc(av_expr(arena, &p.property)),
3769 })
3770 }
3771 ExprKind::MethodCall(m) => {
3772 arena_ast::ExprKind::MethodCall(arena.alloc(arena_ast::MethodCallExpr {
3773 object: arena.alloc(operand),
3774 method: arena.alloc(av_expr(arena, &m.method)),
3775 args: av_args(arena, &m.args),
3776 }))
3777 }
3778 ExprKind::NullsafeMethodCall(m) => {
3779 arena_ast::ExprKind::NullsafeMethodCall(arena.alloc(arena_ast::MethodCallExpr {
3780 object: arena.alloc(operand),
3781 method: arena.alloc(av_expr(arena, &m.method)),
3782 args: av_args(arena, &m.args),
3783 }))
3784 }
3785 ExprKind::StaticPropertyAccess(s) => {
3786 arena_ast::ExprKind::StaticPropertyAccess(arena_ast::StaticAccessExpr {
3787 class: arena.alloc(operand),
3788 member: arena.alloc(av_expr(arena, &s.member)),
3789 })
3790 }
3791 ExprKind::StaticMethodCall(s) => {
3792 arena_ast::ExprKind::StaticMethodCall(arena.alloc(arena_ast::StaticMethodCallExpr {
3793 class: arena.alloc(operand),
3794 method: arena.alloc(av_expr(arena, &s.method)),
3795 args: av_args(arena, &s.args),
3796 }))
3797 }
3798 ExprKind::StaticMethodCallDynamic(s) => arena_ast::ExprKind::StaticMethodCallDynamic(
3799 arena.alloc(arena_ast::StaticMethodCallDynamicExpr {
3800 class: arena.alloc(operand),
3801 method: arena.alloc(av_expr(arena, &s.method)),
3802 args: av_args(arena, &s.args),
3803 }),
3804 ),
3805 ExprKind::ClassConstAccess(s) => {
3806 arena_ast::ExprKind::ClassConstAccess(arena_ast::StaticAccessExpr {
3807 class: arena.alloc(operand),
3808 member: arena.alloc(av_expr(arena, &s.member)),
3809 })
3810 }
3811 ExprKind::ClassConstAccessDynamic { member, .. } => {
3812 arena_ast::ExprKind::ClassConstAccessDynamic {
3813 class: arena.alloc(operand),
3814 member: arena.alloc(av_expr(arena, member)),
3815 }
3816 }
3817 ExprKind::StaticPropertyAccessDynamic { member, .. } => {
3818 arena_ast::ExprKind::StaticPropertyAccessDynamic {
3819 class: arena.alloc(operand),
3820 member: arena.alloc(av_expr(arena, member)),
3821 }
3822 }
3823 ExprKind::CallableCreate(c) => {
3824 arena_ast::ExprKind::CallableCreate(arena_ast::CallableCreateExpr {
3825 kind: match &c.kind {
3826 CallableCreateKind::Function(_) => {
3827 arena_ast::CallableCreateKind::Function(arena.alloc(operand))
3828 }
3829 CallableCreateKind::Method { method, .. } => {
3830 arena_ast::CallableCreateKind::Method {
3831 object: arena.alloc(operand),
3832 method: arena.alloc(av_expr(arena, method)),
3833 }
3834 }
3835 CallableCreateKind::NullsafeMethod { method, .. } => {
3836 arena_ast::CallableCreateKind::NullsafeMethod {
3837 object: arena.alloc(operand),
3838 method: arena.alloc(av_expr(arena, method)),
3839 }
3840 }
3841 CallableCreateKind::StaticMethod { method, .. } => {
3842 arena_ast::CallableCreateKind::StaticMethod {
3843 class: arena.alloc(operand),
3844 method: arena.alloc(av_expr(arena, method)),
3845 }
3846 }
3847 },
3848 })
3849 }
3850 _ => unreachable!("not a chain link"),
3851 }
3852}
3853
3854fn av_param<'a>(arena: &'a bumpalo::Bump, p: &Param) -> arena_ast::Param<'a, 'a> {
3855 arena_ast::Param {
3856 name: av_ident(arena, &p.name),
3857 type_hint: p.type_hint.as_ref().map(|t| av_type_hint(arena, t)),
3858 default: p.default.as_ref().map(|e| av_expr(arena, e)),
3859 by_ref: p.by_ref,
3860 variadic: p.variadic,
3861 modifiers: p.modifiers,
3862 attributes: av_attrs(arena, &p.attributes),
3863 hooks: av_hooks(arena, &p.hooks),
3864 empty_hook_list: p.empty_hook_list,
3865 doc_comment: av_opt_comment(arena, &p.doc_comment),
3866 span: p.span,
3867 }
3868}
3869
3870#[inline(never)]
3871fn av_params<'a>(
3872 arena: &'a bumpalo::Bump,
3873 params: &[Param],
3874) -> arena_ast::ArenaVec<'a, arena_ast::Param<'a, 'a>> {
3875 let mut v = arena_ast::ArenaVec::with_capacity_in(params.len(), arena);
3876 for p in params.iter() {
3877 v.push(av_param(arena, p));
3878 }
3879 v
3880}
3881
3882fn av_hook<'a>(arena: &'a bumpalo::Bump, h: &PropertyHook) -> arena_ast::PropertyHook<'a, 'a> {
3883 arena_ast::PropertyHook {
3884 kind: h.kind,
3885 body: match &h.body {
3886 PropertyHookBody::Block(block) => {
3887 arena_ast::PropertyHookBody::Block(arena.alloc(av_block(arena, block)))
3888 }
3889 PropertyHookBody::Expression(e) => {
3890 arena_ast::PropertyHookBody::Expression(av_expr(arena, e))
3891 }
3892 PropertyHookBody::Abstract => arena_ast::PropertyHookBody::Abstract,
3893 },
3894 modifiers: h.modifiers,
3895 by_ref: h.by_ref,
3896 params: av_params(arena, &h.params),
3897 attributes: av_attrs(arena, &h.attributes),
3898 span: h.span,
3899 }
3900}
3901
3902fn av_hooks<'a>(
3903 arena: &'a bumpalo::Bump,
3904 hooks: &[PropertyHook],
3905) -> arena_ast::ArenaVec<'a, arena_ast::PropertyHook<'a, 'a>> {
3906 let mut v = arena_ast::ArenaVec::with_capacity_in(hooks.len(), arena);
3907 for h in hooks.iter() {
3908 v.push(av_hook(arena, h));
3909 }
3910 v
3911}
3912
3913fn av_stmt<'a>(arena: &'a bumpalo::Bump, stmt: &Stmt) -> arena_ast::Stmt<'a, 'a> {
3914 arena_ast::Stmt {
3915 kind: av_stmt_kind(arena, &stmt.kind),
3916 span: stmt.span,
3917 doc_comment: stmt.doc_comment.as_ref().map(|c| {
3918 &*arena.alloc(arena_ast::Comment {
3919 kind: c.kind,
3920 text: arena.alloc_str(&c.text),
3921 span: c.span,
3922 })
3923 }),
3924 }
3925}
3926
3927fn av_stmts<'a>(
3928 arena: &'a bumpalo::Bump,
3929 stmts: &[Stmt],
3930) -> arena_ast::ArenaVec<'a, arena_ast::Stmt<'a, 'a>> {
3931 let mut v = arena_ast::ArenaVec::with_capacity_in(stmts.len(), arena);
3932 for s in stmts.iter() {
3933 v.push(av_stmt(arena, s));
3934 }
3935 v
3936}
3937
3938fn av_block<'a>(arena: &'a bumpalo::Bump, block: &Block) -> arena_ast::Block<'a, 'a> {
3939 arena_ast::Block {
3940 stmts: av_stmts(arena, &block.stmts),
3941 span: block.span,
3942 }
3943}
3944
3945fn av_stmt_kind<'a>(arena: &'a bumpalo::Bump, k: &StmtKind) -> arena_ast::StmtKind<'a, 'a> {
3946 match k {
3947 StmtKind::Expression(e) => arena_ast::StmtKind::Expression(arena.alloc(av_expr(arena, e))),
3948 StmtKind::Echo(exprs) => arena_ast::StmtKind::Echo(av_exprs(arena, exprs)),
3949 StmtKind::Return(e) => {
3950 arena_ast::StmtKind::Return(e.as_ref().map(|e| &*arena.alloc(av_expr(arena, e))))
3951 }
3952 StmtKind::Block(block) => arena_ast::StmtKind::Block(arena.alloc(av_block(arena, block))),
3953 StmtKind::If(s) => arena_ast::StmtKind::If(arena.alloc(av_if_stmt(arena, s))),
3954 StmtKind::While(s) => arena_ast::StmtKind::While(arena.alloc(av_while_stmt(arena, s))),
3955 StmtKind::For(s) => arena_ast::StmtKind::For(arena.alloc(av_for_stmt(arena, s))),
3956 StmtKind::Foreach(s) => {
3957 arena_ast::StmtKind::Foreach(arena.alloc(av_foreach_stmt(arena, s)))
3958 }
3959 StmtKind::DoWhile(s) => {
3960 arena_ast::StmtKind::DoWhile(arena.alloc(av_do_while_stmt(arena, s)))
3961 }
3962 StmtKind::Function(f) => {
3963 arena_ast::StmtKind::Function(arena.alloc(av_function_decl(arena, f)))
3964 }
3965 StmtKind::Break(e) => {
3966 arena_ast::StmtKind::Break(e.as_ref().map(|e| &*arena.alloc(av_expr(arena, e))))
3967 }
3968 StmtKind::Continue(e) => {
3969 arena_ast::StmtKind::Continue(e.as_ref().map(|e| &*arena.alloc(av_expr(arena, e))))
3970 }
3971 StmtKind::Switch(s) => arena_ast::StmtKind::Switch(arena.alloc(av_switch_stmt(arena, s))),
3972 StmtKind::Goto(ident) => arena_ast::StmtKind::Goto(av_ident(arena, ident)),
3973 StmtKind::Label(ident) => arena_ast::StmtKind::Label(av_ident(arena, ident)),
3974 StmtKind::Declare(d) => {
3975 arena_ast::StmtKind::Declare(arena.alloc(av_declare_stmt(arena, d)))
3976 }
3977 StmtKind::Unset(exprs) => arena_ast::StmtKind::Unset(av_exprs(arena, exprs)),
3978 StmtKind::Throw(e) => arena_ast::StmtKind::Throw(arena.alloc(av_expr(arena, e))),
3979 StmtKind::TryCatch(t) => {
3980 arena_ast::StmtKind::TryCatch(arena.alloc(av_try_catch_stmt(arena, t)))
3981 }
3982 StmtKind::Global(exprs) => arena_ast::StmtKind::Global(av_exprs(arena, exprs)),
3983 StmtKind::Class(cls) => arena_ast::StmtKind::Class(arena.alloc(av_class_decl(arena, cls))),
3984 StmtKind::Interface(iface) => {
3985 arena_ast::StmtKind::Interface(arena.alloc(av_interface_decl(arena, iface)))
3986 }
3987 StmtKind::Trait(tr) => arena_ast::StmtKind::Trait(arena.alloc(av_trait_decl(arena, tr))),
3988 StmtKind::Enum(en) => arena_ast::StmtKind::Enum(arena.alloc(av_enum_decl(arena, en))),
3989 StmtKind::Namespace(ns) => {
3990 arena_ast::StmtKind::Namespace(arena.alloc(av_namespace_decl(arena, ns)))
3991 }
3992 StmtKind::Use(u) => arena_ast::StmtKind::Use(arena.alloc(av_use_decl(arena, u))),
3993 StmtKind::Const(items) => arena_ast::StmtKind::Const(av_const_items(arena, items)),
3994 StmtKind::StaticVar(vars) => arena_ast::StmtKind::StaticVar(av_static_vars(arena, vars)),
3995 StmtKind::HaltCompiler(s) => arena_ast::StmtKind::HaltCompiler(av_str(arena, s)),
3996 StmtKind::Nop => arena_ast::StmtKind::Nop,
3997 StmtKind::InlineHtml(s) => arena_ast::StmtKind::InlineHtml(av_str(arena, s)),
3998 StmtKind::Error => arena_ast::StmtKind::Error,
3999 }
4000}
4001
4002#[inline(never)]
4005fn av_if_stmt<'a>(arena: &'a bumpalo::Bump, s: &IfStmt) -> arena_ast::IfStmt<'a, 'a> {
4006 arena_ast::IfStmt {
4007 condition: av_expr(arena, &s.condition),
4008 then_branch: arena.alloc(av_stmt(arena, &s.then_branch)),
4009 elseif_branches: {
4010 let mut v = arena_ast::ArenaVec::with_capacity_in(s.elseif_branches.len(), arena);
4011 for b in s.elseif_branches.iter() {
4012 v.push(arena_ast::ElseIfBranch {
4013 condition: av_expr(arena, &b.condition),
4014 body: av_stmt(arena, &b.body),
4015 span: b.span,
4016 });
4017 }
4018 v
4019 },
4020 else_branch: s
4021 .else_branch
4022 .as_ref()
4023 .map(|b| &*arena.alloc(av_stmt(arena, b))),
4024 else_kw_span: s.else_kw_span,
4025 uses_alternative: s.uses_alternative,
4026 }
4027}
4028
4029#[inline(never)]
4030fn av_while_stmt<'a>(arena: &'a bumpalo::Bump, s: &WhileStmt) -> arena_ast::WhileStmt<'a, 'a> {
4031 arena_ast::WhileStmt {
4032 condition: av_expr(arena, &s.condition),
4033 body: arena.alloc(av_stmt(arena, &s.body)),
4034 uses_alternative: s.uses_alternative,
4035 }
4036}
4037
4038#[inline(never)]
4039fn av_for_stmt<'a>(arena: &'a bumpalo::Bump, s: &ForStmt) -> arena_ast::ForStmt<'a, 'a> {
4040 arena_ast::ForStmt {
4041 init: av_exprs(arena, &s.init),
4042 condition: av_exprs(arena, &s.condition),
4043 update: av_exprs(arena, &s.update),
4044 body: arena.alloc(av_stmt(arena, &s.body)),
4045 uses_alternative: s.uses_alternative,
4046 }
4047}
4048
4049#[inline(never)]
4050fn av_foreach_stmt<'a>(
4051 arena: &'a bumpalo::Bump,
4052 s: &ForeachStmt,
4053) -> arena_ast::ForeachStmt<'a, 'a> {
4054 arena_ast::ForeachStmt {
4055 expr: av_expr(arena, &s.expr),
4056 key: s.key.as_ref().map(|e| av_expr(arena, e)),
4057 value: av_expr(arena, &s.value),
4058 by_ref: s.by_ref,
4059 by_ref_span: s.by_ref_span,
4060 body: arena.alloc(av_stmt(arena, &s.body)),
4061 uses_alternative: s.uses_alternative,
4062 }
4063}
4064
4065#[inline(never)]
4066fn av_do_while_stmt<'a>(
4067 arena: &'a bumpalo::Bump,
4068 s: &DoWhileStmt,
4069) -> arena_ast::DoWhileStmt<'a, 'a> {
4070 arena_ast::DoWhileStmt {
4071 body: arena.alloc(av_stmt(arena, &s.body)),
4072 condition: av_expr(arena, &s.condition),
4073 }
4074}
4075
4076#[inline(never)]
4077fn av_switch_stmt<'a>(arena: &'a bumpalo::Bump, s: &SwitchStmt) -> arena_ast::SwitchStmt<'a, 'a> {
4078 arena_ast::SwitchStmt {
4079 expr: av_expr(arena, &s.expr),
4080 body: {
4081 let mut cases = arena_ast::ArenaVec::with_capacity_in(s.body.cases.len(), arena);
4082 for c in s.body.cases.iter() {
4083 cases.push(arena_ast::SwitchCase {
4084 value: c.value.as_ref().map(|vl| av_expr(arena, vl)),
4085 body: av_stmts(arena, &c.body),
4086 span: c.span,
4087 });
4088 }
4089 arena_ast::SwitchBody {
4090 cases,
4091 span: s.body.span,
4092 }
4093 },
4094 uses_alternative: s.uses_alternative,
4095 }
4096}
4097
4098#[inline(never)]
4099fn av_declare_stmt<'a>(
4100 arena: &'a bumpalo::Bump,
4101 d: &DeclareStmt,
4102) -> arena_ast::DeclareStmt<'a, 'a> {
4103 arena_ast::DeclareStmt {
4104 directives: {
4105 let mut v = arena_ast::ArenaVec::with_capacity_in(d.directives.len(), arena);
4106 for (k, val) in d.directives.iter() {
4107 v.push((arena.alloc_str(k) as &str, av_expr(arena, val)));
4108 }
4109 v
4110 },
4111 body: d.body.as_ref().map(|b| &*arena.alloc(av_stmt(arena, b))),
4112 uses_alternative: d.uses_alternative,
4113 }
4114}
4115
4116#[inline(never)]
4117fn av_try_catch_stmt<'a>(
4118 arena: &'a bumpalo::Bump,
4119 t: &TryCatchStmt,
4120) -> arena_ast::TryCatchStmt<'a, 'a> {
4121 arena_ast::TryCatchStmt {
4122 body: arena.alloc(av_block(arena, &t.body)),
4123 catches: {
4124 let mut v = arena_ast::ArenaVec::with_capacity_in(t.catches.len(), arena);
4125 for c in t.catches.iter() {
4126 let mut types = arena_ast::ArenaVec::with_capacity_in(c.types.len(), arena);
4127 for n in c.types.iter() {
4128 types.push(av_name(arena, n));
4129 }
4130 v.push(arena_ast::CatchClause {
4131 types,
4132 var: c.var.as_ref().map(|v| av_ident(arena, v)),
4133 body: arena.alloc(av_block(arena, &c.body)),
4134 span: c.span,
4135 });
4136 }
4137 v
4138 },
4139 finally: t
4140 .finally
4141 .as_deref()
4142 .map(|f| &*arena.alloc(av_block(arena, f))),
4143 finally_kw_span: t.finally_kw_span,
4144 }
4145}
4146
4147#[inline(never)]
4148fn av_namespace_decl<'a>(
4149 arena: &'a bumpalo::Bump,
4150 ns: &NamespaceDecl,
4151) -> arena_ast::NamespaceDecl<'a, 'a> {
4152 arena_ast::NamespaceDecl {
4153 name: ns.name.as_ref().map(|n| av_name(arena, n)),
4154 body: match &ns.body {
4155 NamespaceBody::Braced(block) => {
4156 arena_ast::NamespaceBody::Braced(&*arena.alloc(av_block(arena, block)))
4157 }
4158 NamespaceBody::Simple => arena_ast::NamespaceBody::Simple,
4159 },
4160 }
4161}
4162
4163#[inline(never)]
4164fn av_use_decl<'a>(arena: &'a bumpalo::Bump, u: &UseDecl) -> arena_ast::UseDecl<'a, 'a> {
4165 arena_ast::UseDecl {
4166 kind: u.kind,
4167 uses: {
4168 let mut v = arena_ast::ArenaVec::with_capacity_in(u.uses.len(), arena);
4169 for item in u.uses.iter() {
4170 v.push(arena_ast::UseItem {
4171 name: av_name(arena, &item.name),
4172 alias: item.alias.as_ref().map(|a| av_ident(arena, a)),
4173 kind: item.kind,
4174 span: item.span,
4175 });
4176 }
4177 v
4178 },
4179 }
4180}
4181
4182#[inline(never)]
4183fn av_const_items<'a>(
4184 arena: &'a bumpalo::Bump,
4185 items: &[ConstItem],
4186) -> arena_ast::ArenaVec<'a, arena_ast::ConstItem<'a, 'a>> {
4187 let mut v = arena_ast::ArenaVec::with_capacity_in(items.len(), arena);
4188 for item in items.iter() {
4189 v.push(arena_ast::ConstItem {
4190 name: av_ident(arena, &item.name),
4191 value: av_expr(arena, &item.value),
4192 attributes: av_attrs(arena, &item.attributes),
4193 span: item.span,
4194 doc_comment: av_opt_comment(arena, &item.doc_comment),
4195 });
4196 }
4197 v
4198}
4199
4200#[inline(never)]
4201fn av_static_vars<'a>(
4202 arena: &'a bumpalo::Bump,
4203 vars: &[StaticVar],
4204) -> arena_ast::ArenaVec<'a, arena_ast::StaticVar<'a, 'a>> {
4205 let mut v = arena_ast::ArenaVec::with_capacity_in(vars.len(), arena);
4206 for var in vars.iter() {
4207 v.push(arena_ast::StaticVar {
4208 name: av_ident(arena, &var.name),
4209 default: var.default.as_ref().map(|e| av_expr(arena, e)),
4210 span: var.span,
4211 });
4212 }
4213 v
4214}
4215
4216#[inline(never)]
4217fn av_function_decl<'a>(
4218 arena: &'a bumpalo::Bump,
4219 f: &FunctionDecl,
4220) -> arena_ast::FunctionDecl<'a, 'a> {
4221 arena_ast::FunctionDecl {
4222 name: av_ident(arena, &f.name),
4223 params: av_params(arena, &f.params),
4224 missing_param_list: f.missing_param_list,
4225 body: &*arena.alloc(av_block(arena, &f.body)),
4226 return_type: f.return_type.as_ref().map(|t| av_type_hint(arena, t)),
4227 by_ref: f.by_ref,
4228 attributes: av_attrs(arena, &f.attributes),
4229 doc_comment: av_opt_comment(arena, &f.doc_comment),
4230 }
4231}
4232
4233fn av_property<'a>(arena: &'a bumpalo::Bump, p: &PropertyDecl) -> arena_ast::PropertyDecl<'a, 'a> {
4234 arena_ast::PropertyDecl {
4235 name: av_ident(arena, &p.name),
4236 modifiers: p.modifiers,
4237 type_hint: p.type_hint.as_ref().map(|t| av_type_hint(arena, t)),
4238 default: p.default.as_ref().map(|e| av_expr(arena, e)),
4239 attributes: av_attrs(arena, &p.attributes),
4240 hooks: av_hooks(arena, &p.hooks),
4241 empty_hook_list: p.empty_hook_list,
4242 doc_comment: av_opt_comment(arena, &p.doc_comment),
4243 }
4244}
4245
4246fn av_class_member<'a>(
4247 arena: &'a bumpalo::Bump,
4248 m: &ClassMember,
4249) -> arena_ast::ClassMember<'a, 'a> {
4250 arena_ast::ClassMember {
4251 kind: match &m.kind {
4252 ClassMemberKind::Property(p) => {
4253 arena_ast::ClassMemberKind::Property(av_property(arena, p))
4254 }
4255 ClassMemberKind::Method(m) => {
4256 arena_ast::ClassMemberKind::Method(arena_ast::MethodDecl {
4257 name: av_ident(arena, &m.name),
4258 modifiers: m.modifiers,
4259 by_ref: m.by_ref,
4260 params: av_params(arena, &m.params),
4261 missing_param_list: m.missing_param_list,
4262 return_type: m.return_type.as_ref().map(|t| av_type_hint(arena, t)),
4263 body: m.body.as_deref().map(|b| &*arena.alloc(av_block(arena, b))),
4264 attributes: av_attrs(arena, &m.attributes),
4265 doc_comment: av_opt_comment(arena, &m.doc_comment),
4266 })
4267 }
4268 ClassMemberKind::ClassConst(c) => {
4269 arena_ast::ClassMemberKind::ClassConst(av_class_const(arena, c))
4270 }
4271 ClassMemberKind::TraitUse(t) => {
4272 arena_ast::ClassMemberKind::TraitUse(av_trait_use(arena, t))
4273 }
4274 },
4275 span: m.span,
4276 }
4277}
4278
4279fn av_class_members<'a>(
4280 arena: &'a bumpalo::Bump,
4281 members: &[ClassMember],
4282) -> arena_ast::ArenaVec<'a, arena_ast::ClassMember<'a, 'a>> {
4283 let mut v = arena_ast::ArenaVec::with_capacity_in(members.len(), arena);
4284 for m in members.iter() {
4285 v.push(av_class_member(arena, m));
4286 }
4287 v
4288}
4289
4290fn av_class_const<'a>(
4291 arena: &'a bumpalo::Bump,
4292 c: &ClassConstDecl,
4293) -> arena_ast::ClassConstDecl<'a, 'a> {
4294 arena_ast::ClassConstDecl {
4295 name: av_ident(arena, &c.name),
4296 modifiers: c.modifiers,
4297 type_hint: c
4298 .type_hint
4299 .as_ref()
4300 .map(|th| arena.alloc(av_type_hint(arena, th)) as &_),
4301 value: av_expr(arena, &c.value),
4302 attributes: av_attrs(arena, &c.attributes),
4303 doc_comment: av_opt_comment(arena, &c.doc_comment),
4304 }
4305}
4306
4307fn av_trait_use<'a>(arena: &'a bumpalo::Bump, t: &TraitUseDecl) -> arena_ast::TraitUseDecl<'a, 'a> {
4308 let mut traits = arena_ast::ArenaVec::with_capacity_in(t.traits.len(), arena);
4309 for n in t.traits.iter() {
4310 traits.push(av_name(arena, n));
4311 }
4312 let mut adaptations = arena_ast::ArenaVec::with_capacity_in(t.adaptations.len(), arena);
4313 for a in t.adaptations.iter() {
4314 adaptations.push(arena_ast::TraitAdaptation {
4315 kind: match &a.kind {
4316 TraitAdaptationKind::Precedence {
4317 trait_name,
4318 method,
4319 insteadof,
4320 } => {
4321 let mut instead = arena_ast::ArenaVec::with_capacity_in(insteadof.len(), arena);
4322 for n in insteadof.iter() {
4323 instead.push(av_name(arena, n));
4324 }
4325 arena_ast::TraitAdaptationKind::Precedence {
4326 trait_name: av_name(arena, trait_name),
4327 method: av_name(arena, method),
4328 insteadof: instead,
4329 }
4330 }
4331 TraitAdaptationKind::Alias {
4332 trait_name,
4333 method,
4334 new_modifier,
4335 is_final,
4336 new_name,
4337 } => arena_ast::TraitAdaptationKind::Alias {
4338 trait_name: trait_name.as_ref().map(|n| av_name(arena, n)),
4339 method: av_name(arena, method),
4340 new_modifier: *new_modifier,
4341 is_final: *is_final,
4342 new_name: new_name.as_ref().map(|n| av_name(arena, n)),
4343 },
4344 },
4345 span: a.span,
4346 });
4347 }
4348 arena_ast::TraitUseDecl {
4349 traits,
4350 adaptations,
4351 adaptations_brace_span: t.adaptations_brace_span,
4352 doc_comment: av_opt_comment(arena, &t.doc_comment),
4353 }
4354}
4355
4356fn av_class_decl<'a>(arena: &'a bumpalo::Bump, cls: &ClassDecl) -> arena_ast::ClassDecl<'a, 'a> {
4357 let mut implements = arena_ast::ArenaVec::with_capacity_in(cls.implements.len(), arena);
4358 for n in cls.implements.iter() {
4359 implements.push(av_name(arena, n));
4360 }
4361 arena_ast::ClassDecl {
4362 name: cls.name.as_ref().map(|ident| av_ident(arena, ident)),
4363 modifiers: cls.modifiers.clone(),
4364 extends: cls.extends.as_ref().map(|n| av_name(arena, n)),
4365 implements,
4366 body: arena_ast::ClassBody {
4367 members: av_class_members(arena, &cls.body.members),
4368 span: cls.body.span,
4369 },
4370 attributes: av_attrs(arena, &cls.attributes),
4371 doc_comment: av_opt_comment(arena, &cls.doc_comment),
4372 }
4373}
4374
4375#[inline(never)]
4376fn av_interface_decl<'a>(
4377 arena: &'a bumpalo::Bump,
4378 iface: &InterfaceDecl,
4379) -> arena_ast::InterfaceDecl<'a, 'a> {
4380 let mut extends = arena_ast::ArenaVec::with_capacity_in(iface.extends.len(), arena);
4381 for n in iface.extends.iter() {
4382 extends.push(av_name(arena, n));
4383 }
4384 arena_ast::InterfaceDecl {
4385 name: av_ident(arena, &iface.name),
4386 extends,
4387 body: arena_ast::ClassBody {
4388 members: av_class_members(arena, &iface.body.members),
4389 span: iface.body.span,
4390 },
4391 attributes: av_attrs(arena, &iface.attributes),
4392 doc_comment: av_opt_comment(arena, &iface.doc_comment),
4393 }
4394}
4395
4396#[inline(never)]
4397fn av_trait_decl<'a>(arena: &'a bumpalo::Bump, tr: &TraitDecl) -> arena_ast::TraitDecl<'a, 'a> {
4398 arena_ast::TraitDecl {
4399 name: av_ident(arena, &tr.name),
4400 body: arena_ast::ClassBody {
4401 members: av_class_members(arena, &tr.body.members),
4402 span: tr.body.span,
4403 },
4404 attributes: av_attrs(arena, &tr.attributes),
4405 doc_comment: av_opt_comment(arena, &tr.doc_comment),
4406 }
4407}
4408
4409#[inline(never)]
4410fn av_enum_decl<'a>(arena: &'a bumpalo::Bump, en: &EnumDecl) -> arena_ast::EnumDecl<'a, 'a> {
4411 let mut implements = arena_ast::ArenaVec::with_capacity_in(en.implements.len(), arena);
4412 for n in en.implements.iter() {
4413 implements.push(av_name(arena, n));
4414 }
4415 let mut members = arena_ast::ArenaVec::with_capacity_in(en.body.members.len(), arena);
4416 for m in en.body.members.iter() {
4417 members.push(arena_ast::EnumMember {
4418 kind: match &m.kind {
4419 EnumMemberKind::Case(c) => arena_ast::EnumMemberKind::Case(arena_ast::EnumCase {
4420 name: av_ident(arena, &c.name),
4421 value: c.value.as_ref().map(|e| av_expr(arena, e)),
4422 attributes: av_attrs(arena, &c.attributes),
4423 doc_comment: av_opt_comment(arena, &c.doc_comment),
4424 }),
4425 EnumMemberKind::Method(m) => {
4426 arena_ast::EnumMemberKind::Method(arena_ast::MethodDecl {
4427 name: av_ident(arena, &m.name),
4428 modifiers: m.modifiers,
4429 by_ref: m.by_ref,
4430 params: av_params(arena, &m.params),
4431 missing_param_list: m.missing_param_list,
4432 return_type: m.return_type.as_ref().map(|t| av_type_hint(arena, t)),
4433 body: m.body.as_deref().map(|b| &*arena.alloc(av_block(arena, b))),
4434 attributes: av_attrs(arena, &m.attributes),
4435 doc_comment: av_opt_comment(arena, &m.doc_comment),
4436 })
4437 }
4438 EnumMemberKind::ClassConst(c) => {
4439 arena_ast::EnumMemberKind::ClassConst(av_class_const(arena, c))
4440 }
4441 EnumMemberKind::TraitUse(t) => {
4442 arena_ast::EnumMemberKind::TraitUse(av_trait_use(arena, t))
4443 }
4444 EnumMemberKind::Property(p) => {
4445 arena_ast::EnumMemberKind::Property(av_property(arena, p))
4446 }
4447 },
4448 span: m.span,
4449 });
4450 }
4451 arena_ast::EnumDecl {
4452 name: av_ident(arena, &en.name),
4453 scalar_type: en.scalar_type.as_ref().map(|n| av_name(arena, n)),
4454 implements,
4455 body: arena_ast::EnumBody {
4456 members,
4457 span: en.body.span,
4458 },
4459 attributes: av_attrs(arena, &en.attributes),
4460 doc_comment: av_opt_comment(arena, &en.doc_comment),
4461 }
4462}