1use crate::{ident::Ident, span::Span};
4
5use super::{Comment, expr::Expr, item::Modifier, ty::Type};
6
7#[derive(Debug, Clone, PartialEq, Eq, Hash)]
9pub enum Stmt {
10 Empty(Span),
12 Block(Block),
14 Labeled(LabeledStmt),
16 Expr(ExprStmt),
18 LocalVarDecl(LocalVarDeclStmt),
20 If(IfStmt),
22 Assert(AssertStmt),
24 Switch(SwitchStmt),
26 While(WhileStmt),
28 DoWhile(DoWhileStmt),
30 For(ForStmt),
32 EnhancedFor(EnhancedForStmt),
34 Break(JumpStmt),
36 Continue(JumpStmt),
38 Return(ReturnStmt),
40 Throw(ThrowStmt),
42 Synchronized(SynchronizedStmt),
44 Try(TryStmt),
46 Yield(YieldStmt),
48 ClassDecl(Box<super::item::TypeDecl>),
50}
51
52impl Stmt {
53 pub fn span(&self) -> Span {
54 match self {
55 Self::Empty(s) => *s,
56 Self::Block(b) => b.span(),
57 Self::Labeled(l) => l.span(),
58 Self::Expr(e) => e.span(),
59 Self::LocalVarDecl(d) => d.span(),
60 Self::If(s) => s.span(),
61 Self::Assert(s) => s.span(),
62 Self::Switch(s) => s.span(),
63 Self::While(s) => s.span(),
64 Self::DoWhile(s) => s.span(),
65 Self::For(s) => s.span(),
66 Self::EnhancedFor(s) => s.span(),
67 Self::Break(s) => s.span(),
68 Self::Continue(s) => s.span(),
69 Self::Return(s) => s.span(),
70 Self::Throw(s) => s.span(),
71 Self::Synchronized(s) => s.span(),
72 Self::Try(s) => s.span(),
73 Self::Yield(s) => s.span(),
74 Self::ClassDecl(d) => d.span(),
75 }
76 }
77}
78
79#[derive(Debug, Clone, PartialEq, Eq, Hash)]
81pub struct Block {
82 pub leading_comments: Vec<Comment>,
83 pub brace_span: (Span, Span),
84 pub stmts: Vec<Stmt>,
85}
86
87impl Block {
88 pub fn span(&self) -> Span {
89 let start = self
90 .leading_comments
91 .first()
92 .map_or(self.brace_span.0, |c| c.span);
93 start.join(self.brace_span.1)
94 }
95}
96
97#[derive(Debug, Clone, PartialEq, Eq, Hash)]
99pub struct LabeledStmt {
100 pub leading_comments: Vec<Comment>,
101 pub label: Ident,
102 pub colon_span: Span,
103 pub stmt: Box<Stmt>,
104}
105
106impl LabeledStmt {
107 pub fn span(&self) -> Span {
108 let start = self
109 .leading_comments
110 .first()
111 .map_or(self.label.span(), |c| c.span);
112 start.join(self.stmt.span())
113 }
114}
115
116#[derive(Debug, Clone, PartialEq, Eq, Hash)]
118pub struct ExprStmt {
119 pub leading_comments: Vec<Comment>,
120 pub expr: Expr,
121 pub semi_span: Span,
122}
123
124impl ExprStmt {
125 pub fn span(&self) -> Span {
126 let start = self
127 .leading_comments
128 .first()
129 .map_or(self.expr.span(), |c| c.span);
130 start.join(self.semi_span)
131 }
132}
133
134#[derive(Debug, Clone, PartialEq, Eq, Hash)]
136pub struct LocalVarDeclStmt {
137 pub leading_comments: Vec<Comment>,
138 pub modifiers: Vec<Modifier>,
139 pub ty: LocalVarType,
140 pub declarators: Vec<VariableDeclarator>,
141 pub semi_span: Span,
142}
143
144impl LocalVarDeclStmt {
145 pub fn span(&self) -> Span {
146 let start = self
147 .leading_comments
148 .first()
149 .map_or(self.semi_span, |c| c.span);
150 start.join(self.semi_span)
151 }
152}
153
154#[derive(Debug, Clone, PartialEq, Eq, Hash)]
156pub enum LocalVarType {
157 Type(Type),
159 Var(Span),
161}
162
163#[derive(Debug, Clone, PartialEq, Eq, Hash)]
165pub struct VariableDeclarator {
166 pub name: Option<Ident>, pub dims: Vec<super::ty::ArrayDim>,
168 pub initializer: Option<Expr>,
169}
170
171#[derive(Debug, Clone, PartialEq, Eq, Hash)]
173pub struct IfStmt {
174 pub leading_comments: Vec<Comment>,
175 pub if_span: Span,
176 pub paren_span: (Span, Span),
177 pub cond: Expr,
178 pub then_stmt: Box<Stmt>,
179 pub else_clause: Option<(Span, Box<Stmt>)>,
180}
181
182impl IfStmt {
183 pub fn span(&self) -> Span {
184 let end = match &self.else_clause {
185 Some((_, stmt)) => stmt.span(),
186 None => self.then_stmt.span(),
187 };
188 let start = self
189 .leading_comments
190 .first()
191 .map_or(self.if_span, |c| c.span);
192 start.join(end)
193 }
194}
195
196#[derive(Debug, Clone, PartialEq, Eq, Hash)]
198pub struct AssertStmt {
199 pub leading_comments: Vec<Comment>,
200 pub assert_span: Span,
201 pub cond: Expr,
202 pub detail: Option<(Span, Expr)>,
203 pub semi_span: Span,
204}
205
206impl AssertStmt {
207 pub fn span(&self) -> Span {
208 let start = self
209 .leading_comments
210 .first()
211 .map_or(self.assert_span, |c| c.span);
212 start.join(self.semi_span)
213 }
214}
215
216#[derive(Debug, Clone, PartialEq, Eq, Hash)]
218pub struct SwitchStmt {
219 pub leading_comments: Vec<Comment>,
220 pub switch_span: Span,
221 pub paren_span: (Span, Span),
222 pub selector: Expr,
223 pub brace_span: (Span, Span),
224 pub cases: Vec<SwitchCaseGroup>,
225}
226
227impl SwitchStmt {
228 pub fn span(&self) -> Span {
229 let start = self
230 .leading_comments
231 .first()
232 .map_or(self.switch_span, |c| c.span);
233 start.join(self.brace_span.1)
234 }
235}
236
237#[derive(Debug, Clone, PartialEq, Eq, Hash)]
239pub struct SwitchCaseGroup {
240 pub labels: Vec<super::expr::SwitchCase>,
241 pub colon_span: Span,
242 pub stmts: Vec<Stmt>,
243}
244
245#[derive(Debug, Clone, PartialEq, Eq, Hash)]
247pub struct WhileStmt {
248 pub leading_comments: Vec<Comment>,
249 pub while_span: Span,
250 pub paren_span: (Span, Span),
251 pub cond: Expr,
252 pub body: Box<Stmt>,
253}
254
255impl WhileStmt {
256 pub fn span(&self) -> Span {
257 let start = self
258 .leading_comments
259 .first()
260 .map_or(self.while_span, |c| c.span);
261 start.join(self.body.span())
262 }
263}
264
265#[derive(Debug, Clone, PartialEq, Eq, Hash)]
267pub struct DoWhileStmt {
268 pub leading_comments: Vec<Comment>,
269 pub do_span: Span,
270 pub body: Box<Stmt>,
271 pub while_span: Span,
272 pub paren_span: (Span, Span),
273 pub cond: Expr,
274 pub semi_span: Span,
275}
276
277impl DoWhileStmt {
278 pub fn span(&self) -> Span {
279 let start = self
280 .leading_comments
281 .first()
282 .map_or(self.do_span, |c| c.span);
283 start.join(self.semi_span)
284 }
285}
286
287#[derive(Debug, Clone, PartialEq, Eq, Hash)]
289pub struct ForStmt {
290 pub leading_comments: Vec<Comment>,
291 pub for_span: Span,
292 pub paren_span: (Span, Span),
293 pub init: ForInit,
294 pub cond: Option<Expr>,
295 pub semi2_span: Option<Span>,
296 pub update: Vec<Expr>,
297 pub body: Box<Stmt>,
298}
299
300impl ForStmt {
301 pub fn span(&self) -> Span {
302 let start = self
303 .leading_comments
304 .first()
305 .map_or(self.for_span, |c| c.span);
306 start.join(self.body.span())
307 }
308}
309
310#[derive(Debug, Clone, PartialEq, Eq, Hash)]
312pub enum ForInit {
313 Exprs(Vec<Expr>),
315 LocalVarDecl(LocalVarDeclStmt),
317}
318
319#[derive(Debug, Clone, PartialEq, Eq, Hash)]
321pub struct EnhancedForStmt {
322 pub leading_comments: Vec<Comment>,
323 pub for_span: Span,
324 pub paren_span: (Span, Span),
325 pub var_decl: LocalVarDeclStmt,
326 pub colon_span: Span,
327 pub iterable: Expr,
328 pub body: Box<Stmt>,
329}
330
331impl EnhancedForStmt {
332 pub fn span(&self) -> Span {
333 let start = self
334 .leading_comments
335 .first()
336 .map_or(self.for_span, |c| c.span);
337 start.join(self.body.span())
338 }
339}
340
341#[derive(Debug, Clone, PartialEq, Eq, Hash)]
343pub struct JumpStmt {
344 pub leading_comments: Vec<Comment>,
345 pub keyword_span: Span,
346 pub label: Option<Ident>,
347 pub semi_span: Span,
348}
349
350impl JumpStmt {
351 pub fn span(&self) -> Span {
352 let start = self
353 .leading_comments
354 .first()
355 .map_or(self.keyword_span, |c| c.span);
356 start.join(self.semi_span)
357 }
358}
359
360#[derive(Debug, Clone, PartialEq, Eq, Hash)]
362pub struct ReturnStmt {
363 pub leading_comments: Vec<Comment>,
364 pub return_span: Span,
365 pub value: Option<Expr>,
366 pub semi_span: Span,
367}
368
369impl ReturnStmt {
370 pub fn span(&self) -> Span {
371 let start = self
372 .leading_comments
373 .first()
374 .map_or(self.return_span, |c| c.span);
375 start.join(self.semi_span)
376 }
377}
378
379#[derive(Debug, Clone, PartialEq, Eq, Hash)]
381pub struct ThrowStmt {
382 pub leading_comments: Vec<Comment>,
383 pub throw_span: Span,
384 pub expr: Expr,
385 pub semi_span: Span,
386}
387
388impl ThrowStmt {
389 pub fn span(&self) -> Span {
390 let start = self
391 .leading_comments
392 .first()
393 .map_or(self.throw_span, |c| c.span);
394 start.join(self.semi_span)
395 }
396}
397
398#[derive(Debug, Clone, PartialEq, Eq, Hash)]
400pub struct SynchronizedStmt {
401 pub leading_comments: Vec<Comment>,
402 pub synchronized_span: Span,
403 pub paren_span: (Span, Span),
404 pub lock: Expr,
405 pub body: Block,
406}
407
408impl SynchronizedStmt {
409 pub fn span(&self) -> Span {
410 let start = self
411 .leading_comments
412 .first()
413 .map_or(self.synchronized_span, |c| c.span);
414 start.join(self.body.span())
415 }
416}
417
418#[derive(Debug, Clone, PartialEq, Eq, Hash)]
420pub enum TryStmt {
421 Basic {
423 leading_comments: Vec<Comment>,
424 try_span: Span,
425 block: Block,
426 catches: Vec<CatchClause>,
427 finally_block: Option<(Span, Block)>,
428 },
429 TryWithResources {
431 leading_comments: Vec<Comment>,
432 try_span: Span,
433 paren_span: (Span, Span),
434 resources: Vec<TryResource>,
435 block: Block,
436 catches: Vec<CatchClause>,
437 finally_block: Option<(Span, Block)>,
438 },
439}
440
441impl TryStmt {
442 pub fn span(&self) -> Span {
443 match self {
444 Self::Basic {
445 leading_comments,
446 try_span,
447 block,
448 finally_block,
449 ..
450 } => {
451 let end = match finally_block {
452 Some((_, b)) => b.brace_span.1,
453 None => block.brace_span.1,
454 };
455 let start = leading_comments.first().map_or(*try_span, |c| c.span);
456 start.join(end)
457 }
458 Self::TryWithResources {
459 leading_comments,
460 try_span,
461 block,
462 finally_block,
463 ..
464 } => {
465 let end = match finally_block {
466 Some((_, b)) => b.brace_span.1,
467 None => block.brace_span.1,
468 };
469 let start = leading_comments.first().map_or(*try_span, |c| c.span);
470 start.join(end)
471 }
472 }
473 }
474}
475
476#[derive(Debug, Clone, PartialEq, Eq, Hash)]
478pub struct CatchClause {
479 pub catch_span: Span,
480 pub paren_span: (Span, Span),
481 pub param: CatchParam,
482 pub block: Block,
483}
484
485#[derive(Debug, Clone, PartialEq, Eq, Hash)]
487pub struct CatchParam {
488 pub modifiers: Vec<Modifier>,
489 pub ty: CatchType,
490 pub name: Ident,
491}
492
493#[derive(Debug, Clone, PartialEq, Eq, Hash)]
495pub struct CatchType {
496 pub types: Vec<Type>,
497}
498
499#[derive(Debug, Clone, PartialEq, Eq, Hash)]
501pub enum TryResource {
502 Decl(LocalVarDeclStmt),
504 VarRef(Ident),
506}
507
508#[derive(Debug, Clone, PartialEq, Eq, Hash)]
510pub struct YieldStmt {
511 pub leading_comments: Vec<Comment>,
512 pub yield_span: Span,
513 pub value: Expr,
514 pub semi_span: Span,
515}
516
517impl YieldStmt {
518 pub fn span(&self) -> Span {
519 let start = self
520 .leading_comments
521 .first()
522 .map_or(self.yield_span, |c| c.span);
523 start.join(self.semi_span)
524 }
525}