boa_ast/function/
async_arrow_function.rs1use super::{FormalParameterList, FunctionBody};
2use crate::operations::{ContainsSymbol, contains};
3use crate::scope::FunctionScopes;
4use crate::visitor::{VisitWith, Visitor, VisitorMut};
5use crate::{LinearSpan, LinearSpanIgnoreEq, Span, Spanned};
6use crate::{
7 expression::{Expression, Identifier},
8 join_nodes,
9};
10use boa_interner::{Interner, ToIndentedString};
11use core::{fmt::Write as _, ops::ControlFlow};
12
13#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
23#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
24#[derive(Clone, Debug, PartialEq)]
25pub struct AsyncArrowFunction {
26 pub(crate) name: Option<Identifier>,
27 pub(crate) parameters: FormalParameterList,
28 pub(crate) body: FunctionBody,
29 pub(crate) contains_direct_eval: bool,
30
31 #[cfg_attr(feature = "serde", serde(skip))]
32 pub(crate) scopes: FunctionScopes,
33 linear_span: LinearSpanIgnoreEq,
34
35 span: Span,
36}
37
38impl AsyncArrowFunction {
39 #[inline]
41 #[must_use]
42 pub fn new(
43 name: Option<Identifier>,
44 parameters: FormalParameterList,
45 body: FunctionBody,
46 linear_span: LinearSpan,
47 span: Span,
48 ) -> Self {
49 let contains_direct_eval = contains(¶meters, ContainsSymbol::DirectEval)
50 || contains(&body, ContainsSymbol::DirectEval);
51 Self {
52 name,
53 parameters,
54 body,
55 contains_direct_eval,
56 scopes: FunctionScopes::default(),
57 linear_span: linear_span.into(),
58 span,
59 }
60 }
61
62 #[inline]
64 #[must_use]
65 pub const fn name(&self) -> Option<Identifier> {
66 self.name
67 }
68
69 #[inline]
71 pub fn set_name(&mut self, name: Option<Identifier>) {
72 self.name = name;
73 }
74
75 #[inline]
77 #[must_use]
78 pub const fn parameters(&self) -> &FormalParameterList {
79 &self.parameters
80 }
81
82 #[inline]
84 #[must_use]
85 pub const fn body(&self) -> &FunctionBody {
86 &self.body
87 }
88
89 #[inline]
91 #[must_use]
92 pub const fn scopes(&self) -> &FunctionScopes {
93 &self.scopes
94 }
95
96 #[inline]
98 #[must_use]
99 pub const fn linear_span(&self) -> LinearSpan {
100 self.linear_span.0
101 }
102
103 #[inline]
105 #[must_use]
106 pub const fn contains_direct_eval(&self) -> bool {
107 self.contains_direct_eval
108 }
109}
110
111impl Spanned for AsyncArrowFunction {
112 #[inline]
113 fn span(&self) -> Span {
114 self.span
115 }
116}
117
118impl ToIndentedString for AsyncArrowFunction {
119 fn to_indented_string(&self, interner: &Interner, indentation: usize) -> String {
120 let mut buf = format!("async ({}", join_nodes(interner, self.parameters.as_ref()));
121 if self.body().statements().is_empty() {
122 buf.push_str(") => {}");
123 } else {
124 let _ = write!(
125 buf,
126 ") => {{\n{}{}}}",
127 self.body.to_indented_string(interner, indentation + 1),
128 " ".repeat(indentation)
129 );
130 }
131 buf
132 }
133}
134
135impl From<AsyncArrowFunction> for Expression {
136 fn from(decl: AsyncArrowFunction) -> Self {
137 Self::AsyncArrowFunction(decl)
138 }
139}
140
141impl VisitWith for AsyncArrowFunction {
142 fn visit_with<'a, V>(&'a self, visitor: &mut V) -> ControlFlow<V::BreakTy>
143 where
144 V: Visitor<'a>,
145 {
146 if let Some(ident) = &self.name {
147 visitor.visit_identifier(ident)?;
148 }
149 visitor.visit_formal_parameter_list(&self.parameters)?;
150 visitor.visit_function_body(&self.body)
151 }
152
153 fn visit_with_mut<'a, V>(&'a mut self, visitor: &mut V) -> ControlFlow<V::BreakTy>
154 where
155 V: VisitorMut<'a>,
156 {
157 if let Some(ident) = &mut self.name {
158 visitor.visit_identifier_mut(ident)?;
159 }
160 visitor.visit_formal_parameter_list_mut(&mut self.parameters)?;
161 visitor.visit_function_body_mut(&mut self.body)
162 }
163}