use crate::syntax::ast::node::{Declaration, Node};
use boa_interner::{Interner, Sym, ToInternedString};
use rustc_hash::FxHashSet;
#[cfg(feature = "deser")]
use serde::{Deserialize, Serialize};
#[cfg(test)]
mod tests;
#[cfg_attr(feature = "deser", derive(Serialize, Deserialize))]
#[derive(Clone, Debug, Default, PartialEq)]
pub struct StatementList {
items: Box<[Node]>,
strict: bool,
}
impl StatementList {
#[inline]
pub fn items(&self) -> &[Node] {
&self.items
}
#[inline]
pub fn strict(&self) -> bool {
self.strict
}
#[inline]
pub fn set_strict(&mut self, strict: bool) {
self.strict = strict;
}
pub(in crate::syntax::ast::node) fn to_indented_string(
&self,
interner: &Interner,
indentation: usize,
) -> String {
let mut buf = String::new();
for node in self.items.iter() {
buf.push_str(&node.to_indented_string(interner, indentation));
match node {
Node::Block(_) | Node::If(_) | Node::Switch(_) | Node::WhileLoop(_) => {}
_ => buf.push(';'),
}
buf.push('\n');
}
buf
}
pub(crate) fn lexically_declared_names(&self) -> Vec<(Sym, bool)> {
let mut names = Vec::new();
for node in self.items() {
match node {
Node::FunctionDecl(decl) => {
names.push((decl.name(), true));
}
Node::GeneratorDecl(decl) => {
names.push((decl.name(), false));
}
Node::AsyncFunctionDecl(decl) => {
names.push((decl.name(), false));
}
Node::AsyncGeneratorDecl(decl) => {
names.push((decl.name(), false));
}
Node::ClassDecl(decl) => {
names.push((decl.name(), false));
}
Node::LetDeclList(decl_list) | Node::ConstDeclList(decl_list) => match decl_list {
super::DeclarationList::Const(declarations)
| super::DeclarationList::Let(declarations) => {
for decl in declarations.iter() {
match decl {
Declaration::Identifier { ident, .. } => {
names.push((ident.sym(), false));
}
Declaration::Pattern(pattern) => {
names.extend(
pattern.idents().into_iter().map(|name| (name, false)),
);
}
}
}
}
super::DeclarationList::Var(_) => unreachable!(),
},
_ => {}
}
}
names
}
pub(crate) fn lexically_declared_names_top_level(&self) -> Vec<Sym> {
let mut names = Vec::new();
for node in self.items() {
match node {
Node::ClassDecl(decl) => {
names.push(decl.name());
}
Node::LetDeclList(decl_list) | Node::ConstDeclList(decl_list) => match decl_list {
super::DeclarationList::Const(declarations)
| super::DeclarationList::Let(declarations) => {
for decl in declarations.iter() {
match decl {
Declaration::Identifier { ident, .. } => {
names.push(ident.sym());
}
Declaration::Pattern(pattern) => {
names.extend(pattern.idents());
}
}
}
}
super::DeclarationList::Var(_) => unreachable!(),
},
_ => {}
}
}
names
}
pub(crate) fn var_declared_names_new(&self, vars: &mut FxHashSet<Sym>) {
for node in self.items() {
node.var_declared_names(vars);
}
}
}
impl<T> From<T> for StatementList
where
T: Into<Box<[Node]>>,
{
fn from(stm: T) -> Self {
Self {
items: stm.into(),
strict: false,
}
}
}
impl ToInternedString for StatementList {
fn to_interned_string(&self, interner: &Interner) -> String {
self.to_indented_string(interner, 0)
}
}