mxmlextrema_as3parser/tree/
expression.rs

1use crate::ns::*;
2use serde::{Serialize, Deserialize};
3
4/// Expression attached with a source location.
5#[derive(Debug, Clone, Serialize, Deserialize)]
6pub enum Expression {
7    QualifiedIdentifier(QualifiedIdentifier),
8    Paren(ParenExpression),
9    NullLiteral(NullLiteral),
10    BooleanLiteral(BooleanLiteral),
11    NumericLiteral(NumericLiteral),
12    StringLiteral(StringLiteral),
13    ThisLiteral(ThisLiteral),
14    RegExpLiteral(RegExpLiteral),
15    Xml(XmlExpression),
16    XmlMarkup(XmlMarkupExpression),
17    XmlList(XmlListExpression),
18    ArrayLiteral(ArrayLiteral),
19    VectorLiteral(VectorLiteral),
20    ObjectInitializer(ObjectInitializer),
21    Function(FunctionExpression),
22    ImportMeta(ImportMeta),
23    New(NewExpression),
24    Member(MemberExpression),
25    ComputedMember(ComputedMemberExpression),
26    Descendants(DescendantsExpression),
27    Filter(FilterExpression),
28    Super(SuperExpression),
29    Call(CallExpression),
30    WithTypeArguments(ApplyTypeExpression),
31    Unary(UnaryExpression),
32    OptionalChaining(OptionalChainingExpression),
33    OptionalChainingPlaceholder(OptionalChainingPlaceholder),
34    Binary(BinaryExpression),
35    Conditional(ConditionalExpression),
36    Assignment(AssignmentExpression),
37    Sequence(SequenceExpression),
38    AnyType(AnyTypeExpression),
39    VoidType(VoidTypeExpression),
40    ArrayType(ArrayTypeExpression),
41    TupleType(TupleTypeExpression),
42    FunctionType(FunctionTypeExpression),
43    Invalidated(InvalidatedNode),
44    ReservedNamespace(ReservedNamespaceExpression),
45}
46
47impl Expression {
48    pub fn location(&self) -> Location {
49        match self {
50            Self::QualifiedIdentifier(e) => e.location.clone(),
51            Self::Paren(e) => e.location.clone(),
52            Self::NullLiteral(e) => e.location.clone(),
53            Self::BooleanLiteral(e) => e.location.clone(),
54            Self::NumericLiteral(e) => e.location.clone(),
55            Self::StringLiteral(e) => e.location.clone(),
56            Self::ThisLiteral(e) => e.location.clone(),
57            Self::RegExpLiteral(e) => e.location.clone(),
58            Self::Xml(e) => e.location.clone(),
59            Self::XmlMarkup(e) => e.location.clone(),
60            Self::XmlList(e) => e.location.clone(),
61            Self::ArrayLiteral(e) => e.location.clone(),
62            Self::VectorLiteral(e) => e.location.clone(),
63            Self::ObjectInitializer(e) => e.location.clone(),
64            Self::Function(e) => e.location.clone(),
65            Self::ImportMeta(e) => e.location.clone(),
66            Self::New(e) => e.location.clone(),
67            Self::Member(e) => e.location.clone(),
68            Self::ComputedMember(e) => e.location.clone(),
69            Self::Descendants(e) => e.location.clone(),
70            Self::Filter(e) => e.location.clone(),
71            Self::Super(e) => e.location.clone(),
72            Self::Call(e) => e.location.clone(),
73            Self::WithTypeArguments(e) => e.location.clone(),
74            Self::Unary(e) => e.location.clone(),
75            Self::OptionalChaining(e) => e.location.clone(),
76            Self::OptionalChainingPlaceholder(e) => e.location.clone(),
77            Self::Binary(e) => e.location.clone(),
78            Self::Conditional(e) => e.location.clone(),
79            Self::Assignment(e) => e.location.clone(),
80            Self::Sequence(e) => e.location.clone(),
81            Self::AnyType(e) => e.location.clone(),
82            Self::VoidType(e) => e.location.clone(),
83            Self::ArrayType(e) => e.location.clone(),
84            Self::TupleType(e) => e.location.clone(),
85            Self::FunctionType(e) => e.location.clone(),
86            Self::Invalidated(e) => e.location.clone(),
87            Self::ReservedNamespace(e) => e.location(),
88        }
89    }
90
91    pub(crate) fn to_metadata(&self, parser: &Parser) -> Result<Option<Vec<Attribute>>, MetadataRefineError1> {
92        match self {
93            Self::ArrayLiteral(ArrayLiteral { elements, asdoc, .. }) => {
94                if elements.len() != 1 {
95                    return Ok(None);
96                }
97                if let Element::Expression(ref exp) = elements[0] {
98                    Ok(Some(vec![Attribute::Metadata(parser.refine_metadata(exp, asdoc.clone()).map_err(|e| MetadataRefineError1(e, exp.location()))?)]))
99                } else {
100                    Ok(None)
101                }
102            },
103            Self::ComputedMember(ComputedMemberExpression { base, asdoc, key, .. }) => {
104                let a = base.to_metadata(parser)?;
105                if a.is_none() {
106                    return Ok(None);
107                }
108                let mut a = a.unwrap();
109                if matches!(key.as_ref(), Self::Sequence(_)) {
110                    return Ok(None);
111                }
112                a.push(Attribute::Metadata(parser.refine_metadata(key, asdoc.clone()).map_err(|e| MetadataRefineError1(e, key.location()))?));
113                Ok(Some(a))
114            },
115            _ => Ok(None),
116        }
117    }
118
119    pub fn to_identifier_name_or_asterisk(&self) -> Option<(String, Location)> {
120        match self {
121            Self::QualifiedIdentifier(id) => id.to_identifier_name_or_asterisk(),
122            _ => None,
123        }
124    }
125
126    pub fn to_identifier_name(&self) -> Option<(String, Location)> {
127        match self {
128            Self::QualifiedIdentifier(id) => id.to_identifier_name(),
129            _ => None,
130        }
131    }
132
133    pub fn valid_access_modifier(&self) -> bool {
134        match self {
135            Self::QualifiedIdentifier(id) => id.is_identifier_token(),
136            Self::Member(e) => e.base.valid_access_modifier(),
137            Self::ComputedMember(e) => e.base.valid_access_modifier(),
138            _ => false,
139        }
140    }
141
142    pub(crate) fn to_reserved_namespace_string(&self) -> Option<String> {
143        if let Self::ReservedNamespace(e) = self {
144            Some(e.to_string())
145        } else {
146            None
147        }
148    }
149
150    pub(crate) fn to_reserved_namespace_attribute(&self) -> Option<Attribute> {
151        if let Self::ReservedNamespace(e) = self {
152            Some(e.to_attribute())
153        } else {
154            None
155        }
156    }
157
158    pub fn is_invalidated(&self) -> bool {
159        matches!(self, Self::Invalidated(_))
160    }
161
162    pub fn is_non_null_operation(&self) -> bool {
163        match self {
164            Self::Unary(expr) => expr.operator == Operator::NonNull,
165            _ => false,
166        }
167    }
168
169    pub fn is_valid_assignment_left_hand_side(&self) -> bool {
170        match self {
171            Self::Invalidated(_) => true,
172            Self::Unary(e) => if e.operator == Operator::NonNull {
173                e.expression.is_valid_assignment_left_hand_side()
174            } else {
175                true
176            },
177            Self::ArrayLiteral(_) | Self::ObjectInitializer(_) => self.is_valid_destructuring(),
178            _ => true,
179        }
180    }
181
182    pub fn is_valid_destructuring(&self) -> bool {
183        match self {
184            Self::Invalidated(_) => true,
185            Self::QualifiedIdentifier(id) => !id.attribute && id.qualifier.is_none() && match &id.id {
186                QualifiedIdentifierIdentifier::Id(id) => id.0 != "*",
187                _ => false,
188            },
189            Self::ArrayLiteral(expr) => {
190                for el in &expr.elements {
191                    match el {
192                        Element::Elision => {},
193                        Element::Expression(expr) => {
194                            if !expr.is_valid_destructuring() {
195                                return false;
196                            }
197                        },
198                        Element::Rest((expr, _)) => {
199                            if !expr.is_valid_destructuring() {
200                                return false;
201                            }
202                        },
203                    }
204                }
205                true
206            },
207            Self::ObjectInitializer(init) => {
208                for field in init.fields.iter() {
209                    match field.as_ref() {
210                        InitializerField::Field { value, .. } => {
211                            if let Some(val) = value {
212                                if !val.is_valid_destructuring() {
213                                    return false;
214                                }
215                            }
216                        },
217                        InitializerField::Rest((expr, _)) => {
218                            if !expr.is_valid_destructuring() {
219                                return false;
220                            }
221                        },
222                    }
223                }
224                true
225            },
226            _ => false,
227        }
228    }
229
230    /// `CONFIG::VAR_NAME`
231    pub(crate) fn to_configuration_identifier(&self, parser: &Parser) -> Result<Option<((String, Location), (String, Location), Vec<Attribute>)>, MetadataRefineError1> {
232        if let Self::QualifiedIdentifier(id) = self {
233            if id.attribute {
234                return Ok(None);
235            }
236            if let Some(q) = &id.qualifier {
237                if let Some(q) = q.to_identifier_name() {
238                    if let QualifiedIdentifierIdentifier::Id(id) = &id.id {
239                        return Ok(Some((q, id.clone(), vec![])));
240                    }
241                }
242            }
243        }
244        if let Self::ComputedMember(ComputedMemberExpression { base, asdoc, key, .. }) = self {
245            let a = base.to_configuration_identifier(parser)?;
246            if a.is_none() {
247                return Ok(None);
248            }
249            let (ns, name, mut a) = a.unwrap();
250            if matches!(key.as_ref(), Self::Sequence(_)) {
251                return Ok(None);
252            }
253            a.push(Attribute::Metadata(parser.refine_metadata(key, asdoc.clone()).map_err(|e| MetadataRefineError1(e, key.location()))?));
254            return Ok(Some((ns, name, a)));
255        }
256        Ok(None)
257    }
258
259    /// `CONFIG::VAR_NAME`
260    pub(crate) fn to_configuration_identifier_no_metadata(&self) -> Option<((String, Location), (String, Location))> {
261        if let Self::QualifiedIdentifier(id) = self {
262            if id.attribute {
263                return None;
264            }
265            if let Some(q) = &id.qualifier {
266                if let Some(q) = q.to_identifier_name() {
267                    if let QualifiedIdentifierIdentifier::Id(id) = &id.id {
268                        return Some((q, id.clone()));
269                    }
270                }
271            }
272        }
273        None
274    }
275
276    pub fn search_optional_chaining_placeholder(self: &Rc<Self>) -> Option<Rc<Expression>> {
277        match self.as_ref() {
278            Self::OptionalChainingPlaceholder(_) => Some(self.clone()),
279            Self::Member(e) => e.base.search_optional_chaining_placeholder(),
280            Self::ComputedMember(e) => e.base.search_optional_chaining_placeholder(),
281            Self::Descendants(e) => e.base.search_optional_chaining_placeholder(),
282            Self::Filter(e) => e.base.search_optional_chaining_placeholder(),
283            Self::Unary(e) => e.expression.search_optional_chaining_placeholder(),
284            Self::Call(e) => e.base.search_optional_chaining_placeholder(),
285            Self::WithTypeArguments(e) => e.base.search_optional_chaining_placeholder(),
286            _ => None,
287        }
288    }
289}