Skip to content

codegen: expose enum variant documentation. #1251

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Feb 13, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 57 additions & 15 deletions src/codegen/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2129,36 +2129,54 @@ impl EnumVariation {
/// A helper type to construct different enum variations.
enum EnumBuilder<'a> {
Rust {
codegen_depth: usize,
attrs: Vec<quote::Tokens>,
ident: proc_macro2::Term,
tokens: quote::Tokens,
emitted_any_variants: bool,
},
Bitfield {
codegen_depth: usize,
canonical_name: &'a str,
tokens: quote::Tokens,
},
Consts(Vec<quote::Tokens>),
Consts {
variants: Vec<quote::Tokens>,
codegen_depth: usize,
},
ModuleConsts {
codegen_depth: usize,
module_name: &'a str,
module_items: Vec<quote::Tokens>,
},
}

impl<'a> EnumBuilder<'a> {
/// Returns the depth of the code generation for a variant of this enum.
fn codegen_depth(&self) -> usize {
match *self {
EnumBuilder::Rust { codegen_depth, .. } |
EnumBuilder::Bitfield { codegen_depth, .. } |
EnumBuilder::ModuleConsts { codegen_depth, .. } |
EnumBuilder::Consts { codegen_depth, .. } => codegen_depth,
}
}

/// Create a new enum given an item builder, a canonical name, a name for
/// the representation, and which variation it should be generated as.
fn new(
name: &'a str,
attrs: Vec<quote::Tokens>,
repr: quote::Tokens,
enum_variation: EnumVariation
enum_variation: EnumVariation,
enum_codegen_depth: usize,
) -> Self {
let ident = proc_macro2::Term::intern(name);

match enum_variation {
EnumVariation::Bitfield => {
EnumBuilder::Bitfield {
codegen_depth: enum_codegen_depth,
canonical_name: name,
tokens: quote! {
#( #attrs )*
Expand All @@ -2170,6 +2188,7 @@ impl<'a> EnumBuilder<'a> {
EnumVariation::Rust => {
let tokens = quote!();
EnumBuilder::Rust {
codegen_depth: enum_codegen_depth + 1,
attrs,
ident,
tokens,
Expand All @@ -2178,20 +2197,26 @@ impl<'a> EnumBuilder<'a> {
}

EnumVariation::Consts => {
EnumBuilder::Consts(vec![
quote! {
pub type #ident = #repr;
}
])
EnumBuilder::Consts {
variants: vec![
quote! {
#( #attrs )*
pub type #ident = #repr;
}
],
codegen_depth: enum_codegen_depth,
}
}

EnumVariation::ModuleConsts => {
let ident = proc_macro2::Term::intern(CONSTIFIED_ENUM_MODULE_REPR_NAME);
let type_definition = quote! {
#( #attrs )*
pub type #ident = #repr;
};

EnumBuilder::ModuleConsts {
codegen_depth: enum_codegen_depth + 1,
module_name: name,
module_items: vec![type_definition],
}
Expand All @@ -2214,14 +2239,24 @@ impl<'a> EnumBuilder<'a> {
EnumVariantValue::Unsigned(v) => helpers::ast_ty::uint_expr(v),
};

let mut doc = quote! {};
if ctx.options().generate_comments {
if let Some(raw_comment) = variant.comment() {
let comment = comment::preprocess(raw_comment, self.codegen_depth());
doc = attributes::doc(comment);
}
}

match self {
EnumBuilder::Rust { attrs, ident, tokens, emitted_any_variants: _ } => {
EnumBuilder::Rust { attrs, ident, tokens, emitted_any_variants: _, codegen_depth } => {
let name = ctx.rust_ident(variant_name);
EnumBuilder::Rust {
attrs,
ident,
codegen_depth,
tokens: quote! {
#tokens
#doc
#name = #expr,
},
emitted_any_variants: true,
Expand All @@ -2238,6 +2273,7 @@ impl<'a> EnumBuilder<'a> {

let ident = ctx.rust_ident(constant_name);
result.push(quote! {
#doc
pub const #ident : #rust_ty = #rust_ty ( #expr );
});

Expand All @@ -2256,24 +2292,28 @@ impl<'a> EnumBuilder<'a> {

let ident = ctx.rust_ident(constant_name);
result.push(quote! {
#doc
pub const #ident : #rust_ty = #expr ;
});

self
}
EnumBuilder::ModuleConsts {
codegen_depth,
module_name,
mut module_items,
} => {
let name = ctx.rust_ident(variant_name);
let ty = ctx.rust_ident(CONSTIFIED_ENUM_MODULE_REPR_NAME);
module_items.push(quote! {
#doc
pub const #name : #ty = #expr ;
});

EnumBuilder::ModuleConsts {
module_name,
module_items,
codegen_depth,
}
}
}
Expand All @@ -2286,23 +2326,24 @@ impl<'a> EnumBuilder<'a> {
result: &mut CodegenResult<'b>,
) -> quote::Tokens {
match self {
EnumBuilder::Rust { attrs, ident, tokens, emitted_any_variants } => {
EnumBuilder::Rust { attrs, ident, tokens, emitted_any_variants, .. } => {
let variants = if !emitted_any_variants {
quote!(__bindgen_cannot_repr_c_on_empty_enum = 0)
} else {
tokens
};

quote! (
quote! {
#( #attrs )*
pub enum #ident {
#variants
}
)
}
}
EnumBuilder::Bitfield {
canonical_name,
tokens,
..
} => {
let rust_ty_name = ctx.rust_ident_raw(canonical_name);
let prefix = ctx.trait_prefix();
Expand Down Expand Up @@ -2349,10 +2390,11 @@ impl<'a> EnumBuilder<'a> {

tokens
}
EnumBuilder::Consts(tokens) => quote! { #( #tokens )* },
EnumBuilder::Consts { variants, .. } => quote! { #( #variants )* },
EnumBuilder::ModuleConsts {
module_items,
module_name,
..
} => {
let ident = ctx.rust_ident(module_name);
quote! {
Expand Down Expand Up @@ -2489,7 +2531,8 @@ impl CodeGenerator for Enum {
&name,
attrs,
repr,
variation
variation,
item.codegen_depth(ctx),
);

// A map where we keep a value -> variant relation.
Expand Down Expand Up @@ -2522,8 +2565,7 @@ impl CodeGenerator for Enum {
let mut iter = self.variants().iter().peekable();
while let Some(variant) = iter.next().or_else(|| {
constified_variants.pop_front()
})
{
}) {
if variant.hidden() {
continue;
}
Expand Down
5 changes: 5 additions & 0 deletions src/ir/enum_ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,11 @@ impl EnumVariant {
self.val
}

/// Get this variant's documentation.
pub fn comment(&self) -> Option<&str> {
self.comment.as_ref().map(|s| &**s)
}

/// Returns whether this variant should be enforced to be a constant by code
/// generation.
pub fn force_constification(&self) -> bool {
Expand Down
1 change: 1 addition & 0 deletions tests/expectations/tests/constify-enum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,6 @@ pub enum nsCSSPropertyID {
eCSSProperty_b = 1,
eCSSPropertyAlias_aa = 2,
eCSSPropertyAlias_bb = 3,
/// < <div rustbindgen constant></div>
eCSSProperty_COUNT_unexistingVariantValue = 4,
}
49 changes: 49 additions & 0 deletions tests/expectations/tests/enum-doc-bitfield.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/* automatically generated by rust-bindgen */

#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)]

/// Document field with three slashes
pub const B_VAR_A: B = B(0);
/// Document field with preceeding star
pub const B_VAR_B: B = B(1);
/// Document field with preceeding exclamation
pub const B_VAR_C: B = B(2);
/// < Document field with following star
pub const B_VAR_D: B = B(3);
/// < Document field with following exclamation
pub const B_VAR_E: B = B(4);
/// Document field with preceeding star, with a loong long multiline
/// comment.
///
/// Very interesting documentation, definitely.
pub const B_VAR_F: B = B(5);
impl ::std::ops::BitOr<B> for B {
type Output = Self;
#[inline]
fn bitor(self, other: Self) -> Self {
B(self.0 | other.0)
}
}
impl ::std::ops::BitOrAssign for B {
#[inline]
fn bitor_assign(&mut self, rhs: B) {
self.0 |= rhs.0;
}
}
impl ::std::ops::BitAnd<B> for B {
type Output = Self;
#[inline]
fn bitand(self, other: Self) -> Self {
B(self.0 & other.0)
}
}
impl ::std::ops::BitAndAssign for B {
#[inline]
fn bitand_assign(&mut self, rhs: B) {
self.0 &= rhs.0;
}
}
#[repr(C)]
/// Document enum
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct B(pub u32);
23 changes: 23 additions & 0 deletions tests/expectations/tests/enum-doc-mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/* automatically generated by rust-bindgen */

#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)]

pub mod B {
/// Document enum
pub type Type = u32;
/// Document field with three slashes
pub const VAR_A: Type = 0;
/// Document field with preceeding star
pub const VAR_B: Type = 1;
/// Document field with preceeding exclamation
pub const VAR_C: Type = 2;
/// < Document field with following star
pub const VAR_D: Type = 3;
/// < Document field with following exclamation
pub const VAR_E: Type = 4;
/// Document field with preceeding star, with a loong long multiline
/// comment.
///
/// Very interesting documentation, definitely.
pub const VAR_F: Type = 5;
}
24 changes: 24 additions & 0 deletions tests/expectations/tests/enum-doc-rusty.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/* automatically generated by rust-bindgen */

#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)]

#[repr(u32)]
/// Document enum
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum B {
/// Document field with three slashes
VAR_A = 0,
/// Document field with preceeding star
VAR_B = 1,
/// Document field with preceeding exclamation
VAR_C = 2,
/// < Document field with following star
VAR_D = 3,
/// < Document field with following exclamation
VAR_E = 4,
/// Document field with preceeding star, with a loong long multiline
/// comment.
///
/// Very interesting documentation, definitely.
VAR_F = 5,
}
21 changes: 21 additions & 0 deletions tests/expectations/tests/enum-doc.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/* automatically generated by rust-bindgen */

#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)]

/// Document field with three slashes
pub const B_VAR_A: B = 0;
/// Document field with preceeding star
pub const B_VAR_B: B = 1;
/// Document field with preceeding exclamation
pub const B_VAR_C: B = 2;
/// < Document field with following star
pub const B_VAR_D: B = 3;
/// < Document field with following exclamation
pub const B_VAR_E: B = 4;
/// Document field with preceeding star, with a loong long multiline
/// comment.
///
/// Very interesting documentation, definitely.
pub const B_VAR_F: B = 5;
/// Document enum
pub type B = u32;
Loading