Skip to content

Commit

Permalink
feat(lib sorting): add semantic sorting of the output
Browse files Browse the repository at this point in the history
Generated code needs some sorting in a way that is
semantically appealing. The request[1] asks for basic
sorting like "ypes are declared first, then all structs,
then all consts, then all function signatures, etc.

[1] rust-lang#1743
  • Loading branch information
amanjeev committed Aug 11, 2022
1 parent 401cb46 commit f99ed6f
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 6 deletions.
24 changes: 18 additions & 6 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Expand Up @@ -57,6 +57,7 @@ lazycell = "1"
lazy_static = "1"
peeking_take_while = "0.1.2"
quote = { version = "1", default-features = false }
syn = { version = "1.0.99", features = ["full", "extra-traits"]}
regex = { version = "1.5", default-features = false , features = ["std", "unicode"] }
which = { version = "4.2.1", optional = true, default-features = false }
shlex = "1"
Expand Down
60 changes: 60 additions & 0 deletions src/lib.rs
Expand Up @@ -86,6 +86,7 @@ use std::{env, iter};
// Some convenient typedefs for a fast hash map and hash set.
type HashMap<K, V> = ::rustc_hash::FxHashMap<K, V>;
type HashSet<K> = ::rustc_hash::FxHashSet<K>;
use quote::ToTokens;
pub(crate) use std::collections::hash_map::Entry;

/// Default prefix for the anon fields.
Expand Down Expand Up @@ -587,6 +588,10 @@ impl Builder {
output_vector.push("--vtable-generation".into());
}

if self.options.sort_semantically {
output_vector.push("--sort-semantically".into());
}

// Add clang arguments

output_vector.push("--".into());
Expand Down Expand Up @@ -1476,6 +1481,14 @@ impl Builder {
self
}

/// If true, enables the sorting of the output in a predefined manner
///
/// TODO: Perhaps move the sorting order out into a config
pub fn sort_semantically(mut self, doit: bool) -> Self {
self.options.sort_semantically = doit;
self
}

/// Generate the Rust bindings using the options built up thus far.
pub fn generate(mut self) -> Result<Bindings, BindgenError> {
// Add any extra arguments from the environment to the clang command line.
Expand Down Expand Up @@ -2005,6 +2018,9 @@ struct BindgenOptions {

/// Emit vtable functions.
vtable_generation: bool,

/// Sort the code generation
sort_semantically: bool,
}

/// TODO(emilio): This is sort of a lie (see the error message that results from
Expand Down Expand Up @@ -2153,6 +2169,7 @@ impl Default for BindgenOptions {
c_naming: false,
force_explicit_padding: false,
vtable_generation: false,
sort_semantically: false,
}
}
}
Expand Down Expand Up @@ -2437,6 +2454,49 @@ impl Bindings {

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

if options.sort_semantically {
let module_wrapped_tokens =
quote!(mod wrapper_for_sorting_hack { #( #items )* });
let mut syn_parsed_items =
syn::parse2::<syn::ItemMod>(module_wrapped_tokens)
.unwrap()
.content
.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,
});

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

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

Ok(Bindings {
options,
module: quote! {
Expand Down
1 change: 1 addition & 0 deletions src/options.rs
Expand Up @@ -515,6 +515,7 @@ where
Arg::new("vtable-generation")
.long("vtable-generation")
.help("Enables generation of vtable functions."),
Arg::new("sort-semantically").long("sort-semantically").help("Enables sorting of code generation in a predefined manner"),
Arg::new("V")
.long("version")
.help("Prints the version, and exits"),
Expand Down

0 comments on commit f99ed6f

Please sign in to comment.