Skip to content

Commit 6840069

Browse files
authored
Get reference nearest disambiguates with an alias too (#7218)
1 parent 799ea08 commit 6840069

7 files changed

Lines changed: 274 additions & 12 deletions

File tree

src/NuGet.Core/NuGet.Build.Tasks/GetReferenceNearestTargetFrameworkTask.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@ private ITaskItem AssignNearestFrameworkForSingleReference(
169169
// try project fallback frameworks
170170
foreach (var currentProjectTargetFramework in fallbackNuGetFrameworks)
171171
{
172-
nearestNuGetFramework = packageSpec.GetNearestTargetFramework(currentProjectTargetFramework, targetAlias: null);
172+
nearestNuGetFramework = packageSpec.GetNearestTargetFramework(currentProjectTargetFramework, targetAlias: CurrentProjectTargetFrameworkProperty);
173173

174174
if (nearestNuGetFramework.FrameworkName != null)
175175
{

src/NuGet.Core/NuGet.ProjectModel/LockFile/AssetsLogMessage.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,14 @@
55

66
using System;
77
using System.Collections.Generic;
8+
using System.Diagnostics;
89
using System.Text.Json.Serialization;
910
using NuGet.Common;
1011
using NuGet.Shared;
1112

1213
namespace NuGet.ProjectModel
1314
{
15+
[DebuggerDisplay("{Code} {Message}")]
1416
public partial class AssetsLogMessage : IAssetsLogMessage, IEquatable<IAssetsLogMessage>
1517
{
1618
[JsonConverter(typeof(JsonStringEnumConverter<NuGetLogCode>))]

src/NuGet.Core/NuGet.ProjectModel/PackageSpecReferenceDependencyProvider.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -252,7 +252,7 @@ private List<LibraryDependency> GetDependenciesFromSpecRestoreMetadata(PackageSp
252252
{
253253
if (targetFrameworkInfo.FrameworkName == null && targetFramework is AssetTargetFallbackFramework atfFramework)
254254
{
255-
targetFrameworkInfo = packageSpec.GetNearestTargetFramework(atfFramework.AsFallbackFramework(), targetAlias: null);
255+
targetFrameworkInfo = packageSpec.GetNearestTargetFramework(atfFramework.AsFallbackFramework(), targetAlias: targetAlias);
256256
}
257257
}
258258

test/NuGet.Core.FuncTests/Dotnet.Integration.Test/DotnetRestoreTests.cs

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4130,6 +4130,96 @@ await SimpleTestPackageUtility.CreateFolderFeedV3Async(
41304130
assetsFile.LogMessages.Should().BeEmpty();
41314131
}
41324132

4133+
[PlatformFact(Platform.Windows)]
4134+
public async Task DotnetRestore_WithAliasesOfSameFramework_WithAssetTargetFallbackProjectReference_CanBuildSuccessfully()
4135+
{
4136+
using SimpleTestPathContext pathContext = _dotnetFixture.CreateSimpleTestPathContext();
4137+
4138+
var pkgNet472 = new SimpleTestPackageContext("a", "1.0.0");
4139+
pkgNet472.AddFile("lib/net472/a.dll");
4140+
await SimpleTestPackageUtility.CreatePackagesAsync(pathContext.PackageSource, pkgNet472);
4141+
4142+
string apple = nameof(apple);
4143+
string banana = nameof(banana);
4144+
4145+
var project2Name = "Project2";
4146+
var project2File = Path.Combine(pathContext.SolutionRoot, project2Name, $"{project2Name}.csproj");
4147+
_dotnetFixture.CreateDotnetNewProject(pathContext.SolutionRoot, project2Name, " classlib", testOutputHelper: _testOutputHelper);
4148+
using (var stream = File.Open(project2File, FileMode.Open, FileAccess.ReadWrite))
4149+
{
4150+
var xml = XDocument.Load(stream);
4151+
ProjectFileUtils.SetTargetFrameworkForProject(xml, "TargetFrameworks", $"{apple};{banana}");
4152+
4153+
ProjectFileUtils.AddItem(
4154+
xml,
4155+
"PackageReference",
4156+
pkgNet472.Id,
4157+
string.Empty,
4158+
[],
4159+
new Dictionary<string, string>() { { "Version", "1.0.0" } });
4160+
4161+
var frameworkProps = new Dictionary<string, string>
4162+
{
4163+
{ "TargetFrameworkIdentifier", ".NETFramework" },
4164+
{ "TargetFrameworkVersion", $"v4.7.2" },
4165+
};
4166+
4167+
ProjectFileUtils.AddProperties(xml, frameworkProps, $" '$(TargetFramework)' == '{apple}' ");
4168+
ProjectFileUtils.AddProperties(xml, frameworkProps, $" '$(TargetFramework)' == '{banana}' ");
4169+
4170+
ProjectFileUtils.WriteXmlToFile(xml, stream);
4171+
}
4172+
4173+
var projectName = "ClassLibrary1";
4174+
var projectDirectory = Path.Combine(pathContext.SolutionRoot, projectName);
4175+
var projectFile = Path.Combine(projectDirectory, $"{projectName}.csproj");
4176+
_dotnetFixture.CreateDotnetNewProject(pathContext.SolutionRoot, projectName, " classlib", testOutputHelper: _testOutputHelper);
4177+
4178+
using (var stream = File.Open(projectFile, FileMode.Open, FileAccess.ReadWrite))
4179+
{
4180+
var xml = XDocument.Load(stream);
4181+
ProjectFileUtils.SetTargetFrameworkForProject(xml, "TargetFrameworks", $"{apple};{banana}");
4182+
4183+
// Add project reference to project2
4184+
ProjectFileUtils.AddItem(
4185+
xml,
4186+
"ProjectReference",
4187+
$"..\\{project2Name}\\{project2Name}.csproj",
4188+
string.Empty,
4189+
[],
4190+
[]);
4191+
4192+
var frameworkProps = new Dictionary<string, string>
4193+
{
4194+
{ "TargetFrameworkIdentifier", ".NETCoreApp" },
4195+
{ "TargetFrameworkVersion", $"v{TestConstants.DefaultTargetFramework.Version.ToString(2)}" },
4196+
};
4197+
ProjectFileUtils.AddProperties(xml, frameworkProps, $" '$(TargetFramework)' == '{apple}' ");
4198+
ProjectFileUtils.AddProperties(xml, frameworkProps, $" '$(TargetFramework)' == '{banana}' ");
4199+
ProjectFileUtils.WriteXmlToFile(xml, stream);
4200+
}
4201+
4202+
// Act
4203+
var result = _dotnetFixture.RunDotnetExpectSuccess(pathContext.SolutionRoot, $"restore {projectFile}", testOutputHelper: _testOutputHelper);
4204+
4205+
// Assert
4206+
var assetsFilePath = Path.Combine(projectDirectory, "obj", "project.assets.json");
4207+
var assetsFile = new LockFileFormat().Read(assetsFilePath);
4208+
4209+
LockFileTarget appleTarget = assetsFile.GetTarget(apple, null);
4210+
appleTarget.Libraries.Should().HaveCount(2);
4211+
LockFileTarget bananaTarget = assetsFile.GetTarget(banana, null);
4212+
bananaTarget.Libraries.Should().HaveCount(2);
4213+
4214+
assetsFile.LogMessages.Should().HaveCount(1);
4215+
assetsFile.LogMessages[0].Level.Should().Be(LogLevel.Warning);
4216+
assetsFile.LogMessages[0].Code.Should().Be(NuGetLogCode.NU1701);
4217+
//assetsFile.LogMessages[0].TargetGraphs.Should().HaveCount(2);
4218+
4219+
var buildResult = _dotnetFixture.RunDotnetExpectSuccess(pathContext.SolutionRoot, $"build {projectFile} --no-restore", testOutputHelper: _testOutputHelper);
4220+
buildResult.AllOutput.Should().Contain("NU1702");
4221+
}
4222+
41334223
private void AssertRelatedProperty(IList<LockFileItem> items, string path, string related)
41344224
{
41354225
var item = items.Single(i => i.Path.Equals(path));

test/NuGet.Core.FuncTests/NuGet.Commands.FuncTest/RestoreCommandTests.cs

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4365,6 +4365,66 @@ await SimpleTestPackageUtility.CreateFolderFeedV3Async(
43654365
result.LockFile.LogMessages.Should().HaveCount(0);
43664366
}
43674367

4368+
// P (net10.0) -> Net472 package
4369+
// P (net9.0) -> Net472 package
4370+
[Fact(Skip = "https://github.com/NuGet/Home/issues/14815")]
4371+
public async Task RestoreCommand_WithAssetTargetFallbackFromProject_WarningsRaisedWhenApplicable()
4372+
{
4373+
using var pathContext = new SimpleTestPathContext();
4374+
4375+
var net472pkg = new SimpleTestPackageContext("net472pkg", "1.0.0");
4376+
net472pkg.AddFile("lib/net472/a.dll");
4377+
4378+
await SimpleTestPackageUtility.CreatePackagesAsync(pathContext.PackageSource, net472pkg);
4379+
4380+
var project1Spec = @"
4381+
{
4382+
""frameworks"": {
4383+
""net10.0"": {
4384+
""assetTargetFallback"": true,
4385+
""imports"": [ ""net472"" ],
4386+
""warn"": true,
4387+
""dependencies"": {
4388+
""net472pkg"": {
4389+
""version"": ""[1.0.0,)"",
4390+
""target"": ""Package"",
4391+
}
4392+
}
4393+
},
4394+
""net9.0"": {
4395+
""assetTargetFallback"": true,
4396+
""imports"": [ ""net472"" ],
4397+
""warn"": true,
4398+
""dependencies"": {
4399+
""net472pkg"": {
4400+
""version"": ""[1.0.0,)"",
4401+
""target"": ""Package"",
4402+
}
4403+
}
4404+
}
4405+
}
4406+
}";
4407+
4408+
var project1 = ProjectTestHelpers.GetPackageSpecWithProjectNameAndSpec("Project1", pathContext.SolutionRoot, project1Spec);
4409+
4410+
// Act
4411+
var result = await RunRestoreAsync(pathContext, project1);
4412+
4413+
result.Success.Should().BeTrue();
4414+
result.LockFile.Targets.Should().HaveCount(2);
4415+
result.LockFile.Targets[0].Libraries.Should().HaveCount(1);
4416+
result.LockFile.Targets[0].Libraries[0].Name.Should().Be(net472pkg.Id);
4417+
result.LockFile.Targets[1].Libraries.Should().HaveCount(1);
4418+
result.LockFile.Targets[1].Libraries[0].Name.Should().Be(net472pkg.Id);
4419+
4420+
// Verify log messages
4421+
result.LockFile.LogMessages.Should().HaveCount(1);
4422+
result.LockFile.LogMessages[0].Level.Should().Be(LogLevel.Warning);
4423+
result.LockFile.LogMessages[0].Code.Should().Be(NuGetLogCode.NU1701);
4424+
result.LockFile.LogMessages[0].LibraryId.Should().Be(net472pkg.Id);
4425+
result.LockFile.LogMessages[0].TargetGraphs.Should().HaveCount(2);
4426+
}
4427+
43684428
private static void CreateFakeProjectFile(PackageSpec project2spec)
43694429
{
43704430
Directory.CreateDirectory(Path.GetDirectoryName(project2spec.RestoreMetadata.ProjectUniqueName));

test/NuGet.Core.FuncTests/NuGet.Commands.FuncTest/RestoreCommand_Aliases.cs

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -844,6 +844,98 @@ public async Task RestoreCommand_WithAliasesOfSameFrameworkAndProjectReferenceTo
844844
result.LockFile.LogMessages[0].TargetGraphs.Should().BeEquivalentTo([apple, banana]);
845845
}
846846

847+
// P (apple) -> P2(net472) -> Net472 package
848+
// P (banana) -> P2(net472) -> Net472 package
849+
[Fact]
850+
public async Task RestoreCommand_WithAliasesOfSameFramework_WithProjectReference_WithAssetTargetFallback_WarningsRaisedWhenApplicable()
851+
{
852+
using var pathContext = new SimpleTestPathContext();
853+
var pkgA = new SimpleTestPackageContext("pkgA", "1.0.0");
854+
pkgA.AddFile("lib/net472/pkgA.dll");
855+
await SimpleTestPackageUtility.CreatePackagesAsync(pathContext.PackageSource, pkgA);
856+
857+
string apple = nameof(apple);
858+
string banana = nameof(banana);
859+
860+
var project2Spec = @"
861+
{
862+
""frameworks"": {
863+
""apple"": {
864+
""framework"": ""net472"",
865+
""targetAlias"": ""apple"",
866+
""dependencies"": {
867+
""pkgA"": {
868+
""version"": ""[1.0.0,)"",
869+
""target"": ""Package"",
870+
}
871+
}
872+
},
873+
""banana"": {
874+
""framework"": ""net472"",
875+
""targetAlias"": ""banana"",
876+
""dependencies"": {
877+
""pkgA"": {
878+
""version"": ""[1.0.0,)"",
879+
""target"": ""Package"",
880+
}
881+
}
882+
}
883+
}
884+
}";
885+
886+
var project1Spec = @"
887+
{
888+
""frameworks"": {
889+
""apple"": {
890+
""framework"": ""net10.0"",
891+
""targetAlias"": ""apple"",
892+
""assetTargetFallback"": true,
893+
""imports"": [ ""net472"" ],
894+
""warn"": true,
895+
""dependencies"": {
896+
}
897+
},
898+
""banana"": {
899+
""framework"": ""net10.0"",
900+
""targetAlias"": ""banana"",
901+
""assetTargetFallback"": true,
902+
""imports"": [ ""net472"" ],
903+
""warn"": true,
904+
""dependencies"": {
905+
}
906+
}
907+
}
908+
}";
909+
910+
var project2 = ProjectTestHelpers.GetPackageSpecWithProjectNameAndSpec("Project2", pathContext.SolutionRoot, project2Spec);
911+
var project1 = ProjectTestHelpers.GetPackageSpecWithProjectNameAndSpec("Project1", pathContext.SolutionRoot, project1Spec);
912+
project1 = project1.WithTestProjectReference(project2);
913+
914+
// Act
915+
var result = await RunRestoreAsync(pathContext, project1, project2);
916+
917+
// Assert - restore should fail overall due to banana
918+
result.Success.Should().BeTrue();
919+
result.LockFile.Targets.Should().HaveCount(2);
920+
921+
// Apple alias should succeed with both the package and its transitive dependency
922+
var appleTarget = result.LockFile.GetTarget(apple, null);
923+
appleTarget.Should().NotBeNull();
924+
appleTarget.Libraries.Should().HaveCount(2);
925+
appleTarget.Libraries.Should().Contain(e => e.Name == pkgA.Id);
926+
// Banana alias should have no compatible assets for either package
927+
var bananaTarget = result.LockFile.GetTarget(banana, null);
928+
bananaTarget.Should().NotBeNull();
929+
bananaTarget.Libraries.Should().HaveCount(2);
930+
bananaTarget.Libraries.Should().Contain(e => e.Name == pkgA.Id);
931+
932+
// Verify log messages
933+
result.LockFile.LogMessages.Should().HaveCount(1);
934+
result.LockFile.LogMessages[0].Level.Should().Be(LogLevel.Warning);
935+
result.LockFile.LogMessages[0].Code.Should().Be(NuGetLogCode.NU1701);
936+
// result.LockFile.LogMessages[0].TargetGraphs.Should().HaveCount(2); https://github.com/NuGet/Home/issues/14815
937+
}
938+
847939
internal static Task<RestoreResult> RunRestoreAsync(SimpleTestPathContext pathContext, params PackageSpec[] projects)
848940
{
849941
return RunRestoreAsync(pathContext, forceEvaluate: false, new TestLogger(), projects);

test/NuGet.Core.Tests/NuGet.Build.Tasks.Test/GetReferenceNearestTargetFrameworkTaskTest.cs

Lines changed: 28 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -575,12 +575,17 @@ public void GetReferenceNearestTargetFrameworkTask_WithInvalidParameters_Errors(
575575
}
576576

577577
[Theory]
578-
[InlineData(".NETCoreApp,Version=v1.0", "", "net46", ".NETFramework,Version=v4.6", "None", "net45")]
579-
[InlineData(".NETCoreApp,Version=v1.0", "", "netcoreapp2.0", ".NETCoreApp,Version=v2.0", "None", "net45")]
580-
[InlineData(".NETCoreApp,Version=v1.0", "", "netcoreapp2.0", ".NETCoreApp,Version=v2.0", "None", "net45;net461")]
581-
[InlineData(".NETCoreApp,Version=v1.0", "", "netcoreapp2.0;net472", ".NETCoreApp,Version=v2.0;.NETFramework,Version=v4.7.2", "None;None", "net45;net461")]
578+
[InlineData(".NETCoreApp,Version=v1.0", "", "netcoreapp1.0", "net46", ".NETFramework,Version=v4.6", "None", "net45")]
579+
[InlineData(".NETCoreApp,Version=v1.0", "", "netcoreapp1.0", "netcoreapp2.0", ".NETCoreApp,Version=v2.0", "None", "net45")]
580+
[InlineData(".NETCoreApp,Version=v1.0", "", "netcoreapp1.0", "netcoreapp2.0", ".NETCoreApp,Version=v2.0", "None", "net45;net461")]
581+
[InlineData(".NETCoreApp,Version=v1.0", "", "netcoreapp1.0", "netcoreapp2.0;net472", ".NETCoreApp,Version=v2.0;.NETFramework,Version=v4.7.2", "None;None", "net45;net461")]
582+
[InlineData(".NETCoreApp,Version=v10.0", null, "conflict", // TFM & TPM & TF of current project
583+
"apple;banana", // TargetFramework of reference project
584+
".NETFramework,Version=v4.8;.NETFramework,Version=v4.8", // TFM of reference project
585+
"None;None", // TPM of reference project
586+
"net48")] // ATF
582587
public void GetReferenceNearestTargetFrameworkTask_WithTargetFrameworkInformation_WithAssetTargetFallback_NoMatch(
583-
string currentProjectTFM, string currentProjectTPM, string refTargetFrameworks, string refTargetFrameworkMonikers, string refTargetPlatformMonikers, string atf)
588+
string currentProjectTFM, string currentProjectTPM, string currentProjectTargetFramework, string refTargetFrameworks, string refTargetFrameworkMonikers, string refTargetPlatformMonikers, string atf)
584589
{
585590
var buildEngine = new TestBuildEngine();
586591
var testLogger = buildEngine.TestLogger;
@@ -598,6 +603,7 @@ public void GetReferenceNearestTargetFrameworkTask_WithTargetFrameworkInformatio
598603
BuildEngine = buildEngine,
599604
CurrentProjectTargetFramework = currentProjectTFM,
600605
CurrentProjectTargetPlatform = currentProjectTPM,
606+
CurrentProjectTargetFrameworkProperty = currentProjectTargetFramework,
601607
FallbackTargetFrameworks = atf.Split(';'),
602608
AnnotatedProjectReferences = references.ToArray()
603609
};
@@ -614,12 +620,23 @@ public void GetReferenceNearestTargetFrameworkTask_WithTargetFrameworkInformatio
614620

615621

616622
[Theory]
617-
[InlineData(".NETCoreApp,Version=v2.0", "", "net45;net46", ".NETFramework,Version=v4.5;.NETFramework,Version=v4.6", "None;None", "net46;net45;net461", "net46")]
618-
[InlineData(".NETCoreApp,Version=v5.0", "Windows,Version=7.0", "net472", ".NETFramework,Version=v4.7.2", "None", "net472;net471;net47;net462;net461;net46;net45", "net472")]
619-
[InlineData(".NETCoreApp,Version=v5.0", "Windows,Version=7.0", "actualResolvedAlias", ".NETFramework,Version=v4.7.2", "None", "net472;net471;net47;net462;net461;net46;net45", "actualResolvedAlias")]
620-
623+
[InlineData(".NETCoreApp,Version=v2.0", "", "netcoreapp2.0", "net45;net46", ".NETFramework,Version=v4.5;.NETFramework,Version=v4.6", "None;None", "net46;net45;net461", "net46")]
624+
[InlineData(".NETCoreApp,Version=v5.0", "Windows,Version=7.0", "net5.0", "net472", ".NETFramework,Version=v4.7.2", "None", "net472;net471;net47;net462;net461;net46;net45", "net472")]
625+
[InlineData(".NETCoreApp,Version=v5.0", "Windows,Version=7.0", "net5.0", "actualResolvedAlias", ".NETFramework,Version=v4.7.2", "None", "net472;net471;net47;net462;net461;net46;net45", "actualResolvedAlias")]
626+
[InlineData(".NETCoreApp,Version=v10.0", null, "apple", // TFM & TPM & TF of current project
627+
"apple;banana", // TargetFramework of reference project
628+
".NETFramework,Version=v4.8;.NETFramework,Version=v4.8", // TFM of reference project
629+
"None;None", // TPM of reference project
630+
"net48;net47", // ATF
631+
"apple")] // Alias to return
632+
[InlineData(".NETCoreApp,Version=v10.0", null, "banana", // TFM & TPM & TF of current project
633+
"apple;banana", // TargetFramework of reference project
634+
".NETFramework,Version=v4.8;.NETFramework,Version=v4.8", // TFM of reference project
635+
"None;None", // TPM of reference project
636+
"net48;net47", // ATF
637+
"banana")] // Alias to return
621638
public void GetReferenceNearestTargetFrameworkTask_WithTargetFrameworkInformation_WhenATFMatches_Warns(
622-
string currentProjectTFM, string currentProjectTPM, string refTargetFrameworks, string refTargetFrameworkMonikers, string refTargetPlatformMonikers, string atf, string expected)
639+
string currentProjectTFM, string currentProjectTPM, string currentProjectTargetFramework, string refTargetFrameworks, string refTargetFrameworkMonikers, string refTargetPlatformMonikers, string atf, string expected)
623640
{
624641
var buildEngine = new TestBuildEngine();
625642
var testLogger = buildEngine.TestLogger;
@@ -637,6 +654,7 @@ public void GetReferenceNearestTargetFrameworkTask_WithTargetFrameworkInformatio
637654
BuildEngine = buildEngine,
638655
CurrentProjectTargetFramework = currentProjectTFM,
639656
CurrentProjectTargetPlatform = currentProjectTPM,
657+
CurrentProjectTargetFrameworkProperty = currentProjectTargetFramework,
640658
FallbackTargetFrameworks = atf.Split(';'),
641659
AnnotatedProjectReferences = references.ToArray()
642660
};

0 commit comments

Comments
 (0)