1use crate::expression::Expression;
18use crate::function::PrivateName;
19use crate::visitor::{VisitWith, Visitor, VisitorMut};
20use crate::{Span, Spanned};
21use boa_interner::{Interner, ToInternedString};
22use core::ops::ControlFlow;
23
24use super::Identifier;
25
26#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
30#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
31#[derive(Clone, Debug, PartialEq)]
32pub enum PropertyAccessField {
33 Const(Identifier),
35 Expr(Box<Expression>),
37}
38
39impl Spanned for PropertyAccessField {
40 #[inline]
41 fn span(&self) -> Span {
42 match self {
43 Self::Const(identifier) => identifier.span(),
44 Self::Expr(expression) => expression.span(),
45 }
46 }
47}
48
49impl From<Identifier> for PropertyAccessField {
50 #[inline]
51 fn from(id: Identifier) -> Self {
52 Self::Const(id)
53 }
54}
55
56impl From<Expression> for PropertyAccessField {
57 #[inline]
58 fn from(expr: Expression) -> Self {
59 Self::Expr(Box::new(expr))
60 }
61}
62
63impl VisitWith for PropertyAccessField {
64 fn visit_with<'a, V>(&'a self, visitor: &mut V) -> ControlFlow<V::BreakTy>
65 where
66 V: Visitor<'a>,
67 {
68 match self {
69 Self::Const(sym) => visitor.visit_sym(sym.sym_ref()),
70 Self::Expr(expr) => visitor.visit_expression(expr),
71 }
72 }
73
74 fn visit_with_mut<'a, V>(&'a mut self, visitor: &mut V) -> ControlFlow<V::BreakTy>
75 where
76 V: VisitorMut<'a>,
77 {
78 match self {
79 Self::Const(sym) => visitor.visit_sym_mut(sym.sym_mut()),
80 Self::Expr(expr) => visitor.visit_expression_mut(&mut *expr),
81 }
82 }
83}
84
85#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
89#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
90#[derive(Clone, Debug, PartialEq)]
91pub enum PropertyAccess {
92 Simple(SimplePropertyAccess),
94 Private(PrivatePropertyAccess),
96 Super(SuperPropertyAccess),
98}
99
100impl Spanned for PropertyAccess {
101 #[inline]
102 fn span(&self) -> Span {
103 match self {
104 Self::Simple(access) => access.span(),
105 Self::Private(access) => access.span(),
106 Self::Super(access) => access.span(),
107 }
108 }
109}
110
111impl ToInternedString for PropertyAccess {
112 #[inline]
113 fn to_interned_string(&self, interner: &Interner) -> String {
114 match self {
115 Self::Simple(s) => s.to_interned_string(interner),
116 Self::Private(p) => p.to_interned_string(interner),
117 Self::Super(s) => s.to_interned_string(interner),
118 }
119 }
120}
121
122impl From<PropertyAccess> for Expression {
123 #[inline]
124 fn from(access: PropertyAccess) -> Self {
125 Self::PropertyAccess(access)
126 }
127}
128
129impl VisitWith for PropertyAccess {
130 fn visit_with<'a, V>(&'a self, visitor: &mut V) -> ControlFlow<V::BreakTy>
131 where
132 V: Visitor<'a>,
133 {
134 match self {
135 Self::Simple(spa) => visitor.visit_simple_property_access(spa),
136 Self::Private(ppa) => visitor.visit_private_property_access(ppa),
137 Self::Super(supa) => visitor.visit_super_property_access(supa),
138 }
139 }
140
141 fn visit_with_mut<'a, V>(&'a mut self, visitor: &mut V) -> ControlFlow<V::BreakTy>
142 where
143 V: VisitorMut<'a>,
144 {
145 match self {
146 Self::Simple(spa) => visitor.visit_simple_property_access_mut(spa),
147 Self::Private(ppa) => visitor.visit_private_property_access_mut(ppa),
148 Self::Super(supa) => visitor.visit_super_property_access_mut(supa),
149 }
150 }
151}
152
153#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
155#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
156#[derive(Clone, Debug, PartialEq)]
157pub struct SimplePropertyAccess {
158 target: Box<Expression>,
159 field: PropertyAccessField,
160}
161
162impl SimplePropertyAccess {
163 #[inline]
165 #[must_use]
166 pub const fn target(&self) -> &Expression {
167 &self.target
168 }
169
170 #[inline]
172 #[must_use]
173 pub const fn field(&self) -> &PropertyAccessField {
174 &self.field
175 }
176
177 pub fn new<F>(target: Expression, field: F) -> Self
179 where
180 F: Into<PropertyAccessField>,
181 {
182 Self {
183 target: target.into(),
184 field: field.into(),
185 }
186 }
187}
188
189impl Spanned for SimplePropertyAccess {
190 #[inline]
191 fn span(&self) -> Span {
192 Span::new(self.target.span().start(), self.field.span().end())
193 }
194}
195
196impl ToInternedString for SimplePropertyAccess {
197 #[inline]
198 fn to_interned_string(&self, interner: &Interner) -> String {
199 let target = self.target.to_interned_string(interner);
200 match self.field {
201 PropertyAccessField::Const(ident) => {
202 format!("{target}.{}", interner.resolve_expect(ident.sym()))
203 }
204 PropertyAccessField::Expr(ref expr) => {
205 format!("{target}[{}]", expr.to_interned_string(interner))
206 }
207 }
208 }
209}
210
211impl From<SimplePropertyAccess> for PropertyAccess {
212 #[inline]
213 fn from(access: SimplePropertyAccess) -> Self {
214 Self::Simple(access)
215 }
216}
217
218impl VisitWith for SimplePropertyAccess {
219 fn visit_with<'a, V>(&'a self, visitor: &mut V) -> ControlFlow<V::BreakTy>
220 where
221 V: Visitor<'a>,
222 {
223 visitor.visit_expression(&self.target)?;
224 visitor.visit_property_access_field(&self.field)
225 }
226
227 fn visit_with_mut<'a, V>(&'a mut self, visitor: &mut V) -> ControlFlow<V::BreakTy>
228 where
229 V: VisitorMut<'a>,
230 {
231 visitor.visit_expression_mut(&mut self.target)?;
232 visitor.visit_property_access_field_mut(&mut self.field)
233 }
234}
235
236#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
247#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
248#[derive(Clone, Debug, PartialEq)]
249pub struct PrivatePropertyAccess {
250 target: Box<Expression>,
251 field: PrivateName,
252 span: Span,
253}
254
255impl PrivatePropertyAccess {
256 #[inline]
258 #[must_use]
259 pub fn new(value: Expression, field: PrivateName, span: Span) -> Self {
260 Self {
261 target: value.into(),
262 field,
263 span,
264 }
265 }
266
267 #[inline]
269 #[must_use]
270 pub const fn target(&self) -> &Expression {
271 &self.target
272 }
273
274 #[inline]
276 #[must_use]
277 pub const fn field(&self) -> PrivateName {
278 self.field
279 }
280}
281
282impl Spanned for PrivatePropertyAccess {
283 #[inline]
284 fn span(&self) -> Span {
285 self.span
286 }
287}
288
289impl ToInternedString for PrivatePropertyAccess {
290 #[inline]
291 fn to_interned_string(&self, interner: &Interner) -> String {
292 format!(
293 "{}.#{}",
294 self.target.to_interned_string(interner),
295 interner.resolve_expect(self.field.description())
296 )
297 }
298}
299
300impl From<PrivatePropertyAccess> for PropertyAccess {
301 #[inline]
302 fn from(access: PrivatePropertyAccess) -> Self {
303 Self::Private(access)
304 }
305}
306
307impl VisitWith for PrivatePropertyAccess {
308 fn visit_with<'a, V>(&'a self, visitor: &mut V) -> ControlFlow<V::BreakTy>
309 where
310 V: Visitor<'a>,
311 {
312 visitor.visit_expression(&self.target)?;
313 visitor.visit_private_name(&self.field)
314 }
315
316 fn visit_with_mut<'a, V>(&'a mut self, visitor: &mut V) -> ControlFlow<V::BreakTy>
317 where
318 V: VisitorMut<'a>,
319 {
320 visitor.visit_expression_mut(&mut self.target)?;
321 visitor.visit_private_name_mut(&mut self.field)
322 }
323}
324
325#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
333#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
334#[derive(Clone, Debug, PartialEq)]
335pub struct SuperPropertyAccess {
336 field: PropertyAccessField,
337 span: Span,
338}
339
340impl SuperPropertyAccess {
341 #[must_use]
343 pub const fn new(field: PropertyAccessField, span: Span) -> Self {
344 Self { field, span }
345 }
346
347 #[inline]
349 #[must_use]
350 pub const fn field(&self) -> &PropertyAccessField {
351 &self.field
352 }
353}
354
355impl Spanned for SuperPropertyAccess {
356 #[inline]
357 fn span(&self) -> Span {
358 self.span
359 }
360}
361
362impl ToInternedString for SuperPropertyAccess {
363 #[inline]
364 fn to_interned_string(&self, interner: &Interner) -> String {
365 match &self.field {
366 PropertyAccessField::Const(field) => {
367 format!("super.{}", interner.resolve_expect(field.sym()))
368 }
369 PropertyAccessField::Expr(field) => {
370 format!("super[{}]", field.to_interned_string(interner))
371 }
372 }
373 }
374}
375
376impl From<SuperPropertyAccess> for PropertyAccess {
377 #[inline]
378 fn from(access: SuperPropertyAccess) -> Self {
379 Self::Super(access)
380 }
381}
382
383impl VisitWith for SuperPropertyAccess {
384 fn visit_with<'a, V>(&'a self, visitor: &mut V) -> ControlFlow<V::BreakTy>
385 where
386 V: Visitor<'a>,
387 {
388 visitor.visit_property_access_field(&self.field)
389 }
390
391 fn visit_with_mut<'a, V>(&'a mut self, visitor: &mut V) -> ControlFlow<V::BreakTy>
392 where
393 V: VisitorMut<'a>,
394 {
395 visitor.visit_property_access_field_mut(&mut self.field)
396 }
397}