mago_syntax/ast/ast/class_like/
method.rs1use serde::Deserialize;
2use serde::Serialize;
3use strum::Display;
4
5use mago_span::HasSpan;
6use mago_span::Span;
7
8use crate::ast::ast::attribute::AttributeList;
9use crate::ast::ast::block::Block;
10use crate::ast::ast::function_like::parameter::FunctionLikeParameterList;
11use crate::ast::ast::function_like::r#return::FunctionLikeReturnTypeHint;
12use crate::ast::ast::identifier::LocalIdentifier;
13use crate::ast::ast::keyword::Keyword;
14use crate::ast::ast::modifier::Modifier;
15use crate::ast::sequence::Sequence;
16
17#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, Deserialize, PartialOrd, Ord)]
29#[repr(C)]
30pub struct Method {
31 pub attribute_lists: Sequence<AttributeList>,
32 pub modifiers: Sequence<Modifier>,
33 pub function: Keyword,
34 pub ampersand: Option<Span>,
35 pub name: LocalIdentifier,
36 pub parameter_list: FunctionLikeParameterList,
37 pub return_type_hint: Option<FunctionLikeReturnTypeHint>,
38 pub body: MethodBody,
39}
40
41#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, Deserialize, PartialOrd, Ord, Display)]
43#[serde(tag = "type", content = "value")]
44#[repr(C, u8)]
45pub enum MethodBody {
46 Abstract(MethodAbstractBody),
47 Concrete(Block),
48}
49
50#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, Deserialize, PartialOrd, Ord)]
63#[repr(C)]
64pub struct MethodAbstractBody {
65 pub semicolon: Span,
66}
67
68impl Method {
69 pub fn has_promoted_properties(&self) -> bool {
71 self.parameter_list.parameters.iter().any(|parameter| parameter.is_promoted_property())
72 }
73
74 #[inline]
76 pub const fn is_abstract(&self) -> bool {
77 matches!(self.body, MethodBody::Abstract(_))
78 }
79}
80
81impl HasSpan for Method {
82 fn span(&self) -> Span {
83 if let Some(attribute_list) = self.attribute_lists.first() {
84 return Span::between(attribute_list.span(), self.body.span());
85 }
86
87 if let Some(modifier) = self.modifiers.first() {
88 return Span::between(modifier.span(), self.body.span());
89 }
90
91 Span::between(self.function.span, self.body.span())
92 }
93}
94
95impl HasSpan for MethodBody {
96 fn span(&self) -> Span {
97 match self {
98 MethodBody::Abstract(body) => body.span(),
99 MethodBody::Concrete(body) => body.span(),
100 }
101 }
102}
103
104impl HasSpan for MethodAbstractBody {
105 fn span(&self) -> Span {
106 self.semicolon
107 }
108}