Skip to main content

boa_ast/
property.rs

1//! Property definition related types, used in object literals and class definitions.
2
3use super::{Expression, Spanned};
4use crate::{
5    expression::Identifier,
6    visitor::{VisitWith, Visitor, VisitorMut},
7};
8use boa_interner::{Interner, ToInternedString};
9use core::ops::ControlFlow;
10
11/// `PropertyName` can be either a literal or computed.
12///
13/// More information:
14///  - [ECMAScript reference][spec]
15///
16/// [spec]: https://tc39.es/ecma262/#prod-PropertyName
17#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
18#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
19#[derive(Clone, Debug, PartialEq)]
20pub enum PropertyName {
21    /// A `Literal` property name can be either an identifier, a string or a numeric literal.
22    ///
23    /// More information:
24    ///  - [ECMAScript reference][spec]
25    ///
26    /// [spec]: https://tc39.es/ecma262/#prod-LiteralPropertyName
27    Literal(Identifier),
28
29    /// A `Computed` property name is an expression that gets evaluated and converted into a property name.
30    ///
31    /// More information:
32    ///  - [ECMAScript reference][spec]
33    ///
34    /// [spec]: https://tc39.es/ecma262/#prod-ComputedPropertyName
35    Computed(Expression),
36}
37
38impl PropertyName {
39    /// Returns the literal property name if it exists.
40    #[must_use]
41    pub const fn literal(&self) -> Option<Identifier> {
42        if let Self::Literal(ident) = self {
43            Some(*ident)
44        } else {
45            None
46        }
47    }
48
49    /// Returns the expression if the property name is computed.
50    #[must_use]
51    pub const fn computed(&self) -> Option<&Expression> {
52        if let Self::Computed(expr) = self {
53            Some(expr)
54        } else {
55            None
56        }
57    }
58
59    /// Returns either the literal property name or the computed const string property name.
60    #[must_use]
61    pub fn prop_name(&self) -> Option<Identifier> {
62        match self {
63            Self::Literal(ident) => Some(*ident),
64            Self::Computed(Expression::Literal(lit)) => lit
65                .as_string()
66                .map(|value| Identifier::new(value, lit.span())),
67            Self::Computed(_) => None,
68        }
69    }
70}
71
72impl ToInternedString for PropertyName {
73    fn to_interned_string(&self, interner: &Interner) -> String {
74        match self {
75            Self::Literal(key) => interner.resolve_expect(key.sym()).to_string(),
76            Self::Computed(key) => format!("[{}]", key.to_interned_string(interner)),
77        }
78    }
79}
80
81impl From<Identifier> for PropertyName {
82    fn from(name: Identifier) -> Self {
83        Self::Literal(name)
84    }
85}
86
87impl From<Expression> for PropertyName {
88    fn from(name: Expression) -> Self {
89        Self::Computed(name)
90    }
91}
92
93impl VisitWith for PropertyName {
94    fn visit_with<'a, V>(&'a self, visitor: &mut V) -> ControlFlow<V::BreakTy>
95    where
96        V: Visitor<'a>,
97    {
98        match self {
99            Self::Literal(ident) => visitor.visit_sym(ident.sym_ref()),
100            Self::Computed(expr) => visitor.visit_expression(expr),
101        }
102    }
103
104    fn visit_with_mut<'a, V>(&'a mut self, visitor: &mut V) -> ControlFlow<V::BreakTy>
105    where
106        V: VisitorMut<'a>,
107    {
108        match self {
109            Self::Literal(ident) => visitor.visit_sym_mut(ident.sym_mut()),
110            Self::Computed(expr) => visitor.visit_expression_mut(expr),
111        }
112    }
113}
114
115/// The kind of a method definition.
116#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
117#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
118#[derive(Copy, Clone, Debug, PartialEq)]
119pub enum MethodDefinitionKind {
120    /// A getter method.
121    Get,
122
123    /// A setter method.
124    Set,
125
126    /// An ordinary method.
127    Ordinary,
128
129    /// A generator method.
130    Generator,
131
132    /// An async generator method.
133    AsyncGenerator,
134
135    /// An async method.
136    Async,
137}