diff options
author | Nick Fitzgerald <fitzgen@gmail.com> | 2017-02-07 14:48:48 -0800 |
---|---|---|
committer | Nick Fitzgerald <fitzgen@gmail.com> | 2017-02-08 10:08:36 -0800 |
commit | c8a223e898e883c70f1d4d6b758ffc0cf3dc28d2 (patch) | |
tree | b5cfc91fdf4d5a02cad73ac7b462375d2024b470 | |
parent | 19fe07d8cbef3124cad9394f005c96878422f085 (diff) |
Create PartialType for types we are in the middle of parsing
This commit create the PartialType type to represent types that we are in the
middle of parsing and their cursor where we found them. Additionally, it fixes a
long standing FIXME to make `currently_parsed_types` private. Finally, it
implements `TemplateDeclaration` for `PartialType` so that we can get
information about a partially parsed template declaration type's template
parameters.
-rw-r--r-- | src/ir/context.rs | 86 | ||||
-rw-r--r-- | src/ir/item.rs | 28 | ||||
-rw-r--r-- | src/ir/ty.rs | 2 |
3 files changed, 98 insertions, 18 deletions
diff --git a/src/ir/context.rs b/src/ir/context.rs index edf42ec8..a2277b39 100644 --- a/src/ir/context.rs +++ b/src/ir/context.rs @@ -120,9 +120,7 @@ pub struct BindgenContext<'ctx> { /// We could also use the `types` HashMap, but my intention with it is that /// only valid types and declarations end up there, and this could /// potentially break that assumption. - /// - /// FIXME: Should not be public, though... meh. - pub currently_parsed_types: Vec<(Cursor, ItemId)>, + currently_parsed_types: Vec<PartialType>, /// A HashSet with all the already parsed macro names. This is done to avoid /// hard errors while parsing duplicated macros, as well to allow macro @@ -193,6 +191,26 @@ impl<'ctx> BindgenContext<'ctx> { me } + /// Get the stack of partially parsed types that we are in the middle of + /// parsing. + pub fn currently_parsed_types(&self) -> &[PartialType] { + &self.currently_parsed_types[..] + } + + /// Begin parsing the given partial type, and push it onto the + /// `currently_parsed_types` stack so that we won't infinite recurse if we + /// run into a reference to it while parsing it. + pub fn begin_parsing(&mut self, partial_ty: PartialType) { + self.currently_parsed_types.push(partial_ty); + } + + /// Finish parsing the current partial type, pop it off the + /// `currently_parsed_types` stack, and return it. + pub fn finish_parsing(&mut self) -> PartialType { + self.currently_parsed_types.pop() + .expect("should have been parsing a type, if we finished parsing a type") + } + /// Get the user-provided type chooser by reference, if any. pub fn type_chooser(&self) -> Option<&TypeChooser> { self.options().type_chooser.as_ref().map(|t| &**t) @@ -1156,6 +1174,68 @@ impl<'ctx> BindgenContext<'ctx> { } } +/// A type that we are in the middle of parsing. +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct PartialType { + decl: Cursor, + id: ItemId, +} + +impl PartialType { + /// Construct a new `PartialType`. + pub fn new(decl: Cursor, id: ItemId) -> PartialType { + // assert!(decl == decl.canonical()); + PartialType { + decl: decl, + id: id, + } + } + + /// The cursor pointing to this partial type's declaration location. + pub fn decl(&self) -> &Cursor { + &self.decl + } + + /// The item ID allocated for this type. This is *NOT* a key for an entry in + /// the context's item set yet! + pub fn id(&self) -> ItemId { + self.id + } +} + +impl TemplateDeclaration for PartialType { + fn template_params(&self, _ctx: &BindgenContext) -> Option<Vec<ItemId>> { + // Maybe at some point we will eagerly parse named types, but for now we + // don't and this information is unavailable. + None + } + + fn num_template_params(&self, _ctx: &BindgenContext) -> Option<usize> { + // Wouldn't it be nice if libclang would reliably give us this + // information‽ + match self.decl().kind() { + clang_sys::CXCursor_ClassTemplate | + clang_sys::CXCursor_FunctionTemplate | + clang_sys::CXCursor_TypeAliasTemplateDecl => { + let mut num_params = 0; + self.decl().visit(|c| { + match c.kind() { + clang_sys::CXCursor_TemplateTypeParameter | + clang_sys::CXCursor_TemplateTemplateParameter | + clang_sys::CXCursor_NonTypeTemplateParameter => { + num_params += 1; + } + _ => {} + }; + clang_sys::CXChildVisit_Continue + }); + Some(num_params) + } + _ => None, + } + } +} + /// An iterator over whitelisted items. /// /// See `BindgenContext::whitelisted_items` for more information. diff --git a/src/ir/item.rs b/src/ir/item.rs index 3ce228b6..83e2a41f 100644 --- a/src/ir/item.rs +++ b/src/ir/item.rs @@ -1,7 +1,7 @@ //! Bindgen's core intermediate representation type. use super::annotations::Annotations; -use super::context::{BindgenContext, ItemId}; +use super::context::{BindgenContext, ItemId, PartialType}; use super::derive::{CanDeriveCopy, CanDeriveDebug, CanDeriveDefault}; use super::function::Function; use super::item_kind::ItemKind; @@ -1202,18 +1202,18 @@ impl ClangItemParser for Item { }; if valid_decl { - if let Some(&(_, item_id)) = - ctx.currently_parsed_types - .iter() - .find(|&&(d, _)| d == declaration_to_look_for) { + if let Some(partial) = ctx.currently_parsed_types() + .iter() + .find(|ty| *ty.decl() == declaration_to_look_for) { debug!("Avoiding recursion parsing type: {:?}", ty); - return Ok(item_id); + return Ok(partial.id()); } } let current_module = ctx.current_module(); + let partial_ty = PartialType::new(declaration_to_look_for, id); if valid_decl { - ctx.currently_parsed_types.push((declaration_to_look_for, id)); + ctx.begin_parsing(partial_ty); } let result = Type::from_clang_ty(id, ty, location, parent_id, ctx); @@ -1241,9 +1241,8 @@ impl ClangItemParser for Item { // declaration_to_look_for suspiciously shares a lot of // logic with ir::context, so we should refactor that. if valid_decl { - let (popped_decl, _) = - ctx.currently_parsed_types.pop().unwrap(); - assert_eq!(popped_decl, declaration_to_look_for); + let finished = ctx.finish_parsing(); + assert_eq!(*finished.decl(), declaration_to_look_for); } location.visit(|cur| { @@ -1251,8 +1250,9 @@ impl ClangItemParser for Item { }); if valid_decl { - ctx.currently_parsed_types - .push((declaration_to_look_for, id)); + let partial_ty = + PartialType::new(declaration_to_look_for, id); + ctx.begin_parsing(partial_ty); } } // If we have recursed into the AST all we know, and we still @@ -1279,8 +1279,8 @@ impl ClangItemParser for Item { }; if valid_decl { - let (popped_decl, _) = ctx.currently_parsed_types.pop().unwrap(); - assert_eq!(popped_decl, declaration_to_look_for); + let partial_ty = ctx.finish_parsing(); + assert_eq!(*partial_ty.decl(), declaration_to_look_for); } ret diff --git a/src/ir/ty.rs b/src/ir/ty.rs index 0c90547e..a98ca446 100644 --- a/src/ir/ty.rs +++ b/src/ir/ty.rs @@ -755,7 +755,7 @@ impl Type { potential_id, ty, location); - debug!("currently_parsed_types: {:?}", ctx.currently_parsed_types); + debug!("currently_parsed_types: {:?}", ctx.currently_parsed_types()); let canonical_ty = ty.canonical_type(); |