1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
//! One view over block function bodies and concise arrow bodies.
//!
//! Before Oxc 0.151 the parser wrapped a concise arrow body (`() => expr`) in a
//! synthetic `FunctionBody` that held one `ExpressionStatement` with the span of
//! `expr`. Oxc now stores the expression directly in `ArrowFunctionBody`. The
//! helpers that read a function or arrow body take a [`BodyRef`], so a concise
//! body keeps the span and the single-expression shape it had before.
use oxc_ast::{
ast::{ArrowFunctionBody, Expression, FunctionBody, Statement},
match_expression,
};
use oxc_ast_visit::Visit;
use oxc_span::{GetSpan, Span};
/// A block function body, or the expression of a concise arrow body.
#[derive(Clone, Copy)]
pub enum BodyRef<'b, 'a> {
/// `function f() { ... }` or `() => { ... }`.
Block(&'b FunctionBody<'a>),
/// `() => expr`.
Concise(&'b Expression<'a>),
}
impl<'b, 'a> BodyRef<'b, 'a> {
/// The body of an arrow function.
pub fn arrow(body: &'b ArrowFunctionBody<'a>) -> Self {
match body {
ArrowFunctionBody::FunctionBody(block) => Self::Block(block),
match_expression!(ArrowFunctionBody) => Self::Concise(body.to_expression()),
}
}
/// The span of the block, or of the concise expression.
pub fn span(self) -> Span {
match self {
Self::Block(block) => block.span,
Self::Concise(expr) => expr.span(),
}
}
/// The statements of a block body. A concise body has none.
pub fn statements(self) -> &'b [Statement<'a>] {
match self {
Self::Block(block) => &block.statements,
Self::Concise(_) => &[],
}
}
/// Walk the body with `visitor`: `visit_function_body` for a block body,
/// `visit_expression` for a concise body.
pub fn visit<V: Visit<'a>>(self, visitor: &mut V) {
match self {
Self::Block(block) => visitor.visit_function_body(block),
Self::Concise(expr) => visitor.visit_expression(expr),
}
}
/// Visit each statement of a block body, or the expression of a concise
/// body. Directives of a block body are not visited.
pub fn visit_statements<V: Visit<'a>>(self, visitor: &mut V) {
match self {
Self::Block(block) => {
for statement in &block.statements {
visitor.visit_statement(statement);
}
}
Self::Concise(expr) => visitor.visit_expression(expr),
}
}
}