11
11
12
12
namespace Semmle . BuildAnalyser
13
13
{
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
-
46
14
/// <summary>
47
15
/// Main implementation of the build analysis.
48
16
/// </summary>
49
- internal sealed class BuildAnalysis : IBuildAnalysis , IDisposable
17
+ internal sealed class BuildAnalysis : IDisposable
50
18
{
51
19
private readonly AssemblyCache assemblyCache ;
52
- private readonly IProgressMonitor progressMonitor ;
20
+ private readonly ProgressMonitor progressMonitor ;
53
21
private readonly IDictionary < string , bool > usedReferences = new ConcurrentDictionary < string , bool > ( ) ;
54
22
private readonly IDictionary < string , bool > sources = new ConcurrentDictionary < string , bool > ( ) ;
55
23
private readonly IDictionary < string , string > unresolvedReferences = new ConcurrentDictionary < string , string > ( ) ;
56
- private int failedProjects , succeededProjects ;
24
+ private int failedProjects ;
25
+ private int succeededProjects ;
57
26
private readonly string [ ] allSources ;
58
27
private int conflictedReferences = 0 ;
28
+ private readonly Options options ;
29
+ private readonly DirectoryInfo sourceDir ;
59
30
60
31
/// <summary>
61
32
/// Performs a C# build analysis.
62
33
/// </summary>
63
34
/// <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 )
66
37
{
67
38
var startTime = DateTime . Now ;
68
39
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 ) ;
71
43
72
- progressMonitor . FindingFiles ( options . SrcDir ) ;
44
+ this . progressMonitor . FindingFiles ( options . SrcDir ) ;
73
45
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" ) ;
78
51
79
52
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
+
80
67
packageDirectory = new TemporaryDirectory ( ComputeTempDirectory ( sourceDir . FullName ) ) ;
81
68
82
69
if ( options . UseNuGet )
83
70
{
71
+ dllDirNames . Add ( packageDirectory . DirInfo . FullName ) ;
84
72
try
85
73
{
86
- var nuget = new NugetPackages ( sourceDir . FullName , packageDirectory ) ;
87
- nuget . InstallPackages ( progressMonitor ) ;
74
+ var nuget = new NugetPackages ( sourceDir . FullName , packageDirectory , progressMonitor ) ;
75
+ nuget . InstallPackages ( ) ;
88
76
}
89
77
catch ( FileNotFoundException )
90
78
{
91
79
progressMonitor . MissingNuGet ( ) ;
92
80
}
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 ) ;
109
81
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 ) ) )
111
84
{
112
85
RestoreSolutions ( solutions ) ;
113
86
}
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 ) ;
120
87
}
121
88
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 ) )
123
93
{
124
- UseReference ( typeof ( object ) . Assembly . Location ) ;
94
+ UseReference ( filename ) ;
125
95
}
126
96
127
97
ResolveConflicts ( ) ;
@@ -149,6 +119,13 @@ public BuildAnalysis(Options options, IProgressMonitor progress)
149
119
DateTime . Now - startTime ) ;
150
120
}
151
121
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
+
152
129
/// <summary>
153
130
/// Computes a unique temp directory for the packages associated
154
131
/// with this source tree. Use a SHA1 of the directory name.
@@ -158,9 +135,7 @@ public BuildAnalysis(Options options, IProgressMonitor progress)
158
135
private static string ComputeTempDirectory ( string srcDir )
159
136
{
160
137
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 ) ;
164
139
var sb = new StringBuilder ( ) ;
165
140
foreach ( var b in sha . Take ( 8 ) )
166
141
sb . AppendFormat ( "{0:x2}" , b ) ;
@@ -195,12 +170,15 @@ private void ResolveConflicts()
195
170
196
171
// Pick the highest version for each assembly name
197
172
foreach ( var r in sortedReferences )
173
+ {
198
174
finalAssemblyList [ r . Name ] = r ;
199
-
175
+ }
200
176
// Update the used references list
201
177
usedReferences . Clear ( ) ;
202
178
foreach ( var r in finalAssemblyList . Select ( r => r . Value . Filename ) )
179
+ {
203
180
UseReference ( r ) ;
181
+ }
204
182
205
183
// Report the results
206
184
foreach ( var r in sortedReferences )
@@ -278,7 +256,9 @@ private void UnresolvedReference(string id, string projectFile)
278
256
private void AnalyseProjectFiles ( IEnumerable < FileInfo > projectFiles )
279
257
{
280
258
foreach ( var proj in projectFiles )
259
+ {
281
260
AnalyseProject ( proj ) ;
261
+ }
282
262
}
283
263
284
264
private void AnalyseProject ( FileInfo project )
@@ -348,12 +328,12 @@ private void Restore(string projectOrSolution)
348
328
}
349
329
}
350
330
351
- public void RestoreSolutions ( IEnumerable < string > solutions )
331
+ private void RestoreSolutions ( IEnumerable < string > solutions )
352
332
{
353
333
Parallel . ForEach ( solutions , new ParallelOptions { MaxDegreeOfParallelism = 4 } , Restore ) ;
354
334
}
355
335
356
- public void AnalyseSolutions ( IEnumerable < string > solutions )
336
+ private void AnalyseSolutions ( IEnumerable < string > solutions )
357
337
{
358
338
Parallel . ForEach ( solutions , new ParallelOptions { MaxDegreeOfParallelism = 4 } , solutionFile =>
359
339
{
0 commit comments