Skip to content

Commit f99ed6f

Browse files
committed
feat(lib sorting): add semantic sorting of the output
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
1 parent 401cb46 commit f99ed6f

File tree

4 files changed

+80
-6
lines changed

4 files changed

+80
-6
lines changed

Cargo.lock

Lines changed: 18 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ lazycell = "1"
5757
lazy_static = "1"
5858
peeking_take_while = "0.1.2"
5959
quote = { version = "1", default-features = false }
60+
syn = { version = "1.0.99", features = ["full", "extra-traits"]}
6061
regex = { version = "1.5", default-features = false , features = ["std", "unicode"] }
6162
which = { version = "4.2.1", optional = true, default-features = false }
6263
shlex = "1"

src/lib.rs

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ use std::{env, iter};
8686
// Some convenient typedefs for a fast hash map and hash set.
8787
type HashMap<K, V> = ::rustc_hash::FxHashMap<K, V>;
8888
type HashSet<K> = ::rustc_hash::FxHashSet<K>;
89+
use quote::ToTokens;
8990
pub(crate) use std::collections::hash_map::Entry;
9091

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

591+
if self.options.sort_semantically {
592+
output_vector.push("--sort-semantically".into());
593+
}
594+
590595
// Add clang arguments
591596

592597
output_vector.push("--".into());
@@ -1476,6 +1481,14 @@ impl Builder {
14761481
self
14771482
}
14781483

1484+
/// If true, enables the sorting of the output in a predefined manner
1485+
///
1486+
/// TODO: Perhaps move the sorting order out into a config
1487+
pub fn sort_semantically(mut self, doit: bool) -> Self {
1488+
self.options.sort_semantically = doit;
1489+
self
1490+
}
1491+
14791492
/// Generate the Rust bindings using the options built up thus far.
14801493
pub fn generate(mut self) -> Result<Bindings, BindgenError> {
14811494
// Add any extra arguments from the environment to the clang command line.
@@ -2005,6 +2018,9 @@ struct BindgenOptions {
20052018

20062019
/// Emit vtable functions.
20072020
vtable_generation: bool,
2021+
2022+
/// Sort the code generation
2023+
sort_semantically: bool,
20082024
}
20092025

20102026
/// TODO(emilio): This is sort of a lie (see the error message that results from
@@ -2153,6 +2169,7 @@ impl Default for BindgenOptions {
21532169
c_naming: false,
21542170
force_explicit_padding: false,
21552171
vtable_generation: false,
2172+
sort_semantically: false,
21562173
}
21572174
}
21582175
}
@@ -2437,6 +2454,49 @@ impl Bindings {
24372454

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

2457+
if options.sort_semantically {
2458+
let module_wrapped_tokens =
2459+
quote!(mod wrapper_for_sorting_hack { #( #items )* });
2460+
let mut syn_parsed_items =
2461+
syn::parse2::<syn::ItemMod>(module_wrapped_tokens)
2462+
.unwrap()
2463+
.content
2464+
.unwrap()
2465+
.1;
2466+
2467+
syn_parsed_items.sort_by_key(|item| match item {
2468+
syn::Item::Type(_) => 0,
2469+
syn::Item::Struct(_) => 1,
2470+
syn::Item::Const(_) => 2,
2471+
syn::Item::Fn(_) => 3,
2472+
syn::Item::Enum(_) => 4,
2473+
syn::Item::Union(_) => 5,
2474+
syn::Item::Static(_) => 6,
2475+
syn::Item::Trait(_) => 7,
2476+
syn::Item::TraitAlias(_) => 8,
2477+
syn::Item::Impl(_) => 9,
2478+
syn::Item::Mod(_) => 10,
2479+
syn::Item::Use(_) => 11,
2480+
syn::Item::Verbatim(_) => 12,
2481+
syn::Item::ExternCrate(_) => 13,
2482+
syn::Item::ForeignMod(_) => 14,
2483+
syn::Item::Macro(_) => 15,
2484+
syn::Item::Macro2(_) => 16,
2485+
_ => 18,
2486+
});
2487+
2488+
let items = syn_parsed_items
2489+
.into_iter()
2490+
.map(|item| item.into_token_stream());
2491+
2492+
return Ok(Bindings {
2493+
options,
2494+
module: quote! {
2495+
#( #items )*
2496+
},
2497+
});
2498+
}
2499+
24402500
Ok(Bindings {
24412501
options,
24422502
module: quote! {

src/options.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -515,6 +515,7 @@ where
515515
Arg::new("vtable-generation")
516516
.long("vtable-generation")
517517
.help("Enables generation of vtable functions."),
518+
Arg::new("sort-semantically").long("sort-semantically").help("Enables sorting of code generation in a predefined manner"),
518519
Arg::new("V")
519520
.long("version")
520521
.help("Prints the version, and exits"),

0 commit comments

Comments
 (0)