Skip to content

Commit 4e2c6ff

Browse files
committed
C#: Consider possibly restored reference assemblies
1 parent 4887c69 commit 4e2c6ff

File tree

2 files changed

+96
-42
lines changed

2 files changed

+96
-42
lines changed

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

Lines changed: 94 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -96,40 +96,22 @@ public DependencyManager(string srcDir, IDependencyOptions options, ILogger logg
9696
DownloadMissingPackages(allNonBinaryFiles);
9797
}
9898

99+
var existsNetCoreRefNugetPackage = false;
100+
var existsNetFrameworkRefNugetPackage = false;
101+
99102
// Find DLLs in the .Net / Asp.Net Framework
100103
if (options.ScanNetFrameworkDlls)
101104
{
102-
// TODO: check if the nuget restore process has already downloaded any Core or Framework reference assemblies.
103-
// If so, we don't have to do the below.
104-
// `Microsoft.NETCore.App.Ref` or `Microsoft.NETFramework.ReferenceAssemblies.*`
105-
106-
var runtime = new Runtime(dotnet);
107-
string? runtimeLocation = null;
105+
existsNetCoreRefNugetPackage = IsNugetPackageAvailable("microsoft.netcore.app.ref");
106+
existsNetFrameworkRefNugetPackage = IsNugetPackageAvailable("microsoft.netframework.referenceassemblies");
108107

109-
if (options.UseSelfContainedDotnet)
110-
{
111-
runtimeLocation = runtime.ExecutingRuntime;
112-
}
113-
else if (fileContent.IsNewProjectStructureUsed)
108+
if (existsNetCoreRefNugetPackage || existsNetFrameworkRefNugetPackage)
114109
{
115-
runtimeLocation = runtime.NetCoreRuntime;
110+
progressMonitor.LogInfo("Found .NET Core/Framework DLLs in NuGet packages. Not adding installation directory.");
116111
}
117-
else if (fileContent.IsLegacyProjectStructureUsed)
118-
{
119-
runtimeLocation = runtime.DesktopRuntime;
120-
}
121-
122-
runtimeLocation ??= runtime.ExecutingRuntime;
123-
124-
progressMonitor.LogInfo($".NET runtime location selected: {runtimeLocation}");
125-
dllDirNames.Add(runtimeLocation);
126-
127-
if (fileContent.IsNewProjectStructureUsed
128-
&& fileContent.UseAspNetCoreDlls
129-
&& runtime.AspNetCoreRuntime is string aspRuntime)
112+
else
130113
{
131-
progressMonitor.LogInfo($"ASP.NET runtime location selected: {aspRuntime}");
132-
dllDirNames.Add(aspRuntime);
114+
AddNetFrameworkDlls(dllDirNames);
133115
}
134116
}
135117

@@ -141,7 +123,7 @@ public DependencyManager(string srcDir, IDependencyOptions options, ILogger logg
141123
UseReference(filename);
142124
}
143125

144-
RemoveRuntimeNugetPackageReferences();
126+
RemoveUnnecessaryNugetPackages(existsNetCoreRefNugetPackage, existsNetFrameworkRefNugetPackage);
145127
ResolveConflicts();
146128

147129
// Output the findings
@@ -176,38 +158,110 @@ public DependencyManager(string srcDir, IDependencyOptions options, ILogger logg
176158
DateTime.Now - startTime);
177159
}
178160

179-
private void RemoveRuntimeNugetPackageReferences()
161+
private void RemoveUnnecessaryNugetPackages(bool existsNetCoreRefNugetPackage, bool existsNetFrameworkRefNugetPackage)
180162
{
181-
if (!options.UseNuGet)
163+
RemoveRuntimeNugetPackageReferences();
164+
165+
if (fileContent.IsNewProjectStructureUsed
166+
&& !fileContent.UseAspNetCoreDlls)
182167
{
183-
return;
168+
// This might have been restored by the CLI even though the project isn't an asp.net core one.
169+
RemoveNugetPackageReference("microsoft.aspnetcore.app.ref");
184170
}
185171

186-
var packageFolder = packageDirectory.DirInfo.FullName.ToLowerInvariant();
187-
var runtimePackageNamePrefixes = new[]
172+
if (existsNetCoreRefNugetPackage && existsNetFrameworkRefNugetPackage)
173+
{
174+
// Multiple packages are available, we keep only one:
175+
RemoveNugetPackageReference("microsoft.netframework.referenceassemblies.");
176+
}
177+
178+
// TODO: There could be multiple `microsoft.netframework.referenceassemblies` packages,
179+
// we could keep the newest one, but this is covered by the conflict resolution logic
180+
// (if the file names match)
181+
}
182+
183+
private void AddNetFrameworkDlls(List<string> dllDirNames)
184+
{
185+
var runtime = new Runtime(dotnet);
186+
string? runtimeLocation = null;
187+
188+
if (options.UseSelfContainedDotnet)
189+
{
190+
runtimeLocation = runtime.ExecutingRuntime;
191+
}
192+
else if (fileContent.IsNewProjectStructureUsed)
193+
{
194+
runtimeLocation = runtime.NetCoreRuntime;
195+
}
196+
else if (fileContent.IsLegacyProjectStructureUsed)
188197
{
189-
Path.Combine(packageFolder, "microsoft.netcore.app.runtime"),
190-
Path.Combine(packageFolder, "microsoft.aspnetcore.app.runtime"),
191-
Path.Combine(packageFolder, "microsoft.windowsdesktop.app.runtime"),
198+
runtimeLocation = runtime.DesktopRuntime;
199+
}
200+
201+
runtimeLocation ??= runtime.ExecutingRuntime;
202+
203+
progressMonitor.LogInfo($".NET runtime location selected: {runtimeLocation}");
204+
dllDirNames.Add(runtimeLocation);
205+
206+
if (fileContent.IsNewProjectStructureUsed
207+
&& fileContent.UseAspNetCoreDlls
208+
&& runtime.AspNetCoreRuntime is string aspRuntime)
209+
{
210+
progressMonitor.LogInfo($"ASP.NET runtime location selected: {aspRuntime}");
211+
dllDirNames.Add(aspRuntime);
212+
}
213+
}
214+
215+
private void RemoveRuntimeNugetPackageReferences()
216+
{
217+
var runtimePackagePrefixes = new[]
218+
{
219+
"microsoft.netcore.app.runtime",
220+
"microsoft.aspnetcore.app.runtime",
221+
"microsoft.windowsdesktop.app.runtime",
192222

193223
// legacy runtime packages:
194-
Path.Combine(packageFolder, "runtime.linux-x64.microsoft.netcore.app"),
195-
Path.Combine(packageFolder, "runtime.osx-x64.microsoft.netcore.app"),
196-
Path.Combine(packageFolder, "runtime.win-x64.microsoft.netcore.app"),
224+
"runtime.linux-x64.microsoft.netcore.app",
225+
"runtime.osx-x64.microsoft.netcore.app",
226+
"runtime.win-x64.microsoft.netcore.app",
197227
};
228+
RemoveNugetPackageReference(runtimePackagePrefixes);
229+
}
230+
231+
private void RemoveNugetPackageReference(params string[] packagePrefixes)
232+
{
233+
if (!options.UseNuGet)
234+
{
235+
return;
236+
}
237+
238+
var packageFolder = packageDirectory.DirInfo.FullName.ToLowerInvariant();
239+
var packagePathPrefixes = packagePrefixes.Select(p => Path.Combine(packageFolder, p.ToLowerInvariant()));
198240

199241
foreach (var filename in usedReferences.Keys)
200242
{
201243
var lowerFilename = filename.ToLowerInvariant();
202244

203-
if (runtimePackageNamePrefixes.Any(prefix => lowerFilename.StartsWith(prefix)))
245+
if (packagePathPrefixes.Any(prefix => lowerFilename.StartsWith(prefix)))
204246
{
205247
usedReferences.Remove(filename);
206248
progressMonitor.RemovedReference(filename);
207249
}
208250
}
209251
}
210252

253+
private bool IsNugetPackageAvailable(string packagePrefix)
254+
{
255+
if (!options.UseNuGet)
256+
{
257+
return false;
258+
}
259+
260+
return new DirectoryInfo(packageDirectory.DirInfo.FullName)
261+
.EnumerateDirectories(packagePrefix + "*", new EnumerationOptions { MatchCasing = MatchCasing.CaseInsensitive, RecurseSubdirectories = false })
262+
.Any();
263+
}
264+
211265
private void GenerateSourceFileFromImplicitUsings()
212266
{
213267
var usings = new HashSet<string>();

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,10 +55,10 @@ public void NugetInstall(string package) =>
5555
LogInfo($"Restoring {package}...");
5656

5757
public void ResolvedReference(string filename) =>
58-
LogInfo($"Resolved {filename}");
58+
LogInfo($"Resolved reference {filename}");
5959

6060
public void RemovedReference(string filename) =>
61-
LogInfo($"Reference {filename} has been removed");
61+
LogInfo($"Removed reference {filename}");
6262

6363
public void Summary(int existingSources, int usedSources, int missingSources,
6464
int references, int unresolvedReferences,

0 commit comments

Comments
 (0)