1111
1212namespace Semmle . BuildAnalyser
1313{
14- /// <summary>
15- /// The output of a build analysis.
16- /// </summary>
17- internal interface IBuildAnalysis
18- {
19- /// <summary>
20- /// Full filepaths of external references.
21- /// </summary>
22- IEnumerable < string > ReferenceFiles { get ; }
23-
24- /// <summary>
25- /// Full filepaths of C# source files from project files.
26- /// </summary>
27- IEnumerable < string > ProjectSourceFiles { get ; }
28-
29- /// <summary>
30- /// Full filepaths of C# source files in the filesystem.
31- /// </summary>
32- IEnumerable < string > AllSourceFiles { get ; }
33-
34- /// <summary>
35- /// The assembly IDs which could not be resolved.
36- /// </summary>
37- IEnumerable < string > UnresolvedReferences { get ; }
38-
39- /// <summary>
40- /// List of source files referenced by projects but
41- /// which were not found in the filesystem.
42- /// </summary>
43- IEnumerable < string > MissingSourceFiles { get ; }
44- }
45-
4614 /// <summary>
4715 /// Main implementation of the build analysis.
4816 /// </summary>
49- internal sealed class BuildAnalysis : IBuildAnalysis , IDisposable
17+ internal sealed class BuildAnalysis : IDisposable
5018 {
5119 private readonly AssemblyCache assemblyCache ;
52- private readonly IProgressMonitor progressMonitor ;
20+ private readonly ProgressMonitor progressMonitor ;
5321 private readonly IDictionary < string , bool > usedReferences = new ConcurrentDictionary < string , bool > ( ) ;
5422 private readonly IDictionary < string , bool > sources = new ConcurrentDictionary < string , bool > ( ) ;
5523 private readonly IDictionary < string , string > unresolvedReferences = new ConcurrentDictionary < string , string > ( ) ;
56- private int failedProjects , succeededProjects ;
24+ private int failedProjects ;
25+ private int succeededProjects ;
5726 private readonly string [ ] allSources ;
5827 private int conflictedReferences = 0 ;
28+ private readonly Options options ;
29+ private readonly DirectoryInfo sourceDir ;
5930
6031 /// <summary>
6132 /// Performs a C# build analysis.
6233 /// </summary>
6334 /// <param name="options">Analysis options from the command line.</param>
64- /// <param name="progress ">Display of analysis progress.</param>
65- public BuildAnalysis ( Options options , IProgressMonitor progress )
35+ /// <param name="progressMonitor ">Display of analysis progress.</param>
36+ public BuildAnalysis ( Options options , ProgressMonitor progressMonitor )
6637 {
6738 var startTime = DateTime . Now ;
6839
69- progressMonitor = progress ;
70- var sourceDir = new DirectoryInfo ( options . SrcDir ) ;
40+ this . options = options ;
41+ this . progressMonitor = progressMonitor ;
42+ this . sourceDir = new DirectoryInfo ( options . SrcDir ) ;
7143
72- progressMonitor . FindingFiles ( options . SrcDir ) ;
44+ this . progressMonitor . FindingFiles ( options . SrcDir ) ;
7345
74- allSources = sourceDir . GetFiles ( "*.cs" , SearchOption . AllDirectories )
75- . Select ( d => d . FullName )
76- . Where ( d => ! options . ExcludesFile ( d ) )
77- . ToArray ( ) ;
46+ this . allSources = GetFiles ( "*.cs" ) . ToArray ( ) ;
47+
48+ var solutions = options . SolutionFile is not null
49+ ? new [ ] { options . SolutionFile }
50+ : GetFiles ( "*.sln" ) ;
7851
7952 var dllDirNames = options . DllDirs . Select ( Path . GetFullPath ) . ToList ( ) ;
53+
54+ // Find DLLs in the .Net Framework
55+ if ( options . ScanNetFrameworkDlls )
56+ {
57+ var runtimeLocation = Runtime . GetRuntime ( options . UseSelfContainedDotnet ) ;
58+ progressMonitor . Log ( Util . Logging . Severity . Debug , $ "Runtime location selected: { runtimeLocation } ") ;
59+ dllDirNames . Add ( runtimeLocation ) ;
60+ }
61+
62+ if ( options . UseMscorlib )
63+ {
64+ UseReference ( typeof ( object ) . Assembly . Location ) ;
65+ }
66+
8067 packageDirectory = new TemporaryDirectory ( ComputeTempDirectory ( sourceDir . FullName ) ) ;
8168
8269 if ( options . UseNuGet )
8370 {
71+ dllDirNames . Add ( packageDirectory . DirInfo . FullName ) ;
8472 try
8573 {
86- var nuget = new NugetPackages ( sourceDir . FullName , packageDirectory ) ;
87- nuget . InstallPackages ( progressMonitor ) ;
74+ var nuget = new NugetPackages ( sourceDir . FullName , packageDirectory , progressMonitor ) ;
75+ nuget . InstallPackages ( ) ;
8876 }
8977 catch ( FileNotFoundException )
9078 {
9179 progressMonitor . MissingNuGet ( ) ;
9280 }
93- }
94-
95- // Find DLLs in the .Net Framework
96- if ( options . ScanNetFrameworkDlls )
97- {
98- var runtimeLocation = Runtime . GetRuntime ( options . UseSelfContainedDotnet ) ;
99- progressMonitor . Log ( Util . Logging . Severity . Debug , $ "Runtime location selected: { runtimeLocation } ") ;
100- dllDirNames . Add ( runtimeLocation ) ;
101- }
102-
103- // TODO: remove the below when the required SDK is installed
104- using ( new FileRenamer ( sourceDir . GetFiles ( "global.json" , SearchOption . AllDirectories ) ) )
105- {
106- var solutions = options . SolutionFile is not null ?
107- new [ ] { options . SolutionFile } :
108- sourceDir . GetFiles ( "*.sln" , SearchOption . AllDirectories ) . Select ( d => d . FullName ) ;
10981
110- if ( options . UseNuGet )
82+ // TODO: remove the below when the required SDK is installed
83+ using ( new FileRenamer ( sourceDir . GetFiles ( "global.json" , SearchOption . AllDirectories ) ) )
11184 {
11285 RestoreSolutions ( solutions ) ;
11386 }
114- dllDirNames . Add ( packageDirectory . DirInfo . FullName ) ;
115- assemblyCache = new BuildAnalyser . AssemblyCache ( dllDirNames , progress ) ;
116- AnalyseSolutions ( solutions ) ;
117-
118- foreach ( var filename in assemblyCache . AllAssemblies . Select ( a => a . Filename ) )
119- UseReference ( filename ) ;
12087 }
12188
122- if ( options . UseMscorlib )
89+ assemblyCache = new AssemblyCache ( dllDirNames , progressMonitor ) ;
90+ AnalyseSolutions ( solutions ) ;
91+
92+ foreach ( var filename in assemblyCache . AllAssemblies . Select ( a => a . Filename ) )
12393 {
124- UseReference ( typeof ( object ) . Assembly . Location ) ;
94+ UseReference ( filename ) ;
12595 }
12696
12797 ResolveConflicts ( ) ;
@@ -149,6 +119,13 @@ public BuildAnalysis(Options options, IProgressMonitor progress)
149119 DateTime . Now - startTime ) ;
150120 }
151121
122+ private IEnumerable < string > GetFiles ( string pattern )
123+ {
124+ return sourceDir . GetFiles ( pattern , SearchOption . AllDirectories )
125+ . Select ( d => d . FullName )
126+ . Where ( d => ! options . ExcludesFile ( d ) ) ;
127+ }
128+
152129 /// <summary>
153130 /// Computes a unique temp directory for the packages associated
154131 /// with this source tree. Use a SHA1 of the directory name.
@@ -158,9 +135,7 @@ public BuildAnalysis(Options options, IProgressMonitor progress)
158135 private static string ComputeTempDirectory ( string srcDir )
159136 {
160137 var bytes = Encoding . Unicode . GetBytes ( srcDir ) ;
161-
162- using var sha1 = SHA1 . Create ( ) ;
163- var sha = sha1 . ComputeHash ( bytes ) ;
138+ var sha = SHA1 . HashData ( bytes ) ;
164139 var sb = new StringBuilder ( ) ;
165140 foreach ( var b in sha . Take ( 8 ) )
166141 sb . AppendFormat ( "{0:x2}" , b ) ;
@@ -195,12 +170,15 @@ private void ResolveConflicts()
195170
196171 // Pick the highest version for each assembly name
197172 foreach ( var r in sortedReferences )
173+ {
198174 finalAssemblyList [ r . Name ] = r ;
199-
175+ }
200176 // Update the used references list
201177 usedReferences . Clear ( ) ;
202178 foreach ( var r in finalAssemblyList . Select ( r => r . Value . Filename ) )
179+ {
203180 UseReference ( r ) ;
181+ }
204182
205183 // Report the results
206184 foreach ( var r in sortedReferences )
@@ -278,7 +256,9 @@ private void UnresolvedReference(string id, string projectFile)
278256 private void AnalyseProjectFiles ( IEnumerable < FileInfo > projectFiles )
279257 {
280258 foreach ( var proj in projectFiles )
259+ {
281260 AnalyseProject ( proj ) ;
261+ }
282262 }
283263
284264 private void AnalyseProject ( FileInfo project )
@@ -348,12 +328,12 @@ private void Restore(string projectOrSolution)
348328 }
349329 }
350330
351- public void RestoreSolutions ( IEnumerable < string > solutions )
331+ private void RestoreSolutions ( IEnumerable < string > solutions )
352332 {
353333 Parallel . ForEach ( solutions , new ParallelOptions { MaxDegreeOfParallelism = 4 } , Restore ) ;
354334 }
355335
356- public void AnalyseSolutions ( IEnumerable < string > solutions )
336+ private void AnalyseSolutions ( IEnumerable < string > solutions )
357337 {
358338 Parallel . ForEach ( solutions , new ParallelOptions { MaxDegreeOfParallelism = 4 } , solutionFile =>
359339 {
0 commit comments