@@ -156,19 +156,22 @@ pub(crate) fn expand(input: proc_macro::TokenStream) -> proc_macro::TokenStream
156156}
157157
158158/// Generates WIT bindings using `wit-bindgen` directly instead of the `generate!` macro.
159+ ///
160+ /// The `world` parameter specifies which world to generate bindings for. This should already
161+ /// be resolved by the caller (either from inline WIT or from the local wit/ directory).
162+ /// If `None`, wit-bindgen will attempt to select a default world from the loaded packages.
159163fn generate_bindings (
160164 args : & GenerateArgs ,
161165 config : & manifest_paths:: ResolvedWit ,
162- world_override : Option < & str > ,
166+ world : Option < & str > ,
163167) -> Result < TokenStream2 , Error > {
164168 let inline_src = args. inline . as_ref ( ) . map ( |src| src. value ( ) ) ;
165169 let inline_ref = inline_src. as_deref ( ) ;
166170 let wit_sources = load_wit_sources ( & config. paths , inline_ref) ?;
167171
168- let world_spec = world_override. or ( config. world . as_deref ( ) ) ;
169- let world = wit_sources
172+ let world_id = wit_sources
170173 . resolve
171- . select_world ( & wit_sources. packages , world_spec )
174+ . select_world ( & wit_sources. packages , world )
172175 . map_err ( |err| Error :: new ( Span :: call_site ( ) , err. to_string ( ) ) ) ?;
173176
174177 let mut opts = Opts {
@@ -183,7 +186,7 @@ fn generate_bindings(
183186 let mut generated_files = wit_bindgen_core:: Files :: default ( ) ;
184187 let mut generator = opts. build ( ) ;
185188 generator
186- . generate ( & wit_sources. resolve , world , & mut generated_files)
189+ . generate ( & wit_sources. resolve , world_id , & mut generated_files)
187190 . map_err ( |err| Error :: new ( Span :: call_site ( ) , err. to_string ( ) ) ) ?;
188191
189192 let ( _, src_bytes) = generated_files
@@ -950,4 +953,94 @@ mod tests {
950953 assert_eq ! ( parsed. with_entries[ 0 ] . 0 , "miden:a/b" ) ;
951954 assert_eq ! ( parsed. with_entries[ 1 ] . 0 , "miden:c/d" ) ;
952955 }
956+
957+ /// Integration test verifying that `augment_generated_bindings` produces valid Rust code.
958+ ///
959+ /// This test simulates realistic wit-bindgen output with custom types, multiple methods,
960+ /// and verifies the augmented output parses as valid Rust and contains the expected
961+ /// wrapper struct with properly qualified type paths.
962+ #[ test]
963+ fn test_augment_generated_bindings_integration ( ) {
964+ // Simulate more realistic wit-bindgen output with types and multiple leaf modules
965+ let src = r#"
966+ mod miden {
967+ mod basic_wallet {
968+ mod basic_wallet {
969+ pub struct AssetInfo {
970+ pub amount: u64,
971+ }
972+
973+ pub fn receive_asset(asset: AssetInfo) {}
974+ pub fn move_asset_to_note(asset: AssetInfo, note_idx: u32) -> bool { true }
975+ fn _internal_helper() {} // Should be skipped (underscore prefix)
976+ }
977+ }
978+ mod other_component {
979+ mod other_component {
980+ pub fn do_something(value: u64) -> u64 { value }
981+ }
982+ }
983+ }
984+ mod exports {
985+ mod my_export {
986+ pub fn exported_fn() {} // Should be skipped (exports module)
987+ }
988+ }
989+ "# ;
990+
991+ let tokens: TokenStream2 = src. parse ( ) . unwrap ( ) ;
992+ let result = augment_generated_bindings ( tokens) . unwrap ( ) ;
993+
994+ // Verify the output parses as valid Rust
995+ let parsed: File =
996+ syn:: parse2 ( result. clone ( ) ) . expect ( "augmented bindings should be valid Rust syntax" ) ;
997+
998+ // Find the Account struct and impl
999+ let has_account_struct = parsed
1000+ . items
1001+ . iter ( )
1002+ . any ( |item| matches ! ( item, Item :: Struct ( s) if s. ident == "Account" ) ) ;
1003+ let has_account_impl = parsed. items . iter ( ) . any ( |item| {
1004+ matches ! ( item, Item :: Impl ( i) if i. self_ty. to_token_stream( ) . to_string( ) == "Account" )
1005+ } ) ;
1006+
1007+ assert ! ( has_account_struct, "should generate Account struct" ) ;
1008+ assert ! ( has_account_impl, "should generate Account impl" ) ;
1009+
1010+ // Find the impl block and verify methods
1011+ let impl_block = parsed
1012+ . items
1013+ . iter ( )
1014+ . find_map ( |item| match item {
1015+ Item :: Impl ( i) if i. self_ty . to_token_stream ( ) . to_string ( ) == "Account" => Some ( i) ,
1016+ _ => None ,
1017+ } )
1018+ . expect ( "Account impl should exist" ) ;
1019+
1020+ let method_names: Vec < String > = impl_block
1021+ . items
1022+ . iter ( )
1023+ . filter_map ( |item| match item {
1024+ ImplItem :: Fn ( f) => Some ( f. sig . ident . to_string ( ) ) ,
1025+ _ => None ,
1026+ } )
1027+ . collect ( ) ;
1028+
1029+ // Should include methods from both leaf modules
1030+ assert ! ( method_names. contains( & "receive_asset" . to_string( ) ) ) ;
1031+ assert ! ( method_names. contains( & "move_asset_to_note" . to_string( ) ) ) ;
1032+ assert ! ( method_names. contains( & "do_something" . to_string( ) ) ) ;
1033+
1034+ // Should NOT include internal helper or exported functions
1035+ assert ! ( !method_names. contains( & "_internal_helper" . to_string( ) ) ) ;
1036+ assert ! ( !method_names. contains( & "exported_fn" . to_string( ) ) ) ;
1037+
1038+ // Verify type qualification in the result string
1039+ let result_str = result. to_string ( ) ;
1040+ // AssetInfo should be qualified with its module path
1041+ assert ! (
1042+ result_str. contains( "miden :: basic_wallet :: basic_wallet :: AssetInfo" ) ,
1043+ "custom types should be qualified with module path"
1044+ ) ;
1045+ }
9531046}
0 commit comments