88using System . Collections . Concurrent ;
99using System . Text ;
1010using System . Security . Cryptography ;
11- using System . Text . RegularExpressions ;
1211
1312namespace Semmle . BuildAnalyser
1413{
1514 /// <summary>
1615 /// Main implementation of the build analysis.
1716 /// </summary>
18- internal sealed partial class BuildAnalysis : IDisposable
17+ internal sealed class BuildAnalysis : IDisposable
1918 {
2019 private readonly AssemblyCache assemblyCache ;
2120 private readonly ProgressMonitor progressMonitor ;
@@ -29,6 +28,9 @@ internal sealed partial class BuildAnalysis : IDisposable
2928 private readonly Options options ;
3029 private readonly DirectoryInfo sourceDir ;
3130 private readonly DotNet dotnet ;
31+ private readonly FileContent fileContent ;
32+ private readonly TemporaryDirectory packageDirectory ;
33+
3234
3335 /// <summary>
3436 /// Performs a C# build analysis.
@@ -55,6 +57,9 @@ public BuildAnalysis(Options options, ProgressMonitor progressMonitor)
5557
5658 this . progressMonitor . FindingFiles ( options . SrcDir ) ;
5759
60+ packageDirectory = new TemporaryDirectory ( ComputeTempDirectory ( sourceDir . FullName ) ) ;
61+
62+ this . fileContent = new FileContent ( packageDirectory , progressMonitor , ( ) => GetFiles ( "*.*" ) ) ;
5863 this . allSources = GetFiles ( "*.cs" ) . ToArray ( ) ;
5964 var allProjects = GetFiles ( "*.csproj" ) ;
6065 var solutions = options . SolutionFile is not null
@@ -63,21 +68,26 @@ public BuildAnalysis(Options options, ProgressMonitor progressMonitor)
6368
6469 var dllDirNames = options . DllDirs . Select ( Path . GetFullPath ) . ToList ( ) ;
6570
66- // Find DLLs in the .Net Framework
71+ // Find DLLs in the .Net / Asp.Net Framework
6772 if ( options . ScanNetFrameworkDlls )
6873 {
69- var runtimeLocation = new Runtime ( dotnet ) . GetRuntime ( options . UseSelfContainedDotnet ) ;
70- progressMonitor . Log ( Util . Logging . Severity . Info , $ "Runtime location selected: { runtimeLocation } ") ;
74+ var runtime = new Runtime ( dotnet ) ;
75+ var runtimeLocation = runtime . GetRuntime ( options . UseSelfContainedDotnet ) ;
76+ progressMonitor . LogInfo ( $ ".NET runtime location selected: { runtimeLocation } ") ;
7177 dllDirNames . Add ( runtimeLocation ) ;
78+
79+ if ( fileContent . UseAspNetDlls && runtime . GetAspRuntime ( ) is string aspRuntime )
80+ {
81+ progressMonitor . LogInfo ( $ "ASP.NET runtime location selected: { aspRuntime } ") ;
82+ dllDirNames . Add ( aspRuntime ) ;
83+ }
7284 }
7385
7486 if ( options . UseMscorlib )
7587 {
7688 UseReference ( typeof ( object ) . Assembly . Location ) ;
7789 }
7890
79- packageDirectory = new TemporaryDirectory ( ComputeTempDirectory ( sourceDir . FullName ) ) ;
80-
8191 if ( options . UseNuGet )
8292 {
8393 dllDirNames . Add ( packageDirectory . DirInfo . FullName ) ;
@@ -187,6 +197,7 @@ private void ResolveConflicts()
187197 {
188198 finalAssemblyList [ r . Name ] = r ;
189199 }
200+
190201 // Update the used references list
191202 usedReferences . Clear ( ) ;
192203 foreach ( var r in finalAssemblyList . Select ( r => r . Value . Filename ) )
@@ -210,24 +221,18 @@ private void ResolveConflicts()
210221 /// Store that a particular reference file is used.
211222 /// </summary>
212223 /// <param name="reference">The filename of the reference.</param>
213- private void UseReference ( string reference )
214- {
215- usedReferences [ reference ] = true ;
216- }
224+ private void UseReference ( string reference ) => usedReferences [ reference ] = true ;
217225
218226 /// <summary>
219227 /// Store that a particular source file is used (by a project file).
220228 /// </summary>
221229 /// <param name="sourceFile">The source file.</param>
222- private void UseSource ( FileInfo sourceFile )
223- {
224- sources [ sourceFile . FullName ] = sourceFile . Exists ;
225- }
230+ private void UseSource ( FileInfo sourceFile ) => sources [ sourceFile . FullName ] = sourceFile . Exists ;
226231
227232 /// <summary>
228233 /// The list of resolved reference files.
229234 /// </summary>
230- public IEnumerable < string > ReferenceFiles => this . usedReferences . Keys ;
235+ public IEnumerable < string > ReferenceFiles => usedReferences . Keys ;
231236
232237 /// <summary>
233238 /// The list of source files used in projects.
@@ -242,7 +247,7 @@ private void UseSource(FileInfo sourceFile)
242247 /// <summary>
243248 /// List of assembly IDs which couldn't be resolved.
244249 /// </summary>
245- public IEnumerable < string > UnresolvedReferences => this . unresolvedReferences . Select ( r => r . Key ) ;
250+ public IEnumerable < string > UnresolvedReferences => unresolvedReferences . Select ( r => r . Key ) ;
246251
247252 /// <summary>
248253 /// List of source files which were mentioned in project files but
@@ -256,12 +261,7 @@ private void UseSource(FileInfo sourceFile)
256261 /// </summary>
257262 /// <param name="id">The assembly ID.</param>
258263 /// <param name="projectFile">The project file making the reference.</param>
259- private void UnresolvedReference ( string id , string projectFile )
260- {
261- unresolvedReferences [ id ] = projectFile ;
262- }
263-
264- private readonly TemporaryDirectory packageDirectory ;
264+ private void UnresolvedReference ( string id , string projectFile ) => unresolvedReferences [ id ] = projectFile ;
265265
266266 /// <summary>
267267 /// Reads all the source files and references from the given list of projects.
@@ -318,10 +318,8 @@ private void AnalyseProject(FileInfo project)
318318
319319 }
320320
321- private bool Restore ( string target , string ? pathToNugetConfig = null )
322- {
323- return dotnet . RestoreToDirectory ( target , packageDirectory . DirInfo . FullName , pathToNugetConfig ) ;
324- }
321+ private bool Restore ( string target , string ? pathToNugetConfig = null ) =>
322+ dotnet . RestoreToDirectory ( target , packageDirectory . DirInfo . FullName , pathToNugetConfig ) ;
325323
326324 private void Restore ( IEnumerable < string > targets , string ? pathToNugetConfig = null )
327325 {
@@ -331,11 +329,9 @@ private void Restore(IEnumerable<string> targets, string? pathToNugetConfig = nu
331329 }
332330 }
333331
332+
334333 private void DownloadMissingPackages ( IEnumerable < string > restoreTargets )
335334 {
336- var alreadyDownloadedPackages = Directory . GetDirectories ( packageDirectory . DirInfo . FullName ) . Select ( d => Path . GetFileName ( d ) . ToLowerInvariant ( ) ) . ToHashSet ( ) ;
337- var notYetDownloadedPackages = new HashSet < string > ( ) ;
338-
339335 var nugetConfigs = GetFiles ( "nuget.config" , recurseSubdirectories : true ) . ToArray ( ) ;
340336 string ? nugetConfig = null ;
341337 if ( nugetConfigs . Length > 1 )
@@ -352,46 +348,7 @@ private void DownloadMissingPackages(IEnumerable<string> restoreTargets)
352348 nugetConfig = nugetConfigs . FirstOrDefault ( ) ;
353349 }
354350
355- var allFiles = GetFiles ( "*.*" ) ;
356- foreach ( var file in allFiles )
357- {
358- try
359- {
360- using var sr = new StreamReader ( file ) ;
361- ReadOnlySpan < char > line ;
362- while ( ( line = sr . ReadLine ( ) ) != null )
363- {
364- foreach ( var valueMatch in PackageReference ( ) . EnumerateMatches ( line ) )
365- {
366- // We can't get the group from the ValueMatch, so doing it manually:
367- var match = line . Slice ( valueMatch . Index , valueMatch . Length ) ;
368- var includeIndex = match . IndexOf ( "Include" , StringComparison . InvariantCultureIgnoreCase ) ;
369- if ( includeIndex == - 1 )
370- {
371- continue ;
372- }
373-
374- match = match . Slice ( includeIndex + "Include" . Length + 1 ) ;
375-
376- var quoteIndex1 = match . IndexOf ( "\" " ) ;
377- var quoteIndex2 = match . Slice ( quoteIndex1 + 1 ) . IndexOf ( "\" " ) ;
378-
379- var packageName = match . Slice ( quoteIndex1 + 1 , quoteIndex2 ) . ToString ( ) . ToLowerInvariant ( ) ;
380- if ( ! alreadyDownloadedPackages . Contains ( packageName ) )
381- {
382- notYetDownloadedPackages . Add ( packageName ) ;
383- }
384- }
385- }
386- }
387- catch ( Exception ex )
388- {
389- progressMonitor . FailedToReadFile ( file , ex ) ;
390- continue ;
391- }
392- }
393-
394- foreach ( var package in notYetDownloadedPackages )
351+ foreach ( var package in fileContent . NotYetDownloadedPackages )
395352 {
396353 progressMonitor . NugetInstall ( package ) ;
397354 using var tempDir = new TemporaryDirectory ( ComputeTempDirectory ( package ) ) ;
@@ -434,12 +391,6 @@ private void AnalyseSolutions(IEnumerable<string> solutions)
434391 } ) ;
435392 }
436393
437- public void Dispose ( )
438- {
439- packageDirectory ? . Dispose ( ) ;
440- }
441-
442- [ GeneratedRegex ( "<PackageReference .*Include=\" (.*?)\" .*/>" , RegexOptions . IgnoreCase | RegexOptions . Compiled | RegexOptions . Singleline ) ]
443- private static partial Regex PackageReference ( ) ;
394+ public void Dispose ( ) => packageDirectory ? . Dispose ( ) ;
444395 }
445396}
0 commit comments