diff options
author | Christian Poveda <christian.poveda@ferrous-systems.com> | 2022-09-23 21:36:14 -0500 |
---|---|---|
committer | Christian Poveda <christian.poveda@ferrous-systems.com> | 2022-10-04 20:47:17 -0500 |
commit | 0296f9e86c7756e718b6b82836ce1e09b5f8d08a (patch) | |
tree | b5954c6680b243c0b1671a80ea973ef90877e462 /bindgen/codegen/postprocessing/mod.rs | |
parent | a900f8f863d1313ad76603234aaeea22bb9ba7b3 (diff) |
split the repo into a workspace
remove `clap` dependency :tada:
update the book installation instructions
Diffstat (limited to 'bindgen/codegen/postprocessing/mod.rs')
-rw-r--r-- | bindgen/codegen/postprocessing/mod.rs | 66 |
1 files changed, 66 insertions, 0 deletions
diff --git a/bindgen/codegen/postprocessing/mod.rs b/bindgen/codegen/postprocessing/mod.rs new file mode 100644 index 00000000..c6612f2b --- /dev/null +++ b/bindgen/codegen/postprocessing/mod.rs @@ -0,0 +1,66 @@ +use proc_macro2::TokenStream; +use quote::ToTokens; +use syn::Item; + +use crate::BindgenOptions; + +mod merge_extern_blocks; +mod sort_semantically; + +use merge_extern_blocks::merge_extern_blocks; +use sort_semantically::sort_semantically; + +struct PostProcessingPass { + should_run: fn(&BindgenOptions) -> bool, + run: fn(&mut Vec<Item>), +} + +// TODO: This can be a const fn when mutable references are allowed in const +// context. +macro_rules! pass { + ($pass:ident) => { + PostProcessingPass { + should_run: |options| options.$pass, + run: |items| $pass(items), + } + }; +} + +const PASSES: &[PostProcessingPass] = + &[pass!(merge_extern_blocks), pass!(sort_semantically)]; + +pub(crate) fn postprocessing( + items: Vec<TokenStream>, + options: &BindgenOptions, +) -> TokenStream { + let require_syn = PASSES.iter().any(|pass| (pass.should_run)(options)); + if !require_syn { + return items.into_iter().collect(); + } + let module_wrapped_tokens = + quote!(mod wrapper_for_sorting_hack { #( #items )* }); + + // 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 + // 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 items) = syn::parse2::<syn::ItemMod>(module_wrapped_tokens) + .unwrap() + .content + .unwrap(); + + for pass in PASSES { + if (pass.should_run)(options) { + (pass.run)(&mut items); + } + } + + let synful_items = items.into_iter().map(|item| item.into_token_stream()); + + quote! { #( #synful_items )* } +} |