Skip to main content

boa_ast/declaration/
mod.rs

1//! The [`Declaration`] Parse Node, as defined by the [spec].
2//!
3//! ECMAScript declarations include:
4//! - [Lexical][lex] declarations (`let`, `const`).
5//! - [Function][fun] declarations (`function`, `async function`).
6//! - [Class][class] declarations.
7//!
8//! See [*Difference between statements and declarations*][diff] for an explanation on why `Declaration`s
9//! and `Statement`s are distinct nodes.
10//!
11//! [spec]: https://tc39.es/ecma262/#prod-Declaration
12//! [lex]: https://tc39.es/ecma262/#prod-LexicalDeclaration
13//! [fun]: https://tc39.es/ecma262/#prod-HoistableDeclaration
14//! [class]: https://tc39.es/ecma262/#prod-ClassDeclaration
15//! [diff]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements#difference_between_statements_and_declarations
16
17use super::function::{
18    AsyncFunctionDeclaration, AsyncGeneratorDeclaration, FunctionDeclaration, GeneratorDeclaration,
19};
20use crate::{
21    function::ClassDeclaration,
22    visitor::{VisitWith, Visitor, VisitorMut},
23};
24use boa_interner::{Interner, Sym, ToIndentedString, ToInternedString};
25use core::ops::ControlFlow;
26
27mod export;
28mod import;
29mod variable;
30
31pub use export::*;
32pub use import::*;
33pub use variable::*;
34
35/// The `Declaration` Parse Node.
36///
37/// See the [module level documentation][self] for more information.
38#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
39#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
40#[derive(Clone, Debug, PartialEq)]
41pub enum Declaration {
42    /// See [`FunctionDeclaration`]
43    FunctionDeclaration(FunctionDeclaration),
44
45    /// See [`GeneratorDeclaration`]
46    GeneratorDeclaration(GeneratorDeclaration),
47
48    /// See [`AsyncFunctionDeclaration`]
49    AsyncFunctionDeclaration(AsyncFunctionDeclaration),
50
51    /// See [`AsyncGeneratorDeclaration`]
52    AsyncGeneratorDeclaration(AsyncGeneratorDeclaration),
53
54    /// See [`ClassDeclaration`]
55    ClassDeclaration(Box<ClassDeclaration>),
56
57    /// See [`LexicalDeclaration`]
58    Lexical(LexicalDeclaration),
59}
60
61impl ToIndentedString for Declaration {
62    fn to_indented_string(&self, interner: &Interner, indentation: usize) -> String {
63        match self {
64            Self::FunctionDeclaration(f) => f.to_indented_string(interner, indentation),
65            Self::GeneratorDeclaration(g) => g.to_indented_string(interner, indentation),
66            Self::AsyncFunctionDeclaration(af) => af.to_indented_string(interner, indentation),
67            Self::AsyncGeneratorDeclaration(ag) => ag.to_indented_string(interner, indentation),
68            Self::ClassDeclaration(c) => c.to_indented_string(interner, indentation),
69            Self::Lexical(l) => {
70                let mut s = l.to_interned_string(interner);
71                s.push(';');
72                s
73            }
74        }
75    }
76}
77
78impl VisitWith for Declaration {
79    fn visit_with<'a, V>(&'a self, visitor: &mut V) -> ControlFlow<V::BreakTy>
80    where
81        V: Visitor<'a>,
82    {
83        match self {
84            Self::FunctionDeclaration(f) => visitor.visit_function_declaration(f),
85            Self::GeneratorDeclaration(g) => visitor.visit_generator_declaration(g),
86            Self::AsyncFunctionDeclaration(af) => visitor.visit_async_function_declaration(af),
87            Self::AsyncGeneratorDeclaration(ag) => visitor.visit_async_generator_declaration(ag),
88            Self::ClassDeclaration(c) => visitor.visit_class_declaration(c),
89            Self::Lexical(ld) => visitor.visit_lexical_declaration(ld),
90        }
91    }
92
93    fn visit_with_mut<'a, V>(&'a mut self, visitor: &mut V) -> ControlFlow<V::BreakTy>
94    where
95        V: VisitorMut<'a>,
96    {
97        match self {
98            Self::FunctionDeclaration(f) => visitor.visit_function_declaration_mut(f),
99            Self::GeneratorDeclaration(g) => visitor.visit_generator_declaration_mut(g),
100            Self::AsyncFunctionDeclaration(af) => visitor.visit_async_function_declaration_mut(af),
101            Self::AsyncGeneratorDeclaration(ag) => {
102                visitor.visit_async_generator_declaration_mut(ag)
103            }
104            Self::ClassDeclaration(c) => visitor.visit_class_declaration_mut(c),
105            Self::Lexical(ld) => visitor.visit_lexical_declaration_mut(ld),
106        }
107    }
108}
109
110/// Module specifier.
111///
112/// This is equivalent to the [`ModuleSpecifier`] production.
113///
114/// [`FromClause`]: https://tc39.es/ecma262/#prod-ModuleSpecifier
115#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
116#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
117#[derive(Clone, Debug, Copy, PartialEq, Eq)]
118pub struct ModuleSpecifier {
119    module: Sym,
120}
121
122impl ModuleSpecifier {
123    /// Creates a `ModuleSpecifier` from a `Sym`.
124    #[must_use]
125    pub const fn new(module: Sym) -> Self {
126        Self { module }
127    }
128
129    /// Gets the inner `Sym` of the module specifier.
130    #[inline]
131    #[must_use]
132    pub const fn sym(self) -> Sym {
133        self.module
134    }
135}
136
137impl From<Sym> for ModuleSpecifier {
138    #[inline]
139    fn from(module: Sym) -> Self {
140        Self::new(module)
141    }
142}
143
144impl VisitWith for ModuleSpecifier {
145    fn visit_with<'a, V>(&'a self, visitor: &mut V) -> ControlFlow<V::BreakTy>
146    where
147        V: Visitor<'a>,
148    {
149        visitor.visit_sym(&self.module)
150    }
151
152    fn visit_with_mut<'a, V>(&'a mut self, visitor: &mut V) -> ControlFlow<V::BreakTy>
153    where
154        V: VisitorMut<'a>,
155    {
156        visitor.visit_sym_mut(&mut self.module)
157    }
158}
159
160/// An import attribute entry in an [`ImportDeclaration`].
161///
162/// This is a key-value pair, where the key is an identifier or string literal,
163/// and the value is a string literal.
164///
165/// More information:
166///  - [ECMAScript specification][spec]
167///
168/// [spec]: https://tc39.es/ecma262/#sec-imports
169#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
170#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
171#[derive(Clone, Debug, Copy, PartialEq, Eq)]
172pub struct ImportAttribute {
173    key: Sym,
174    value: Sym,
175}
176
177impl ImportAttribute {
178    /// Creates a new `ImportAttribute`.
179    #[inline]
180    #[must_use]
181    pub const fn new(key: Sym, value: Sym) -> Self {
182        Self { key, value }
183    }
184
185    /// Gets the attribute key.
186    #[inline]
187    #[must_use]
188    pub const fn key(self) -> Sym {
189        self.key
190    }
191
192    /// Gets the attribute value.
193    #[inline]
194    #[must_use]
195    pub const fn value(self) -> Sym {
196        self.value
197    }
198}
199
200impl VisitWith for ImportAttribute {
201    fn visit_with<'a, V>(&'a self, visitor: &mut V) -> ControlFlow<V::BreakTy>
202    where
203        V: Visitor<'a>,
204    {
205        visitor.visit_sym(&self.key)?;
206        visitor.visit_sym(&self.value)
207    }
208
209    fn visit_with_mut<'a, V>(&'a mut self, visitor: &mut V) -> ControlFlow<V::BreakTy>
210    where
211        V: VisitorMut<'a>,
212    {
213        visitor.visit_sym_mut(&mut self.key)?;
214        visitor.visit_sym_mut(&mut self.value)
215    }
216}