mago_ast/ast/function_like/
closure.rs

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