Skip to main content

mago_syntax/cst/cst/
array.rs

1use mago_span::HasSpan;
2use mago_span::Span;
3
4use crate::cst::cst::expression::Expression;
5use crate::cst::cst::keyword::Keyword;
6use crate::cst::sequence::TokenSeparatedSequence;
7
8#[derive(Debug, Clone, Eq, PartialEq, Hash, PartialOrd, Ord)]
9#[cfg_attr(feature = "serde", derive(serde::Serialize))]
10pub struct ArrayAccess<'arena> {
11    pub array: &'arena Expression<'arena>,
12    pub left_bracket: Span,
13    pub index: &'arena Expression<'arena>,
14    pub right_bracket: Span,
15}
16
17#[derive(Debug, Clone, Eq, PartialEq, Hash, PartialOrd, Ord)]
18#[cfg_attr(feature = "serde", derive(serde::Serialize))]
19pub struct ArrayAppend<'arena> {
20    pub array: &'arena Expression<'arena>,
21    pub left_bracket: Span,
22    pub right_bracket: Span,
23}
24
25/// Represents a PHP list, defined using `list` keyword and parentheses `()`.
26///
27/// # Example:
28///
29/// ```php
30/// <?php
31///
32/// list($a, 'b' => $c, /* missing */, ...$rest) = $arr;
33/// ```
34#[derive(Debug, Clone, Eq, PartialEq, Hash, PartialOrd, Ord)]
35#[cfg_attr(feature = "serde", derive(serde::Serialize))]
36pub struct List<'arena> {
37    pub list: Keyword<'arena>,
38    pub left_parenthesis: Span,
39    pub elements: TokenSeparatedSequence<'arena, ArrayElement<'arena>>,
40    pub right_parenthesis: Span,
41}
42
43/// Represents a standard PHP array, defined using square brackets `[]`.
44///
45/// # Example:
46///
47/// ```php
48/// <?php
49///
50/// $arr = ['apple', 'banana', 3 => 'orange'];
51/// ```
52#[derive(Debug, Clone, Eq, PartialEq, Hash, PartialOrd, Ord)]
53#[cfg_attr(feature = "serde", derive(serde::Serialize))]
54pub struct Array<'arena> {
55    pub left_bracket: Span,
56    pub elements: TokenSeparatedSequence<'arena, ArrayElement<'arena>>,
57    pub right_bracket: Span,
58}
59
60/// Represents a legacy PHP array, defined using `array` keyword and parentheses `()`.
61///
62/// # Example:
63///
64/// ```php
65/// <?php
66///
67/// $arr = array('apple', 'banana', 3 => 'orange');
68/// ```
69#[derive(Debug, Clone, Eq, PartialEq, Hash, PartialOrd, Ord)]
70#[cfg_attr(feature = "serde", derive(serde::Serialize))]
71pub struct LegacyArray<'arena> {
72    pub array: Keyword<'arena>,
73    pub left_parenthesis: Span,
74    pub elements: TokenSeparatedSequence<'arena, ArrayElement<'arena>>,
75    pub right_parenthesis: Span,
76}
77
78/// Represents an array element.
79#[derive(Debug, Clone, Eq, PartialEq, Hash, PartialOrd, Ord)]
80#[cfg_attr(feature = "serde", derive(serde::Serialize))]
81#[cfg_attr(feature = "serde", serde(tag = "type", content = "value"))]
82pub enum ArrayElement<'arena> {
83    KeyValue(KeyValueArrayElement<'arena>),
84    Value(ValueArrayElement<'arena>),
85    Variadic(VariadicArrayElement<'arena>),
86    Missing(MissingArrayElement),
87}
88
89/// Represents a key-value pair in an array.
90///
91/// # Example:
92///
93/// ```php
94/// <?php
95///
96/// $arr = [
97///   1 => 'orange',
98/// ];
99/// ```
100#[derive(Debug, Clone, Eq, PartialEq, Hash, PartialOrd, Ord)]
101#[cfg_attr(feature = "serde", derive(serde::Serialize))]
102pub struct KeyValueArrayElement<'arena> {
103    pub key: &'arena Expression<'arena>,
104    pub double_arrow: Span,
105    pub value: &'arena Expression<'arena>,
106}
107
108/// Represents a value in an array.
109///
110/// # Example:
111///
112/// ```php
113/// <?php
114///
115/// $arr = [
116///   'orange',
117/// ];
118/// ```
119#[derive(Debug, Clone, Eq, PartialEq, Hash, PartialOrd, Ord)]
120#[cfg_attr(feature = "serde", derive(serde::Serialize))]
121pub struct ValueArrayElement<'arena> {
122    pub value: &'arena Expression<'arena>,
123}
124
125/// Represents a variadic array element.
126///
127/// # Example:
128///
129/// ```php
130/// <?php
131///
132/// $arr = [
133///   ...$other,
134/// ];
135/// ```
136#[derive(Debug, Clone, Eq, PartialEq, Hash, PartialOrd, Ord)]
137#[cfg_attr(feature = "serde", derive(serde::Serialize))]
138pub struct VariadicArrayElement<'arena> {
139    pub ellipsis: Span,
140    pub value: &'arena Expression<'arena>,
141}
142
143/// Represents a missing array element.
144///
145/// # Example:
146///
147/// ```php
148/// <?php
149///
150/// $arr = [
151///   'first',
152///   ,
153///   'third',
154/// ];
155#[derive(Debug, Clone, Eq, PartialEq, Hash, PartialOrd, Ord)]
156#[cfg_attr(feature = "serde", derive(serde::Serialize))]
157pub struct MissingArrayElement {
158    pub comma: Span,
159}
160
161impl<'arena> ArrayElement<'arena> {
162    #[inline]
163    #[must_use]
164    pub const fn is_variadic(&self) -> bool {
165        matches!(self, ArrayElement::Variadic(_))
166    }
167
168    #[inline]
169    #[must_use]
170    pub const fn is_missing(&self) -> bool {
171        matches!(self, ArrayElement::Missing(_))
172    }
173
174    #[inline]
175    #[must_use]
176    pub const fn is_key_value(&self) -> bool {
177        matches!(self, ArrayElement::KeyValue(_))
178    }
179
180    #[inline]
181    #[must_use]
182    pub const fn is_value(&self) -> bool {
183        matches!(self, ArrayElement::Value(_))
184    }
185
186    #[inline]
187    #[must_use]
188    pub fn get_key(&self) -> Option<&Expression<'arena>> {
189        match self {
190            ArrayElement::KeyValue(element) => Some(element.key),
191            ArrayElement::Value(_) => None,
192            ArrayElement::Variadic(_) => None,
193            ArrayElement::Missing(_) => None,
194        }
195    }
196
197    #[inline]
198    #[must_use]
199    pub fn get_value(&self) -> Option<&Expression<'arena>> {
200        match self {
201            ArrayElement::KeyValue(element) => Some(element.value),
202            ArrayElement::Value(element) => Some(element.value),
203            ArrayElement::Variadic(element) => Some(element.value),
204            ArrayElement::Missing(_) => None,
205        }
206    }
207}
208
209impl HasSpan for ArrayAccess<'_> {
210    fn span(&self) -> Span {
211        self.array.span().join(self.right_bracket)
212    }
213}
214
215impl HasSpan for ArrayAppend<'_> {
216    fn span(&self) -> Span {
217        self.array.span().join(self.right_bracket)
218    }
219}
220
221impl HasSpan for List<'_> {
222    fn span(&self) -> Span {
223        self.list.span().join(self.right_parenthesis)
224    }
225}
226
227impl HasSpan for Array<'_> {
228    fn span(&self) -> Span {
229        self.left_bracket.join(self.right_bracket)
230    }
231}
232
233impl HasSpan for LegacyArray<'_> {
234    fn span(&self) -> Span {
235        self.array.span().join(self.right_parenthesis)
236    }
237}
238
239impl HasSpan for ArrayElement<'_> {
240    fn span(&self) -> Span {
241        match self {
242            ArrayElement::KeyValue(element) => element.span(),
243            ArrayElement::Value(element) => element.span(),
244            ArrayElement::Variadic(element) => element.span(),
245            ArrayElement::Missing(element) => element.span(),
246        }
247    }
248}
249
250impl HasSpan for KeyValueArrayElement<'_> {
251    fn span(&self) -> Span {
252        self.key.span().join(self.value.span())
253    }
254}
255
256impl HasSpan for ValueArrayElement<'_> {
257    fn span(&self) -> Span {
258        self.value.span()
259    }
260}
261
262impl HasSpan for VariadicArrayElement<'_> {
263    fn span(&self) -> Span {
264        self.ellipsis.join(self.value.span())
265    }
266}
267
268impl HasSpan for MissingArrayElement {
269    fn span(&self) -> Span {
270        self.comma
271    }
272}