Skip to main content

php_ast/ast/
decls.rs

1use serde::Serialize;
2
3use crate::Span;
4
5use super::{ArenaVec, Attribute, Comment, Expr, Ident, Name, Stmt, TypeHint};
6
7#[derive(Debug, Serialize)]
8pub struct FunctionDecl<'arena, 'src> {
9    pub name: Ident<'src>,
10    pub params: ArenaVec<'arena, Param<'arena, 'src>>,
11    pub body: ArenaVec<'arena, Stmt<'arena, 'src>>,
12    pub return_type: Option<TypeHint<'arena, 'src>>,
13    pub by_ref: bool,
14    pub attributes: ArenaVec<'arena, Attribute<'arena, 'src>>,
15    #[serde(skip_serializing_if = "Option::is_none")]
16    pub doc_comment: Option<Comment<'src>>,
17}
18
19#[derive(Debug, Serialize)]
20pub struct Param<'arena, 'src> {
21    pub name: Ident<'src>,
22    pub type_hint: Option<TypeHint<'arena, 'src>>,
23    pub default: Option<Expr<'arena, 'src>>,
24    pub by_ref: bool,
25    pub variadic: bool,
26    pub is_readonly: bool,
27    pub is_final: bool,
28    pub visibility: Option<Visibility>,
29    pub set_visibility: Option<Visibility>,
30    pub attributes: ArenaVec<'arena, Attribute<'arena, 'src>>,
31    #[serde(skip_serializing_if = "ArenaVec::is_empty")]
32    pub hooks: ArenaVec<'arena, PropertyHook<'arena, 'src>>,
33    pub span: Span,
34}
35
36#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
37pub enum Visibility {
38    /// `public` — accessible from anywhere.
39    Public,
40    /// `protected` — accessible within the class and its subclasses.
41    Protected,
42    /// `private` — accessible only within the declaring class.
43    Private,
44}
45
46#[derive(Debug, Serialize)]
47pub struct ClassDecl<'arena, 'src> {
48    pub name: Option<Ident<'src>>,
49    pub modifiers: ClassModifiers,
50    pub extends: Option<Name<'arena, 'src>>,
51    pub implements: ArenaVec<'arena, Name<'arena, 'src>>,
52    pub members: ArenaVec<'arena, ClassMember<'arena, 'src>>,
53    pub attributes: ArenaVec<'arena, Attribute<'arena, 'src>>,
54    #[serde(skip_serializing_if = "Option::is_none")]
55    pub doc_comment: Option<Comment<'src>>,
56}
57
58#[derive(Debug, Clone, Serialize, Default)]
59pub struct ClassModifiers {
60    pub is_abstract: bool,
61    pub is_final: bool,
62    pub is_readonly: bool,
63}
64
65#[derive(Debug, Serialize)]
66pub struct ClassMember<'arena, 'src> {
67    pub kind: ClassMemberKind<'arena, 'src>,
68    pub span: Span,
69}
70
71#[derive(Debug, Serialize)]
72pub enum ClassMemberKind<'arena, 'src> {
73    Property(PropertyDecl<'arena, 'src>),
74    Method(MethodDecl<'arena, 'src>),
75    ClassConst(ClassConstDecl<'arena, 'src>),
76    TraitUse(TraitUseDecl<'arena, 'src>),
77}
78
79#[derive(Debug, Serialize)]
80pub struct PropertyDecl<'arena, 'src> {
81    pub name: Ident<'src>,
82    pub visibility: Option<Visibility>,
83    pub set_visibility: Option<Visibility>,
84    pub is_static: bool,
85    pub is_readonly: bool,
86    pub type_hint: Option<TypeHint<'arena, 'src>>,
87    pub default: Option<Expr<'arena, 'src>>,
88    pub attributes: ArenaVec<'arena, Attribute<'arena, 'src>>,
89    #[serde(skip_serializing_if = "ArenaVec::is_empty")]
90    pub hooks: ArenaVec<'arena, PropertyHook<'arena, 'src>>,
91    #[serde(skip_serializing_if = "Option::is_none")]
92    pub doc_comment: Option<Comment<'src>>,
93}
94
95#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
96pub enum PropertyHookKind {
97    /// `get` hook — called when the property is read.
98    Get,
99    /// `set` hook — called when the property is written; receives the incoming value as `$value`.
100    Set,
101}
102
103#[derive(Debug, Serialize)]
104pub enum PropertyHookBody<'arena, 'src> {
105    /// `{ stmts }` — a full statement block.
106    Block(ArenaVec<'arena, Stmt<'arena, 'src>>),
107    /// `=> expr` — short-form expression body.
108    Expression(Expr<'arena, 'src>),
109    /// No body — the hook is declared abstract (on an abstract class or interface).
110    Abstract,
111}
112
113#[derive(Debug, Serialize)]
114pub struct PropertyHook<'arena, 'src> {
115    pub kind: PropertyHookKind,
116    pub body: PropertyHookBody<'arena, 'src>,
117    pub is_final: bool,
118    pub by_ref: bool,
119    pub params: ArenaVec<'arena, Param<'arena, 'src>>,
120    pub attributes: ArenaVec<'arena, Attribute<'arena, 'src>>,
121    pub span: Span,
122}
123
124#[derive(Debug, Serialize)]
125pub struct MethodDecl<'arena, 'src> {
126    pub name: Ident<'src>,
127    pub visibility: Option<Visibility>,
128    pub is_static: bool,
129    pub is_abstract: bool,
130    pub is_final: bool,
131    pub by_ref: bool,
132    pub params: ArenaVec<'arena, Param<'arena, 'src>>,
133    pub return_type: Option<TypeHint<'arena, 'src>>,
134    pub body: Option<ArenaVec<'arena, Stmt<'arena, 'src>>>,
135    pub attributes: ArenaVec<'arena, Attribute<'arena, 'src>>,
136    #[serde(skip_serializing_if = "Option::is_none")]
137    pub doc_comment: Option<Comment<'src>>,
138}
139
140#[derive(Debug, Serialize)]
141pub struct ClassConstDecl<'arena, 'src> {
142    pub name: Ident<'src>,
143    pub visibility: Option<Visibility>,
144    pub is_final: bool,
145    #[serde(skip_serializing_if = "Option::is_none")]
146    pub type_hint: Option<&'arena TypeHint<'arena, 'src>>,
147    pub value: Expr<'arena, 'src>,
148    pub attributes: ArenaVec<'arena, Attribute<'arena, 'src>>,
149    #[serde(skip_serializing_if = "Option::is_none")]
150    pub doc_comment: Option<Comment<'src>>,
151}
152
153#[derive(Debug, Serialize)]
154pub struct TraitUseDecl<'arena, 'src> {
155    pub traits: ArenaVec<'arena, Name<'arena, 'src>>,
156    pub adaptations: ArenaVec<'arena, TraitAdaptation<'arena, 'src>>,
157}
158
159#[derive(Debug, Serialize)]
160pub struct TraitAdaptation<'arena, 'src> {
161    pub kind: TraitAdaptationKind<'arena, 'src>,
162    pub span: Span,
163}
164
165#[derive(Debug, Serialize)]
166pub enum TraitAdaptationKind<'arena, 'src> {
167    /// `A::foo insteadof B, C;`
168    Precedence {
169        trait_name: Name<'arena, 'src>,
170        method: Name<'arena, 'src>,
171        insteadof: ArenaVec<'arena, Name<'arena, 'src>>,
172    },
173    /// `foo as bar;` or `A::foo as protected bar;` or `foo as protected;`
174    Alias {
175        trait_name: Option<Name<'arena, 'src>>,
176        method: Name<'arena, 'src>,
177        new_modifier: Option<Visibility>,
178        new_name: Option<Name<'arena, 'src>>,
179    },
180}
181
182#[derive(Debug, Serialize)]
183pub struct InterfaceDecl<'arena, 'src> {
184    pub name: Ident<'src>,
185    pub extends: ArenaVec<'arena, Name<'arena, 'src>>,
186    pub members: ArenaVec<'arena, ClassMember<'arena, 'src>>,
187    pub attributes: ArenaVec<'arena, Attribute<'arena, 'src>>,
188    #[serde(skip_serializing_if = "Option::is_none")]
189    pub doc_comment: Option<Comment<'src>>,
190}
191
192#[derive(Debug, Serialize)]
193pub struct TraitDecl<'arena, 'src> {
194    pub name: Ident<'src>,
195    pub members: ArenaVec<'arena, ClassMember<'arena, 'src>>,
196    pub attributes: ArenaVec<'arena, Attribute<'arena, 'src>>,
197    #[serde(skip_serializing_if = "Option::is_none")]
198    pub doc_comment: Option<Comment<'src>>,
199}
200
201#[derive(Debug, Serialize)]
202pub struct EnumDecl<'arena, 'src> {
203    pub name: Ident<'src>,
204    pub scalar_type: Option<Name<'arena, 'src>>,
205    pub implements: ArenaVec<'arena, Name<'arena, 'src>>,
206    pub members: ArenaVec<'arena, EnumMember<'arena, 'src>>,
207    pub attributes: ArenaVec<'arena, Attribute<'arena, 'src>>,
208    #[serde(skip_serializing_if = "Option::is_none")]
209    pub doc_comment: Option<Comment<'src>>,
210}
211
212#[derive(Debug, Serialize)]
213pub struct EnumMember<'arena, 'src> {
214    pub kind: EnumMemberKind<'arena, 'src>,
215    pub span: Span,
216}
217
218#[derive(Debug, Serialize)]
219pub enum EnumMemberKind<'arena, 'src> {
220    /// An enum case: `case Foo;` or `case Foo = 'foo';` (backed enum).
221    Case(EnumCase<'arena, 'src>),
222    /// A method defined inside the enum body.
223    Method(MethodDecl<'arena, 'src>),
224    /// A constant defined inside the enum body: `const X = 1;`.
225    ClassConst(ClassConstDecl<'arena, 'src>),
226    /// A trait use inside the enum body: `use SomeTrait;`.
227    TraitUse(TraitUseDecl<'arena, 'src>),
228}
229
230#[derive(Debug, Serialize)]
231pub struct EnumCase<'arena, 'src> {
232    pub name: Ident<'src>,
233    pub value: Option<Expr<'arena, 'src>>,
234    pub attributes: ArenaVec<'arena, Attribute<'arena, 'src>>,
235    #[serde(skip_serializing_if = "Option::is_none")]
236    pub doc_comment: Option<Comment<'src>>,
237}