1#[cfg(feature = "serde")]
2use serde::Serialize;
3
4use crate::Span;
5
6use super::{
7 ArenaVec, Attribute, ClassDecl, Comment, EnumDecl, Expr, FunctionDecl, Ident, InterfaceDecl,
8 Name, TraitDecl,
9};
10
11#[cfg(feature = "serde")]
12fn is_false(b: &bool) -> bool {
13 !b
14}
15
16#[derive(Debug)]
18#[cfg_attr(feature = "serde", derive(Serialize))]
19pub struct Stmt<'arena, 'src> {
20 pub kind: StmtKind<'arena, 'src>,
22 pub span: Span,
24 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
41 pub doc_comment: Option<&'arena Comment<'src>>,
42}
43
44impl<'arena, 'src> Stmt<'arena, 'src> {
45 pub fn leading_doc_comment(&self) -> Option<&Comment<'src>> {
66 if let Some(doc) = self.doc_comment {
67 return Some(doc);
68 }
69 match &self.kind {
70 StmtKind::Function(f) => f.doc_comment.as_ref(),
71 StmtKind::Class(c) => c.doc_comment.as_ref(),
72 StmtKind::Interface(i) => i.doc_comment.as_ref(),
73 StmtKind::Trait(t) => t.doc_comment.as_ref(),
74 StmtKind::Enum(e) => e.doc_comment.as_ref(),
75 StmtKind::Const(items) => items.first().and_then(|i| i.doc_comment.as_ref()),
76 _ => None,
77 }
78 }
79}
80
81#[derive(Debug)]
87#[cfg_attr(feature = "serde", derive(Serialize))]
88#[cfg_attr(feature = "serde", serde(transparent))]
89pub struct Block<'arena, 'src> {
90 pub stmts: ArenaVec<'arena, Stmt<'arena, 'src>>,
92 #[cfg_attr(feature = "serde", serde(skip))]
95 pub span: Span,
96}
97
98#[derive(Debug)]
100#[cfg_attr(feature = "serde", derive(Serialize))]
101#[non_exhaustive]
102pub enum StmtKind<'arena, 'src> {
103 Expression(&'arena Expr<'arena, 'src>),
105
106 Echo(ArenaVec<'arena, Expr<'arena, 'src>>),
108
109 Return(Option<&'arena Expr<'arena, 'src>>),
111
112 Block(&'arena Block<'arena, 'src>),
114
115 If(&'arena IfStmt<'arena, 'src>),
117
118 While(&'arena WhileStmt<'arena, 'src>),
120
121 For(&'arena ForStmt<'arena, 'src>),
123
124 Foreach(&'arena ForeachStmt<'arena, 'src>),
126
127 DoWhile(&'arena DoWhileStmt<'arena, 'src>),
129
130 Function(&'arena FunctionDecl<'arena, 'src>),
132
133 Break(Option<&'arena Expr<'arena, 'src>>),
135
136 Continue(Option<&'arena Expr<'arena, 'src>>),
138
139 Switch(&'arena SwitchStmt<'arena, 'src>),
141
142 Goto(Ident<'src>),
144
145 Label(Ident<'src>),
147
148 Declare(&'arena DeclareStmt<'arena, 'src>),
150
151 Unset(ArenaVec<'arena, Expr<'arena, 'src>>),
153
154 Throw(&'arena Expr<'arena, 'src>),
156
157 TryCatch(&'arena TryCatchStmt<'arena, 'src>),
159
160 Global(ArenaVec<'arena, Expr<'arena, 'src>>),
162
163 Class(&'arena ClassDecl<'arena, 'src>),
165
166 Interface(&'arena InterfaceDecl<'arena, 'src>),
168
169 Trait(&'arena TraitDecl<'arena, 'src>),
171
172 Enum(&'arena EnumDecl<'arena, 'src>),
174
175 Namespace(&'arena NamespaceDecl<'arena, 'src>),
177
178 Use(&'arena UseDecl<'arena, 'src>),
180
181 Const(ArenaVec<'arena, ConstItem<'arena, 'src>>),
183
184 StaticVar(ArenaVec<'arena, StaticVar<'arena, 'src>>),
186
187 HaltCompiler(&'src str),
189
190 Nop,
192
193 InlineHtml(&'src str),
195
196 Error,
198}
199
200#[derive(Debug)]
202#[cfg_attr(feature = "serde", derive(Serialize))]
203#[non_exhaustive]
204pub struct IfStmt<'arena, 'src> {
205 pub condition: Expr<'arena, 'src>,
207 pub then_branch: &'arena Stmt<'arena, 'src>,
209 pub elseif_branches: ArenaVec<'arena, ElseIfBranch<'arena, 'src>>,
211 pub else_branch: Option<&'arena Stmt<'arena, 'src>>,
213 #[cfg_attr(feature = "serde", serde(skip))]
215 #[doc(hidden)]
216 pub else_kw_span: Option<Span>,
217 #[cfg_attr(feature = "serde", serde(default, skip_serializing_if = "is_false"))]
219 pub uses_alternative: bool,
220}
221
222impl<'arena, 'src> IfStmt<'arena, 'src> {
223 pub fn new(
226 arena: &'arena bumpalo::Bump,
227 condition: Expr<'arena, 'src>,
228 then_branch: &'arena Stmt<'arena, 'src>,
229 ) -> Self {
230 Self {
231 condition,
232 then_branch,
233 elseif_branches: ArenaVec::new_in(arena),
234 else_branch: None,
235 else_kw_span: None,
236 uses_alternative: false,
237 }
238 }
239}
240
241#[derive(Debug)]
243#[cfg_attr(feature = "serde", derive(Serialize))]
244pub struct ElseIfBranch<'arena, 'src> {
245 pub condition: Expr<'arena, 'src>,
247 pub body: Stmt<'arena, 'src>,
249 pub span: Span,
251}
252
253#[derive(Debug)]
255#[cfg_attr(feature = "serde", derive(Serialize))]
256#[non_exhaustive]
257pub struct WhileStmt<'arena, 'src> {
258 pub condition: Expr<'arena, 'src>,
260 pub body: &'arena Stmt<'arena, 'src>,
262 #[cfg_attr(feature = "serde", serde(default, skip_serializing_if = "is_false"))]
264 pub uses_alternative: bool,
265}
266
267impl<'arena, 'src> WhileStmt<'arena, 'src> {
268 pub fn new(condition: Expr<'arena, 'src>, body: &'arena Stmt<'arena, 'src>) -> Self {
271 Self {
272 condition,
273 body,
274 uses_alternative: false,
275 }
276 }
277}
278
279#[derive(Debug)]
281#[cfg_attr(feature = "serde", derive(Serialize))]
282#[non_exhaustive]
283pub struct ForStmt<'arena, 'src> {
284 pub init: ArenaVec<'arena, Expr<'arena, 'src>>,
286 pub condition: ArenaVec<'arena, Expr<'arena, 'src>>,
288 pub update: ArenaVec<'arena, Expr<'arena, 'src>>,
290 pub body: &'arena Stmt<'arena, 'src>,
292 #[cfg_attr(feature = "serde", serde(default, skip_serializing_if = "is_false"))]
294 pub uses_alternative: bool,
295}
296
297impl<'arena, 'src> ForStmt<'arena, 'src> {
298 pub fn new(arena: &'arena bumpalo::Bump, body: &'arena Stmt<'arena, 'src>) -> Self {
301 Self {
302 init: ArenaVec::new_in(arena),
303 condition: ArenaVec::new_in(arena),
304 update: ArenaVec::new_in(arena),
305 body,
306 uses_alternative: false,
307 }
308 }
309}
310
311#[derive(Debug)]
313#[cfg_attr(feature = "serde", derive(Serialize))]
314#[non_exhaustive]
315pub struct ForeachStmt<'arena, 'src> {
316 pub expr: Expr<'arena, 'src>,
318 pub key: Option<Expr<'arena, 'src>>,
320 pub value: Expr<'arena, 'src>,
322 #[cfg_attr(feature = "serde", serde(default, skip_serializing_if = "is_false"))]
324 pub by_ref: bool,
325 pub body: &'arena Stmt<'arena, 'src>,
327 #[cfg_attr(feature = "serde", serde(default, skip_serializing_if = "is_false"))]
329 pub uses_alternative: bool,
330}
331
332impl<'arena, 'src> ForeachStmt<'arena, 'src> {
333 pub fn new(
336 expr: Expr<'arena, 'src>,
337 value: Expr<'arena, 'src>,
338 body: &'arena Stmt<'arena, 'src>,
339 ) -> Self {
340 Self {
341 expr,
342 key: None,
343 value,
344 by_ref: false,
345 body,
346 uses_alternative: false,
347 }
348 }
349}
350
351#[derive(Debug)]
353#[cfg_attr(feature = "serde", derive(Serialize))]
354#[non_exhaustive]
355pub struct DoWhileStmt<'arena, 'src> {
356 pub body: &'arena Stmt<'arena, 'src>,
358 pub condition: Expr<'arena, 'src>,
360}
361
362impl<'arena, 'src> DoWhileStmt<'arena, 'src> {
363 pub fn new(body: &'arena Stmt<'arena, 'src>, condition: Expr<'arena, 'src>) -> Self {
366 Self { body, condition }
367 }
368}
369
370#[derive(Debug)]
372#[cfg_attr(feature = "serde", derive(Serialize))]
373pub struct SwitchBody<'arena, 'src> {
374 pub cases: ArenaVec<'arena, SwitchCase<'arena, 'src>>,
376 #[cfg_attr(feature = "serde", serde(skip))]
378 pub span: Span,
379}
380
381#[derive(Debug)]
383#[cfg_attr(feature = "serde", derive(Serialize))]
384#[non_exhaustive]
385pub struct SwitchStmt<'arena, 'src> {
386 pub expr: Expr<'arena, 'src>,
388 #[cfg_attr(feature = "serde", serde(flatten))]
390 pub body: SwitchBody<'arena, 'src>,
391 #[cfg_attr(feature = "serde", serde(default, skip_serializing_if = "is_false"))]
393 pub uses_alternative: bool,
394}
395
396impl<'arena, 'src> SwitchStmt<'arena, 'src> {
397 pub fn new(expr: Expr<'arena, 'src>, body: SwitchBody<'arena, 'src>) -> Self {
400 Self {
401 expr,
402 body,
403 uses_alternative: false,
404 }
405 }
406}
407
408#[derive(Debug)]
410#[cfg_attr(feature = "serde", derive(Serialize))]
411pub struct SwitchCase<'arena, 'src> {
412 pub value: Option<Expr<'arena, 'src>>,
414 pub body: ArenaVec<'arena, Stmt<'arena, 'src>>,
416 pub span: Span,
418}
419
420#[derive(Debug)]
422#[cfg_attr(feature = "serde", derive(Serialize))]
423#[non_exhaustive]
424pub struct TryCatchStmt<'arena, 'src> {
425 pub body: &'arena Block<'arena, 'src>,
427 pub catches: ArenaVec<'arena, CatchClause<'arena, 'src>>,
429 pub finally: Option<&'arena Block<'arena, 'src>>,
431 #[cfg_attr(feature = "serde", serde(skip))]
433 #[doc(hidden)]
434 pub finally_kw_span: Option<Span>,
435}
436
437impl<'arena, 'src> TryCatchStmt<'arena, 'src> {
438 pub fn new(arena: &'arena bumpalo::Bump, body: &'arena Block<'arena, 'src>) -> Self {
441 Self {
442 body,
443 catches: ArenaVec::new_in(arena),
444 finally: None,
445 finally_kw_span: None,
446 }
447 }
448}
449
450#[derive(Debug)]
452#[cfg_attr(feature = "serde", derive(Serialize))]
453#[non_exhaustive]
454pub struct CatchClause<'arena, 'src> {
455 pub types: ArenaVec<'arena, Name<'arena, 'src>>,
457 pub var: Option<Ident<'src>>,
459 pub body: &'arena Block<'arena, 'src>,
461 pub span: Span,
463}
464
465impl<'arena, 'src> CatchClause<'arena, 'src> {
466 pub fn new(
469 arena: &'arena bumpalo::Bump,
470 body: &'arena Block<'arena, 'src>,
471 span: Span,
472 ) -> Self {
473 Self {
474 types: ArenaVec::new_in(arena),
475 var: None,
476 body,
477 span,
478 }
479 }
480}
481
482#[derive(Debug)]
484#[cfg_attr(feature = "serde", derive(Serialize))]
485#[non_exhaustive]
486pub struct NamespaceDecl<'arena, 'src> {
487 pub name: Option<Name<'arena, 'src>>,
489 pub body: NamespaceBody<'arena, 'src>,
491}
492
493impl<'arena, 'src> NamespaceDecl<'arena, 'src> {
494 pub fn new(name: Option<Name<'arena, 'src>>, body: NamespaceBody<'arena, 'src>) -> Self {
497 Self { name, body }
498 }
499}
500
501#[derive(Debug)]
503#[cfg_attr(feature = "serde", derive(Serialize))]
504#[non_exhaustive]
505pub enum NamespaceBody<'arena, 'src> {
506 Braced(&'arena Block<'arena, 'src>),
508 Simple,
510}
511
512#[derive(Debug)]
514#[cfg_attr(feature = "serde", derive(Serialize))]
515#[non_exhaustive]
516pub struct DeclareStmt<'arena, 'src> {
517 pub directives: ArenaVec<'arena, (&'src str, Expr<'arena, 'src>)>,
519 pub body: Option<&'arena Stmt<'arena, 'src>>,
521 #[cfg_attr(feature = "serde", serde(default, skip_serializing_if = "is_false"))]
523 pub uses_alternative: bool,
524}
525
526impl<'arena, 'src> DeclareStmt<'arena, 'src> {
527 pub fn new(directives: ArenaVec<'arena, (&'src str, Expr<'arena, 'src>)>) -> Self {
530 Self {
531 directives,
532 body: None,
533 uses_alternative: false,
534 }
535 }
536}
537
538#[derive(Debug)]
540#[cfg_attr(feature = "serde", derive(Serialize))]
541#[non_exhaustive]
542pub struct UseDecl<'arena, 'src> {
543 pub kind: UseKind,
545 pub uses: ArenaVec<'arena, UseItem<'arena, 'src>>,
547}
548
549impl<'arena, 'src> UseDecl<'arena, 'src> {
550 pub fn new(kind: UseKind, uses: ArenaVec<'arena, UseItem<'arena, 'src>>) -> Self {
553 Self { kind, uses }
554 }
555}
556
557#[derive(Debug, Clone, Copy, PartialEq, Eq)]
559#[cfg_attr(feature = "serde", derive(Serialize))]
560#[non_exhaustive]
561pub enum UseKind {
562 Normal,
564 Function,
566 Const,
568}
569
570#[derive(Debug)]
572#[cfg_attr(feature = "serde", derive(Serialize))]
573pub struct UseItem<'arena, 'src> {
574 pub name: Name<'arena, 'src>,
576 pub alias: Option<Ident<'src>>,
578 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
580 pub kind: Option<UseKind>,
581 pub span: Span,
583}
584
585#[derive(Debug)]
587#[cfg_attr(feature = "serde", derive(Serialize))]
588pub struct ConstItem<'arena, 'src> {
589 pub name: Ident<'src>,
591 pub value: Expr<'arena, 'src>,
593 pub attributes: ArenaVec<'arena, Attribute<'arena, 'src>>,
595 pub span: Span,
597 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
599 pub doc_comment: Option<Comment<'src>>,
600}
601
602#[derive(Debug)]
604#[cfg_attr(feature = "serde", derive(Serialize))]
605pub struct StaticVar<'arena, 'src> {
606 pub name: Ident<'src>,
608 pub default: Option<Expr<'arena, 'src>>,
610 pub span: Span,
612}