Skip to main content

mago_syntax/cst/cst/class_like/
member.rs

1use strum::Display;
2
3use mago_span::HasSpan;
4use mago_span::Span;
5
6use crate::cst::Sequence;
7use crate::cst::cst::class_like::constant::ClassLikeConstant;
8use crate::cst::cst::class_like::enum_case::EnumCase;
9use crate::cst::cst::class_like::method::Method;
10use crate::cst::cst::class_like::property::Property;
11use crate::cst::cst::class_like::trait_use::TraitUse;
12use crate::cst::cst::expression::Expression;
13use crate::cst::cst::identifier::LocalIdentifier;
14use crate::cst::cst::variable::Variable;
15
16#[derive(Debug, Clone, Eq, PartialEq, Hash, PartialOrd, Ord, Display)]
17#[cfg_attr(feature = "serde", derive(serde::Serialize))]
18#[cfg_attr(feature = "serde", serde(tag = "type", content = "value"))]
19pub enum ClassLikeMember<'arena> {
20    TraitUse(TraitUse<'arena>),
21    Constant(ClassLikeConstant<'arena>),
22    Property(Property<'arena>),
23    EnumCase(EnumCase<'arena>),
24    Method(Method<'arena>),
25}
26
27#[derive(Debug, Clone, Eq, PartialEq, Hash, PartialOrd, Ord, Display)]
28#[cfg_attr(feature = "serde", derive(serde::Serialize))]
29#[cfg_attr(feature = "serde", serde(tag = "type", content = "value"))]
30pub enum ClassLikeMemberSelector<'arena> {
31    Identifier(LocalIdentifier<'arena>),
32    Variable(Variable<'arena>),
33    Expression(ClassLikeMemberExpressionSelector<'arena>),
34    Missing(Span),
35}
36
37#[derive(Debug, Clone, Eq, PartialEq, Hash, PartialOrd, Ord, Display)]
38#[cfg_attr(feature = "serde", derive(serde::Serialize))]
39#[cfg_attr(feature = "serde", serde(tag = "type", content = "value"))]
40pub enum ClassLikeConstantSelector<'arena> {
41    Identifier(LocalIdentifier<'arena>),
42    Expression(ClassLikeMemberExpressionSelector<'arena>),
43    Missing(Span),
44}
45
46#[derive(Debug, Clone, Eq, PartialEq, Hash, PartialOrd, Ord)]
47#[cfg_attr(feature = "serde", derive(serde::Serialize))]
48pub struct ClassLikeMemberExpressionSelector<'arena> {
49    pub left_brace: Span,
50    pub expression: &'arena Expression<'arena>,
51    pub right_brace: Span,
52}
53
54impl ClassLikeMember<'_> {
55    #[inline]
56    #[must_use]
57    pub const fn is_trait_use(&self) -> bool {
58        matches!(self, ClassLikeMember::TraitUse(_))
59    }
60
61    #[inline]
62    #[must_use]
63    pub const fn is_constant(&self) -> bool {
64        matches!(self, ClassLikeMember::Constant(_))
65    }
66
67    #[inline]
68    #[must_use]
69    pub const fn is_property(&self) -> bool {
70        matches!(self, ClassLikeMember::Property(_))
71    }
72
73    #[inline]
74    #[must_use]
75    pub const fn is_enum_case(&self) -> bool {
76        matches!(self, ClassLikeMember::EnumCase(_))
77    }
78
79    #[inline]
80    #[must_use]
81    pub const fn is_method(&self) -> bool {
82        matches!(self, ClassLikeMember::Method(_))
83    }
84}
85
86impl ClassLikeMemberSelector<'_> {
87    #[inline]
88    #[must_use]
89    pub const fn is_identifier(&self) -> bool {
90        matches!(self, ClassLikeMemberSelector::Identifier(_))
91    }
92
93    #[inline]
94    #[must_use]
95    pub const fn is_variable(&self) -> bool {
96        matches!(self, ClassLikeMemberSelector::Variable(_))
97    }
98
99    #[inline]
100    #[must_use]
101    pub const fn is_expression(&self) -> bool {
102        matches!(self, ClassLikeMemberSelector::Expression(_))
103    }
104
105    #[inline]
106    #[must_use]
107    pub const fn is_missing(&self) -> bool {
108        matches!(self, ClassLikeMemberSelector::Missing(_))
109    }
110}
111
112impl ClassLikeConstantSelector<'_> {
113    #[inline]
114    #[must_use]
115    pub const fn is_identifier(&self) -> bool {
116        matches!(self, ClassLikeConstantSelector::Identifier(_))
117    }
118
119    #[inline]
120    #[must_use]
121    pub const fn is_expression(&self) -> bool {
122        matches!(self, ClassLikeConstantSelector::Expression(_))
123    }
124
125    #[inline]
126    #[must_use]
127    pub const fn is_missing(&self) -> bool {
128        matches!(self, ClassLikeConstantSelector::Missing(_))
129    }
130}
131
132/// Accessors over a class-like member [`Sequence`]. Lives as a trait
133/// because [`Sequence`] is defined in [`mago_syntax_core`]; `use`-import
134/// it to get the methods in scope.
135pub trait ClassLikeMemberSequenceExt<'arena> {
136    fn contains_trait_uses(&self) -> bool;
137    fn contains_constants(&self) -> bool;
138    fn contains_properties(&self) -> bool;
139    fn contains_enum_cases(&self) -> bool;
140    fn contains_methods(&self) -> bool;
141}
142
143impl<'arena> ClassLikeMemberSequenceExt<'arena> for Sequence<'arena, ClassLikeMember<'arena>> {
144    #[inline]
145    fn contains_trait_uses(&self) -> bool {
146        self.iter().any(|member| matches!(member, ClassLikeMember::TraitUse(_)))
147    }
148
149    #[inline]
150    fn contains_constants(&self) -> bool {
151        self.iter().any(|member| matches!(member, ClassLikeMember::Constant(_)))
152    }
153
154    #[inline]
155    fn contains_properties(&self) -> bool {
156        self.iter().any(|member| matches!(member, ClassLikeMember::Property(_)))
157    }
158
159    #[inline]
160    fn contains_enum_cases(&self) -> bool {
161        self.iter().any(|member| matches!(member, ClassLikeMember::EnumCase(_)))
162    }
163
164    #[inline]
165    fn contains_methods(&self) -> bool {
166        self.iter().any(|member| matches!(member, ClassLikeMember::Method(_)))
167    }
168}
169
170impl HasSpan for ClassLikeMember<'_> {
171    fn span(&self) -> Span {
172        match self {
173            ClassLikeMember::TraitUse(trait_use) => trait_use.span(),
174            ClassLikeMember::Constant(constant) => constant.span(),
175            ClassLikeMember::Property(property) => property.span(),
176            ClassLikeMember::EnumCase(enum_case) => enum_case.span(),
177            ClassLikeMember::Method(method) => method.span(),
178        }
179    }
180}
181
182impl HasSpan for ClassLikeMemberSelector<'_> {
183    fn span(&self) -> Span {
184        match self {
185            ClassLikeMemberSelector::Identifier(i) => i.span(),
186            ClassLikeMemberSelector::Variable(v) => v.span(),
187            ClassLikeMemberSelector::Expression(e) => e.span(),
188            ClassLikeMemberSelector::Missing(span) => *span,
189        }
190    }
191}
192
193impl HasSpan for ClassLikeConstantSelector<'_> {
194    fn span(&self) -> Span {
195        match self {
196            ClassLikeConstantSelector::Identifier(i) => i.span(),
197            ClassLikeConstantSelector::Expression(e) => e.span(),
198            ClassLikeConstantSelector::Missing(span) => *span,
199        }
200    }
201}
202
203impl HasSpan for ClassLikeMemberExpressionSelector<'_> {
204    fn span(&self) -> Span {
205        self.left_brace.join(self.right_brace)
206    }
207}