Skip to content

Commit 33c9fe4

Browse files
authored
Remove the wrapping mod hack (#2441)
1 parent f019a9b commit 33c9fe4

File tree

3 files changed

+92
-88
lines changed

3 files changed

+92
-88
lines changed
Original file line numberDiff line numberDiff line change
@@ -1,66 +1,70 @@
11
use syn::{
2-
visit_mut::{visit_item_mod_mut, VisitMut},
3-
Item, ItemForeignMod, ItemMod,
2+
visit_mut::{visit_file_mut, visit_item_mod_mut, VisitMut},
3+
File, Item, ItemForeignMod, ItemMod,
44
};
55

6-
pub(super) fn merge_extern_blocks(item_mod: &mut ItemMod) {
7-
Visitor.visit_item_mod_mut(item_mod)
6+
pub(super) fn merge_extern_blocks(file: &mut File) {
7+
Visitor.visit_file_mut(file)
88
}
99

1010
struct Visitor;
1111

1212
impl VisitMut for Visitor {
13+
fn visit_file_mut(&mut self, file: &mut File) {
14+
visit_items(&mut file.items);
15+
visit_file_mut(self, file)
16+
}
17+
1318
fn visit_item_mod_mut(&mut self, item_mod: &mut ItemMod) {
1419
if let Some((_, ref mut items)) = item_mod.content {
15-
// Keep all the extern blocks in a different `Vec` for faster search.
16-
let mut extern_blocks = Vec::<ItemForeignMod>::new();
20+
visit_items(items);
21+
}
22+
visit_item_mod_mut(self, item_mod)
23+
}
24+
}
25+
26+
fn visit_items(items: &mut Vec<Item>) {
27+
// Keep all the extern blocks in a different `Vec` for faster search.
28+
let mut extern_blocks = Vec::<ItemForeignMod>::new();
1729

18-
for item in std::mem::take(items) {
19-
if let Item::ForeignMod(ItemForeignMod {
30+
for item in std::mem::take(items) {
31+
if let Item::ForeignMod(ItemForeignMod {
32+
attrs,
33+
abi,
34+
brace_token,
35+
items: extern_block_items,
36+
}) = item
37+
{
38+
let mut exists = false;
39+
for extern_block in &mut extern_blocks {
40+
// Check if there is a extern block with the same ABI and
41+
// attributes.
42+
if extern_block.attrs == attrs && extern_block.abi == abi {
43+
// Merge the items of the two blocks.
44+
extern_block.items.extend_from_slice(&extern_block_items);
45+
exists = true;
46+
break;
47+
}
48+
}
49+
// If no existing extern block had the same ABI and attributes, store
50+
// it.
51+
if !exists {
52+
extern_blocks.push(ItemForeignMod {
2053
attrs,
2154
abi,
2255
brace_token,
2356
items: extern_block_items,
24-
}) = item
25-
{
26-
let mut exists = false;
27-
for extern_block in &mut extern_blocks {
28-
// Check if there is a extern block with the same ABI and
29-
// attributes.
30-
if extern_block.attrs == attrs &&
31-
extern_block.abi == abi
32-
{
33-
// Merge the items of the two blocks.
34-
extern_block
35-
.items
36-
.extend_from_slice(&extern_block_items);
37-
exists = true;
38-
break;
39-
}
40-
}
41-
// If no existing extern block had the same ABI and attributes, store
42-
// it.
43-
if !exists {
44-
extern_blocks.push(ItemForeignMod {
45-
attrs,
46-
abi,
47-
brace_token,
48-
items: extern_block_items,
49-
});
50-
}
51-
} else {
52-
// If the item is not an extern block, we don't have to do anything and just
53-
// push it back.
54-
items.push(item);
55-
}
56-
}
57-
58-
// Move all the extern blocks alongside the rest of the items.
59-
for extern_block in extern_blocks {
60-
items.push(Item::ForeignMod(extern_block));
57+
});
6158
}
59+
} else {
60+
// If the item is not an extern block, we don't have to do anything and just
61+
// push it back.
62+
items.push(item);
6263
}
64+
}
6365

64-
visit_item_mod_mut(self, item_mod)
66+
// Move all the extern blocks alongside the rest of the items.
67+
for extern_block in extern_blocks {
68+
items.push(Item::ForeignMod(extern_block));
6569
}
6670
}

bindgen/codegen/postprocessing/mod.rs

+9-18
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use proc_macro2::TokenStream;
22
use quote::ToTokens;
3-
use syn::{parse2, ItemMod};
3+
use syn::{parse2, File};
44

55
use crate::BindgenOptions;
66

@@ -12,7 +12,7 @@ use sort_semantically::sort_semantically;
1212

1313
struct PostProcessingPass {
1414
should_run: fn(&BindgenOptions) -> bool,
15-
run: fn(&mut ItemMod),
15+
run: fn(&mut File),
1616
}
1717

1818
// TODO: This can be a const fn when mutable references are allowed in const
@@ -21,7 +21,7 @@ macro_rules! pass {
2121
($pass:ident) => {
2222
PostProcessingPass {
2323
should_run: |options| options.$pass,
24-
run: |item_mod| $pass(item_mod),
24+
run: |file| $pass(file),
2525
}
2626
};
2727
}
@@ -33,34 +33,25 @@ pub(crate) fn postprocessing(
3333
items: Vec<TokenStream>,
3434
options: &BindgenOptions,
3535
) -> TokenStream {
36+
let items = items.into_iter().collect();
3637
let require_syn = PASSES.iter().any(|pass| (pass.should_run)(options));
38+
3739
if !require_syn {
38-
return items.into_iter().collect();
40+
return items;
3941
}
40-
let module_wrapped_tokens =
41-
quote!(mod wrapper_for_postprocessing_hack { #( #items )* });
4242

4343
// This syn business is a hack, for now. This means that we are re-parsing already
4444
// generated code using `syn` (as opposed to `quote`) because `syn` provides us more
4545
// control over the elements.
46-
// One caveat is that some of the items coming from `quote`d output might have
47-
// multiple items within them. Hence, we have to wrap the incoming in a `mod`.
4846
// The `unwrap` here is deliberate because bindgen should generate valid rust items at all
4947
// times.
50-
let mut item_mod = parse2::<ItemMod>(module_wrapped_tokens).unwrap();
48+
let mut file = parse2::<File>(items).unwrap();
5149

5250
for pass in PASSES {
5351
if (pass.should_run)(options) {
54-
(pass.run)(&mut item_mod);
52+
(pass.run)(&mut file);
5553
}
5654
}
5755

58-
let synful_items = item_mod
59-
.content
60-
.map(|(_, items)| items)
61-
.unwrap_or_default()
62-
.into_iter()
63-
.map(|item| item.into_token_stream());
64-
65-
quote! { #( #synful_items )* }
56+
file.into_token_stream()
6657
}
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,47 @@
11
use syn::{
2-
visit_mut::{visit_item_mod_mut, VisitMut},
3-
Item, ItemMod,
2+
visit_mut::{visit_file_mut, visit_item_mod_mut, VisitMut},
3+
File, Item, ItemMod,
44
};
55

6-
pub(super) fn sort_semantically(item_mod: &mut ItemMod) {
7-
Visitor.visit_item_mod_mut(item_mod)
6+
pub(super) fn sort_semantically(file: &mut File) {
7+
Visitor.visit_file_mut(file)
88
}
99

1010
struct Visitor;
1111

1212
impl VisitMut for Visitor {
13+
fn visit_file_mut(&mut self, file: &mut File) {
14+
visit_items(&mut file.items);
15+
visit_file_mut(self, file)
16+
}
17+
1318
fn visit_item_mod_mut(&mut self, item_mod: &mut ItemMod) {
1419
if let Some((_, ref mut items)) = item_mod.content {
15-
items.sort_by_key(|item| match item {
16-
Item::Type(_) => 0,
17-
Item::Struct(_) => 1,
18-
Item::Const(_) => 2,
19-
Item::Fn(_) => 3,
20-
Item::Enum(_) => 4,
21-
Item::Union(_) => 5,
22-
Item::Static(_) => 6,
23-
Item::Trait(_) => 7,
24-
Item::TraitAlias(_) => 8,
25-
Item::Impl(_) => 9,
26-
Item::Mod(_) => 10,
27-
Item::Use(_) => 11,
28-
Item::Verbatim(_) => 12,
29-
Item::ExternCrate(_) => 13,
30-
Item::ForeignMod(_) => 14,
31-
Item::Macro(_) => 15,
32-
Item::Macro2(_) => 16,
33-
_ => 18,
34-
});
20+
visit_items(items);
3521
}
3622
visit_item_mod_mut(self, item_mod)
3723
}
3824
}
25+
26+
fn visit_items(items: &mut [Item]) {
27+
items.sort_by_key(|item| match item {
28+
Item::Type(_) => 0,
29+
Item::Struct(_) => 1,
30+
Item::Const(_) => 2,
31+
Item::Fn(_) => 3,
32+
Item::Enum(_) => 4,
33+
Item::Union(_) => 5,
34+
Item::Static(_) => 6,
35+
Item::Trait(_) => 7,
36+
Item::TraitAlias(_) => 8,
37+
Item::Impl(_) => 9,
38+
Item::Mod(_) => 10,
39+
Item::Use(_) => 11,
40+
Item::Verbatim(_) => 12,
41+
Item::ExternCrate(_) => 13,
42+
Item::ForeignMod(_) => 14,
43+
Item::Macro(_) => 15,
44+
Item::Macro2(_) => 16,
45+
_ => 18,
46+
});
47+
}

0 commit comments

Comments
 (0)