Skip to content

Commit d2b0c87

Browse files
committed
Code quality improvements
1 parent 95ddc01 commit d2b0c87

File tree

4 files changed

+76
-117
lines changed

4 files changed

+76
-117
lines changed

csharp/extractor/Semmle.Extraction.CSharp.Standalone/AssemblyCache.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,12 @@ internal class AssemblyCache
1616
/// Locate all reference files and index them.
1717
/// </summary>
1818
/// <param name="dirs">Directories to search.</param>
19-
/// <param name="progress">Callback for progress.</param>
20-
public AssemblyCache(IEnumerable<string> dirs, IProgressMonitor progress)
19+
/// <param name="progressMonitor">Callback for progress.</param>
20+
public AssemblyCache(IEnumerable<string> dirs, ProgressMonitor progressMonitor)
2121
{
2222
foreach (var dir in dirs)
2323
{
24-
progress.FindingFiles(dir);
24+
progressMonitor.FindingFiles(dir);
2525
AddReferenceDirectory(dir);
2626
}
2727
IndexReferences();

csharp/extractor/Semmle.Extraction.CSharp.Standalone/BuildAnalysis.cs

Lines changed: 57 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -11,117 +11,87 @@
1111

1212
namespace 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
{

csharp/extractor/Semmle.Extraction.CSharp.Standalone/NugetPackages.cs

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -17,26 +17,24 @@ internal class NugetPackages
1717
/// <summary>
1818
/// Create the package manager for a specified source tree.
1919
/// </summary>
20-
/// <param name="sourceDir">The source directory.</param>
21-
public NugetPackages(string sourceDir, TemporaryDirectory packageDirectory)
20+
public NugetPackages(string sourceDir, TemporaryDirectory packageDirectory, ProgressMonitor progressMonitor)
2221
{
2322
SourceDirectory = sourceDir;
2423
PackageDirectory = packageDirectory;
24+
this.progressMonitor = progressMonitor;
2525

2626
// Expect nuget.exe to be in a `nuget` directory under the directory containing this exe.
2727
var currentAssembly = System.Reflection.Assembly.GetExecutingAssembly().Location;
28-
var directory = Path.GetDirectoryName(currentAssembly);
29-
if (directory is null)
30-
throw new FileNotFoundException($"Directory path '{currentAssembly}' of current assembly is null");
31-
28+
var directory = Path.GetDirectoryName(currentAssembly)
29+
?? throw new FileNotFoundException($"Directory path '{currentAssembly}' of current assembly is null");
3230
nugetExe = Path.Combine(directory, "nuget", "nuget.exe");
3331

3432
if (!File.Exists(nugetExe))
3533
throw new FileNotFoundException(string.Format("NuGet could not be found at {0}", nugetExe));
3634

37-
packages = new DirectoryInfo(SourceDirectory).
38-
EnumerateFiles("packages.config", SearchOption.AllDirectories).
39-
ToArray();
35+
packages = new DirectoryInfo(SourceDirectory)
36+
.EnumerateFiles("packages.config", SearchOption.AllDirectories)
37+
.ToArray();
4038
}
4139

4240
// List of package files to download.
@@ -51,11 +49,11 @@ public NugetPackages(string sourceDir, TemporaryDirectory packageDirectory)
5149
/// Download the packages to the temp folder.
5250
/// </summary>
5351
/// <param name="pm">The progress monitor used for reporting errors etc.</param>
54-
public void InstallPackages(IProgressMonitor pm)
52+
public void InstallPackages()
5553
{
5654
foreach (var package in packages)
5755
{
58-
RestoreNugetPackage(package.FullName, pm);
56+
RestoreNugetPackage(package.FullName);
5957
}
6058
}
6159

@@ -80,9 +78,9 @@ public string SourceDirectory
8078
/// </summary>
8179
/// <param name="package">The package file.</param>
8280
/// <param name="pm">Where to log progress/errors.</param>
83-
private void RestoreNugetPackage(string package, IProgressMonitor pm)
81+
private void RestoreNugetPackage(string package)
8482
{
85-
pm.NugetInstall(package);
83+
progressMonitor.NugetInstall(package);
8684

8785
/* Use nuget.exe to install a package.
8886
* Note that there is a clutch of NuGet assemblies which could be used to
@@ -115,7 +113,7 @@ private void RestoreNugetPackage(string package, IProgressMonitor pm)
115113

116114
if (p is null)
117115
{
118-
pm.FailedNugetCommand(pi.FileName, pi.Arguments, "Couldn't start process.");
116+
progressMonitor.FailedNugetCommand(pi.FileName, pi.Arguments, "Couldn't start process.");
119117
return;
120118
}
121119

@@ -125,16 +123,17 @@ private void RestoreNugetPackage(string package, IProgressMonitor pm)
125123
p.WaitForExit();
126124
if (p.ExitCode != 0)
127125
{
128-
pm.FailedNugetCommand(pi.FileName, pi.Arguments, output + error);
126+
progressMonitor.FailedNugetCommand(pi.FileName, pi.Arguments, output + error);
129127
}
130128
}
131129
catch (Exception ex)
132130
when (ex is System.ComponentModel.Win32Exception || ex is FileNotFoundException)
133131
{
134-
pm.FailedNugetCommand(pi.FileName, pi.Arguments, ex.Message);
132+
progressMonitor.FailedNugetCommand(pi.FileName, pi.Arguments, ex.Message);
135133
}
136134
}
137135

138136
private readonly string nugetExe;
137+
private readonly ProgressMonitor progressMonitor;
139138
}
140139
}

csharp/extractor/Semmle.Extraction.CSharp.Standalone/ProgressMonitor.cs

Lines changed: 1 addition & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -3,27 +3,7 @@
33

44
namespace Semmle.BuildAnalyser
55
{
6-
/// <summary>
7-
/// Callback for various events that may happen during the build analysis.
8-
/// </summary>
9-
internal interface IProgressMonitor
10-
{
11-
void FindingFiles(string dir);
12-
void UnresolvedReference(string id, string project);
13-
void AnalysingSolution(string filename);
14-
void FailedProjectFile(string filename, string reason);
15-
void FailedNugetCommand(string exe, string args, string message);
16-
void NugetInstall(string package);
17-
void ResolvedReference(string filename);
18-
void Summary(int existingSources, int usedSources, int missingSources, int references, int unresolvedReferences, int resolvedConflicts, int totalProjects, int failedProjects, TimeSpan analysisTime);
19-
void Log(Severity severity, string message);
20-
void ResolvedConflict(string asm1, string asm2);
21-
void MissingProject(string projectFile);
22-
void CommandFailed(string exe, string arguments, int exitCode);
23-
void MissingNuGet();
24-
}
25-
26-
internal class ProgressMonitor : IProgressMonitor
6+
internal class ProgressMonitor
277
{
288
private readonly ILogger logger;
299

0 commit comments

Comments
 (0)