Skip to main content

just_engine/parser/
ast.rs

1use crate::parser::util::{format_has_meta_option, format_option, format_struct, format_vec};
2use pest::error::Error;
3use std::fmt;
4use std::fmt::{Debug, Display, Formatter};
5use std::hash::{Hash, Hasher};
6use std::rc::Rc;
7
8#[derive(Debug)]
9pub struct JsError<Rule> {
10    pub kind: JsErrorType<Rule>,
11    pub message: String,
12}
13
14#[derive(Debug)]
15pub enum JsErrorType<R> {
16    Unexpected(&'static str),
17    ParserValidation(Error<R>),
18    AstBuilderValidation(AstBuilderValidationErrorType, Meta),
19    ParserGeneralError,
20}
21
22#[derive(Debug)]
23pub enum AstBuilderValidationErrorType {
24    SyntaxError,
25    ReferenceError,
26}
27
28#[derive(Debug)]
29pub struct Meta {
30    pub start_index: usize,
31    pub end_index: usize,
32    pub script: Rc<String>,
33}
34impl Meta {
35    pub fn to_formatted_string(&self, script: &str) -> String {
36        format!(
37            "Meta {{ \"{}\" }}",
38            &script[self.start_index..self.end_index].replace("\n", "░")
39        )
40    }
41
42    pub fn to_formatted_code(&self) -> String {
43        if self.script.len() <= self.end_index {
44            self.script[self.start_index..self.end_index].to_string()
45        } else {
46            "[unknown]".to_string()
47        }
48    }
49}
50impl Clone for Meta {
51    fn clone(&self) -> Self {
52        Meta {
53            start_index: self.start_index,
54            end_index: self.end_index,
55            script: self.script.clone(),
56        }
57    }
58}
59
60pub trait HasMeta {
61    fn get_meta(&self) -> &Meta;
62    fn to_formatted_string(&self, script: &str) -> String;
63}
64
65#[derive(Debug)]
66pub struct IdentifierData {
67    pub name: String,
68    pub meta: Meta,
69    pub is_binding_identifier: bool,
70}
71impl HasMeta for IdentifierData {
72    fn get_meta(&self) -> &Meta {
73        &self.meta
74    }
75
76    fn to_formatted_string(&self, script: &str) -> String {
77        format_struct("IdentifierData")
78            .add_fields("meta", self.meta.to_formatted_string(script))
79            .add_fields("name", self.name.to_string())
80            .to_string()
81    }
82}
83impl PartialEq for IdentifierData {
84    fn eq(&self, other: &Self) -> bool {
85        self.name == other.name
86    }
87}
88impl Eq for IdentifierData {}
89impl Hash for IdentifierData {
90    fn hash<H: Hasher>(&self, state: &mut H) {
91        self.name.hash(state)
92    }
93}
94impl Clone for IdentifierData {
95    fn clone(&self) -> Self {
96        IdentifierData {
97            name: self.name.to_string(),
98            meta: self.meta.clone(),
99            is_binding_identifier: self.is_binding_identifier,
100        }
101    }
102}
103impl Display for IdentifierData {
104    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
105        write!(f, "'{}'", self.name)
106    }
107}
108
109#[derive(Debug)]
110pub enum ExpressionPatternType {
111    Identifier(IdentifierData),
112}
113
114impl ExpressionPatternType {
115    pub fn convert_to_pattern(self) -> PatternType {
116        PatternType::PatternWhichCanBeExpression(self)
117    }
118
119    pub fn convert_to_expression(self) -> ExpressionType {
120        ExpressionType::ExpressionWhichCanBePattern(self)
121    }
122}
123impl HasMeta for ExpressionPatternType {
124    fn get_meta(&self) -> &Meta {
125        match self {
126            ExpressionPatternType::Identifier(data) => &data.meta,
127        }
128    }
129
130    fn to_formatted_string(&self, script: &str) -> String {
131        match self {
132            ExpressionPatternType::Identifier(data) => {
133                format!(
134                    "ExpressionPatternType::Identifier({})",
135                    data.to_formatted_string(script)
136                )
137            }
138        }
139    }
140}
141
142#[derive(Debug)]
143pub enum ExpressionType {
144    ExpressionWhichCanBePattern(ExpressionPatternType),
145    Literal(LiteralData),
146    MemberExpression(MemberExpressionType),
147    ThisExpression {
148        meta: Meta,
149    },
150    ArrayExpression {
151        meta: Meta,
152        elements: Vec<Option<ExpressionOrSpreadElement>>,
153    },
154    ObjectExpression {
155        meta: Meta,
156        properties: Vec<PropertyData<Box<ExpressionType>>>,
157    },
158    FunctionOrGeneratorExpression(FunctionData),
159    UnaryExpression {
160        meta: Meta,
161        operator: UnaryOperator,
162        argument: Box<ExpressionType>,
163    },
164    UpdateExpression {
165        meta: Meta,
166        operator: UpdateOperator,
167        argument: Box<ExpressionType>,
168        prefix: bool,
169    },
170    BinaryExpression {
171        meta: Meta,
172        operator: BinaryOperator,
173        left: Box<ExpressionType>,
174        right: Box<ExpressionType>,
175    },
176    AssignmentExpression {
177        meta: Meta,
178        operator: AssignmentOperator,
179        left: PatternOrExpression,
180        right: Box<ExpressionType>,
181    },
182    LogicalExpression {
183        meta: Meta,
184        operator: LogicalOperator,
185        left: Box<ExpressionType>,
186        right: Box<ExpressionType>,
187    },
188    ConditionalExpression {
189        meta: Meta,
190        test: Box<ExpressionType>,
191        consequent: Box<ExpressionType>,
192        alternate: Box<ExpressionType>,
193    },
194    CallExpression {
195        //A function or method call expression.
196        meta: Meta,
197        callee: ExpressionOrSuper,
198        arguments: Vec<ExpressionOrSpreadElement>,
199    },
200    NewExpression {
201        meta: Meta,
202        callee: Box<ExpressionType>,
203        arguments: Vec<ExpressionOrSpreadElement>,
204    },
205    SequenceExpression {
206        //A comma-separated sequence of expressions
207        meta: Meta,
208        expressions: Vec<Box<ExpressionType>>,
209    },
210    ArrowFunctionExpression {
211        meta: Meta,
212        params: Vec<PatternType>,
213        body: Box<FunctionBodyOrExpression>,
214    },
215    YieldExpression {
216        meta: Meta,
217        argument: Option<Box<ExpressionType>>,
218        delegate: bool,
219    },
220    TemplateLiteral(TemplateLiteralData),
221    TaggedTemplateExpression {
222        meta: Meta,
223        tag: Box<ExpressionType>,
224        quasi: TemplateLiteralData,
225    },
226    ClassExpression(ClassData),
227    MetaProperty {
228        //Represents new.target meta property in ES2015. In the future, it will represent other meta properties as well.
229        meta: Meta,
230        meta_object: IdentifierData,
231        property: IdentifierData,
232    },
233}
234
235impl HasMeta for ExpressionType {
236    fn get_meta(&self) -> &Meta {
237        match self {
238            ExpressionType::Literal(data) => &data.meta,
239            ExpressionType::ThisExpression { meta } => &meta,
240            ExpressionType::ArrayExpression { meta, .. } => &meta,
241            ExpressionType::ObjectExpression { meta, .. } => &meta,
242            ExpressionType::FunctionOrGeneratorExpression(data) => &data.meta,
243            ExpressionType::UnaryExpression { meta, .. } => &meta,
244            ExpressionType::UpdateExpression { meta, .. } => &meta,
245            ExpressionType::BinaryExpression { meta, .. } => &meta,
246            ExpressionType::AssignmentExpression { meta, .. } => &meta,
247            ExpressionType::LogicalExpression { meta, .. } => &meta,
248            ExpressionType::ConditionalExpression { meta, .. } => &meta,
249            ExpressionType::CallExpression { meta, .. } => &meta,
250            ExpressionType::NewExpression { meta, .. } => &meta,
251            ExpressionType::SequenceExpression { meta, .. } => &meta,
252            ExpressionType::ArrowFunctionExpression { meta, .. } => &meta,
253            ExpressionType::YieldExpression { meta, .. } => &meta,
254            ExpressionType::TemplateLiteral(data) => &data.meta,
255            ExpressionType::TaggedTemplateExpression { meta, .. } => &meta,
256            ExpressionType::ClassExpression(data) => &data.meta,
257            ExpressionType::MetaProperty { meta, .. } => &meta,
258            ExpressionType::ExpressionWhichCanBePattern(d) => d.get_meta(),
259            ExpressionType::MemberExpression(data) => data.get_meta(),
260        }
261    }
262
263    fn to_formatted_string(&self, script: &str) -> String {
264        match self {
265            ExpressionType::Literal(data) => format!(
266                "ExpressionType::Literal({})",
267                data.to_formatted_string(script)
268            ),
269            ExpressionType::ThisExpression { meta } => {
270                format_struct("ExpressionType::ThisExpression")
271                    .add_fields("meta", meta.to_formatted_string(script))
272                    .to_string()
273            }
274            ExpressionType::ArrayExpression { meta, elements } => {
275                format_struct("ExpressionType::ArrayExpression")
276                    .add_fields("meta", meta.to_formatted_string(script))
277                    .add_fields(
278                        "elements",
279                        format_vec(elements, |p| format_has_meta_option(&p, script)),
280                    )
281                    .to_string()
282            }
283            ExpressionType::ObjectExpression { meta, properties } => {
284                format_struct("ExpressionType::ObjectExpression")
285                    .add_fields("meta", meta.to_formatted_string(script))
286                    .add_fields(
287                        "properties",
288                        format_vec(properties, |p| p.to_formatted_string(script)),
289                    )
290                    .to_string()
291            }
292            ExpressionType::FunctionOrGeneratorExpression(data) => format!(
293                "ExpressionType::FunctionExpression({})",
294                data.to_formatted_string(script)
295            ),
296            ExpressionType::UnaryExpression {
297                meta,
298                operator,
299                argument,
300            } => format_struct("ExpressionType::UnaryExpression")
301                .add_fields("meta", meta.to_formatted_string(script))
302                .add_fields("operator", format!("{:?}", operator))
303                .add_fields("argument", argument.to_formatted_string(script))
304                .to_string(),
305            ExpressionType::UpdateExpression {
306                meta,
307                operator,
308                argument,
309                prefix,
310            } => format_struct("ExpressionType::UpdateExpression")
311                .add_fields("meta", meta.to_formatted_string(script))
312                .add_fields("operator", format!("{:?}", operator))
313                .add_fields("argument", argument.to_formatted_string(script))
314                .add_fields("prefix", format!("{}", prefix))
315                .to_string(),
316            ExpressionType::BinaryExpression {
317                meta,
318                operator,
319                left,
320                right,
321            } => format_struct("ExpressionType::BinaryExpression")
322                .add_fields("meta", meta.to_formatted_string(script))
323                .add_fields("operator", format!("{:?}", operator))
324                .add_fields("left", left.to_formatted_string(script))
325                .add_fields("right", right.to_formatted_string(script))
326                .to_string(),
327            ExpressionType::AssignmentExpression {
328                meta,
329                operator,
330                left,
331                right,
332            } => format_struct("ExpressionType::AssignmentExpression")
333                .add_fields("meta", meta.to_formatted_string(script))
334                .add_fields("operator", format!("{:?}", operator))
335                .add_fields("left", left.to_formatted_string(script))
336                .add_fields("right", right.to_formatted_string(script))
337                .to_string(),
338            ExpressionType::LogicalExpression {
339                meta,
340                operator,
341                left,
342                right,
343            } => format_struct("ExpressionType::LogicalExpression")
344                .add_fields("meta", meta.to_formatted_string(script))
345                .add_fields("operator", format!("{:?}", operator))
346                .add_fields("left", left.to_formatted_string(script))
347                .add_fields("right", right.to_formatted_string(script))
348                .to_string(),
349            ExpressionType::ConditionalExpression {
350                meta,
351                test,
352                consequent,
353                alternate,
354            } => format_struct("ExpressionType::ConditionalExpression")
355                .add_fields("meta", meta.to_formatted_string(script))
356                .add_fields("test", test.to_formatted_string(script))
357                .add_fields("consequent", consequent.to_formatted_string(script))
358                .add_fields("alternate", alternate.to_formatted_string(script))
359                .to_string(),
360            ExpressionType::CallExpression {
361                meta,
362                callee,
363                arguments,
364            } => format_struct("ExpressionType::CallExpression")
365                .add_fields("meta", meta.to_formatted_string(script))
366                .add_fields("callee", callee.to_formatted_string(script))
367                .add_fields(
368                    "arguments",
369                    format_vec(arguments, |p| p.to_formatted_string(script)),
370                )
371                .to_string(),
372            ExpressionType::NewExpression {
373                meta,
374                callee,
375                arguments,
376            } => format_struct("ExpressionType::NewExpression")
377                .add_fields("meta", meta.to_formatted_string(script))
378                .add_fields("callee", callee.to_formatted_string(script))
379                .add_fields(
380                    "arguments",
381                    format_vec(arguments, |p| p.to_formatted_string(script)),
382                )
383                .to_string(),
384            ExpressionType::SequenceExpression { meta, expressions } => {
385                format_struct("ExpressionType::SequenceExpression")
386                    .add_fields("meta", meta.to_formatted_string(script))
387                    .add_fields(
388                        "expressions",
389                        format_vec(expressions, |p| p.to_formatted_string(script)),
390                    )
391                    .to_string()
392            }
393            ExpressionType::ArrowFunctionExpression { meta, params, body } => {
394                format_struct("ExpressionType::ArrowFunctionExpression")
395                    .add_fields("meta", meta.to_formatted_string(script))
396                    .add_fields(
397                        "params",
398                        format_vec(params, |p| p.to_formatted_string(script)),
399                    )
400                    .add_fields("body", body.to_formatted_string(script))
401                    .to_string()
402            }
403            ExpressionType::YieldExpression {
404                meta,
405                argument,
406                delegate,
407            } => format_struct("ExpressionType::yield_expression")
408                .add_fields("meta", meta.to_formatted_string(script))
409                .add_fields(
410                    "argument",
411                    format_option(argument, |o| o.to_formatted_string(script)),
412                )
413                .add_fields("delegate", delegate.to_string())
414                .to_string(),
415            ExpressionType::TemplateLiteral(data) => format!(
416                "ExpressionType::TemplateLiteral({})",
417                data.to_formatted_string(script)
418            ),
419            ExpressionType::TaggedTemplateExpression { meta, tag, quasi } => {
420                format_struct("ExpressionType::TaggedTemplateExpression")
421                    .add_fields("meta", meta.to_formatted_string(script))
422                    .add_fields("tag", tag.to_formatted_string(script))
423                    .add_fields("quasi", quasi.to_formatted_string(script))
424                    .to_string()
425            }
426            ExpressionType::ClassExpression(data) => format!(
427                "ExpressionType::ClassExpression({})",
428                data.to_formatted_string(script)
429            ),
430            ExpressionType::MetaProperty {
431                meta,
432                meta_object,
433                property,
434            } => format_struct("ExpressionType::TaggedTemplateExpression")
435                .add_fields("meta", meta.to_formatted_string(script))
436                .add_fields("meta_object", meta_object.to_formatted_string(script))
437                .add_fields("property", property.to_formatted_string(script))
438                .to_string(),
439            ExpressionType::ExpressionWhichCanBePattern(d) => format!(
440                "ExpressionType::ExpressionWhichCanBePattern({})",
441                d.to_formatted_string(script)
442            ),
443            ExpressionType::MemberExpression(data) => format!(
444                "ExpressionType::MemberExpression({})",
445                data.to_formatted_string(script)
446            ),
447        }
448    }
449}
450
451#[derive(Debug)]
452pub enum PatternType {
453    PatternWhichCanBeExpression(ExpressionPatternType),
454    ObjectPattern {
455        meta: Meta,
456        properties: Vec<AssignmentPropertyData>,
457    },
458    ArrayPattern {
459        meta: Meta,
460        elements: Vec<Option<Box<PatternType>>>,
461    },
462    RestElement {
463        meta: Meta,
464        argument: Box<PatternType>,
465    },
466    AssignmentPattern {
467        meta: Meta,
468        left: Box<PatternType>,
469        right: Box<ExpressionType>,
470    },
471}
472impl HasMeta for PatternType {
473    fn get_meta(&self) -> &Meta {
474        match self {
475            PatternType::ObjectPattern { meta, .. } => &meta,
476            PatternType::ArrayPattern { meta, .. } => &meta,
477            PatternType::RestElement { meta, .. } => &meta,
478            PatternType::AssignmentPattern { meta, .. } => &meta,
479            PatternType::PatternWhichCanBeExpression(d) => d.get_meta(),
480        }
481    }
482
483    fn to_formatted_string(&self, script: &str) -> String {
484        match self {
485            PatternType::ObjectPattern { meta, properties } => {
486                format_struct("PatternType::ObjectPattern")
487                    .add_fields("meta", meta.to_formatted_string(script))
488                    .add_fields(
489                        "properties",
490                        format_vec(properties, |p| p.to_formatted_string(script)),
491                    )
492                    .to_string()
493            }
494            PatternType::ArrayPattern { meta, elements } => {
495                format_struct("PatternType::ArrayPattern")
496                    .add_fields("meta", meta.to_formatted_string(script))
497                    .add_fields(
498                        "elements",
499                        format_vec(elements, |p| {
500                            format_option(&p, |o| o.to_formatted_string(script))
501                        }),
502                    )
503                    .to_string()
504            }
505            PatternType::RestElement { meta, argument } => {
506                format_struct("PatternType::RestElement")
507                    .add_fields("meta", meta.to_formatted_string(script))
508                    .add_fields("argument", argument.to_formatted_string(script))
509                    .to_string()
510            }
511            PatternType::AssignmentPattern { meta, left, right } => {
512                format_struct("ExpressionType::AssignmentPattern")
513                    .add_fields("meta", meta.to_formatted_string(script))
514                    .add_fields("left", left.to_formatted_string(script))
515                    .add_fields("right", right.to_formatted_string(script))
516                    .to_string()
517            }
518            PatternType::PatternWhichCanBeExpression(d) => format!(
519                "PatternType::PatternWhichCanBeExpression({})",
520                d.to_formatted_string(script)
521            ),
522        }
523    }
524}
525
526#[derive(Debug)]
527pub struct TemplateLiteralData {
528    pub meta: Meta,
529    pub quasis: Vec<TemplateElementData>,
530    pub expressions: Vec<Box<ExpressionType>>,
531}
532
533impl HasMeta for TemplateLiteralData {
534    fn get_meta(&self) -> &Meta {
535        &self.meta
536    }
537
538    fn to_formatted_string(&self, script: &str) -> String {
539        format_struct("TemplateLiteralData")
540            .add_fields("meta", self.meta.to_formatted_string(script))
541            .add_fields(
542                "quasis",
543                format_vec(&self.quasis, |p| p.to_formatted_string(script)),
544            )
545            .add_fields(
546                "expressions",
547                format_vec(&self.expressions, |p| p.to_formatted_string(script)),
548            )
549            .to_string()
550    }
551}
552
553#[derive(Debug)]
554pub struct TemplateElementData {
555    pub meta: Meta,
556    pub tail: bool,
557    pub cooked_value: String,
558    pub raw_value: String,
559}
560
561impl HasMeta for TemplateElementData {
562    fn get_meta(&self) -> &Meta {
563        &self.meta
564    }
565
566    fn to_formatted_string(&self, script: &str) -> String {
567        format_struct("TemplateElementData")
568            .add_fields("meta", self.meta.to_formatted_string(script))
569            .add_fields("tail", self.tail.to_string())
570            .add_fields("cooked_value", self.cooked_value.to_string())
571            .add_fields("raw_value", self.raw_value.to_string())
572            .to_string()
573    }
574}
575
576#[derive(Debug)]
577pub enum FunctionBodyOrExpression {
578    FunctionBody(FunctionBodyData),
579    Expression(ExpressionType),
580}
581
582impl HasMeta for FunctionBodyOrExpression {
583    fn get_meta(&self) -> &Meta {
584        match self {
585            FunctionBodyOrExpression::FunctionBody(d) => d.get_meta(),
586            FunctionBodyOrExpression::Expression(d) => d.get_meta(),
587        }
588    }
589
590    fn to_formatted_string(&self, script: &str) -> String {
591        match self {
592            FunctionBodyOrExpression::FunctionBody(d) => format!(
593                "FunctionBodyOrExpression::FunctionBody({})",
594                d.to_formatted_string(script)
595            ),
596            FunctionBodyOrExpression::Expression(d) => format!(
597                "FunctionBodyOrExpression::Expression({})",
598                d.to_formatted_string(script)
599            ),
600        }
601    }
602}
603
604#[derive(Debug)]
605pub enum ExpressionOrSuper {
606    Expression(Box<ExpressionType>),
607    Super,
608}
609
610impl HasMeta for ExpressionOrSuper {
611    fn get_meta(&self) -> &Meta {
612        match self {
613            ExpressionOrSuper::Expression(d) => d.get_meta(),
614            ExpressionOrSuper::Super => panic!("Tried to get meta of ExpressionOrSuper::Super"),
615        }
616    }
617
618    fn to_formatted_string(&self, script: &str) -> String {
619        match self {
620            ExpressionOrSuper::Expression(d) => format!(
621                "ExpressionOrSuper::Expression({})",
622                d.to_formatted_string(script)
623            ),
624            ExpressionOrSuper::Super => format!("ExpressionOrSuper::Super"),
625        }
626    }
627}
628
629#[derive(Debug)]
630pub enum MemberExpressionType {
631    SimpleMemberExpression {
632        meta: Meta,
633        object: ExpressionOrSuper,
634        property: IdentifierData,
635    },
636    ComputedMemberExpression {
637        meta: Meta,
638        object: ExpressionOrSuper,
639        property: Box<ExpressionType>,
640    },
641}
642
643impl HasMeta for MemberExpressionType {
644    fn get_meta(&self) -> &Meta {
645        match self {
646            MemberExpressionType::SimpleMemberExpression { meta, .. } => &meta,
647            MemberExpressionType::ComputedMemberExpression { meta, .. } => &meta,
648        }
649    }
650
651    fn to_formatted_string(&self, script: &str) -> String {
652        match self {
653            MemberExpressionType::SimpleMemberExpression {
654                meta,
655                object,
656                property,
657            } => format_struct("MemberExpressionType::SimpleMemberExpression")
658                .add_fields("meta", meta.to_formatted_string(script))
659                .add_fields("object", object.to_formatted_string(script))
660                .add_fields("property", property.to_formatted_string(script))
661                .to_string(),
662            MemberExpressionType::ComputedMemberExpression {
663                meta,
664                object,
665                property,
666            } => format_struct("MemberExpressionType::ComputedMemberExpression")
667                .add_fields("meta", meta.to_formatted_string(script))
668                .add_fields("object", object.to_formatted_string(script))
669                .add_fields("property", property.to_formatted_string(script))
670                .to_string(),
671        }
672    }
673}
674
675#[derive(Debug)]
676pub enum ExpressionOrSpreadElement {
677    Expression(Box<ExpressionType>),
678    SpreadElement(Box<ExpressionType>),
679}
680
681impl HasMeta for ExpressionOrSpreadElement {
682    fn get_meta(&self) -> &Meta {
683        match self {
684            ExpressionOrSpreadElement::Expression(data) => data.get_meta(),
685            ExpressionOrSpreadElement::SpreadElement(data) => data.get_meta(),
686        }
687    }
688
689    fn to_formatted_string(&self, script: &str) -> String {
690        match self {
691            ExpressionOrSpreadElement::Expression(data) => format!(
692                "ExpressionOrSpreadElement::Expression({})",
693                data.to_formatted_string(script)
694            ),
695            ExpressionOrSpreadElement::SpreadElement(data) => format!(
696                "ExpressionOrSpreadElement::SpreadElement({})",
697                data.to_formatted_string(script)
698            ),
699        }
700    }
701}
702
703#[derive(Debug)]
704pub struct MemberExpressionData {
705    pub meta: Meta,
706    pub object: Box<ExpressionType>,
707    pub property: Box<ExpressionType>,
708    pub computed: bool,
709}
710
711#[derive(Debug)]
712pub enum PatternOrExpression {
713    Pattern(Box<PatternType>),
714    Expression(Box<ExpressionType>),
715}
716
717impl HasMeta for PatternOrExpression {
718    fn get_meta(&self) -> &Meta {
719        match self {
720            PatternOrExpression::Pattern(d) => d.get_meta(),
721            PatternOrExpression::Expression(d) => d.get_meta(),
722        }
723    }
724
725    fn to_formatted_string(&self, script: &str) -> String {
726        match self {
727            PatternOrExpression::Pattern(d) => d.to_formatted_string(script),
728            PatternOrExpression::Expression(d) => d.to_formatted_string(script),
729        }
730    }
731}
732
733#[derive(Debug)]
734pub enum AssignmentOperator {
735    Equals,
736    AddEquals,
737    SubtractEquals,
738    MultiplyEquals,
739    DivideEquals,
740    ModuloEquals,
741    BitwiseLeftShiftEquals,
742    BitwiseRightShiftEquals,
743    BitwiseUnsignedRightShiftEquals,
744    BitwiseOrEquals,
745    BitwiseAndEquals,
746    BitwiseXorEquals,
747}
748
749#[derive(Debug)]
750pub enum UnaryOperator {
751    Minus,
752    Plus,
753    LogicalNot,
754    BitwiseNot,
755    TypeOf,
756    Void,
757    Delete,
758}
759
760#[derive(Debug)]
761pub enum UpdateOperator {
762    PlusPlus,
763    MinusMinus,
764}
765
766#[derive(Debug)]
767pub enum BinaryOperator {
768    LooselyEqual,
769    LooselyUnequal,
770    StrictlyEqual,
771    StrictlyUnequal,
772    LessThan,
773    LessThanEqual,
774    GreaterThan,
775    GreaterThanEqual,
776    BitwiseLeftShift,
777    BitwiseRightShift,
778    BitwiseUnsignedRightShift,
779    Add,
780    Subtract,
781    Multiply,
782    Divide,
783    Modulo,
784    BitwiseOr,
785    BitwiseAnd,
786    BitwiseXor,
787    In,
788    InstanceOf,
789}
790
791#[derive(Debug)]
792pub enum LogicalOperator {
793    Or,
794    And,
795}
796
797#[derive(Debug)]
798pub struct LiteralData {
799    pub meta: Meta,
800    pub value: LiteralType,
801}
802
803impl HasMeta for LiteralData {
804    fn get_meta(&self) -> &Meta {
805        &self.meta
806    }
807
808    fn to_formatted_string(&self, script: &str) -> String {
809        format_struct("LiteralData")
810            .add_fields("meta", self.meta.to_formatted_string(script))
811            .add_fields("value", format!("{:?}", self.value))
812            .to_string()
813    }
814}
815
816#[derive(Debug)]
817pub enum LiteralType {
818    StringLiteral(String),
819    BooleanLiteral(bool),
820    NullLiteral,
821    NumberLiteral(NumberLiteralType),
822    RegExpLiteral(RegExpLiteralData),
823}
824
825#[derive(Debug)]
826pub struct RegExpLiteralData {
827    pub pattern: String,
828    pub flags: String,
829}
830
831#[derive(Debug)]
832pub enum NumberLiteralType {
833    IntegerLiteral(i64),
834    FloatLiteral(f64),
835}
836
837#[derive(Debug)]
838pub enum ExtendedNumberLiteralType {
839    Std(NumberLiteralType),
840    Infinity,
841    NegativeInfinity,
842}
843#[cfg(test)]
844impl ExtendedNumberLiteralType {
845    pub(crate) fn exactly_eq(&self, other: &Self) -> bool {
846        match self {
847            ExtendedNumberLiteralType::Std(n) => {
848                if let ExtendedNumberLiteralType::Std(other_n) = other {
849                    match n {
850                        NumberLiteralType::IntegerLiteral(i) => {
851                            matches!(other_n, NumberLiteralType::IntegerLiteral(other_i) if i == other_i)
852                        }
853                        NumberLiteralType::FloatLiteral(f) => {
854                            matches!(other_n, NumberLiteralType::FloatLiteral(other_f) if f == other_f)
855                        }
856                    }
857                } else {
858                    false
859                }
860            }
861            ExtendedNumberLiteralType::Infinity => matches!(other, ExtendedNumberLiteralType::Infinity),
862            ExtendedNumberLiteralType::NegativeInfinity => matches!(other, ExtendedNumberLiteralType::NegativeInfinity),
863        }
864    }
865}
866
867#[derive(Debug)]
868pub struct ProgramData {
869    pub meta: Meta,
870    pub body: Vec<StatementType>,
871}
872
873impl HasMeta for ProgramData {
874    fn get_meta(&self) -> &Meta {
875        &self.meta
876    }
877
878    fn to_formatted_string(&self, script: &str) -> String {
879        format_struct("ProgramData")
880            .add_fields("meta", self.meta.to_formatted_string(script))
881            .add_fields(
882                "body",
883                format_vec(&self.body, |p| p.to_formatted_string(script)),
884            )
885            .to_string()
886    }
887}
888
889#[derive(Debug)]
890pub struct BlockStatementData {
891    pub meta: Meta,
892    pub body: Vec<StatementType>,
893}
894impl HasMeta for BlockStatementData {
895    fn get_meta(&self) -> &Meta {
896        &self.meta
897    }
898
899    fn to_formatted_string(&self, script: &str) -> String {
900        format_struct("BlockStatementData")
901            .add_fields("meta", self.meta.to_formatted_string(script))
902            .add_fields(
903                "body",
904                format_vec(&self.body, |p| p.to_formatted_string(script)),
905            )
906            .to_string()
907    }
908}
909
910#[derive(Debug)]
911pub enum StatementType {
912    ExpressionStatement {
913        meta: Meta,
914        expression: Box<ExpressionType>,
915    },
916    BlockStatement(BlockStatementData),
917    FunctionBody(FunctionBodyData),
918    EmptyStatement {
919        meta: Meta,
920    },
921    DebuggerStatement {
922        meta: Meta,
923    },
924    ReturnStatement {
925        meta: Meta,
926        argument: Option<Box<ExpressionType>>,
927    },
928    //Label Statement not supported, hence break & continue with labels not supported
929    BreakStatement {
930        meta: Meta,
931    },
932    ContinueStatement {
933        meta: Meta,
934    },
935    IfStatement {
936        meta: Meta,
937        test: Box<ExpressionType>,
938        consequent: Box<StatementType>,
939        alternate: Option<Box<StatementType>>,
940    },
941    SwitchStatement {
942        meta: Meta,
943        discriminant: Box<ExpressionType>,
944        cases: Vec<SwitchCaseData>,
945    },
946    ThrowStatement {
947        meta: Meta,
948        argument: Box<ExpressionType>,
949    },
950    TryStatement {
951        meta: Meta,
952        block: BlockStatementData,
953        handler: Option<CatchClauseData>,
954        finalizer: Option<BlockStatementData>,
955    },
956    WhileStatement {
957        meta: Meta,
958        test: Box<ExpressionType>,
959        body: Box<StatementType>,
960    },
961    DoWhileStatement {
962        meta: Meta,
963        test: Box<ExpressionType>,
964        body: Box<StatementType>,
965    },
966    ForStatement {
967        meta: Meta,
968        init: Option<VariableDeclarationOrExpression>,
969        test: Option<Box<ExpressionType>>,
970        update: Option<Box<ExpressionType>>,
971        body: Box<StatementType>,
972    },
973    ForInStatement(ForIteratorData),
974    ForOfStatement(ForIteratorData),
975    DeclarationStatement(DeclarationType),
976}
977
978impl HasMeta for StatementType {
979    fn get_meta(&self) -> &Meta {
980        match self {
981            StatementType::ExpressionStatement { meta, .. } => &meta,
982            StatementType::BlockStatement(data) => &data.meta,
983            StatementType::FunctionBody(data) => data.get_meta(),
984            StatementType::EmptyStatement { meta, .. } => &meta,
985            StatementType::DebuggerStatement { meta, .. } => &meta,
986            StatementType::ReturnStatement { meta, .. } => &meta,
987            StatementType::BreakStatement { meta, .. } => &meta,
988            StatementType::ContinueStatement { meta, .. } => &meta,
989            StatementType::IfStatement { meta, .. } => &meta,
990            StatementType::SwitchStatement { meta, .. } => &meta,
991            StatementType::ThrowStatement { meta, .. } => &meta,
992            StatementType::TryStatement { meta, .. } => &meta,
993            StatementType::WhileStatement { meta, .. } => &meta,
994            StatementType::DoWhileStatement { meta, .. } => &meta,
995            StatementType::ForStatement { meta, .. } => &meta,
996            StatementType::ForInStatement(data) => data.get_meta(),
997            StatementType::ForOfStatement(data) => data.get_meta(),
998            StatementType::DeclarationStatement(data) => data.get_meta(),
999        }
1000    }
1001
1002    fn to_formatted_string(&self, script: &str) -> String {
1003        match self {
1004            StatementType::ExpressionStatement { meta, expression } => {
1005                format_struct("StatementType::ExpressionStatement")
1006                    .add_fields("meta", meta.to_formatted_string(script))
1007                    .add_fields("expression", expression.to_formatted_string(script))
1008                    .to_string()
1009            }
1010            StatementType::BlockStatement(data) => format!(
1011                "StatementType::BlockStatement({})",
1012                data.to_formatted_string(script)
1013            ),
1014            StatementType::FunctionBody(data) => format!(
1015                "StatementType::FunctionBody({})",
1016                data.to_formatted_string(script)
1017            ),
1018            StatementType::EmptyStatement { meta } => {
1019                format_struct("StatementType::EmptyStatement")
1020                    .add_fields("meta", meta.to_formatted_string(script))
1021                    .to_string()
1022            }
1023            StatementType::DebuggerStatement { meta } => {
1024                format_struct("StatementType::DebuggerStatement")
1025                    .add_fields("meta", meta.to_formatted_string(script))
1026                    .to_string()
1027            }
1028            StatementType::ReturnStatement { meta, argument } => {
1029                format_struct("StatementType::ReturnStatement")
1030                    .add_fields("meta", meta.to_formatted_string(script))
1031                    .add_fields(
1032                        "argument",
1033                        format_option(argument, |o| o.to_formatted_string(script)),
1034                    )
1035                    .to_string()
1036            }
1037            StatementType::BreakStatement { meta } => {
1038                format_struct("StatementType::BreakStatement")
1039                    .add_fields("meta", meta.to_formatted_string(script))
1040                    .to_string()
1041            }
1042            StatementType::ContinueStatement { meta } => {
1043                format_struct("StatementType::ContinueStatement")
1044                    .add_fields("meta", meta.to_formatted_string(script))
1045                    .to_string()
1046            }
1047            StatementType::IfStatement {
1048                meta,
1049                test,
1050                consequent,
1051                alternate,
1052            } => format_struct("StatementType::IfStatement")
1053                .add_fields("meta", meta.to_formatted_string(script))
1054                .add_fields("test", test.to_formatted_string(script))
1055                .add_fields("consequent", consequent.to_formatted_string(script))
1056                .add_fields(
1057                    "alternate",
1058                    format_option(alternate, |o| o.to_formatted_string(script)),
1059                )
1060                .to_string(),
1061            StatementType::SwitchStatement {
1062                meta,
1063                discriminant,
1064                cases,
1065            } => format_struct("StatementType::SwitchStatement")
1066                .add_fields("meta", meta.to_formatted_string(script))
1067                .add_fields("discriminant", discriminant.to_formatted_string(script))
1068                .add_fields(
1069                    "cases",
1070                    format_vec(cases, |p| p.to_formatted_string(script)),
1071                )
1072                .to_string(),
1073            StatementType::ThrowStatement { meta, argument } => {
1074                format_struct("StatementType::ThrowStatement")
1075                    .add_fields("meta", meta.to_formatted_string(script))
1076                    .add_fields("argument", argument.to_formatted_string(script))
1077                    .to_string()
1078            }
1079            StatementType::TryStatement {
1080                meta,
1081                block,
1082                handler,
1083                finalizer,
1084            } => format_struct("StatementType::TryStatement")
1085                .add_fields("meta", meta.to_formatted_string(script))
1086                .add_fields("block", block.to_formatted_string(script))
1087                .add_fields(
1088                    "handler",
1089                    format_option(handler, |o| o.to_formatted_string(script)),
1090                )
1091                .add_fields(
1092                    "finalizer",
1093                    format_option(finalizer, |o| o.to_formatted_string(script)),
1094                )
1095                .to_string(),
1096            StatementType::WhileStatement { meta, test, body } => {
1097                format_struct("StatementType::WhileStatement")
1098                    .add_fields("meta", meta.to_formatted_string(script))
1099                    .add_fields("test", test.to_formatted_string(script))
1100                    .add_fields("body", body.to_formatted_string(script))
1101                    .to_string()
1102            }
1103            StatementType::DoWhileStatement { meta, test, body } => {
1104                format_struct("StatementType::DoWhileStatement")
1105                    .add_fields("meta", meta.to_formatted_string(script))
1106                    .add_fields("test", test.to_formatted_string(script))
1107                    .add_fields("body", body.to_formatted_string(script))
1108                    .to_string()
1109            }
1110            StatementType::ForStatement {
1111                meta,
1112                init,
1113                test,
1114                update,
1115                body,
1116            } => format_struct("StatementType::ForStatement")
1117                .add_fields("meta", meta.to_formatted_string(script))
1118                .add_fields(
1119                    "init",
1120                    format_option(init, |o| o.to_formatted_string(script)),
1121                )
1122                .add_fields(
1123                    "test",
1124                    format_option(test, |o| o.to_formatted_string(script)),
1125                )
1126                .add_fields(
1127                    "update",
1128                    format_option(update, |o| o.to_formatted_string(script)),
1129                )
1130                .add_fields("body", body.to_formatted_string(script))
1131                .to_string(),
1132            StatementType::ForInStatement(data) => format!(
1133                "StatementType::ForInStatement({})",
1134                data.to_formatted_string(script)
1135            ),
1136            StatementType::ForOfStatement(data) => format!(
1137                "StatementType::ForOfStatement({})",
1138                data.to_formatted_string(script)
1139            ),
1140            StatementType::DeclarationStatement(data) => format!(
1141                "StatementType::DeclarationStatement({})",
1142                data.to_formatted_string(script)
1143            ),
1144        }
1145    }
1146}
1147
1148#[derive(Debug)]
1149pub struct FunctionBodyData {
1150    pub meta: Meta,
1151    pub body: Vec<StatementType>, /*Actual code was -- Rc<Vec<DirectiveOrStatement>> -- We do not support directives, like 'use strict'*/
1152}
1153
1154impl HasMeta for FunctionBodyData {
1155    fn get_meta(&self) -> &Meta {
1156        &self.meta
1157    }
1158
1159    fn to_formatted_string(&self, script: &str) -> String {
1160        format_struct("FunctionBodyData")
1161            .add_fields("meta", self.meta.to_formatted_string(script))
1162            .add_fields(
1163                "body",
1164                format_vec(&self.body, |p| p.to_formatted_string(script)),
1165            )
1166            .to_string()
1167    }
1168}
1169
1170#[derive(Debug)]
1171pub struct ForIteratorData {
1172    pub meta: Meta,
1173    // As per ESTree spec (https://github.com/estree/estree/blob/master/es5.md#forinstatement) it
1174    // should be VariableDeclarationOrPattern. However, as per rules we left_hand_side_expression
1175    // which is an expression, which can be MemberExpression (which is also a Pattern).
1176    pub left: VariableDeclarationOrPattern,
1177    pub right: Box<ExpressionType>,
1178    pub body: Box<StatementType>,
1179}
1180
1181impl HasMeta for ForIteratorData {
1182    fn get_meta(&self) -> &Meta {
1183        &self.meta
1184    }
1185
1186    fn to_formatted_string(&self, script: &str) -> String {
1187        format_struct("ForIteratorData")
1188            .add_fields("meta", self.meta.to_formatted_string(script))
1189            .add_fields("left", self.left.to_formatted_string(script))
1190            .add_fields("right", self.right.to_formatted_string(script))
1191            .add_fields("body", self.body.to_formatted_string(script))
1192            .to_string()
1193    }
1194}
1195
1196#[derive(Debug)]
1197pub enum VariableDeclarationOrExpression {
1198    VariableDeclaration(VariableDeclarationData),
1199    Expression(Box<ExpressionType>),
1200}
1201
1202impl HasMeta for VariableDeclarationOrExpression {
1203    fn get_meta(&self) -> &Meta {
1204        match self {
1205            VariableDeclarationOrExpression::VariableDeclaration(d) => d.get_meta(),
1206            VariableDeclarationOrExpression::Expression(d) => d.get_meta(),
1207        }
1208    }
1209
1210    fn to_formatted_string(&self, script: &str) -> String {
1211        match self {
1212            VariableDeclarationOrExpression::VariableDeclaration(d) => format!(
1213                "VariableDeclarationOrExpression::VariableDeclaration({})",
1214                d.to_formatted_string(script)
1215            ),
1216            VariableDeclarationOrExpression::Expression(d) => format!(
1217                "VariableDeclarationOrExpression::Expression({})",
1218                d.to_formatted_string(script)
1219            ),
1220        }
1221    }
1222}
1223
1224#[derive(Debug)]
1225pub enum VariableDeclarationOrPattern {
1226    VariableDeclaration(VariableDeclarationData),
1227    Pattern(Box<PatternType>),
1228}
1229
1230impl HasMeta for VariableDeclarationOrPattern {
1231    fn get_meta(&self) -> &Meta {
1232        match self {
1233            VariableDeclarationOrPattern::VariableDeclaration(d) => d.get_meta(),
1234            VariableDeclarationOrPattern::Pattern(d) => d.get_meta(),
1235        }
1236    }
1237
1238    fn to_formatted_string(&self, script: &str) -> String {
1239        match self {
1240            VariableDeclarationOrPattern::VariableDeclaration(d) => format!(
1241                "VariableDeclarationOrPattern::VariableDeclaration({})",
1242                d.to_formatted_string(script)
1243            ),
1244            VariableDeclarationOrPattern::Pattern(d) => format!(
1245                "VariableDeclarationOrPattern::Pattern({})",
1246                d.to_formatted_string(script)
1247            ),
1248        }
1249    }
1250}
1251
1252#[derive(Debug)]
1253pub enum DeclarationType {
1254    FunctionOrGeneratorDeclaration(FunctionData), //id is mandatory here
1255    VariableDeclaration(VariableDeclarationData),
1256    ClassDeclaration(ClassData),
1257}
1258
1259impl HasMeta for DeclarationType {
1260    fn get_meta(&self) -> &Meta {
1261        match self {
1262            DeclarationType::FunctionOrGeneratorDeclaration(data) => data.get_meta(),
1263            DeclarationType::VariableDeclaration(data) => data.get_meta(),
1264            DeclarationType::ClassDeclaration(data) => data.get_meta(),
1265        }
1266    }
1267
1268    fn to_formatted_string(&self, script: &str) -> String {
1269        match self {
1270            DeclarationType::FunctionOrGeneratorDeclaration(data) => format!(
1271                "DeclarationType::FunctionDeclaration({})",
1272                data.to_formatted_string(script)
1273            ),
1274            DeclarationType::VariableDeclaration(data) => format!(
1275                "DeclarationType::VariableDeclaration({})",
1276                data.to_formatted_string(script)
1277            ),
1278            DeclarationType::ClassDeclaration(data) => format!(
1279                "DeclarationType::ClassDeclaration({})",
1280                data.to_formatted_string(script)
1281            ),
1282        }
1283    }
1284}
1285
1286#[derive(Debug)]
1287pub struct VariableDeclarationData {
1288    pub meta: Meta,
1289    pub declarations: Vec<VariableDeclaratorData>,
1290    pub kind: VariableDeclarationKind,
1291}
1292
1293impl HasMeta for VariableDeclarationData {
1294    fn get_meta(&self) -> &Meta {
1295        &self.meta
1296    }
1297
1298    fn to_formatted_string(&self, script: &str) -> String {
1299        format_struct("VariableDeclarationData")
1300            .add_fields("meta", self.meta.to_formatted_string(script))
1301            .add_fields(
1302                "declarations",
1303                format_vec(&self.declarations, |p| p.to_formatted_string(script)),
1304            )
1305            .add_fields("kind", format!("{:?}", self.kind))
1306            .to_string()
1307    }
1308}
1309
1310#[derive(Debug)]
1311pub enum VariableDeclarationKind {
1312    Var,
1313    Let,
1314    Const,
1315}
1316
1317#[derive(Debug)]
1318pub struct SwitchCaseData {
1319    pub meta: Meta,
1320    pub test: Option<Box<ExpressionType>>,
1321    pub consequent: Vec<StatementType>,
1322}
1323
1324impl HasMeta for SwitchCaseData {
1325    fn get_meta(&self) -> &Meta {
1326        &self.meta
1327    }
1328
1329    fn to_formatted_string(&self, script: &str) -> String {
1330        format_struct("SwitchCaseData")
1331            .add_fields("meta", self.meta.to_formatted_string(script))
1332            .add_fields(
1333                "test",
1334                format_option(&self.test, |o| o.to_formatted_string(script)),
1335            )
1336            .add_fields(
1337                "consequent",
1338                format_vec(&self.consequent, |p| p.to_formatted_string(script)),
1339            )
1340            .to_string()
1341    }
1342}
1343
1344#[derive(Debug)]
1345pub struct FormalParameters {
1346    pub list: Vec<PatternType>,
1347    pub is_simple_parameter_list: bool,
1348}
1349
1350impl FormalParameters {
1351    pub fn new(params: Vec<PatternType>) -> Self {
1352        let is_simple = params.iter().all(|p| {
1353            matches!(
1354                p,
1355                PatternType::PatternWhichCanBeExpression(ExpressionPatternType::Identifier(_))
1356            )
1357        });
1358        FormalParameters {
1359            list: params,
1360            is_simple_parameter_list: is_simple,
1361        }
1362    }
1363}
1364
1365#[derive(Debug)]
1366pub struct FunctionData {
1367    pub meta: Meta,
1368    pub id: Option<IdentifierData>,
1369    pub params: FormalParameters,
1370    pub body: Box<FunctionBodyData>,
1371    pub generator: bool,
1372}
1373
1374impl HasMeta for FunctionData {
1375    fn get_meta(&self) -> &Meta {
1376        &self.meta
1377    }
1378
1379    fn to_formatted_string(&self, script: &str) -> String {
1380        format_struct("FunctionData")
1381            .add_fields("meta", self.meta.to_formatted_string(script))
1382            .add_fields(
1383                "id",
1384                format_option(&self.id, |o| o.to_formatted_string(script)),
1385            )
1386            .add_fields(
1387                "params",
1388                format_vec(&self.params.list, |p| p.to_formatted_string(script)),
1389            )
1390            .add_fields("body", self.body.to_formatted_string(script))
1391            .add_fields("generator", self.generator.to_string())
1392            .to_string()
1393    }
1394}
1395
1396#[derive(Debug)]
1397pub struct CatchClauseData {
1398    pub meta: Meta,
1399    pub param: Box<PatternType>,
1400    pub body: BlockStatementData,
1401}
1402
1403impl HasMeta for CatchClauseData {
1404    fn get_meta(&self) -> &Meta {
1405        &self.meta
1406    }
1407
1408    fn to_formatted_string(&self, script: &str) -> String {
1409        format_struct("CatchClauseData")
1410            .add_fields("meta", self.meta.to_formatted_string(script))
1411            .add_fields("param", self.param.to_formatted_string(script))
1412            .add_fields("body", self.body.to_formatted_string(script))
1413            .to_string()
1414    }
1415}
1416
1417#[derive(Debug)]
1418pub struct VariableDeclaratorData {
1419    pub meta: Meta,
1420    pub id: Box<PatternType>,
1421    pub init: Option<Box<ExpressionType>>,
1422}
1423
1424impl HasMeta for VariableDeclaratorData {
1425    fn get_meta(&self) -> &Meta {
1426        &self.meta
1427    }
1428
1429    fn to_formatted_string(&self, script: &str) -> String {
1430        format_struct("VariableDeclaratorData")
1431            .add_fields("meta", self.meta.to_formatted_string(script))
1432            .add_fields("id", self.id.to_formatted_string(script))
1433            .add_fields(
1434                "init",
1435                format_option(&self.init, |o| o.to_formatted_string(script)),
1436            )
1437            .to_string()
1438    }
1439}
1440
1441#[derive(Debug)]
1442pub struct PropertyData<V> {
1443    pub meta: Meta,
1444    pub key: Box<ExpressionType>,
1445    pub value: V,
1446    pub kind: PropertyKind,
1447    pub method: bool,
1448    pub shorthand: bool,
1449    pub computed: bool,
1450}
1451impl<V> PropertyData<V> {
1452    pub(crate) fn new_with_identifier_key(
1453        meta: Meta,
1454        key: IdentifierData,
1455        value: V,
1456        kind: PropertyKind,
1457        method: bool,
1458        shorthand: bool,
1459    ) -> Self {
1460        PropertyData {
1461            meta,
1462            key: Box::new(ExpressionPatternType::Identifier(key).convert_to_expression()),
1463            value,
1464            kind,
1465            method,
1466            shorthand,
1467            computed: false,
1468        }
1469    }
1470
1471    pub(crate) fn new_with_literal_key(
1472        meta: Meta,
1473        key: LiteralData,
1474        value: V,
1475        kind: PropertyKind,
1476        method: bool,
1477    ) -> Self {
1478        PropertyData {
1479            meta,
1480            key: Box::new(ExpressionType::Literal(key)),
1481            value,
1482            kind,
1483            method,
1484            shorthand: false,
1485            computed: false,
1486        }
1487    }
1488
1489    pub(crate) fn new_with_computed_key(
1490        meta: Meta,
1491        key: ExpressionType,
1492        value: V,
1493        kind: PropertyKind,
1494        method: bool,
1495    ) -> Self {
1496        PropertyData {
1497            meta,
1498            key: Box::new(key),
1499            value,
1500            kind,
1501            method,
1502            shorthand: false,
1503            computed: true,
1504        }
1505    }
1506
1507    pub(crate) fn new_with_any_expression_key(
1508        meta: Meta,
1509        key: ExpressionType,
1510        value: V,
1511        kind: PropertyKind,
1512        method: bool,
1513        shorthand: bool,
1514    ) -> Self {
1515        match key {
1516            ExpressionType::ExpressionWhichCanBePattern(e) => match e {
1517                ExpressionPatternType::Identifier(id) => {
1518                    Self::new_with_identifier_key(meta, id, value, kind, method, shorthand)
1519                }
1520            },
1521            ExpressionType::Literal(l) => Self::new_with_literal_key(meta, l, value, kind, method),
1522            ExpressionType::MemberExpression(_) => {
1523                Self::new_with_computed_key(meta, key, value, kind, method)
1524            }
1525            _ => Self::new_with_computed_key(meta, key, value, kind, method),
1526        }
1527    }
1528}
1529impl HasMeta for PropertyData<Box<ExpressionType>> {
1530    fn get_meta(&self) -> &Meta {
1531        &self.meta
1532    }
1533
1534    fn to_formatted_string(&self, script: &str) -> String {
1535        format_struct("PropertyData<for Expression>")
1536            .add_fields("meta", self.meta.to_formatted_string(script))
1537            .add_fields("key", self.key.to_formatted_string(script))
1538            .add_fields("kind", format!("{:?}", self.kind))
1539            .add_fields("method", self.method.to_string())
1540            .add_fields("value", self.value.to_formatted_string(script))
1541            .to_string()
1542    }
1543}
1544impl HasMeta for PropertyData<Box<PatternType>> {
1545    fn get_meta(&self) -> &Meta {
1546        &self.meta
1547    }
1548
1549    fn to_formatted_string(&self, script: &str) -> String {
1550        format_struct("PropertyData<for Pattern>")
1551            .add_fields("meta", self.meta.to_formatted_string(script))
1552            .add_fields("key", self.key.to_formatted_string(script))
1553            .add_fields("kind", format!("{:?}", self.kind))
1554            .add_fields("method", self.method.to_string())
1555            .add_fields("value", self.value.to_formatted_string(script))
1556            .to_string()
1557    }
1558}
1559
1560#[derive(Debug)]
1561pub struct AssignmentPropertyData(pub PropertyData<Box<PatternType>>);
1562impl AssignmentPropertyData {
1563    pub(crate) fn new_with_identifier_key(
1564        meta: Meta,
1565        key: IdentifierData,
1566        value: PatternType,
1567        shorthand: bool,
1568    ) -> Self {
1569        AssignmentPropertyData(PropertyData::new_with_identifier_key(
1570            meta,
1571            key,
1572            Box::new(value),
1573            PropertyKind::Init,
1574            false,
1575            shorthand,
1576        ))
1577    }
1578
1579    pub(crate) fn new_with_any_expression_key(
1580        meta: Meta,
1581        key: ExpressionType,
1582        value: PatternType,
1583        shorthand: bool,
1584    ) -> Self {
1585        AssignmentPropertyData(PropertyData::new_with_any_expression_key(
1586            meta,
1587            key,
1588            Box::new(value),
1589            PropertyKind::Init,
1590            false,
1591            shorthand,
1592        ))
1593    }
1594}
1595impl HasMeta for AssignmentPropertyData {
1596    fn get_meta(&self) -> &Meta {
1597        &self.0.meta
1598    }
1599
1600    fn to_formatted_string(&self, script: &str) -> String {
1601        format!(
1602            "AssignmentPropertyData({})",
1603            self.0.to_formatted_string(script)
1604        )
1605    }
1606}
1607
1608#[derive(Debug)]
1609pub enum PropertyKind {
1610    Init,
1611    Get,
1612    Set,
1613}
1614
1615#[derive(Debug)]
1616pub struct ClassData {
1617    pub meta: Meta,
1618    pub id: Option<IdentifierData>,
1619    pub super_class: Option<Box<ExpressionType>>,
1620    pub body: ClassBodyData,
1621}
1622impl HasMeta for ClassData {
1623    fn get_meta(&self) -> &Meta {
1624        &self.meta
1625    }
1626
1627    fn to_formatted_string(&self, script: &str) -> String {
1628        format_struct("ClassData")
1629            .add_fields("meta", self.meta.to_formatted_string(script))
1630            .add_fields("id", format_has_meta_option(&self.id, script))
1631            .add_fields(
1632                "super_class",
1633                format_option(&self.super_class, |o| o.to_formatted_string(script)),
1634            )
1635            .add_fields("body", self.body.to_formatted_string(script))
1636            .to_string()
1637    }
1638}
1639
1640#[derive(Debug)]
1641pub struct ClassBodyData {
1642    pub meta: Meta,
1643    pub body: Vec<MethodDefinitionData>,
1644}
1645impl HasMeta for ClassBodyData {
1646    fn get_meta(&self) -> &Meta {
1647        &self.meta
1648    }
1649
1650    fn to_formatted_string(&self, script: &str) -> String {
1651        format_struct("ClassBodyData")
1652            .add_fields("meta", self.meta.to_formatted_string(script))
1653            .add_fields(
1654                "body",
1655                format_vec(&self.body, |p| p.to_formatted_string(script)),
1656            )
1657            .to_string()
1658    }
1659}
1660
1661#[derive(Debug)]
1662pub struct MethodDefinitionData {
1663    pub meta: Meta,
1664    pub key: Box<ExpressionType>,
1665    pub value: FunctionData,
1666    pub kind: MethodDefinitionKind,
1667    pub computed: bool,
1668    pub static_flag: bool,
1669}
1670
1671impl HasMeta for MethodDefinitionData {
1672    fn get_meta(&self) -> &Meta {
1673        &self.meta
1674    }
1675
1676    fn to_formatted_string(&self, script: &str) -> String {
1677        format_struct("MethodDefinitionData")
1678            .add_fields("meta", self.meta.to_formatted_string(script))
1679            .add_fields("key", self.key.to_formatted_string(script))
1680            .add_fields("value", self.value.to_formatted_string(script))
1681            .add_fields("kind", format!("{:?}", self.kind))
1682            .add_fields("computed", self.computed.to_string())
1683            .add_fields("static_flag", self.static_flag.to_string())
1684            .to_string()
1685    }
1686}
1687
1688#[derive(Debug)]
1689pub enum MethodDefinitionKind {
1690    Constructor,
1691    Method,
1692    Get,
1693    Set,
1694}