summaryrefslogtreecommitdiff
path: root/bindgen/codegen/postprocessing/merge_extern_blocks.rs
diff options
context:
space:
mode:
authorChristian Poveda <christian.poveda@ferrous-systems.com>2022-10-06 14:52:29 -0500
committerChristian Poveda <christian.poveda@ferrous-systems.com>2022-10-06 14:52:29 -0500
commit4dd91ff6d72fb5df122e5957f31d1368e84d80a2 (patch)
tree1481911049423b9af30b28cf5acc48036d83c215 /bindgen/codegen/postprocessing/merge_extern_blocks.rs
parent576fd8d424c8248726542b0951c594a9734cd02a (diff)
Make postprocessing more robust
This is done by merging extern blocks and sorting items in every module instead of just in the root module. The tests were changed to use `cxx` namespaces so they effectively check that items are manipulated correctly in every single module.
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)
}
}