1use serde::Deserialize;
2use serde::Serialize;
3use strum::Display;
4
5use mago_span::HasSpan;
6use mago_span::Span;
7
8use crate::ast::identifier::Identifier;
9use crate::ast::identifier::LocalIdentifier;
10use crate::ast::keyword::Keyword;
11use crate::ast::modifier::Modifier;
12use crate::ast::terminator::Terminator;
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 TraitUse {
19 pub r#use: Keyword,
20 pub trait_names: TokenSeparatedSequence<Identifier>,
21 pub specification: TraitUseSpecification,
22}
23
24#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, Deserialize, PartialOrd, Ord, Display)]
25#[serde(tag = "type", content = "value")]
26#[repr(C, u8)]
27pub enum TraitUseSpecification {
28 Abstract(TraitUseAbstractSpecification),
29 Concrete(TraitUseConcreteSpecification),
30}
31
32#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, Deserialize, PartialOrd, Ord)]
33#[repr(C)]
34pub struct TraitUseAbstractSpecification(pub Terminator);
35
36#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, Deserialize, PartialOrd, Ord)]
37#[repr(C)]
38pub struct TraitUseConcreteSpecification {
39 pub left_brace: Span,
40 pub adaptations: Sequence<TraitUseAdaptation>,
41 pub right_brace: Span,
42}
43
44#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, Deserialize, PartialOrd, Ord, Display)]
45#[serde(tag = "type", content = "value")]
46#[repr(C, u8)]
47pub enum TraitUseAdaptation {
48 Precedence(TraitUsePrecedenceAdaptation),
49 Alias(TraitUseAliasAdaptation),
50}
51
52#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, Deserialize, PartialOrd, Ord)]
53#[repr(C)]
54pub struct TraitUsePrecedenceAdaptation {
55 pub method_reference: TraitUseAbsoluteMethodReference,
56 pub insteadof: Keyword,
57 pub trait_names: TokenSeparatedSequence<Identifier>,
58 pub terminator: Terminator,
59}
60
61#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, Deserialize, PartialOrd, Ord)]
62#[repr(C)]
63pub struct TraitUseAliasAdaptation {
64 pub method_reference: TraitUseMethodReference,
65 pub r#as: Keyword,
66 pub visibility: Option<Modifier>,
67 pub alias: Option<LocalIdentifier>,
68 pub terminator: Terminator,
69}
70
71#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, Deserialize, PartialOrd, Ord, Display)]
72#[serde(tag = "type", content = "value")]
73#[repr(C, u8)]
74pub enum TraitUseMethodReference {
75 Identifier(LocalIdentifier),
76 Absolute(TraitUseAbsoluteMethodReference),
77}
78
79#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, Deserialize, PartialOrd, Ord)]
80#[repr(C)]
81pub struct TraitUseAbsoluteMethodReference {
82 pub trait_name: Identifier,
83 pub double_colon: Span,
84 pub method_name: LocalIdentifier,
85}
86
87impl HasSpan for TraitUse {
88 fn span(&self) -> Span {
89 Span::between(self.r#use.span(), self.specification.span())
90 }
91}
92
93impl HasSpan for TraitUseSpecification {
94 fn span(&self) -> Span {
95 match self {
96 TraitUseSpecification::Abstract(specification) => specification.span(),
97 TraitUseSpecification::Concrete(specification) => specification.span(),
98 }
99 }
100}
101
102impl HasSpan for TraitUseAbstractSpecification {
103 fn span(&self) -> Span {
104 self.0.span()
105 }
106}
107
108impl HasSpan for TraitUseConcreteSpecification {
109 fn span(&self) -> Span {
110 Span::between(self.left_brace, self.right_brace)
111 }
112}
113
114impl HasSpan for TraitUseAdaptation {
115 fn span(&self) -> Span {
116 match self {
117 TraitUseAdaptation::Precedence(adaptation) => adaptation.span(),
118 TraitUseAdaptation::Alias(adaptation) => adaptation.span(),
119 }
120 }
121}
122
123impl HasSpan for TraitUsePrecedenceAdaptation {
124 fn span(&self) -> Span {
125 Span::between(self.method_reference.span(), self.terminator.span())
126 }
127}
128
129impl HasSpan for TraitUseAliasAdaptation {
130 fn span(&self) -> Span {
131 self.method_reference.span().join(self.terminator.span())
132 }
133}
134
135impl HasSpan for TraitUseMethodReference {
136 fn span(&self) -> Span {
137 match self {
138 TraitUseMethodReference::Identifier(identifier) => identifier.span(),
139 TraitUseMethodReference::Absolute(absolute) => absolute.span(),
140 }
141 }
142}
143
144impl HasSpan for TraitUseAbsoluteMethodReference {
145 fn span(&self) -> Span {
146 Span::between(self.trait_name.span(), self.method_name.span())
147 }
148}