@@ -4,145 +4,126 @@ use syn::Item;
4
4
5
5
use crate :: BindgenOptions ;
6
6
7
- macro_rules! decl_postprocessing {
8
- ( $( $ty: ty) ,* ) => {
9
- pub ( crate ) fn postprocessing(
10
- items: Vec <TokenStream >,
11
- options: & BindgenOptions ,
12
- ) -> TokenStream {
13
- // Whether any of the enabled options requires `syn`.
14
- let require_syn = $( <$ty as PostProcessing >:: should_run( options) ) ||* ;
15
-
16
- if !require_syn {
17
- return items. into_iter( ) . collect( ) ;
18
- }
19
-
20
- let module_wrapped_tokens =
21
- quote!( mod wrapper_for_sorting_hack { #( #items ) * } ) ;
22
-
23
- // This syn business is a hack, for now. This means that we are re-parsing already
24
- // generated code using `syn` (as opposed to `quote`) because `syn` provides us more
25
- // control over the elements.
26
- // One caveat is that some of the items coming from `quote`d output might have
27
- // multiple items within them. Hence, we have to wrap the incoming in a `mod`.
28
- // The two `unwrap`s here are deliberate because
29
- // The first one won't panic because we build the `mod` and know it is there
30
- // The second one won't panic because we know original output has something in
31
- // it already.
32
- let mut items =
33
- syn:: parse2:: <syn:: ItemMod >( module_wrapped_tokens)
34
- . unwrap( )
35
- . content
36
- . unwrap( )
37
- . 1 ;
38
-
39
- $( if <$ty as PostProcessing >:: should_run( options) {
40
- <$ty as PostProcessing >:: run( & mut items) ;
41
- } ) *
42
-
43
- let synful_items = items
44
- . into_iter( )
45
- . map( |item| item. into_token_stream( ) ) ;
7
+ struct PostProcessingPass {
8
+ should_run : fn ( & BindgenOptions ) -> bool ,
9
+ run : fn ( & mut Vec < Item > ) ,
10
+ }
46
11
47
- quote! { #( #synful_items ) * }
12
+ // TODO: This can be a const fn when mutable references are allowed in const
13
+ // context.
14
+ macro_rules! pass {
15
+ ( $pass: ident) => {
16
+ PostProcessingPass {
17
+ should_run: |options| options. $pass,
18
+ run: $pass,
48
19
}
49
20
} ;
50
21
}
51
22
52
- decl_postprocessing ! {
53
- MergeExternBlocks ,
54
- SortSemantically
55
- }
56
-
57
- trait PostProcessing {
58
- fn should_run ( options : & BindgenOptions ) -> bool ;
59
-
60
- fn run ( items : & mut Vec < Item > ) ;
61
- }
62
-
63
- struct SortSemantically ;
23
+ static PASSES : [ PostProcessingPass ; 2 ] =
24
+ [ pass ! ( merge_extern_blocks) , pass ! ( sort_semantically) ] ;
64
25
65
- impl PostProcessing for SortSemantically {
66
- #[ inline]
67
- fn should_run ( options : & BindgenOptions ) -> bool {
68
- options. sort_semantically
26
+ pub ( crate ) fn postprocessing (
27
+ items : Vec < TokenStream > ,
28
+ options : & BindgenOptions ,
29
+ ) -> TokenStream {
30
+ let require_syn = PASSES . iter ( ) . any ( |pass| ( pass. should_run ) ( options) ) ;
31
+ if !require_syn {
32
+ return items. into_iter ( ) . collect ( ) ;
69
33
}
70
-
71
- fn run ( items : & mut Vec < Item > ) {
72
- items . sort_by_key ( |item| match item {
73
- Item :: Type ( _ ) => 0 ,
74
- Item :: Struct ( _ ) => 1 ,
75
- Item :: Const ( _ ) => 2 ,
76
- Item :: Fn ( _ ) => 3 ,
77
- Item :: Enum ( _ ) => 4 ,
78
- Item :: Union ( _ ) => 5 ,
79
- Item :: Static ( _ ) => 6 ,
80
- Item :: Trait ( _ ) => 7 ,
81
- Item :: TraitAlias ( _ ) => 8 ,
82
- Item :: Impl ( _ ) => 9 ,
83
- Item :: Mod ( _ ) => 10 ,
84
- Item :: Use ( _ ) => 11 ,
85
- Item :: Verbatim ( _ ) => 12 ,
86
- Item :: ExternCrate ( _ ) => 13 ,
87
- Item :: ForeignMod ( _ ) => 14 ,
88
- Item :: Macro ( _ ) => 15 ,
89
- Item :: Macro2 ( _ ) => 16 ,
90
- _ => 18 ,
91
- } ) ;
34
+ let module_wrapped_tokens =
35
+ quote ! ( mod wrapper_for_sorting_hack { # ( #items ) * } ) ;
36
+
37
+ // This syn business is a hack, for now. This means that we are re-parsing already
38
+ // generated code using `syn` (as opposed to `quote`) because `syn` provides us more
39
+ // control over the elements.
40
+ // One caveat is that some of the items coming from `quote`d output might have
41
+ // multiple items within them. Hence, we have to wrap the incoming in a `mod`.
42
+ // The two `unwrap`s here are deliberate because
43
+ // The first one won't panic because we build the `mod` and know it is there
44
+ // The second one won't panic because we know original output has something in
45
+ // it already.
46
+ let mut items = syn :: parse2 :: < syn :: ItemMod > ( module_wrapped_tokens )
47
+ . unwrap ( )
48
+ . content
49
+ . unwrap ( )
50
+ . 1 ;
51
+
52
+ for pass in PASSES . iter ( ) {
53
+ if ( pass . should_run ) ( options ) {
54
+ ( pass . run ) ( & mut items ) ;
55
+ }
92
56
}
93
- }
94
57
95
- struct MergeExternBlocks ;
58
+ let synful_items = items . into_iter ( ) . map ( |item| item . into_token_stream ( ) ) ;
96
59
97
- impl PostProcessing for MergeExternBlocks {
98
- #[ inline]
99
- fn should_run ( options : & BindgenOptions ) -> bool {
100
- options. merge_extern_blocks
101
- }
60
+ quote ! { #( #synful_items ) * }
61
+ }
102
62
103
- fn run ( items : & mut Vec < Item > ) {
104
- // Keep all the extern blocks in a different `Vec` for faster search.
105
- let mut foreign_mods = Vec :: < syn:: ItemForeignMod > :: new ( ) ;
63
+ fn sort_semantically ( items : & mut Vec < Item > ) {
64
+ items. sort_by_key ( |item| match item {
65
+ Item :: Type ( _) => 0 ,
66
+ Item :: Struct ( _) => 1 ,
67
+ Item :: Const ( _) => 2 ,
68
+ Item :: Fn ( _) => 3 ,
69
+ Item :: Enum ( _) => 4 ,
70
+ Item :: Union ( _) => 5 ,
71
+ Item :: Static ( _) => 6 ,
72
+ Item :: Trait ( _) => 7 ,
73
+ Item :: TraitAlias ( _) => 8 ,
74
+ Item :: Impl ( _) => 9 ,
75
+ Item :: Mod ( _) => 10 ,
76
+ Item :: Use ( _) => 11 ,
77
+ Item :: Verbatim ( _) => 12 ,
78
+ Item :: ExternCrate ( _) => 13 ,
79
+ Item :: ForeignMod ( _) => 14 ,
80
+ Item :: Macro ( _) => 15 ,
81
+ Item :: Macro2 ( _) => 16 ,
82
+ _ => 18 ,
83
+ } ) ;
84
+ }
106
85
107
- for item in std:: mem:: take ( items) {
108
- match item {
109
- Item :: ForeignMod ( syn:: ItemForeignMod {
110
- attrs,
111
- abi,
112
- brace_token,
113
- items : foreign_items,
114
- } ) => {
115
- let mut exists = false ;
116
- for foreign_mod in & mut foreign_mods {
117
- // Check if there is a extern block with the same ABI and
118
- // attributes.
119
- if foreign_mod. attrs == attrs && foreign_mod. abi == abi
120
- {
121
- // Merge the items of the two blocks.
122
- foreign_mod. items . extend_from_slice ( & foreign_items) ;
123
- exists = true ;
124
- break ;
125
- }
126
- }
127
- // If no existing extern block had the same ABI and attributes, store
128
- // it.
129
- if !exists {
130
- foreign_mods. push ( syn:: ItemForeignMod {
131
- attrs,
132
- abi,
133
- brace_token,
134
- items : foreign_items,
135
- } ) ;
86
+ fn merge_extern_blocks ( items : & mut Vec < Item > ) {
87
+ // Keep all the extern blocks in a different `Vec` for faster search.
88
+ let mut foreign_mods = Vec :: < syn:: ItemForeignMod > :: new ( ) ;
89
+
90
+ for item in std:: mem:: take ( items) {
91
+ match item {
92
+ Item :: ForeignMod ( syn:: ItemForeignMod {
93
+ attrs,
94
+ abi,
95
+ brace_token,
96
+ items : foreign_items,
97
+ } ) => {
98
+ let mut exists = false ;
99
+ for foreign_mod in & mut foreign_mods {
100
+ // Check if there is a extern block with the same ABI and
101
+ // attributes.
102
+ if foreign_mod. attrs == attrs && foreign_mod. abi == abi {
103
+ // Merge the items of the two blocks.
104
+ foreign_mod. items . extend_from_slice ( & foreign_items) ;
105
+ exists = true ;
106
+ break ;
136
107
}
137
108
}
138
- // If the item is not an extern block, we don't have to do anything.
139
- _ => items. push ( item) ,
109
+ // If no existing extern block had the same ABI and attributes, store
110
+ // it.
111
+ if !exists {
112
+ foreign_mods. push ( syn:: ItemForeignMod {
113
+ attrs,
114
+ abi,
115
+ brace_token,
116
+ items : foreign_items,
117
+ } ) ;
118
+ }
140
119
}
120
+ // If the item is not an extern block, we don't have to do anything.
121
+ _ => items. push ( item) ,
141
122
}
123
+ }
142
124
143
- // Move all the extern blocks alongiside the rest of the items.
144
- for foreign_mod in foreign_mods {
145
- items. push ( Item :: ForeignMod ( foreign_mod) ) ;
146
- }
125
+ // Move all the extern blocks alongside the rest of the items.
126
+ for foreign_mod in foreign_mods {
127
+ items. push ( Item :: ForeignMod ( foreign_mod) ) ;
147
128
}
148
129
}
0 commit comments