1+ using LibGit2Sharp ;
2+ using Microsoft . CodeAnalysis ;
3+ using Microsoft . CodeAnalysis . CSharp ;
4+ using Microsoft . SourceBrowser . BinLogParser ;
5+ using Mono . Options ;
6+ using NuGet . Frameworks ;
17using System ;
28using System . Collections . Generic ;
39using System . Diagnostics . CodeAnalysis ;
410using System . IO ;
511using System . Linq ;
6- using System . Numerics ;
712using System . Reflection . Metadata ;
813using System . Reflection . PortableExecutable ;
914using System . Runtime . CompilerServices ;
10- using LibGit2Sharp ;
11- using Microsoft . CodeAnalysis ;
12- using Microsoft . CodeAnalysis . CSharp ;
13- using Microsoft . SourceBrowser . BinLogParser ;
14- using Mono . Options ;
15- using NuGet . Frameworks ;
1615
1716[ assembly: InternalsVisibleTo ( "BinLogToSln.Tests" ) ]
1817
@@ -146,6 +145,7 @@ private static bool ShouldExcludeInvocation(CompilerInvocation invocation)
146145
147146 return false ;
148147 }
148+
149149 static void Main ( string [ ] args )
150150 {
151151 string binlog = null ;
@@ -205,7 +205,7 @@ static void Main(string[] args)
205205 WriteSolutionHeader ( sln ) ;
206206
207207 IEnumerable < CompilerInvocation > invocations = BinLogCompilerInvocationsReader . ExtractInvocations ( binlog ) ;
208-
208+
209209 // Group invocations by assembly name and select the best one for each
210210 var invocationGroups = invocations
211211 . Where ( invocation => ! ShouldExcludeInvocation ( invocation ) )
@@ -240,11 +240,10 @@ static void Main(string[] args)
240240 using var projFile = new FileStream ( projectFilePath , FileMode . Create ) ;
241241 using var project = new StreamWriter ( projFile ) ;
242242
243- string typeGuid = invocation . Language switch
243+ ( string typeGuid , bool isCSharp ) = invocation . Language switch
244244 {
245- LanguageNames . CSharp => CSharpProjectTypeGuid ,
246- LanguageNames . VisualBasic => VBProjectTypeGuid ,
247- _ => CSharpProjectTypeGuid ,
245+ LanguageNames . VisualBasic => ( VBProjectTypeGuid , false ) ,
246+ _ => ( CSharpProjectTypeGuid , true ) ,
248247 } ;
249248 sln . WriteLine ( $ "Project(\" { typeGuid } \" ) = \" { projectName } \" , \" { Path . Join ( "src" , repoRelativeProjectPath ) } \" , \" { GetProjectGuid ( ) } \" ") ;
250249 sln . WriteLine ( "EndProject" ) ;
@@ -255,6 +254,7 @@ static void Main(string[] args)
255254 project . WriteLine ( " <GenerateAssemblyInfo>false</GenerateAssemblyInfo>" ) ;
256255 project . WriteLine ( " <GenerateTargetFrameworkAttribute>false</GenerateTargetFrameworkAttribute>" ) ;
257256 project . WriteLine ( " <DisableImplicitFrameworkReferences>true</DisableImplicitFrameworkReferences>" ) ;
257+ project . WriteLine ( " <_SkipAnalyzers>true</_SkipAnalyzers>" ) ;
258258 project . WriteLine ( $ " <AssemblyName>{ invocation . AssemblyName } </AssemblyName>") ;
259259 int idx = 1 ;
260260 if ( invocation . Parsed . CompilationOptions is CSharpCompilationOptions cSharpOptions )
@@ -269,7 +269,7 @@ static void Main(string[] args)
269269 }
270270 if ( cSharpOptions . CryptoKeyFile != null )
271271 {
272- includeFile ( cSharpOptions . CryptoKeyFile , out string projectRelativePath , out _ ) ;
272+ string projectRelativePath = includeFile ( cSharpOptions . CryptoKeyFile , includeCompile : false ) ;
273273 project . WriteLine ( $ " <KeyOriginatorFile>{ projectRelativePath } </KeyOriginatorFile>") ;
274274 }
275275 }
@@ -283,25 +283,33 @@ static void Main(string[] args)
283283 project . WriteLine ( " <ItemGroup>" ) ;
284284 foreach ( CommandLineSourceFile sourceFile in invocation . Parsed . SourceFiles )
285285 {
286- includeFile ( sourceFile . Path , out string projectRelativePath , out string link ) ;
287- project . WriteLine ( $ " <Compile Include=\" { projectRelativePath } \" { ( link != null ? $ " Link=\" { link } \" " : "" ) } />") ;
286+ includeFile ( sourceFile . Path ) ;
288287 }
289288 project . WriteLine ( " </ItemGroup>" ) ;
290289 project . WriteLine ( " <ItemGroup>" ) ;
291290 foreach ( CommandLineReference reference in invocation . Parsed . MetadataReferences )
292291 {
293- string path = reference . Reference ;
294- if ( ! File . Exists ( path ) )
292+ includeReference ( "ReferencePath" , reference . Reference ) ;
293+ }
294+ project . WriteLine ( " </ItemGroup>" ) ;
295+
296+ // Add generated files.
297+ project . WriteLine ( " <ItemGroup>" ) ;
298+ foreach ( var generatedFile in getGeneratedFiles ( ) )
299+ {
300+ string filePath = generatedFile . FilePath ;
301+ if ( ! File . Exists ( filePath ) )
295302 {
296- Console . WriteLine ( $ "Could not find reference '{ path } '") ;
297- continue ;
303+ Directory . CreateDirectory ( Path . GetDirectoryName ( filePath ) ) ;
304+ var stream = generatedFile . Stream ;
305+ stream . Position = 0 ;
306+ using var fileStream = File . OpenWrite ( filePath ) ;
307+ stream . CopyTo ( fileStream ) ;
298308 }
299- string projToRepoPath = Path . GetRelativePath ( invocation . ProjectDirectory , repoRoot ) ;
300- string projToOutputPath = Path . Join ( projToRepoPath , ".." ) ;
301- string refPath = DedupeReference ( output , path ) ;
302- project . WriteLine ( $ " <ReferencePath Include=\" { Path . Join ( projToOutputPath , refPath ) } \" />") ;
309+ includeFile ( filePath ) ;
303310 }
304311 project . WriteLine ( " </ItemGroup>" ) ;
312+
305313 project . WriteLine ( "</Project>" ) ;
306314 if ( ! string . IsNullOrEmpty ( invocation . OutputAssemblyPath ) )
307315 {
@@ -311,12 +319,13 @@ static void Main(string[] args)
311319 File . Copy ( invocation . OutputAssemblyPath , outputFilePath , true ) ;
312320 }
313321
314- void includeFile ( string originalPath , out string projectRelativePath , out string link )
322+ string includeFile ( string originalPath , bool includeCompile = true )
315323 {
316324 string filePath = Path . GetFullPath ( originalPath ) ;
317325 string repoRelativePath = Path . GetRelativePath ( repoRoot , filePath ) ;
318326 string outputFile ;
319- link = null ;
327+ string link = null ;
328+ string projectRelativePath ;
320329 if ( repoRelativePath . StartsWith ( "..\\ " , StringComparison . Ordinal ) || repoRelativePath . StartsWith ( "../" , StringComparison . Ordinal ) || Path . IsPathRooted ( repoRelativePath ) )
321330 {
322331 string externalPath = Path . Join ( "_external" , idx ++ . ToString ( ) , Path . GetFileName ( filePath ) ) ;
@@ -338,6 +347,44 @@ void includeFile(string originalPath, out string projectRelativePath, out string
338347 {
339348 File . Copy ( filePath , outputFile ) ;
340349 }
350+
351+ if ( includeCompile )
352+ {
353+ project . WriteLine ( $ " <Compile Include=\" { projectRelativePath } \" { ( link != null ? $ " Link=\" { link } \" " : "" ) } />") ;
354+ }
355+
356+ return projectRelativePath ;
357+ }
358+
359+ void includeReference ( string kind , string path )
360+ {
361+ if ( ! File . Exists ( path ) )
362+ {
363+ Console . WriteLine ( $ "Could not find { kind } '{ path } '") ;
364+ return ;
365+ }
366+
367+ string projToRepoPath = Path . GetRelativePath ( invocation . ProjectDirectory , repoRoot ) ;
368+ string projToOutputPath = Path . Join ( projToRepoPath , ".." ) ;
369+ string refPath = DedupeReference ( output , path ) ;
370+ project . WriteLine ( $ " <{ kind } Include=\" { Path . Join ( projToOutputPath , refPath ) } \" />") ;
371+ }
372+
373+ IEnumerable < ( string FilePath , MemoryStream Stream ) > getGeneratedFiles ( )
374+ {
375+ try
376+ {
377+ return Basic . CompilerLog . Util . RoslynUtil . ReadGeneratedFilesFromPdb (
378+ isCSharp : isCSharp ,
379+ diagnosticName : invocation . ProjectFilePath ,
380+ invocation . Parsed ) ;
381+ }
382+ catch ( Exception ex )
383+ {
384+ // We don't want to fail official builds during stage 1, so just log a warning.
385+ Console . WriteLine ( $ "##vso[task.logissue type=warning;]Error processing generated files for '{ invocation . ProjectFilePath } ': { ex } ") ;
386+ return [ ] ;
387+ }
341388 }
342389 }
343390
@@ -386,7 +433,7 @@ private static string GetProjectGuid()
386433 return Guid . NewGuid ( ) . ToString ( "B" ) ;
387434 }
388435
389- private static string CSharpProjectTypeGuid = "{9A19103F-16F7-4668-BE54-9A1E7A4F7556}" ;
390- private static string VBProjectTypeGuid = "{F184B08F-C81C-45F6-A57F-5ABD9991F28F}" ;
436+ private static readonly string CSharpProjectTypeGuid = "{9A19103F-16F7-4668-BE54-9A1E7A4F7556}" ;
437+ private static readonly string VBProjectTypeGuid = "{F184B08F-C81C-45F6-A57F-5ABD9991F28F}" ;
391438 }
392439}
0 commit comments