summaryrefslogtreecommitdiffstats
path: root/src/parser/clang/entities.rs
diff options
context:
space:
mode:
authorMinijackson <minijackson@riseup.net>2020-02-23 17:01:14 +0100
committerMinijackson <minijackson@riseup.net>2020-02-23 17:01:14 +0100
commit5b137e8bb767aa2b381e9d5a0710583c4edaa889 (patch)
treeb732d1071bffda7b9d54aaa5ebeb0122890a750a /src/parser/clang/entities.rs
parent5a83e2b55b672042562601866ed0253613c5e8b8 (diff)
downloadposeidoc-5b137e8bb767aa2b381e9d5a0710583c4edaa889.tar.gz
poseidoc-5b137e8bb767aa2b381e9d5a0710583c4edaa889.zip
Big clang refactoring
- Manipulating the entity tree should be much nicer: - "Typesafe type erasure" - Entry API for the tree - *NOT clang specific*: There is now a single entity at the top of the tree: the global namespace scope for the case of C/C++
Diffstat (limited to 'src/parser/clang/entities.rs')
-rw-r--r--src/parser/clang/entities.rs1477
1 files changed, 1106 insertions, 371 deletions
diff --git a/src/parser/clang/entities.rs b/src/parser/clang/entities.rs
index 0e9305b..b1689aa 100644
--- a/src/parser/clang/entities.rs
+++ b/src/parser/clang/entities.rs
@@ -1,541 +1,1276 @@
1use crate::types::{self, *}; 1use crate::types;
2 2
3use clang::{EntityKind, Usr}; 3use anyhow::{anyhow, Error, Result};
4use serde_json::{Map, Value as JSONValue}; 4use clang::Usr;
5use serde_json::{json, Map as JSONMap, Value as JSONValue};
5use thiserror::Error; 6use thiserror::Error;
6 7
7use std::collections::BTreeMap; 8use std::collections::BTreeMap;
8use std::convert::TryFrom; 9use std::convert::{TryFrom, TryInto};
9
10// TODO: factor out hardcoded strings
11 10
12#[derive(Debug, Clone, Copy, PartialEq, Eq)] 11#[derive(Debug, Clone, Copy, PartialEq, Eq)]
13pub(super) enum ClangEntityKind { 12pub(super) enum EntityKind {
14 Namespace, 13 Namespace,
15 Variable(VariableKind),
16 Struct(StructKind),
17 Function(FunctionKind),
18 Typedef,
19 Enum,
20 EnumConstant,
21}
22
23#[derive(Debug, Clone, Copy, PartialEq, Eq)]
24pub(super) enum VariableKind {
25 Variable, 14 Variable,
26 Field,
27}
28
29#[derive(Debug, Clone, Copy, PartialEq, Eq)]
30pub(super) enum StructKind {
31 Struct, 15 Struct,
32 Class,
33}
34
35#[derive(Debug, Clone, Copy, PartialEq, Eq)]
36pub(super) enum FunctionKind {
37 Function, 16 Function,
38 Method, 17 Enum,
39} 18 EnumConstant,
40 19 TypeAlias,
41impl ClangEntityKind {
42 fn to_str_singular(self) -> &'static str {
43 match self {
44 ClangEntityKind::Namespace => "namespace",
45 ClangEntityKind::Variable(VariableKind::Variable) => "variable",
46 ClangEntityKind::Variable(VariableKind::Field) => "field",
47 ClangEntityKind::Struct(StructKind::Struct) => "struct",
48 ClangEntityKind::Struct(StructKind::Class) => "class",
49 ClangEntityKind::Function(FunctionKind::Function) => "function",
50 ClangEntityKind::Function(FunctionKind::Method) => "method",
51 ClangEntityKind::Typedef => "typedef",
52 ClangEntityKind::Enum => "enum",
53 ClangEntityKind::EnumConstant => "enum-constant",
54 }
55 }
56
57 fn to_str_plural(self) -> &'static str {
58 match self {
59 ClangEntityKind::Namespace => "namespaces",
60 ClangEntityKind::Variable(VariableKind::Variable) => "variables",
61 ClangEntityKind::Variable(VariableKind::Field) => "fields",
62 ClangEntityKind::Struct(StructKind::Struct) => "structs",
63 ClangEntityKind::Struct(StructKind::Class) => "classes",
64 ClangEntityKind::Function(FunctionKind::Function) => "functions",
65 ClangEntityKind::Function(FunctionKind::Method) => "methods",
66 ClangEntityKind::Typedef => "typedefs",
67 ClangEntityKind::Enum => "enums",
68 ClangEntityKind::EnumConstant => "enum-constants",
69 }
70 }
71} 20}
72 21
73#[derive(Debug, Error)] 22#[derive(Debug, Error, PartialEq, Eq)]
74#[error("Unsupported Clang entity kind: {:?}", _0)] 23#[error("Unsupported Clang entity kind: {:?}", _0)]
75pub(super) struct TryFromEntityKindError(String); 24pub(super) struct TryFromEntityKindError(String);
76 25
77impl TryFrom<EntityKind> for ClangEntityKind { 26impl TryFrom<clang::EntityKind> for EntityKind {
78 type Error = TryFromEntityKindError; 27 type Error = TryFromEntityKindError;
79 28
80 fn try_from(kind: EntityKind) -> Result<ClangEntityKind, TryFromEntityKindError> { 29 fn try_from(kind: clang::EntityKind) -> Result<EntityKind, TryFromEntityKindError> {
81 Ok(match kind { 30 Ok(match kind {
82 EntityKind::Namespace => ClangEntityKind::Namespace, 31 clang::EntityKind::Namespace | clang::EntityKind::TranslationUnit => {
83 EntityKind::VarDecl => ClangEntityKind::Variable(VariableKind::Variable), 32 EntityKind::Namespace
84 EntityKind::FieldDecl => ClangEntityKind::Variable(VariableKind::Field),
85 EntityKind::FunctionDecl | EntityKind::FunctionTemplate => {
86 ClangEntityKind::Function(FunctionKind::Function)
87 }
88 EntityKind::Method | EntityKind::Constructor | EntityKind::Destructor => {
89 ClangEntityKind::Function(FunctionKind::Method)
90 } 33 }
91 EntityKind::StructDecl => ClangEntityKind::Struct(StructKind::Struct), 34 clang::EntityKind::VarDecl | clang::EntityKind::FieldDecl => EntityKind::Variable,
92 EntityKind::ClassDecl | EntityKind::ClassTemplate => { 35 clang::EntityKind::StructDecl
93 ClangEntityKind::Struct(StructKind::Class) 36 | clang::EntityKind::ClassDecl
94 } 37 | clang::EntityKind::ClassTemplate => EntityKind::Struct,
95 EntityKind::TypedefDecl 38 clang::EntityKind::FunctionDecl
96 | EntityKind::TypeAliasDecl 39 | clang::EntityKind::FunctionTemplate
97 | EntityKind::TypeAliasTemplateDecl => ClangEntityKind::Typedef, 40 | clang::EntityKind::Method
98 EntityKind::EnumDecl => ClangEntityKind::Enum, 41 | clang::EntityKind::Constructor
99 EntityKind::EnumConstantDecl => ClangEntityKind::EnumConstant, 42 | clang::EntityKind::Destructor => EntityKind::Function,
43 clang::EntityKind::TypedefDecl
44 | clang::EntityKind::TypeAliasDecl
45 | clang::EntityKind::TypeAliasTemplateDecl => EntityKind::TypeAlias,
46 clang::EntityKind::EnumDecl => EntityKind::Enum,
47 clang::EntityKind::EnumConstantDecl => EntityKind::EnumConstant,
100 kind => return Err(TryFromEntityKindError(format!("{:?}", kind))), 48 kind => return Err(TryFromEntityKindError(format!("{:?}", kind))),
101 }) 49 })
102 } 50 }
103} 51}
104 52
105#[derive(Debug)] 53#[derive(Debug, Clone, PartialEq, Eq)]
106pub(super) struct PartialEntity { 54pub(super) struct Description {
107 properties: Map<String, JSONValue>, 55 name: String,
108 children: Children, 56 brief: String,
57 detailed: String,
109} 58}
110 59
111pub(super) trait ClangEntity { 60impl<'a> TryFrom<clang::Entity<'a>> for Description {
112 fn kind(&self) -> ClangEntityKind; 61 type Error = Error;
113 62
114 fn get_member_namespaces(&mut self) -> Option<&mut BTreeMap<Usr, Described<Namespace>>> { 63 fn try_from(entity: clang::Entity) -> Result<Self> {
115 None 64 let name = entity
65 .get_display_name()
66 .ok_or_else(|| anyhow!("Entity has no name: {:?}", entity))?;
67
68 // TODO: is that the best?
69 if let (Some(brief), Some(comment)) = (entity.get_comment_brief(), entity.get_comment()) {
70 Ok(Description {
71 name,
72 brief,
73 detailed: super::parsing::parse_comment(comment),
74 })
75 } else {
76 Ok(Description {
77 name,
78 brief: String::new(),
79 detailed: String::new(),
80 })
81 }
116 } 82 }
117 fn get_member_variables(&mut self) -> Option<&mut BTreeMap<Usr, Described<Variable>>> { 83}
118 None 84
85#[derive(Debug, Clone, PartialEq, Eq)]
86pub(super) struct Described<T> {
87 pub description: Description,
88 pub entity: T,
89}
90
91type DescribedDynEntity = Described<DynEntity>;
92
93impl<T: Entity> Described<T> {
94 /*
95 fn into_dyn(self) -> Described<DynEntity> {
96 Described {
97 description: self.description,
98 entity: self.entity.into_dyn(),
99 }
119 } 100 }
120 fn get_member_structs(&mut self) -> Option<&mut BTreeMap<Usr, Described<Struct>>> { 101 */
121 None 102
103 fn to_dyn(&self) -> DescribedRef<DynEntityRef> {
104 DescribedRef {
105 description: &self.description,
106 entity: self.entity.to_dyn(),
107 }
122 } 108 }
123 fn get_member_functions(&mut self) -> Option<&mut BTreeMap<Usr, Described<Function>>> { 109
124 None 110 #[allow(clippy::wrong_self_convention)]
111 fn to_dyn_mut(&mut self) -> DescribedRefMut<DynEntityRefMut> {
112 DescribedRefMut {
113 description: &mut self.description,
114 entity: self.entity.to_dyn_mut(),
115 }
125 } 116 }
126 fn get_member_typedefs(&mut self) -> Option<&mut BTreeMap<Usr, Described<Typedef>>> { 117}
127 None 118
119impl<'a, T> TryFrom<clang::Entity<'a>> for Described<T>
120where
121 T: TryFrom<clang::Entity<'a>, Error = Error>,
122{
123 type Error = Error;
124
125 fn try_from(entity: clang::Entity<'a>) -> Result<Self, Error> {
126 Ok(Described::<T> {
127 description: entity.try_into()?,
128 entity: T::try_from(entity)?,
129 })
128 } 130 }
129 fn get_member_enums(&mut self) -> Option<&mut BTreeMap<Usr, Described<Enum>>> { 131}
130 None 132
133impl<T: Entity + Into<PartialEntity>> From<Described<T>> for types::Entity {
134 fn from(entity: Described<T>) -> Self {
135 let kind = types::EntityKind(entity.entity.kind_name_singular().to_owned());
136 let partial_entity: PartialEntity = entity.entity.into();
137
138 types::Entity {
139 name: entity.description.name,
140 language: types::Language::Clang,
141 kind,
142 brief_description: entity.description.brief,
143 documentation: entity.description.detailed,
144 properties: partial_entity.properties,
145 children: partial_entity.children,
146 }
131 } 147 }
132} 148}
133 149
150#[derive(Debug, Clone)]
151pub(super) struct DescribedRef<'a, T> {
152 pub description: &'a Description,
153 pub entity: T,
154}
155
156type DescribedDynEntityRef<'d, 'e> = DescribedRef<'d, DynEntityRef<'e>>;
157
134/* 158/*
135pub(super) trait FromNamespaceParent: ClangEntity + Sized { 159impl<'d, 'e, T: Entity> DescribedRef<'d, &'e T> {
136 fn from_namespace_parent<'a>( 160 fn from_dyn_ref(dyn_entity: DescribedDynEntityRef<'d, 'e>) -> Option<Self> {
137 parent: &'a mut Described<Namespace>, 161 Some(DescribedRef {
138 name: &Usr, 162 description: dyn_entity.description,
139 ) -> Option<&'a mut Described<Self>>; 163 entity: Entity::from_dyn_ref(dyn_entity.entity)?,
164 })
165 }
140} 166}
141*/ 167*/
142 168
143pub(super) trait NamespaceParentManipulation<T: ClangEntity + Sized> { 169#[derive(Debug, Clone)]
144 fn get_members_mut(&mut self) -> Option<&mut BTreeMap<Usr, Described<T>>>; 170pub(super) struct DescribedRefMut<'a, T> {
171 pub description: &'a Description,
172 pub entity: T,
145} 173}
146 174
147impl<U> NamespaceParentManipulation<Namespace> for U 175type DescribedDynEntityRefMut<'a, 'b> = DescribedRefMut<'a, DynEntityRefMut<'b>>;
148where 176
149 U: ClangEntity, 177impl<'d, 'e, T: Entity> DescribedRefMut<'d, &'e mut T> {
150{ 178 fn from_dyn_mut(dyn_entity: DescribedDynEntityRefMut<'d, 'e>) -> Option<Self> {
151 fn get_members_mut(&mut self) -> Option<&mut BTreeMap<Usr, Described<Namespace>>> { 179 Some(DescribedRefMut {
152 self.get_member_namespaces() 180 description: dyn_entity.description,
181 entity: Entity::from_dyn_mut(dyn_entity.entity)?,
182 })
153 } 183 }
154} 184}
155 185
156impl<U> NamespaceParentManipulation<Variable> for U 186pub(super) trait Entity: Traversable + KindName {
157where 187 const KIND: EntityKind;
158 U: ClangEntity, 188
159{ 189 /*
160 fn get_members_mut(&mut self) -> Option<&mut BTreeMap<Usr, Described<Variable>>> { 190 /// Transform a generic entity to a specific entity
161 self.get_member_variables() 191 fn try_into_specific<T: Entity>(self) -> Option<T>
192 where
193 Self: Sized,
194 {
195 T::from_dyn(self.into_dyn())
162 } 196 }
163}
164 197
165impl<U> NamespaceParentManipulation<Function> for U 198 /// Transform a generic entity to a specific entity
166where 199 ///
167 U: ClangEntity, 200 /// Panics if not the right entity kind
168{ 201 fn into_specific<T: Entity>(self) -> T
169 fn get_members_mut(&mut self) -> Option<&mut BTreeMap<Usr, Described<Function>>> { 202 where
170 self.get_member_functions() 203 Self: Sized,
204 {
205 self.try_into_specific().unwrap()
171 } 206 }
207 */
208
209 fn from_dyn(dyn_entity: DynEntity) -> Option<Self>
210 where
211 Self: Sized;
212 fn from_dyn_ref(dyn_entity: DynEntityRef) -> Option<&Self>;
213 fn from_dyn_mut(dyn_entity: DynEntityRefMut) -> Option<&mut Self>;
214 fn into_dyn(self) -> DynEntity;
215 fn to_dyn(&self) -> DynEntityRef;
216 fn to_dyn_mut(&mut self) -> DynEntityRefMut;
172} 217}
173 218
174impl<U> NamespaceParentManipulation<Struct> for U 219pub(super) trait Traversable {
175where 220 fn has_child_from_kind(&self, usr: &Usr, kind: EntityKind) -> bool;
176 U: ClangEntity, 221 fn get_child_from_kind(&self, usr: &Usr, kind: EntityKind) -> Option<DescribedDynEntityRef>;
177{ 222 fn get_mut_child_from_kind(
178 fn get_members_mut(&mut self) -> Option<&mut BTreeMap<Usr, Described<Struct>>> { 223 &mut self,
179 self.get_member_structs() 224 usr: &Usr,
180 } 225 kind: EntityKind,
226 ) -> Option<DescribedDynEntityRefMut>;
227 fn insert(&mut self, usr: Usr, child: DescribedDynEntity) -> Result<()>;
181} 228}
182 229
183impl<U> NamespaceParentManipulation<Typedef> for U 230pub(super) trait KindName {
184where 231 fn kind_name_singular(&self) -> &'static str;
185 U: ClangEntity, 232 fn kind_name_plural(&self) -> &'static str;
186{
187 fn get_members_mut(&mut self) -> Option<&mut BTreeMap<Usr, Described<Typedef>>> {
188 self.get_member_typedefs()
189 }
190} 233}
191 234
192impl<U> NamespaceParentManipulation<Enum> for U 235#[derive(Debug)]
193where 236pub(super) struct PartialEntity {
194 U: ClangEntity, 237 properties: JSONMap<String, JSONValue>,
195{ 238 children: types::Children,
196 fn get_members_mut(&mut self) -> Option<&mut BTreeMap<Usr, Described<Enum>>> {
197 self.get_member_enums()
198 }
199} 239}
200 240
201fn entity_id(usr: Usr) -> EntityId { 241fn entity_id(usr: Usr) -> types::EntityId {
242 fn is_identifier_char(c: char) -> bool {
243 c.is_ascii() || c == '-' || c == '_' || c == ':' || c == '.'
244 }
202 // This is a somewhat ugly workaround, because Pandoc parses markdown identifiers as alphanum 245 // This is a somewhat ugly workaround, because Pandoc parses markdown identifiers as alphanum
203 // or one of "-_:.", which means Pandoc can't parse libclang's USRs in title ids and related. 246 // or one of "-_:.", which means Pandoc can't parse libclang's USRs in title ids and related.
204 // 247 //
205 // <https://github.com/jgm/pandoc/blob/2.9/src/Text/Pandoc/Readers/Markdown.hs#L581> 248 // <https://github.com/jgm/pandoc/blob/2.9/src/Text/Pandoc/Readers/Markdown.hs#L581>
206 EntityId(usr.0.replace("@", "::").replace("#", ".").replace("$", "-")) 249 types::EntityId(
250 usr.0
251 .replace("@", "::")
252 .replace("#", ".")
253 .replace("$", "-")
254 .replace(|c| !is_identifier_char(c), ""),
255 )
207} 256}
208 257
209fn append_children<T: ClangEntity + Into<PartialEntity>>( 258macro_rules! entity {
210 acc: &mut types::Children, 259 (
211 to_insert: BTreeMap<Usr, Described<T>>, 260 $(#[$meta: meta])*
212) { 261 $struct_vis: vis struct $name: ident {
213 for (usr, child) in to_insert { 262 $($(
214 acc.entry(ChildrenKind(String::from( 263 $(#[$field_meta: meta])*
215 child.entity.kind().to_str_plural(), 264 $field_vis: vis $field: ident : $type: ty,
216 ))) 265 )+)?
217 .or_default() 266 $(#children => [
218 .insert(entity_id(usr), child.into()); 267 $($child_name: ident: $child_type: ident),* $(,)?
219 } 268 ],)?
220} 269 $(#properties($properties_var: ident) => $properties: expr,)?
270 }
271 ) => {
272
273 #[derive(Debug, Clone, PartialEq, Eq)]
274 $(#[$meta])*
275 $struct_vis struct $name {
276 $($(
277 $(#[$field_meta])*
278 $field_vis $field: $type,
279 )+)?
280 $($($child_name: BTreeMap<Usr, Described<$child_type>>),*)?
281 }
221 282
222impl<T: ClangEntity + Into<PartialEntity>> From<Described<T>> for Entity { 283 impl Entity for $name {
223 fn from(entity: Described<T>) -> Self { 284 const KIND: EntityKind = EntityKind::$name;
224 let kind = EntityKind(String::from(entity.entity.kind().to_str_singular()));
225 let partial_entity: PartialEntity = entity.entity.into();
226 285
227 Entity { 286 fn from_dyn(dyn_entity: DynEntity) -> Option<Self> {
228 name: entity.description.name, 287 match dyn_entity {
229 language: Language::Clang, 288 DynEntity::$name(me) => Some(me),
230 kind, 289 _ => None,
231 brief_description: entity.description.brief, 290 }
232 documentation: entity.description.detailed, 291 }
233 properties: partial_entity.properties, 292
234 children: partial_entity.children, 293 fn from_dyn_ref(dyn_entity: DynEntityRef) -> Option<&Self> {
294 match dyn_entity {
295 DynEntityRef::$name(me) => Some(me),
296 _ => None,
297 }
298 }
299
300 fn from_dyn_mut(dyn_entity: DynEntityRefMut) -> Option<&mut Self> {
301 match dyn_entity {
302 DynEntityRefMut::$name(me) => Some(me),
303 _ => None,
304 }
305 }
306
307 fn into_dyn(self) -> DynEntity {
308 DynEntity::$name(self)
309 }
310
311 fn to_dyn(&self) -> DynEntityRef {
312 DynEntityRef::$name(self)
313 }
314
315 fn to_dyn_mut(&mut self) -> DynEntityRefMut {
316 DynEntityRefMut::$name(self)
317 }
318 }
319
320 impl Traversable for $name {
321 #[allow(unused_variables, unreachable_patterns)]
322 fn has_child_from_kind(&self, usr: &Usr, kind: EntityKind) -> bool {
323 match kind {
324 $($(
325 EntityKind::$child_type => self.$child_name.contains_key(usr),
326 )*)?
327 _ => false,
328 }
329 }
330
331 #[allow(unused_variables, unreachable_patterns)]
332 fn get_child_from_kind(
333 &self,
334 usr: &Usr,
335 kind: EntityKind
336 ) -> Option<DescribedDynEntityRef> {
337 match kind {
338 $($(
339 EntityKind::$child_type => {
340 self.$child_name.get(usr).map(Described::to_dyn)
341 }
342 )*)?
343 _ => None,
344 }
345 }
346
347 #[allow(unused_variables, unreachable_patterns)]
348 fn get_mut_child_from_kind(
349 &mut self,
350 usr: &Usr,
351 kind: EntityKind
352 ) -> Option<DescribedDynEntityRefMut> {
353 match kind {
354 $($(
355 EntityKind::$child_type => {
356 self.$child_name.get_mut(usr).map(Described::to_dyn_mut)
357 }
358 )*)?
359 _ => None,
360 }
361 }
362
363 #[allow(unused_variables, unreachable_patterns)]
364 fn insert(&mut self, usr: Usr, child: DescribedDynEntity) -> Result<()> {
365 match child.entity {
366 $($(
367 DynEntity::$child_type(entity) => {
368 self.$child_name.insert(
369 usr,
370 Described { description: child.description, entity }
371 );
372 Ok(())
373 }
374 )*)?
375 // TODO: Properly define an error
376 other => Err(anyhow!("Impossible to insert {:?} into {:?}", other, Self::KIND)),
377 }
378 }
379 }
380
381 // TODO: explain why we do this (hygienic)
382 entity!{@partial_entity $name, $($properties_var,)? $($($child_name)*)?, $($properties)?}
383
384 };
385
386 (@partial_entity $name: ident, $entity_var: ident, $($child_name: ident)*, $($properties: expr)?) => {
387 impl<'a> From<$name> for PartialEntity {
388 #[allow(unused_variables, unused_mut)]
389 fn from($entity_var: $name) -> Self {
390 let mut children = types::Children::default();
391 $(
392 for (usr, child) in $entity_var.$child_name {
393 children.entry(types::ChildrenKind(String::from(
394 child.entity.kind_name_plural(),
395 )))
396 .or_default()
397 .insert(entity_id(usr), child.into());
398 }
399 )*
400
401 let properties = entity!(@properties $($properties)?);
402
403 Self { properties, children }
404 }
405 }
406 };
407
408 (@partial_entity $name: ident, $($child_name: ident)*, $($properties: expr)?) => {
409 entity!{@partial_entity $name, entity, $($child_name)*, $($properties)?}
410 };
411
412 (@properties $properties: expr) => {{
413 match $properties {
414 JSONValue::Object(map) => map,
415 _ => panic!("Entity properties not given in JSON object form"),
235 } 416 }
417 }};
418
419 (@properties) => {
420 Default::default()
236 } 421 }
237} 422}
238 423
239#[derive(Debug, Clone, Default)] 424#[derive(Debug, Clone, PartialEq, Eq)]
240pub(super) struct Description { 425pub(super) struct TopLevel(Described<Namespace>);
241 pub(super) name: String, 426
242 pub(super) brief: String, 427impl Default for TopLevel {
243 pub(super) detailed: String, 428 fn default() -> Self {
429 TopLevel(Described::<Namespace> {
430 description: Description {
431 name: String::new(),
432 brief: String::new(),
433 detailed: String::new(),
434 },
435 entity: Namespace::new_global(),
436 })
437 }
244} 438}
245 439
246#[derive(Debug, Clone)] 440impl From<TopLevel> for types::Entity {
247pub(super) struct Described<T> { 441 fn from(toplevel: TopLevel) -> Self {
248 pub(super) description: Description, 442 toplevel.0.into()
249 pub(super) entity: T, 443 }
250} 444}
251 445
252#[derive(Debug, Clone)] 446// TODO: Probably remove NoParent in favor of the Error variant of Result
253pub(super) struct Namespace { 447#[derive(Debug)]
254 pub(super) member_namespaces: BTreeMap<Usr, Described<Namespace>>, 448pub(super) enum EntityEntry<'d, 'e, T> {
255 pub(super) member_variables: BTreeMap<Usr, Described<Variable>>, 449 Vacant {
256 pub(super) member_structs: BTreeMap<Usr, Described<Struct>>, 450 parent: DescribedRefMut<'d, &'e mut Namespace>,
257 pub(super) member_functions: BTreeMap<Usr, Described<Function>>, 451 },
258 pub(super) member_typedefs: BTreeMap<Usr, Described<Typedef>>, 452 Occupied {
259 pub(super) member_enums: BTreeMap<Usr, Described<Enum>>, 453 entity: DescribedRefMut<'d, T>,
454 },
455}
456
457#[derive(Debug, Error, PartialEq, Eq)]
458pub(super) enum TopLevelEntryError {
459 #[error("Entity has no parent")]
460 NoParent,
461 #[error("Entity has no USR")]
462 NoUsr,
463 #[error("Entity kind is not supported")]
464 UnknownKind,
260} 465}
261 466
262impl ClangEntity for Namespace { 467impl TopLevel {
263 fn kind(&self) -> ClangEntityKind { 468 /*
264 ClangEntityKind::Namespace 469 pub(super) fn get_dyn(&self, path: clang::Entity) -> Option<DescribedDynEntityRef> {
470 if path.get_kind() == clang::EntityKind::TranslationUnit {
471 return Some(self.0.to_dyn());
472 }
473 let usr = path.get_usr()?;
474 let parent_path = path
475 .get_semantic_parent()
476 .expect("get_semantic_parent() returned None");
477
478 let kind = path.get_kind().try_into().ok()?;
479 self.get_dyn(parent_path).and_then(|parent| {
480 parent
481 .entity
482 .map(|parent| parent.get_child_from_kind(&usr, kind))
483 })
484 }
485 */
486
487 pub(super) fn get_dyn_mut(&mut self, path: clang::Entity) -> Option<DescribedDynEntityRefMut> {
488 if path.get_kind() == clang::EntityKind::TranslationUnit {
489 return Some(self.0.to_dyn_mut());
490 }
491 let usr = path.get_usr()?;
492 let parent_path = path
493 .get_semantic_parent()
494 .expect("get_semantic_parent() returned None");
495
496 let kind = path.get_kind().try_into().ok()?;
497 self.get_dyn_mut(parent_path).and_then(|parent| {
498 parent
499 .entity
500 .map(|parent| parent.get_mut_child_from_kind(&usr, kind))
501 })
265 } 502 }
266 503
267 fn get_member_namespaces(&mut self) -> Option<&mut BTreeMap<Usr, Described<Namespace>>> { 504 /*
268 Some(&mut self.member_namespaces) 505 pub(super) fn get<T>(&self, path: clang::Entity) -> Option<DescribedRef<&T>>
506 where
507 T: Entity,
508 {
509 assert_eq!(path.get_kind().try_into(), Ok(T::KIND),);
510 self.get_dyn(path).and_then(DescribedRef::from_dyn_ref)
269 } 511 }
270 fn get_member_variables(&mut self) -> Option<&mut BTreeMap<Usr, Described<Variable>>> { 512
271 Some(&mut self.member_variables) 513 pub(super) fn get_mut<T>(&mut self, path: clang::Entity) -> Option<DescribedRefMut<&mut T>>
514 where
515 T: Entity,
516 {
517 assert_eq!(path.get_kind().try_into(), Ok(T::KIND),);
518 self.get_dyn_mut(path)
519 .and_then(DescribedRefMut::from_dyn_mut)
272 } 520 }
273 fn get_member_structs(&mut self) -> Option<&mut BTreeMap<Usr, Described<Struct>>> { 521
274 Some(&mut self.member_structs) 522 pub(super) fn insert_dyn(
523 &mut self,
524 path: clang::Entity,
525 entity: DescribedDynEntity,
526 ) -> Result<()> {
527 let usr = path.get_usr().ok_or_else(|| anyhow!("no usr"))?;
528 let parent_path = path
529 .get_semantic_parent()
530 .ok_or_else(|| anyhow!("Trying to insert the global namespace"))?;
531
532 self.get_dyn_mut(parent_path)
533 .map(|described_entity| described_entity.entity)
534 // TODO: Properly define an error
535 .ok_or_else(|| anyhow!("has parent: {:?} but no parent in tree", parent_path))?
536 .map(|parent| parent.insert(usr, entity))
275 } 537 }
276 fn get_member_functions(&mut self) -> Option<&mut BTreeMap<Usr, Described<Function>>> { 538
277 Some(&mut self.member_functions) 539 pub(super) fn insert<T>(&mut self, path: clang::Entity, entity: Described<T>) -> Result<()>
540 where
541 T: Entity,
542 {
543 self.insert_dyn(path, entity.into_dyn())
278 } 544 }
279 fn get_member_typedefs(&mut self) -> Option<&mut BTreeMap<Usr, Described<Typedef>>> { 545 */
280 Some(&mut self.member_typedefs) 546
547 // TODO: does not check whether a vacant entry is allowed to be in parent.
548 // For example, it can return a vacant EnumConstant inside a Struct.
549 pub(super) fn entry_dyn(
550 &mut self,
551 path: clang::Entity,
552 ) -> Result<EntityEntry<DynEntityRefMut>, TopLevelEntryError> {
553 let kind = path
554 .get_kind()
555 .try_into()
556 .map_err(|_err| TopLevelEntryError::UnknownKind)?;
557 let usr = path.get_usr().ok_or(TopLevelEntryError::NoUsr)?;
558 let parent_path = match path.get_semantic_parent() {
559 Some(parent) => parent,
560 // No parent? It must be the TranslationUnit / Global Namespace
561 None => {
562 return Ok(EntityEntry::Vacant {
563 parent: DescribedRefMut {
564 description: &mut self.0.description,
565 entity: &mut self.0.entity,
566 },
567 })
568 }
569 };
570
571 let dyn_parent = self
572 .get_dyn_mut(parent_path)
573 .ok_or(TopLevelEntryError::NoParent)?;
574
575 if dyn_parent
576 .entity
577 .map_ref(|parent| !parent.has_child_from_kind(&usr, kind))
578 {
579 return Ok(EntityEntry::Vacant {
580 parent: DescribedRefMut::from_dyn_mut(dyn_parent).unwrap(),
581 });
582 }
583
584 match dyn_parent
585 .entity
586 .map(|parent| parent.get_mut_child_from_kind(&usr, kind))
587 {
588 Some(entity) => Ok(EntityEntry::Occupied { entity }),
589 None => unreachable!(),
590 }
281 } 591 }
282 fn get_member_enums(&mut self) -> Option<&mut BTreeMap<Usr, Described<Enum>>> { 592
283 Some(&mut self.member_enums) 593 /*
594 pub(super) fn entry<T>(
595 &mut self,
596 path: clang::Entity,
597 ) -> Result<EntityEntry<&mut T>, TopLevelEntryError>
598 where
599 T: Entity,
600 {
601 Ok(match self.entry_dyn(path)? {
602 EntityEntry::Occupied { entity } => EntityEntry::Occupied {
603 entity: DescribedRefMut::from_dyn_mut(entity).unwrap(),
604 },
605 EntityEntry::Vacant { parent } => EntityEntry::Vacant { parent },
606 })
284 } 607 }
608 */
609}
610
611// TODO: all of the DynEntity business can probably be macro generated too
612
613#[derive(Debug)]
614pub(super) enum DynEntity {
615 Namespace(Namespace),
616 Variable(Variable),
617 Struct(Struct),
618 Function(Function),
619 Enum(Enum),
620 EnumConstant(EnumConstant),
621 TypeAlias(TypeAlias),
622}
623
624#[derive(Debug, Clone, Copy)]
625pub(super) enum DynEntityRef<'a> {
626 Namespace(&'a Namespace),
627 Variable(&'a Variable),
628 Struct(&'a Struct),
629 Function(&'a Function),
630 Enum(&'a Enum),
631 EnumConstant(&'a EnumConstant),
632 TypeAlias(&'a TypeAlias),
285} 633}
286 634
287/* 635/*
288impl FromNamespaceParent for Namespace { 636impl<'a> DynEntityRef<'a> {
289 fn from_namespace_parent<'a>( 637 fn map<U, F>(&self, f: F) -> U
290 parent: &'a mut Described<Namespace>, 638 where
291 name: &Usr, 639 F: FnOnce(&'a dyn Traversable) -> U,
292 ) -> Option<&'a mut Described<Self>> { 640 {
293 parent.entity.member_namespaces.get_mut(name) 641 match self {
642 DynEntityRef::Namespace(namespace) => f(*namespace),
643 DynEntityRef::Variable(variable) => f(*variable),
644 DynEntityRef::Struct(r#struct) => f(*r#struct),
645 DynEntityRef::Function(function) => f(*function),
646 DynEntityRef::Enum(Enum) => f(*Enum),
647 DynEntityRef::EnumConstant(enum_constant) => f(*enum_constant),
648 DynEntityRef::TypeAlias(type_alias) => f(*type_alias),
649 }
294 } 650 }
295} 651}
296*/ 652*/
297 653
298impl From<Namespace> for PartialEntity { 654#[derive(Debug)]
299 fn from(entity: Namespace) -> Self { 655pub(super) enum DynEntityRefMut<'a> {
300 let mut children = Default::default(); 656 Namespace(&'a mut Namespace),
301 append_children(&mut children, entity.member_namespaces); 657 Variable(&'a mut Variable),
302 append_children(&mut children, entity.member_variables); 658 Struct(&'a mut Struct),
303 append_children(&mut children, entity.member_structs); 659 Function(&'a mut Function),
304 append_children(&mut children, entity.member_functions); 660 Enum(&'a mut Enum),
305 append_children(&mut children, entity.member_typedefs); 661 EnumConstant(&'a mut EnumConstant),
306 append_children(&mut children, entity.member_enums); 662 TypeAlias(&'a mut TypeAlias),
307 663}
308 PartialEntity { 664
309 properties: Default::default(), 665impl<'a> DynEntityRefMut<'a> {
310 children, 666 fn map<U, F>(self, f: F) -> U
667 where
668 F: FnOnce(&'a mut dyn Traversable) -> U,
669 {
670 match self {
671 DynEntityRefMut::Namespace(namespace) => f(namespace),
672 DynEntityRefMut::Variable(variable) => f(variable),
673 DynEntityRefMut::Struct(r#struct) => f(r#struct),
674 DynEntityRefMut::Function(function) => f(function),
675 DynEntityRefMut::Enum(r#enum) => f(r#enum),
676 DynEntityRefMut::EnumConstant(enum_constant) => f(enum_constant),
677 DynEntityRefMut::TypeAlias(type_alias) => f(type_alias),
311 } 678 }
312 } 679 }
313}
314 680
315#[derive(Debug, Clone)] 681 fn map_ref<U, F>(&self, f: F) -> U
316pub(super) struct Variable { 682 where
317 pub(super) kind: VariableKind, 683 F: FnOnce(&dyn Traversable) -> U,
318 pub(super) r#type: String, 684 {
685 match self {
686 DynEntityRefMut::Namespace(namespace) => f(*namespace),
687 DynEntityRefMut::Variable(variable) => f(*variable),
688 DynEntityRefMut::Struct(r#struct) => f(*r#struct),
689 DynEntityRefMut::Function(function) => f(*function),
690 DynEntityRefMut::Enum(r#enum) => f(*r#enum),
691 DynEntityRefMut::EnumConstant(enum_constant) => f(*enum_constant),
692 DynEntityRefMut::TypeAlias(type_alias) => f(*type_alias),
693 }
694 }
319} 695}
320 696
321impl ClangEntity for Variable { 697impl<'a> TryFrom<clang::Entity<'a>> for DynEntity {
322 fn kind(&self) -> ClangEntityKind { 698 type Error = Error;
323 ClangEntityKind::Variable(self.kind) 699
700 fn try_from(entity: clang::Entity) -> Result<Self> {
701 Ok(match entity.get_kind().try_into()? {
702 EntityKind::Namespace => Namespace::try_from(entity)?.into_dyn(),
703 EntityKind::Variable => Variable::try_from(entity)?.into_dyn(),
704 EntityKind::Struct => Struct::try_from(entity)?.into_dyn(),
705 EntityKind::Function => Function::try_from(entity)?.into_dyn(),
706 EntityKind::Enum => Enum::try_from(entity)?.into_dyn(),
707 EntityKind::EnumConstant => EnumConstant::try_from(entity)?.into_dyn(),
708 EntityKind::TypeAlias => TypeAlias::try_from(entity)?.into_dyn(),
709 })
324 } 710 }
325} 711}
326 712
327impl From<Variable> for PartialEntity { 713#[derive(Debug, Clone, Copy, PartialEq, Eq)]
328 fn from(entity: Variable) -> Self { 714struct ClassMemberProperties {
329 let mut properties = Map::new(); 715 accessibility: clang::Accessibility,
330 properties.insert(String::from("type"), JSONValue::String(entity.r#type)); 716}
331 PartialEntity { 717
332 properties, 718#[derive(Debug, Error, PartialEq, Eq)]
333 children: Default::default(), 719pub(super) enum TryFromClassMemberPropsError {
334 } 720 #[error("Failed to get accessibility status")]
721 Accessibility,
722}
723
724impl ClassMemberProperties {
725 fn try_from_clang(entity: clang::Entity) -> Result<Self> {
726 Ok(ClassMemberProperties {
727 accessibility: entity
728 .get_accessibility()
729 .ok_or(TryFromClassMemberPropsError::Accessibility)?,
730 })
335 } 731 }
336} 732}
337 733
338/* 734impl From<ClassMemberProperties> for JSONMap<String, JSONValue> {
339impl FromNamespaceParent for Variable { 735 fn from(member_properties: ClassMemberProperties) -> JSONMap<String, JSONValue> {
340 fn from_namespace_parent<'a>( 736 let mut properties = JSONMap::new();
341 parent: &'a mut Described<Namespace>, 737 properties.insert(
342 name: &Usr, 738 String::from("accessibility"),
343 ) -> Option<&'a mut Described<Self>> { 739 match member_properties.accessibility {
344 parent.entity.member_variables.get_mut(name) 740 clang::Accessibility::Private => JSONValue::String(String::from("private")),
741 clang::Accessibility::Protected => JSONValue::String(String::from("protected")),
742 clang::Accessibility::Public => JSONValue::String(String::from("public")),
743 },
744 );
745 properties
345 } 746 }
346} 747}
347*/
348 748
349#[derive(Debug, Clone)] 749// =================
350pub(super) struct Struct { 750// === Namespace ===
351 //pub(super) member_types: Vec<Usr>, 751// =================
352 pub(super) kind: StructKind, 752
353 pub(super) member_variables: BTreeMap<Usr, Described<Variable>>, 753entity! {
354 pub(super) member_structs: BTreeMap<Usr, Described<Struct>>, 754 pub(super) struct Namespace {
355 pub(super) member_functions: BTreeMap<Usr, Described<Function>>, 755 /// Whether this is the global namespace
356 pub(super) member_typedefs: BTreeMap<Usr, Described<Typedef>>, 756 global: bool,
357 pub(super) member_enums: BTreeMap<Usr, Described<Enum>>, 757 #children => [
758 member_namespaces: Namespace,
759 member_variables: Variable,
760 member_structs: Struct,
761 member_functions: Function,
762 member_type_aliases: TypeAlias,
763 member_enums: Enum,
764 ],
765 #properties(entity) => json!({"global": entity.global}),
766 }
358} 767}
359 768
360impl ClangEntity for Struct { 769impl Namespace {
361 fn kind(&self) -> ClangEntityKind { 770 fn new_global() -> Self {
362 ClangEntityKind::Struct(self.kind) 771 Namespace {
772 global: true,
773 ..Default::default()
774 }
363 } 775 }
776}
364 777
365 fn get_member_variables(&mut self) -> Option<&mut BTreeMap<Usr, Described<Variable>>> { 778impl KindName for Namespace {
366 Some(&mut self.member_variables) 779 fn kind_name_singular(&self) -> &'static str {
780 if self.global {
781 "global namespace"
782 } else {
783 "namespace"
784 }
367 } 785 }
368 fn get_member_structs(&mut self) -> Option<&mut BTreeMap<Usr, Described<Struct>>> { 786
369 Some(&mut self.member_structs) 787 fn kind_name_plural(&self) -> &'static str {
788 if self.global {
789 // TODO: probably panic here, branch should not happen
790 "global namespaces"
791 } else {
792 "namespaces"
793 }
370 } 794 }
371 fn get_member_functions(&mut self) -> Option<&mut BTreeMap<Usr, Described<Function>>> { 795}
372 Some(&mut self.member_functions) 796
797impl Default for Namespace {
798 fn default() -> Self {
799 Namespace {
800 global: false,
801 member_variables: Default::default(),
802 member_structs: Default::default(),
803 member_namespaces: Default::default(),
804 member_functions: Default::default(),
805 member_type_aliases: Default::default(),
806 member_enums: Default::default(),
807 }
373 } 808 }
374 fn get_member_typedefs(&mut self) -> Option<&mut BTreeMap<Usr, Described<Typedef>>> { 809}
375 Some(&mut self.member_typedefs) 810
811impl<'a> TryFrom<clang::Entity<'a>> for Namespace {
812 type Error = Error;
813
814 fn try_from(entity: clang::Entity) -> Result<Self> {
815 assert_eq!(
816 entity.get_kind().try_into(),
817 Ok(EntityKind::Namespace),
818 "Trying to parse a non-variable into a variable"
819 );
820 debug!("Parsing Namespace: {:?}", entity);
821
822 // Do not recurse here, but recurse in the main loop, since namespace
823 // definitions is allowed to change between translation units
824
825 Ok(Namespace::default())
376 } 826 }
377 fn get_member_enums(&mut self) -> Option<&mut BTreeMap<Usr, Described<Enum>>> { 827}
378 Some(&mut self.member_enums) 828
829// ================
830// === Variable ===
831// ================
832
833#[derive(Debug, Clone, Copy, PartialEq, Eq)]
834enum VariableKind {
835 Variable,
836 Field {
837 member_properties: ClassMemberProperties,
838 },
839}
840
841entity! {
842 pub(super) struct Variable {
843 kind: VariableKind,
844 r#type: String,
845 #properties(entity) => {
846 let mut properties = json!({"type": entity.r#type});
847 if let VariableKind::Field { member_properties } = entity.kind {
848 properties.as_object_mut().unwrap().extend(JSONMap::from(member_properties));
849 }
850 properties
851 },
379 } 852 }
380} 853}
381 854
382impl From<Struct> for PartialEntity { 855impl KindName for Variable {
383 fn from(entity: Struct) -> Self { 856 fn kind_name_singular(&self) -> &'static str {
384 let mut children = Default::default(); 857 match self.kind {
385 append_children(&mut children, entity.member_variables); 858 VariableKind::Variable => "variable",
386 append_children(&mut children, entity.member_structs); 859 VariableKind::Field { .. } => "field",
387 append_children(&mut children, entity.member_functions); 860 }
388 append_children(&mut children, entity.member_typedefs); 861 }
389 append_children(&mut children, entity.member_enums);
390 862
391 PartialEntity { 863 fn kind_name_plural(&self) -> &'static str {
392 properties: Default::default(), 864 match self.kind {
393 children, 865 VariableKind::Variable => "variables",
866 VariableKind::Field { .. } => "fields",
394 } 867 }
395 } 868 }
396} 869}
397 870
398/* 871impl<'a> TryFrom<clang::Entity<'a>> for Variable {
399impl FromNamespaceParent for Struct { 872 type Error = Error;
400 fn from_namespace_parent<'a>( 873
401 parent: &'a mut Described<Namespace>, 874 fn try_from(entity: clang::Entity) -> Result<Self> {
402 name: &Usr, 875 let clang_kind = entity.get_kind();
403 ) -> Option<&'a mut Described<Self>> { 876 assert_eq!(
404 parent.entity.member_structs.get_mut(name) 877 clang_kind.try_into(),
878 Ok(EntityKind::Variable),
879 "Trying to parse a non-variable into a variable"
880 );
881 debug!("Parsing Variable: {:?}", entity);
882
883 let kind = match clang_kind {
884 clang::EntityKind::VarDecl => VariableKind::Variable,
885 clang::EntityKind::FieldDecl => VariableKind::Field {
886 // TODO: should probably not return on error
887 member_properties: ClassMemberProperties::try_from_clang(entity)?,
888 },
889 // We panic here because we've asserted the type in the beginning
890 other => panic!("Trying to parse {:?} as a variable", other),
891 };
892
893 let r#type = entity.get_type().unwrap().get_display_name();
894 trace!("Variable has type: {:?}", r#type);
895
896 Ok(Variable { kind, r#type })
405 } 897 }
406} 898}
407*/
408 899
409#[derive(Debug, Clone)] 900// ==============
410pub(super) struct Function { 901// === Struct ===
411 pub(super) kind: FunctionKind, 902// ==============
412 pub(super) arguments: Vec<FunctionArgument>, 903
413 pub(super) return_type: String, 904#[derive(Debug, Clone, Copy, PartialEq, Eq)]
905pub(super) enum StructKind {
906 Struct,
907 Class,
414} 908}
415 909
416impl ClangEntity for Function { 910entity! {
417 fn kind(&self) -> ClangEntityKind { 911 pub(super) struct Struct {
418 ClangEntityKind::Function(self.kind) 912 kind: StructKind,
913 #children => [
914 member_variables: Variable,
915 member_structs: Struct,
916 member_functions: Function,
917 member_enums: Enum,
918 member_type_aliases: TypeAlias,
919 ],
419 } 920 }
420} 921}
421 922
422impl From<Function> for PartialEntity { 923impl KindName for Struct {
423 fn from(entity: Function) -> Self { 924 fn kind_name_singular(&self) -> &'static str {
424 let mut properties = Map::with_capacity(2); 925 match self.kind {
425 properties.insert( 926 StructKind::Struct => "struct",
426 String::from("return-type"), 927 StructKind::Class => "class",
427 JSONValue::String(entity.return_type), 928 }
428 ); 929 }
429 properties.insert( 930
430 String::from("arguments"), 931 fn kind_name_plural(&self) -> &'static str {
431 JSONValue::Array(entity.arguments.into_iter().map(Into::into).collect()), 932 match self.kind {
933 StructKind::Struct => "structs",
934 StructKind::Class => "classes",
935 }
936 }
937}
938
939impl<'a> TryFrom<clang::Entity<'a>> for Struct {
940 type Error = Error;
941
942 fn try_from(entity: clang::Entity) -> Result<Self, Error> {
943 let clang_kind = entity.get_kind();
944 assert_eq!(
945 clang_kind.try_into(),
946 Ok(EntityKind::Struct),
947 "Trying to parse a non-struct into a struct"
432 ); 948 );
949 debug!("Parsing Struct: {:?}", entity);
433 950
434 PartialEntity { 951 let mut member_variables = BTreeMap::new();
435 properties, 952 let mut member_structs = BTreeMap::new();
436 children: Default::default(), 953 let mut member_functions = BTreeMap::new();
954 let mut member_enums = BTreeMap::new();
955 let mut member_type_aliases = BTreeMap::new();
956
957 for child in entity.get_children() {
958 trace!("Struct has child: {:?}", child);
959
960 let kind = child.get_kind();
961
962 match kind {
963 ::clang::EntityKind::AccessSpecifier | ::clang::EntityKind::BaseSpecifier => {
964 continue
965 }
966 _ => {}
967 }
968
969 let mut parse_child = || -> Result<()> {
970 match kind.try_into() {
971 Ok(EntityKind::Variable) => {
972 let child_usr = child
973 .get_usr()
974 .ok_or_else(|| anyhow!("no usr for: {:?}", child))?;
975 member_variables.insert(child_usr, Described::<Variable>::try_from(child)?);
976 }
977 Ok(EntityKind::Struct) => {
978 let child_usr: Usr = child
979 .get_usr()
980 .ok_or_else(|| anyhow!("no usr for: {:?}", child))?;
981 member_structs.insert(child_usr, Described::<Struct>::try_from(child)?);
982 }
983 Ok(EntityKind::Function) => {
984 let child_usr = child
985 .get_usr()
986 .ok_or_else(|| anyhow!("no usr for: {:?}", child))?;
987 member_functions.insert(child_usr, Described::<Function>::try_from(child)?);
988 }
989 Ok(EntityKind::Enum) => {
990 let child_usr = child
991 .get_usr()
992 .ok_or_else(|| anyhow!("no usr for: {:?}", child))?;
993 member_enums.insert(child_usr, Described::<Enum>::try_from(child)?);
994 }
995 Ok(EntityKind::TypeAlias) => {
996 let child_usr = child
997 .get_usr()
998 .ok_or_else(|| anyhow!("no usr for: {:?}", child))?;
999 member_type_aliases
1000 .insert(child_usr, Described::<TypeAlias>::try_from(child)?);
1001 }
1002 Ok(other) => warn!("Unsupported child of struct {:?}: {:?}", other, child),
1003 Err(err) => info!("Error while parsing entity {:?}: {}", child, err),
1004 }
1005
1006 Ok(())
1007 };
1008
1009 match parse_child() {
1010 Ok(()) => {}
1011 Err(err) => {
1012 warn!("Error while parsing child {:?}: {}", child, err);
1013 }
1014 }
437 } 1015 }
1016
1017 let kind = match clang_kind {
1018 clang::EntityKind::StructDecl => StructKind::Struct,
1019 clang::EntityKind::ClassDecl => StructKind::Class,
1020 // We panic here because we've asserted the type in the beginning
1021 other => panic!("Trying to parse {:?} as a variable", other),
1022 };
1023
1024 Ok(Struct {
1025 kind,
1026 member_variables,
1027 member_structs,
1028 member_functions,
1029 member_enums,
1030 member_type_aliases,
1031 })
438 } 1032 }
439} 1033}
440 1034
441/* 1035// ================
442impl FromNamespaceParent for Function { 1036// === Function ===
443 fn from_namespace_parent<'a>( 1037// ================
444 parent: &'a mut Described<Namespace>, 1038
445 name: &Usr, 1039#[derive(Debug, Clone, Copy, PartialEq, Eq)]
446 ) -> Option<&'a mut Described<Self>> { 1040pub(super) enum FunctionKind {
447 parent.entity.member_functions.get_mut(name) 1041 Function,
1042 Method,
1043}
1044
1045entity! {
1046 pub(super) struct Function {
1047 kind: FunctionKind,
1048 arguments: Vec<FunctionArgument>,
1049 return_type: String,
448 } 1050 }
449} 1051}
450*/
451 1052
452#[derive(Debug, Clone)] 1053#[derive(Debug, Clone, PartialEq, Eq)]
453pub(super) struct FunctionArgument { 1054pub(super) struct FunctionArgument {
454 pub(super) name: String, 1055 pub(super) name: String,
455 pub(super) r#type: String, 1056 pub(super) r#type: String,
456} 1057}
457 1058
458impl From<FunctionArgument> for JSONValue { 1059impl KindName for Function {
459 fn from(argument: FunctionArgument) -> JSONValue { 1060 fn kind_name_singular(&self) -> &'static str {
460 let mut object = Map::new(); 1061 match self.kind {
461 object.insert(String::from("type"), JSONValue::String(argument.r#type)); 1062 FunctionKind::Function => "function",
462 object.insert(String::from("name"), JSONValue::String(argument.name)); 1063 FunctionKind::Method => "method",
463 JSONValue::Object(object) 1064 }
1065 }
1066
1067 fn kind_name_plural(&self) -> &'static str {
1068 match self.kind {
1069 FunctionKind::Function => "functions",
1070 FunctionKind::Method => "methods",
1071 }
464 } 1072 }
465} 1073}
466 1074
467#[derive(Debug, Clone)] 1075impl<'a> TryFrom<clang::Entity<'a>> for Function {
468pub(super) struct Typedef { 1076 type Error = Error;
469 pub(super) referee: String, 1077
1078 fn try_from(entity: clang::Entity) -> Result<Self, Error> {
1079 let clang_kind = entity.get_kind();
1080 assert_eq!(
1081 clang_kind.try_into(),
1082 Ok(EntityKind::Function),
1083 "Trying to parse a non-function into a function"
1084 );
1085 debug!("Parsing Function: {:?}", entity);
1086
1087 let return_type = entity.get_result_type().unwrap().get_display_name();
1088 trace!("Function has return type: {:?}", return_type);
1089 let arguments = entity
1090 .get_arguments()
1091 // TODO: this seems weird, but it fixes a None for a function that takes only a
1092 // variadic argument from its own template declaration.
1093 .unwrap_or_else(|| vec![])
1094 .into_iter()
1095 .map(|arg| {
1096 let name = arg
1097 .get_display_name()
1098 .unwrap_or_else(|| String::from("unnamed"));
1099 let r#type = arg.get_type().unwrap().get_display_name();
1100 trace!("Function has argument {:?} of type {:?}", name, r#type);
1101 FunctionArgument { name, r#type }
1102 })
1103 .collect();
1104
1105 let kind = match clang_kind {
1106 clang::EntityKind::FunctionDecl | clang::EntityKind::FunctionTemplate => {
1107 FunctionKind::Function
1108 }
1109 clang::EntityKind::Method
1110 | clang::EntityKind::Constructor
1111 | clang::EntityKind::Destructor => FunctionKind::Method,
1112 // We panic here because we've asserted the type in the beginning
1113 other => panic!("Trying to parse {:?} as a function", other),
1114 };
1115
1116 Ok(Function {
1117 kind,
1118 arguments,
1119 return_type,
1120 })
1121 }
470} 1122}
471 1123
472impl ClangEntity for Typedef { 1124// ============
473 fn kind(&self) -> ClangEntityKind { 1125// === Enum ===
474 ClangEntityKind::Typedef 1126// ============
1127
1128entity! {
1129 pub(super) struct Enum {
1130 underlying_type: String,
1131 #children => [
1132 constants: EnumConstant,
1133 ],
475 } 1134 }
476} 1135}
477 1136
478impl From<Typedef> for PartialEntity { 1137impl KindName for Enum {
479 fn from(entity: Typedef) -> Self { 1138 fn kind_name_singular(&self) -> &'static str {
480 let mut properties = Map::with_capacity(1); 1139 "enum"
481 properties.insert(String::from("referee"), JSONValue::String(entity.referee)); 1140 }
1141
1142 fn kind_name_plural(&self) -> &'static str {
1143 "enums"
1144 }
1145}
482 1146
483 PartialEntity { 1147impl<'a> TryFrom<clang::Entity<'a>> for Enum {
484 properties, 1148 type Error = Error;
485 children: Default::default(), 1149
1150 fn try_from(entity: clang::Entity) -> Result<Self, Error> {
1151 assert_eq!(
1152 entity.get_kind().try_into(),
1153 Ok(EntityKind::Enum),
1154 "Trying to parse a non-type alias into a type alias"
1155 );
1156 debug!("Parsing enum: {:?}", entity);
1157
1158 let underlying_type = entity
1159 .get_enum_underlying_type()
1160 .ok_or_else(|| anyhow!("No enum underlying type"))?
1161 .get_display_name();
1162
1163 let mut constants = BTreeMap::new();
1164 for child in entity.get_children() {
1165 trace!("Enum has child: {:?}", child);
1166 match child.get_kind().try_into() {
1167 Ok(EntityKind::EnumConstant) => {
1168 let child_usr = child
1169 .get_usr()
1170 .ok_or_else(|| anyhow!("no usr for: {:?}", child))?;
1171 constants.insert(child_usr, Described::<EnumConstant>::try_from(child)?);
1172 }
1173 Ok(other) => warn!("Unsupported child of enum {:?}: {:?}", other, child),
1174 Err(err) => info!("Error while parsing entity {:?}: {}", child, err),
1175 }
486 } 1176 }
1177
1178 Ok(Enum {
1179 underlying_type,
1180 constants,
1181 })
487 } 1182 }
488} 1183}
489 1184
490#[derive(Debug, Clone)] 1185// ======================
491pub(super) struct Enum { 1186// === Enum Constants ===
492 pub(super) underlying_type: String, 1187// ======================
493 pub(super) constants: BTreeMap<Usr, Described<EnumConstant>>, 1188
1189entity! {
1190 pub(super) struct EnumConstant {
1191 value: String,
1192 }
494} 1193}
495 1194
496impl ClangEntity for Enum { 1195impl KindName for EnumConstant {
497 fn kind(&self) -> ClangEntityKind { 1196 fn kind_name_singular(&self) -> &'static str {
498 ClangEntityKind::Enum 1197 "enum variant"
1198 }
1199
1200 fn kind_name_plural(&self) -> &'static str {
1201 "enum variants"
499 } 1202 }
500} 1203}
501 1204
502impl From<Enum> for PartialEntity { 1205impl<'a> TryFrom<clang::Entity<'a>> for EnumConstant {
503 fn from(entity: Enum) -> Self { 1206 type Error = Error;
504 let mut properties = Map::with_capacity(1); 1207
505 properties.insert( 1208 fn try_from(entity: clang::Entity) -> Result<Self, Error> {
506 String::from("underlying-type"), 1209 assert_eq!(
507 JSONValue::String(entity.underlying_type), 1210 entity.get_kind().try_into(),
1211 Ok(EntityKind::EnumConstant),
1212 "Trying to parse a non-type alias into a type alias"
508 ); 1213 );
1214 debug!("Parsing enum: {:?}", entity);
1215
1216 let (signed_value, unsigned_value) = entity
1217 .get_enum_constant_value()
1218 .ok_or_else(|| anyhow!("No enum constant value"))?;
1219
1220 let is_signed = entity
1221 .get_semantic_parent()
1222 .ok_or_else(|| anyhow!("Enum constant not attached to an enum"))?
1223 .get_enum_underlying_type()
1224 .ok_or_else(|| anyhow!("Enum doesn't have an underlying type"))?
1225 .get_canonical_type()
1226 .is_signed_integer();
1227
1228 let value = if is_signed {
1229 format!("{}", signed_value)
1230 } else {
1231 format!("{}", unsigned_value)
1232 };
1233
1234 Ok(EnumConstant { value })
1235 }
1236}
509 1237
510 let mut children = Default::default(); 1238// ==================
511 append_children(&mut children, entity.constants); 1239// === Type Alias ===
1240// ==================
512 1241
513 PartialEntity { 1242entity! {
514 properties, 1243 pub(super) struct TypeAlias {
515 children, 1244 referee: String,
516 }
517 } 1245 }
518} 1246}
519 1247
520#[derive(Debug, Clone)] 1248impl KindName for TypeAlias {
521pub(super) struct EnumConstant { 1249 fn kind_name_singular(&self) -> &'static str {
522 pub(super) value: String, 1250 "type alias"
523} 1251 }
524 1252
525impl ClangEntity for EnumConstant { 1253 fn kind_name_plural(&self) -> &'static str {
526 fn kind(&self) -> ClangEntityKind { 1254 "type aliases"
527 ClangEntityKind::EnumConstant
528 } 1255 }
529} 1256}
530 1257
531impl From<EnumConstant> for PartialEntity { 1258impl<'a> TryFrom<clang::Entity<'a>> for TypeAlias {
532 fn from(entity: EnumConstant) -> Self { 1259 type Error = Error;
533 let mut properties = Map::with_capacity(1);
534 properties.insert(String::from("value"), JSONValue::String(entity.value));
535 1260
536 PartialEntity { 1261 fn try_from(entity: clang::Entity) -> Result<Self, Error> {
537 properties, 1262 assert_eq!(
538 children: Default::default(), 1263 entity.get_kind().try_into(),
539 } 1264 Ok(EntityKind::TypeAlias),
1265 "Trying to parse a non-type alias into a type alias"
1266 );
1267 debug!("Parsing typedef: {:?}", entity);
1268
1269 let referee = entity
1270 .get_typedef_underlying_type()
1271 .ok_or_else(|| anyhow!("No underlying type"))?
1272 .get_display_name();
1273
1274 Ok(TypeAlias { referee })
540 } 1275 }
541} 1276}