22using Microsoft . CodeAnalysis . CSharp ;
33
44using Mono . Cecil ;
5+ using Mono . Cecil . Cil ;
56
67using System ;
78using System . Globalization ;
@@ -48,6 +49,14 @@ public class InjectorGenerator : IIncrementalGenerator
4849 DiagnosticSeverity . Error ,
4950 true ) ;
5051
52+ private static readonly DiagnosticDescriptor MissingEmbeddedResource = new (
53+ "INJ005" ,
54+ "Missing Embedded Resource" ,
55+ "Embedded resource '{0}' not found in assembly." ,
56+ "Generator" ,
57+ DiagnosticSeverity . Error ,
58+ true ) ;
59+
5160 private static readonly Regex InvalidIdentifierCharacters = new ( "[^a-zA-Z0-9]" , RegexOptions . Compiled ) ;
5261
5362 public void Initialize ( IncrementalGeneratorInitializationContext context )
@@ -74,8 +83,15 @@ public void Initialize(IncrementalGeneratorInitializationContext context)
7483
7584 try
7685 {
77- var fullPath = Path . Combine ( Path . GetDirectoryName ( props . CsProjPath ) ! , props . OutputPath ) ;
78- GenerateAssembly ( fullPath , props . ModuleId ) ;
86+ var projectDir = Path . GetDirectoryName ( props . CsProjPath ) ;
87+ if ( projectDir is null )
88+ {
89+ spc . ReportDiagnostic ( Diagnostic . Create ( ModuleGenerationFailed , Location . None , props . ModuleId , "Could not determine project directory" ) ) ;
90+ return ;
91+ }
92+
93+ var fullPath = Path . Combine ( projectDir , props . OutputPath ) ;
94+ GenerateAssembly ( spc , fullPath , props . ModuleId ) ;
7995 spc . ReportDiagnostic ( Diagnostic . Create ( ModuleGenerationSuccessful , Location . None , props . ModuleId ) ) ;
8096 }
8197 catch ( Exception ex )
@@ -85,38 +101,47 @@ public void Initialize(IncrementalGeneratorInitializationContext context)
85101 } ) ;
86102 }
87103
88- private static void GenerateAssembly ( string fullPath , string moduleId )
104+ private static void GenerateAssembly ( SourceProductionContext spc , string fullPath , string moduleId )
89105 {
90- CopyEmbeddedResourceToFile ( "Bannerlord.ModuleLoader.dll" , Path . Combine ( fullPath , $ "Bannerlord.ModuleLoader.{ moduleId } .dll") , stream => SetNames ( moduleId , stream ) ) ;
91- CopyEmbeddedResourceToFile ( "Bannerlord.ModuleLoader.pdb" , Path . Combine ( fullPath , $ "Bannerlord.ModuleLoader.{ moduleId } .pdb") ) ;
92- }
106+ using var dllStream = typeof ( InjectorGenerator ) . Assembly . GetManifestResourceStream ( "Bannerlord.ModuleLoader.dll" ) ;
107+ using var pdbStream = typeof ( InjectorGenerator ) . Assembly . GetManifestResourceStream ( "Bannerlord.ModuleLoader.pdb" ) ;
93108
94- private static void CopyEmbeddedResourceToFile ( string resourceName , string destinationPath , Func < Stream , Stream > ? transform = null )
95- {
96- using var resourceStream = typeof ( InjectorGenerator ) . Assembly . GetManifestResourceStream ( resourceName ) ;
97- if ( resourceStream is null ) return ;
109+ if ( dllStream is null )
110+ {
111+ spc . ReportDiagnostic ( Diagnostic . Create ( MissingEmbeddedResource , Location . None , "Bannerlord.ModuleLoader.dll" ) ) ;
112+ return ;
113+ }
98114
99- using var outputStream = new FileStream ( destinationPath , FileMode . Create , FileAccess . Write ) ;
100- using var finalStream = transform is not null ? transform ( resourceStream ) : resourceStream ;
115+ if ( pdbStream is null )
116+ {
117+ spc . ReportDiagnostic ( Diagnostic . Create ( MissingEmbeddedResource , Location . None , "Bannerlord.ModuleLoader.pdb" ) ) ;
118+ return ;
119+ }
101120
102- finalStream . CopyTo ( outputStream ) ;
103- }
121+ using var modifiedAssembly = AssemblyDefinition . ReadAssembly ( dllStream , new ReaderParameters
122+ {
123+ SymbolStream = pdbStream ,
124+ ReadSymbols = true
125+ } ) ;
104126
105- private static Stream SetNames ( string moduleName , Stream ? assemblyStream )
106- {
107- if ( assemblyStream is null )
108- throw new ArgumentNullException ( nameof ( assemblyStream ) ) ;
127+ modifiedAssembly . Name . Name = moduleId ;
128+
129+ var type = modifiedAssembly . MainModule . GetType ( "Bannerlord.ModuleLoader.SubModule" ) ;
130+ type . Name = FlatName ( moduleId ) ;
109131
110- using var modifiedAss = AssemblyDefinition . ReadAssembly ( assemblyStream ) ;
111- modifiedAss . Name . Name = moduleName ;
132+ var dllPath = Path . Combine ( fullPath , $ "Bannerlord.ModuleLoader. { moduleId } .dll" ) ;
133+ var pdbPath = Path . Combine ( fullPath , $ "Bannerlord.ModuleLoader. { moduleId } .pdb" ) ;
112134
113- var type = modifiedAss . MainModule . GetType ( "Bannerlord.ModuleLoader.SubModule" ) ;
114- type . Name = FlatName ( moduleName ) ;
135+ using var outputDllStream = new FileStream ( dllPath , FileMode . Create , FileAccess . Write ) ;
136+ using var outputPdbStream = new FileStream ( pdbPath , FileMode . Create , FileAccess . Write ) ;
115137
116- var ms = new MemoryStream ( ) ;
117- modifiedAss . Write ( ms , new WriterParameters { DeterministicMvid = true } ) ;
118- ms . Seek ( 0 , SeekOrigin . Begin ) ;
119- return ms ;
138+ modifiedAssembly . Write ( outputDllStream , new WriterParameters
139+ {
140+ DeterministicMvid = true ,
141+ WriteSymbols = true ,
142+ SymbolStream = outputPdbStream ,
143+ SymbolWriterProvider = new PortablePdbWriterProvider ( )
144+ } ) ;
120145 }
121146
122147 private static string FlatNameRegex ( string str ) => InvalidIdentifierCharacters . Replace ( str , "_" ) ;
0 commit comments