diff options
Diffstat (limited to 'src/parser')
-rw-r--r-- | src/parser/clang/entities.rs | 55 | ||||
-rw-r--r-- | src/parser/clang/mod.rs | 2 | ||||
-rw-r--r-- | src/parser/clang/parsing.rs | 282 |
3 files changed, 255 insertions, 84 deletions
diff --git a/src/parser/clang/entities.rs b/src/parser/clang/entities.rs index cbc17b7..a5b6462 100644 --- a/src/parser/clang/entities.rs +++ b/src/parser/clang/entities.rs | |||
@@ -14,6 +14,7 @@ pub(super) struct Children { | |||
14 | variables: Option<BTreeMap<Usr, Described<Variable>>>, | 14 | variables: Option<BTreeMap<Usr, Described<Variable>>>, |
15 | structs: Option<BTreeMap<Usr, Described<Struct>>>, | 15 | structs: Option<BTreeMap<Usr, Described<Struct>>>, |
16 | functions: Option<BTreeMap<Usr, Described<Function>>>, | 16 | functions: Option<BTreeMap<Usr, Described<Function>>>, |
17 | typedefs: Option<BTreeMap<Usr, Described<Typedef>>>, | ||
17 | } | 18 | } |
18 | 19 | ||
19 | #[derive(Debug, Clone, Copy, PartialEq, Eq)] | 20 | #[derive(Debug, Clone, Copy, PartialEq, Eq)] |
@@ -22,6 +23,7 @@ pub(super) enum ClangEntityKind { | |||
22 | Variable(VariableKind), | 23 | Variable(VariableKind), |
23 | Struct(StructKind), | 24 | Struct(StructKind), |
24 | Function(FunctionKind), | 25 | Function(FunctionKind), |
26 | Typedef, | ||
25 | } | 27 | } |
26 | 28 | ||
27 | #[derive(Debug, Clone, Copy, PartialEq, Eq)] | 29 | #[derive(Debug, Clone, Copy, PartialEq, Eq)] |
@@ -52,6 +54,7 @@ impl ClangEntityKind { | |||
52 | ClangEntityKind::Struct(StructKind::Class) => "class", | 54 | ClangEntityKind::Struct(StructKind::Class) => "class", |
53 | ClangEntityKind::Function(FunctionKind::Function) => "function", | 55 | ClangEntityKind::Function(FunctionKind::Function) => "function", |
54 | ClangEntityKind::Function(FunctionKind::Method) => "method", | 56 | ClangEntityKind::Function(FunctionKind::Method) => "method", |
57 | ClangEntityKind::Typedef => "typedef", | ||
55 | } | 58 | } |
56 | } | 59 | } |
57 | 60 | ||
@@ -64,6 +67,7 @@ impl ClangEntityKind { | |||
64 | ClangEntityKind::Struct(StructKind::Class) => "classes", | 67 | ClangEntityKind::Struct(StructKind::Class) => "classes", |
65 | ClangEntityKind::Function(FunctionKind::Function) => "functions", | 68 | ClangEntityKind::Function(FunctionKind::Function) => "functions", |
66 | ClangEntityKind::Function(FunctionKind::Method) => "methods", | 69 | ClangEntityKind::Function(FunctionKind::Method) => "methods", |
70 | ClangEntityKind::Typedef => "typedefs", | ||
67 | } | 71 | } |
68 | } | 72 | } |
69 | } | 73 | } |
@@ -80,12 +84,19 @@ impl TryFrom<EntityKind> for ClangEntityKind { | |||
80 | EntityKind::Namespace => ClangEntityKind::Namespace, | 84 | EntityKind::Namespace => ClangEntityKind::Namespace, |
81 | EntityKind::VarDecl => ClangEntityKind::Variable(VariableKind::Variable), | 85 | EntityKind::VarDecl => ClangEntityKind::Variable(VariableKind::Variable), |
82 | EntityKind::FieldDecl => ClangEntityKind::Variable(VariableKind::Field), | 86 | EntityKind::FieldDecl => ClangEntityKind::Variable(VariableKind::Field), |
83 | EntityKind::FunctionDecl => ClangEntityKind::Function(FunctionKind::Function), | 87 | EntityKind::FunctionDecl | EntityKind::FunctionTemplate => { |
84 | EntityKind::Method | EntityKind::Constructor => { | 88 | ClangEntityKind::Function(FunctionKind::Function) |
89 | } | ||
90 | EntityKind::Method | EntityKind::Constructor | EntityKind::Destructor => { | ||
85 | ClangEntityKind::Function(FunctionKind::Method) | 91 | ClangEntityKind::Function(FunctionKind::Method) |
86 | } | 92 | } |
87 | EntityKind::StructDecl => ClangEntityKind::Struct(StructKind::Struct), | 93 | EntityKind::StructDecl => ClangEntityKind::Struct(StructKind::Struct), |
88 | EntityKind::ClassDecl => ClangEntityKind::Struct(StructKind::Class), | 94 | EntityKind::ClassDecl | EntityKind::ClassTemplate => { |
95 | ClangEntityKind::Struct(StructKind::Class) | ||
96 | } | ||
97 | EntityKind::TypedefDecl | ||
98 | | EntityKind::TypeAliasDecl | ||
99 | | EntityKind::TypeAliasTemplateDecl => ClangEntityKind::Typedef, | ||
89 | kind => return Err(TryFromEntityKindError(format!("{:?}", kind))), | 100 | kind => return Err(TryFromEntityKindError(format!("{:?}", kind))), |
90 | }) | 101 | }) |
91 | } | 102 | } |
@@ -106,6 +117,9 @@ pub(super) trait ClangEntity { | |||
106 | fn get_member_functions(&mut self) -> Option<&mut BTreeMap<Usr, Described<Function>>> { | 117 | fn get_member_functions(&mut self) -> Option<&mut BTreeMap<Usr, Described<Function>>> { |
107 | None | 118 | None |
108 | } | 119 | } |
120 | fn get_member_typedefs(&mut self) -> Option<&mut BTreeMap<Usr, Described<Typedef>>> { | ||
121 | None | ||
122 | } | ||
109 | 123 | ||
110 | fn into_children(self) -> Children | 124 | fn into_children(self) -> Children |
111 | where | 125 | where |
@@ -116,6 +130,7 @@ pub(super) trait ClangEntity { | |||
116 | variables: None, | 130 | variables: None, |
117 | structs: None, | 131 | structs: None, |
118 | functions: None, | 132 | functions: None, |
133 | typedefs: None, | ||
119 | } | 134 | } |
120 | } | 135 | } |
121 | } | 136 | } |
@@ -169,12 +184,23 @@ where | |||
169 | } | 184 | } |
170 | } | 185 | } |
171 | 186 | ||
187 | impl<U> NamespaceParentManipulation<Typedef> for U | ||
188 | where | ||
189 | U: ClangEntity, | ||
190 | { | ||
191 | fn get_members_mut(&mut self) -> Option<&mut BTreeMap<Usr, Described<Typedef>>> { | ||
192 | self.get_member_typedefs() | ||
193 | } | ||
194 | } | ||
195 | |||
172 | fn entity_id(usr: Usr) -> EntityId { | 196 | fn entity_id(usr: Usr) -> EntityId { |
173 | // This is a somewhat ugly workaround, because Pandoc parses markdown identifiers as alphanum | 197 | // This is a somewhat ugly workaround, because Pandoc parses markdown identifiers as alphanum |
174 | // or one of "-_:.", which means Pandoc can't parse libclang's USRs in title ids and related. | 198 | // or one of "-_:.", which means Pandoc can't parse libclang's USRs in title ids and related. |
175 | // | 199 | // |
176 | // <https://github.com/jgm/pandoc/blob/2.9/src/Text/Pandoc/Readers/Markdown.hs#L581> | 200 | // <https://github.com/jgm/pandoc/blob/2.9/src/Text/Pandoc/Readers/Markdown.hs#L581> |
177 | EntityId(usr.0.replace("@", "::").replace("#", ".").replace("$", "-")) | 201 | EntityId( |
202 | usr.0.replace("@", "::").replace("#", ".").replace("$", "-") | ||
203 | ) | ||
178 | } | 204 | } |
179 | 205 | ||
180 | fn append_children<T: ClangEntity>( | 206 | fn append_children<T: ClangEntity>( |
@@ -243,6 +269,7 @@ pub(super) struct Namespace { | |||
243 | pub(super) member_variables: BTreeMap<Usr, Described<Variable>>, | 269 | pub(super) member_variables: BTreeMap<Usr, Described<Variable>>, |
244 | pub(super) member_structs: BTreeMap<Usr, Described<Struct>>, | 270 | pub(super) member_structs: BTreeMap<Usr, Described<Struct>>, |
245 | pub(super) member_functions: BTreeMap<Usr, Described<Function>>, | 271 | pub(super) member_functions: BTreeMap<Usr, Described<Function>>, |
272 | pub(super) member_typedefs: BTreeMap<Usr, Described<Typedef>>, | ||
246 | } | 273 | } |
247 | 274 | ||
248 | impl ClangEntity for Namespace { | 275 | impl ClangEntity for Namespace { |
@@ -262,6 +289,9 @@ impl ClangEntity for Namespace { | |||
262 | fn get_member_functions(&mut self) -> Option<&mut BTreeMap<Usr, Described<Function>>> { | 289 | fn get_member_functions(&mut self) -> Option<&mut BTreeMap<Usr, Described<Function>>> { |
263 | Some(&mut self.member_functions) | 290 | Some(&mut self.member_functions) |
264 | } | 291 | } |
292 | fn get_member_typedefs(&mut self) -> Option<&mut BTreeMap<Usr, Described<Typedef>>> { | ||
293 | Some(&mut self.member_typedefs) | ||
294 | } | ||
265 | 295 | ||
266 | fn into_children(self) -> Children { | 296 | fn into_children(self) -> Children { |
267 | Children { | 297 | Children { |
@@ -269,6 +299,7 @@ impl ClangEntity for Namespace { | |||
269 | variables: Some(self.member_variables), | 299 | variables: Some(self.member_variables), |
270 | structs: Some(self.member_structs), | 300 | structs: Some(self.member_structs), |
271 | functions: Some(self.member_functions), | 301 | functions: Some(self.member_functions), |
302 | typedefs: Some(self.member_typedefs), | ||
272 | } | 303 | } |
273 | } | 304 | } |
274 | } | 305 | } |
@@ -314,6 +345,7 @@ pub(super) struct Struct { | |||
314 | pub(super) member_variables: BTreeMap<Usr, Described<Variable>>, | 345 | pub(super) member_variables: BTreeMap<Usr, Described<Variable>>, |
315 | pub(super) member_structs: BTreeMap<Usr, Described<Struct>>, | 346 | pub(super) member_structs: BTreeMap<Usr, Described<Struct>>, |
316 | pub(super) member_functions: BTreeMap<Usr, Described<Function>>, | 347 | pub(super) member_functions: BTreeMap<Usr, Described<Function>>, |
348 | pub(super) member_typedefs: BTreeMap<Usr, Described<Typedef>>, | ||
317 | } | 349 | } |
318 | 350 | ||
319 | impl ClangEntity for Struct { | 351 | impl ClangEntity for Struct { |
@@ -330,6 +362,9 @@ impl ClangEntity for Struct { | |||
330 | fn get_member_functions(&mut self) -> Option<&mut BTreeMap<Usr, Described<Function>>> { | 362 | fn get_member_functions(&mut self) -> Option<&mut BTreeMap<Usr, Described<Function>>> { |
331 | Some(&mut self.member_functions) | 363 | Some(&mut self.member_functions) |
332 | } | 364 | } |
365 | fn get_member_typedefs(&mut self) -> Option<&mut BTreeMap<Usr, Described<Typedef>>> { | ||
366 | Some(&mut self.member_typedefs) | ||
367 | } | ||
333 | 368 | ||
334 | fn into_children(self) -> Children { | 369 | fn into_children(self) -> Children { |
335 | Children { | 370 | Children { |
@@ -337,6 +372,7 @@ impl ClangEntity for Struct { | |||
337 | variables: Some(self.member_variables), | 372 | variables: Some(self.member_variables), |
338 | structs: Some(self.member_structs), | 373 | structs: Some(self.member_structs), |
339 | functions: Some(self.member_functions), | 374 | functions: Some(self.member_functions), |
375 | typedefs: Some(self.member_typedefs), | ||
340 | } | 376 | } |
341 | } | 377 | } |
342 | } | 378 | } |
@@ -381,3 +417,14 @@ pub(super) struct FunctionArgument { | |||
381 | pub(super) name: String, | 417 | pub(super) name: String, |
382 | pub(super) r#type: String, | 418 | pub(super) r#type: String, |
383 | } | 419 | } |
420 | |||
421 | #[derive(Debug, Clone)] | ||
422 | pub(super) struct Typedef { | ||
423 | pub(super) referee: String, | ||
424 | } | ||
425 | |||
426 | impl ClangEntity for Typedef { | ||
427 | fn kind(&self) -> ClangEntityKind { | ||
428 | ClangEntityKind::Typedef | ||
429 | } | ||
430 | } | ||
diff --git a/src/parser/clang/mod.rs b/src/parser/clang/mod.rs index 047c49e..da49462 100644 --- a/src/parser/clang/mod.rs +++ b/src/parser/clang/mod.rs | |||
@@ -2,4 +2,4 @@ pub(crate) mod config; | |||
2 | mod entities; | 2 | mod entities; |
3 | mod parsing; | 3 | mod parsing; |
4 | 4 | ||
5 | pub(crate) use parsing::parse_compile_commands; | 5 | pub(crate) use parsing::{parse_compile_commands, parse_file}; |
diff --git a/src/parser/clang/parsing.rs b/src/parser/clang/parsing.rs index a654681..1f1691f 100644 --- a/src/parser/clang/parsing.rs +++ b/src/parser/clang/parsing.rs | |||
@@ -11,12 +11,15 @@ use std::collections::BTreeMap; | |||
11 | use std::convert::{TryFrom, TryInto}; | 11 | use std::convert::{TryFrom, TryInto}; |
12 | use std::path::{Path, PathBuf}; | 12 | use std::path::{Path, PathBuf}; |
13 | 13 | ||
14 | // TODO: check for use of Extend instead of loop+insert | ||
15 | |||
14 | #[derive(Debug, Default)] | 16 | #[derive(Debug, Default)] |
15 | struct TopLevel { | 17 | struct TopLevel { |
16 | namespaces: BTreeMap<Usr, Described<Namespace>>, | 18 | namespaces: BTreeMap<Usr, Described<Namespace>>, |
17 | variables: BTreeMap<Usr, Described<Variable>>, | 19 | variables: BTreeMap<Usr, Described<Variable>>, |
18 | structs: BTreeMap<Usr, Described<Struct>>, | 20 | structs: BTreeMap<Usr, Described<Struct>>, |
19 | functions: BTreeMap<Usr, Described<Function>>, | 21 | functions: BTreeMap<Usr, Described<Function>>, |
22 | typedefs: BTreeMap<Usr, Described<Typedef>>, | ||
20 | } | 23 | } |
21 | 24 | ||
22 | /* | 25 | /* |
@@ -82,6 +85,9 @@ impl TopLevel { | |||
82 | ClangEntityKind::Struct(_) => { | 85 | ClangEntityKind::Struct(_) => { |
83 | &mut parent.get_member_structs()?.get_mut(&usr)?.entity | 86 | &mut parent.get_member_structs()?.get_mut(&usr)?.entity |
84 | } | 87 | } |
88 | ClangEntityKind::Typedef => { | ||
89 | &mut parent.get_member_typedefs()?.get_mut(&usr)?.entity | ||
90 | } | ||
85 | }) | 91 | }) |
86 | } else { | 92 | } else { |
87 | Some(match path.get_kind().try_into().ok()? { | 93 | Some(match path.get_kind().try_into().ok()? { |
@@ -89,6 +95,7 @@ impl TopLevel { | |||
89 | ClangEntityKind::Variable(_) => &mut self.variables.get_mut(&usr)?.entity, | 95 | ClangEntityKind::Variable(_) => &mut self.variables.get_mut(&usr)?.entity, |
90 | ClangEntityKind::Struct(_) => &mut self.structs.get_mut(&usr)?.entity, | 96 | ClangEntityKind::Struct(_) => &mut self.structs.get_mut(&usr)?.entity, |
91 | ClangEntityKind::Function(_) => &mut self.functions.get_mut(&usr)?.entity, | 97 | ClangEntityKind::Function(_) => &mut self.functions.get_mut(&usr)?.entity, |
98 | ClangEntityKind::Typedef => &mut self.typedefs.get_mut(&usr)?.entity, | ||
92 | }) | 99 | }) |
93 | } | 100 | } |
94 | } | 101 | } |
@@ -121,7 +128,10 @@ impl TopLevel { | |||
121 | .insert(usr, entity); | 128 | .insert(usr, entity); |
122 | Ok(()) | 129 | Ok(()) |
123 | } else { | 130 | } else { |
124 | Err(anyhow!("has parent but no parent in tree")) | 131 | Err(anyhow!( |
132 | "has parent: {:?} but no parent in tree", | ||
133 | parent_path | ||
134 | )) | ||
125 | } | 135 | } |
126 | } else { | 136 | } else { |
127 | self.insert_toplevel(usr, entity); | 137 | self.insert_toplevel(usr, entity); |
@@ -175,6 +185,12 @@ impl TopLevelManipulation<Struct> for TopLevel { | |||
175 | } | 185 | } |
176 | } | 186 | } |
177 | 187 | ||
188 | impl TopLevelManipulation<Typedef> for TopLevel { | ||
189 | fn insert_toplevel(&mut self, usr: Usr, entity: Described<Typedef>) { | ||
190 | self.typedefs.insert(usr, entity); | ||
191 | } | ||
192 | } | ||
193 | |||
178 | /* | 194 | /* |
179 | trait FromTopLevel: ClangEntity + Sized { | 195 | trait FromTopLevel: ClangEntity + Sized { |
180 | fn from_toplevel<'a>(toplevel: &'a mut TopLevel, usr: &Usr) -> Option<&'a mut Described<Self>>; | 196 | fn from_toplevel<'a>(toplevel: &'a mut TopLevel, usr: &Usr) -> Option<&'a mut Described<Self>>; |
@@ -268,7 +284,7 @@ pub(crate) fn parse_compile_commands( | |||
268 | &codemap, | 284 | &codemap, |
269 | )?; | 285 | )?; |
270 | 286 | ||
271 | trace!("Changing directory to: {:?}", directory); | 287 | trace!("Changing directory to: {:?}", toplevel_directory); |
272 | std::env::set_current_dir(&toplevel_directory).with_context(|| { | 288 | std::env::set_current_dir(&toplevel_directory).with_context(|| { |
273 | format!( | 289 | format!( |
274 | "Cannot change current directory to: {:?}", | 290 | "Cannot change current directory to: {:?}", |
@@ -277,74 +293,77 @@ pub(crate) fn parse_compile_commands( | |||
277 | })?; | 293 | })?; |
278 | } | 294 | } |
279 | 295 | ||
280 | let normalized_entities = entities | 296 | Ok(entities.into()) |
281 | .namespaces | ||
282 | .into_iter() | ||
283 | .map(|(usr, entity)| (EntityId(usr.0), entity.into())) | ||
284 | .chain( | ||
285 | entities | ||
286 | .variables | ||
287 | .into_iter() | ||
288 | .map(|(usr, entity)| (EntityId(usr.0), entity.into())), | ||
289 | ) | ||
290 | .chain( | ||
291 | entities | ||
292 | .structs | ||
293 | .into_iter() | ||
294 | .map(|(usr, entity)| (EntityId(usr.0), entity.into())), | ||
295 | ) | ||
296 | .chain( | ||
297 | entities | ||
298 | .functions | ||
299 | .into_iter() | ||
300 | .map(|(usr, entity)| (EntityId(usr.0), entity.into())), | ||
301 | ) | ||
302 | .collect(); | ||
303 | |||
304 | Ok(normalized_entities) | ||
305 | } | 297 | } |
306 | 298 | ||
307 | /* | 299 | pub(crate) fn parse_file<T>( |
308 | pub(crate) fn parse_file<T, S>(path: T, extra_args: &[S]) -> EntitiesManager | 300 | path: T, |
301 | config: &Config, | ||
302 | codemap: &mut CodeMap, | ||
303 | ) -> Result<BTreeMap<EntityId, Entity>> | ||
309 | where | 304 | where |
310 | T: Into<PathBuf>, | 305 | T: Into<PathBuf>, |
311 | T: AsRef<Path>, | 306 | T: AsRef<Path>, |
312 | T: ToString, | 307 | T: ToString, |
313 | S: AsRef<str>, | ||
314 | S: std::fmt::Debug, | ||
315 | { | 308 | { |
316 | let mut codemap = CodeMap::new(); | ||
317 | let file_map = codemap.add_file(path.to_string(), std::fs::read_to_string(&path).unwrap()); | ||
318 | let file_span = file_map.span; | ||
319 | |||
320 | let clang = Clang::new().unwrap(); | 309 | let clang = Clang::new().unwrap(); |
321 | let index = Index::new(&clang, true, false); | 310 | let index = Index::new(&clang, true, false); |
322 | let mut parser = index.parser(path); | ||
323 | parser.skip_function_bodies(true); | ||
324 | 311 | ||
325 | parser.arguments(&extra_args); | 312 | // as provided in the command line |
313 | let filename = path.to_string(); | ||
314 | let file_map = codemap.add_file(filename.clone(), std::fs::read_to_string(&path)?); | ||
326 | 315 | ||
327 | if log_enabled!(log::Level::Debug) { | 316 | let path = path.as_ref().canonicalize()?; |
328 | for extra_arg in extra_args { | 317 | let toplevel_directory = std::env::current_dir().context("Cannot read current directory")?; |
329 | debug!("Extra libclang argument: {:?}", extra_arg); | 318 | |
330 | } | 319 | let maybe_commands = CompilationDatabase::from_directory(&config.compile_commands_location) |
320 | .and_then(|database| database.get_compile_commands(&path)) | ||
321 | .ok(); | ||
322 | let maybe_command = maybe_commands | ||
323 | .as_ref() | ||
324 | .and_then(|commands| commands.get_commands().pop()); | ||
325 | |||
326 | let mut clang_arguments = maybe_command | ||
327 | .map(|command| command.get_arguments()) | ||
328 | .unwrap_or_default(); | ||
329 | clang_arguments.extend_from_slice(&config.extra_args); | ||
330 | |||
331 | if let Some(command) = maybe_command { | ||
332 | let directory = command.get_directory(); | ||
333 | trace!("Changing directory to: {:?}", directory); | ||
334 | std::env::set_current_dir(&directory) | ||
335 | .with_context(|| format!("Cannot change current directory to: {:?}", directory))?; | ||
331 | } | 336 | } |
332 | 337 | ||
333 | let trans_unit = parser.parse().unwrap(); | 338 | let mut parser = index.parser(""); |
334 | let mut entities = EntitiesManager::new(); | 339 | parser.skip_function_bodies(true); |
340 | |||
341 | parser.arguments(&clang_arguments); | ||
342 | |||
343 | trace!("Parsing with libclang arguments: {:?}", clang_arguments); | ||
344 | |||
345 | let mut entities = TopLevel::default(); | ||
335 | 346 | ||
336 | parse_unit( | 347 | parse_unit( |
337 | &trans_unit, | 348 | &parser |
349 | .parse() | ||
350 | .with_context(|| format!("Could not parse file: {:?}", filename))?, | ||
338 | &mut entities, | 351 | &mut entities, |
339 | &std::env::current_dir().unwrap(), | 352 | &toplevel_directory, |
340 | file_span, | 353 | file_map.span, |
341 | &codemap, | 354 | &codemap, |
342 | ) | 355 | )?; |
343 | .unwrap(); | ||
344 | 356 | ||
345 | entities | 357 | trace!("Changing directory to: {:?}", toplevel_directory); |
358 | std::env::set_current_dir(&toplevel_directory).with_context(|| { | ||
359 | format!( | ||
360 | "Cannot change current directory to: {:?}", | ||
361 | toplevel_directory | ||
362 | ) | ||
363 | })?; | ||
364 | |||
365 | Ok(entities.into()) | ||
346 | } | 366 | } |
347 | */ | ||
348 | 367 | ||
349 | fn parse_unit( | 368 | fn parse_unit( |
350 | trans_unit: &TranslationUnit, | 369 | trans_unit: &TranslationUnit, |
@@ -355,10 +374,7 @@ fn parse_unit( | |||
355 | ) -> Result<()> { | 374 | ) -> Result<()> { |
356 | trans_unit.get_entity().visit_children(|entity, _parent| { | 375 | trans_unit.get_entity().visit_children(|entity, _parent| { |
357 | if is_in_system_header(entity, &base_dir) { | 376 | if is_in_system_header(entity, &base_dir) { |
358 | trace!( | 377 | trace!("Entity is in system header, skipping: {:?}", entity); |
359 | "Entity is in system header, skipping: USR = {:?}", | ||
360 | entity.get_display_name() | ||
361 | ); | ||
362 | return clang::EntityVisitResult::Continue; | 378 | return clang::EntityVisitResult::Continue; |
363 | } | 379 | } |
364 | 380 | ||
@@ -374,12 +390,13 @@ fn parse_unit( | |||
374 | add_entity(entity, entities, file_span, codemap) | 390 | add_entity(entity, entities, file_span, codemap) |
375 | }); | 391 | }); |
376 | 392 | ||
377 | /* | ||
378 | use codemap_diagnostic::{ColorConfig, Emitter}; | 393 | use codemap_diagnostic::{ColorConfig, Emitter}; |
379 | 394 | ||
380 | let mut emitter = Emitter::stderr(ColorConfig::Auto, Some(&codemap)); | 395 | let mut emitter = Emitter::stderr(ColorConfig::Auto, Some(&codemap)); |
381 | 396 | ||
382 | for diagnostic in trans_unit.get_diagnostics().iter() { | 397 | for diagnostic in trans_unit.get_diagnostics().iter() { |
398 | warn!("{}", diagnostic); | ||
399 | /* | ||
383 | let main_diag = match clang_diag_to_codemap_diag(&diagnostic, file_span) { | 400 | let main_diag = match clang_diag_to_codemap_diag(&diagnostic, file_span) { |
384 | Some(diag) => diag, | 401 | Some(diag) => diag, |
385 | None => continue, | 402 | None => continue, |
@@ -401,8 +418,8 @@ fn parse_unit( | |||
401 | .chain(fix_it_diags) | 418 | .chain(fix_it_diags) |
402 | .collect::<Vec<_>>(), | 419 | .collect::<Vec<_>>(), |
403 | ); | 420 | ); |
421 | */ | ||
404 | } | 422 | } |
405 | */ | ||
406 | 423 | ||
407 | Ok(()) | 424 | Ok(()) |
408 | } | 425 | } |
@@ -412,11 +429,12 @@ fn is_in_system_header(entity: clang::Entity, base_dir: impl AsRef<Path>) -> boo | |||
412 | true | 429 | true |
413 | } else if let Some(location) = entity.get_location() { | 430 | } else if let Some(location) = entity.get_location() { |
414 | if let Some(file) = location.get_file_location().file { | 431 | if let Some(file) = location.get_file_location().file { |
415 | !file | 432 | // !file |
416 | .get_path() | 433 | // .get_path() |
417 | .canonicalize() | 434 | // .canonicalize() |
418 | .unwrap() | 435 | // .unwrap() |
419 | .starts_with(base_dir) | 436 | // .starts_with(base_dir) |
437 | false | ||
420 | } else { | 438 | } else { |
421 | // Not defined in a file? probably shouldn't document | 439 | // Not defined in a file? probably shouldn't document |
422 | true | 440 | true |
@@ -481,7 +499,8 @@ fn add_entity( | |||
481 | // if current.has_documentation && !tree.has_documentation { | 499 | // if current.has_documentation && !tree.has_documentation { |
482 | // append_documentation | 500 | // append_documentation |
483 | // } | 501 | // } |
484 | } else if libclang_entity.is_definition() { | 502 | } else { |
503 | //if libclang_entity.is_definition() { | ||
485 | // TODO: This probably means that you can't put documentation in forward declarations. | 504 | // TODO: This probably means that you can't put documentation in forward declarations. |
486 | // TODO: Ad-hoc toplevel functions are not documented | 505 | // TODO: Ad-hoc toplevel functions are not documented |
487 | // | 506 | // |
@@ -492,19 +511,32 @@ fn add_entity( | |||
492 | // when we see the definition. | 511 | // when we see the definition. |
493 | 512 | ||
494 | let result = match kind { | 513 | let result = match kind { |
495 | ClangEntityKind::Namespace => Described::<Namespace>::try_from(libclang_entity) | 514 | ClangEntityKind::Namespace => { |
496 | .and_then(|namespace| toplevel.insert(libclang_entity, namespace)), | 515 | if libclang_entity.get_name().is_some() { |
516 | Described::<Namespace>::try_from(libclang_entity) | ||
517 | .and_then(|namespace| toplevel.insert(libclang_entity, namespace)) | ||
518 | } else { | ||
519 | Ok(()) | ||
520 | } | ||
521 | } | ||
497 | ClangEntityKind::Variable(_) => Described::<Variable>::try_from(libclang_entity) | 522 | ClangEntityKind::Variable(_) => Described::<Variable>::try_from(libclang_entity) |
498 | .and_then(|variable| toplevel.insert(libclang_entity, variable)), | 523 | .and_then(|variable| toplevel.insert(libclang_entity, variable)), |
499 | ClangEntityKind::Struct(_) => Described::<Struct>::try_from(libclang_entity) | 524 | ClangEntityKind::Struct(_) => Described::<Struct>::try_from(libclang_entity) |
500 | .and_then(|r#struct| toplevel.insert(libclang_entity, r#struct)), | 525 | .and_then(|r#struct| toplevel.insert(libclang_entity, r#struct)), |
501 | ClangEntityKind::Function(_) => Described::<Function>::try_from(libclang_entity) | 526 | ClangEntityKind::Function(_) => Described::<Function>::try_from(libclang_entity) |
502 | .and_then(|function| toplevel.insert(libclang_entity, function)), | 527 | .and_then(|function| toplevel.insert(libclang_entity, function)), |
528 | ClangEntityKind::Typedef => Described::<Typedef>::try_from(libclang_entity) | ||
529 | .and_then(|function| toplevel.insert(libclang_entity, function)), | ||
503 | }; | 530 | }; |
504 | // TODO: check result | 531 | // TODO: check result |
532 | |||
533 | if let Err(err) = result { | ||
534 | error!("{}: {:?}", err, libclang_entity); | ||
535 | return ::clang::EntityVisitResult::Continue; | ||
536 | } | ||
505 | } | 537 | } |
506 | 538 | ||
507 | if kind == ClangEntityKind::Namespace { | 539 | if kind == ClangEntityKind::Namespace && libclang_entity.get_name().is_some() { |
508 | // Recurse here since namespace definitions are allowed to change between translation units. | 540 | // Recurse here since namespace definitions are allowed to change between translation units. |
509 | ::clang::EntityVisitResult::Recurse | 541 | ::clang::EntityVisitResult::Recurse |
510 | } else { | 542 | } else { |
@@ -512,6 +544,40 @@ fn add_entity( | |||
512 | } | 544 | } |
513 | } | 545 | } |
514 | 546 | ||
547 | impl From<TopLevel> for BTreeMap<EntityId, Entity> { | ||
548 | fn from(toplevel: TopLevel) -> Self { | ||
549 | toplevel | ||
550 | .namespaces | ||
551 | .into_iter() | ||
552 | .map(|(usr, entity)| (EntityId(usr.0), entity.into())) | ||
553 | .chain( | ||
554 | toplevel | ||
555 | .variables | ||
556 | .into_iter() | ||
557 | .map(|(usr, entity)| (EntityId(usr.0), entity.into())), | ||
558 | ) | ||
559 | .chain( | ||
560 | toplevel | ||
561 | .structs | ||
562 | .into_iter() | ||
563 | .map(|(usr, entity)| (EntityId(usr.0), entity.into())), | ||
564 | ) | ||
565 | .chain( | ||
566 | toplevel | ||
567 | .functions | ||
568 | .into_iter() | ||
569 | .map(|(usr, entity)| (EntityId(usr.0), entity.into())), | ||
570 | ) | ||
571 | .chain( | ||
572 | toplevel | ||
573 | .typedefs | ||
574 | .into_iter() | ||
575 | .map(|(usr, entity)| (EntityId(usr.0), entity.into())), | ||
576 | ) | ||
577 | .collect() | ||
578 | } | ||
579 | } | ||
580 | |||
515 | impl<'a, T> TryFrom<clang::Entity<'a>> for Described<T> | 581 | impl<'a, T> TryFrom<clang::Entity<'a>> for Described<T> |
516 | where | 582 | where |
517 | T: TryFrom<clang::Entity<'a>, Error = Error>, | 583 | T: TryFrom<clang::Entity<'a>, Error = Error>, |
@@ -544,6 +610,7 @@ impl<'a> TryFrom<clang::Entity<'a>> for Namespace { | |||
544 | member_variables: Default::default(), | 610 | member_variables: Default::default(), |
545 | member_structs: Default::default(), | 611 | member_structs: Default::default(), |
546 | member_functions: Default::default(), | 612 | member_functions: Default::default(), |
613 | member_typedefs: Default::default(), | ||
547 | }) | 614 | }) |
548 | } | 615 | } |
549 | } | 616 | } |
@@ -580,31 +647,65 @@ impl<'a> TryFrom<clang::Entity<'a>> for Struct { | |||
580 | Ok(ClangEntityKind::Struct(kind)) => { | 647 | Ok(ClangEntityKind::Struct(kind)) => { |
581 | struct_kind = kind; | 648 | struct_kind = kind; |
582 | } | 649 | } |
583 | _ => panic!("Trying to parse a non-class into a class"), | 650 | _ => panic!("Trying to parse a non-struct into a struct"), |
584 | } | 651 | } |
585 | debug!("Parsing Struct: {:?}", entity); | 652 | debug!("Parsing Struct: {:?}", entity); |
586 | 653 | ||
587 | let mut member_variables = BTreeMap::new(); | 654 | let mut member_variables = BTreeMap::new(); |
588 | let mut member_structs = BTreeMap::new(); | 655 | let mut member_structs = BTreeMap::new(); |
589 | let mut member_functions = BTreeMap::new(); | 656 | let mut member_functions = BTreeMap::new(); |
657 | let mut member_typedefs = BTreeMap::new(); | ||
590 | 658 | ||
591 | for child in entity.get_children() { | 659 | for child in entity.get_children() { |
592 | trace!("Struct has child: {:?}", child); | 660 | trace!("Struct has child: {:?}", child); |
593 | 661 | ||
594 | match child.get_kind().try_into() { | 662 | let kind = child.get_kind(); |
595 | Ok(ClangEntityKind::Variable(_)) => { | 663 | |
596 | let child_usr = child.get_usr().ok_or_else(|| anyhow!("no usr"))?; | 664 | match kind { |
597 | member_variables.insert(child_usr, Described::<Variable>::try_from(child)?); | 665 | ::clang::EntityKind::AccessSpecifier | ::clang::EntityKind::BaseSpecifier => { |
666 | continue | ||
598 | } | 667 | } |
599 | Ok(ClangEntityKind::Struct(_)) => { | 668 | _ => {} |
600 | let child_usr: Usr = child.get_usr().ok_or_else(|| anyhow!("no usr"))?; | 669 | } |
601 | member_structs.insert(child_usr, Described::<Struct>::try_from(child)?); | 670 | |
671 | let mut parse_child = || -> Result<()> { | ||
672 | match kind.try_into() { | ||
673 | Ok(ClangEntityKind::Variable(_)) => { | ||
674 | let child_usr = child | ||
675 | .get_usr() | ||
676 | .ok_or_else(|| anyhow!("no usr for: {:?}", child))?; | ||
677 | member_variables.insert(child_usr, Described::<Variable>::try_from(child)?); | ||
678 | } | ||
679 | Ok(ClangEntityKind::Struct(_)) => { | ||
680 | let child_usr: Usr = child | ||
681 | .get_usr() | ||
682 | .ok_or_else(|| anyhow!("no usr for: {:?}", child))?; | ||
683 | member_structs.insert(child_usr, Described::<Struct>::try_from(child)?); | ||
684 | } | ||
685 | Ok(ClangEntityKind::Function(_)) => { | ||
686 | let child_usr = child | ||
687 | .get_usr() | ||
688 | .ok_or_else(|| anyhow!("no usr for: {:?}", child))?; | ||
689 | member_functions.insert(child_usr, Described::<Function>::try_from(child)?); | ||
690 | } | ||
691 | Ok(ClangEntityKind::Typedef) => { | ||
692 | let child_usr = child | ||
693 | .get_usr() | ||
694 | .ok_or_else(|| anyhow!("no usr for: {:?}", child))?; | ||
695 | member_typedefs.insert(child_usr, Described::<Typedef>::try_from(child)?); | ||
696 | } | ||
697 | Ok(other) => warn!("Unsupported child of struct {:?}: {:?}", other, child), | ||
698 | Err(err) => info!("Error while parsing entity {:?}: {}", child, err), | ||
602 | } | 699 | } |
603 | Ok(ClangEntityKind::Function(_)) => { | 700 | |
604 | let child_usr = child.get_usr().ok_or_else(|| anyhow!("no usr"))?; | 701 | Ok(()) |
605 | member_functions.insert(child_usr, Described::<Function>::try_from(child)?); | 702 | }; |
703 | |||
704 | match parse_child() { | ||
705 | Ok(()) => {} | ||
706 | Err(err) => { | ||
707 | warn!("Error while parsing child {:?}: {}", child, err); | ||
606 | } | 708 | } |
607 | _ => trace!("Skipping child"), | ||
608 | } | 709 | } |
609 | } | 710 | } |
610 | 711 | ||
@@ -613,6 +714,7 @@ impl<'a> TryFrom<clang::Entity<'a>> for Struct { | |||
613 | member_functions, | 714 | member_functions, |
614 | member_structs, | 715 | member_structs, |
615 | member_variables, | 716 | member_variables, |
717 | member_typedefs, | ||
616 | }) | 718 | }) |
617 | } | 719 | } |
618 | } | 720 | } |
@@ -634,7 +736,9 @@ impl<'a> TryFrom<clang::Entity<'a>> for Function { | |||
634 | trace!("Function has return type: {:?}", return_type); | 736 | trace!("Function has return type: {:?}", return_type); |
635 | let arguments = entity | 737 | let arguments = entity |
636 | .get_arguments() | 738 | .get_arguments() |
637 | .unwrap() | 739 | // TODO: this seems weird, but it fixes a None for a function that takes only a |
740 | // variadic argument from its own template declaration. | ||
741 | .unwrap_or_else(|| vec![]) | ||
638 | .into_iter() | 742 | .into_iter() |
639 | .map(|arg| { | 743 | .map(|arg| { |
640 | let name = arg | 744 | let name = arg |
@@ -654,6 +758,26 @@ impl<'a> TryFrom<clang::Entity<'a>> for Function { | |||
654 | } | 758 | } |
655 | } | 759 | } |
656 | 760 | ||
761 | impl<'a> TryFrom<clang::Entity<'a>> for Typedef { | ||
762 | type Error = Error; | ||
763 | |||
764 | fn try_from(entity: clang::Entity) -> Result<Self, Error> { | ||
765 | match entity.get_kind().try_into() { | ||
766 | Ok(ClangEntityKind::Typedef) => {} | ||
767 | _ => panic!("Trying to parse a non-typedef into a typedef"), | ||
768 | } | ||
769 | debug!("Parsing typedef: {:?}", entity); | ||
770 | |||
771 | // TODO: unwrap (and unwrap in other similar places too) | ||
772 | let referee = entity | ||
773 | .get_typedef_underlying_type() | ||
774 | .ok_or_else(|| anyhow!("No underlying type"))? | ||
775 | .get_display_name(); | ||
776 | |||
777 | Ok(Typedef { referee }) | ||
778 | } | ||
779 | } | ||
780 | |||
657 | fn get_description(entity: clang::Entity) -> Result<Description> { | 781 | fn get_description(entity: clang::Entity) -> Result<Description> { |
658 | let name = entity | 782 | let name = entity |
659 | .get_display_name() | 783 | .get_display_name() |