diff options
Diffstat (limited to 'src/parser/clang/entities.rs')
-rw-r--r-- | src/parser/clang/entities.rs | 390 |
1 files changed, 390 insertions, 0 deletions
diff --git a/src/parser/clang/entities.rs b/src/parser/clang/entities.rs new file mode 100644 index 0000000..41fe061 --- /dev/null +++ b/src/parser/clang/entities.rs | |||
@@ -0,0 +1,390 @@ | |||
1 | use crate::types::*; | ||
2 | |||
3 | use clang::{EntityKind, Usr}; | ||
4 | use thiserror::Error; | ||
5 | |||
6 | use std::collections::BTreeMap; | ||
7 | use std::convert::TryFrom; | ||
8 | |||
9 | // TODO: factor out hardcoded strings | ||
10 | |||
11 | #[derive(Debug)] | ||
12 | pub(super) struct Children { | ||
13 | namespaces: Option<BTreeMap<Usr, Described<Namespace>>>, | ||
14 | variables: Option<BTreeMap<Usr, Described<Variable>>>, | ||
15 | structs: Option<BTreeMap<Usr, Described<Struct>>>, | ||
16 | functions: Option<BTreeMap<Usr, Described<Function>>>, | ||
17 | } | ||
18 | |||
19 | #[derive(Debug, Clone, Copy, PartialEq, Eq)] | ||
20 | pub(super) enum ClangEntityKind { | ||
21 | Namespace, | ||
22 | Variable(VariableKind), | ||
23 | Struct(StructKind), | ||
24 | Function(FunctionKind), | ||
25 | } | ||
26 | |||
27 | #[derive(Debug, Clone, Copy, PartialEq, Eq)] | ||
28 | pub(super) enum VariableKind { | ||
29 | Variable, | ||
30 | Field, | ||
31 | } | ||
32 | |||
33 | #[derive(Debug, Clone, Copy, PartialEq, Eq)] | ||
34 | pub(super) enum StructKind { | ||
35 | Struct, | ||
36 | Class, | ||
37 | } | ||
38 | |||
39 | #[derive(Debug, Clone, Copy, PartialEq, Eq)] | ||
40 | pub(super) enum FunctionKind { | ||
41 | Function, | ||
42 | Method, | ||
43 | } | ||
44 | |||
45 | impl ClangEntityKind { | ||
46 | fn to_str_singular(self) -> &'static str { | ||
47 | match self { | ||
48 | ClangEntityKind::Namespace => "namespace", | ||
49 | ClangEntityKind::Variable(VariableKind::Variable) => "variable", | ||
50 | ClangEntityKind::Variable(VariableKind::Field) => "field", | ||
51 | ClangEntityKind::Struct(StructKind::Struct) => "struct", | ||
52 | ClangEntityKind::Struct(StructKind::Class) => "class", | ||
53 | ClangEntityKind::Function(FunctionKind::Function) => "function", | ||
54 | ClangEntityKind::Function(FunctionKind::Method) => "method", | ||
55 | } | ||
56 | } | ||
57 | |||
58 | fn to_str_plural(self) -> &'static str { | ||
59 | match self { | ||
60 | ClangEntityKind::Namespace => "namespaces", | ||
61 | ClangEntityKind::Variable(VariableKind::Variable) => "variables", | ||
62 | ClangEntityKind::Variable(VariableKind::Field) => "fields", | ||
63 | ClangEntityKind::Struct(StructKind::Struct) => "structs", | ||
64 | ClangEntityKind::Struct(StructKind::Class) => "classes", | ||
65 | ClangEntityKind::Function(FunctionKind::Function) => "functions", | ||
66 | ClangEntityKind::Function(FunctionKind::Method) => "methods", | ||
67 | } | ||
68 | } | ||
69 | } | ||
70 | |||
71 | #[derive(Debug, Error)] | ||
72 | #[error("Unsupported Clang entity kind: {:?}", _0)] | ||
73 | pub(super) struct TryFromEntityKindError(String); | ||
74 | |||
75 | impl TryFrom<EntityKind> for ClangEntityKind { | ||
76 | type Error = TryFromEntityKindError; | ||
77 | |||
78 | fn try_from(kind: EntityKind) -> Result<ClangEntityKind, TryFromEntityKindError> { | ||
79 | Ok(match kind { | ||
80 | EntityKind::Namespace => ClangEntityKind::Namespace, | ||
81 | EntityKind::VarDecl => ClangEntityKind::Variable(VariableKind::Variable), | ||
82 | EntityKind::FieldDecl => ClangEntityKind::Variable(VariableKind::Field), | ||
83 | EntityKind::FunctionDecl => ClangEntityKind::Function(FunctionKind::Function), | ||
84 | EntityKind::Method | EntityKind::Constructor => { | ||
85 | ClangEntityKind::Function(FunctionKind::Method) | ||
86 | } | ||
87 | EntityKind::StructDecl => ClangEntityKind::Struct(StructKind::Struct), | ||
88 | EntityKind::ClassDecl => ClangEntityKind::Struct(StructKind::Class), | ||
89 | kind => return Err(TryFromEntityKindError(format!("{:?}", kind))), | ||
90 | }) | ||
91 | } | ||
92 | } | ||
93 | |||
94 | pub(super) trait ClangEntity { | ||
95 | fn kind(&self) -> ClangEntityKind; | ||
96 | |||
97 | fn get_member_namespaces(&mut self) -> Option<&mut BTreeMap<Usr, Described<Namespace>>> { | ||
98 | None | ||
99 | } | ||
100 | fn get_member_variables(&mut self) -> Option<&mut BTreeMap<Usr, Described<Variable>>> { | ||
101 | None | ||
102 | } | ||
103 | fn get_member_structs(&mut self) -> Option<&mut BTreeMap<Usr, Described<Struct>>> { | ||
104 | None | ||
105 | } | ||
106 | fn get_member_functions(&mut self) -> Option<&mut BTreeMap<Usr, Described<Function>>> { | ||
107 | None | ||
108 | } | ||
109 | |||
110 | fn into_children(self) -> Children | ||
111 | where | ||
112 | Self: Sized, | ||
113 | { | ||
114 | Children { | ||
115 | namespaces: None, | ||
116 | variables: None, | ||
117 | structs: None, | ||
118 | functions: None, | ||
119 | } | ||
120 | } | ||
121 | } | ||
122 | |||
123 | /* | ||
124 | pub(super) trait FromNamespaceParent: ClangEntity + Sized { | ||
125 | fn from_namespace_parent<'a>( | ||
126 | parent: &'a mut Described<Namespace>, | ||
127 | name: &Usr, | ||
128 | ) -> Option<&'a mut Described<Self>>; | ||
129 | } | ||
130 | */ | ||
131 | |||
132 | pub(super) trait NamespaceParentManipulation<T: ClangEntity + Sized> { | ||
133 | fn get_members_mut(&mut self) -> Option<&mut BTreeMap<Usr, Described<T>>>; | ||
134 | } | ||
135 | |||
136 | impl<U> NamespaceParentManipulation<Namespace> for U | ||
137 | where | ||
138 | U: ClangEntity, | ||
139 | { | ||
140 | fn get_members_mut(&mut self) -> Option<&mut BTreeMap<Usr, Described<Namespace>>> { | ||
141 | self.get_member_namespaces() | ||
142 | } | ||
143 | } | ||
144 | |||
145 | impl<U> NamespaceParentManipulation<Variable> for U | ||
146 | where | ||
147 | U: ClangEntity, | ||
148 | { | ||
149 | fn get_members_mut(&mut self) -> Option<&mut BTreeMap<Usr, Described<Variable>>> { | ||
150 | self.get_member_variables() | ||
151 | } | ||
152 | } | ||
153 | |||
154 | impl<U> NamespaceParentManipulation<Function> for U | ||
155 | where | ||
156 | U: ClangEntity, | ||
157 | { | ||
158 | fn get_members_mut(&mut self) -> Option<&mut BTreeMap<Usr, Described<Function>>> { | ||
159 | self.get_member_functions() | ||
160 | } | ||
161 | } | ||
162 | |||
163 | impl<U> NamespaceParentManipulation<Struct> for U | ||
164 | where | ||
165 | U: ClangEntity, | ||
166 | { | ||
167 | fn get_members_mut(&mut self) -> Option<&mut BTreeMap<Usr, Described<Struct>>> { | ||
168 | self.get_member_structs() | ||
169 | } | ||
170 | } | ||
171 | |||
172 | impl<T: ClangEntity> From<Described<T>> for Entity { | ||
173 | fn from(entity: Described<T>) -> Self { | ||
174 | let mut children: BTreeMap<ChildrenKind, BTreeMap<EntityId, Entity>> = BTreeMap::new(); | ||
175 | |||
176 | let kind = EntityKind(String::from(entity.entity.kind().to_str_singular())); | ||
177 | let clang_children = entity.entity.into_children(); | ||
178 | |||
179 | if let Some(namespaces) = clang_children.namespaces { | ||
180 | for (usr, namespace) in namespaces { | ||
181 | children | ||
182 | .entry(ChildrenKind(String::from( | ||
183 | namespace.entity.kind().to_str_plural(), | ||
184 | ))) | ||
185 | .or_default() | ||
186 | .insert(EntityId(usr.0), namespace.into()); | ||
187 | } | ||
188 | } | ||
189 | |||
190 | if let Some(variables) = clang_children.variables { | ||
191 | for (usr, variable) in variables { | ||
192 | children | ||
193 | .entry(ChildrenKind(String::from( | ||
194 | variable.entity.kind().to_str_plural(), | ||
195 | ))) | ||
196 | .or_default() | ||
197 | .insert(EntityId(usr.0), variable.into()); | ||
198 | } | ||
199 | } | ||
200 | |||
201 | if let Some(structs) = clang_children.structs { | ||
202 | for (usr, r#struct) in structs { | ||
203 | children | ||
204 | .entry(ChildrenKind(String::from( | ||
205 | r#struct.entity.kind().to_str_plural(), | ||
206 | ))) | ||
207 | .or_default() | ||
208 | .insert(EntityId(usr.0), r#struct.into()); | ||
209 | } | ||
210 | } | ||
211 | |||
212 | if let Some(functions) = clang_children.functions { | ||
213 | for (usr, function) in functions { | ||
214 | children | ||
215 | .entry(ChildrenKind(String::from( | ||
216 | function.entity.kind().to_str_plural(), | ||
217 | ))) | ||
218 | .or_default() | ||
219 | .insert(EntityId(usr.0), function.into()); | ||
220 | } | ||
221 | } | ||
222 | |||
223 | Entity { | ||
224 | name: entity.description.name, | ||
225 | language: Language::Clang, | ||
226 | kind, | ||
227 | brief_description: entity.description.brief, | ||
228 | documentation: entity.description.detailed, | ||
229 | children, | ||
230 | } | ||
231 | } | ||
232 | } | ||
233 | |||
234 | #[derive(Debug, Clone, Default)] | ||
235 | pub(super) struct Description { | ||
236 | pub(super) name: String, | ||
237 | pub(super) brief: String, | ||
238 | pub(super) detailed: String, | ||
239 | } | ||
240 | |||
241 | #[derive(Debug, Clone)] | ||
242 | pub(super) struct Described<T> { | ||
243 | pub(super) description: Description, | ||
244 | pub(super) entity: T, | ||
245 | } | ||
246 | |||
247 | #[derive(Debug, Clone)] | ||
248 | pub(super) struct Namespace { | ||
249 | pub(super) member_namespaces: BTreeMap<Usr, Described<Namespace>>, | ||
250 | pub(super) member_variables: BTreeMap<Usr, Described<Variable>>, | ||
251 | pub(super) member_structs: BTreeMap<Usr, Described<Struct>>, | ||
252 | pub(super) member_functions: BTreeMap<Usr, Described<Function>>, | ||
253 | } | ||
254 | |||
255 | impl ClangEntity for Namespace { | ||
256 | fn kind(&self) -> ClangEntityKind { | ||
257 | ClangEntityKind::Namespace | ||
258 | } | ||
259 | |||
260 | fn get_member_namespaces(&mut self) -> Option<&mut BTreeMap<Usr, Described<Namespace>>> { | ||
261 | Some(&mut self.member_namespaces) | ||
262 | } | ||
263 | fn get_member_variables(&mut self) -> Option<&mut BTreeMap<Usr, Described<Variable>>> { | ||
264 | Some(&mut self.member_variables) | ||
265 | } | ||
266 | fn get_member_structs(&mut self) -> Option<&mut BTreeMap<Usr, Described<Struct>>> { | ||
267 | Some(&mut self.member_structs) | ||
268 | } | ||
269 | fn get_member_functions(&mut self) -> Option<&mut BTreeMap<Usr, Described<Function>>> { | ||
270 | Some(&mut self.member_functions) | ||
271 | } | ||
272 | |||
273 | fn into_children(self) -> Children { | ||
274 | Children { | ||
275 | namespaces: Some(self.member_namespaces), | ||
276 | variables: Some(self.member_variables), | ||
277 | structs: Some(self.member_structs), | ||
278 | functions: Some(self.member_functions), | ||
279 | } | ||
280 | } | ||
281 | } | ||
282 | |||
283 | /* | ||
284 | impl FromNamespaceParent for Namespace { | ||
285 | fn from_namespace_parent<'a>( | ||
286 | parent: &'a mut Described<Namespace>, | ||
287 | name: &Usr, | ||
288 | ) -> Option<&'a mut Described<Self>> { | ||
289 | parent.entity.member_namespaces.get_mut(name) | ||
290 | } | ||
291 | } | ||
292 | */ | ||
293 | |||
294 | #[derive(Debug, Clone)] | ||
295 | pub(super) struct Variable { | ||
296 | pub(super) kind: VariableKind, | ||
297 | pub(super) r#type: String, | ||
298 | } | ||
299 | |||
300 | impl ClangEntity for Variable { | ||
301 | fn kind(&self) -> ClangEntityKind { | ||
302 | ClangEntityKind::Variable(self.kind) | ||
303 | } | ||
304 | } | ||
305 | |||
306 | /* | ||
307 | impl FromNamespaceParent for Variable { | ||
308 | fn from_namespace_parent<'a>( | ||
309 | parent: &'a mut Described<Namespace>, | ||
310 | name: &Usr, | ||
311 | ) -> Option<&'a mut Described<Self>> { | ||
312 | parent.entity.member_variables.get_mut(name) | ||
313 | } | ||
314 | } | ||
315 | */ | ||
316 | |||
317 | #[derive(Debug, Clone)] | ||
318 | pub(super) struct Struct { | ||
319 | //pub(super) member_types: Vec<Usr>, | ||
320 | pub(super) kind: StructKind, | ||
321 | pub(super) member_variables: BTreeMap<Usr, Described<Variable>>, | ||
322 | pub(super) member_structs: BTreeMap<Usr, Described<Struct>>, | ||
323 | pub(super) member_functions: BTreeMap<Usr, Described<Function>>, | ||
324 | } | ||
325 | |||
326 | impl ClangEntity for Struct { | ||
327 | fn kind(&self) -> ClangEntityKind { | ||
328 | ClangEntityKind::Struct(self.kind) | ||
329 | } | ||
330 | |||
331 | fn get_member_variables(&mut self) -> Option<&mut BTreeMap<Usr, Described<Variable>>> { | ||
332 | Some(&mut self.member_variables) | ||
333 | } | ||
334 | fn get_member_structs(&mut self) -> Option<&mut BTreeMap<Usr, Described<Struct>>> { | ||
335 | Some(&mut self.member_structs) | ||
336 | } | ||
337 | fn get_member_functions(&mut self) -> Option<&mut BTreeMap<Usr, Described<Function>>> { | ||
338 | Some(&mut self.member_functions) | ||
339 | } | ||
340 | |||
341 | fn into_children(self) -> Children { | ||
342 | Children { | ||
343 | namespaces: None, | ||
344 | variables: Some(self.member_variables), | ||
345 | structs: Some(self.member_structs), | ||
346 | functions: Some(self.member_functions), | ||
347 | } | ||
348 | } | ||
349 | } | ||
350 | |||
351 | /* | ||
352 | impl FromNamespaceParent for Struct { | ||
353 | fn from_namespace_parent<'a>( | ||
354 | parent: &'a mut Described<Namespace>, | ||
355 | name: &Usr, | ||
356 | ) -> Option<&'a mut Described<Self>> { | ||
357 | parent.entity.member_structs.get_mut(name) | ||
358 | } | ||
359 | } | ||
360 | */ | ||
361 | |||
362 | #[derive(Debug, Clone)] | ||
363 | pub(super) struct Function { | ||
364 | pub(super) kind: FunctionKind, | ||
365 | pub(super) arguments: Vec<FunctionArgument>, | ||
366 | pub(super) return_type: String, | ||
367 | } | ||
368 | |||
369 | impl ClangEntity for Function { | ||
370 | fn kind(&self) -> ClangEntityKind { | ||
371 | ClangEntityKind::Function(self.kind) | ||
372 | } | ||
373 | } | ||
374 | |||
375 | /* | ||
376 | impl FromNamespaceParent for Function { | ||
377 | fn from_namespace_parent<'a>( | ||
378 | parent: &'a mut Described<Namespace>, | ||
379 | name: &Usr, | ||
380 | ) -> Option<&'a mut Described<Self>> { | ||
381 | parent.entity.member_functions.get_mut(name) | ||
382 | } | ||
383 | } | ||
384 | */ | ||
385 | |||
386 | #[derive(Debug, Clone)] | ||
387 | pub(super) struct FunctionArgument { | ||
388 | pub(super) name: String, | ||
389 | pub(super) r#type: String, | ||
390 | } | ||