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 #[cfg_attr(feature = "serde", serde(default, skip_serializing_if = "is_false"))]
322 pub key_by_ref: bool,
323 pub value: Expr<'arena, 'src>,
325 #[cfg_attr(feature = "serde", serde(default, skip_serializing_if = "is_false"))]
327 pub by_ref: bool,
328 #[cfg_attr(
330 feature = "serde",
331 serde(default, skip_serializing_if = "Option::is_none")
332 )]
333 pub by_ref_span: Option<Span>,
334 pub body: &'arena Stmt<'arena, 'src>,
336 #[cfg_attr(feature = "serde", serde(default, skip_serializing_if = "is_false"))]
338 pub uses_alternative: bool,
339}
340
341impl<'arena, 'src> ForeachStmt<'arena, 'src> {
342 pub fn new(
345 expr: Expr<'arena, 'src>,
346 value: Expr<'arena, 'src>,
347 body: &'arena Stmt<'arena, 'src>,
348 ) -> Self {
349 Self {
350 expr,
351 key: None,
352 key_by_ref: false,
353 value,
354 by_ref: false,
355 by_ref_span: None,
356 body,
357 uses_alternative: false,
358 }
359 }
360}
361
362#[derive(Debug)]
364#[cfg_attr(feature = "serde", derive(Serialize))]
365#[non_exhaustive]
366pub struct DoWhileStmt<'arena, 'src> {
367 pub body: &'arena Stmt<'arena, 'src>,
369 pub condition: Expr<'arena, 'src>,
371}
372
373impl<'arena, 'src> DoWhileStmt<'arena, 'src> {
374 pub fn new(body: &'arena Stmt<'arena, 'src>, condition: Expr<'arena, 'src>) -> Self {
377 Self { body, condition }
378 }
379}
380
381#[derive(Debug)]
383#[cfg_attr(feature = "serde", derive(Serialize))]
384pub struct SwitchBody<'arena, 'src> {
385 pub cases: ArenaVec<'arena, SwitchCase<'arena, 'src>>,
387 #[cfg_attr(feature = "serde", serde(skip))]
389 pub span: Span,
390}
391
392#[derive(Debug)]
394#[cfg_attr(feature = "serde", derive(Serialize))]
395#[non_exhaustive]
396pub struct SwitchStmt<'arena, 'src> {
397 pub expr: Expr<'arena, 'src>,
399 #[cfg_attr(feature = "serde", serde(flatten))]
401 pub body: SwitchBody<'arena, 'src>,
402 #[cfg_attr(feature = "serde", serde(default, skip_serializing_if = "is_false"))]
404 pub uses_alternative: bool,
405}
406
407impl<'arena, 'src> SwitchStmt<'arena, 'src> {
408 pub fn new(expr: Expr<'arena, 'src>, body: SwitchBody<'arena, 'src>) -> Self {
411 Self {
412 expr,
413 body,
414 uses_alternative: false,
415 }
416 }
417}
418
419#[derive(Debug)]
421#[cfg_attr(feature = "serde", derive(Serialize))]
422pub struct SwitchCase<'arena, 'src> {
423 pub value: Option<Expr<'arena, 'src>>,
425 pub body: ArenaVec<'arena, Stmt<'arena, 'src>>,
427 pub span: Span,
429}
430
431#[derive(Debug)]
433#[cfg_attr(feature = "serde", derive(Serialize))]
434#[non_exhaustive]
435pub struct TryCatchStmt<'arena, 'src> {
436 pub body: &'arena Block<'arena, 'src>,
438 pub catches: ArenaVec<'arena, CatchClause<'arena, 'src>>,
440 pub finally: Option<&'arena Block<'arena, 'src>>,
442 #[cfg_attr(feature = "serde", serde(skip))]
444 #[doc(hidden)]
445 pub finally_kw_span: Option<Span>,
446}
447
448impl<'arena, 'src> TryCatchStmt<'arena, 'src> {
449 pub fn new(arena: &'arena bumpalo::Bump, body: &'arena Block<'arena, 'src>) -> Self {
452 Self {
453 body,
454 catches: ArenaVec::new_in(arena),
455 finally: None,
456 finally_kw_span: None,
457 }
458 }
459}
460
461#[derive(Debug)]
463#[cfg_attr(feature = "serde", derive(Serialize))]
464#[non_exhaustive]
465pub struct CatchClause<'arena, 'src> {
466 pub types: ArenaVec<'arena, Name<'arena, 'src>>,
468 pub var: Option<Ident<'src>>,
470 pub body: &'arena Block<'arena, 'src>,
472 pub span: Span,
474}
475
476impl<'arena, 'src> CatchClause<'arena, 'src> {
477 pub fn new(
480 arena: &'arena bumpalo::Bump,
481 body: &'arena Block<'arena, 'src>,
482 span: Span,
483 ) -> Self {
484 Self {
485 types: ArenaVec::new_in(arena),
486 var: None,
487 body,
488 span,
489 }
490 }
491}
492
493#[derive(Debug)]
495#[cfg_attr(feature = "serde", derive(Serialize))]
496#[non_exhaustive]
497pub struct NamespaceDecl<'arena, 'src> {
498 pub name: Option<Name<'arena, 'src>>,
500 pub body: NamespaceBody<'arena, 'src>,
502}
503
504impl<'arena, 'src> NamespaceDecl<'arena, 'src> {
505 pub fn new(name: Option<Name<'arena, 'src>>, body: NamespaceBody<'arena, 'src>) -> Self {
508 Self { name, body }
509 }
510}
511
512#[derive(Debug)]
514#[cfg_attr(feature = "serde", derive(Serialize))]
515#[non_exhaustive]
516pub enum NamespaceBody<'arena, 'src> {
517 Braced(&'arena Block<'arena, 'src>),
519 Simple,
521}
522
523#[derive(Debug)]
525#[cfg_attr(feature = "serde", derive(Serialize))]
526#[non_exhaustive]
527pub struct DeclareStmt<'arena, 'src> {
528 pub directives: ArenaVec<'arena, (&'src str, Expr<'arena, 'src>)>,
530 pub body: Option<&'arena Stmt<'arena, 'src>>,
532 #[cfg_attr(feature = "serde", serde(default, skip_serializing_if = "is_false"))]
534 pub uses_alternative: bool,
535}
536
537impl<'arena, 'src> DeclareStmt<'arena, 'src> {
538 pub fn new(directives: ArenaVec<'arena, (&'src str, Expr<'arena, 'src>)>) -> Self {
541 Self {
542 directives,
543 body: None,
544 uses_alternative: false,
545 }
546 }
547}
548
549#[derive(Debug)]
551#[cfg_attr(feature = "serde", derive(Serialize))]
552#[non_exhaustive]
553pub struct UseDecl<'arena, 'src> {
554 pub kind: UseKind,
556 pub uses: ArenaVec<'arena, UseItem<'arena, 'src>>,
558}
559
560impl<'arena, 'src> UseDecl<'arena, 'src> {
561 pub fn new(kind: UseKind, uses: ArenaVec<'arena, UseItem<'arena, 'src>>) -> Self {
564 Self { kind, uses }
565 }
566}
567
568#[derive(Debug, Clone, Copy, PartialEq, Eq)]
570#[cfg_attr(feature = "serde", derive(Serialize))]
571#[non_exhaustive]
572pub enum UseKind {
573 Normal,
575 Function,
577 Const,
579}
580
581#[derive(Debug)]
583#[cfg_attr(feature = "serde", derive(Serialize))]
584pub struct UseItem<'arena, 'src> {
585 pub name: Name<'arena, 'src>,
587 pub alias: Option<Ident<'src>>,
589 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
591 pub kind: Option<UseKind>,
592 pub span: Span,
594}
595
596#[derive(Debug)]
598#[cfg_attr(feature = "serde", derive(Serialize))]
599pub struct ConstItem<'arena, 'src> {
600 pub name: Ident<'src>,
602 pub value: Expr<'arena, 'src>,
604 pub attributes: ArenaVec<'arena, Attribute<'arena, 'src>>,
606 pub span: Span,
608 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
610 pub doc_comment: Option<Comment<'src>>,
611}
612
613#[derive(Debug)]
615#[cfg_attr(feature = "serde", derive(Serialize))]
616pub struct StaticVar<'arena, 'src> {
617 pub name: Ident<'src>,
619 pub default: Option<Expr<'arena, 'src>>,
621 pub span: Span,
623}