8
8
using System . Collections . Concurrent ;
9
9
using System . Text ;
10
10
using System . Security . Cryptography ;
11
- using System . Text . RegularExpressions ;
12
11
13
12
namespace Semmle . BuildAnalyser
14
13
{
15
14
/// <summary>
16
15
/// Main implementation of the build analysis.
17
16
/// </summary>
18
- internal sealed partial class BuildAnalysis : IDisposable
17
+ internal sealed class BuildAnalysis : IDisposable
19
18
{
20
19
private readonly AssemblyCache assemblyCache ;
21
20
private readonly ProgressMonitor progressMonitor ;
@@ -29,6 +28,9 @@ internal sealed partial class BuildAnalysis : IDisposable
29
28
private readonly Options options ;
30
29
private readonly DirectoryInfo sourceDir ;
31
30
private readonly DotNet dotnet ;
31
+ private readonly FileContent fileContent ;
32
+ private readonly TemporaryDirectory packageDirectory ;
33
+
32
34
33
35
/// <summary>
34
36
/// Performs a C# build analysis.
@@ -55,6 +57,9 @@ public BuildAnalysis(Options options, ProgressMonitor progressMonitor)
55
57
56
58
this . progressMonitor . FindingFiles ( options . SrcDir ) ;
57
59
60
+ packageDirectory = new TemporaryDirectory ( ComputeTempDirectory ( sourceDir . FullName ) ) ;
61
+
62
+ this . fileContent = new FileContent ( packageDirectory , progressMonitor , ( ) => GetFiles ( "*.*" ) ) ;
58
63
this . allSources = GetFiles ( "*.cs" ) . ToArray ( ) ;
59
64
var allProjects = GetFiles ( "*.csproj" ) ;
60
65
var solutions = options . SolutionFile is not null
@@ -63,21 +68,26 @@ public BuildAnalysis(Options options, ProgressMonitor progressMonitor)
63
68
64
69
var dllDirNames = options . DllDirs . Select ( Path . GetFullPath ) . ToList ( ) ;
65
70
66
- // Find DLLs in the .Net Framework
71
+ // Find DLLs in the .Net / Asp.Net Framework
67
72
if ( options . ScanNetFrameworkDlls )
68
73
{
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 } ") ;
71
77
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
+ }
72
84
}
73
85
74
86
if ( options . UseMscorlib )
75
87
{
76
88
UseReference ( typeof ( object ) . Assembly . Location ) ;
77
89
}
78
90
79
- packageDirectory = new TemporaryDirectory ( ComputeTempDirectory ( sourceDir . FullName ) ) ;
80
-
81
91
if ( options . UseNuGet )
82
92
{
83
93
dllDirNames . Add ( packageDirectory . DirInfo . FullName ) ;
@@ -187,6 +197,7 @@ private void ResolveConflicts()
187
197
{
188
198
finalAssemblyList [ r . Name ] = r ;
189
199
}
200
+
190
201
// Update the used references list
191
202
usedReferences . Clear ( ) ;
192
203
foreach ( var r in finalAssemblyList . Select ( r => r . Value . Filename ) )
@@ -210,24 +221,18 @@ private void ResolveConflicts()
210
221
/// Store that a particular reference file is used.
211
222
/// </summary>
212
223
/// <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 ;
217
225
218
226
/// <summary>
219
227
/// Store that a particular source file is used (by a project file).
220
228
/// </summary>
221
229
/// <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 ;
226
231
227
232
/// <summary>
228
233
/// The list of resolved reference files.
229
234
/// </summary>
230
- public IEnumerable < string > ReferenceFiles => this . usedReferences . Keys ;
235
+ public IEnumerable < string > ReferenceFiles => usedReferences . Keys ;
231
236
232
237
/// <summary>
233
238
/// The list of source files used in projects.
@@ -242,7 +247,7 @@ private void UseSource(FileInfo sourceFile)
242
247
/// <summary>
243
248
/// List of assembly IDs which couldn't be resolved.
244
249
/// </summary>
245
- public IEnumerable < string > UnresolvedReferences => this . unresolvedReferences . Select ( r => r . Key ) ;
250
+ public IEnumerable < string > UnresolvedReferences => unresolvedReferences . Select ( r => r . Key ) ;
246
251
247
252
/// <summary>
248
253
/// List of source files which were mentioned in project files but
@@ -256,12 +261,7 @@ private void UseSource(FileInfo sourceFile)
256
261
/// </summary>
257
262
/// <param name="id">The assembly ID.</param>
258
263
/// <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 ;
265
265
266
266
/// <summary>
267
267
/// Reads all the source files and references from the given list of projects.
@@ -318,10 +318,8 @@ private void AnalyseProject(FileInfo project)
318
318
319
319
}
320
320
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 ) ;
325
323
326
324
private void Restore ( IEnumerable < string > targets , string ? pathToNugetConfig = null )
327
325
{
@@ -331,11 +329,9 @@ private void Restore(IEnumerable<string> targets, string? pathToNugetConfig = nu
331
329
}
332
330
}
333
331
332
+
334
333
private void DownloadMissingPackages ( IEnumerable < string > restoreTargets )
335
334
{
336
- var alreadyDownloadedPackages = Directory . GetDirectories ( packageDirectory . DirInfo . FullName ) . Select ( d => Path . GetFileName ( d ) . ToLowerInvariant ( ) ) . ToHashSet ( ) ;
337
- var notYetDownloadedPackages = new HashSet < string > ( ) ;
338
-
339
335
var nugetConfigs = GetFiles ( "nuget.config" , recurseSubdirectories : true ) . ToArray ( ) ;
340
336
string ? nugetConfig = null ;
341
337
if ( nugetConfigs . Length > 1 )
@@ -352,46 +348,7 @@ private void DownloadMissingPackages(IEnumerable<string> restoreTargets)
352
348
nugetConfig = nugetConfigs . FirstOrDefault ( ) ;
353
349
}
354
350
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 )
395
352
{
396
353
progressMonitor . NugetInstall ( package ) ;
397
354
using var tempDir = new TemporaryDirectory ( ComputeTempDirectory ( package ) ) ;
@@ -434,12 +391,6 @@ private void AnalyseSolutions(IEnumerable<string> solutions)
434
391
} ) ;
435
392
}
436
393
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 ( ) ;
444
395
}
445
396
}
0 commit comments