@@ -25,18 +25,6 @@ use wit_component::{StringEncoding, WitPrinter};
2525mod csproj;
2626pub use csproj:: CSProject ;
2727
28- //TODO remove unused
29- const CSHARP_IMPORTS : & str = "\
30- using System;
31- using System.Runtime.CompilerServices;
32- using System.Collections;
33- using System.Runtime.InteropServices;
34- using System.Text;
35- using System.Collections.Generic;
36- using System.Diagnostics;
37- using System.Diagnostics.CodeAnalysis;
38- " ;
39-
4028#[ derive( Default , Debug , Clone ) ]
4129#[ cfg_attr( feature = "clap" , derive( clap:: Args ) ) ]
4230pub struct Opts {
@@ -106,6 +94,8 @@ struct InterfaceFragment {
10694 csharp_src : String ,
10795 csharp_interop_src : String ,
10896 stub : String ,
97+ usings : HashSet < String > ,
98+ interop_usings : HashSet < String > ,
10999}
110100
111101pub struct InterfaceTypeAndFragments {
@@ -133,6 +123,8 @@ pub enum FunctionLevel {
133123pub struct CSharp {
134124 opts : Opts ,
135125 name : String ,
126+ usings : HashSet < String > ,
127+ interop_usings : HashSet < String > ,
136128 return_area_size : usize ,
137129 return_area_align : usize ,
138130 tuple_counts : HashSet < usize > ,
@@ -180,6 +172,8 @@ impl CSharp {
180172 resolve,
181173 name,
182174 direction,
175+ usings : HashSet :: < String > :: new ( ) ,
176+ interop_usings : HashSet :: < String > :: new ( ) ,
183177 }
184178 }
185179
@@ -196,6 +190,20 @@ impl CSharp {
196190 ( String :: new ( ) , String :: new ( ) )
197191 }
198192 }
193+
194+ fn require_using ( & mut self , using_ns : & str ) {
195+ if !self . usings . contains ( using_ns) {
196+ let using_ns_string = using_ns. to_string ( ) ;
197+ self . usings . insert ( using_ns_string) ;
198+ }
199+ }
200+
201+ fn require_interop_using ( & mut self , using_ns : & str ) {
202+ if !self . interop_usings . contains ( using_ns) {
203+ let using_ns_string = using_ns. to_string ( ) ;
204+ self . interop_usings . insert ( using_ns_string) ;
205+ }
206+ }
199207}
200208
201209impl WorldGenerator for CSharp {
@@ -405,10 +413,11 @@ impl WorldGenerator for CSharp {
405413
406414 let access = self . access_modifier ( ) ;
407415
416+ let using_pos = src. len ( ) ;
417+
408418 uwrite ! (
409419 src,
410- "{CSHARP_IMPORTS}
411-
420+ "
412421 namespace {world_namespace} {{
413422
414423 {access} interface I{name}World {{
@@ -424,6 +433,16 @@ impl WorldGenerator for CSharp {
424433 . join ( "\n " ) ,
425434 ) ;
426435
436+ let usings: Vec < _ > = self
437+ . world_fragments
438+ . iter ( )
439+ . flat_map ( |f| & f. usings )
440+ . cloned ( )
441+ . collect ( ) ;
442+ usings. iter ( ) . for_each ( |u| {
443+ self . require_using ( u) ;
444+ } ) ;
445+
427446 let mut producers = wasm_metadata:: Producers :: empty ( ) ;
428447 producers. add (
429448 "processed-by" ,
@@ -434,6 +453,7 @@ impl WorldGenerator for CSharp {
434453 src. push_str ( "}\n " ) ;
435454
436455 if self . needs_result {
456+ self . require_using ( "System.Runtime.InteropServices" ) ;
437457 uwrite ! (
438458 src,
439459 r#"
@@ -495,6 +515,7 @@ impl WorldGenerator for CSharp {
495515 }
496516
497517 if self . needs_option {
518+ self . require_using ( "System.Diagnostics.CodeAnalysis" ) ;
498519 uwrite ! (
499520 src,
500521 r#"
@@ -525,6 +546,8 @@ impl WorldGenerator for CSharp {
525546 }
526547
527548 if self . needs_interop_string {
549+ self . require_using ( "System.Text" ) ;
550+ self . require_using ( "System.Runtime.InteropServices" ) ;
528551 uwrite ! (
529552 src,
530553 r#"
@@ -568,6 +591,8 @@ impl WorldGenerator for CSharp {
568591
569592 let ( array_size, element_type) =
570593 dotnet_aligned_array ( self . return_area_size , self . return_area_align ) ;
594+
595+ self . require_using ( "System.Runtime.CompilerServices" ) ;
571596 uwrite ! (
572597 ret_area_str,
573598 "
@@ -607,6 +632,17 @@ impl WorldGenerator for CSharp {
607632 src. push_str ( "\n " ) ;
608633
609634 src. push_str ( "namespace exports {\n " ) ;
635+
636+ src. push_str (
637+ & self
638+ . world_fragments
639+ . iter ( )
640+ . flat_map ( |f| & f. interop_usings )
641+ . map ( |s| "using " . to_owned ( ) + s + ";" )
642+ . collect :: < Vec < String > > ( )
643+ . join ( "\n " ) ,
644+ ) ;
645+
610646 src. push_str ( & format ! ( "{access} static class {name}World\n " ) ) ;
611647 src. push_str ( "{" ) ;
612648
@@ -623,6 +659,16 @@ impl WorldGenerator for CSharp {
623659
624660 src. push_str ( "}\n " ) ;
625661
662+ src. insert_str (
663+ using_pos,
664+ & self
665+ . usings
666+ . iter ( )
667+ . map ( |s| "using " . to_owned ( ) + s + ";" )
668+ . collect :: < Vec < String > > ( )
669+ . join ( "\n " ) ,
670+ ) ;
671+
626672 files. push ( & format ! ( "{name}.cs" ) , indent ( & src) . as_bytes ( ) ) ;
627673
628674 let generate_stub = |name : String , files : & mut Files , stubs : Stubs | {
@@ -668,8 +714,6 @@ impl WorldGenerator for CSharp {
668714
669715 let body = format ! (
670716 "{header}
671- {CSHARP_IMPORTS}
672-
673717 namespace {fully_qualified_namespace};
674718
675719 {access} partial class {stub_class_name} : {interface_or_class_name} {{
@@ -789,14 +833,20 @@ impl WorldGenerator for CSharp {
789833 if body. len ( ) > 0 {
790834 let body = format ! (
791835 "{header}
792- {CSHARP_IMPORTS }
836+ {0 }
793837
794838 namespace {namespace};
795839
796840 {access} interface {interface_name} {{
797841 {body}
798842 }}
799- "
843+ " ,
844+ fragments
845+ . iter( )
846+ . flat_map( |f| & f. usings)
847+ . map( |s| "using " . to_owned( ) + s + ";" )
848+ . collect:: <Vec <String >>( )
849+ . join( "\n " ) ,
800850 ) ;
801851
802852 files. push ( & format ! ( "{full_name}.cs" ) , indent ( & body) . as_bytes ( ) ) ;
@@ -812,15 +862,21 @@ impl WorldGenerator for CSharp {
812862 let class_name = interface_name. strip_prefix ( "I" ) . unwrap ( ) ;
813863 let body = format ! (
814864 "{header}
815- {CSHARP_IMPORTS }
865+ {0 }
816866
817867 namespace {namespace}
818868 {{
819869 {access} static class {class_name}Interop {{
820870 {body}
821871 }}
822872 }}
823- "
873+ " ,
874+ fragments
875+ . iter( )
876+ . flat_map( |f| & f. interop_usings)
877+ . map( |s| "using " . to_owned( ) + s + ";\n " )
878+ . collect:: <Vec <String >>( )
879+ . join( "" ) ,
824880 ) ;
825881
826882 files. push (
@@ -845,6 +901,8 @@ struct InterfaceGenerator<'a> {
845901 resolve : & ' a Resolve ,
846902 name : & ' a str ,
847903 direction : Direction ,
904+ usings : HashSet < String > ,
905+ interop_usings : HashSet < String > ,
848906}
849907
850908impl InterfaceGenerator < ' _ > {
@@ -956,6 +1014,8 @@ impl InterfaceGenerator<'_> {
9561014 csharp_src : self . src ,
9571015 csharp_interop_src : self . csharp_interop_src ,
9581016 stub : self . stub ,
1017+ usings : self . usings ,
1018+ interop_usings : self . interop_usings ,
9591019 } ) ;
9601020 }
9611021
@@ -964,6 +1024,8 @@ impl InterfaceGenerator<'_> {
9641024 csharp_src : self . src ,
9651025 csharp_interop_src : self . csharp_interop_src ,
9661026 stub : self . stub ,
1027+ usings : self . usings ,
1028+ interop_usings : self . interop_usings ,
9671029 } ) ;
9681030 }
9691031
@@ -1083,8 +1145,10 @@ impl InterfaceGenerator<'_> {
10831145 let import_name = & func. name ;
10841146
10851147 let target = if let FunctionKind :: Freestanding = & func. kind {
1148+ self . require_interop_using ( "System.Runtime.InteropServices" ) ;
10861149 & mut self . csharp_interop_src
10871150 } else {
1151+ self . require_using ( "System.Runtime.InteropServices" ) ;
10881152 & mut self . src
10891153 } ;
10901154
@@ -1229,6 +1293,7 @@ impl InterfaceGenerator<'_> {
12291293 let export_name = func. legacy_core_export_name ( core_module_name. as_deref ( ) ) ;
12301294 let access = self . gen . access_modifier ( ) ;
12311295
1296+ self . require_interop_using ( "System.Runtime.InteropServices" ) ;
12321297 uwrite ! (
12331298 self . csharp_interop_src,
12341299 r#"
@@ -1429,6 +1494,20 @@ impl InterfaceGenerator<'_> {
14291494 }
14301495 }
14311496
1497+ fn require_using ( & mut self , using_ns : & str ) {
1498+ if !self . usings . contains ( using_ns) {
1499+ let using_ns_string = using_ns. to_string ( ) ;
1500+ self . usings . insert ( using_ns_string) ;
1501+ }
1502+ }
1503+
1504+ fn require_interop_using ( & mut self , using_ns : & str ) {
1505+ if !self . interop_usings . contains ( using_ns) {
1506+ let using_ns_string = using_ns. to_string ( ) ;
1507+ self . interop_usings . insert ( using_ns_string) ;
1508+ }
1509+ }
1510+
14321511 fn start_resource ( & mut self , id : TypeId , key : Option < & WorldKey > ) {
14331512 let access = self . gen . access_modifier ( ) ;
14341513 let qualified = self . type_name_with_qualifier ( & Type :: Id ( id) , true ) ;
@@ -1444,6 +1523,7 @@ impl InterfaceGenerator<'_> {
14441523 . map ( |key| self . resolve . name_world_key ( key) )
14451524 . unwrap_or_else ( || "$root" . into ( ) ) ;
14461525
1526+ self . require_using ( "System.Runtime.InteropServices" ) ;
14471527 // As of this writing, we cannot safely drop a handle to an imported resource from a .NET finalizer
14481528 // because it may still have one or more open child resources. Once WIT has explicit syntax for
14491529 // indicating parent/child relationships, we should be able to use that information to keep track
@@ -1482,6 +1562,7 @@ impl InterfaceGenerator<'_> {
14821562 . map ( |s| format ! ( "{}#" , self . resolve. name_world_key( s) ) )
14831563 . unwrap_or_else ( String :: new) ;
14841564
1565+ self . require_interop_using ( "System.Runtime.InteropServices" ) ;
14851566 uwrite ! (
14861567 self . csharp_interop_src,
14871568 r#"
@@ -1500,6 +1581,7 @@ impl InterfaceGenerator<'_> {
15001581 . map ( |key| format ! ( "[export]{}" , self . resolve. name_world_key( key) ) )
15011582 . unwrap_or_else ( || "[export]$root" . into ( ) ) ;
15021583
1584+ self . require_using ( "System.Runtime.InteropServices" ) ;
15031585 // The ergonomics of exported resources are not ideal, currently. Implementing such a resource
15041586 // requires both extending a class and implementing an interface. The reason for the class is to
15051587 // allow implementers to inherit code which tracks and disposes of the resource handle; the reason
@@ -2584,10 +2666,18 @@ impl Bindgen for FunctionBindgen<'_, '_> {
25842666 self . gen . gen . needs_interop_string = true ;
25852667 }
25862668
2587- Instruction :: StringLift { .. } => results. push ( format ! (
2588- "Encoding.UTF8.GetString((byte*){}, {})" ,
2589- operands[ 0 ] , operands[ 1 ]
2590- ) ) ,
2669+ Instruction :: StringLift { .. } => {
2670+ if FunctionKind :: Freestanding == * self . kind || self . gen . direction == Direction :: Export {
2671+ self . gen . require_interop_using ( "System.Text" ) ;
2672+ } else {
2673+ self . gen . require_using ( "System.Text" ) ;
2674+ }
2675+
2676+ results. push ( format ! (
2677+ "Encoding.UTF8.GetString((byte*){}, {})" ,
2678+ operands[ 0 ] , operands[ 1 ]
2679+ ) ) ;
2680+ }
25912681
25922682 Instruction :: ListLower { element, realloc } => {
25932683 let Block {
0 commit comments