Skip to main content

mago_syntax/ast/ast/
modifier.rs

1use serde::Serialize;
2use strum::Display;
3
4use mago_span::HasSpan;
5use mago_span::Span;
6
7use crate::ast::ast::keyword::Keyword;
8use crate::ast::sequence::Sequence;
9
10/// Represents a modifier statement.
11///
12/// # Examples
13///
14/// ```php
15/// final class Foo {}
16/// ```
17#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, PartialOrd, Ord, Display)]
18#[serde(tag = "type", content = "value")]
19pub enum Modifier<'arena> {
20    Static(Keyword<'arena>),
21    Final(Keyword<'arena>),
22    Abstract(Keyword<'arena>),
23    Readonly(Keyword<'arena>),
24    Public(Keyword<'arena>),
25    PublicSet(Keyword<'arena>),
26    Protected(Keyword<'arena>),
27    ProtectedSet(Keyword<'arena>),
28    Private(Keyword<'arena>),
29    PrivateSet(Keyword<'arena>),
30}
31
32impl<'arena> Modifier<'arena> {
33    #[must_use]
34    pub fn get_keyword(&self) -> &Keyword<'arena> {
35        match self {
36            Modifier::Static(k) => k,
37            Modifier::Final(k) => k,
38            Modifier::Abstract(k) => k,
39            Modifier::Readonly(k) => k,
40            Modifier::Public(k) => k,
41            Modifier::PublicSet(k) => k,
42            Modifier::Protected(k) => k,
43            Modifier::ProtectedSet(k) => k,
44            Modifier::Private(k) => k,
45            Modifier::PrivateSet(k) => k,
46        }
47    }
48
49    /// Returns `true` if the modifier is a visibility modifier.
50    #[must_use]
51    pub fn is_visibility(&self) -> bool {
52        matches!(
53            self,
54            Modifier::Public(..)
55                | Modifier::Protected(..)
56                | Modifier::Private(..)
57                | Modifier::PrivateSet(..)
58                | Modifier::ProtectedSet(..)
59                | Modifier::PublicSet(..)
60        )
61    }
62
63    /// Returns `true` if the modifier is a read visibility modifier.
64    #[must_use]
65    pub fn is_read_visibility(&self) -> bool {
66        matches!(self, Modifier::Public(..) | Modifier::Protected(..) | Modifier::Private(..))
67    }
68
69    /// Returns `true` if the modifier is a write visibility modifier.
70    #[must_use]
71    pub fn is_write_visibility(&self) -> bool {
72        matches!(self, Modifier::PrivateSet(..) | Modifier::ProtectedSet(..) | Modifier::PublicSet(..))
73    }
74
75    #[inline]
76    #[must_use]
77    pub const fn is_static(&self) -> bool {
78        matches!(self, Modifier::Static(..))
79    }
80
81    #[inline]
82    #[must_use]
83    pub const fn is_final(&self) -> bool {
84        matches!(self, Modifier::Final(..))
85    }
86
87    #[inline]
88    #[must_use]
89    pub const fn is_abstract(&self) -> bool {
90        matches!(self, Modifier::Abstract(..))
91    }
92
93    #[inline]
94    #[must_use]
95    pub const fn is_readonly(&self) -> bool {
96        matches!(self, Modifier::Readonly(..))
97    }
98
99    #[inline]
100    #[must_use]
101    pub const fn is_public(&self) -> bool {
102        matches!(self, Modifier::Public(..))
103    }
104
105    #[inline]
106    #[must_use]
107    pub const fn is_protected(&self) -> bool {
108        matches!(self, Modifier::Protected(..))
109    }
110
111    #[inline]
112    #[must_use]
113    pub const fn is_private(&self) -> bool {
114        matches!(self, Modifier::Private(..))
115    }
116
117    #[inline]
118    #[must_use]
119    pub const fn is_public_set(&self) -> bool {
120        matches!(self, Modifier::PublicSet(..))
121    }
122
123    #[inline]
124    #[must_use]
125    pub const fn is_protected_set(&self) -> bool {
126        matches!(self, Modifier::ProtectedSet(..))
127    }
128
129    #[inline]
130    #[must_use]
131    pub const fn is_private_set(&self) -> bool {
132        matches!(self, Modifier::PrivateSet(..))
133    }
134}
135
136impl HasSpan for Modifier<'_> {
137    fn span(&self) -> Span {
138        match self {
139            Modifier::Static(value)
140            | Modifier::Final(value)
141            | Modifier::Abstract(value)
142            | Modifier::Readonly(value)
143            | Modifier::Public(value)
144            | Modifier::Protected(value)
145            | Modifier::Private(value)
146            | Modifier::PrivateSet(value)
147            | Modifier::ProtectedSet(value)
148            | Modifier::PublicSet(value) => value.span(),
149        }
150    }
151}
152
153impl<'arena> Sequence<'arena, Modifier<'arena>> {
154    /// Returns the first abstract modifier in the sequence, if any.
155    #[must_use]
156    pub fn get_static(&self) -> Option<&Modifier<'arena>> {
157        self.iter().find(|modifier| matches!(modifier, Modifier::Static(..)))
158    }
159
160    /// Returns `true` if the sequence contains a static modifier.
161    #[must_use]
162    pub fn contains_static(&self) -> bool {
163        self.iter().any(|modifier| matches!(modifier, Modifier::Static(..)))
164    }
165
166    /// Return the first final modifier in the sequence, if any.
167    #[must_use]
168    pub fn get_final(&self) -> Option<&Modifier<'arena>> {
169        self.iter().find(|modifier| matches!(modifier, Modifier::Final(_)))
170    }
171
172    /// Returns `true` if the sequence contains a final modifier.
173    #[must_use]
174    pub fn contains_final(&self) -> bool {
175        self.iter().any(|modifier| matches!(modifier, Modifier::Final(..)))
176    }
177
178    /// Returns the first abstract modifier in the sequence, if any.
179    #[must_use]
180    pub fn get_abstract(&self) -> Option<&Modifier<'arena>> {
181        self.iter().find(|modifier| matches!(modifier, Modifier::Abstract(..)))
182    }
183
184    /// Returns `true` if the sequence contains an abstract modifier.
185    #[must_use]
186    pub fn contains_abstract(&self) -> bool {
187        self.iter().any(|modifier| matches!(modifier, Modifier::Abstract(..)))
188    }
189
190    /// Returns the first abstract modifier in the sequence, if any.
191    #[must_use]
192    pub fn get_readonly(&self) -> Option<&Modifier<'arena>> {
193        self.iter().find(|modifier| matches!(modifier, Modifier::Readonly(..)))
194    }
195
196    /// Returns `true` if the sequence contains a readonly modifier.
197    #[must_use]
198    pub fn contains_readonly(&self) -> bool {
199        self.iter().any(|modifier| matches!(modifier, Modifier::Readonly(..)))
200    }
201
202    #[must_use]
203    pub fn get_first_visibility(&self) -> Option<&Modifier<'arena>> {
204        self.iter().find(|modifier| {
205            matches!(
206                modifier,
207                Modifier::Public(..)
208                    | Modifier::Protected(..)
209                    | Modifier::Private(..)
210                    | Modifier::PrivateSet(..)
211                    | Modifier::ProtectedSet(..)
212                    | Modifier::PublicSet(..)
213            )
214        })
215    }
216
217    #[must_use]
218    pub fn get_first_read_visibility(&self) -> Option<&Modifier<'arena>> {
219        self.iter()
220            .find(|modifier| matches!(modifier, Modifier::Public(..) | Modifier::Protected(..) | Modifier::Private(..)))
221    }
222
223    #[must_use]
224    pub fn get_first_write_visibility(&self) -> Option<&Modifier<'arena>> {
225        self.iter().find(|modifier| {
226            matches!(modifier, Modifier::PrivateSet(..) | Modifier::ProtectedSet(..) | Modifier::PublicSet(..))
227        })
228    }
229
230    /// Returns `true` if the sequence contains a visibility modifier for reading or writing.
231    pub fn contains_visibility(&self) -> bool {
232        self.iter().any(Modifier::is_visibility)
233    }
234
235    #[must_use]
236    pub fn get_public(&self) -> Option<&Modifier<'arena>> {
237        self.iter().find(|modifier| matches!(modifier, Modifier::Public(..)))
238    }
239
240    /// Returns `true` if the sequence contains a public visibility modifier.
241    #[must_use]
242    pub fn contains_public(&self) -> bool {
243        self.iter().any(|modifier| matches!(modifier, Modifier::Public(..)))
244    }
245
246    #[must_use]
247    pub fn get_protected(&self) -> Option<&Modifier<'arena>> {
248        self.iter().find(|modifier| matches!(modifier, Modifier::Protected(..)))
249    }
250
251    /// Returns `true` if the sequence contains a protected visibility modifier.
252    #[must_use]
253    pub fn contains_protected(&self) -> bool {
254        self.iter().any(|modifier| matches!(modifier, Modifier::Protected(..)))
255    }
256
257    #[must_use]
258    pub fn get_private(&self) -> Option<&Modifier<'arena>> {
259        self.iter().find(|modifier| matches!(modifier, Modifier::Private(..)))
260    }
261
262    /// Returns `true` if the sequence contains a private visibility modifier.
263    #[must_use]
264    pub fn contains_private(&self) -> bool {
265        self.iter().any(|modifier| matches!(modifier, Modifier::Private(..)))
266    }
267
268    #[must_use]
269    pub fn get_private_set(&self) -> Option<&Modifier<'arena>> {
270        self.iter().find(|modifier| matches!(modifier, Modifier::PrivateSet(..)))
271    }
272
273    #[must_use]
274    pub fn contains_private_set(&self) -> bool {
275        self.iter().any(|modifier| matches!(modifier, Modifier::PrivateSet(..)))
276    }
277
278    #[must_use]
279    pub fn get_protected_set(&self) -> Option<&Modifier<'arena>> {
280        self.iter().find(|modifier| matches!(modifier, Modifier::ProtectedSet(..)))
281    }
282
283    #[must_use]
284    pub fn contains_protected_set(&self) -> bool {
285        self.iter().any(|modifier| matches!(modifier, Modifier::ProtectedSet(..)))
286    }
287
288    #[must_use]
289    pub fn get_public_set(&self) -> Option<&Modifier<'arena>> {
290        self.iter().find(|modifier| matches!(modifier, Modifier::PublicSet(..)))
291    }
292
293    #[must_use]
294    pub fn contains_public_set(&self) -> bool {
295        self.iter().any(|modifier| matches!(modifier, Modifier::PublicSet(..)))
296    }
297}