use oxc_allocator::ArenaVec;
use oxc_ast::ast::{BlockStatement, IfStatement, Statement, TryStatement};
pub trait IsTerminated {
fn is_terminated(&self) -> bool;
}
impl IsTerminated for Statement<'_> {
fn is_terminated(&self) -> bool {
match self {
Statement::IfStatement(stmt) => stmt.is_terminated(),
Statement::BlockStatement(stmt) => stmt.is_terminated(),
Statement::TryStatement(stmt) => stmt.is_terminated(),
_ => self.is_jump_statement(),
}
}
}
impl IsTerminated for IfStatement<'_> {
fn is_terminated(&self) -> bool {
self.consequent.is_terminated() && self.alternate.is_terminated()
}
}
impl IsTerminated for TryStatement<'_> {
fn is_terminated(&self) -> bool {
self.finalizer.as_ref().is_some_and(|f| f.is_terminated())
|| (self.block.is_terminated()
&& self.handler.as_ref().is_none_or(|h| h.body.is_terminated()))
}
}
impl IsTerminated for BlockStatement<'_> {
fn is_terminated(&self) -> bool {
self.body.is_terminated()
}
}
impl IsTerminated for ArenaVec<'_, Statement<'_>> {
fn is_terminated(&self) -> bool {
self.iter()
.rev()
.find(|stmt| match stmt {
Statement::FunctionDeclaration(_) => false,
Statement::VariableDeclaration(decl) => {
!(decl.kind.is_var() && decl.declarations.iter().all(|d| d.init.is_none()))
}
_ => true,
})
.is_some_and(Statement::is_terminated)
}
}
impl<T: IsTerminated> IsTerminated for Option<T> {
fn is_terminated(&self) -> bool {
self.as_ref().is_some_and(IsTerminated::is_terminated)
}
}