mago_ast/ast/function_like/
closure.rs1use 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}