mago_ast/ast/
array.rs

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