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 #[cfg_attr(
327 feature = "serde",
328 serde(default, skip_serializing_if = "Option::is_none")
329 )]
330 pub by_ref_span: Option<Span>,
331 pub body: &'arena Stmt<'arena, 'src>,
333 #[cfg_attr(feature = "serde", serde(default, skip_serializing_if = "is_false"))]
335 pub uses_alternative: bool,
336}
337
338impl<'arena, 'src> ForeachStmt<'arena, 'src> {
339 pub fn new(
342 expr: Expr<'arena, 'src>,
343 value: Expr<'arena, 'src>,
344 body: &'arena Stmt<'arena, 'src>,
345 ) -> Self {
346 Self {
347 expr,
348 key: None,
349 value,
350 by_ref: false,
351 by_ref_span: None,
352 body,
353 uses_alternative: false,
354 }
355 }
356}
357
358#[derive(Debug)]
360#[cfg_attr(feature = "serde", derive(Serialize))]
361#[non_exhaustive]
362pub struct DoWhileStmt<'arena, 'src> {
363 pub body: &'arena Stmt<'arena, 'src>,
365 pub condition: Expr<'arena, 'src>,
367}
368
369impl<'arena, 'src> DoWhileStmt<'arena, 'src> {
370 pub fn new(body: &'arena Stmt<'arena, 'src>, condition: Expr<'arena, 'src>) -> Self {
373 Self { body, condition }
374 }
375}
376
377#[derive(Debug)]
379#[cfg_attr(feature = "serde", derive(Serialize))]
380pub struct SwitchBody<'arena, 'src> {
381 pub cases: ArenaVec<'arena, SwitchCase<'arena, 'src>>,
383 #[cfg_attr(feature = "serde", serde(skip))]
385 pub span: Span,
386}
387
388#[derive(Debug)]
390#[cfg_attr(feature = "serde", derive(Serialize))]
391#[non_exhaustive]
392pub struct SwitchStmt<'arena, 'src> {
393 pub expr: Expr<'arena, 'src>,
395 #[cfg_attr(feature = "serde", serde(flatten))]
397 pub body: SwitchBody<'arena, 'src>,
398 #[cfg_attr(feature = "serde", serde(default, skip_serializing_if = "is_false"))]
400 pub uses_alternative: bool,
401}
402
403impl<'arena, 'src> SwitchStmt<'arena, 'src> {
404 pub fn new(expr: Expr<'arena, 'src>, body: SwitchBody<'arena, 'src>) -> Self {
407 Self {
408 expr,
409 body,
410 uses_alternative: false,
411 }
412 }
413}
414
415#[derive(Debug)]
417#[cfg_attr(feature = "serde", derive(Serialize))]
418pub struct SwitchCase<'arena, 'src> {
419 pub value: Option<Expr<'arena, 'src>>,
421 pub body: ArenaVec<'arena, Stmt<'arena, 'src>>,
423 pub span: Span,
425}
426
427#[derive(Debug)]
429#[cfg_attr(feature = "serde", derive(Serialize))]
430#[non_exhaustive]
431pub struct TryCatchStmt<'arena, 'src> {
432 pub body: &'arena Block<'arena, 'src>,
434 pub catches: ArenaVec<'arena, CatchClause<'arena, 'src>>,
436 pub finally: Option<&'arena Block<'arena, 'src>>,
438 #[cfg_attr(feature = "serde", serde(skip))]
440 #[doc(hidden)]
441 pub finally_kw_span: Option<Span>,
442}
443
444impl<'arena, 'src> TryCatchStmt<'arena, 'src> {
445 pub fn new(arena: &'arena bumpalo::Bump, body: &'arena Block<'arena, 'src>) -> Self {
448 Self {
449 body,
450 catches: ArenaVec::new_in(arena),
451 finally: None,
452 finally_kw_span: None,
453 }
454 }
455}
456
457#[derive(Debug)]
459#[cfg_attr(feature = "serde", derive(Serialize))]
460#[non_exhaustive]
461pub struct CatchClause<'arena, 'src> {
462 pub types: ArenaVec<'arena, Name<'arena, 'src>>,
464 pub var: Option<Ident<'src>>,
466 pub body: &'arena Block<'arena, 'src>,
468 pub span: Span,
470}
471
472impl<'arena, 'src> CatchClause<'arena, 'src> {
473 pub fn new(
476 arena: &'arena bumpalo::Bump,
477 body: &'arena Block<'arena, 'src>,
478 span: Span,
479 ) -> Self {
480 Self {
481 types: ArenaVec::new_in(arena),
482 var: None,
483 body,
484 span,
485 }
486 }
487}
488
489#[derive(Debug)]
491#[cfg_attr(feature = "serde", derive(Serialize))]
492#[non_exhaustive]
493pub struct NamespaceDecl<'arena, 'src> {
494 pub name: Option<Name<'arena, 'src>>,
496 pub body: NamespaceBody<'arena, 'src>,
498}
499
500impl<'arena, 'src> NamespaceDecl<'arena, 'src> {
501 pub fn new(name: Option<Name<'arena, 'src>>, body: NamespaceBody<'arena, 'src>) -> Self {
504 Self { name, body }
505 }
506}
507
508#[derive(Debug)]
510#[cfg_attr(feature = "serde", derive(Serialize))]
511#[non_exhaustive]
512pub enum NamespaceBody<'arena, 'src> {
513 Braced(&'arena Block<'arena, 'src>),
515 Simple,
517}
518
519#[derive(Debug)]
521#[cfg_attr(feature = "serde", derive(Serialize))]
522#[non_exhaustive]
523pub struct DeclareStmt<'arena, 'src> {
524 pub directives: ArenaVec<'arena, (&'src str, Expr<'arena, 'src>)>,
526 pub body: Option<&'arena Stmt<'arena, 'src>>,
528 #[cfg_attr(feature = "serde", serde(default, skip_serializing_if = "is_false"))]
530 pub uses_alternative: bool,
531}
532
533impl<'arena, 'src> DeclareStmt<'arena, 'src> {
534 pub fn new(directives: ArenaVec<'arena, (&'src str, Expr<'arena, 'src>)>) -> Self {
537 Self {
538 directives,
539 body: None,
540 uses_alternative: false,
541 }
542 }
543}
544
545#[derive(Debug)]
547#[cfg_attr(feature = "serde", derive(Serialize))]
548#[non_exhaustive]
549pub struct UseDecl<'arena, 'src> {
550 pub kind: UseKind,
552 pub uses: ArenaVec<'arena, UseItem<'arena, 'src>>,
554}
555
556impl<'arena, 'src> UseDecl<'arena, 'src> {
557 pub fn new(kind: UseKind, uses: ArenaVec<'arena, UseItem<'arena, 'src>>) -> Self {
560 Self { kind, uses }
561 }
562}
563
564#[derive(Debug, Clone, Copy, PartialEq, Eq)]
566#[cfg_attr(feature = "serde", derive(Serialize))]
567#[non_exhaustive]
568pub enum UseKind {
569 Normal,
571 Function,
573 Const,
575}
576
577#[derive(Debug)]
579#[cfg_attr(feature = "serde", derive(Serialize))]
580pub struct UseItem<'arena, 'src> {
581 pub name: Name<'arena, 'src>,
583 pub alias: Option<Ident<'src>>,
585 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
587 pub kind: Option<UseKind>,
588 pub span: Span,
590}
591
592#[derive(Debug)]
594#[cfg_attr(feature = "serde", derive(Serialize))]
595pub struct ConstItem<'arena, 'src> {
596 pub name: Ident<'src>,
598 pub value: Expr<'arena, 'src>,
600 pub attributes: ArenaVec<'arena, Attribute<'arena, 'src>>,
602 pub span: Span,
604 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
606 pub doc_comment: Option<Comment<'src>>,
607}
608
609#[derive(Debug)]
611#[cfg_attr(feature = "serde", derive(Serialize))]
612pub struct StaticVar<'arena, 'src> {
613 pub name: Ident<'src>,
615 pub default: Option<Expr<'arena, 'src>>,
617 pub span: Span,
619}