#[cfg(feature = "serde")]
use serde::Serialize;
use crate::Span;
use super::{
ArenaVec, Attribute, ClassDecl, Comment, EnumDecl, Expr, FunctionDecl, Ident, InterfaceDecl,
Name, TraitDecl,
};
#[cfg(feature = "serde")]
fn is_false(b: &bool) -> bool {
!b
}
#[derive(Debug)]
#[cfg_attr(feature = "serde", derive(Serialize))]
pub struct Stmt<'arena, 'src> {
pub kind: StmtKind<'arena, 'src>,
pub span: Span,
#[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
pub doc_comment: Option<&'arena Comment<'src>>,
}
impl<'arena, 'src> Stmt<'arena, 'src> {
pub fn leading_doc_comment(&self) -> Option<&Comment<'src>> {
if let Some(doc) = self.doc_comment {
return Some(doc);
}
match &self.kind {
StmtKind::Function(f) => f.doc_comment.as_ref(),
StmtKind::Class(c) => c.doc_comment.as_ref(),
StmtKind::Interface(i) => i.doc_comment.as_ref(),
StmtKind::Trait(t) => t.doc_comment.as_ref(),
StmtKind::Enum(e) => e.doc_comment.as_ref(),
StmtKind::Const(items) => items.first().and_then(|i| i.doc_comment.as_ref()),
_ => None,
}
}
}
#[derive(Debug)]
#[cfg_attr(feature = "serde", derive(Serialize))]
#[cfg_attr(feature = "serde", serde(transparent))]
pub struct Block<'arena, 'src> {
pub stmts: ArenaVec<'arena, Stmt<'arena, 'src>>,
#[cfg_attr(feature = "serde", serde(skip))]
pub span: Span,
}
#[derive(Debug)]
#[cfg_attr(feature = "serde", derive(Serialize))]
#[non_exhaustive]
pub enum StmtKind<'arena, 'src> {
Expression(&'arena Expr<'arena, 'src>),
Echo(ArenaVec<'arena, Expr<'arena, 'src>>),
Return(Option<&'arena Expr<'arena, 'src>>),
Block(&'arena Block<'arena, 'src>),
If(&'arena IfStmt<'arena, 'src>),
While(&'arena WhileStmt<'arena, 'src>),
For(&'arena ForStmt<'arena, 'src>),
Foreach(&'arena ForeachStmt<'arena, 'src>),
DoWhile(&'arena DoWhileStmt<'arena, 'src>),
Function(&'arena FunctionDecl<'arena, 'src>),
Break(Option<&'arena Expr<'arena, 'src>>),
Continue(Option<&'arena Expr<'arena, 'src>>),
Switch(&'arena SwitchStmt<'arena, 'src>),
Goto(Ident<'src>),
Label(Ident<'src>),
Declare(&'arena DeclareStmt<'arena, 'src>),
Unset(ArenaVec<'arena, Expr<'arena, 'src>>),
Throw(&'arena Expr<'arena, 'src>),
TryCatch(&'arena TryCatchStmt<'arena, 'src>),
Global(ArenaVec<'arena, Expr<'arena, 'src>>),
Class(&'arena ClassDecl<'arena, 'src>),
Interface(&'arena InterfaceDecl<'arena, 'src>),
Trait(&'arena TraitDecl<'arena, 'src>),
Enum(&'arena EnumDecl<'arena, 'src>),
Namespace(&'arena NamespaceDecl<'arena, 'src>),
Use(&'arena UseDecl<'arena, 'src>),
Const(ArenaVec<'arena, ConstItem<'arena, 'src>>),
StaticVar(ArenaVec<'arena, StaticVar<'arena, 'src>>),
HaltCompiler(&'src str),
Nop,
InlineHtml(&'src str),
Error,
}
#[derive(Debug)]
#[cfg_attr(feature = "serde", derive(Serialize))]
#[non_exhaustive]
pub struct IfStmt<'arena, 'src> {
pub condition: Expr<'arena, 'src>,
pub then_branch: &'arena Stmt<'arena, 'src>,
pub elseif_branches: ArenaVec<'arena, ElseIfBranch<'arena, 'src>>,
pub else_branch: Option<&'arena Stmt<'arena, 'src>>,
#[cfg_attr(feature = "serde", serde(skip))]
#[doc(hidden)]
pub else_kw_span: Option<Span>,
#[cfg_attr(feature = "serde", serde(default, skip_serializing_if = "is_false"))]
pub uses_alternative: bool,
}
impl<'arena, 'src> IfStmt<'arena, 'src> {
pub fn new(
arena: &'arena bumpalo::Bump,
condition: Expr<'arena, 'src>,
then_branch: &'arena Stmt<'arena, 'src>,
) -> Self {
Self {
condition,
then_branch,
elseif_branches: ArenaVec::new_in(arena),
else_branch: None,
else_kw_span: None,
uses_alternative: false,
}
}
}
#[derive(Debug)]
#[cfg_attr(feature = "serde", derive(Serialize))]
pub struct ElseIfBranch<'arena, 'src> {
pub condition: Expr<'arena, 'src>,
pub body: Stmt<'arena, 'src>,
pub span: Span,
}
#[derive(Debug)]
#[cfg_attr(feature = "serde", derive(Serialize))]
#[non_exhaustive]
pub struct WhileStmt<'arena, 'src> {
pub condition: Expr<'arena, 'src>,
pub body: &'arena Stmt<'arena, 'src>,
#[cfg_attr(feature = "serde", serde(default, skip_serializing_if = "is_false"))]
pub uses_alternative: bool,
}
impl<'arena, 'src> WhileStmt<'arena, 'src> {
pub fn new(condition: Expr<'arena, 'src>, body: &'arena Stmt<'arena, 'src>) -> Self {
Self {
condition,
body,
uses_alternative: false,
}
}
}
#[derive(Debug)]
#[cfg_attr(feature = "serde", derive(Serialize))]
#[non_exhaustive]
pub struct ForStmt<'arena, 'src> {
pub init: ArenaVec<'arena, Expr<'arena, 'src>>,
pub condition: ArenaVec<'arena, Expr<'arena, 'src>>,
pub update: ArenaVec<'arena, Expr<'arena, 'src>>,
pub body: &'arena Stmt<'arena, 'src>,
#[cfg_attr(feature = "serde", serde(default, skip_serializing_if = "is_false"))]
pub uses_alternative: bool,
}
impl<'arena, 'src> ForStmt<'arena, 'src> {
pub fn new(arena: &'arena bumpalo::Bump, body: &'arena Stmt<'arena, 'src>) -> Self {
Self {
init: ArenaVec::new_in(arena),
condition: ArenaVec::new_in(arena),
update: ArenaVec::new_in(arena),
body,
uses_alternative: false,
}
}
}
#[derive(Debug)]
#[cfg_attr(feature = "serde", derive(Serialize))]
#[non_exhaustive]
pub struct ForeachStmt<'arena, 'src> {
pub expr: Expr<'arena, 'src>,
pub key: Option<Expr<'arena, 'src>>,
pub value: Expr<'arena, 'src>,
#[cfg_attr(feature = "serde", serde(default, skip_serializing_if = "is_false"))]
pub by_ref: bool,
#[cfg_attr(
feature = "serde",
serde(default, skip_serializing_if = "Option::is_none")
)]
pub by_ref_span: Option<Span>,
pub body: &'arena Stmt<'arena, 'src>,
#[cfg_attr(feature = "serde", serde(default, skip_serializing_if = "is_false"))]
pub uses_alternative: bool,
}
impl<'arena, 'src> ForeachStmt<'arena, 'src> {
pub fn new(
expr: Expr<'arena, 'src>,
value: Expr<'arena, 'src>,
body: &'arena Stmt<'arena, 'src>,
) -> Self {
Self {
expr,
key: None,
value,
by_ref: false,
by_ref_span: None,
body,
uses_alternative: false,
}
}
}
#[derive(Debug)]
#[cfg_attr(feature = "serde", derive(Serialize))]
#[non_exhaustive]
pub struct DoWhileStmt<'arena, 'src> {
pub body: &'arena Stmt<'arena, 'src>,
pub condition: Expr<'arena, 'src>,
}
impl<'arena, 'src> DoWhileStmt<'arena, 'src> {
pub fn new(body: &'arena Stmt<'arena, 'src>, condition: Expr<'arena, 'src>) -> Self {
Self { body, condition }
}
}
#[derive(Debug)]
#[cfg_attr(feature = "serde", derive(Serialize))]
pub struct SwitchBody<'arena, 'src> {
pub cases: ArenaVec<'arena, SwitchCase<'arena, 'src>>,
#[cfg_attr(feature = "serde", serde(skip))]
pub span: Span,
}
#[derive(Debug)]
#[cfg_attr(feature = "serde", derive(Serialize))]
#[non_exhaustive]
pub struct SwitchStmt<'arena, 'src> {
pub expr: Expr<'arena, 'src>,
#[cfg_attr(feature = "serde", serde(flatten))]
pub body: SwitchBody<'arena, 'src>,
#[cfg_attr(feature = "serde", serde(default, skip_serializing_if = "is_false"))]
pub uses_alternative: bool,
}
impl<'arena, 'src> SwitchStmt<'arena, 'src> {
pub fn new(expr: Expr<'arena, 'src>, body: SwitchBody<'arena, 'src>) -> Self {
Self {
expr,
body,
uses_alternative: false,
}
}
}
#[derive(Debug)]
#[cfg_attr(feature = "serde", derive(Serialize))]
pub struct SwitchCase<'arena, 'src> {
pub value: Option<Expr<'arena, 'src>>,
pub body: ArenaVec<'arena, Stmt<'arena, 'src>>,
pub span: Span,
}
#[derive(Debug)]
#[cfg_attr(feature = "serde", derive(Serialize))]
#[non_exhaustive]
pub struct TryCatchStmt<'arena, 'src> {
pub body: &'arena Block<'arena, 'src>,
pub catches: ArenaVec<'arena, CatchClause<'arena, 'src>>,
pub finally: Option<&'arena Block<'arena, 'src>>,
#[cfg_attr(feature = "serde", serde(skip))]
#[doc(hidden)]
pub finally_kw_span: Option<Span>,
}
impl<'arena, 'src> TryCatchStmt<'arena, 'src> {
pub fn new(arena: &'arena bumpalo::Bump, body: &'arena Block<'arena, 'src>) -> Self {
Self {
body,
catches: ArenaVec::new_in(arena),
finally: None,
finally_kw_span: None,
}
}
}
#[derive(Debug)]
#[cfg_attr(feature = "serde", derive(Serialize))]
#[non_exhaustive]
pub struct CatchClause<'arena, 'src> {
pub types: ArenaVec<'arena, Name<'arena, 'src>>,
pub var: Option<Ident<'src>>,
pub body: &'arena Block<'arena, 'src>,
pub span: Span,
}
impl<'arena, 'src> CatchClause<'arena, 'src> {
pub fn new(
arena: &'arena bumpalo::Bump,
body: &'arena Block<'arena, 'src>,
span: Span,
) -> Self {
Self {
types: ArenaVec::new_in(arena),
var: None,
body,
span,
}
}
}
#[derive(Debug)]
#[cfg_attr(feature = "serde", derive(Serialize))]
#[non_exhaustive]
pub struct NamespaceDecl<'arena, 'src> {
pub name: Option<Name<'arena, 'src>>,
pub body: NamespaceBody<'arena, 'src>,
}
impl<'arena, 'src> NamespaceDecl<'arena, 'src> {
pub fn new(name: Option<Name<'arena, 'src>>, body: NamespaceBody<'arena, 'src>) -> Self {
Self { name, body }
}
}
#[derive(Debug)]
#[cfg_attr(feature = "serde", derive(Serialize))]
#[non_exhaustive]
pub enum NamespaceBody<'arena, 'src> {
Braced(&'arena Block<'arena, 'src>),
Simple,
}
#[derive(Debug)]
#[cfg_attr(feature = "serde", derive(Serialize))]
#[non_exhaustive]
pub struct DeclareStmt<'arena, 'src> {
pub directives: ArenaVec<'arena, (&'src str, Expr<'arena, 'src>)>,
pub body: Option<&'arena Stmt<'arena, 'src>>,
#[cfg_attr(feature = "serde", serde(default, skip_serializing_if = "is_false"))]
pub uses_alternative: bool,
}
impl<'arena, 'src> DeclareStmt<'arena, 'src> {
pub fn new(directives: ArenaVec<'arena, (&'src str, Expr<'arena, 'src>)>) -> Self {
Self {
directives,
body: None,
uses_alternative: false,
}
}
}
#[derive(Debug)]
#[cfg_attr(feature = "serde", derive(Serialize))]
#[non_exhaustive]
pub struct UseDecl<'arena, 'src> {
pub kind: UseKind,
pub uses: ArenaVec<'arena, UseItem<'arena, 'src>>,
}
impl<'arena, 'src> UseDecl<'arena, 'src> {
pub fn new(kind: UseKind, uses: ArenaVec<'arena, UseItem<'arena, 'src>>) -> Self {
Self { kind, uses }
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(Serialize))]
#[non_exhaustive]
pub enum UseKind {
Normal,
Function,
Const,
}
#[derive(Debug)]
#[cfg_attr(feature = "serde", derive(Serialize))]
pub struct UseItem<'arena, 'src> {
pub name: Name<'arena, 'src>,
pub alias: Option<Ident<'src>>,
#[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
pub kind: Option<UseKind>,
pub span: Span,
}
#[derive(Debug)]
#[cfg_attr(feature = "serde", derive(Serialize))]
pub struct ConstItem<'arena, 'src> {
pub name: Ident<'src>,
pub value: Expr<'arena, 'src>,
pub attributes: ArenaVec<'arena, Attribute<'arena, 'src>>,
pub span: Span,
#[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
pub doc_comment: Option<Comment<'src>>,
}
#[derive(Debug)]
#[cfg_attr(feature = "serde", derive(Serialize))]
pub struct StaticVar<'arena, 'src> {
pub name: Ident<'src>,
pub default: Option<Expr<'arena, 'src>>,
pub span: Span,
}