summaryrefslogtreecommitdiff
path: root/bindgen/codegen/postprocessing/merge_extern_blocks.rs
diff options
context:
space:
mode:
authorJustin Smith <justsmth@amazon.com>2022-10-06 13:30:17 -0400
committerJustin Smith <justsmth@amazon.com>2022-10-06 13:30:17 -0400
commitc1d8cfb5528e3e7d061ae7574195664bc71b5004 (patch)
treef26aa7dbe22fe9ed3b884fb3d4620b44b5138be0 /bindgen/codegen/postprocessing/merge_extern_blocks.rs
parent5209ebdbdfbe0663824d2abb688ac30c2c602726 (diff)
parent576fd8d424c8248726542b0951c594a9734cd02a (diff)
Merge branch 'master' into generated_name_override
Diffstat (limited to 'bindgen/codegen/postprocessing/merge_extern_blocks.rs')
-rw-r--r--bindgen/codegen/postprocessing/merge_extern_blocks.rs46
1 files changed, 46 insertions, 0 deletions
diff --git a/bindgen/codegen/postprocessing/merge_extern_blocks.rs b/bindgen/codegen/postprocessing/merge_extern_blocks.rs
new file mode 100644
index 00000000..2b761494
--- /dev/null
+++ b/bindgen/codegen/postprocessing/merge_extern_blocks.rs
@@ -0,0 +1,46 @@
+use syn::{Item, ItemForeignMod};
+
+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();
+
+ 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;
+ }
+ }
+ // 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 foreign_mod in foreign_mods {
+ items.push(Item::ForeignMod(foreign_mod));
+ }
+}