1use std::borrow::Cow;
2
3use serde::Serialize;
4
5use crate::Span;
6
7fn is_false(b: &bool) -> bool {
8 !*b
9}
10
11pub struct ArenaVec<'arena, T>(bumpalo::collections::Vec<'arena, T>);
13
14impl<'arena, T> ArenaVec<'arena, T> {
15 #[inline]
16 pub fn new_in(arena: &'arena bumpalo::Bump) -> Self {
17 Self(bumpalo::collections::Vec::new_in(arena))
18 }
19 #[inline]
20 pub fn with_capacity_in(cap: usize, arena: &'arena bumpalo::Bump) -> Self {
21 Self(bumpalo::collections::Vec::with_capacity_in(cap, arena))
22 }
23 #[inline]
24 pub fn push(&mut self, val: T) {
25 self.0.push(val)
26 }
27 #[inline]
28 pub fn is_empty(&self) -> bool {
29 self.0.is_empty()
30 }
31 #[inline]
32 pub fn len(&self) -> usize {
33 self.0.len()
34 }
35 #[inline]
36 pub fn last(&self) -> Option<&T> {
37 self.0.last()
38 }
39}
40
41impl<'arena, T> IntoIterator for ArenaVec<'arena, T> {
42 type Item = T;
43 type IntoIter = bumpalo::collections::vec::IntoIter<'arena, T>;
44 #[inline]
45 fn into_iter(self) -> Self::IntoIter {
46 self.0.into_iter()
47 }
48}
49
50impl<'arena, T> std::ops::Deref for ArenaVec<'arena, T> {
51 type Target = [T];
52 #[inline]
53 fn deref(&self) -> &[T] {
54 &self.0
55 }
56}
57
58impl<'arena, T> std::ops::DerefMut for ArenaVec<'arena, T> {
59 #[inline]
60 fn deref_mut(&mut self) -> &mut [T] {
61 &mut self.0
62 }
63}
64
65impl<'arena, T: serde::Serialize> serde::Serialize for ArenaVec<'arena, T> {
66 fn serialize<S: serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
67 self.0.as_slice().serialize(s)
68 }
69}
70
71impl<'arena, T: std::fmt::Debug> std::fmt::Debug for ArenaVec<'arena, T> {
72 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
73 self.0.as_slice().fmt(f)
74 }
75}
76
77#[derive(Debug, Serialize)]
79pub struct Comment<'src> {
80 pub kind: CommentKind,
81 pub text: &'src str,
83 pub span: Span,
84}
85
86#[derive(Debug, Serialize, Clone, Copy, PartialEq, Eq)]
88pub enum CommentKind {
89 Line,
91 Hash,
93 Block,
95 Doc,
97}
98
99#[derive(Debug, Serialize)]
105pub struct PhpDoc<'src> {
106 pub summary: Option<&'src str>,
108 pub description: Option<&'src str>,
110 pub tags: Vec<PhpDocTag<'src>>,
112}
113
114#[derive(Debug, Serialize)]
116pub enum PhpDocTag<'src> {
117 Param {
119 type_str: Option<&'src str>,
120 name: Option<&'src str>,
121 description: Option<&'src str>,
122 },
123 Return {
125 type_str: Option<&'src str>,
126 description: Option<&'src str>,
127 },
128 Var {
130 type_str: Option<&'src str>,
131 name: Option<&'src str>,
132 description: Option<&'src str>,
133 },
134 Throws {
136 type_str: Option<&'src str>,
137 description: Option<&'src str>,
138 },
139 Deprecated { description: Option<&'src str> },
141 Template {
143 name: &'src str,
144 bound: Option<&'src str>,
145 },
146 Extends { type_str: &'src str },
148 Implements { type_str: &'src str },
150 Method { signature: &'src str },
152 Property {
154 type_str: Option<&'src str>,
155 name: Option<&'src str>,
156 description: Option<&'src str>,
157 },
158 PropertyRead {
160 type_str: Option<&'src str>,
161 name: Option<&'src str>,
162 description: Option<&'src str>,
163 },
164 PropertyWrite {
166 type_str: Option<&'src str>,
167 name: Option<&'src str>,
168 description: Option<&'src str>,
169 },
170 See { reference: &'src str },
172 Link { url: &'src str },
174 Since { version: &'src str },
176 Author { name: &'src str },
178 Internal,
180 InheritDoc,
182 Assert {
184 type_str: Option<&'src str>,
185 name: Option<&'src str>,
186 },
187 TypeAlias {
189 name: Option<&'src str>,
190 type_str: Option<&'src str>,
191 },
192 ImportType { body: &'src str },
194 Suppress { rules: &'src str },
196 Pure,
198 Readonly,
200 Immutable,
202 Mixin { class: &'src str },
204 TemplateCovariant {
206 name: &'src str,
207 bound: Option<&'src str>,
208 },
209 TemplateContravariant {
211 name: &'src str,
212 bound: Option<&'src str>,
213 },
214 Generic {
216 tag: &'src str,
217 body: Option<&'src str>,
218 },
219}
220
221#[derive(Debug, Serialize)]
223pub struct Program<'arena, 'src> {
224 pub stmts: ArenaVec<'arena, Stmt<'arena, 'src>>,
225 pub span: Span,
226}
227
228pub enum Name<'arena, 'src> {
241 Simple { value: &'src str, span: Span },
244 Complex {
246 parts: ArenaVec<'arena, &'src str>,
247 kind: NameKind,
248 span: Span,
249 },
250}
251
252impl<'arena, 'src> Name<'arena, 'src> {
253 #[inline]
254 pub fn span(&self) -> Span {
255 match self {
256 Self::Simple { span, .. } | Self::Complex { span, .. } => *span,
257 }
258 }
259
260 #[inline]
261 pub fn kind(&self) -> NameKind {
262 match self {
263 Self::Simple { .. } => NameKind::Unqualified,
264 Self::Complex { kind, .. } => *kind,
265 }
266 }
267
268 #[inline]
271 pub fn to_string_repr(&self) -> Cow<'src, str> {
272 match self {
273 Self::Simple { value, .. } => Cow::Borrowed(value),
274 Self::Complex { parts, kind, .. } => {
275 let joined = parts.join("\\");
276 if *kind == NameKind::FullyQualified {
277 Cow::Owned(format!("\\{}", joined))
278 } else {
279 Cow::Owned(joined)
280 }
281 }
282 }
283 }
284
285 #[inline]
288 pub fn join_parts(&self) -> Cow<'src, str> {
289 match self {
290 Self::Simple { value, .. } => Cow::Borrowed(value),
291 Self::Complex { parts, .. } => Cow::Owned(parts.join("\\")),
292 }
293 }
294
295 #[inline]
298 pub fn parts_slice(&self) -> &[&'src str] {
299 match self {
300 Self::Simple { value, .. } => std::slice::from_ref(value),
301 Self::Complex { parts, .. } => parts,
302 }
303 }
304}
305
306impl<'arena, 'src> std::fmt::Debug for Name<'arena, 'src> {
307 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
308 match self {
309 Self::Simple { value, span } => f
310 .debug_struct("Name")
311 .field("parts", &std::slice::from_ref(value))
312 .field("kind", &NameKind::Unqualified)
313 .field("span", span)
314 .finish(),
315 Self::Complex { parts, kind, span } => f
316 .debug_struct("Name")
317 .field("parts", parts)
318 .field("kind", kind)
319 .field("span", span)
320 .finish(),
321 }
322 }
323}
324
325impl<'arena, 'src> serde::Serialize for Name<'arena, 'src> {
326 fn serialize<S: serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
327 use serde::ser::SerializeStruct;
328 let mut st = s.serialize_struct("Name", 3)?;
329 match self {
330 Self::Simple { value, span } => {
331 st.serialize_field("parts", std::slice::from_ref(value))?;
332 st.serialize_field("kind", &NameKind::Unqualified)?;
333 st.serialize_field("span", span)?;
334 }
335 Self::Complex { parts, kind, span } => {
336 st.serialize_field("parts", parts)?;
337 st.serialize_field("kind", kind)?;
338 st.serialize_field("span", span)?;
339 }
340 }
341 st.end()
342 }
343}
344
345#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
346pub enum NameKind {
347 Unqualified,
348 Qualified,
349 FullyQualified,
350 Relative,
351}
352
353#[repr(u8)]
356#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
357pub enum BuiltinType {
358 Int,
359 Integer,
360 Float,
361 Double,
362 String,
363 Bool,
364 Boolean,
365 Void,
366 Never,
367 Mixed,
368 Object,
369 Iterable,
370 Callable,
371 Array,
372 Self_,
373 Parent_,
374 Static,
375 Null,
376 True,
377 False,
378}
379
380impl BuiltinType {
381 #[inline]
383 pub fn as_str(self) -> &'static str {
384 match self {
385 Self::Int => "int",
386 Self::Integer => "integer",
387 Self::Float => "float",
388 Self::Double => "double",
389 Self::String => "string",
390 Self::Bool => "bool",
391 Self::Boolean => "boolean",
392 Self::Void => "void",
393 Self::Never => "never",
394 Self::Mixed => "mixed",
395 Self::Object => "object",
396 Self::Iterable => "iterable",
397 Self::Callable => "callable",
398 Self::Array => "array",
399 Self::Self_ => "self",
400 Self::Parent_ => "parent",
401 Self::Static => "static",
402 Self::Null => "null",
403 Self::True => "true",
404 Self::False => "false",
405 }
406 }
407}
408
409#[derive(Debug, Serialize)]
410pub struct TypeHint<'arena, 'src> {
411 pub kind: TypeHintKind<'arena, 'src>,
412 pub span: Span,
413}
414
415#[derive(Debug)]
423pub enum TypeHintKind<'arena, 'src> {
424 Named(Name<'arena, 'src>),
425 Keyword(BuiltinType, Span),
427 Nullable(&'arena TypeHint<'arena, 'src>),
428 Union(ArenaVec<'arena, TypeHint<'arena, 'src>>),
429 Intersection(ArenaVec<'arena, TypeHint<'arena, 'src>>),
430}
431
432impl<'arena, 'src> serde::Serialize for TypeHintKind<'arena, 'src> {
433 fn serialize<S: serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
434 match self {
435 Self::Named(name) => s.serialize_newtype_variant("TypeHintKind", 0, "Named", name),
437 Self::Nullable(inner) => {
438 s.serialize_newtype_variant("TypeHintKind", 2, "Nullable", inner)
439 }
440 Self::Union(types) => s.serialize_newtype_variant("TypeHintKind", 3, "Union", types),
441 Self::Intersection(types) => {
442 s.serialize_newtype_variant("TypeHintKind", 4, "Intersection", types)
443 }
444 Self::Keyword(builtin, span) => {
447 struct BuiltinNameRepr<'a>(&'a BuiltinType, &'a Span);
448 impl serde::Serialize for BuiltinNameRepr<'_> {
449 fn serialize<S: serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
450 use serde::ser::SerializeStruct;
451 let mut st = s.serialize_struct("Name", 3)?;
452 st.serialize_field("parts", &[self.0.as_str()])?;
453 st.serialize_field("kind", &NameKind::Unqualified)?;
454 st.serialize_field("span", self.1)?;
455 st.end()
456 }
457 }
458 s.serialize_newtype_variant(
459 "TypeHintKind",
460 0,
461 "Named",
462 &BuiltinNameRepr(builtin, span),
463 )
464 }
465 }
466 }
467}
468
469#[derive(Debug, Serialize)]
474pub struct Arg<'arena, 'src> {
475 pub name: Option<Cow<'src, str>>,
476 pub value: Expr<'arena, 'src>,
477 pub unpack: bool,
478 pub by_ref: bool,
479 pub span: Span,
480}
481
482#[derive(Debug, Serialize)]
487pub struct Attribute<'arena, 'src> {
488 pub name: Name<'arena, 'src>,
489 pub args: ArenaVec<'arena, Arg<'arena, 'src>>,
490 pub span: Span,
491}
492
493#[derive(Debug, Serialize)]
498pub struct Stmt<'arena, 'src> {
499 pub kind: StmtKind<'arena, 'src>,
500 pub span: Span,
501}
502
503#[derive(Debug, Serialize)]
504pub enum StmtKind<'arena, 'src> {
505 Expression(&'arena Expr<'arena, 'src>),
507
508 Echo(ArenaVec<'arena, Expr<'arena, 'src>>),
510
511 Return(Option<&'arena Expr<'arena, 'src>>),
513
514 Block(ArenaVec<'arena, Stmt<'arena, 'src>>),
516
517 If(&'arena IfStmt<'arena, 'src>),
519
520 While(&'arena WhileStmt<'arena, 'src>),
522
523 For(&'arena ForStmt<'arena, 'src>),
525
526 Foreach(&'arena ForeachStmt<'arena, 'src>),
528
529 DoWhile(&'arena DoWhileStmt<'arena, 'src>),
531
532 Function(&'arena FunctionDecl<'arena, 'src>),
534
535 Break(Option<&'arena Expr<'arena, 'src>>),
537
538 Continue(Option<&'arena Expr<'arena, 'src>>),
540
541 Switch(&'arena SwitchStmt<'arena, 'src>),
543
544 Goto(&'src str),
546
547 Label(&'arena str),
549
550 Declare(&'arena DeclareStmt<'arena, 'src>),
552
553 Unset(ArenaVec<'arena, Expr<'arena, 'src>>),
555
556 Throw(&'arena Expr<'arena, 'src>),
558
559 TryCatch(&'arena TryCatchStmt<'arena, 'src>),
561
562 Global(ArenaVec<'arena, Expr<'arena, 'src>>),
564
565 Class(&'arena ClassDecl<'arena, 'src>),
567
568 Interface(&'arena InterfaceDecl<'arena, 'src>),
570
571 Trait(&'arena TraitDecl<'arena, 'src>),
573
574 Enum(&'arena EnumDecl<'arena, 'src>),
576
577 Namespace(&'arena NamespaceDecl<'arena, 'src>),
579
580 Use(&'arena UseDecl<'arena, 'src>),
582
583 Const(ArenaVec<'arena, ConstItem<'arena, 'src>>),
585
586 StaticVar(ArenaVec<'arena, StaticVar<'arena, 'src>>),
588
589 HaltCompiler(&'src str),
591
592 Nop,
594
595 InlineHtml(&'src str),
597
598 Error,
600}
601
602#[derive(Debug, Serialize)]
603pub struct IfStmt<'arena, 'src> {
604 pub condition: Expr<'arena, 'src>,
605 pub then_branch: &'arena Stmt<'arena, 'src>,
606 pub elseif_branches: ArenaVec<'arena, ElseIfBranch<'arena, 'src>>,
607 pub else_branch: Option<&'arena Stmt<'arena, 'src>>,
608}
609
610#[derive(Debug, Serialize)]
611pub struct ElseIfBranch<'arena, 'src> {
612 pub condition: Expr<'arena, 'src>,
613 pub body: Stmt<'arena, 'src>,
614 pub span: Span,
615}
616
617#[derive(Debug, Serialize)]
618pub struct WhileStmt<'arena, 'src> {
619 pub condition: Expr<'arena, 'src>,
620 pub body: &'arena Stmt<'arena, 'src>,
621}
622
623#[derive(Debug, Serialize)]
624pub struct ForStmt<'arena, 'src> {
625 pub init: ArenaVec<'arena, Expr<'arena, 'src>>,
626 pub condition: ArenaVec<'arena, Expr<'arena, 'src>>,
627 pub update: ArenaVec<'arena, Expr<'arena, 'src>>,
628 pub body: &'arena Stmt<'arena, 'src>,
629}
630
631#[derive(Debug, Serialize)]
632pub struct ForeachStmt<'arena, 'src> {
633 pub expr: Expr<'arena, 'src>,
634 pub key: Option<Expr<'arena, 'src>>,
635 pub value: Expr<'arena, 'src>,
636 pub body: &'arena Stmt<'arena, 'src>,
637}
638
639#[derive(Debug, Serialize)]
640pub struct DoWhileStmt<'arena, 'src> {
641 pub body: &'arena Stmt<'arena, 'src>,
642 pub condition: Expr<'arena, 'src>,
643}
644
645#[derive(Debug, Serialize)]
646pub struct FunctionDecl<'arena, 'src> {
647 pub name: &'src str,
648 pub params: ArenaVec<'arena, Param<'arena, 'src>>,
649 pub body: ArenaVec<'arena, Stmt<'arena, 'src>>,
650 pub return_type: Option<TypeHint<'arena, 'src>>,
651 pub by_ref: bool,
652 pub attributes: ArenaVec<'arena, Attribute<'arena, 'src>>,
653 #[serde(skip_serializing_if = "Option::is_none")]
654 pub doc_comment: Option<Comment<'src>>,
655}
656
657#[derive(Debug, Serialize)]
658pub struct Param<'arena, 'src> {
659 pub name: &'src str,
660 pub type_hint: Option<TypeHint<'arena, 'src>>,
661 pub default: Option<Expr<'arena, 'src>>,
662 pub by_ref: bool,
663 pub variadic: bool,
664 pub is_readonly: bool,
665 pub is_final: bool,
666 pub visibility: Option<Visibility>,
667 pub set_visibility: Option<Visibility>,
668 pub attributes: ArenaVec<'arena, Attribute<'arena, 'src>>,
669 #[serde(skip_serializing_if = "ArenaVec::is_empty")]
670 pub hooks: ArenaVec<'arena, PropertyHook<'arena, 'src>>,
671 pub span: Span,
672}
673
674#[derive(Debug, Serialize)]
675pub struct SwitchStmt<'arena, 'src> {
676 pub expr: Expr<'arena, 'src>,
677 pub cases: ArenaVec<'arena, SwitchCase<'arena, 'src>>,
678}
679
680#[derive(Debug, Serialize)]
681pub struct SwitchCase<'arena, 'src> {
682 pub value: Option<Expr<'arena, 'src>>,
683 pub body: ArenaVec<'arena, Stmt<'arena, 'src>>,
684 pub span: Span,
685}
686
687#[derive(Debug, Serialize)]
688pub struct TryCatchStmt<'arena, 'src> {
689 pub body: ArenaVec<'arena, Stmt<'arena, 'src>>,
690 pub catches: ArenaVec<'arena, CatchClause<'arena, 'src>>,
691 pub finally: Option<ArenaVec<'arena, Stmt<'arena, 'src>>>,
692}
693
694#[derive(Debug, Serialize)]
695pub struct CatchClause<'arena, 'src> {
696 pub types: ArenaVec<'arena, Name<'arena, 'src>>,
697 pub var: Option<&'src str>,
698 pub body: ArenaVec<'arena, Stmt<'arena, 'src>>,
699 pub span: Span,
700}
701
702#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
707pub enum Visibility {
708 Public,
709 Protected,
710 Private,
711}
712
713#[derive(Debug, Serialize)]
714pub struct ClassDecl<'arena, 'src> {
715 pub name: Option<&'src str>,
716 pub modifiers: ClassModifiers,
717 pub extends: Option<Name<'arena, 'src>>,
718 pub implements: ArenaVec<'arena, Name<'arena, 'src>>,
719 pub members: ArenaVec<'arena, ClassMember<'arena, 'src>>,
720 pub attributes: ArenaVec<'arena, Attribute<'arena, 'src>>,
721 #[serde(skip_serializing_if = "Option::is_none")]
722 pub doc_comment: Option<Comment<'src>>,
723}
724
725#[derive(Debug, Clone, Serialize, Default)]
726pub struct ClassModifiers {
727 pub is_abstract: bool,
728 pub is_final: bool,
729 pub is_readonly: bool,
730}
731
732#[derive(Debug, Serialize)]
733pub struct ClassMember<'arena, 'src> {
734 pub kind: ClassMemberKind<'arena, 'src>,
735 pub span: Span,
736}
737
738#[derive(Debug, Serialize)]
739pub enum ClassMemberKind<'arena, 'src> {
740 Property(PropertyDecl<'arena, 'src>),
741 Method(MethodDecl<'arena, 'src>),
742 ClassConst(ClassConstDecl<'arena, 'src>),
743 TraitUse(TraitUseDecl<'arena, 'src>),
744}
745
746#[derive(Debug, Serialize)]
747pub struct PropertyDecl<'arena, 'src> {
748 pub name: &'src str,
749 pub visibility: Option<Visibility>,
750 pub set_visibility: Option<Visibility>,
751 pub is_static: bool,
752 pub is_readonly: bool,
753 pub type_hint: Option<TypeHint<'arena, 'src>>,
754 pub default: Option<Expr<'arena, 'src>>,
755 pub attributes: ArenaVec<'arena, Attribute<'arena, 'src>>,
756 #[serde(skip_serializing_if = "ArenaVec::is_empty")]
757 pub hooks: ArenaVec<'arena, PropertyHook<'arena, 'src>>,
758 #[serde(skip_serializing_if = "Option::is_none")]
759 pub doc_comment: Option<Comment<'src>>,
760}
761
762#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
763pub enum PropertyHookKind {
764 Get,
765 Set,
766}
767
768#[derive(Debug, Serialize)]
769pub enum PropertyHookBody<'arena, 'src> {
770 Block(ArenaVec<'arena, Stmt<'arena, 'src>>),
771 Expression(Expr<'arena, 'src>),
772 Abstract,
773}
774
775#[derive(Debug, Serialize)]
776pub struct PropertyHook<'arena, 'src> {
777 pub kind: PropertyHookKind,
778 pub body: PropertyHookBody<'arena, 'src>,
779 pub is_final: bool,
780 pub by_ref: bool,
781 pub params: ArenaVec<'arena, Param<'arena, 'src>>,
782 pub attributes: ArenaVec<'arena, Attribute<'arena, 'src>>,
783 pub span: Span,
784}
785
786#[derive(Debug, Serialize)]
787pub struct MethodDecl<'arena, 'src> {
788 pub name: &'src str,
789 pub visibility: Option<Visibility>,
790 pub is_static: bool,
791 pub is_abstract: bool,
792 pub is_final: bool,
793 pub by_ref: bool,
794 pub params: ArenaVec<'arena, Param<'arena, 'src>>,
795 pub return_type: Option<TypeHint<'arena, 'src>>,
796 pub body: Option<ArenaVec<'arena, Stmt<'arena, 'src>>>,
797 pub attributes: ArenaVec<'arena, Attribute<'arena, 'src>>,
798 #[serde(skip_serializing_if = "Option::is_none")]
799 pub doc_comment: Option<Comment<'src>>,
800}
801
802#[derive(Debug, Serialize)]
803pub struct ClassConstDecl<'arena, 'src> {
804 pub name: &'src str,
805 pub visibility: Option<Visibility>,
806 #[serde(skip_serializing_if = "Option::is_none")]
807 pub type_hint: Option<&'arena TypeHint<'arena, 'src>>,
808 pub value: Expr<'arena, 'src>,
809 pub attributes: ArenaVec<'arena, Attribute<'arena, 'src>>,
810 #[serde(skip_serializing_if = "Option::is_none")]
811 pub doc_comment: Option<Comment<'src>>,
812}
813
814#[derive(Debug, Serialize)]
815pub struct TraitUseDecl<'arena, 'src> {
816 pub traits: ArenaVec<'arena, Name<'arena, 'src>>,
817 pub adaptations: ArenaVec<'arena, TraitAdaptation<'arena, 'src>>,
818}
819
820#[derive(Debug, Serialize)]
821pub struct TraitAdaptation<'arena, 'src> {
822 pub kind: TraitAdaptationKind<'arena, 'src>,
823 pub span: Span,
824}
825
826#[derive(Debug, Serialize)]
827pub enum TraitAdaptationKind<'arena, 'src> {
828 Precedence {
830 trait_name: Name<'arena, 'src>,
831 method: &'src str,
832 insteadof: ArenaVec<'arena, Name<'arena, 'src>>,
833 },
834 Alias {
836 trait_name: Option<Name<'arena, 'src>>,
837 method: Cow<'src, str>,
838 new_modifier: Option<Visibility>,
839 new_name: Option<&'src str>,
840 },
841}
842
843#[derive(Debug, Serialize)]
844pub struct InterfaceDecl<'arena, 'src> {
845 pub name: &'src str,
846 pub extends: ArenaVec<'arena, Name<'arena, 'src>>,
847 pub members: ArenaVec<'arena, ClassMember<'arena, 'src>>,
848 pub attributes: ArenaVec<'arena, Attribute<'arena, 'src>>,
849 #[serde(skip_serializing_if = "Option::is_none")]
850 pub doc_comment: Option<Comment<'src>>,
851}
852
853#[derive(Debug, Serialize)]
854pub struct TraitDecl<'arena, 'src> {
855 pub name: &'src str,
856 pub members: ArenaVec<'arena, ClassMember<'arena, 'src>>,
857 pub attributes: ArenaVec<'arena, Attribute<'arena, 'src>>,
858 #[serde(skip_serializing_if = "Option::is_none")]
859 pub doc_comment: Option<Comment<'src>>,
860}
861
862#[derive(Debug, Serialize)]
863pub struct EnumDecl<'arena, 'src> {
864 pub name: &'src str,
865 pub scalar_type: Option<Name<'arena, 'src>>,
866 pub implements: ArenaVec<'arena, Name<'arena, 'src>>,
867 pub members: ArenaVec<'arena, EnumMember<'arena, 'src>>,
868 pub attributes: ArenaVec<'arena, Attribute<'arena, 'src>>,
869 #[serde(skip_serializing_if = "Option::is_none")]
870 pub doc_comment: Option<Comment<'src>>,
871}
872
873#[derive(Debug, Serialize)]
874pub struct EnumMember<'arena, 'src> {
875 pub kind: EnumMemberKind<'arena, 'src>,
876 pub span: Span,
877}
878
879#[derive(Debug, Serialize)]
880pub enum EnumMemberKind<'arena, 'src> {
881 Case(EnumCase<'arena, 'src>),
882 Method(MethodDecl<'arena, 'src>),
883 ClassConst(ClassConstDecl<'arena, 'src>),
884 TraitUse(TraitUseDecl<'arena, 'src>),
885}
886
887#[derive(Debug, Serialize)]
888pub struct EnumCase<'arena, 'src> {
889 pub name: &'src str,
890 pub value: Option<Expr<'arena, 'src>>,
891 pub attributes: ArenaVec<'arena, Attribute<'arena, 'src>>,
892 #[serde(skip_serializing_if = "Option::is_none")]
893 pub doc_comment: Option<Comment<'src>>,
894}
895
896#[derive(Debug, Serialize)]
901pub struct NamespaceDecl<'arena, 'src> {
902 pub name: Option<Name<'arena, 'src>>,
903 pub body: NamespaceBody<'arena, 'src>,
904}
905
906#[derive(Debug, Serialize)]
907pub enum NamespaceBody<'arena, 'src> {
908 Braced(ArenaVec<'arena, Stmt<'arena, 'src>>),
909 Simple,
910}
911
912#[derive(Debug, Serialize)]
913pub struct DeclareStmt<'arena, 'src> {
914 pub directives: ArenaVec<'arena, (&'src str, Expr<'arena, 'src>)>,
915 pub body: Option<&'arena Stmt<'arena, 'src>>,
916}
917
918#[derive(Debug, Serialize)]
919pub struct UseDecl<'arena, 'src> {
920 pub kind: UseKind,
921 pub uses: ArenaVec<'arena, UseItem<'arena, 'src>>,
922}
923
924#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
925pub enum UseKind {
926 Normal,
927 Function,
928 Const,
929}
930
931#[derive(Debug, Serialize)]
932pub struct UseItem<'arena, 'src> {
933 pub name: Name<'arena, 'src>,
934 pub alias: Option<&'src str>,
935 #[serde(skip_serializing_if = "Option::is_none")]
936 pub kind: Option<UseKind>,
937 pub span: Span,
938}
939
940#[derive(Debug, Serialize)]
941pub struct ConstItem<'arena, 'src> {
942 pub name: &'src str,
943 pub value: Expr<'arena, 'src>,
944 pub attributes: ArenaVec<'arena, Attribute<'arena, 'src>>,
945 pub span: Span,
946}
947
948#[derive(Debug, Serialize)]
949pub struct StaticVar<'arena, 'src> {
950 pub name: &'src str,
951 pub default: Option<Expr<'arena, 'src>>,
952 pub span: Span,
953}
954
955#[derive(Debug, Serialize)]
960pub struct Expr<'arena, 'src> {
961 pub kind: ExprKind<'arena, 'src>,
962 pub span: Span,
963}
964
965#[derive(Debug, Serialize)]
966pub enum ExprKind<'arena, 'src> {
967 Int(i64),
969
970 Float(f64),
972
973 String(&'arena str),
975
976 InterpolatedString(ArenaVec<'arena, StringPart<'arena, 'src>>),
978
979 Heredoc {
981 label: &'src str,
982 parts: ArenaVec<'arena, StringPart<'arena, 'src>>,
983 },
984
985 Nowdoc {
987 label: &'src str,
988 value: &'arena str,
989 },
990
991 ShellExec(ArenaVec<'arena, StringPart<'arena, 'src>>),
993
994 Bool(bool),
996
997 Null,
999
1000 Variable(Cow<'src, str>),
1002
1003 VariableVariable(&'arena Expr<'arena, 'src>),
1005
1006 Identifier(&'arena str),
1008
1009 Assign(AssignExpr<'arena, 'src>),
1011
1012 Binary(BinaryExpr<'arena, 'src>),
1014
1015 UnaryPrefix(UnaryPrefixExpr<'arena, 'src>),
1017
1018 UnaryPostfix(UnaryPostfixExpr<'arena, 'src>),
1020
1021 Ternary(TernaryExpr<'arena, 'src>),
1023
1024 NullCoalesce(NullCoalesceExpr<'arena, 'src>),
1026
1027 FunctionCall(FunctionCallExpr<'arena, 'src>),
1029
1030 Array(ArenaVec<'arena, ArrayElement<'arena, 'src>>),
1032
1033 ArrayAccess(ArrayAccessExpr<'arena, 'src>),
1035
1036 Print(&'arena Expr<'arena, 'src>),
1038
1039 Parenthesized(&'arena Expr<'arena, 'src>),
1041
1042 Cast(CastKind, &'arena Expr<'arena, 'src>),
1044
1045 ErrorSuppress(&'arena Expr<'arena, 'src>),
1047
1048 Isset(ArenaVec<'arena, Expr<'arena, 'src>>),
1050
1051 Empty(&'arena Expr<'arena, 'src>),
1053
1054 Include(IncludeKind, &'arena Expr<'arena, 'src>),
1056
1057 Eval(&'arena Expr<'arena, 'src>),
1059
1060 Exit(Option<&'arena Expr<'arena, 'src>>),
1062
1063 MagicConst(MagicConstKind),
1065
1066 Clone(&'arena Expr<'arena, 'src>),
1068
1069 CloneWith(&'arena Expr<'arena, 'src>, &'arena Expr<'arena, 'src>),
1071
1072 New(NewExpr<'arena, 'src>),
1074
1075 PropertyAccess(PropertyAccessExpr<'arena, 'src>),
1077
1078 NullsafePropertyAccess(PropertyAccessExpr<'arena, 'src>),
1080
1081 MethodCall(&'arena MethodCallExpr<'arena, 'src>),
1083
1084 NullsafeMethodCall(&'arena MethodCallExpr<'arena, 'src>),
1086
1087 StaticPropertyAccess(StaticAccessExpr<'arena, 'src>),
1089
1090 StaticMethodCall(&'arena StaticMethodCallExpr<'arena, 'src>),
1092
1093 ClassConstAccess(StaticAccessExpr<'arena, 'src>),
1095
1096 ClassConstAccessDynamic {
1098 class: &'arena Expr<'arena, 'src>,
1099 member: &'arena Expr<'arena, 'src>,
1100 },
1101
1102 StaticPropertyAccessDynamic {
1104 class: &'arena Expr<'arena, 'src>,
1105 member: &'arena Expr<'arena, 'src>,
1106 },
1107
1108 Closure(&'arena ClosureExpr<'arena, 'src>),
1110
1111 ArrowFunction(&'arena ArrowFunctionExpr<'arena, 'src>),
1113
1114 Match(MatchExpr<'arena, 'src>),
1116
1117 ThrowExpr(&'arena Expr<'arena, 'src>),
1119
1120 Yield(YieldExpr<'arena, 'src>),
1122
1123 AnonymousClass(&'arena ClassDecl<'arena, 'src>),
1125
1126 CallableCreate(CallableCreateExpr<'arena, 'src>),
1128
1129 Omit,
1131
1132 Error,
1134}
1135
1136#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
1137pub enum CastKind {
1138 Int,
1139 Float,
1140 String,
1141 Bool,
1142 Array,
1143 Object,
1144 Unset,
1145 Void,
1146}
1147
1148#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
1149pub enum IncludeKind {
1150 Include,
1151 IncludeOnce,
1152 Require,
1153 RequireOnce,
1154}
1155
1156#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
1157pub enum MagicConstKind {
1158 Class,
1159 Dir,
1160 File,
1161 Function,
1162 Line,
1163 Method,
1164 Namespace,
1165 Trait,
1166 Property,
1167}
1168
1169#[derive(Debug, Serialize)]
1172pub struct AssignExpr<'arena, 'src> {
1173 pub target: &'arena Expr<'arena, 'src>,
1174 pub op: AssignOp,
1175 pub value: &'arena Expr<'arena, 'src>,
1176 #[serde(skip_serializing_if = "is_false")]
1177 pub by_ref: bool,
1178}
1179
1180#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
1181pub enum AssignOp {
1182 Assign,
1183 Plus,
1184 Minus,
1185 Mul,
1186 Div,
1187 Mod,
1188 Pow,
1189 Concat,
1190 BitwiseAnd,
1191 BitwiseOr,
1192 BitwiseXor,
1193 ShiftLeft,
1194 ShiftRight,
1195 Coalesce,
1196}
1197
1198#[derive(Debug, Serialize)]
1199pub struct BinaryExpr<'arena, 'src> {
1200 pub left: &'arena Expr<'arena, 'src>,
1201 pub op: BinaryOp,
1202 pub right: &'arena Expr<'arena, 'src>,
1203}
1204
1205#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
1206pub enum BinaryOp {
1207 Add,
1208 Sub,
1209 Mul,
1210 Div,
1211 Mod,
1212 Pow,
1213 Concat,
1214 Equal,
1215 NotEqual,
1216 Identical,
1217 NotIdentical,
1218 Less,
1219 Greater,
1220 LessOrEqual,
1221 GreaterOrEqual,
1222 Spaceship,
1223 BooleanAnd,
1224 BooleanOr,
1225 BitwiseAnd,
1226 BitwiseOr,
1227 BitwiseXor,
1228 ShiftLeft,
1229 ShiftRight,
1230 LogicalAnd,
1231 LogicalOr,
1232 LogicalXor,
1233 Instanceof,
1234 Pipe,
1235}
1236
1237#[derive(Debug, Serialize)]
1238pub struct UnaryPrefixExpr<'arena, 'src> {
1239 pub op: UnaryPrefixOp,
1240 pub operand: &'arena Expr<'arena, 'src>,
1241}
1242
1243#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
1244pub enum UnaryPrefixOp {
1245 Negate,
1246 Plus,
1247 BooleanNot,
1248 BitwiseNot,
1249 PreIncrement,
1250 PreDecrement,
1251}
1252
1253#[derive(Debug, Serialize)]
1254pub struct UnaryPostfixExpr<'arena, 'src> {
1255 pub operand: &'arena Expr<'arena, 'src>,
1256 pub op: UnaryPostfixOp,
1257}
1258
1259#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
1260pub enum UnaryPostfixOp {
1261 PostIncrement,
1262 PostDecrement,
1263}
1264
1265#[derive(Debug, Serialize)]
1266pub struct TernaryExpr<'arena, 'src> {
1267 pub condition: &'arena Expr<'arena, 'src>,
1268 pub then_expr: Option<&'arena Expr<'arena, 'src>>,
1270 pub else_expr: &'arena Expr<'arena, 'src>,
1271}
1272
1273#[derive(Debug, Serialize)]
1274pub struct NullCoalesceExpr<'arena, 'src> {
1275 pub left: &'arena Expr<'arena, 'src>,
1276 pub right: &'arena Expr<'arena, 'src>,
1277}
1278
1279#[derive(Debug, Serialize)]
1280pub struct FunctionCallExpr<'arena, 'src> {
1281 pub name: &'arena Expr<'arena, 'src>,
1282 pub args: ArenaVec<'arena, Arg<'arena, 'src>>,
1283}
1284
1285#[derive(Debug, Serialize)]
1286pub struct ArrayElement<'arena, 'src> {
1287 pub key: Option<Expr<'arena, 'src>>,
1288 pub value: Expr<'arena, 'src>,
1289 pub unpack: bool,
1290 #[serde(skip_serializing_if = "is_false")]
1291 pub by_ref: bool,
1292 pub span: Span,
1293}
1294
1295#[derive(Debug, Serialize)]
1296pub struct ArrayAccessExpr<'arena, 'src> {
1297 pub array: &'arena Expr<'arena, 'src>,
1298 pub index: Option<&'arena Expr<'arena, 'src>>,
1299}
1300
1301#[derive(Debug, Serialize)]
1304pub struct NewExpr<'arena, 'src> {
1305 pub class: &'arena Expr<'arena, 'src>,
1306 pub args: ArenaVec<'arena, Arg<'arena, 'src>>,
1307}
1308
1309#[derive(Debug, Serialize)]
1310pub struct PropertyAccessExpr<'arena, 'src> {
1311 pub object: &'arena Expr<'arena, 'src>,
1312 pub property: &'arena Expr<'arena, 'src>,
1313}
1314
1315#[derive(Debug, Serialize)]
1316pub struct MethodCallExpr<'arena, 'src> {
1317 pub object: &'arena Expr<'arena, 'src>,
1318 pub method: &'arena Expr<'arena, 'src>,
1319 pub args: ArenaVec<'arena, Arg<'arena, 'src>>,
1320}
1321
1322#[derive(Debug, Serialize)]
1323pub struct StaticAccessExpr<'arena, 'src> {
1324 pub class: &'arena Expr<'arena, 'src>,
1325 pub member: Cow<'src, str>,
1326}
1327
1328#[derive(Debug, Serialize)]
1329pub struct StaticMethodCallExpr<'arena, 'src> {
1330 pub class: &'arena Expr<'arena, 'src>,
1331 pub method: Cow<'src, str>,
1332 pub args: ArenaVec<'arena, Arg<'arena, 'src>>,
1333}
1334
1335#[derive(Debug, Serialize)]
1336pub struct ClosureExpr<'arena, 'src> {
1337 pub is_static: bool,
1338 pub by_ref: bool,
1339 pub params: ArenaVec<'arena, Param<'arena, 'src>>,
1340 pub use_vars: ArenaVec<'arena, ClosureUseVar<'src>>,
1341 pub return_type: Option<TypeHint<'arena, 'src>>,
1342 pub body: ArenaVec<'arena, Stmt<'arena, 'src>>,
1343 pub attributes: ArenaVec<'arena, Attribute<'arena, 'src>>,
1344}
1345
1346#[derive(Debug, Clone, Serialize)]
1347pub struct ClosureUseVar<'src> {
1348 pub name: &'src str,
1349 pub by_ref: bool,
1350 pub span: Span,
1351}
1352
1353#[derive(Debug, Serialize)]
1354pub struct ArrowFunctionExpr<'arena, 'src> {
1355 pub is_static: bool,
1356 pub by_ref: bool,
1357 pub params: ArenaVec<'arena, Param<'arena, 'src>>,
1358 pub return_type: Option<TypeHint<'arena, 'src>>,
1359 pub body: &'arena Expr<'arena, 'src>,
1360 pub attributes: ArenaVec<'arena, Attribute<'arena, 'src>>,
1361}
1362
1363#[derive(Debug, Serialize)]
1364pub struct MatchExpr<'arena, 'src> {
1365 pub subject: &'arena Expr<'arena, 'src>,
1366 pub arms: ArenaVec<'arena, MatchArm<'arena, 'src>>,
1367}
1368
1369#[derive(Debug, Serialize)]
1370pub struct MatchArm<'arena, 'src> {
1371 pub conditions: Option<ArenaVec<'arena, Expr<'arena, 'src>>>,
1373 pub body: Expr<'arena, 'src>,
1374 pub span: Span,
1375}
1376
1377#[derive(Debug, Serialize)]
1378pub struct YieldExpr<'arena, 'src> {
1379 pub key: Option<&'arena Expr<'arena, 'src>>,
1380 pub value: Option<&'arena Expr<'arena, 'src>>,
1381 pub is_from: bool,
1383}
1384
1385#[derive(Debug, Serialize)]
1388pub struct CallableCreateExpr<'arena, 'src> {
1389 pub kind: CallableCreateKind<'arena, 'src>,
1390}
1391
1392#[derive(Debug, Serialize)]
1393pub enum CallableCreateKind<'arena, 'src> {
1394 Function(&'arena Expr<'arena, 'src>),
1396 Method {
1398 object: &'arena Expr<'arena, 'src>,
1399 method: &'arena Expr<'arena, 'src>,
1400 },
1401 NullsafeMethod {
1403 object: &'arena Expr<'arena, 'src>,
1404 method: &'arena Expr<'arena, 'src>,
1405 },
1406 StaticMethod {
1408 class: &'arena Expr<'arena, 'src>,
1409 method: Cow<'src, str>,
1410 },
1411}
1412
1413#[derive(Debug, Serialize)]
1416pub enum StringPart<'arena, 'src> {
1417 Literal(&'arena str),
1418 Expr(Expr<'arena, 'src>),
1419}