swift_demangler/
constructor.rs1use crate::context::{SymbolContext, extract_context};
6use crate::helpers::{
7 HasExtensionContext, HasFunctionSignature, HasGenericSignature, HasModule, NodeExt,
8};
9use crate::raw::{Node, NodeKind};
10use crate::types::{FunctionType, GenericSignature, TypeRef};
11
12#[derive(Clone, Copy)]
14pub struct Constructor<'ctx> {
15 raw: Node<'ctx>,
16}
17
18impl<'ctx> Constructor<'ctx> {
19 pub fn new(raw: Node<'ctx>) -> Self {
21 Self { raw }
22 }
23
24 pub fn raw(&self) -> Node<'ctx> {
26 self.raw
27 }
28
29 pub fn context(&self) -> SymbolContext<'ctx> {
31 extract_context(self.raw)
32 }
33
34 pub fn kind(&self) -> ConstructorKind {
36 match self.raw.kind() {
37 NodeKind::Allocator => ConstructorKind::Allocating,
38 NodeKind::Constructor => ConstructorKind::Regular,
39 _ => ConstructorKind::Regular,
40 }
41 }
42
43 pub fn containing_type(&self) -> Option<&'ctx str> {
45 self.raw.find_containing_type()
46 }
47
48 pub fn containing_type_is_class(&self) -> bool {
50 self.raw.containing_type_is_class()
51 }
52
53 pub fn containing_type_is_protocol(&self) -> bool {
55 self.raw.containing_type_is_protocol()
56 }
57
58 pub fn labels(&self) -> Vec<Option<&'ctx str>> {
60 self.raw.extract_labels()
61 }
62
63 pub fn is_failable(&self) -> bool {
65 if let Some(sig) = self.signature() {
66 if let Some(ret) = sig.return_type() {
67 matches!(ret.kind(), crate::types::TypeKind::Optional(_))
69 } else {
70 false
71 }
72 } else {
73 false
74 }
75 }
76}
77
78impl<'ctx> HasGenericSignature<'ctx> for Constructor<'ctx> {
79 fn generic_signature(&self) -> Option<GenericSignature<'ctx>> {
80 self.raw.find_generic_signature()
81 }
82}
83
84impl<'ctx> HasFunctionSignature<'ctx> for Constructor<'ctx> {
85 fn signature(&self) -> Option<FunctionType<'ctx>> {
86 self.raw.find_function_type()
87 }
88}
89
90impl<'ctx> HasExtensionContext<'ctx> for Constructor<'ctx> {
91 fn raw(&self) -> Node<'ctx> {
92 self.raw
93 }
94}
95
96impl<'ctx> HasModule<'ctx> for Constructor<'ctx> {
97 fn module(&self) -> Option<&'ctx str> {
98 self.raw.find_module()
99 }
100}
101
102impl std::fmt::Debug for Constructor<'_> {
103 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
104 let mut s = f.debug_struct("Constructor");
105 s.field("kind", &self.kind())
106 .field("containing_type", &self.containing_type())
107 .field("module", &self.module())
108 .field("labels", &self.labels())
109 .field("is_async", &self.is_async())
110 .field("is_throwing", &self.is_throwing())
111 .field("is_failable", &self.is_failable())
112 .field("is_extension", &self.is_extension())
113 .field("is_generic", &self.is_generic());
114 if let Some(sig) = self.signature() {
115 s.field("signature", &sig);
116 }
117 if self.is_extension() {
118 s.field("extension_module", &self.extension_module());
119 let ext_requirements = self.extension_generic_requirements();
120 if !ext_requirements.is_empty() {
121 s.field("extension_generic_requirements", &ext_requirements);
122 }
123 }
124 let requirements = self.generic_requirements();
125 if !requirements.is_empty() {
126 s.field("generic_requirements", &requirements);
127 }
128 s.finish()
129 }
130}
131
132impl std::fmt::Display for Constructor<'_> {
133 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
134 write!(f, "{}", self.raw)
135 }
136}
137
138#[derive(Debug, Clone, Copy, PartialEq, Eq)]
140pub enum ConstructorKind {
141 Regular,
143 Allocating,
145}
146
147#[derive(Clone, Copy)]
149pub struct Destructor<'ctx> {
150 raw: Node<'ctx>,
151}
152
153impl<'ctx> Destructor<'ctx> {
154 pub fn new(raw: Node<'ctx>) -> Self {
156 Self { raw }
157 }
158
159 pub fn raw(&self) -> Node<'ctx> {
161 self.raw
162 }
163
164 pub fn context(&self) -> SymbolContext<'ctx> {
166 extract_context(self.raw)
167 }
168
169 pub fn kind(&self) -> DestructorKind {
171 match self.raw.kind() {
172 NodeKind::Deallocator => DestructorKind::Deallocating,
173 NodeKind::IsolatedDeallocator => DestructorKind::IsolatedDeallocating,
174 NodeKind::Destructor => DestructorKind::Regular,
175 _ => DestructorKind::Regular,
176 }
177 }
178
179 pub fn containing_type(&self) -> Option<&'ctx str> {
181 self.raw.find_containing_type()
182 }
183
184 pub fn containing_type_is_class(&self) -> bool {
186 self.raw.containing_type_is_class()
187 }
188
189 pub fn containing_type_is_protocol(&self) -> bool {
191 self.raw.containing_type_is_protocol()
192 }
193
194 pub fn destroyed_type(&self) -> Option<TypeRef<'ctx>> {
196 for child in self.raw.children() {
197 match child.kind() {
198 NodeKind::Class | NodeKind::Structure | NodeKind::Enum => {
199 return Some(TypeRef::new(child));
200 }
201 _ => {}
202 }
203 }
204 None
205 }
206}
207
208impl<'ctx> HasModule<'ctx> for Destructor<'ctx> {
209 fn module(&self) -> Option<&'ctx str> {
210 self.raw.find_module()
211 }
212}
213
214impl std::fmt::Debug for Destructor<'_> {
215 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
216 f.debug_struct("Destructor")
217 .field("kind", &self.kind())
218 .field("containing_type", &self.containing_type())
219 .field("module", &self.module())
220 .finish()
221 }
222}
223
224impl std::fmt::Display for Destructor<'_> {
225 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
226 write!(f, "{}", self.raw)
227 }
228}
229
230#[derive(Debug, Clone, Copy, PartialEq, Eq)]
232pub enum DestructorKind {
233 Regular,
235 Deallocating,
237 IsolatedDeallocating,
239}
240
241#[cfg(test)]
242mod tests {
243 use super::*;
244
245 #[test]
246 fn test_constructor_kind() {
247 assert_eq!(ConstructorKind::Regular, ConstructorKind::Regular);
248 assert_ne!(ConstructorKind::Regular, ConstructorKind::Allocating);
249 }
250
251 #[test]
252 fn test_destructor_kind() {
253 assert_eq!(DestructorKind::Regular, DestructorKind::Regular);
254 assert_ne!(DestructorKind::Regular, DestructorKind::Deallocating);
255 }
256
257 }