@@ -254,42 +254,74 @@ struct SignatureStruct {
254254 args_comment : Option < String > , // Parsed from // args: (name: type, ...) comment
255255}
256256
257- // Find all interface imports in the world WIT file
257+ // Find all interface imports in the selected world WIT file(s)
258258#[ instrument( level = "trace" , skip_all) ]
259- fn find_interfaces_in_world ( api_dir : & Path ) -> Result < Vec < String > > {
260- debug ! ( dir = ?api_dir, "Finding interface imports in world definitions" ) ;
261- let mut interfaces = Vec :: new ( ) ;
259+ fn find_interfaces_in_world ( api_dir : & Path , world_name : & str ) -> Result < Vec < String > > {
260+ debug ! ( dir = ?api_dir, world = %world_name , "Finding interface imports in world definitions" ) ;
261+ let mut world_defs : HashMap < String , String > = HashMap :: new ( ) ;
262262
263- // Find world definition files
263+ // Index world definition files by world name
264264 for entry in WalkDir :: new ( api_dir)
265265 . max_depth ( 1 )
266266 . into_iter ( )
267267 . filter_map ( Result :: ok)
268268 {
269269 let path = entry. path ( ) ;
270+ if !( path. is_file ( ) && path. extension ( ) . map_or ( false , |ext| ext == "wit" ) ) {
271+ continue ;
272+ }
273+ let Ok ( content) = fs:: read_to_string ( path) else {
274+ continue ;
275+ } ;
276+ if !content. contains ( "world " ) {
277+ continue ;
278+ }
279+ if let Some ( world_line) = content. lines ( ) . find ( |line| line. trim ( ) . starts_with ( "world " ) ) {
280+ if let Some ( name) = world_line. trim ( ) . split_whitespace ( ) . nth ( 1 ) {
281+ let clean_name = name. trim_end_matches ( " {" ) . trim_start_matches ( '%' ) ;
282+ world_defs. insert ( clean_name. to_string ( ) , content) ;
283+ debug ! ( file = %path. display( ) , world = %clean_name, "Indexed world definition" ) ;
284+ }
285+ }
286+ }
270287
271- if path. is_file ( ) && path. extension ( ) . map_or ( false , |ext| ext == "wit" ) {
272- if let Ok ( content) = fs:: read_to_string ( path) {
273- if content. contains ( "world " ) {
274- debug ! ( file = %path. display( ) , "Analyzing world definition file for imports" ) ;
275-
276- // Extract import statements
277- for line in content. lines ( ) {
278- let line = line. trim ( ) ;
279- if line. starts_with ( "import " ) && line. ends_with ( ";" ) {
280- let interface = line
281- . trim_start_matches ( "import " )
282- . trim_end_matches ( ";" )
283- . trim ( ) ;
284-
285- interfaces. push ( interface. to_string ( ) ) ;
286- debug ! ( interface = %interface, "Found interface import" ) ;
287- }
288- }
289- }
288+ let mut interfaces = Vec :: new ( ) ;
289+ let mut visited = std:: collections:: HashSet :: new ( ) ;
290+ let mut stack = vec ! [ world_name. to_string( ) ] ;
291+
292+ while let Some ( current_world) = stack. pop ( ) {
293+ let clean_world = current_world. trim_start_matches ( '%' ) . to_string ( ) ;
294+ if !visited. insert ( clean_world. clone ( ) ) {
295+ continue ;
296+ }
297+ let Some ( content) = world_defs. get ( & clean_world) else {
298+ debug ! ( world = %clean_world, "World definition not found for imports" ) ;
299+ continue ;
300+ } ;
301+
302+ debug ! ( world = %clean_world, "Analyzing world definition file for imports" ) ;
303+ for line in content. lines ( ) {
304+ let line = line. trim ( ) ;
305+ if line. starts_with ( "import " ) && line. ends_with ( ';' ) {
306+ let interface = line
307+ . trim_start_matches ( "import " )
308+ . trim_end_matches ( ';' )
309+ . trim ( )
310+ . trim_start_matches ( '%' ) ;
311+ interfaces. push ( interface. to_string ( ) ) ;
312+ debug ! ( interface = %interface, "Found interface import" ) ;
313+ } else if line. starts_with ( "include " ) && line. ends_with ( ';' ) {
314+ let include_world = line
315+ . trim_start_matches ( "include " )
316+ . trim_end_matches ( ';' )
317+ . trim ( )
318+ . trim_start_matches ( '%' )
319+ . to_string ( ) ;
320+ stack. push ( include_world) ;
290321 }
291322 }
292323 }
324+
293325 debug ! ( count = interfaces. len( ) , interfaces = ?interfaces, "Found interface imports" ) ;
294326 Ok ( interfaces)
295327}
@@ -620,8 +652,8 @@ crate-type = ["cdylib", "lib"]
620652 "types"
621653 } ;
622654
623- // Get all interfaces from the world file
624- let interface_imports = find_interfaces_in_world ( api_dir) ?;
655+ // Get all interfaces from the selected world
656+ let interface_imports = find_interfaces_in_world ( api_dir, world_name ) ?;
625657
626658 // Store all types from each interface
627659 let mut interface_types: HashMap < String , Vec < String > > = HashMap :: new ( ) ;
@@ -638,8 +670,17 @@ crate-type = ["cdylib", "lib"]
638670 // Exclude world definition files
639671 if let Ok ( content) = fs:: read_to_string ( path) {
640672 if !content. contains ( "world " ) {
641- debug ! ( file = %path. display( ) , "Adding WIT file for parsing" ) ;
642- wit_files. push ( path. to_path_buf ( ) ) ;
673+ let interface_name = path. file_stem ( ) . unwrap ( ) . to_string_lossy ( ) ;
674+ let interface_name = interface_name. trim_start_matches ( '%' ) ;
675+ if interface_imports
676+ . iter ( )
677+ . any ( |i| i. trim_start_matches ( '%' ) == interface_name)
678+ {
679+ debug ! ( file = %path. display( ) , "Adding WIT file for parsing" ) ;
680+ wit_files. push ( path. to_path_buf ( ) ) ;
681+ } else {
682+ debug ! ( file = %path. display( ) , "Skipping WIT file not in selected world" ) ;
683+ }
643684 } else {
644685 debug ! ( file = %path. display( ) , "Skipping world definition WIT file" ) ;
645686 }
0 commit comments