diff options
author | bors-servo <lbergstrom+bors@mozilla.com> | 2017-06-21 05:03:08 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-06-21 05:03:08 -0700 |
commit | 480c2d197199e7b1f824a01cc63acd33d81f6622 (patch) | |
tree | a244ca35506dc52f8a965a797dedeaa5715a5e82 /src/codegen/mod.rs | |
parent | 232a21ebc4a4ddc2468aed8e54d165c613037038 (diff) | |
parent | 814d28e0f256a24865f633b5992ced6f035d6f4c (diff) |
Auto merge of #741 - tmfink:feature-699-constified-enum-module, r=emilio
Feature 699 constified enum module
This is a work in progress for issue #699 that adds the `--constified-enum-module` option to bindgen.
@emilio, could you give me some guidance on fixing the uses of the enum variant types? In the example below, `foo` should be replaced with `foo::Type`. I'm not sure of the proper way to rename `Item`s after the structures have been defined. My initial thought was to redefine the `CodeGenerator` trait to take a mutable reference to `item`, but that will not work because of the borrow checker. Thoughts?
Todo:
- [x] put constified enum variants in a `mod`
- [x] ensure references to constified enum `foo` are changed to `foo::Type`
- [x] handle `typedef` enums
-----
Given the input header `tests/headers/constify-module-enums.h`:
~~~c
// bindgen-flags: --constified-enum-module foo
enum foo {
THIS,
SHOULD_BE,
A_CONSTANT,
};
struct bar {
enum foo this_should_work;
};
~~~
`$ cargo run -- tests/headers/constify-module-enums.h --constified-enum-module foo --no-layout-tests` will output:
~~~rust
/* automatically generated by rust-bindgen */
pub mod foo {
pub type Type = ::std::os::raw::c_uint;
pub const THIS: Type = 0;
pub const SHOULD_BE: Type = 1;
pub const A_CONSTANT: Type = 2;
}
#[repr(C)]
#[derive(Debug, Copy)]
pub struct bar {
pub this_should_work: foo,
}
impl Clone for bar {
fn clone(&self) -> Self { *self }
}
~~~
Diffstat (limited to 'src/codegen/mod.rs')
-rw-r--r-- | src/codegen/mod.rs | 74 |
1 files changed, 67 insertions, 7 deletions
diff --git a/src/codegen/mod.rs b/src/codegen/mod.rs index 3aff1b68..d926f02b 100644 --- a/src/codegen/mod.rs +++ b/src/codegen/mod.rs @@ -36,9 +36,12 @@ use std::mem; use std::ops; use syntax::abi; use syntax::ast; -use syntax::codemap::{Span, respan}; +use syntax::codemap::{DUMMY_SP, Span, respan}; use syntax::ptr::P; +// Name of type defined in constified enum module +pub static CONSTIFIED_ENUM_MODULE_REPR_NAME: &'static str = "Type"; + fn root_import_depth(ctx: &BindgenContext, item: &Item) -> usize { if !ctx.options().enable_cxx_namespaces { return 0; @@ -244,7 +247,6 @@ impl ForeignModBuilder { } fn build(self, ctx: &BindgenContext) -> P<ast::Item> { - use syntax::codemap::DUMMY_SP; P(ast::Item { ident: ctx.rust_ident(""), id: ast::DUMMY_NODE_ID, @@ -2049,6 +2051,10 @@ enum EnumBuilder<'a> { aster: P<ast::Item>, }, Consts { aster: P<ast::Item> }, + ModuleConsts { + module_name: &'a str, + module_items: Vec<P<ast::Item>>, + }, } impl<'a> EnumBuilder<'a> { @@ -2058,7 +2064,8 @@ impl<'a> EnumBuilder<'a> { name: &'a str, repr: P<ast::Ty>, bitfield_like: bool, - constify: bool) + constify: bool, + constify_module: bool) -> Self { if bitfield_like { EnumBuilder::Bitfield { @@ -2070,8 +2077,20 @@ impl<'a> EnumBuilder<'a> { .build(), } } else if constify { - EnumBuilder::Consts { - aster: aster.type_(name).build_ty(repr), + if constify_module { + let type_definition = aster::item::ItemBuilder::new() + .pub_() + .type_(CONSTIFIED_ENUM_MODULE_REPR_NAME) + .build_ty(repr); + + EnumBuilder::ModuleConsts { + module_name: name, + module_items: vec![type_definition], + } + } else { + EnumBuilder::Consts { + aster: aster.type_(name).build_ty(repr), + } } } else { EnumBuilder::Rust(aster.enum_(name)) @@ -2143,6 +2162,27 @@ impl<'a> EnumBuilder<'a> { result.push(constant); self } + EnumBuilder::ModuleConsts { module_name, module_items, .. } => { + // Variant type + let inside_module_type = + aster::AstBuilder::new().ty().id(CONSTIFIED_ENUM_MODULE_REPR_NAME); + + let constant = aster::AstBuilder::new() + .item() + .pub_() + .const_(&*variant_name) + .expr() + .build(expr) + .build(inside_module_type.clone()); + + let mut module_items = module_items.clone(); + module_items.push(constant); + + EnumBuilder::ModuleConsts { + module_name, + module_items, + } + } } } @@ -2208,6 +2248,22 @@ impl<'a> EnumBuilder<'a> { aster } EnumBuilder::Consts { aster, .. } => aster, + EnumBuilder::ModuleConsts { module_items, module_name, .. } => { + // Create module item with type and variant definitions + let module_item = P(ast::Item { + ident: ast::Ident::from_str(module_name), + attrs: vec![], + id: ast::DUMMY_NODE_ID, + node: ast::ItemKind::Mod(ast::Mod { + inner: DUMMY_SP, + items: module_items, + }), + vis: ast::Visibility::Public, + span: DUMMY_SP, + }); + + module_item + } } } } @@ -2273,7 +2329,10 @@ impl CodeGenerator for Enum { .any(|v| ctx.options().bitfield_enums.matches(&v.name()))) }; - let is_constified_enum = { + let is_constified_enum_module = self.is_constified_enum_module(ctx, item); + + let is_constified_enum = { + is_constified_enum_module || ctx.options().constified_enums.matches(&name) || (enum_ty.name().is_none() && self.variants() @@ -2353,7 +2412,8 @@ impl CodeGenerator for Enum { &name, repr, is_bitfield, - is_constified_enum); + is_constified_enum, + is_constified_enum_module); // A map where we keep a value -> variant relation. let mut seen_values = HashMap::<_, String>::new(); |