mago_syntax/ast/ast/function_like/
closure.rs1use serde::Serialize;
2
3use mago_span::HasSpan;
4use mago_span::Span;
5
6use crate::ast::ast::attribute::AttributeList;
7use crate::ast::ast::block::Block;
8use crate::ast::ast::function_like::parameter::FunctionLikeParameterList;
9use crate::ast::ast::function_like::r#return::FunctionLikeReturnTypeHint;
10use crate::ast::ast::keyword::Keyword;
11use crate::ast::ast::variable::DirectVariable;
12use crate::ast::sequence::Sequence;
13use crate::ast::sequence::TokenSeparatedSequence;
14
15#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, PartialOrd, Ord)]
16pub struct Closure<'arena> {
17 pub attribute_lists: Sequence<'arena, AttributeList<'arena>>,
18 pub r#static: Option<Keyword<'arena>>,
19 pub function: Keyword<'arena>,
20 pub ampersand: Option<Span>,
21 pub parameter_list: FunctionLikeParameterList<'arena>,
22 pub use_clause: Option<ClosureUseClause<'arena>>,
23 pub return_type_hint: Option<FunctionLikeReturnTypeHint<'arena>>,
24 pub body: Block<'arena>,
25}
26
27#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, PartialOrd, Ord)]
28pub struct ClosureUseClause<'arena> {
29 pub r#use: Keyword<'arena>,
30 pub left_parenthesis: Span,
31 pub variables: TokenSeparatedSequence<'arena, ClosureUseClauseVariable<'arena>>,
32 pub right_parenthesis: Span,
33}
34
35#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, PartialOrd, Ord)]
36pub struct ClosureUseClauseVariable<'arena> {
37 pub ampersand: Option<Span>,
38 pub variable: DirectVariable<'arena>,
39}
40
41impl HasSpan for Closure<'_> {
42 fn span(&self) -> Span {
43 if let Some(attribute_list) = self.attribute_lists.first() {
44 return attribute_list.span().join(self.body.span());
45 }
46
47 if let Some(r#static) = &self.r#static {
48 return r#static.span().join(self.body.span());
49 }
50
51 self.function.span.join(self.body.span())
52 }
53}
54
55impl HasSpan for ClosureUseClause<'_> {
56 fn span(&self) -> Span {
57 Span::between(self.r#use.span(), self.right_parenthesis)
58 }
59}
60
61impl HasSpan for ClosureUseClauseVariable<'_> {
62 fn span(&self) -> Span {
63 if let Some(ampersand) = self.ampersand {
64 Span::between(ampersand, self.variable.span())
65 } else {
66 self.variable.span()
67 }
68 }
69}