Skip to main content

mago_syntax/ast/ast/function_like/
closure.rs

1use 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}