use crate::syntax::ast::node::{Block, Declaration, Node};
use boa_interner::{Interner, ToInternedString};
#[cfg(feature = "deser")]
use serde::{Deserialize, Serialize};
#[cfg(test)]
mod tests;
#[cfg_attr(feature = "deser", derive(Serialize, Deserialize))]
#[derive(Clone, Debug, PartialEq)]
pub struct Try {
block: Block,
catch: Option<Catch>,
finally: Option<Finally>,
}
impl Try {
pub(in crate::syntax) fn new<B>(
block: B,
catch: Option<Catch>,
finally: Option<Finally>,
) -> Self
where
B: Into<Block>,
{
assert!(
catch.is_some() || finally.is_some(),
"one of catch or finally must be pressent"
);
Self {
block: block.into(),
catch,
finally,
}
}
pub fn block(&self) -> &Block {
&self.block
}
pub fn catch(&self) -> Option<&Catch> {
self.catch.as_ref()
}
pub fn finally(&self) -> Option<&Block> {
self.finally.as_ref().map(Finally::block)
}
pub(in crate::syntax::ast::node) fn to_indented_string(
&self,
interner: &Interner,
indentation: usize,
) -> String {
let mut buf = format!(
"{}try {}",
" ".repeat(indentation),
self.block.to_indented_string(interner, indentation)
);
if let Some(ref catch) = self.catch {
buf.push_str(&catch.to_indented_string(interner, indentation));
}
if let Some(ref finally) = self.finally {
buf.push_str(&finally.to_indented_string(interner, indentation));
}
buf
}
}
impl ToInternedString for Try {
fn to_interned_string(&self, interner: &Interner) -> String {
self.to_indented_string(interner, 0)
}
}
impl From<Try> for Node {
fn from(try_catch: Try) -> Self {
Self::Try(Box::new(try_catch))
}
}
#[cfg_attr(feature = "deser", derive(Serialize, Deserialize))]
#[derive(Clone, Debug, PartialEq)]
pub struct Catch {
parameter: Option<Box<Declaration>>,
block: Block,
}
impl Catch {
pub(in crate::syntax) fn new<OD, D, B>(parameter: OD, block: B) -> Self
where
OD: Into<Option<D>>,
D: Into<Declaration>,
B: Into<Block>,
{
Self {
parameter: parameter.into().map(|d| Box::new(d.into())),
block: block.into(),
}
}
pub fn parameter(&self) -> Option<&Declaration> {
self.parameter.as_deref()
}
pub fn block(&self) -> &Block {
&self.block
}
pub(super) fn to_indented_string(&self, interner: &Interner, indentation: usize) -> String {
let mut buf = " catch".to_owned();
if let Some(ref param) = self.parameter {
buf.push_str(&format!("({})", param.to_interned_string(interner)));
}
buf.push_str(&format!(
" {}",
self.block.to_indented_string(interner, indentation)
));
buf
}
}
impl ToInternedString for Catch {
fn to_interned_string(&self, interner: &Interner) -> String {
self.to_indented_string(interner, 0)
}
}
#[cfg_attr(feature = "deser", derive(Serialize, Deserialize))]
#[derive(Clone, Debug, PartialEq)]
pub struct Finally {
block: Block,
}
impl Finally {
pub fn block(&self) -> &Block {
&self.block
}
pub(super) fn to_indented_string(&self, interner: &Interner, indentation: usize) -> String {
format!(
" finally {}",
self.block.to_indented_string(interner, indentation)
)
}
}
impl<T> From<T> for Finally
where
T: Into<Block>,
{
fn from(block: T) -> Self {
Self {
block: block.into(),
}
}
}