dependabot-nuget 0.301.1 → 0.303.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. checksums.yaml +4 -4
  2. data/helpers/lib/NuGetUpdater/Directory.Packages.props +5 -5
  3. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/DependencyDiscovery.props +4 -1
  4. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/DependencyDiscovery.targets +19 -4
  5. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/DependencyDiscoveryTargetingPacks.props +10 -0
  6. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/DiscoveryWorker.cs +20 -17
  7. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/SdkProjectDiscovery.cs +179 -28
  8. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/ExperimentsManager.cs +3 -0
  9. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/FrameworkChecker/FrameworkCompatibilityService.cs +15 -6
  10. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/FrameworkChecker/SupportedFrameworks.cs +6 -4
  11. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/NuGetUpdater.Core.csproj +1 -0
  12. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/RunWorker.cs +8 -0
  13. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/BindingRedirectManager.cs +7 -4
  14. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/LockFileUpdater.cs +2 -0
  15. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/PackageReferenceUpdater.cs +257 -37
  16. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/PackagesConfigUpdater.cs +13 -4
  17. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/{WebApplicationTargetsConditionPatcher.cs → SpecialImportsConditionPatcher.cs} +18 -11
  18. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/UpdateOperationBase.cs +209 -0
  19. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/UpdateOperationResult.cs +3 -0
  20. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/UpdaterWorker.cs +79 -24
  21. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/XmlFilePreAndPostProcessor.cs +26 -11
  22. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/MSBuildHelper.cs +48 -22
  23. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Analyze/AnalyzeWorkerTests.cs +54 -0
  24. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.PackagesConfig.cs +68 -0
  25. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.Project.cs +94 -0
  26. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/FrameworkChecker/FrameworkCompatibilityServiceFacts.cs +1 -1
  27. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Run/RunWorkerTests.cs +24 -6
  28. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/PackageReferenceUpdaterTests.cs +177 -0
  29. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/SpecialFilePatcherTests.cs +99 -0
  30. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateOperationBaseTests.cs +130 -0
  31. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTestBase.cs +5 -0
  32. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.Mixed.cs +71 -5
  33. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.PackageReference.cs +125 -3
  34. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.PackagesConfig.cs +23 -0
  35. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Utilities/MSBuildHelperTests.cs +145 -147
  36. data/lib/dependabot/nuget/file_parser.rb +22 -19
  37. metadata +13 -8
@@ -6,6 +6,7 @@ using System.Text.Json;
6
6
  using System.Text.Json.Nodes;
7
7
  using System.Text.RegularExpressions;
8
8
  using System.Xml;
9
+ using System.Xml.Linq;
9
10
 
10
11
  using Microsoft.Build.Construction;
11
12
  using Microsoft.Build.Definition;
@@ -30,6 +31,8 @@ internal static partial class MSBuildHelper
30
31
 
31
32
  public static bool IsMSBuildRegistered => MSBuildPath.Length > 0;
32
33
 
34
+ public static string GetFileFromRuntimeDirectory(string fileName) => Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)!, fileName);
35
+
33
36
  public static void RegisterMSBuild(string currentDirectory, string rootDirectory)
34
37
  {
35
38
  // Ensure MSBuild types are registered before calling a method that loads the types
@@ -338,7 +341,7 @@ internal static partial class MSBuildHelper
338
341
  return false;
339
342
  }
340
343
 
341
- internal static async Task<bool> DependenciesAreCoherentAsync(string repoRoot, string projectPath, string targetFramework, Dependency[] packages, ExperimentsManager experimentsManager, ILogger logger)
344
+ internal static async Task<bool> DependenciesAreCoherentAsync(string repoRoot, string projectPath, string targetFramework, ImmutableArray<Dependency> packages, ExperimentsManager experimentsManager, ILogger logger)
342
345
  {
343
346
  var tempDirectory = Directory.CreateTempSubdirectory("package-dependency-coherence_");
344
347
  try
@@ -356,7 +359,7 @@ internal static partial class MSBuildHelper
356
359
  }
357
360
  }
358
361
 
359
- internal static async Task<Dependency[]?> ResolveDependencyConflicts(string repoRoot, string projectPath, string targetFramework, Dependency[] packages, Dependency[] update, ExperimentsManager experimentsManager, ILogger logger)
362
+ internal static async Task<ImmutableArray<Dependency>?> ResolveDependencyConflicts(string repoRoot, string projectPath, string targetFramework, ImmutableArray<Dependency> packages, ImmutableArray<Dependency> update, ExperimentsManager experimentsManager, ILogger logger)
360
363
  {
361
364
  var tempDirectory = Directory.CreateTempSubdirectory("package-dependency-coherence_");
362
365
  PackageManager packageManager = new PackageManager(repoRoot, projectPath);
@@ -474,7 +477,7 @@ internal static partial class MSBuildHelper
474
477
  .ToList();
475
478
 
476
479
  // Return as array
477
- Dependency[] candidatePackagesArray = candidatePackages.ToArray();
480
+ var candidatePackagesArray = candidatePackages.ToImmutableArray();
478
481
 
479
482
  var targetFrameworks = new NuGetFramework[] { NuGetFramework.Parse(targetFramework) };
480
483
 
@@ -514,7 +517,7 @@ internal static partial class MSBuildHelper
514
517
  }
515
518
  }
516
519
 
517
- internal static async Task<Dependency[]?> ResolveDependencyConflictsWithBruteForce(string repoRoot, string projectPath, string targetFramework, Dependency[] packages, ExperimentsManager experimentsManager, ILogger logger)
520
+ internal static async Task<ImmutableArray<Dependency>?> ResolveDependencyConflictsWithBruteForce(string repoRoot, string projectPath, string targetFramework, ImmutableArray<Dependency> packages, ExperimentsManager experimentsManager, ILogger logger)
518
521
  {
519
522
  var tempDirectory = Directory.CreateTempSubdirectory("package-dependency-coherence_");
520
523
  try
@@ -596,7 +599,7 @@ internal static partial class MSBuildHelper
596
599
  {
597
600
  // rebuild candidate dependency list with the relevant versions
598
601
  Dictionary<string, NuGetVersion> packageVersions = candidateSet.ToDictionary(candidateSet => candidateSet.PackageName, candidateSet => candidateSet.PackageVersion);
599
- Dependency[] candidatePackages = packages.Select(p =>
602
+ var candidatePackages = packages.Select(p =>
600
603
  {
601
604
  if (packageVersions.TryGetValue(p.Name, out var version))
602
605
  {
@@ -606,7 +609,7 @@ internal static partial class MSBuildHelper
606
609
 
607
610
  // not the dependency we're looking for, use whatever it already was in this set
608
611
  return p;
609
- }).ToArray();
612
+ }).ToImmutableArray();
610
613
 
611
614
  if (await DependenciesAreCoherentAsync(repoRoot, projectPath, targetFramework, candidatePackages, experimentsManager, logger))
612
615
  {
@@ -663,7 +666,7 @@ internal static partial class MSBuildHelper
663
666
  }
664
667
  }
665
668
 
666
- internal static async Task<string> CreateTempProjectAsync(
669
+ internal static Task<string> CreateTempProjectAsync(
667
670
  DirectoryInfo tempDir,
668
671
  string repoRoot,
669
672
  string projectPath,
@@ -671,7 +674,32 @@ internal static partial class MSBuildHelper
671
674
  IReadOnlyCollection<Dependency> packages,
672
675
  ExperimentsManager experimentsManager,
673
676
  ILogger logger,
674
- bool usePackageDownload = false)
677
+ bool usePackageDownload = false,
678
+ bool importDependencyTargets = true
679
+ ) => CreateTempProjectAsync(tempDir, repoRoot, projectPath, new XElement("TargetFramework", targetFramework), packages, experimentsManager, logger, usePackageDownload, importDependencyTargets);
680
+
681
+ internal static Task<string> CreateTempProjectAsync(
682
+ DirectoryInfo tempDir,
683
+ string repoRoot,
684
+ string projectPath,
685
+ ImmutableArray<string> targetFrameworks,
686
+ IReadOnlyCollection<Dependency> packages,
687
+ ExperimentsManager experimentsManager,
688
+ ILogger logger,
689
+ bool usePackageDownload = false,
690
+ bool importDependencyTargets = true
691
+ ) => CreateTempProjectAsync(tempDir, repoRoot, projectPath, new XElement("TargetFrameworks", string.Join(";", targetFrameworks)), packages, experimentsManager, logger, usePackageDownload, importDependencyTargets);
692
+
693
+ private static async Task<string> CreateTempProjectAsync(
694
+ DirectoryInfo tempDir,
695
+ string repoRoot,
696
+ string projectPath,
697
+ XElement targetFrameworkElement,
698
+ IReadOnlyCollection<Dependency> packages,
699
+ ExperimentsManager experimentsManager,
700
+ ILogger logger,
701
+ bool usePackageDownload,
702
+ bool importDependencyTargets)
675
703
  {
676
704
  var projectDirectory = Path.GetDirectoryName(projectPath);
677
705
  projectDirectory ??= repoRoot;
@@ -720,18 +748,18 @@ internal static partial class MSBuildHelper
720
748
  // empty `Version` attributes will cause the temporary project to not build
721
749
  .Where(p => (p.EvaluationResult is null || p.EvaluationResult.ResultType == EvaluationResultType.Success) && !string.IsNullOrWhiteSpace(p.Version))
722
750
  // If all PackageReferences for a package are update-only mark it as such, otherwise it can cause package incoherence errors which do not exist in the repo.
723
- .Select(p => $"<{(usePackageDownload ? "PackageDownload" : "PackageReference")} {(p.IsUpdate ? "Update" : "Include")}=\"{p.Name}\" Version=\"[{p.Version}]\" />"));
751
+ .Select(p => $"<{(usePackageDownload ? "PackageDownload" : "PackageReference")} {(p.IsUpdate ? "Update" : "Include")}=\"{p.Name}\" Version=\"{(p.Version!.Contains("*") ? p.Version : $"[{p.Version}]")}\" />"));
752
+
753
+ var dependencyTargetsImport = importDependencyTargets
754
+ ? $"""<Import Project="{GetFileFromRuntimeDirectory("DependencyDiscovery.targets")}" />"""
755
+ : string.Empty;
724
756
 
725
757
  var projectContents = $"""
726
758
  <Project Sdk="Microsoft.NET.Sdk">
727
759
  <PropertyGroup>
728
- <TargetFramework>{targetFramework}</TargetFramework>
729
- <GenerateDependencyFile>true</GenerateDependencyFile>
730
- <RunAnalyzers>false</RunAnalyzers>
731
- <NuGetInteractive>false</NuGetInteractive>
732
- <DesignTimeBuild>true</DesignTimeBuild>
733
- <TargetPlatformVersion Condition=" $(TargetFramework.Contains('-')) ">1.0</TargetPlatformVersion>
760
+ {targetFrameworkElement}
734
761
  </PropertyGroup>
762
+ {dependencyTargetsImport}
735
763
  <ItemGroup>
736
764
  {packageReferences}
737
765
  </ItemGroup>
@@ -763,8 +791,6 @@ internal static partial class MSBuildHelper
763
791
  """
764
792
  <Project>
765
793
  <PropertyGroup>
766
- <!-- For Windows-specific apps -->
767
- <EnableWindowsTargeting>true</EnableWindowsTargeting>
768
794
  <!-- Really ensure CPM is disabled -->
769
795
  <ManagePackageVersionsCentrally>false</ManagePackageVersionsCentrally>
770
796
  </PropertyGroup>
@@ -854,7 +880,7 @@ internal static partial class MSBuildHelper
854
880
  return tfms;
855
881
  }
856
882
 
857
- internal static async Task<Dependency[]> GetAllPackageDependenciesAsync(
883
+ internal static async Task<ImmutableArray<Dependency>> GetAllPackageDependenciesAsync(
858
884
  string repoRoot,
859
885
  string projectPath,
860
886
  string targetFramework,
@@ -867,16 +893,16 @@ internal static partial class MSBuildHelper
867
893
  try
868
894
  {
869
895
  var topLevelPackagesNames = packages.Select(p => p.Name).ToHashSet(StringComparer.OrdinalIgnoreCase);
870
- var tempProjectPath = await CreateTempProjectAsync(tempDirectory, repoRoot, projectPath, targetFramework, packages, experimentsManager, logger);
896
+ var tempProjectPath = await CreateTempProjectAsync(tempDirectory, repoRoot, projectPath, targetFramework, packages, experimentsManager, logger, importDependencyTargets: !experimentsManager.UseDirectDiscovery);
871
897
 
872
- Dependency[] allDependencies;
898
+ ImmutableArray<Dependency> allDependencies;
873
899
  if (experimentsManager.UseDirectDiscovery)
874
900
  {
875
901
  var projectDiscovery = await SdkProjectDiscovery.DiscoverAsync(repoRoot, tempDirectory.FullName, tempProjectPath, experimentsManager, logger);
876
902
  allDependencies = projectDiscovery
877
903
  .Where(p => p.FilePath == Path.GetFileName(tempProjectPath))
878
904
  .FirstOrDefault()
879
- ?.Dependencies.ToArray() ?? [];
905
+ ?.Dependencies.ToImmutableArray() ?? [];
880
906
  }
881
907
  else
882
908
  {
@@ -897,7 +923,7 @@ internal static partial class MSBuildHelper
897
923
  var isTransitive = !topLevelPackagesNames.Contains(PackageName);
898
924
  return new Dependency(PackageName, match.Groups["PackageVersion"].Value, DependencyType.Unknown, TargetFrameworks: tfms, IsTransitive: isTransitive);
899
925
  })
900
- .ToArray();
926
+ .ToImmutableArray();
901
927
  }
902
928
  else
903
929
  {
@@ -533,6 +533,60 @@ public partial class AnalyzeWorkerTests : AnalyzeWorkerTestBase
533
533
  );
534
534
  }
535
535
 
536
+ [Fact]
537
+ public async Task WindowsSpecificProjectAndWindowsSpecificDependency()
538
+ {
539
+ await TestAnalyzeAsync(
540
+ experimentsManager: new ExperimentsManager() { UseDirectDiscovery = true },
541
+ packages: [
542
+ MockNuGetPackage.CreateSimplePackage("Some.Package", "1.0.0", "net6.0-windows7.0"),
543
+ MockNuGetPackage.CreateSimplePackage("Some.Package", "1.0.1", "net6.0-windows7.0"),
544
+ ],
545
+ discovery: new()
546
+ {
547
+ Path = "/",
548
+ Projects = [
549
+ new()
550
+ {
551
+ FilePath = "./project.csproj",
552
+ TargetFrameworks = ["net9.0-windows"],
553
+ Dependencies = [
554
+ new("Some.Package", "1.0.0", DependencyType.PackageReference),
555
+ ],
556
+ ReferencedProjectPaths = [],
557
+ ImportedFiles = [],
558
+ AdditionalFiles = [],
559
+ },
560
+ ],
561
+ },
562
+ dependencyInfo: new()
563
+ {
564
+ Name = "Some.Package",
565
+ Version = "1.0.0",
566
+ IgnoredVersions = [],
567
+ IsVulnerable = false,
568
+ Vulnerabilities = [
569
+ new()
570
+ {
571
+ DependencyName = "Some.Package",
572
+ PackageManager = "nuget",
573
+ VulnerableVersions = [],
574
+ SafeVersions = []
575
+ }
576
+ ],
577
+ },
578
+ expectedResult: new()
579
+ {
580
+ UpdatedVersion = "1.0.1",
581
+ CanUpdate = true,
582
+ VersionComesFromMultiDependencyProperty = false,
583
+ UpdatedDependencies = [
584
+ new("Some.Package", "1.0.1", DependencyType.PackageReference, TargetFrameworks: ["net9.0-windows"], IsDirect: true),
585
+ ],
586
+ }
587
+ );
588
+ }
589
+
536
590
  [Fact]
537
591
  public async Task VersionFinderCanHandle404FromPackageSource_V2()
538
592
  {
@@ -171,5 +171,73 @@ public partial class DiscoveryWorkerTests
171
171
  }
172
172
  );
173
173
  }
174
+
175
+ [Fact]
176
+ public async Task DirectDiscoveryWorksEvenWithTargetsImportsOnlyProvidedByVisualStudio()
177
+ {
178
+ await TestDiscoveryAsync(
179
+ workspacePath: "project1/",
180
+ experimentsManager: new ExperimentsManager() { UseDirectDiscovery = true },
181
+ packages: [
182
+ MockNuGetPackage.CreateSimplePackage("Some.Package", "1.0.0", "net48"),
183
+ ],
184
+ files: [
185
+ ("project1/project1.csproj", """
186
+ <Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
187
+ <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
188
+ <PropertyGroup>
189
+ <OutputType>Library</OutputType>
190
+ <TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
191
+ </PropertyGroup>
192
+ <ItemGroup>
193
+ <None Include="packages.config" />
194
+ </ItemGroup>
195
+ <ItemGroup>
196
+ <ProjectReference Include="..\project2\project2.csproj" />
197
+ </ItemGroup>
198
+ <Import Project="$(VSToolsPath)\SomeSubPath\WebApplications\Microsoft.WebApplication.targets" />
199
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
200
+ </Project>
201
+ """),
202
+ ("project1/packages.config", """
203
+ <?xml version="1.0" encoding="utf-8"?>
204
+ <packages>
205
+ <package id="Some.Package" version="1.0.0" targetFramework="net48" />
206
+ </packages>
207
+ """),
208
+ ("project2/project2.csproj", """
209
+ <Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
210
+ <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
211
+ <PropertyGroup>
212
+ <OutputType>Library</OutputType>
213
+ <TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
214
+ </PropertyGroup>
215
+ <Import Project="$(VSToolsPath)\SomeSubPath\WebApplications\Microsoft.WebApplication.targets" />
216
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
217
+ </Project>
218
+ """)
219
+ ],
220
+ expectedResult: new()
221
+ {
222
+ Path = "project1/",
223
+ Projects = [
224
+ new()
225
+ {
226
+ FilePath = "project1.csproj",
227
+ Properties = [],
228
+ TargetFrameworks = ["net48"],
229
+ Dependencies = [
230
+ new("Some.Package", "1.0.0", DependencyType.PackagesConfig, TargetFrameworks: ["net48"]),
231
+ ],
232
+ ReferencedProjectPaths = [],
233
+ ImportedFiles = [],
234
+ AdditionalFiles = [
235
+ "packages.config"
236
+ ],
237
+ }
238
+ ]
239
+ }
240
+ );
241
+ }
174
242
  }
175
243
  }
@@ -1116,6 +1116,50 @@ public partial class DiscoveryWorkerTests
1116
1116
  );
1117
1117
  }
1118
1118
 
1119
+ [Fact]
1120
+ public async Task WindowsSpecificProjectAndWindowsSpecificDependency()
1121
+ {
1122
+ await TestDiscoveryAsync(
1123
+ experimentsManager: new ExperimentsManager() { UseDirectDiscovery = true },
1124
+ packages: [
1125
+ MockNuGetPackage.CreateSimplePackage("Some.Os.Package", "1.2.3", "net6.0-windows7.0")
1126
+ ],
1127
+ workspacePath: "",
1128
+ files: [
1129
+ ("project.csproj", """
1130
+ <Project Sdk="Microsoft.NET.Sdk">
1131
+ <PropertyGroup>
1132
+ <TargetFramework>net9.0-windows</TargetFramework>
1133
+ </PropertyGroup>
1134
+ <ItemGroup>
1135
+ <PackageReference Include="Some.Os.Package" Version="1.2.3" />
1136
+ </ItemGroup>
1137
+ </Project>
1138
+ """)
1139
+ ],
1140
+ expectedResult: new()
1141
+ {
1142
+ Path = "",
1143
+ Projects = [
1144
+ new()
1145
+ {
1146
+ FilePath = "project.csproj",
1147
+ Dependencies = [
1148
+ new("Some.Os.Package", "1.2.3", DependencyType.PackageReference, TargetFrameworks: ["net9.0-windows"], IsDirect: true)
1149
+ ],
1150
+ Properties = [
1151
+ new("TargetFramework", "net9.0-windows", "project.csproj")
1152
+ ],
1153
+ TargetFrameworks = ["net9.0-windows"],
1154
+ ReferencedProjectPaths = [],
1155
+ ImportedFiles = [],
1156
+ AdditionalFiles = []
1157
+ }
1158
+ ]
1159
+ }
1160
+ );
1161
+ }
1162
+
1119
1163
  [Fact]
1120
1164
  public async Task DiscoveryWithTargetPlaformVersion_DirectDiscovery()
1121
1165
  {
@@ -1375,5 +1419,55 @@ public partial class DiscoveryWorkerTests
1375
1419
  }
1376
1420
  );
1377
1421
  }
1422
+
1423
+ [Fact]
1424
+ public async Task LegacyProjectWithPackageReferencesReportsDependencies()
1425
+ {
1426
+ // This is a feature of the VS project system - a legacy project with <PackageReference> elements. The `dotnet` CLI
1427
+ // can't resolve the transitive dependencies; only the VS project system can, so there are some manual steps to allow
1428
+ // dependency discovery.
1429
+ await TestDiscoveryAsync(
1430
+ experimentsManager: new ExperimentsManager() { UseDirectDiscovery = true },
1431
+ packages: [
1432
+ MockNuGetPackage.CreateSimplePackage("Some.Dependency", "1.0.0", "net48", [(null, [("Some.Transitive.Dependency", "2.0.0")])]),
1433
+ MockNuGetPackage.CreateSimplePackage("Some.Transitive.Dependency", "2.0.0", "net48"),
1434
+ ],
1435
+ workspacePath: "",
1436
+ files: [
1437
+ ("project.csproj", """
1438
+ <Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
1439
+ <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
1440
+ <PropertyGroup>
1441
+ <OutputType>Library</OutputType>
1442
+ <TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
1443
+ </PropertyGroup>
1444
+ <ItemGroup>
1445
+ <PackageReference Include="Some.Dependency" Version="1.0.0" />
1446
+ </ItemGroup>
1447
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
1448
+ </Project>
1449
+ """)
1450
+ ],
1451
+ expectedResult: new()
1452
+ {
1453
+ Path = "",
1454
+ Projects = [
1455
+ new()
1456
+ {
1457
+ FilePath = "project.csproj",
1458
+ Dependencies = [
1459
+ new("Some.Dependency", "1.0.0", DependencyType.PackageReference, TargetFrameworks: ["net48"], IsDirect: true),
1460
+ new("Some.Transitive.Dependency", "2.0.0", DependencyType.Unknown, TargetFrameworks: ["net48"], IsTransitive: true),
1461
+ ],
1462
+ Properties = [],
1463
+ TargetFrameworks = ["net48"],
1464
+ ReferencedProjectPaths = [],
1465
+ ImportedFiles = [],
1466
+ AdditionalFiles = [],
1467
+ }
1468
+ ]
1469
+ }
1470
+ );
1471
+ }
1378
1472
  }
1379
1473
  }
@@ -102,7 +102,7 @@ public class FrameworkCompatibilityServiceFacts
102
102
  }
103
103
 
104
104
  [Theory]
105
- [InlineData("net6.0-windows7.0", "net6.0-windows", "net6.0-windows7.0", "net7.0-windows", "net7.0-windows7.0")]
105
+ [InlineData("net6.0-windows7.0", "net6.0-windows", "net6.0-windows7.0", "net7.0-windows", "net7.0-windows7.0", "net8.0-windows", "net8.0-windows7.0", "net9.0-windows", "net9.0-windows7.0")]
106
106
  public void WindowsPlatformVersionsShouldContainAllSpecifiedFrameworks(string windowsDefaultVersionFramework, params string[] windowsProjectFrameworks)
107
107
  {
108
108
  var packageFramework = NuGetFramework.Parse(windowsDefaultVersionFramework);
@@ -106,7 +106,10 @@ public class RunWorkerTests
106
106
  </ItemGroup>
107
107
  </Project>
108
108
  """.SetEOL(EOL));
109
- return new UpdateOperationResult();
109
+ return new UpdateOperationResult()
110
+ {
111
+ UpdateOperations = [],
112
+ };
110
113
  }),
111
114
  expectedResult: new RunResult()
112
115
  {
@@ -314,7 +317,10 @@ public class RunWorkerTests
314
317
  </ItemGroup>
315
318
  </Project>
316
319
  """.SetEOL(EOL));
317
- return new UpdateOperationResult();
320
+ return new UpdateOperationResult()
321
+ {
322
+ UpdateOperations = [],
323
+ };
318
324
  }),
319
325
  expectedResult: new RunResult()
320
326
  {
@@ -681,7 +687,10 @@ public class RunWorkerTests
681
687
  throw new NotSupportedException();
682
688
  }
683
689
 
684
- return new UpdateOperationResult();
690
+ return new UpdateOperationResult()
691
+ {
692
+ UpdateOperations = [],
693
+ };
685
694
  }),
686
695
  expectedResult: new RunResult()
687
696
  {
@@ -1091,7 +1100,10 @@ public class RunWorkerTests
1091
1100
  throw new NotSupportedException();
1092
1101
  }
1093
1102
 
1094
- return new UpdateOperationResult();
1103
+ return new UpdateOperationResult()
1104
+ {
1105
+ UpdateOperations = [],
1106
+ };
1095
1107
  }),
1096
1108
  expectedResult: new RunResult()
1097
1109
  {
@@ -1553,7 +1565,10 @@ public class RunWorkerTests
1553
1565
  </PropertyGroup>
1554
1566
  </Project>
1555
1567
  """.SetEOL(EOL));
1556
- return new UpdateOperationResult();
1568
+ return new UpdateOperationResult()
1569
+ {
1570
+ UpdateOperations = [],
1571
+ };
1557
1572
  }),
1558
1573
  expectedResult: new RunResult()
1559
1574
  {
@@ -2316,7 +2331,10 @@ public class RunWorkerTests
2316
2331
  _ => throw new NotImplementedException("unreachable")
2317
2332
  };
2318
2333
  await File.WriteAllTextAsync(dependencyFilePath, updatedContent);
2319
- return new UpdateOperationResult();
2334
+ return new UpdateOperationResult()
2335
+ {
2336
+ UpdateOperations = [],
2337
+ };
2320
2338
  }),
2321
2339
  expectedResult: new()
2322
2340
  {