Skip to content
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

add BindgenOptions::require_syn method #2265

Merged
merged 2 commits into from Sep 10, 2022
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
14 changes: 13 additions & 1 deletion CONTRIBUTING.md
Expand Up @@ -318,7 +318,19 @@ parameters a given type uses. The analyses are defined in

The final phase is generating Rust source text from the analyzed IR, and it is
defined in `src/codegen/*`. We use the `quote` crate, which provides the `quote!
{ ... }` macro for quasi-quoting Rust forms.
{ ... }` macro for quasi-quoting Rust forms. Some options that affect the
generated Rust code are implemented using the [`syn`](https://docs.rs/syn) crate.

### Implementing new options using `syn`
pvdrz marked this conversation as resolved.
Show resolved Hide resolved

Here is a list of recommendations to be followed if a new option can be
implemented using the `syn` crate:

- The `BindgenOptions::require_syn` method must be updated to reflect that this
new option requires parsing the generated Rust code with `syn`.

- The implementation of the new option should be added at the end of
`Bindings::generate`, inside the `if options.require_syn() { ... }` block.

## Pull Requests and Code Reviews

Expand Down
71 changes: 36 additions & 35 deletions src/lib.rs
Expand Up @@ -2029,6 +2029,11 @@ struct BindgenOptions {
impl ::std::panic::UnwindSafe for BindgenOptions {}

impl BindgenOptions {
/// Whether any of the enabled options requires `syn`.
fn require_syn(&self) -> bool {
self.sort_semantically
}

fn build(&mut self) {
let mut regex_sets = [
&mut self.allowlisted_vars,
Expand Down Expand Up @@ -2455,13 +2460,13 @@ impl Bindings {

let (items, options, warnings) = codegen::codegen(context);

if options.sort_semantically {
let module = if options.require_syn() {
let module_wrapped_tokens =
quote!(mod wrapper_for_sorting_hack { #( #items )* });

// This semantically sorting business is a hack, for now. This means that we are
// re-parsing already generated code using `syn` (as opposed to `quote`) because
// `syn` provides us more control over the elements.
// This syn business is a hack, for now. This means that we are re-parsing already
// generated code using `syn` (as opposed to `quote`) because `syn` provides us more
// control over the elements.
// One caveat is that some of the items coming from `quote`d output might have
// multiple items within them. Hence, we have to wrap the incoming in a `mod`.
// The two `unwrap`s here are deliberate because
Expand All @@ -2475,46 +2480,42 @@ impl Bindings {
.unwrap()
.1;

syn_parsed_items.sort_by_key(|item| match item {
syn::Item::Type(_) => 0,
syn::Item::Struct(_) => 1,
syn::Item::Const(_) => 2,
syn::Item::Fn(_) => 3,
syn::Item::Enum(_) => 4,
syn::Item::Union(_) => 5,
syn::Item::Static(_) => 6,
syn::Item::Trait(_) => 7,
syn::Item::TraitAlias(_) => 8,
syn::Item::Impl(_) => 9,
syn::Item::Mod(_) => 10,
syn::Item::Use(_) => 11,
syn::Item::Verbatim(_) => 12,
syn::Item::ExternCrate(_) => 13,
syn::Item::ForeignMod(_) => 14,
syn::Item::Macro(_) => 15,
syn::Item::Macro2(_) => 16,
_ => 18,
});
if options.sort_semantically {
syn_parsed_items.sort_by_key(|item| match item {
syn::Item::Type(_) => 0,
syn::Item::Struct(_) => 1,
syn::Item::Const(_) => 2,
syn::Item::Fn(_) => 3,
syn::Item::Enum(_) => 4,
syn::Item::Union(_) => 5,
syn::Item::Static(_) => 6,
syn::Item::Trait(_) => 7,
syn::Item::TraitAlias(_) => 8,
syn::Item::Impl(_) => 9,
syn::Item::Mod(_) => 10,
syn::Item::Use(_) => 11,
syn::Item::Verbatim(_) => 12,
syn::Item::ExternCrate(_) => 13,
syn::Item::ForeignMod(_) => 14,
syn::Item::Macro(_) => 15,
syn::Item::Macro2(_) => 16,
_ => 18,
});
}

let synful_items = syn_parsed_items
.into_iter()
.map(|item| item.into_token_stream());

return Ok(Bindings {
options,
warnings,
module: quote! {
#( #synful_items )*
},
});
}
quote! { #( #synful_items )* }
} else {
quote! { #( #items )* }
};

Ok(Bindings {
options,
warnings,
module: quote! {
#( #items )*
},
module,
})
}

Expand Down