summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/lib.rs71
-rw-r--r--src/options.rs7
2 files changed, 78 insertions, 0 deletions
diff --git a/src/lib.rs b/src/lib.rs
index c102c47d..b90faba6 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -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.
@@ -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());
@@ -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.
@@ -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
@@ -2153,6 +2169,7 @@ impl Default for BindgenOptions {
c_naming: false,
force_explicit_padding: false,
vtable_generation: false,
+ sort_semantically: false,
}
}
}
@@ -2438,6 +2455,60 @@ impl Bindings {
let (items, options, warnings) = codegen::codegen(context);
+ if options.sort_semantically {
+ 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.
+ // 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
+ // The first one won't panic because we build the `mod` and know it is there
+ // The second one won't panic because we know original output has something in
+ // it already.
+ 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 synful_items = syn_parsed_items
+ .into_iter()
+ .map(|item| item.into_token_stream());
+
+ return Ok(Bindings {
+ options,
+ warnings,
+ module: quote! {
+ #( #synful_items )*
+ },
+ });
+ }
+
Ok(Bindings {
options,
warnings,
diff --git a/src/options.rs b/src/options.rs
index a11f3ddd..83da21f4 100644
--- a/src/options.rs
+++ b/src/options.rs
@@ -515,6 +515,9 @@ 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"),
@@ -1000,5 +1003,9 @@ where
builder = builder.vtable_generation(true);
}
+ if matches.is_present("sort-semantically") {
+ builder = builder.sort_semantically(true);
+ }
+
Ok((builder, output, verbose))
}