1pub mod fold;
21pub mod visitor;
22
23pub use fold::{
24 fold_owned_arg, fold_owned_attribute, fold_owned_catch_clause, fold_owned_class_member,
25 fold_owned_closure_use_var, fold_owned_enum_member, fold_owned_expr, fold_owned_match_arm,
26 fold_owned_name, fold_owned_param, fold_owned_program, fold_owned_property_hook,
27 fold_owned_stmt, fold_owned_type_hint, FoldOwned,
28};
29pub use visitor::{
30 walk_owned_arg, walk_owned_attribute, walk_owned_catch_clause, walk_owned_class_member,
31 walk_owned_comments, walk_owned_enum_member, walk_owned_expr, walk_owned_match_arm,
32 walk_owned_name, walk_owned_param, walk_owned_program, walk_owned_property_hook,
33 walk_owned_stmt, walk_owned_trait_use, walk_owned_type_hint, OwnedScope, OwnedScopeVisitor,
34 OwnedScopeWalker, OwnedVisitor,
35};
36
37use serde::Serialize;
38
39use crate::ast as arena_ast;
40use crate::ast::{
41 AssignOp, BinaryOp, BuiltinType, CastKind, ClassModifiers, CommentKind, IncludeKind,
42 MagicConstKind, NameKind, PropertyHookKind, UnaryPostfixOp, UnaryPrefixOp, UseKind, Visibility,
43};
44use crate::Span;
45
46fn is_false(b: &bool) -> bool {
51 !*b
52}
53
54fn slice_is_empty<T>(v: &[T]) -> bool {
55 v.is_empty()
56}
57
58pub type Ident = Option<Box<str>>;
70
71#[derive(Debug, Clone, Serialize)]
82pub struct Name {
83 pub parts: Box<[Box<str>]>,
85 pub kind: NameKind,
87 pub span: Span,
89}
90
91#[derive(Debug, Clone, Serialize)]
97pub struct Comment {
98 pub kind: CommentKind,
100 pub text: Box<str>,
102 pub span: Span,
104}
105
106#[derive(Debug, Clone, Serialize)]
115pub struct TypeHint {
116 pub kind: TypeHintKind,
118 pub span: Span,
120}
121
122#[derive(Debug, Clone)]
124pub enum TypeHintKind {
125 Named(Name),
127 Keyword(BuiltinType, Span),
129 Nullable(Box<TypeHint>),
131 Union(Box<[TypeHint]>),
133 Intersection(Box<[TypeHint]>),
135}
136
137impl Serialize for TypeHintKind {
138 fn serialize<S: serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
139 match self {
140 Self::Named(name) => s.serialize_newtype_variant("TypeHintKind", 0, "Named", name),
141 Self::Nullable(inner) => {
142 s.serialize_newtype_variant("TypeHintKind", 2, "Nullable", inner)
143 }
144 Self::Union(types) => s.serialize_newtype_variant("TypeHintKind", 3, "Union", types),
145 Self::Intersection(types) => {
146 s.serialize_newtype_variant("TypeHintKind", 4, "Intersection", types)
147 }
148 Self::Keyword(builtin, span) => {
149 struct BuiltinNameRepr<'a>(&'a BuiltinType, &'a Span);
150 impl Serialize for BuiltinNameRepr<'_> {
151 fn serialize<S: serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
152 use serde::ser::SerializeStruct;
153 let mut st = s.serialize_struct("Name", 3)?;
154 st.serialize_field("parts", &[self.0.as_str()])?;
155 st.serialize_field("kind", &NameKind::Unqualified)?;
156 st.serialize_field("span", self.1)?;
157 st.end()
158 }
159 }
160 s.serialize_newtype_variant(
161 "TypeHintKind",
162 0,
163 "Named",
164 &BuiltinNameRepr(builtin, span),
165 )
166 }
167 }
168 }
169}
170
171#[derive(Debug, Clone, Serialize)]
177pub struct Arg {
178 pub name: Option<Name>,
180 pub value: Option<Expr>,
182 pub unpack: bool,
184 pub by_ref: bool,
186 pub span: Span,
188}
189
190#[derive(Debug, Clone, Serialize)]
192pub struct Attribute {
193 pub name: Name,
195 pub args: Box<[Arg]>,
197 pub span: Span,
199}
200
201#[derive(Debug, Clone, Serialize)]
207pub struct Program {
208 pub stmts: Box<[Stmt]>,
210 pub span: Span,
212}
213
214#[derive(Debug, Clone, Serialize)]
220pub struct Stmt {
221 pub kind: StmtKind,
223 pub span: Span,
225 #[serde(skip_serializing_if = "Option::is_none")]
227 pub doc_comment: Option<Comment>,
228}
229
230impl Stmt {
231 pub fn leading_doc_comment(&self) -> Option<&Comment> {
235 if let Some(doc) = &self.doc_comment {
236 return Some(doc);
237 }
238 match &self.kind {
239 StmtKind::Function(f) => f.doc_comment.as_ref(),
240 StmtKind::Class(c) => c.doc_comment.as_ref(),
241 StmtKind::Interface(i) => i.doc_comment.as_ref(),
242 StmtKind::Trait(t) => t.doc_comment.as_ref(),
243 StmtKind::Enum(e) => e.doc_comment.as_ref(),
244 StmtKind::Const(items) => items.first().and_then(|i| i.doc_comment.as_ref()),
245 _ => None,
246 }
247 }
248}
249
250#[derive(Debug, Clone, Serialize)]
252#[serde(transparent)]
253pub struct Block {
254 pub stmts: Box<[Stmt]>,
256 #[serde(skip)]
258 pub span: Span,
259}
260
261#[derive(Debug, Clone, Serialize)]
263pub enum StmtKind {
264 Expression(Box<Expr>),
266 Echo(Box<[Expr]>),
268 Return(Option<Box<Expr>>),
270 Block(Box<Block>),
272 If(Box<IfStmt>),
274 While(Box<WhileStmt>),
276 For(Box<ForStmt>),
278 Foreach(Box<ForeachStmt>),
280 DoWhile(Box<DoWhileStmt>),
282 Function(Box<FunctionDecl>),
284 Break(Option<Box<Expr>>),
286 Continue(Option<Box<Expr>>),
288 Switch(Box<SwitchStmt>),
290 Goto(Ident),
292 Label(Box<str>),
294 Declare(Box<DeclareStmt>),
296 Unset(Box<[Expr]>),
298 Throw(Box<Expr>),
300 TryCatch(Box<TryCatchStmt>),
302 Global(Box<[Expr]>),
304 Class(Box<ClassDecl>),
306 Interface(Box<InterfaceDecl>),
308 Trait(Box<TraitDecl>),
310 Enum(Box<EnumDecl>),
312 Namespace(Box<NamespaceDecl>),
314 Use(Box<UseDecl>),
316 Const(Box<[ConstItem]>),
318 StaticVar(Box<[StaticVar]>),
320 HaltCompiler(Box<str>),
322 Nop,
324 InlineHtml(Box<str>),
326 Error,
328}
329
330#[derive(Debug, Clone, Serialize)]
332pub struct IfStmt {
333 pub condition: Expr,
335 pub then_branch: Box<Stmt>,
337 pub elseif_branches: Box<[ElseIfBranch]>,
339 pub else_branch: Option<Box<Stmt>>,
341 #[serde(skip)]
343 pub else_kw_start: Option<u32>,
344 #[serde(default, skip_serializing_if = "is_false")]
346 pub uses_alternative: bool,
347}
348
349#[derive(Debug, Clone, Serialize)]
351pub struct ElseIfBranch {
352 pub condition: Expr,
354 pub body: Stmt,
356 pub span: Span,
358}
359
360#[derive(Debug, Clone, Serialize)]
362pub struct WhileStmt {
363 pub condition: Expr,
365 pub body: Box<Stmt>,
367 #[serde(default, skip_serializing_if = "is_false")]
369 pub uses_alternative: bool,
370}
371
372#[derive(Debug, Clone, Serialize)]
374pub struct ForStmt {
375 pub init: Box<[Expr]>,
377 pub condition: Box<[Expr]>,
379 pub update: Box<[Expr]>,
381 pub body: Box<Stmt>,
383 #[serde(default, skip_serializing_if = "is_false")]
385 pub uses_alternative: bool,
386}
387
388#[derive(Debug, Clone, Serialize)]
390pub struct ForeachStmt {
391 pub expr: Expr,
393 pub key: Option<Expr>,
395 pub value: Expr,
397 pub body: Box<Stmt>,
399 #[serde(default, skip_serializing_if = "is_false")]
401 pub uses_alternative: bool,
402}
403
404#[derive(Debug, Clone, Serialize)]
406pub struct DoWhileStmt {
407 pub body: Box<Stmt>,
409 pub condition: Expr,
411}
412
413#[derive(Debug, Clone, Serialize)]
415pub struct SwitchBody {
416 pub cases: Box<[SwitchCase]>,
418 #[serde(skip)]
420 pub span: Span,
421}
422
423#[derive(Debug, Clone, Serialize)]
425pub struct SwitchStmt {
426 pub expr: Expr,
428 #[serde(flatten)]
430 pub body: SwitchBody,
431 #[serde(default, skip_serializing_if = "is_false")]
433 pub uses_alternative: bool,
434}
435
436#[derive(Debug, Clone, Serialize)]
438pub struct SwitchCase {
439 pub value: Option<Expr>,
441 pub body: Box<[Stmt]>,
443 pub span: Span,
445}
446
447#[derive(Debug, Clone, Serialize)]
449pub struct TryCatchStmt {
450 pub body: Box<Block>,
452 pub catches: Box<[CatchClause]>,
454 pub finally: Option<Box<Block>>,
456 #[serde(skip)]
458 pub finally_kw_start: Option<u32>,
459}
460
461#[derive(Debug, Clone, Serialize)]
463pub struct CatchClause {
464 pub types: Box<[Name]>,
466 pub var: Option<Box<str>>,
468 pub body: Box<Block>,
470 pub span: Span,
472}
473
474#[derive(Debug, Clone, Serialize)]
476pub struct NamespaceDecl {
477 pub name: Option<Name>,
479 pub body: NamespaceBody,
481}
482
483#[derive(Debug, Clone, Serialize)]
485pub enum NamespaceBody {
486 Braced(Box<Block>),
488 Simple,
490}
491
492#[derive(Debug, Clone, Serialize)]
494pub struct DeclareStmt {
495 pub directives: Box<[(Box<str>, Expr)]>,
497 pub body: Option<Box<Stmt>>,
499 #[serde(default, skip_serializing_if = "is_false")]
501 pub uses_alternative: bool,
502}
503
504#[derive(Debug, Clone, Serialize)]
506pub struct UseDecl {
507 pub kind: UseKind,
509 pub uses: Box<[UseItem]>,
511}
512
513#[derive(Debug, Clone, Serialize)]
515pub struct UseItem {
516 pub name: Name,
518 pub alias: Option<Box<str>>,
520 #[serde(skip_serializing_if = "Option::is_none")]
522 pub kind: Option<UseKind>,
523 pub span: Span,
525}
526
527#[derive(Debug, Clone, Serialize)]
529pub struct ConstItem {
530 pub name: Ident,
532 pub value: Expr,
534 pub attributes: Box<[Attribute]>,
536 pub span: Span,
538 #[serde(skip_serializing_if = "Option::is_none")]
540 pub doc_comment: Option<Comment>,
541}
542
543#[derive(Debug, Clone, Serialize)]
545pub struct StaticVar {
546 pub name: Ident,
548 pub default: Option<Expr>,
550 pub span: Span,
552}
553
554#[derive(Debug, Clone, Serialize)]
560pub struct Expr {
561 pub kind: ExprKind,
563 pub span: Span,
565}
566
567#[derive(Debug, Clone, Serialize)]
569pub enum ExprKind {
570 Int(i64),
572 Float(f64),
574 String(Box<str>),
576 InterpolatedString(Box<[StringPart]>),
578 Heredoc {
580 label: Box<str>,
582 parts: Box<[StringPart]>,
584 },
585 Nowdoc {
587 label: Box<str>,
589 value: Box<str>,
591 },
592 ShellExec(Box<[StringPart]>),
594 Bool(bool),
596 Null,
598 Variable(Box<str>),
600 VariableVariable(Box<Expr>),
602 Identifier(Box<str>),
604 Assign(AssignExpr),
606 Binary(BinaryExpr),
608 UnaryPrefix(UnaryPrefixExpr),
610 UnaryPostfix(UnaryPostfixExpr),
612 Ternary(TernaryExpr),
614 NullCoalesce(NullCoalesceExpr),
616 FunctionCall(FunctionCallExpr),
618 Array(Box<[ArrayElement]>),
620 ArrayAccess(ArrayAccessExpr),
622 Print(Box<Expr>),
624 Parenthesized(Box<Expr>),
626 Cast(CastKind, Box<Expr>),
628 ErrorSuppress(Box<Expr>),
630 Isset(Box<[Expr]>),
632 Empty(Box<Expr>),
634 Include(IncludeKind, Box<Expr>),
636 Eval(Box<Expr>),
638 Exit(Option<Box<Expr>>),
640 MagicConst(MagicConstKind),
642 Clone(Box<Expr>),
644 CloneWith(Box<Expr>, Box<Expr>),
646 New(NewExpr),
648 PropertyAccess(PropertyAccessExpr),
650 NullsafePropertyAccess(PropertyAccessExpr),
652 MethodCall(Box<MethodCallExpr>),
654 NullsafeMethodCall(Box<MethodCallExpr>),
656 StaticPropertyAccess(StaticAccessExpr),
658 StaticMethodCall(Box<StaticMethodCallExpr>),
660 StaticDynMethodCall(Box<StaticDynMethodCallExpr>),
662 ClassConstAccess(StaticAccessExpr),
664 ClassConstAccessDynamic {
666 class: Box<Expr>,
668 member: Box<Expr>,
670 },
671 StaticPropertyAccessDynamic {
673 class: Box<Expr>,
675 member: Box<Expr>,
677 },
678 Closure(Box<ClosureExpr>),
680 ArrowFunction(Box<ArrowFunctionExpr>),
682 Match(MatchExpr),
684 ThrowExpr(Box<Expr>),
686 Yield(YieldExpr),
688 AnonymousClass(Box<ClassDecl>),
690 CallableCreate(CallableCreateExpr),
692 Omit,
694 Error,
696}
697
698#[derive(Debug, Clone, Serialize)]
700pub struct AssignExpr {
701 pub target: Box<Expr>,
703 pub op: AssignOp,
705 pub value: Box<Expr>,
707 #[serde(skip_serializing_if = "is_false")]
709 pub by_ref: bool,
710}
711
712#[derive(Debug, Clone, Serialize)]
714pub struct BinaryExpr {
715 pub left: Box<Expr>,
717 pub op: BinaryOp,
719 pub right: Box<Expr>,
721}
722
723#[derive(Debug, Clone, Serialize)]
725pub struct UnaryPrefixExpr {
726 pub op: UnaryPrefixOp,
728 pub operand: Box<Expr>,
730}
731
732#[derive(Debug, Clone, Serialize)]
734pub struct UnaryPostfixExpr {
735 pub operand: Box<Expr>,
737 pub op: UnaryPostfixOp,
739}
740
741#[derive(Debug, Clone, Serialize)]
743pub struct TernaryExpr {
744 pub condition: Box<Expr>,
746 pub then_expr: Option<Box<Expr>>,
748 pub else_expr: Box<Expr>,
750}
751
752#[derive(Debug, Clone, Serialize)]
754pub struct NullCoalesceExpr {
755 pub left: Box<Expr>,
757 pub right: Box<Expr>,
759}
760
761#[derive(Debug, Clone, Serialize)]
763pub struct FunctionCallExpr {
764 pub name: Box<Expr>,
766 pub args: Box<[Arg]>,
768}
769
770#[derive(Debug, Clone, Serialize)]
772pub struct ArrayElement {
773 pub key: Option<Expr>,
775 pub value: Expr,
777 pub unpack: bool,
779 #[serde(skip_serializing_if = "is_false")]
781 pub by_ref: bool,
782 pub span: Span,
784}
785
786#[derive(Debug, Clone, Serialize)]
788pub struct ArrayAccessExpr {
789 pub array: Box<Expr>,
791 pub index: Option<Box<Expr>>,
793}
794
795#[derive(Debug, Clone, Serialize)]
797pub struct NewExpr {
798 pub class: Box<Expr>,
800 pub args: Box<[Arg]>,
802}
803
804#[derive(Debug, Clone, Serialize)]
806pub struct PropertyAccessExpr {
807 pub object: Box<Expr>,
809 pub property: Box<Expr>,
811}
812
813#[derive(Debug, Clone, Serialize)]
815pub struct MethodCallExpr {
816 pub object: Box<Expr>,
818 pub method: Box<Expr>,
820 pub args: Box<[Arg]>,
822}
823
824#[derive(Debug, Clone, Serialize)]
826pub struct StaticAccessExpr {
827 pub class: Box<Expr>,
829 pub member: Box<Expr>,
831}
832
833#[derive(Debug, Clone, Serialize)]
835pub struct StaticMethodCallExpr {
836 pub class: Box<Expr>,
838 pub method: Box<Expr>,
840 pub args: Box<[Arg]>,
842}
843
844#[derive(Debug, Clone, Serialize)]
846pub struct StaticDynMethodCallExpr {
847 pub class: Box<Expr>,
849 pub method: Box<Expr>,
851 pub args: Box<[Arg]>,
853}
854
855#[derive(Debug, Clone, Serialize)]
857pub struct ClosureExpr {
858 pub is_static: bool,
860 pub by_ref: bool,
862 pub params: Box<[Param]>,
864 pub use_vars: Box<[ClosureUseVar]>,
866 pub return_type: Option<TypeHint>,
868 pub body: Box<Block>,
870 pub attributes: Box<[Attribute]>,
872}
873
874#[derive(Debug, Clone, Serialize)]
876pub struct ClosureUseVar {
877 pub name: Box<str>,
879 pub by_ref: bool,
881 pub span: Span,
883}
884
885#[derive(Debug, Clone, Serialize)]
887pub struct ArrowFunctionExpr {
888 pub is_static: bool,
890 pub by_ref: bool,
892 pub params: Box<[Param]>,
894 pub return_type: Option<TypeHint>,
896 pub body: Box<Expr>,
898 pub attributes: Box<[Attribute]>,
900}
901
902#[derive(Debug, Clone, Serialize)]
904pub struct MatchExpr {
905 pub subject: Box<Expr>,
907 pub arms: Box<[MatchArm]>,
909 #[serde(skip)]
911 pub brace_start: u32,
912}
913
914#[derive(Debug, Clone, Serialize)]
916pub struct MatchArm {
917 pub conditions: Option<Box<[Expr]>>,
919 pub body: Expr,
921 pub span: Span,
923}
924
925#[derive(Debug, Clone, Serialize)]
927pub struct YieldExpr {
928 pub key: Option<Box<Expr>>,
930 pub value: Option<Box<Expr>>,
932 pub is_from: bool,
934}
935
936#[derive(Debug, Clone, Serialize)]
938pub struct CallableCreateExpr {
939 pub kind: CallableCreateKind,
941}
942
943#[derive(Debug, Clone, Serialize)]
945pub enum CallableCreateKind {
946 Function(Box<Expr>),
948 Method {
950 object: Box<Expr>,
952 method: Box<Expr>,
954 },
955 NullsafeMethod {
957 object: Box<Expr>,
959 method: Box<Expr>,
961 },
962 StaticMethod {
964 class: Box<Expr>,
966 method: Box<Expr>,
968 },
969}
970
971#[derive(Debug, Clone, Serialize)]
973pub enum StringPart {
974 Literal(Box<str>),
976 Expr(Expr),
978}
979
980#[derive(Debug, Clone, Serialize)]
986pub struct FunctionDecl {
987 pub name: Ident,
989 pub params: Box<[Param]>,
991 pub body: Box<Block>,
993 pub return_type: Option<TypeHint>,
995 pub by_ref: bool,
997 pub attributes: Box<[Attribute]>,
999 #[serde(skip_serializing_if = "Option::is_none")]
1001 pub doc_comment: Option<Comment>,
1002}
1003
1004#[derive(Debug, Clone, Serialize)]
1006pub struct Param {
1007 pub name: Ident,
1009 pub type_hint: Option<TypeHint>,
1011 pub default: Option<Expr>,
1013 pub by_ref: bool,
1015 pub variadic: bool,
1017 pub is_readonly: bool,
1019 pub is_final: bool,
1021 pub visibility: Option<Visibility>,
1023 pub set_visibility: Option<Visibility>,
1025 pub attributes: Box<[Attribute]>,
1027 #[serde(skip_serializing_if = "slice_is_empty")]
1029 pub hooks: Box<[PropertyHook]>,
1030 #[serde(skip_serializing_if = "Option::is_none")]
1032 pub doc_comment: Option<Comment>,
1033 pub span: Span,
1035}
1036
1037#[derive(Debug, Clone, Serialize)]
1039pub struct ClassBody {
1040 pub members: Box<[ClassMember]>,
1042 #[serde(skip)]
1044 pub span: Span,
1045}
1046
1047#[derive(Debug, Clone, Serialize)]
1049pub struct ClassDecl {
1050 pub name: Option<Ident>,
1052 pub modifiers: ClassModifiers,
1054 pub extends: Option<Name>,
1056 pub implements: Box<[Name]>,
1058 #[serde(flatten)]
1060 pub body: ClassBody,
1061 pub attributes: Box<[Attribute]>,
1063 #[serde(skip_serializing_if = "Option::is_none")]
1065 pub doc_comment: Option<Comment>,
1066}
1067
1068#[derive(Debug, Clone, Serialize)]
1070pub struct ClassMember {
1071 pub kind: ClassMemberKind,
1073 pub span: Span,
1075}
1076
1077#[derive(Debug, Clone, Serialize)]
1079pub enum ClassMemberKind {
1080 Property(PropertyDecl),
1082 Method(MethodDecl),
1084 ClassConst(ClassConstDecl),
1086 TraitUse(TraitUseDecl),
1088}
1089
1090#[derive(Debug, Clone, Serialize)]
1092pub struct PropertyDecl {
1093 pub name: Ident,
1095 pub visibility: Option<Visibility>,
1097 pub set_visibility: Option<Visibility>,
1099 pub is_static: bool,
1101 pub is_readonly: bool,
1103 pub type_hint: Option<TypeHint>,
1105 pub default: Option<Expr>,
1107 pub attributes: Box<[Attribute]>,
1109 #[serde(skip_serializing_if = "slice_is_empty")]
1111 pub hooks: Box<[PropertyHook]>,
1112 #[serde(skip_serializing_if = "Option::is_none")]
1114 pub doc_comment: Option<Comment>,
1115}
1116
1117#[derive(Debug, Clone, Serialize)]
1119pub struct PropertyHook {
1120 pub kind: PropertyHookKind,
1122 pub body: PropertyHookBody,
1124 pub is_final: bool,
1126 pub by_ref: bool,
1128 pub params: Box<[Param]>,
1130 pub attributes: Box<[Attribute]>,
1132 pub span: Span,
1134}
1135
1136#[derive(Debug, Clone, Serialize)]
1138pub enum PropertyHookBody {
1139 Block(Box<Block>),
1141 Expression(Expr),
1143 Abstract,
1145}
1146
1147#[derive(Debug, Clone, Serialize)]
1149pub struct MethodDecl {
1150 pub name: Ident,
1152 pub visibility: Option<Visibility>,
1154 pub is_static: bool,
1156 pub is_abstract: bool,
1158 pub is_final: bool,
1160 pub by_ref: bool,
1162 pub params: Box<[Param]>,
1164 pub return_type: Option<TypeHint>,
1166 pub body: Option<Box<Block>>,
1168 pub attributes: Box<[Attribute]>,
1170 #[serde(skip_serializing_if = "Option::is_none")]
1172 pub doc_comment: Option<Comment>,
1173}
1174
1175#[derive(Debug, Clone, Serialize)]
1177pub struct ClassConstDecl {
1178 pub name: Ident,
1180 pub visibility: Option<Visibility>,
1182 pub is_final: bool,
1184 #[serde(skip_serializing_if = "Option::is_none")]
1186 pub type_hint: Option<Box<TypeHint>>,
1187 pub value: Expr,
1189 pub attributes: Box<[Attribute]>,
1191 #[serde(skip_serializing_if = "Option::is_none")]
1193 pub doc_comment: Option<Comment>,
1194}
1195
1196#[derive(Debug, Clone, Serialize)]
1198pub struct TraitUseDecl {
1199 pub traits: Box<[Name]>,
1201 pub adaptations: Box<[TraitAdaptation]>,
1203 #[serde(skip)]
1205 pub adaptations_brace_start: Option<u32>,
1206 #[serde(skip_serializing_if = "Option::is_none")]
1208 pub doc_comment: Option<Comment>,
1209}
1210
1211#[derive(Debug, Clone, Serialize)]
1213pub struct TraitAdaptation {
1214 pub kind: TraitAdaptationKind,
1216 pub span: Span,
1218}
1219
1220#[derive(Debug, Clone, Serialize)]
1222pub enum TraitAdaptationKind {
1223 Precedence {
1225 trait_name: Name,
1227 method: Name,
1229 insteadof: Box<[Name]>,
1231 },
1232 Alias {
1234 trait_name: Option<Name>,
1236 method: Name,
1238 new_modifier: Option<Visibility>,
1240 new_name: Option<Name>,
1242 },
1243}
1244
1245#[derive(Debug, Clone, Serialize)]
1247pub struct InterfaceDecl {
1248 pub name: Ident,
1250 pub extends: Box<[Name]>,
1252 #[serde(flatten)]
1254 pub body: ClassBody,
1255 pub attributes: Box<[Attribute]>,
1257 #[serde(skip_serializing_if = "Option::is_none")]
1259 pub doc_comment: Option<Comment>,
1260}
1261
1262#[derive(Debug, Clone, Serialize)]
1264pub struct TraitDecl {
1265 pub name: Ident,
1267 #[serde(flatten)]
1269 pub body: ClassBody,
1270 pub attributes: Box<[Attribute]>,
1272 #[serde(skip_serializing_if = "Option::is_none")]
1274 pub doc_comment: Option<Comment>,
1275}
1276
1277#[derive(Debug, Clone, Serialize)]
1279pub struct EnumBody {
1280 pub members: Box<[EnumMember]>,
1282 #[serde(skip)]
1284 pub span: Span,
1285}
1286
1287#[derive(Debug, Clone, Serialize)]
1289pub struct EnumDecl {
1290 pub name: Ident,
1292 pub scalar_type: Option<Name>,
1294 pub implements: Box<[Name]>,
1296 #[serde(flatten)]
1298 pub body: EnumBody,
1299 pub attributes: Box<[Attribute]>,
1301 #[serde(skip_serializing_if = "Option::is_none")]
1303 pub doc_comment: Option<Comment>,
1304}
1305
1306#[derive(Debug, Clone, Serialize)]
1308pub struct EnumMember {
1309 pub kind: EnumMemberKind,
1311 pub span: Span,
1313}
1314
1315#[derive(Debug, Clone, Serialize)]
1317pub enum EnumMemberKind {
1318 Case(EnumCase),
1320 Method(MethodDecl),
1322 ClassConst(ClassConstDecl),
1324 TraitUse(TraitUseDecl),
1326}
1327
1328#[derive(Debug, Clone, Serialize)]
1330pub struct EnumCase {
1331 pub name: Ident,
1333 pub value: Option<Expr>,
1335 pub attributes: Box<[Attribute]>,
1337 #[serde(skip_serializing_if = "Option::is_none")]
1339 pub doc_comment: Option<Comment>,
1340}
1341
1342fn owned_ident(ident: arena_ast::Ident<'_>) -> Ident {
1347 ident.as_str().map(|s| s.into())
1348}
1349
1350fn owned_name(name: &arena_ast::Name<'_, '_>) -> Name {
1351 match name {
1352 arena_ast::Name::Simple { value, span } => Name {
1353 parts: vec![Box::from(*value)].into_boxed_slice(),
1354 kind: NameKind::Unqualified,
1355 span: *span,
1356 },
1357 arena_ast::Name::Complex { parts, kind, span } => Name {
1358 parts: parts
1359 .iter()
1360 .map(|s| Box::from(*s))
1361 .collect::<Vec<_>>()
1362 .into_boxed_slice(),
1363 kind: *kind,
1364 span: *span,
1365 },
1366 arena_ast::Name::Error { span } => Name {
1367 parts: Box::from([]),
1368 kind: NameKind::Error,
1369 span: *span,
1370 },
1371 }
1372}
1373
1374fn owned_comment(c: &arena_ast::Comment<'_>) -> Comment {
1375 Comment {
1376 kind: c.kind,
1377 text: c.text.into(),
1378 span: c.span,
1379 }
1380}
1381
1382fn owned_opt_comment(c: &Option<arena_ast::Comment<'_>>) -> Option<Comment> {
1383 c.as_ref().map(owned_comment)
1384}
1385
1386fn owned_type_hint(th: &arena_ast::TypeHint<'_, '_>) -> TypeHint {
1387 TypeHint {
1388 kind: owned_type_hint_kind(&th.kind),
1389 span: th.span,
1390 }
1391}
1392
1393fn owned_type_hint_kind(k: &arena_ast::TypeHintKind<'_, '_>) -> TypeHintKind {
1394 match k {
1395 arena_ast::TypeHintKind::Named(n) => TypeHintKind::Named(owned_name(n)),
1396 arena_ast::TypeHintKind::Keyword(b, span) => TypeHintKind::Keyword(*b, *span),
1397 arena_ast::TypeHintKind::Nullable(inner) => {
1398 TypeHintKind::Nullable(Box::new(owned_type_hint(inner)))
1399 }
1400 arena_ast::TypeHintKind::Union(types) => TypeHintKind::Union(
1401 types
1402 .iter()
1403 .map(owned_type_hint)
1404 .collect::<Vec<_>>()
1405 .into_boxed_slice(),
1406 ),
1407 arena_ast::TypeHintKind::Intersection(types) => TypeHintKind::Intersection(
1408 types
1409 .iter()
1410 .map(owned_type_hint)
1411 .collect::<Vec<_>>()
1412 .into_boxed_slice(),
1413 ),
1414 }
1415}
1416
1417fn owned_arg(arg: &arena_ast::Arg<'_, '_>) -> Arg {
1418 Arg {
1419 name: arg.name.as_ref().map(owned_name),
1420 value: arg.value.as_ref().map(owned_expr),
1421 unpack: arg.unpack,
1422 by_ref: arg.by_ref,
1423 span: arg.span,
1424 }
1425}
1426
1427fn owned_args(args: &[arena_ast::Arg<'_, '_>]) -> Box<[Arg]> {
1428 args.iter()
1429 .map(owned_arg)
1430 .collect::<Vec<_>>()
1431 .into_boxed_slice()
1432}
1433
1434fn owned_attr(attr: &arena_ast::Attribute<'_, '_>) -> Attribute {
1435 Attribute {
1436 name: owned_name(&attr.name),
1437 args: owned_args(&attr.args),
1438 span: attr.span,
1439 }
1440}
1441
1442fn owned_attrs(attrs: &[arena_ast::Attribute<'_, '_>]) -> Box<[Attribute]> {
1443 attrs
1444 .iter()
1445 .map(owned_attr)
1446 .collect::<Vec<_>>()
1447 .into_boxed_slice()
1448}
1449
1450fn owned_string_parts(parts: &[arena_ast::StringPart<'_, '_>]) -> Box<[StringPart]> {
1451 parts
1452 .iter()
1453 .map(|p| match p {
1454 arena_ast::StringPart::Literal(s) => StringPart::Literal(Box::from(*s)),
1455 arena_ast::StringPart::Expr(e) => StringPart::Expr(owned_expr(e)),
1456 })
1457 .collect::<Vec<_>>()
1458 .into_boxed_slice()
1459}
1460
1461pub fn to_owned_expr(expr: &arena_ast::Expr<'_, '_>) -> Expr {
1463 owned_expr(expr)
1464}
1465
1466pub fn to_owned_name(name: &arena_ast::Name<'_, '_>) -> Name {
1468 owned_name(name)
1469}
1470
1471pub fn to_owned_type_hint(hint: &arena_ast::TypeHint<'_, '_>) -> TypeHint {
1473 owned_type_hint(hint)
1474}
1475
1476fn owned_expr(expr: &arena_ast::Expr<'_, '_>) -> Expr {
1477 Expr {
1478 kind: owned_expr_kind(&expr.kind),
1479 span: expr.span,
1480 }
1481}
1482
1483fn owned_exprs(exprs: &[arena_ast::Expr<'_, '_>]) -> Box<[Expr]> {
1484 exprs
1485 .iter()
1486 .map(owned_expr)
1487 .collect::<Vec<_>>()
1488 .into_boxed_slice()
1489}
1490
1491fn owned_expr_kind(k: &arena_ast::ExprKind<'_, '_>) -> ExprKind {
1492 match k {
1493 arena_ast::ExprKind::Int(v) => ExprKind::Int(*v),
1494 arena_ast::ExprKind::Float(v) => ExprKind::Float(*v),
1495 arena_ast::ExprKind::String(s) => ExprKind::String(Box::from(*s)),
1496 arena_ast::ExprKind::InterpolatedString(parts) => {
1497 ExprKind::InterpolatedString(owned_string_parts(parts))
1498 }
1499 arena_ast::ExprKind::Heredoc { label, parts } => ExprKind::Heredoc {
1500 label: Box::from(*label),
1501 parts: owned_string_parts(parts),
1502 },
1503 arena_ast::ExprKind::Nowdoc { label, value } => ExprKind::Nowdoc {
1504 label: Box::from(*label),
1505 value: Box::from(*value),
1506 },
1507 arena_ast::ExprKind::ShellExec(parts) => ExprKind::ShellExec(owned_string_parts(parts)),
1508 arena_ast::ExprKind::Bool(v) => ExprKind::Bool(*v),
1509 arena_ast::ExprKind::Null => ExprKind::Null,
1510 arena_ast::ExprKind::Variable(s) => ExprKind::Variable(s.as_str().into()),
1511 arena_ast::ExprKind::VariableVariable(inner) => {
1512 ExprKind::VariableVariable(Box::new(owned_expr(inner)))
1513 }
1514 arena_ast::ExprKind::Identifier(s) => ExprKind::Identifier(s.as_str().into()),
1515 arena_ast::ExprKind::Assign(a) => ExprKind::Assign(AssignExpr {
1516 target: Box::new(owned_expr(a.target)),
1517 op: a.op,
1518 value: Box::new(owned_expr(a.value)),
1519 by_ref: a.by_ref,
1520 }),
1521 arena_ast::ExprKind::Binary(b) => ExprKind::Binary(BinaryExpr {
1522 left: Box::new(owned_expr(b.left)),
1523 op: b.op,
1524 right: Box::new(owned_expr(b.right)),
1525 }),
1526 arena_ast::ExprKind::UnaryPrefix(u) => ExprKind::UnaryPrefix(UnaryPrefixExpr {
1527 op: u.op,
1528 operand: Box::new(owned_expr(u.operand)),
1529 }),
1530 arena_ast::ExprKind::UnaryPostfix(u) => ExprKind::UnaryPostfix(UnaryPostfixExpr {
1531 operand: Box::new(owned_expr(u.operand)),
1532 op: u.op,
1533 }),
1534 arena_ast::ExprKind::Ternary(t) => ExprKind::Ternary(TernaryExpr {
1535 condition: Box::new(owned_expr(t.condition)),
1536 then_expr: t.then_expr.map(|e| Box::new(owned_expr(e))),
1537 else_expr: Box::new(owned_expr(t.else_expr)),
1538 }),
1539 arena_ast::ExprKind::NullCoalesce(n) => ExprKind::NullCoalesce(NullCoalesceExpr {
1540 left: Box::new(owned_expr(n.left)),
1541 right: Box::new(owned_expr(n.right)),
1542 }),
1543 arena_ast::ExprKind::FunctionCall(f) => ExprKind::FunctionCall(FunctionCallExpr {
1544 name: Box::new(owned_expr(f.name)),
1545 args: owned_args(&f.args),
1546 }),
1547 arena_ast::ExprKind::Array(elems) => ExprKind::Array(
1548 elems
1549 .iter()
1550 .map(|e| ArrayElement {
1551 key: e.key.as_ref().map(owned_expr),
1552 value: owned_expr(&e.value),
1553 unpack: e.unpack,
1554 by_ref: e.by_ref,
1555 span: e.span,
1556 })
1557 .collect::<Vec<_>>()
1558 .into_boxed_slice(),
1559 ),
1560 arena_ast::ExprKind::ArrayAccess(a) => ExprKind::ArrayAccess(ArrayAccessExpr {
1561 array: Box::new(owned_expr(a.array)),
1562 index: a.index.map(|e| Box::new(owned_expr(e))),
1563 }),
1564 arena_ast::ExprKind::Print(e) => ExprKind::Print(Box::new(owned_expr(e))),
1565 arena_ast::ExprKind::Parenthesized(e) => ExprKind::Parenthesized(Box::new(owned_expr(e))),
1566 arena_ast::ExprKind::Cast(kind, e) => ExprKind::Cast(*kind, Box::new(owned_expr(e))),
1567 arena_ast::ExprKind::ErrorSuppress(e) => ExprKind::ErrorSuppress(Box::new(owned_expr(e))),
1568 arena_ast::ExprKind::Isset(exprs) => ExprKind::Isset(owned_exprs(exprs)),
1569 arena_ast::ExprKind::Empty(e) => ExprKind::Empty(Box::new(owned_expr(e))),
1570 arena_ast::ExprKind::Include(kind, e) => ExprKind::Include(*kind, Box::new(owned_expr(e))),
1571 arena_ast::ExprKind::Eval(e) => ExprKind::Eval(Box::new(owned_expr(e))),
1572 arena_ast::ExprKind::Exit(e) => ExprKind::Exit(e.map(|e| Box::new(owned_expr(e)))),
1573 arena_ast::ExprKind::MagicConst(m) => ExprKind::MagicConst(*m),
1574 arena_ast::ExprKind::Clone(e) => ExprKind::Clone(Box::new(owned_expr(e))),
1575 arena_ast::ExprKind::CloneWith(obj, props) => {
1576 ExprKind::CloneWith(Box::new(owned_expr(obj)), Box::new(owned_expr(props)))
1577 }
1578 arena_ast::ExprKind::New(n) => ExprKind::New(NewExpr {
1579 class: Box::new(owned_expr(n.class)),
1580 args: owned_args(&n.args),
1581 }),
1582 arena_ast::ExprKind::PropertyAccess(p) => ExprKind::PropertyAccess(PropertyAccessExpr {
1583 object: Box::new(owned_expr(p.object)),
1584 property: Box::new(owned_expr(p.property)),
1585 }),
1586 arena_ast::ExprKind::NullsafePropertyAccess(p) => {
1587 ExprKind::NullsafePropertyAccess(PropertyAccessExpr {
1588 object: Box::new(owned_expr(p.object)),
1589 property: Box::new(owned_expr(p.property)),
1590 })
1591 }
1592 arena_ast::ExprKind::MethodCall(m) => ExprKind::MethodCall(Box::new(MethodCallExpr {
1593 object: Box::new(owned_expr(m.object)),
1594 method: Box::new(owned_expr(m.method)),
1595 args: owned_args(&m.args),
1596 })),
1597 arena_ast::ExprKind::NullsafeMethodCall(m) => {
1598 ExprKind::NullsafeMethodCall(Box::new(MethodCallExpr {
1599 object: Box::new(owned_expr(m.object)),
1600 method: Box::new(owned_expr(m.method)),
1601 args: owned_args(&m.args),
1602 }))
1603 }
1604 arena_ast::ExprKind::StaticPropertyAccess(s) => {
1605 ExprKind::StaticPropertyAccess(StaticAccessExpr {
1606 class: Box::new(owned_expr(s.class)),
1607 member: Box::new(owned_expr(s.member)),
1608 })
1609 }
1610 arena_ast::ExprKind::StaticMethodCall(s) => {
1611 ExprKind::StaticMethodCall(Box::new(StaticMethodCallExpr {
1612 class: Box::new(owned_expr(s.class)),
1613 method: Box::new(owned_expr(s.method)),
1614 args: owned_args(&s.args),
1615 }))
1616 }
1617 arena_ast::ExprKind::StaticDynMethodCall(s) => {
1618 ExprKind::StaticDynMethodCall(Box::new(StaticDynMethodCallExpr {
1619 class: Box::new(owned_expr(s.class)),
1620 method: Box::new(owned_expr(s.method)),
1621 args: owned_args(&s.args),
1622 }))
1623 }
1624 arena_ast::ExprKind::ClassConstAccess(s) => ExprKind::ClassConstAccess(StaticAccessExpr {
1625 class: Box::new(owned_expr(s.class)),
1626 member: Box::new(owned_expr(s.member)),
1627 }),
1628 arena_ast::ExprKind::ClassConstAccessDynamic { class, member } => {
1629 ExprKind::ClassConstAccessDynamic {
1630 class: Box::new(owned_expr(class)),
1631 member: Box::new(owned_expr(member)),
1632 }
1633 }
1634 arena_ast::ExprKind::StaticPropertyAccessDynamic { class, member } => {
1635 ExprKind::StaticPropertyAccessDynamic {
1636 class: Box::new(owned_expr(class)),
1637 member: Box::new(owned_expr(member)),
1638 }
1639 }
1640 arena_ast::ExprKind::Closure(c) => ExprKind::Closure(Box::new(ClosureExpr {
1641 is_static: c.is_static,
1642 by_ref: c.by_ref,
1643 params: owned_params(&c.params),
1644 use_vars: c
1645 .use_vars
1646 .iter()
1647 .map(|v| ClosureUseVar {
1648 name: v.name.into(),
1649 by_ref: v.by_ref,
1650 span: v.span,
1651 })
1652 .collect::<Vec<_>>()
1653 .into_boxed_slice(),
1654 return_type: c.return_type.as_ref().map(owned_type_hint),
1655 body: Box::new(owned_block(c.body)),
1656 attributes: owned_attrs(&c.attributes),
1657 })),
1658 arena_ast::ExprKind::ArrowFunction(f) => {
1659 ExprKind::ArrowFunction(Box::new(ArrowFunctionExpr {
1660 is_static: f.is_static,
1661 by_ref: f.by_ref,
1662 params: owned_params(&f.params),
1663 return_type: f.return_type.as_ref().map(owned_type_hint),
1664 body: Box::new(owned_expr(f.body)),
1665 attributes: owned_attrs(&f.attributes),
1666 }))
1667 }
1668 arena_ast::ExprKind::Match(m) => ExprKind::Match(MatchExpr {
1669 subject: Box::new(owned_expr(m.subject)),
1670 arms: m
1671 .arms
1672 .iter()
1673 .map(|arm| MatchArm {
1674 conditions: arm.conditions.as_ref().map(|conds| owned_exprs(conds)),
1675 body: owned_expr(&arm.body),
1676 span: arm.span,
1677 })
1678 .collect::<Vec<_>>()
1679 .into_boxed_slice(),
1680 brace_start: m.brace_start,
1681 }),
1682 arena_ast::ExprKind::ThrowExpr(e) => ExprKind::ThrowExpr(Box::new(owned_expr(e))),
1683 arena_ast::ExprKind::Yield(y) => ExprKind::Yield(YieldExpr {
1684 key: y.key.map(|e| Box::new(owned_expr(e))),
1685 value: y.value.map(|e| Box::new(owned_expr(e))),
1686 is_from: y.is_from,
1687 }),
1688 arena_ast::ExprKind::AnonymousClass(cls) => {
1689 ExprKind::AnonymousClass(Box::new(owned_class_decl(cls)))
1690 }
1691 arena_ast::ExprKind::CallableCreate(c) => ExprKind::CallableCreate(CallableCreateExpr {
1692 kind: match &c.kind {
1693 arena_ast::CallableCreateKind::Function(e) => {
1694 CallableCreateKind::Function(Box::new(owned_expr(e)))
1695 }
1696 arena_ast::CallableCreateKind::Method { object, method } => {
1697 CallableCreateKind::Method {
1698 object: Box::new(owned_expr(object)),
1699 method: Box::new(owned_expr(method)),
1700 }
1701 }
1702 arena_ast::CallableCreateKind::NullsafeMethod { object, method } => {
1703 CallableCreateKind::NullsafeMethod {
1704 object: Box::new(owned_expr(object)),
1705 method: Box::new(owned_expr(method)),
1706 }
1707 }
1708 arena_ast::CallableCreateKind::StaticMethod { class, method } => {
1709 CallableCreateKind::StaticMethod {
1710 class: Box::new(owned_expr(class)),
1711 method: Box::new(owned_expr(method)),
1712 }
1713 }
1714 },
1715 }),
1716 arena_ast::ExprKind::Omit => ExprKind::Omit,
1717 arena_ast::ExprKind::Error => ExprKind::Error,
1718 }
1719}
1720
1721fn owned_param(p: &arena_ast::Param<'_, '_>) -> Param {
1722 Param {
1723 name: owned_ident(p.name),
1724 type_hint: p.type_hint.as_ref().map(owned_type_hint),
1725 default: p.default.as_ref().map(owned_expr),
1726 by_ref: p.by_ref,
1727 variadic: p.variadic,
1728 is_readonly: p.is_readonly,
1729 is_final: p.is_final,
1730 visibility: p.visibility,
1731 set_visibility: p.set_visibility,
1732 attributes: owned_attrs(&p.attributes),
1733 hooks: owned_hooks(&p.hooks),
1734 doc_comment: p.doc_comment.as_ref().map(owned_comment),
1735 span: p.span,
1736 }
1737}
1738
1739fn owned_params(params: &[arena_ast::Param<'_, '_>]) -> Box<[Param]> {
1740 params
1741 .iter()
1742 .map(owned_param)
1743 .collect::<Vec<_>>()
1744 .into_boxed_slice()
1745}
1746
1747fn owned_hook(h: &arena_ast::PropertyHook<'_, '_>) -> PropertyHook {
1748 PropertyHook {
1749 kind: h.kind,
1750 body: match &h.body {
1751 arena_ast::PropertyHookBody::Block(block) => {
1752 PropertyHookBody::Block(Box::new(owned_block(block)))
1753 }
1754 arena_ast::PropertyHookBody::Expression(e) => {
1755 PropertyHookBody::Expression(owned_expr(e))
1756 }
1757 arena_ast::PropertyHookBody::Abstract => PropertyHookBody::Abstract,
1758 },
1759 is_final: h.is_final,
1760 by_ref: h.by_ref,
1761 params: owned_params(&h.params),
1762 attributes: owned_attrs(&h.attributes),
1763 span: h.span,
1764 }
1765}
1766
1767fn owned_hooks(hooks: &[arena_ast::PropertyHook<'_, '_>]) -> Box<[PropertyHook]> {
1768 hooks
1769 .iter()
1770 .map(owned_hook)
1771 .collect::<Vec<_>>()
1772 .into_boxed_slice()
1773}
1774
1775fn owned_stmts(stmts: &[arena_ast::Stmt<'_, '_>]) -> Box<[Stmt]> {
1776 stmts
1777 .iter()
1778 .map(owned_stmt)
1779 .collect::<Vec<_>>()
1780 .into_boxed_slice()
1781}
1782
1783pub fn to_owned_stmt(stmt: &arena_ast::Stmt<'_, '_>) -> Stmt {
1785 owned_stmt(stmt)
1786}
1787
1788fn owned_block(block: &arena_ast::Block<'_, '_>) -> Block {
1789 Block {
1790 stmts: owned_stmts(&block.stmts),
1791 span: block.span,
1792 }
1793}
1794
1795fn owned_stmt(stmt: &arena_ast::Stmt<'_, '_>) -> Stmt {
1796 Stmt {
1797 kind: owned_stmt_kind(&stmt.kind),
1798 span: stmt.span,
1799 doc_comment: stmt.doc_comment.map(owned_comment),
1800 }
1801}
1802
1803fn owned_stmt_kind(k: &arena_ast::StmtKind<'_, '_>) -> StmtKind {
1804 match k {
1805 arena_ast::StmtKind::Expression(e) => StmtKind::Expression(Box::new(owned_expr(e))),
1806 arena_ast::StmtKind::Echo(exprs) => StmtKind::Echo(owned_exprs(exprs)),
1807 arena_ast::StmtKind::Return(e) => StmtKind::Return(e.map(|e| Box::new(owned_expr(e)))),
1808 arena_ast::StmtKind::Block(block) => StmtKind::Block(Box::new(owned_block(block))),
1809 arena_ast::StmtKind::If(s) => StmtKind::If(Box::new(IfStmt {
1810 condition: owned_expr(&s.condition),
1811 then_branch: Box::new(owned_stmt(s.then_branch)),
1812 elseif_branches: s
1813 .elseif_branches
1814 .iter()
1815 .map(|b| ElseIfBranch {
1816 condition: owned_expr(&b.condition),
1817 body: owned_stmt(&b.body),
1818 span: b.span,
1819 })
1820 .collect::<Vec<_>>()
1821 .into_boxed_slice(),
1822 else_branch: s.else_branch.map(|b| Box::new(owned_stmt(b))),
1823 else_kw_start: s.else_kw_start,
1824 uses_alternative: s.uses_alternative,
1825 })),
1826 arena_ast::StmtKind::While(s) => StmtKind::While(Box::new(WhileStmt {
1827 condition: owned_expr(&s.condition),
1828 body: Box::new(owned_stmt(s.body)),
1829 uses_alternative: s.uses_alternative,
1830 })),
1831 arena_ast::StmtKind::For(s) => StmtKind::For(Box::new(ForStmt {
1832 init: owned_exprs(&s.init),
1833 condition: owned_exprs(&s.condition),
1834 update: owned_exprs(&s.update),
1835 body: Box::new(owned_stmt(s.body)),
1836 uses_alternative: s.uses_alternative,
1837 })),
1838 arena_ast::StmtKind::Foreach(s) => StmtKind::Foreach(Box::new(ForeachStmt {
1839 expr: owned_expr(&s.expr),
1840 key: s.key.as_ref().map(owned_expr),
1841 value: owned_expr(&s.value),
1842 body: Box::new(owned_stmt(s.body)),
1843 uses_alternative: s.uses_alternative,
1844 })),
1845 arena_ast::StmtKind::DoWhile(s) => StmtKind::DoWhile(Box::new(DoWhileStmt {
1846 body: Box::new(owned_stmt(s.body)),
1847 condition: owned_expr(&s.condition),
1848 })),
1849 arena_ast::StmtKind::Function(f) => StmtKind::Function(Box::new(owned_function_decl(f))),
1850 arena_ast::StmtKind::Break(e) => StmtKind::Break(e.map(|e| Box::new(owned_expr(e)))),
1851 arena_ast::StmtKind::Continue(e) => StmtKind::Continue(e.map(|e| Box::new(owned_expr(e)))),
1852 arena_ast::StmtKind::Switch(s) => StmtKind::Switch(Box::new(SwitchStmt {
1853 expr: owned_expr(&s.expr),
1854 body: SwitchBody {
1855 cases: s
1856 .body
1857 .cases
1858 .iter()
1859 .map(|c| SwitchCase {
1860 value: c.value.as_ref().map(owned_expr),
1861 body: owned_stmts(&c.body),
1862 span: c.span,
1863 })
1864 .collect::<Vec<_>>()
1865 .into_boxed_slice(),
1866 span: s.body.span,
1867 },
1868 uses_alternative: s.uses_alternative,
1869 })),
1870 arena_ast::StmtKind::Goto(ident) => StmtKind::Goto(owned_ident(*ident)),
1871 arena_ast::StmtKind::Label(s) => StmtKind::Label(Box::from(*s)),
1872 arena_ast::StmtKind::Declare(d) => StmtKind::Declare(Box::new(DeclareStmt {
1873 directives: d
1874 .directives
1875 .iter()
1876 .map(|(k, v)| (Box::from(*k), owned_expr(v)))
1877 .collect::<Vec<_>>()
1878 .into_boxed_slice(),
1879 body: d.body.map(|b| Box::new(owned_stmt(b))),
1880 uses_alternative: d.uses_alternative,
1881 })),
1882 arena_ast::StmtKind::Unset(exprs) => StmtKind::Unset(owned_exprs(exprs)),
1883 arena_ast::StmtKind::Throw(e) => StmtKind::Throw(Box::new(owned_expr(e))),
1884 arena_ast::StmtKind::TryCatch(t) => StmtKind::TryCatch(Box::new(TryCatchStmt {
1885 body: Box::new(owned_block(t.body)),
1886 catches: t
1887 .catches
1888 .iter()
1889 .map(|c| CatchClause {
1890 types: c
1891 .types
1892 .iter()
1893 .map(owned_name)
1894 .collect::<Vec<_>>()
1895 .into_boxed_slice(),
1896 var: c.var.map(Box::from),
1897 body: Box::new(owned_block(c.body)),
1898 span: c.span,
1899 })
1900 .collect::<Vec<_>>()
1901 .into_boxed_slice(),
1902 finally: t.finally.map(|f| Box::new(owned_block(f))),
1903 finally_kw_start: t.finally_kw_start,
1904 })),
1905 arena_ast::StmtKind::Global(exprs) => StmtKind::Global(owned_exprs(exprs)),
1906 arena_ast::StmtKind::Class(cls) => StmtKind::Class(Box::new(owned_class_decl(cls))),
1907 arena_ast::StmtKind::Interface(iface) => {
1908 StmtKind::Interface(Box::new(owned_interface_decl(iface)))
1909 }
1910 arena_ast::StmtKind::Trait(tr) => StmtKind::Trait(Box::new(owned_trait_decl(tr))),
1911 arena_ast::StmtKind::Enum(en) => StmtKind::Enum(Box::new(owned_enum_decl(en))),
1912 arena_ast::StmtKind::Namespace(ns) => StmtKind::Namespace(Box::new(NamespaceDecl {
1913 name: ns.name.as_ref().map(owned_name),
1914 body: match &ns.body {
1915 arena_ast::NamespaceBody::Braced(block) => {
1916 NamespaceBody::Braced(Box::new(owned_block(block)))
1917 }
1918 arena_ast::NamespaceBody::Simple => NamespaceBody::Simple,
1919 },
1920 })),
1921 arena_ast::StmtKind::Use(u) => StmtKind::Use(Box::new(UseDecl {
1922 kind: u.kind,
1923 uses: u
1924 .uses
1925 .iter()
1926 .map(|item| UseItem {
1927 name: owned_name(&item.name),
1928 alias: item.alias.map(Box::from),
1929 kind: item.kind,
1930 span: item.span,
1931 })
1932 .collect::<Vec<_>>()
1933 .into_boxed_slice(),
1934 })),
1935 arena_ast::StmtKind::Const(items) => StmtKind::Const(
1936 items
1937 .iter()
1938 .map(|item| ConstItem {
1939 name: owned_ident(item.name),
1940 value: owned_expr(&item.value),
1941 attributes: owned_attrs(&item.attributes),
1942 span: item.span,
1943 doc_comment: owned_opt_comment(&item.doc_comment),
1944 })
1945 .collect::<Vec<_>>()
1946 .into_boxed_slice(),
1947 ),
1948 arena_ast::StmtKind::StaticVar(vars) => StmtKind::StaticVar(
1949 vars.iter()
1950 .map(|v| StaticVar {
1951 name: owned_ident(v.name),
1952 default: v.default.as_ref().map(owned_expr),
1953 span: v.span,
1954 })
1955 .collect::<Vec<_>>()
1956 .into_boxed_slice(),
1957 ),
1958 arena_ast::StmtKind::HaltCompiler(s) => StmtKind::HaltCompiler(Box::from(*s)),
1959 arena_ast::StmtKind::Nop => StmtKind::Nop,
1960 arena_ast::StmtKind::InlineHtml(s) => StmtKind::InlineHtml(Box::from(*s)),
1961 arena_ast::StmtKind::Error => StmtKind::Error,
1962 }
1963}
1964
1965fn owned_function_decl(f: &arena_ast::FunctionDecl<'_, '_>) -> FunctionDecl {
1966 FunctionDecl {
1967 name: owned_ident(f.name),
1968 params: owned_params(&f.params),
1969 body: Box::new(owned_block(f.body)),
1970 return_type: f.return_type.as_ref().map(owned_type_hint),
1971 by_ref: f.by_ref,
1972 attributes: owned_attrs(&f.attributes),
1973 doc_comment: owned_opt_comment(&f.doc_comment),
1974 }
1975}
1976
1977fn owned_class_member(m: &arena_ast::ClassMember<'_, '_>) -> ClassMember {
1978 ClassMember {
1979 kind: match &m.kind {
1980 arena_ast::ClassMemberKind::Property(p) => ClassMemberKind::Property(PropertyDecl {
1981 name: owned_ident(p.name),
1982 visibility: p.visibility,
1983 set_visibility: p.set_visibility,
1984 is_static: p.is_static,
1985 is_readonly: p.is_readonly,
1986 type_hint: p.type_hint.as_ref().map(owned_type_hint),
1987 default: p.default.as_ref().map(owned_expr),
1988 attributes: owned_attrs(&p.attributes),
1989 hooks: owned_hooks(&p.hooks),
1990 doc_comment: owned_opt_comment(&p.doc_comment),
1991 }),
1992 arena_ast::ClassMemberKind::Method(m) => ClassMemberKind::Method(MethodDecl {
1993 name: owned_ident(m.name),
1994 visibility: m.visibility,
1995 is_static: m.is_static,
1996 is_abstract: m.is_abstract,
1997 is_final: m.is_final,
1998 by_ref: m.by_ref,
1999 params: owned_params(&m.params),
2000 return_type: m.return_type.as_ref().map(owned_type_hint),
2001 body: m.body.map(|b| Box::new(owned_block(b))),
2002 attributes: owned_attrs(&m.attributes),
2003 doc_comment: owned_opt_comment(&m.doc_comment),
2004 }),
2005 arena_ast::ClassMemberKind::ClassConst(c) => {
2006 ClassMemberKind::ClassConst(owned_class_const(c))
2007 }
2008 arena_ast::ClassMemberKind::TraitUse(t) => {
2009 ClassMemberKind::TraitUse(owned_trait_use(t))
2010 }
2011 },
2012 span: m.span,
2013 }
2014}
2015
2016fn owned_class_members(members: &[arena_ast::ClassMember<'_, '_>]) -> Box<[ClassMember]> {
2017 members
2018 .iter()
2019 .map(owned_class_member)
2020 .collect::<Vec<_>>()
2021 .into_boxed_slice()
2022}
2023
2024fn owned_class_const(c: &arena_ast::ClassConstDecl<'_, '_>) -> ClassConstDecl {
2025 ClassConstDecl {
2026 name: owned_ident(c.name),
2027 visibility: c.visibility,
2028 is_final: c.is_final,
2029 type_hint: c.type_hint.map(|th| Box::new(owned_type_hint(th))),
2030 value: owned_expr(&c.value),
2031 attributes: owned_attrs(&c.attributes),
2032 doc_comment: owned_opt_comment(&c.doc_comment),
2033 }
2034}
2035
2036fn owned_trait_use(t: &arena_ast::TraitUseDecl<'_, '_>) -> TraitUseDecl {
2037 TraitUseDecl {
2038 traits: t
2039 .traits
2040 .iter()
2041 .map(owned_name)
2042 .collect::<Vec<_>>()
2043 .into_boxed_slice(),
2044 adaptations: t
2045 .adaptations
2046 .iter()
2047 .map(|a| TraitAdaptation {
2048 kind: match &a.kind {
2049 arena_ast::TraitAdaptationKind::Precedence {
2050 trait_name,
2051 method,
2052 insteadof,
2053 } => TraitAdaptationKind::Precedence {
2054 trait_name: owned_name(trait_name),
2055 method: owned_name(method),
2056 insteadof: insteadof
2057 .iter()
2058 .map(owned_name)
2059 .collect::<Vec<_>>()
2060 .into_boxed_slice(),
2061 },
2062 arena_ast::TraitAdaptationKind::Alias {
2063 trait_name,
2064 method,
2065 new_modifier,
2066 new_name,
2067 } => TraitAdaptationKind::Alias {
2068 trait_name: trait_name.as_ref().map(owned_name),
2069 method: owned_name(method),
2070 new_modifier: *new_modifier,
2071 new_name: new_name.as_ref().map(owned_name),
2072 },
2073 },
2074 span: a.span,
2075 })
2076 .collect::<Vec<_>>()
2077 .into_boxed_slice(),
2078 adaptations_brace_start: t.adaptations_brace_start,
2079 doc_comment: owned_opt_comment(&t.doc_comment),
2080 }
2081}
2082
2083fn owned_class_decl(cls: &arena_ast::ClassDecl<'_, '_>) -> ClassDecl {
2084 ClassDecl {
2085 name: cls
2086 .name
2087 .map(|ident| Some(owned_ident(ident)))
2088 .unwrap_or(None),
2089 modifiers: cls.modifiers.clone(),
2090 extends: cls.extends.as_ref().map(owned_name),
2091 implements: cls
2092 .implements
2093 .iter()
2094 .map(owned_name)
2095 .collect::<Vec<_>>()
2096 .into_boxed_slice(),
2097 body: ClassBody {
2098 members: owned_class_members(&cls.body.members),
2099 span: cls.body.span,
2100 },
2101 attributes: owned_attrs(&cls.attributes),
2102 doc_comment: owned_opt_comment(&cls.doc_comment),
2103 }
2104}
2105
2106fn owned_interface_decl(iface: &arena_ast::InterfaceDecl<'_, '_>) -> InterfaceDecl {
2107 InterfaceDecl {
2108 name: owned_ident(iface.name),
2109 extends: iface
2110 .extends
2111 .iter()
2112 .map(owned_name)
2113 .collect::<Vec<_>>()
2114 .into_boxed_slice(),
2115 body: ClassBody {
2116 members: owned_class_members(&iface.body.members),
2117 span: iface.body.span,
2118 },
2119 attributes: owned_attrs(&iface.attributes),
2120 doc_comment: owned_opt_comment(&iface.doc_comment),
2121 }
2122}
2123
2124fn owned_trait_decl(tr: &arena_ast::TraitDecl<'_, '_>) -> TraitDecl {
2125 TraitDecl {
2126 name: owned_ident(tr.name),
2127 body: ClassBody {
2128 members: owned_class_members(&tr.body.members),
2129 span: tr.body.span,
2130 },
2131 attributes: owned_attrs(&tr.attributes),
2132 doc_comment: owned_opt_comment(&tr.doc_comment),
2133 }
2134}
2135
2136fn owned_enum_decl(en: &arena_ast::EnumDecl<'_, '_>) -> EnumDecl {
2137 EnumDecl {
2138 name: owned_ident(en.name),
2139 scalar_type: en.scalar_type.as_ref().map(owned_name),
2140 implements: en
2141 .implements
2142 .iter()
2143 .map(owned_name)
2144 .collect::<Vec<_>>()
2145 .into_boxed_slice(),
2146 body: EnumBody {
2147 members: en
2148 .body
2149 .members
2150 .iter()
2151 .map(|m| EnumMember {
2152 kind: match &m.kind {
2153 arena_ast::EnumMemberKind::Case(c) => EnumMemberKind::Case(EnumCase {
2154 name: owned_ident(c.name),
2155 value: c.value.as_ref().map(owned_expr),
2156 attributes: owned_attrs(&c.attributes),
2157 doc_comment: owned_opt_comment(&c.doc_comment),
2158 }),
2159 arena_ast::EnumMemberKind::Method(m) => {
2160 EnumMemberKind::Method(MethodDecl {
2161 name: owned_ident(m.name),
2162 visibility: m.visibility,
2163 is_static: m.is_static,
2164 is_abstract: m.is_abstract,
2165 is_final: m.is_final,
2166 by_ref: m.by_ref,
2167 params: owned_params(&m.params),
2168 return_type: m.return_type.as_ref().map(owned_type_hint),
2169 body: m.body.map(|b| Box::new(owned_block(b))),
2170 attributes: owned_attrs(&m.attributes),
2171 doc_comment: owned_opt_comment(&m.doc_comment),
2172 })
2173 }
2174 arena_ast::EnumMemberKind::ClassConst(c) => {
2175 EnumMemberKind::ClassConst(owned_class_const(c))
2176 }
2177 arena_ast::EnumMemberKind::TraitUse(t) => {
2178 EnumMemberKind::TraitUse(owned_trait_use(t))
2179 }
2180 },
2181 span: m.span,
2182 })
2183 .collect::<Vec<_>>()
2184 .into_boxed_slice(),
2185 span: en.body.span,
2186 },
2187 attributes: owned_attrs(&en.attributes),
2188 doc_comment: owned_opt_comment(&en.doc_comment),
2189 }
2190}
2191
2192pub fn to_owned_program(program: &arena_ast::Program<'_, '_>) -> Program {
2194 Program {
2195 stmts: owned_stmts(&program.stmts),
2196 span: program.span,
2197 }
2198}
2199
2200pub fn from_owned_program<'arena>(
2214 arena: &'arena bumpalo::Bump,
2215 program: &Program,
2216) -> arena_ast::Program<'arena, 'arena> {
2217 arena_ast::Program {
2218 stmts: av_stmts(arena, &program.stmts),
2219 span: program.span,
2220 }
2221}
2222
2223#[inline]
2225fn av_str<'a>(arena: &'a bumpalo::Bump, s: &str) -> &'a str {
2226 arena.alloc_str(s)
2227}
2228
2229fn av_ident<'a>(arena: &'a bumpalo::Bump, ident: &Ident) -> arena_ast::Ident<'a> {
2230 match ident {
2231 Some(s) => arena_ast::Ident::name(arena.alloc_str(s)),
2232 None => arena_ast::Ident::ERROR,
2233 }
2234}
2235
2236fn av_name<'a>(arena: &'a bumpalo::Bump, name: &Name) -> arena_ast::Name<'a, 'a> {
2237 if name.kind == NameKind::Error {
2238 return arena_ast::Name::Error { span: name.span };
2239 }
2240 if name.parts.len() == 1 && name.kind == NameKind::Unqualified {
2241 return arena_ast::Name::Simple {
2242 value: arena.alloc_str(&name.parts[0]),
2243 span: name.span,
2244 };
2245 }
2246 let mut parts = arena_ast::ArenaVec::with_capacity_in(name.parts.len(), arena);
2247 for p in name.parts.iter() {
2248 parts.push(arena.alloc_str(p) as &str);
2249 }
2250 arena_ast::Name::Complex {
2251 parts,
2252 kind: name.kind,
2253 span: name.span,
2254 }
2255}
2256
2257fn av_type_hint<'a>(arena: &'a bumpalo::Bump, th: &TypeHint) -> arena_ast::TypeHint<'a, 'a> {
2258 arena_ast::TypeHint {
2259 kind: av_type_hint_kind(arena, &th.kind),
2260 span: th.span,
2261 }
2262}
2263
2264fn av_type_hint_kind<'a>(
2265 arena: &'a bumpalo::Bump,
2266 k: &TypeHintKind,
2267) -> arena_ast::TypeHintKind<'a, 'a> {
2268 match k {
2269 TypeHintKind::Named(n) => arena_ast::TypeHintKind::Named(av_name(arena, n)),
2270 TypeHintKind::Keyword(b, span) => arena_ast::TypeHintKind::Keyword(*b, *span),
2271 TypeHintKind::Nullable(inner) => {
2272 arena_ast::TypeHintKind::Nullable(arena.alloc(av_type_hint(arena, inner)))
2273 }
2274 TypeHintKind::Union(types) => {
2275 let mut v = arena_ast::ArenaVec::with_capacity_in(types.len(), arena);
2276 for t in types.iter() {
2277 v.push(av_type_hint(arena, t));
2278 }
2279 arena_ast::TypeHintKind::Union(v)
2280 }
2281 TypeHintKind::Intersection(types) => {
2282 let mut v = arena_ast::ArenaVec::with_capacity_in(types.len(), arena);
2283 for t in types.iter() {
2284 v.push(av_type_hint(arena, t));
2285 }
2286 arena_ast::TypeHintKind::Intersection(v)
2287 }
2288 }
2289}
2290
2291fn av_arg<'a>(arena: &'a bumpalo::Bump, arg: &Arg) -> arena_ast::Arg<'a, 'a> {
2292 arena_ast::Arg {
2293 name: arg.name.as_ref().map(|n| av_name(arena, n)),
2294 value: arg.value.as_ref().map(|v| av_expr(arena, v)),
2295 unpack: arg.unpack,
2296 by_ref: arg.by_ref,
2297 span: arg.span,
2298 }
2299}
2300
2301fn av_args<'a>(
2302 arena: &'a bumpalo::Bump,
2303 args: &[Arg],
2304) -> arena_ast::ArenaVec<'a, arena_ast::Arg<'a, 'a>> {
2305 let mut v = arena_ast::ArenaVec::with_capacity_in(args.len(), arena);
2306 for a in args.iter() {
2307 v.push(av_arg(arena, a));
2308 }
2309 v
2310}
2311
2312fn av_attr<'a>(arena: &'a bumpalo::Bump, attr: &Attribute) -> arena_ast::Attribute<'a, 'a> {
2313 arena_ast::Attribute {
2314 name: av_name(arena, &attr.name),
2315 args: av_args(arena, &attr.args),
2316 span: attr.span,
2317 }
2318}
2319
2320fn av_attrs<'a>(
2321 arena: &'a bumpalo::Bump,
2322 attrs: &[Attribute],
2323) -> arena_ast::ArenaVec<'a, arena_ast::Attribute<'a, 'a>> {
2324 let mut v = arena_ast::ArenaVec::with_capacity_in(attrs.len(), arena);
2325 for a in attrs.iter() {
2326 v.push(av_attr(arena, a));
2327 }
2328 v
2329}
2330
2331fn av_comment<'a>(arena: &'a bumpalo::Bump, c: &Comment) -> arena_ast::Comment<'a> {
2332 arena_ast::Comment {
2333 kind: c.kind,
2334 text: arena.alloc_str(&c.text),
2335 span: c.span,
2336 }
2337}
2338
2339fn av_opt_comment<'a>(
2340 arena: &'a bumpalo::Bump,
2341 c: &Option<Comment>,
2342) -> Option<arena_ast::Comment<'a>> {
2343 c.as_ref().map(|c| av_comment(arena, c))
2344}
2345
2346fn av_string_parts<'a>(
2347 arena: &'a bumpalo::Bump,
2348 parts: &[StringPart],
2349) -> arena_ast::ArenaVec<'a, arena_ast::StringPart<'a, 'a>> {
2350 let mut v = arena_ast::ArenaVec::with_capacity_in(parts.len(), arena);
2351 for p in parts.iter() {
2352 v.push(match p {
2353 StringPart::Literal(s) => arena_ast::StringPart::Literal(arena.alloc_str(s)),
2354 StringPart::Expr(e) => arena_ast::StringPart::Expr(av_expr(arena, e)),
2355 });
2356 }
2357 v
2358}
2359
2360fn av_expr<'a>(arena: &'a bumpalo::Bump, expr: &Expr) -> arena_ast::Expr<'a, 'a> {
2361 arena_ast::Expr {
2362 kind: av_expr_kind(arena, &expr.kind),
2363 span: expr.span,
2364 }
2365}
2366
2367fn av_exprs<'a>(
2368 arena: &'a bumpalo::Bump,
2369 exprs: &[Expr],
2370) -> arena_ast::ArenaVec<'a, arena_ast::Expr<'a, 'a>> {
2371 let mut v = arena_ast::ArenaVec::with_capacity_in(exprs.len(), arena);
2372 for e in exprs.iter() {
2373 v.push(av_expr(arena, e));
2374 }
2375 v
2376}
2377
2378fn av_namestr<'a>(arena: &'a bumpalo::Bump, s: &str) -> arena_ast::NameStr<'a, 'a> {
2379 arena_ast::NameStr::__arena(arena.alloc_str(s))
2380}
2381
2382fn av_expr_kind<'a>(arena: &'a bumpalo::Bump, k: &ExprKind) -> arena_ast::ExprKind<'a, 'a> {
2383 match k {
2384 ExprKind::Int(v) => arena_ast::ExprKind::Int(*v),
2385 ExprKind::Float(v) => arena_ast::ExprKind::Float(*v),
2386 ExprKind::String(s) => arena_ast::ExprKind::String(arena.alloc_str(s)),
2387 ExprKind::InterpolatedString(parts) => {
2388 arena_ast::ExprKind::InterpolatedString(av_string_parts(arena, parts))
2389 }
2390 ExprKind::Heredoc { label, parts } => arena_ast::ExprKind::Heredoc {
2391 label: arena.alloc_str(label),
2392 parts: av_string_parts(arena, parts),
2393 },
2394 ExprKind::Nowdoc { label, value } => arena_ast::ExprKind::Nowdoc {
2395 label: arena.alloc_str(label),
2396 value: arena.alloc_str(value),
2397 },
2398 ExprKind::ShellExec(parts) => arena_ast::ExprKind::ShellExec(av_string_parts(arena, parts)),
2399 ExprKind::Bool(v) => arena_ast::ExprKind::Bool(*v),
2400 ExprKind::Null => arena_ast::ExprKind::Null,
2401 ExprKind::Variable(s) => arena_ast::ExprKind::Variable(av_namestr(arena, s)),
2402 ExprKind::VariableVariable(inner) => {
2403 arena_ast::ExprKind::VariableVariable(arena.alloc(av_expr(arena, inner)))
2404 }
2405 ExprKind::Identifier(s) => arena_ast::ExprKind::Identifier(av_namestr(arena, s)),
2406 ExprKind::Assign(a) => arena_ast::ExprKind::Assign(arena_ast::AssignExpr {
2407 target: arena.alloc(av_expr(arena, &a.target)),
2408 op: a.op,
2409 value: arena.alloc(av_expr(arena, &a.value)),
2410 by_ref: a.by_ref,
2411 }),
2412 ExprKind::Binary(b) => arena_ast::ExprKind::Binary(arena_ast::BinaryExpr {
2413 left: arena.alloc(av_expr(arena, &b.left)),
2414 op: b.op,
2415 right: arena.alloc(av_expr(arena, &b.right)),
2416 }),
2417 ExprKind::UnaryPrefix(u) => arena_ast::ExprKind::UnaryPrefix(arena_ast::UnaryPrefixExpr {
2418 op: u.op,
2419 operand: arena.alloc(av_expr(arena, &u.operand)),
2420 }),
2421 ExprKind::UnaryPostfix(u) => {
2422 arena_ast::ExprKind::UnaryPostfix(arena_ast::UnaryPostfixExpr {
2423 operand: arena.alloc(av_expr(arena, &u.operand)),
2424 op: u.op,
2425 })
2426 }
2427 ExprKind::Ternary(t) => arena_ast::ExprKind::Ternary(arena_ast::TernaryExpr {
2428 condition: arena.alloc(av_expr(arena, &t.condition)),
2429 then_expr: t
2430 .then_expr
2431 .as_ref()
2432 .map(|e| &*arena.alloc(av_expr(arena, e))),
2433 else_expr: arena.alloc(av_expr(arena, &t.else_expr)),
2434 }),
2435 ExprKind::NullCoalesce(n) => {
2436 arena_ast::ExprKind::NullCoalesce(arena_ast::NullCoalesceExpr {
2437 left: arena.alloc(av_expr(arena, &n.left)),
2438 right: arena.alloc(av_expr(arena, &n.right)),
2439 })
2440 }
2441 ExprKind::FunctionCall(f) => {
2442 arena_ast::ExprKind::FunctionCall(arena_ast::FunctionCallExpr {
2443 name: arena.alloc(av_expr(arena, &f.name)),
2444 args: av_args(arena, &f.args),
2445 })
2446 }
2447 ExprKind::Array(elems) => {
2448 let mut v = arena_ast::ArenaVec::with_capacity_in(elems.len(), arena);
2449 for e in elems.iter() {
2450 v.push(arena_ast::ArrayElement {
2451 key: e.key.as_ref().map(|k| av_expr(arena, k)),
2452 value: av_expr(arena, &e.value),
2453 unpack: e.unpack,
2454 by_ref: e.by_ref,
2455 span: e.span,
2456 });
2457 }
2458 arena_ast::ExprKind::Array(v)
2459 }
2460 ExprKind::ArrayAccess(a) => arena_ast::ExprKind::ArrayAccess(arena_ast::ArrayAccessExpr {
2461 array: arena.alloc(av_expr(arena, &a.array)),
2462 index: a.index.as_ref().map(|e| &*arena.alloc(av_expr(arena, e))),
2463 }),
2464 ExprKind::Print(e) => arena_ast::ExprKind::Print(arena.alloc(av_expr(arena, e))),
2465 ExprKind::Parenthesized(e) => {
2466 arena_ast::ExprKind::Parenthesized(arena.alloc(av_expr(arena, e)))
2467 }
2468 ExprKind::Cast(kind, e) => arena_ast::ExprKind::Cast(*kind, arena.alloc(av_expr(arena, e))),
2469 ExprKind::ErrorSuppress(e) => {
2470 arena_ast::ExprKind::ErrorSuppress(arena.alloc(av_expr(arena, e)))
2471 }
2472 ExprKind::Isset(exprs) => arena_ast::ExprKind::Isset(av_exprs(arena, exprs)),
2473 ExprKind::Empty(e) => arena_ast::ExprKind::Empty(arena.alloc(av_expr(arena, e))),
2474 ExprKind::Include(kind, e) => {
2475 arena_ast::ExprKind::Include(*kind, arena.alloc(av_expr(arena, e)))
2476 }
2477 ExprKind::Eval(e) => arena_ast::ExprKind::Eval(arena.alloc(av_expr(arena, e))),
2478 ExprKind::Exit(e) => {
2479 arena_ast::ExprKind::Exit(e.as_ref().map(|e| &*arena.alloc(av_expr(arena, e))))
2480 }
2481 ExprKind::MagicConst(m) => arena_ast::ExprKind::MagicConst(*m),
2482 ExprKind::Clone(e) => arena_ast::ExprKind::Clone(arena.alloc(av_expr(arena, e))),
2483 ExprKind::CloneWith(obj, props) => arena_ast::ExprKind::CloneWith(
2484 arena.alloc(av_expr(arena, obj)),
2485 arena.alloc(av_expr(arena, props)),
2486 ),
2487 ExprKind::New(n) => arena_ast::ExprKind::New(arena_ast::NewExpr {
2488 class: arena.alloc(av_expr(arena, &n.class)),
2489 args: av_args(arena, &n.args),
2490 }),
2491 ExprKind::PropertyAccess(p) => {
2492 arena_ast::ExprKind::PropertyAccess(arena_ast::PropertyAccessExpr {
2493 object: arena.alloc(av_expr(arena, &p.object)),
2494 property: arena.alloc(av_expr(arena, &p.property)),
2495 })
2496 }
2497 ExprKind::NullsafePropertyAccess(p) => {
2498 arena_ast::ExprKind::NullsafePropertyAccess(arena_ast::PropertyAccessExpr {
2499 object: arena.alloc(av_expr(arena, &p.object)),
2500 property: arena.alloc(av_expr(arena, &p.property)),
2501 })
2502 }
2503 ExprKind::MethodCall(m) => {
2504 arena_ast::ExprKind::MethodCall(arena.alloc(arena_ast::MethodCallExpr {
2505 object: arena.alloc(av_expr(arena, &m.object)),
2506 method: arena.alloc(av_expr(arena, &m.method)),
2507 args: av_args(arena, &m.args),
2508 }))
2509 }
2510 ExprKind::NullsafeMethodCall(m) => {
2511 arena_ast::ExprKind::NullsafeMethodCall(arena.alloc(arena_ast::MethodCallExpr {
2512 object: arena.alloc(av_expr(arena, &m.object)),
2513 method: arena.alloc(av_expr(arena, &m.method)),
2514 args: av_args(arena, &m.args),
2515 }))
2516 }
2517 ExprKind::StaticPropertyAccess(s) => {
2518 arena_ast::ExprKind::StaticPropertyAccess(arena_ast::StaticAccessExpr {
2519 class: arena.alloc(av_expr(arena, &s.class)),
2520 member: arena.alloc(av_expr(arena, &s.member)),
2521 })
2522 }
2523 ExprKind::StaticMethodCall(s) => {
2524 arena_ast::ExprKind::StaticMethodCall(arena.alloc(arena_ast::StaticMethodCallExpr {
2525 class: arena.alloc(av_expr(arena, &s.class)),
2526 method: arena.alloc(av_expr(arena, &s.method)),
2527 args: av_args(arena, &s.args),
2528 }))
2529 }
2530 ExprKind::StaticDynMethodCall(s) => arena_ast::ExprKind::StaticDynMethodCall(arena.alloc(
2531 arena_ast::StaticDynMethodCallExpr {
2532 class: arena.alloc(av_expr(arena, &s.class)),
2533 method: arena.alloc(av_expr(arena, &s.method)),
2534 args: av_args(arena, &s.args),
2535 },
2536 )),
2537 ExprKind::ClassConstAccess(s) => {
2538 arena_ast::ExprKind::ClassConstAccess(arena_ast::StaticAccessExpr {
2539 class: arena.alloc(av_expr(arena, &s.class)),
2540 member: arena.alloc(av_expr(arena, &s.member)),
2541 })
2542 }
2543 ExprKind::ClassConstAccessDynamic { class, member } => {
2544 arena_ast::ExprKind::ClassConstAccessDynamic {
2545 class: arena.alloc(av_expr(arena, class)),
2546 member: arena.alloc(av_expr(arena, member)),
2547 }
2548 }
2549 ExprKind::StaticPropertyAccessDynamic { class, member } => {
2550 arena_ast::ExprKind::StaticPropertyAccessDynamic {
2551 class: arena.alloc(av_expr(arena, class)),
2552 member: arena.alloc(av_expr(arena, member)),
2553 }
2554 }
2555 ExprKind::Closure(c) => arena_ast::ExprKind::Closure(arena.alloc(arena_ast::ClosureExpr {
2556 is_static: c.is_static,
2557 by_ref: c.by_ref,
2558 params: av_params(arena, &c.params),
2559 use_vars: {
2560 let mut v = arena_ast::ArenaVec::with_capacity_in(c.use_vars.len(), arena);
2561 for uv in c.use_vars.iter() {
2562 v.push(arena_ast::ClosureUseVar {
2563 name: arena.alloc_str(&uv.name),
2564 by_ref: uv.by_ref,
2565 span: uv.span,
2566 });
2567 }
2568 v
2569 },
2570 return_type: c.return_type.as_ref().map(|t| av_type_hint(arena, t)),
2571 body: &*arena.alloc(av_block(arena, &c.body)),
2572 attributes: av_attrs(arena, &c.attributes),
2573 })),
2574 ExprKind::ArrowFunction(f) => {
2575 arena_ast::ExprKind::ArrowFunction(arena.alloc(arena_ast::ArrowFunctionExpr {
2576 is_static: f.is_static,
2577 by_ref: f.by_ref,
2578 params: av_params(arena, &f.params),
2579 return_type: f.return_type.as_ref().map(|t| av_type_hint(arena, t)),
2580 body: arena.alloc(av_expr(arena, &f.body)),
2581 attributes: av_attrs(arena, &f.attributes),
2582 }))
2583 }
2584 ExprKind::Match(m) => arena_ast::ExprKind::Match(arena_ast::MatchExpr {
2585 subject: arena.alloc(av_expr(arena, &m.subject)),
2586 arms: {
2587 let mut v = arena_ast::ArenaVec::with_capacity_in(m.arms.len(), arena);
2588 for arm in m.arms.iter() {
2589 v.push(arena_ast::MatchArm {
2590 conditions: arm.conditions.as_ref().map(|conds| av_exprs(arena, conds)),
2591 body: av_expr(arena, &arm.body),
2592 span: arm.span,
2593 });
2594 }
2595 v
2596 },
2597 brace_start: m.brace_start,
2598 }),
2599 ExprKind::ThrowExpr(e) => arena_ast::ExprKind::ThrowExpr(arena.alloc(av_expr(arena, e))),
2600 ExprKind::Yield(y) => arena_ast::ExprKind::Yield(arena_ast::YieldExpr {
2601 key: y.key.as_ref().map(|e| &*arena.alloc(av_expr(arena, e))),
2602 value: y.value.as_ref().map(|e| &*arena.alloc(av_expr(arena, e))),
2603 is_from: y.is_from,
2604 }),
2605 ExprKind::AnonymousClass(cls) => {
2606 arena_ast::ExprKind::AnonymousClass(arena.alloc(av_class_decl(arena, cls)))
2607 }
2608 ExprKind::CallableCreate(c) => {
2609 arena_ast::ExprKind::CallableCreate(arena_ast::CallableCreateExpr {
2610 kind: match &c.kind {
2611 CallableCreateKind::Function(e) => {
2612 arena_ast::CallableCreateKind::Function(arena.alloc(av_expr(arena, e)))
2613 }
2614 CallableCreateKind::Method { object, method } => {
2615 arena_ast::CallableCreateKind::Method {
2616 object: arena.alloc(av_expr(arena, object)),
2617 method: arena.alloc(av_expr(arena, method)),
2618 }
2619 }
2620 CallableCreateKind::NullsafeMethod { object, method } => {
2621 arena_ast::CallableCreateKind::NullsafeMethod {
2622 object: arena.alloc(av_expr(arena, object)),
2623 method: arena.alloc(av_expr(arena, method)),
2624 }
2625 }
2626 CallableCreateKind::StaticMethod { class, method } => {
2627 arena_ast::CallableCreateKind::StaticMethod {
2628 class: arena.alloc(av_expr(arena, class)),
2629 method: arena.alloc(av_expr(arena, method)),
2630 }
2631 }
2632 },
2633 })
2634 }
2635 ExprKind::Omit => arena_ast::ExprKind::Omit,
2636 ExprKind::Error => arena_ast::ExprKind::Error,
2637 }
2638}
2639
2640fn av_param<'a>(arena: &'a bumpalo::Bump, p: &Param) -> arena_ast::Param<'a, 'a> {
2641 arena_ast::Param {
2642 name: av_ident(arena, &p.name),
2643 type_hint: p.type_hint.as_ref().map(|t| av_type_hint(arena, t)),
2644 default: p.default.as_ref().map(|e| av_expr(arena, e)),
2645 by_ref: p.by_ref,
2646 variadic: p.variadic,
2647 is_readonly: p.is_readonly,
2648 is_final: p.is_final,
2649 visibility: p.visibility,
2650 set_visibility: p.set_visibility,
2651 attributes: av_attrs(arena, &p.attributes),
2652 hooks: av_hooks(arena, &p.hooks),
2653 doc_comment: av_opt_comment(arena, &p.doc_comment),
2654 span: p.span,
2655 }
2656}
2657
2658fn av_params<'a>(
2659 arena: &'a bumpalo::Bump,
2660 params: &[Param],
2661) -> arena_ast::ArenaVec<'a, arena_ast::Param<'a, 'a>> {
2662 let mut v = arena_ast::ArenaVec::with_capacity_in(params.len(), arena);
2663 for p in params.iter() {
2664 v.push(av_param(arena, p));
2665 }
2666 v
2667}
2668
2669fn av_hook<'a>(arena: &'a bumpalo::Bump, h: &PropertyHook) -> arena_ast::PropertyHook<'a, 'a> {
2670 arena_ast::PropertyHook {
2671 kind: h.kind,
2672 body: match &h.body {
2673 PropertyHookBody::Block(block) => {
2674 arena_ast::PropertyHookBody::Block(arena.alloc(av_block(arena, block)))
2675 }
2676 PropertyHookBody::Expression(e) => {
2677 arena_ast::PropertyHookBody::Expression(av_expr(arena, e))
2678 }
2679 PropertyHookBody::Abstract => arena_ast::PropertyHookBody::Abstract,
2680 },
2681 is_final: h.is_final,
2682 by_ref: h.by_ref,
2683 params: av_params(arena, &h.params),
2684 attributes: av_attrs(arena, &h.attributes),
2685 span: h.span,
2686 }
2687}
2688
2689fn av_hooks<'a>(
2690 arena: &'a bumpalo::Bump,
2691 hooks: &[PropertyHook],
2692) -> arena_ast::ArenaVec<'a, arena_ast::PropertyHook<'a, 'a>> {
2693 let mut v = arena_ast::ArenaVec::with_capacity_in(hooks.len(), arena);
2694 for h in hooks.iter() {
2695 v.push(av_hook(arena, h));
2696 }
2697 v
2698}
2699
2700fn av_stmt<'a>(arena: &'a bumpalo::Bump, stmt: &Stmt) -> arena_ast::Stmt<'a, 'a> {
2701 arena_ast::Stmt {
2702 kind: av_stmt_kind(arena, &stmt.kind),
2703 span: stmt.span,
2704 doc_comment: stmt.doc_comment.as_ref().map(|c| {
2705 &*arena.alloc(arena_ast::Comment {
2706 kind: c.kind,
2707 text: arena.alloc_str(&c.text),
2708 span: c.span,
2709 })
2710 }),
2711 }
2712}
2713
2714fn av_stmts<'a>(
2715 arena: &'a bumpalo::Bump,
2716 stmts: &[Stmt],
2717) -> arena_ast::ArenaVec<'a, arena_ast::Stmt<'a, 'a>> {
2718 let mut v = arena_ast::ArenaVec::with_capacity_in(stmts.len(), arena);
2719 for s in stmts.iter() {
2720 v.push(av_stmt(arena, s));
2721 }
2722 v
2723}
2724
2725fn av_block<'a>(arena: &'a bumpalo::Bump, block: &Block) -> arena_ast::Block<'a, 'a> {
2726 arena_ast::Block {
2727 stmts: av_stmts(arena, &block.stmts),
2728 span: block.span,
2729 }
2730}
2731
2732fn av_stmt_kind<'a>(arena: &'a bumpalo::Bump, k: &StmtKind) -> arena_ast::StmtKind<'a, 'a> {
2733 match k {
2734 StmtKind::Expression(e) => arena_ast::StmtKind::Expression(arena.alloc(av_expr(arena, e))),
2735 StmtKind::Echo(exprs) => arena_ast::StmtKind::Echo(av_exprs(arena, exprs)),
2736 StmtKind::Return(e) => {
2737 arena_ast::StmtKind::Return(e.as_ref().map(|e| &*arena.alloc(av_expr(arena, e))))
2738 }
2739 StmtKind::Block(block) => arena_ast::StmtKind::Block(arena.alloc(av_block(arena, block))),
2740 StmtKind::If(s) => arena_ast::StmtKind::If(
2741 arena.alloc(arena_ast::IfStmt {
2742 condition: av_expr(arena, &s.condition),
2743 then_branch: arena.alloc(av_stmt(arena, &s.then_branch)),
2744 elseif_branches: {
2745 let mut v =
2746 arena_ast::ArenaVec::with_capacity_in(s.elseif_branches.len(), arena);
2747 for b in s.elseif_branches.iter() {
2748 v.push(arena_ast::ElseIfBranch {
2749 condition: av_expr(arena, &b.condition),
2750 body: av_stmt(arena, &b.body),
2751 span: b.span,
2752 });
2753 }
2754 v
2755 },
2756 else_branch: s
2757 .else_branch
2758 .as_ref()
2759 .map(|b| &*arena.alloc(av_stmt(arena, b))),
2760 else_kw_start: s.else_kw_start,
2761 uses_alternative: s.uses_alternative,
2762 }),
2763 ),
2764 StmtKind::While(s) => arena_ast::StmtKind::While(arena.alloc(arena_ast::WhileStmt {
2765 condition: av_expr(arena, &s.condition),
2766 body: arena.alloc(av_stmt(arena, &s.body)),
2767 uses_alternative: s.uses_alternative,
2768 })),
2769 StmtKind::For(s) => arena_ast::StmtKind::For(arena.alloc(arena_ast::ForStmt {
2770 init: av_exprs(arena, &s.init),
2771 condition: av_exprs(arena, &s.condition),
2772 update: av_exprs(arena, &s.update),
2773 body: arena.alloc(av_stmt(arena, &s.body)),
2774 uses_alternative: s.uses_alternative,
2775 })),
2776 StmtKind::Foreach(s) => arena_ast::StmtKind::Foreach(arena.alloc(arena_ast::ForeachStmt {
2777 expr: av_expr(arena, &s.expr),
2778 key: s.key.as_ref().map(|e| av_expr(arena, e)),
2779 value: av_expr(arena, &s.value),
2780 body: arena.alloc(av_stmt(arena, &s.body)),
2781 uses_alternative: s.uses_alternative,
2782 })),
2783 StmtKind::DoWhile(s) => arena_ast::StmtKind::DoWhile(arena.alloc(arena_ast::DoWhileStmt {
2784 body: arena.alloc(av_stmt(arena, &s.body)),
2785 condition: av_expr(arena, &s.condition),
2786 })),
2787 StmtKind::Function(f) => {
2788 arena_ast::StmtKind::Function(arena.alloc(av_function_decl(arena, f)))
2789 }
2790 StmtKind::Break(e) => {
2791 arena_ast::StmtKind::Break(e.as_ref().map(|e| &*arena.alloc(av_expr(arena, e))))
2792 }
2793 StmtKind::Continue(e) => {
2794 arena_ast::StmtKind::Continue(e.as_ref().map(|e| &*arena.alloc(av_expr(arena, e))))
2795 }
2796 StmtKind::Switch(s) => arena_ast::StmtKind::Switch(arena.alloc(arena_ast::SwitchStmt {
2797 expr: av_expr(arena, &s.expr),
2798 body: {
2799 let mut cases = arena_ast::ArenaVec::with_capacity_in(s.body.cases.len(), arena);
2800 for c in s.body.cases.iter() {
2801 cases.push(arena_ast::SwitchCase {
2802 value: c.value.as_ref().map(|vl| av_expr(arena, vl)),
2803 body: av_stmts(arena, &c.body),
2804 span: c.span,
2805 });
2806 }
2807 arena_ast::SwitchBody {
2808 cases,
2809 span: s.body.span,
2810 }
2811 },
2812 uses_alternative: s.uses_alternative,
2813 })),
2814 StmtKind::Goto(ident) => arena_ast::StmtKind::Goto(av_ident(arena, ident)),
2815 StmtKind::Label(s) => arena_ast::StmtKind::Label(av_str(arena, s)),
2816 StmtKind::Declare(d) => arena_ast::StmtKind::Declare(arena.alloc(arena_ast::DeclareStmt {
2817 directives: {
2818 let mut v = arena_ast::ArenaVec::with_capacity_in(d.directives.len(), arena);
2819 for (k, val) in d.directives.iter() {
2820 v.push((arena.alloc_str(k) as &str, av_expr(arena, val)));
2821 }
2822 v
2823 },
2824 body: d.body.as_ref().map(|b| &*arena.alloc(av_stmt(arena, b))),
2825 uses_alternative: d.uses_alternative,
2826 })),
2827 StmtKind::Unset(exprs) => arena_ast::StmtKind::Unset(av_exprs(arena, exprs)),
2828 StmtKind::Throw(e) => arena_ast::StmtKind::Throw(arena.alloc(av_expr(arena, e))),
2829 StmtKind::TryCatch(t) => arena_ast::StmtKind::TryCatch(
2830 arena.alloc(arena_ast::TryCatchStmt {
2831 body: arena.alloc(av_block(arena, &t.body)),
2832 catches: {
2833 let mut v = arena_ast::ArenaVec::with_capacity_in(t.catches.len(), arena);
2834 for c in t.catches.iter() {
2835 let mut types = arena_ast::ArenaVec::with_capacity_in(c.types.len(), arena);
2836 for n in c.types.iter() {
2837 types.push(av_name(arena, n));
2838 }
2839 v.push(arena_ast::CatchClause {
2840 types,
2841 var: c.var.as_deref().map(|s| av_str(arena, s)),
2842 body: arena.alloc(av_block(arena, &c.body)),
2843 span: c.span,
2844 });
2845 }
2846 v
2847 },
2848 finally: t
2849 .finally
2850 .as_deref()
2851 .map(|f| &*arena.alloc(av_block(arena, f))),
2852 finally_kw_start: t.finally_kw_start,
2853 }),
2854 ),
2855 StmtKind::Global(exprs) => arena_ast::StmtKind::Global(av_exprs(arena, exprs)),
2856 StmtKind::Class(cls) => arena_ast::StmtKind::Class(arena.alloc(av_class_decl(arena, cls))),
2857 StmtKind::Interface(iface) => {
2858 arena_ast::StmtKind::Interface(arena.alloc(av_interface_decl(arena, iface)))
2859 }
2860 StmtKind::Trait(tr) => arena_ast::StmtKind::Trait(arena.alloc(av_trait_decl(arena, tr))),
2861 StmtKind::Enum(en) => arena_ast::StmtKind::Enum(arena.alloc(av_enum_decl(arena, en))),
2862 StmtKind::Namespace(ns) => {
2863 arena_ast::StmtKind::Namespace(arena.alloc(arena_ast::NamespaceDecl {
2864 name: ns.name.as_ref().map(|n| av_name(arena, n)),
2865 body: match &ns.body {
2866 NamespaceBody::Braced(block) => {
2867 arena_ast::NamespaceBody::Braced(&*arena.alloc(av_block(arena, block)))
2868 }
2869 NamespaceBody::Simple => arena_ast::NamespaceBody::Simple,
2870 },
2871 }))
2872 }
2873 StmtKind::Use(u) => arena_ast::StmtKind::Use(arena.alloc(arena_ast::UseDecl {
2874 kind: u.kind,
2875 uses: {
2876 let mut v = arena_ast::ArenaVec::with_capacity_in(u.uses.len(), arena);
2877 for item in u.uses.iter() {
2878 v.push(arena_ast::UseItem {
2879 name: av_name(arena, &item.name),
2880 alias: item.alias.as_deref().map(|s| av_str(arena, s)),
2881 kind: item.kind,
2882 span: item.span,
2883 });
2884 }
2885 v
2886 },
2887 })),
2888 StmtKind::Const(items) => {
2889 let mut v = arena_ast::ArenaVec::with_capacity_in(items.len(), arena);
2890 for item in items.iter() {
2891 v.push(arena_ast::ConstItem {
2892 name: av_ident(arena, &item.name),
2893 value: av_expr(arena, &item.value),
2894 attributes: av_attrs(arena, &item.attributes),
2895 span: item.span,
2896 doc_comment: av_opt_comment(arena, &item.doc_comment),
2897 });
2898 }
2899 arena_ast::StmtKind::Const(v)
2900 }
2901 StmtKind::StaticVar(vars) => {
2902 let mut v = arena_ast::ArenaVec::with_capacity_in(vars.len(), arena);
2903 for var in vars.iter() {
2904 v.push(arena_ast::StaticVar {
2905 name: av_ident(arena, &var.name),
2906 default: var.default.as_ref().map(|e| av_expr(arena, e)),
2907 span: var.span,
2908 });
2909 }
2910 arena_ast::StmtKind::StaticVar(v)
2911 }
2912 StmtKind::HaltCompiler(s) => arena_ast::StmtKind::HaltCompiler(av_str(arena, s)),
2913 StmtKind::Nop => arena_ast::StmtKind::Nop,
2914 StmtKind::InlineHtml(s) => arena_ast::StmtKind::InlineHtml(av_str(arena, s)),
2915 StmtKind::Error => arena_ast::StmtKind::Error,
2916 }
2917}
2918
2919fn av_function_decl<'a>(
2920 arena: &'a bumpalo::Bump,
2921 f: &FunctionDecl,
2922) -> arena_ast::FunctionDecl<'a, 'a> {
2923 arena_ast::FunctionDecl {
2924 name: av_ident(arena, &f.name),
2925 params: av_params(arena, &f.params),
2926 body: &*arena.alloc(av_block(arena, &f.body)),
2927 return_type: f.return_type.as_ref().map(|t| av_type_hint(arena, t)),
2928 by_ref: f.by_ref,
2929 attributes: av_attrs(arena, &f.attributes),
2930 doc_comment: av_opt_comment(arena, &f.doc_comment),
2931 }
2932}
2933
2934fn av_class_member<'a>(
2935 arena: &'a bumpalo::Bump,
2936 m: &ClassMember,
2937) -> arena_ast::ClassMember<'a, 'a> {
2938 arena_ast::ClassMember {
2939 kind: match &m.kind {
2940 ClassMemberKind::Property(p) => {
2941 arena_ast::ClassMemberKind::Property(arena_ast::PropertyDecl {
2942 name: av_ident(arena, &p.name),
2943 visibility: p.visibility,
2944 set_visibility: p.set_visibility,
2945 is_static: p.is_static,
2946 is_readonly: p.is_readonly,
2947 type_hint: p.type_hint.as_ref().map(|t| av_type_hint(arena, t)),
2948 default: p.default.as_ref().map(|e| av_expr(arena, e)),
2949 attributes: av_attrs(arena, &p.attributes),
2950 hooks: av_hooks(arena, &p.hooks),
2951 doc_comment: av_opt_comment(arena, &p.doc_comment),
2952 })
2953 }
2954 ClassMemberKind::Method(m) => {
2955 arena_ast::ClassMemberKind::Method(arena_ast::MethodDecl {
2956 name: av_ident(arena, &m.name),
2957 visibility: m.visibility,
2958 is_static: m.is_static,
2959 is_abstract: m.is_abstract,
2960 is_final: m.is_final,
2961 by_ref: m.by_ref,
2962 params: av_params(arena, &m.params),
2963 return_type: m.return_type.as_ref().map(|t| av_type_hint(arena, t)),
2964 body: m.body.as_deref().map(|b| &*arena.alloc(av_block(arena, b))),
2965 attributes: av_attrs(arena, &m.attributes),
2966 doc_comment: av_opt_comment(arena, &m.doc_comment),
2967 })
2968 }
2969 ClassMemberKind::ClassConst(c) => {
2970 arena_ast::ClassMemberKind::ClassConst(av_class_const(arena, c))
2971 }
2972 ClassMemberKind::TraitUse(t) => {
2973 arena_ast::ClassMemberKind::TraitUse(av_trait_use(arena, t))
2974 }
2975 },
2976 span: m.span,
2977 }
2978}
2979
2980fn av_class_members<'a>(
2981 arena: &'a bumpalo::Bump,
2982 members: &[ClassMember],
2983) -> arena_ast::ArenaVec<'a, arena_ast::ClassMember<'a, 'a>> {
2984 let mut v = arena_ast::ArenaVec::with_capacity_in(members.len(), arena);
2985 for m in members.iter() {
2986 v.push(av_class_member(arena, m));
2987 }
2988 v
2989}
2990
2991fn av_class_const<'a>(
2992 arena: &'a bumpalo::Bump,
2993 c: &ClassConstDecl,
2994) -> arena_ast::ClassConstDecl<'a, 'a> {
2995 arena_ast::ClassConstDecl {
2996 name: av_ident(arena, &c.name),
2997 visibility: c.visibility,
2998 is_final: c.is_final,
2999 type_hint: c
3000 .type_hint
3001 .as_ref()
3002 .map(|th| arena.alloc(av_type_hint(arena, th)) as &_),
3003 value: av_expr(arena, &c.value),
3004 attributes: av_attrs(arena, &c.attributes),
3005 doc_comment: av_opt_comment(arena, &c.doc_comment),
3006 }
3007}
3008
3009fn av_trait_use<'a>(arena: &'a bumpalo::Bump, t: &TraitUseDecl) -> arena_ast::TraitUseDecl<'a, 'a> {
3010 let mut traits = arena_ast::ArenaVec::with_capacity_in(t.traits.len(), arena);
3011 for n in t.traits.iter() {
3012 traits.push(av_name(arena, n));
3013 }
3014 let mut adaptations = arena_ast::ArenaVec::with_capacity_in(t.adaptations.len(), arena);
3015 for a in t.adaptations.iter() {
3016 adaptations.push(arena_ast::TraitAdaptation {
3017 kind: match &a.kind {
3018 TraitAdaptationKind::Precedence {
3019 trait_name,
3020 method,
3021 insteadof,
3022 } => {
3023 let mut instead = arena_ast::ArenaVec::with_capacity_in(insteadof.len(), arena);
3024 for n in insteadof.iter() {
3025 instead.push(av_name(arena, n));
3026 }
3027 arena_ast::TraitAdaptationKind::Precedence {
3028 trait_name: av_name(arena, trait_name),
3029 method: av_name(arena, method),
3030 insteadof: instead,
3031 }
3032 }
3033 TraitAdaptationKind::Alias {
3034 trait_name,
3035 method,
3036 new_modifier,
3037 new_name,
3038 } => arena_ast::TraitAdaptationKind::Alias {
3039 trait_name: trait_name.as_ref().map(|n| av_name(arena, n)),
3040 method: av_name(arena, method),
3041 new_modifier: *new_modifier,
3042 new_name: new_name.as_ref().map(|n| av_name(arena, n)),
3043 },
3044 },
3045 span: a.span,
3046 });
3047 }
3048 arena_ast::TraitUseDecl {
3049 traits,
3050 adaptations,
3051 adaptations_brace_start: t.adaptations_brace_start,
3052 doc_comment: av_opt_comment(arena, &t.doc_comment),
3053 }
3054}
3055
3056fn av_class_decl<'a>(arena: &'a bumpalo::Bump, cls: &ClassDecl) -> arena_ast::ClassDecl<'a, 'a> {
3057 let mut implements = arena_ast::ArenaVec::with_capacity_in(cls.implements.len(), arena);
3058 for n in cls.implements.iter() {
3059 implements.push(av_name(arena, n));
3060 }
3061 arena_ast::ClassDecl {
3062 name: cls.name.as_ref().map(|ident| av_ident(arena, ident)),
3063 modifiers: cls.modifiers.clone(),
3064 extends: cls.extends.as_ref().map(|n| av_name(arena, n)),
3065 implements,
3066 body: arena_ast::ClassBody {
3067 members: av_class_members(arena, &cls.body.members),
3068 span: cls.body.span,
3069 },
3070 attributes: av_attrs(arena, &cls.attributes),
3071 doc_comment: av_opt_comment(arena, &cls.doc_comment),
3072 }
3073}
3074
3075fn av_interface_decl<'a>(
3076 arena: &'a bumpalo::Bump,
3077 iface: &InterfaceDecl,
3078) -> arena_ast::InterfaceDecl<'a, 'a> {
3079 let mut extends = arena_ast::ArenaVec::with_capacity_in(iface.extends.len(), arena);
3080 for n in iface.extends.iter() {
3081 extends.push(av_name(arena, n));
3082 }
3083 arena_ast::InterfaceDecl {
3084 name: av_ident(arena, &iface.name),
3085 extends,
3086 body: arena_ast::ClassBody {
3087 members: av_class_members(arena, &iface.body.members),
3088 span: iface.body.span,
3089 },
3090 attributes: av_attrs(arena, &iface.attributes),
3091 doc_comment: av_opt_comment(arena, &iface.doc_comment),
3092 }
3093}
3094
3095fn av_trait_decl<'a>(arena: &'a bumpalo::Bump, tr: &TraitDecl) -> arena_ast::TraitDecl<'a, 'a> {
3096 arena_ast::TraitDecl {
3097 name: av_ident(arena, &tr.name),
3098 body: arena_ast::ClassBody {
3099 members: av_class_members(arena, &tr.body.members),
3100 span: tr.body.span,
3101 },
3102 attributes: av_attrs(arena, &tr.attributes),
3103 doc_comment: av_opt_comment(arena, &tr.doc_comment),
3104 }
3105}
3106
3107fn av_enum_decl<'a>(arena: &'a bumpalo::Bump, en: &EnumDecl) -> arena_ast::EnumDecl<'a, 'a> {
3108 let mut implements = arena_ast::ArenaVec::with_capacity_in(en.implements.len(), arena);
3109 for n in en.implements.iter() {
3110 implements.push(av_name(arena, n));
3111 }
3112 let mut members = arena_ast::ArenaVec::with_capacity_in(en.body.members.len(), arena);
3113 for m in en.body.members.iter() {
3114 members.push(arena_ast::EnumMember {
3115 kind: match &m.kind {
3116 EnumMemberKind::Case(c) => arena_ast::EnumMemberKind::Case(arena_ast::EnumCase {
3117 name: av_ident(arena, &c.name),
3118 value: c.value.as_ref().map(|e| av_expr(arena, e)),
3119 attributes: av_attrs(arena, &c.attributes),
3120 doc_comment: av_opt_comment(arena, &c.doc_comment),
3121 }),
3122 EnumMemberKind::Method(m) => {
3123 arena_ast::EnumMemberKind::Method(arena_ast::MethodDecl {
3124 name: av_ident(arena, &m.name),
3125 visibility: m.visibility,
3126 is_static: m.is_static,
3127 is_abstract: m.is_abstract,
3128 is_final: m.is_final,
3129 by_ref: m.by_ref,
3130 params: av_params(arena, &m.params),
3131 return_type: m.return_type.as_ref().map(|t| av_type_hint(arena, t)),
3132 body: m.body.as_deref().map(|b| &*arena.alloc(av_block(arena, b))),
3133 attributes: av_attrs(arena, &m.attributes),
3134 doc_comment: av_opt_comment(arena, &m.doc_comment),
3135 })
3136 }
3137 EnumMemberKind::ClassConst(c) => {
3138 arena_ast::EnumMemberKind::ClassConst(av_class_const(arena, c))
3139 }
3140 EnumMemberKind::TraitUse(t) => {
3141 arena_ast::EnumMemberKind::TraitUse(av_trait_use(arena, t))
3142 }
3143 },
3144 span: m.span,
3145 });
3146 }
3147 arena_ast::EnumDecl {
3148 name: av_ident(arena, &en.name),
3149 scalar_type: en.scalar_type.as_ref().map(|n| av_name(arena, n)),
3150 implements,
3151 body: arena_ast::EnumBody {
3152 members,
3153 span: en.body.span,
3154 },
3155 attributes: av_attrs(arena, &en.attributes),
3156 doc_comment: av_opt_comment(arena, &en.doc_comment),
3157 }
3158}