Skip to content

Commit 1f1d48f

Browse files
authored
Merge pull request github#14020 from tamasvajk/fix/dependency-fetching-1
C#: Fix lazy evaluation of not yet downloaded packages
2 parents cf53956 + c1f167c commit 1f1d48f

File tree

3 files changed

+26
-29
lines changed

3 files changed

+26
-29
lines changed

csharp/extractor/Semmle.Extraction.CSharp.DependencyFetching/DependencyManager.cs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ public DependencyManager(string srcDir, IDependencyOptions options, ILogger logg
6060

6161
packageDirectory = new TemporaryDirectory(ComputeTempDirectory(sourceDir.FullName));
6262

63-
this.fileContent = new FileContent(packageDirectory, progressMonitor, () => GetFiles("*.*"));
63+
this.fileContent = new FileContent(progressMonitor, () => GetFiles("*.*"));
6464
this.allSources = GetFiles("*.cs").ToList();
6565
var allProjects = GetFiles("*.csproj");
6666
var solutions = options.SolutionFile is not null
@@ -388,7 +388,11 @@ private void DownloadMissingPackages()
388388
nugetConfig = nugetConfigs.FirstOrDefault();
389389
}
390390

391-
foreach (var package in fileContent.NotYetDownloadedPackages)
391+
var alreadyDownloadedPackages = Directory.GetDirectories(packageDirectory.DirInfo.FullName)
392+
.Select(d => Path.GetFileName(d)
393+
.ToLowerInvariant());
394+
var notYetDownloadedPackages = fileContent.AllPackages.Except(alreadyDownloadedPackages);
395+
foreach (var package in notYetDownloadedPackages)
392396
{
393397
progressMonitor.NugetInstall(package);
394398
using var tempDir = new TemporaryDirectory(ComputeTempDirectory(package));

csharp/extractor/Semmle.Extraction.CSharp.DependencyFetching/FileContent.cs

Lines changed: 9 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -12,23 +12,22 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
1212
// This class is used to read a set of files and decide different properties about the
1313
// content (by reading the content of the files only once).
1414
// The implementation is lazy, so the properties are only calculated when
15-
// the first property is accessed.
15+
// the first property is accessed.
1616
// </summary>
1717
internal partial class FileContent
1818
{
1919
private readonly ProgressMonitor progressMonitor;
2020
private readonly IUnsafeFileReader unsafeFileReader;
2121
private readonly Func<IEnumerable<string>> getFiles;
22-
private readonly Func<HashSet<string>> getAlreadyDownloadedPackages;
23-
private readonly HashSet<string> notYetDownloadedPackages = new HashSet<string>();
22+
private readonly HashSet<string> allPackages = new HashSet<string>();
2423
private readonly Initializer initialize;
2524

26-
public HashSet<string> NotYetDownloadedPackages
25+
public HashSet<string> AllPackages
2726
{
2827
get
2928
{
3029
initialize.Run();
31-
return notYetDownloadedPackages;
30+
return allPackages;
3231
}
3332
}
3433

@@ -50,23 +49,18 @@ public bool UseAspNetDlls
5049
}
5150
}
5251

53-
internal FileContent(Func<HashSet<string>> getAlreadyDownloadedPackages,
54-
ProgressMonitor progressMonitor,
52+
internal FileContent(ProgressMonitor progressMonitor,
5553
Func<IEnumerable<string>> getFiles,
5654
IUnsafeFileReader unsafeFileReader)
5755
{
58-
this.getAlreadyDownloadedPackages = getAlreadyDownloadedPackages;
5956
this.progressMonitor = progressMonitor;
6057
this.getFiles = getFiles;
6158
this.unsafeFileReader = unsafeFileReader;
6259
this.initialize = new Initializer(DoInitialize);
6360
}
6461

6562

66-
public FileContent(TemporaryDirectory packageDirectory, ProgressMonitor progressMonitor, Func<IEnumerable<string>> getFiles) : this(() => Directory.GetDirectories(packageDirectory.DirInfo.FullName)
67-
.Select(d => Path.GetFileName(d)
68-
.ToLowerInvariant())
69-
.ToHashSet(), progressMonitor, getFiles, new UnsafeFileReader())
63+
public FileContent(ProgressMonitor progressMonitor, Func<IEnumerable<string>> getFiles) : this(progressMonitor, getFiles, new UnsafeFileReader())
7064
{ }
7165

7266
private static string GetGroup(ReadOnlySpan<char> input, ValueMatch valueMatch, string groupPrefix)
@@ -101,22 +95,21 @@ private static bool IsGroupMatch(ReadOnlySpan<char> line, Regex regex, string gr
10195

10296
private void DoInitialize()
10397
{
104-
var alreadyDownloadedPackages = getAlreadyDownloadedPackages();
10598
foreach (var file in getFiles())
10699
{
107100
try
108101
{
109102
foreach (ReadOnlySpan<char> line in unsafeFileReader.ReadLines(file))
110103
{
111104

112-
// Find the not yet downloaded packages.
105+
// Find all the packages.
113106
foreach (var valueMatch in PackageReference().EnumerateMatches(line))
114107
{
115108
// We can't get the group from the ValueMatch, so doing it manually:
116109
var packageName = GetGroup(line, valueMatch, "Include");
117-
if (!string.IsNullOrEmpty(packageName) && !alreadyDownloadedPackages.Contains(packageName))
110+
if (!string.IsNullOrEmpty(packageName))
118111
{
119-
notYetDownloadedPackages.Add(packageName);
112+
allPackages.Add(packageName);
120113
}
121114
}
122115

csharp/extractor/Semmle.Extraction.Tests/FileContent.cs

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using Xunit;
22
using System.Collections.Generic;
3+
using System.Linq;
34
using Semmle.Util.Logging;
45
using Semmle.Extraction.CSharp.DependencyFetching;
56

@@ -33,8 +34,7 @@ public IEnumerable<string> ReadLines(string file)
3334

3435
internal class TestFileContent : FileContent
3536
{
36-
public TestFileContent(List<string> lines) : base(() => new HashSet<string>(),
37-
new ProgressMonitor(new LoggerStub()),
37+
public TestFileContent(List<string> lines) : base(new ProgressMonitor(new LoggerStub()),
3838
() => new List<string>() { "test1.cs" },
3939
new UnsafeFileReaderStub(lines))
4040
{ }
@@ -57,15 +57,15 @@ public void TestFileContent1()
5757
var fileContent = new TestFileContent(lines);
5858

5959
// Execute
60-
var notYetDownloadedPackages = fileContent.NotYetDownloadedPackages;
60+
var allPackages = fileContent.AllPackages;
6161
var useAspNetDlls = fileContent.UseAspNetDlls;
6262

6363
// Verify
6464
Assert.False(useAspNetDlls);
65-
Assert.Equal(3, notYetDownloadedPackages.Count);
66-
Assert.Contains("DotNetAnalyzers.DocumentationAnalyzers".ToLowerInvariant(), notYetDownloadedPackages);
67-
Assert.Contains("Microsoft.CodeAnalysis.NetAnalyzers".ToLowerInvariant(), notYetDownloadedPackages);
68-
Assert.Contains("StyleCop.Analyzers".ToLowerInvariant(), notYetDownloadedPackages);
65+
Assert.Equal(3, allPackages.Count);
66+
Assert.Contains("DotNetAnalyzers.DocumentationAnalyzers".ToLowerInvariant(), allPackages);
67+
Assert.Contains("Microsoft.CodeAnalysis.NetAnalyzers".ToLowerInvariant(), allPackages);
68+
Assert.Contains("StyleCop.Analyzers".ToLowerInvariant(), allPackages);
6969
}
7070

7171
[Fact]
@@ -83,13 +83,13 @@ public void TestFileContent2()
8383

8484
// Execute
8585
var useAspNetDlls = fileContent.UseAspNetDlls;
86-
var notYetDownloadedPackages = fileContent.NotYetDownloadedPackages;
86+
var allPackages = fileContent.AllPackages;
8787

8888
// Verify
8989
Assert.True(useAspNetDlls);
90-
Assert.Equal(2, notYetDownloadedPackages.Count);
91-
Assert.Contains("Microsoft.CodeAnalysis.NetAnalyzers".ToLowerInvariant(), notYetDownloadedPackages);
92-
Assert.Contains("StyleCop.Analyzers".ToLowerInvariant(), notYetDownloadedPackages);
90+
Assert.Equal(2, allPackages.Count);
91+
Assert.Contains("Microsoft.CodeAnalysis.NetAnalyzers".ToLowerInvariant(), allPackages);
92+
Assert.Contains("StyleCop.Analyzers".ToLowerInvariant(), allPackages);
9393
}
9494
}
9595
}

0 commit comments

Comments
 (0)