summaryrefslogtreecommitdiff
path: root/bindgen/codegen/postprocessing/merge_extern_blocks.rs
diff options
context:
space:
mode:
Diffstat (limited to 'bindgen/codegen/postprocessing/merge_extern_blocks.rs')
-rw-r--r--bindgen/codegen/postprocessing/merge_extern_blocks.rs94
1 files changed, 57 insertions, 37 deletions
diff --git a/bindgen/codegen/postprocessing/merge_extern_blocks.rs b/bindgen/codegen/postprocessing/merge_extern_blocks.rs
index 2b761494..05e7e9ef 100644
--- a/bindgen/codegen/postprocessing/merge_extern_blocks.rs
+++ b/bindgen/codegen/postprocessing/merge_extern_blocks.rs
@@ -1,46 +1,66 @@
-use syn::{Item, ItemForeignMod};
+use syn::{
+ visit_mut::{visit_item_mod_mut, VisitMut},
+ Item, ItemForeignMod, ItemMod,
+};
-pub(super) fn merge_extern_blocks(items: &mut Vec<Item>) {
- // Keep all the extern blocks in a different `Vec` for faster search.
- let mut foreign_mods = Vec::<ItemForeignMod>::new();
+pub(super) fn merge_extern_blocks(item_mod: &mut ItemMod) {
+ Visitor.visit_item_mod_mut(item_mod)
+}
+
+struct Visitor;
- for item in std::mem::take(items) {
- match item {
- Item::ForeignMod(ItemForeignMod {
- attrs,
- abi,
- brace_token,
- items: foreign_items,
- }) => {
- let mut exists = false;
- for foreign_mod in &mut foreign_mods {
- // Check if there is a extern block with the same ABI and
- // attributes.
- if foreign_mod.attrs == attrs && foreign_mod.abi == abi {
- // Merge the items of the two blocks.
- foreign_mod.items.extend_from_slice(&foreign_items);
- exists = true;
- break;
+impl VisitMut for Visitor {
+ fn visit_item_mod_mut(&mut self, item_mod: &mut ItemMod) {
+ if let Some((_, ref mut items)) = item_mod.content {
+ // Keep all the extern blocks in a different `Vec` for faster search.
+ let mut extern_blocks = Vec::<ItemForeignMod>::new();
+
+ for item in std::mem::take(items) {
+ if let Item::ForeignMod(ItemForeignMod {
+ attrs,
+ abi,
+ brace_token,
+ items: extern_block_items,
+ }) = item
+ {
+ let mut exists = false;
+ for extern_block in &mut extern_blocks {
+ // Check if there is a extern block with the same ABI and
+ // attributes.
+ if extern_block.attrs == attrs &&
+ extern_block.abi == abi
+ {
+ // Merge the items of the two blocks.
+ extern_block
+ .items
+ .extend_from_slice(&extern_block_items);
+ exists = true;
+ break;
+ }
}
+ // If no existing extern block had the same ABI and attributes, store
+ // it.
+ if !exists {
+ extern_blocks.push(ItemForeignMod {
+ attrs,
+ abi,
+ brace_token,
+ items: extern_block_items,
+ });
+ }
+ } else {
+ // If the item is not an extern block, we don't have to do anything and just
+ // push it back.
+ items.push(item);
}
- // If no existing extern block had the same ABI and attributes, store
- // it.
- if !exists {
- foreign_mods.push(ItemForeignMod {
- attrs,
- abi,
- brace_token,
- items: foreign_items,
- });
- }
}
- // If the item is not an extern block, we don't have to do anything.
- _ => items.push(item),
+
+ // Move all the extern blocks alongside the rest of the items.
+ for extern_block in extern_blocks {
+ items.push(Item::ForeignMod(extern_block));
+ }
}
- }
- // Move all the extern blocks alongside the rest of the items.
- for foreign_mod in foreign_mods {
- items.push(Item::ForeignMod(foreign_mod));
+ visit_item_mod_mut(self, item_mod)
}
}