| use proc_macro2::TokenStream; |
| use quote::ToTokens; |
| use syn::{parse2, File}; |
| |
| 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 File), |
| } |
| |
| // 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: |file| $pass(file), |
| } |
| }; |
| } |
| |
| const PASSES: &[PostProcessingPass] = |
| &[pass!(merge_extern_blocks), pass!(sort_semantically)]; |
| |
| pub(crate) fn postprocessing( |
| items: Vec<TokenStream>, |
| options: &BindgenOptions, |
| ) -> TokenStream { |
| let items = items.into_iter().collect(); |
| let require_syn = PASSES.iter().any(|pass| (pass.should_run)(options)); |
| |
| if !require_syn { |
| return 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. |
| // The `unwrap` here is deliberate because bindgen should generate valid rust items at all |
| // times. |
| let mut file = parse2::<File>(items).unwrap(); |
| |
| for pass in PASSES { |
| if (pass.should_run)(options) { |
| (pass.run)(&mut file); |
| } |
| } |
| |
| file.into_token_stream() |
| } |