Skip to content

Commit a553524

Browse files
authored
Handle missing TargetFramework in nomination (#7196)
1 parent ab7d0d6 commit a553524

3 files changed

Lines changed: 98 additions & 4 deletions

File tree

src/NuGet.Clients/NuGet.SolutionRestoreManager/VSNominationUtilities.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ internal static TargetFrameworkInformation ToTargetFrameworkInformation(
158158
FrameworkReferences = frameworkReferences,
159159
Imports = imports,
160160
RuntimeIdentifierGraphPath = GetPropertyValueOrNull(targetFrameworkInfo.Properties, ProjectBuildProperties.RuntimeIdentifierGraphPath),
161-
TargetAlias = GetPropertyValueOrNull(targetFrameworkInfo.Properties, ProjectBuildProperties.TargetFramework),
161+
TargetAlias = GetPropertyValueOrNull(targetFrameworkInfo.Properties, ProjectBuildProperties.TargetFramework) ?? string.Empty,
162162
Warn = warn,
163163
PackagesToPrune = packagesToPrune,
164164
};
@@ -191,7 +191,7 @@ internal static ProjectRestoreMetadataFrameworkInfo ToProjectRestoreMetadataFram
191191
var tfi = new ProjectRestoreMetadataFrameworkInfo
192192
{
193193
FrameworkName = GetTargetFramework(targetFrameworkInfo.Properties, projectFullPath),
194-
TargetAlias = GetPropertyValueOrNull(targetFrameworkInfo.Properties, ProjectBuildProperties.TargetFramework)
194+
TargetAlias = GetPropertyValueOrNull(targetFrameworkInfo.Properties, ProjectBuildProperties.TargetFramework) ?? string.Empty,
195195
};
196196

197197
if (targetFrameworkInfo.Items?.TryGetValue(ProjectItems.ProjectReference, out var projectReferences) ?? false)

test/NuGet.Clients.Tests/NuGet.SolutionRestoreManager.Test/TestProjectRestoreInfoBuilder.cs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ internal class TestProjectRestoreInfoBuilder
1414
{
1515
List<IVsTargetFrameworkInfo4> _targetFrameworks = new();
1616
List<VsReferenceItem2>? _toolReferences = null;
17+
bool _useTargetFrameworks;
1718

1819
public IVsProjectRestoreInfo3 Build()
1920
{
@@ -22,7 +23,7 @@ public IVsProjectRestoreInfo3 Build()
2223
throw new InvalidOperationException("At least one target framework must be added before building the project restore info.");
2324
}
2425

25-
var originalTargetFrameworks = string.Join(";", _targetFrameworks.Select(tf => tf.Properties[ProjectBuildProperties.TargetFramework]));
26+
var originalTargetFrameworks = (_useTargetFrameworks || _targetFrameworks.Count > 1) ? string.Join(";", _targetFrameworks.Select(tf => tf.Properties[ProjectBuildProperties.TargetFramework])) : null;
2627

2728
var pri = new VsProjectRestoreInfo3
2829
{
@@ -34,6 +35,11 @@ public IVsProjectRestoreInfo3 Build()
3435
return pri;
3536
}
3637

38+
public void WithTargetFrameworksProperty()
39+
{
40+
_useTargetFrameworks = true;
41+
}
42+
3743
public TestProjectRestoreInfoBuilder WithTargetFrameworkInfo(
3844
string targetFramework,
3945
Action<TargetFrameworkBuilder>? builder = null)
@@ -118,7 +124,7 @@ internal class TargetFrameworkBuilder
118124

119125
public TargetFrameworkBuilder WithProperty(string key, string value)
120126
{
121-
if (string.IsNullOrEmpty(key))
127+
if (string.IsNullOrEmpty(value))
122128
{
123129
Properties.Remove(key);
124130
}

test/NuGet.Clients.Tests/NuGet.SolutionRestoreManager.Test/VsSolutionRestoreServiceTests.cs

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,7 @@ public async Task NominateProjectAsync_CrossTargeting(string targetFrameworks)
255255
{
256256
builder.WithTargetFrameworkInfo(targetFramework);
257257
}
258+
builder.WithTargetFrameworksProperty();
258259

259260
var projectRestoreInfo = builder.Build();
260261

@@ -1821,6 +1822,93 @@ public void ToPackageSpec_WithPrunePackageReference_AccountsForDefaults()
18211822
resultB.Value.VersionRange.Should().Be(VersionRange.Parse("(, 1.0.0]"));
18221823
}
18231824

1825+
[Fact]
1826+
public async Task NominateProjectAsync_SimulatedCPPProject_WithMissingTargetFramework_AliasRemainsEmpty()
1827+
{
1828+
var projectRestoreInfo = new TestProjectRestoreInfoBuilder()
1829+
.WithTargetFrameworkInfo(CommonFrameworks.Native.GetShortFolderName(), builder =>
1830+
{
1831+
builder
1832+
.WithProperty(ProjectBuildProperties.MSBuildProjectExtensionsPath, @"y:\src\some\project\obj")
1833+
.WithProperty("MSBuildProjectFullPath", @"y:\src\some\project\project.vcxproj")
1834+
.WithProperty("TargetFrameworkIdentifier", "NETFramework")
1835+
.WithProperty("TargetFrameworkMoniker", ".NETFramework,Version=v4.8")
1836+
.WithProperty("UsingMicrosoftNETSdk", "false")
1837+
.WithProperty("TargetFramework", null!);
1838+
})
1839+
.Build();
1840+
// Act
1841+
var actualRestoreSpec = await CaptureNominateResultAsync(projectRestoreInfo);
1842+
1843+
// Assert
1844+
SpecValidationUtility.ValidateDependencySpec(actualRestoreSpec);
1845+
1846+
var actualProjectSpec = actualRestoreSpec.Projects.Single();
1847+
Assert.Equal("1.0.0", actualProjectSpec.Version.ToString());
1848+
1849+
var actualMetadata = actualProjectSpec.RestoreMetadata;
1850+
Assert.NotNull(actualMetadata);
1851+
Assert.Equal(ProjectStyle.PackageReference, actualMetadata.ProjectStyle);
1852+
1853+
Assert.Single(actualProjectSpec.TargetFrameworks);
1854+
var actualTfi = actualProjectSpec.TargetFrameworks.Single();
1855+
1856+
var expectedFramework = CommonFrameworks.Native;
1857+
Assert.Equal(expectedFramework, actualTfi.FrameworkName);
1858+
Assert.Equal(string.Empty, actualTfi.TargetAlias);
1859+
1860+
Assert.Single(actualProjectSpec.RestoreMetadata.TargetFrameworks);
1861+
var actualPRMFI = actualProjectSpec.RestoreMetadata.TargetFrameworks.Single();
1862+
Assert.Equal(expectedFramework, actualPRMFI.FrameworkName);
1863+
Assert.Equal(string.Empty, actualPRMFI.TargetAlias);
1864+
}
1865+
1866+
[Fact]
1867+
public async Task NominateProjectAsync_SimulatedCPPProject_WithMissingTargetFrameworkAndAssetTargetFallback_AliasRemainsEmpty()
1868+
{
1869+
var projectRestoreInfo = new TestProjectRestoreInfoBuilder()
1870+
.WithTargetFrameworkInfo(CommonFrameworks.Native.GetShortFolderName(), builder =>
1871+
{
1872+
builder
1873+
.WithProperty(ProjectBuildProperties.MSBuildProjectExtensionsPath, @"y:\src\some\project\obj")
1874+
.WithProperty("MSBuildProjectFullPath", @"y:\src\some\project\project.vcxproj")
1875+
.WithProperty("TargetFrameworkIdentifier", "NETFramework")
1876+
.WithProperty("TargetFrameworkMoniker", ".NETFramework,Version=v4.8")
1877+
.WithProperty("UsingMicrosoftNETSdk", "false")
1878+
.WithProperty("TargetFramework", null!)
1879+
.WithProperty("AssetTargetFallback", "net48");
1880+
})
1881+
.Build();
1882+
// Act
1883+
var actualRestoreSpec = await CaptureNominateResultAsync(projectRestoreInfo);
1884+
1885+
// Assert
1886+
SpecValidationUtility.ValidateDependencySpec(actualRestoreSpec);
1887+
1888+
var actualProjectSpec = actualRestoreSpec.Projects.Single();
1889+
Assert.Equal("1.0.0", actualProjectSpec.Version.ToString());
1890+
1891+
var actualMetadata = actualProjectSpec.RestoreMetadata;
1892+
Assert.NotNull(actualMetadata);
1893+
Assert.Equal(ProjectStyle.PackageReference, actualMetadata.ProjectStyle);
1894+
1895+
Assert.Single(actualProjectSpec.TargetFrameworks);
1896+
var actualTfi = actualProjectSpec.TargetFrameworks.Single();
1897+
1898+
var expectedFramework = CommonFrameworks.Native;
1899+
Assert.Equal(expectedFramework, actualTfi.FrameworkName);
1900+
Assert.Equal(string.Empty, actualTfi.TargetAlias);
1901+
Assert.IsType<AssetTargetFallbackFramework>(actualTfi.FrameworkName);
1902+
var assetTargetFallback = (AssetTargetFallbackFramework)actualTfi.FrameworkName;
1903+
Assert.Equal(expectedFramework, assetTargetFallback.RootFramework);
1904+
Assert.Equal([CommonFrameworks.Net48], assetTargetFallback.Fallback);
1905+
1906+
Assert.Single(actualProjectSpec.RestoreMetadata.TargetFrameworks);
1907+
var actualPRMFI = actualProjectSpec.RestoreMetadata.TargetFrameworks.Single();
1908+
Assert.Equal(expectedFramework, actualPRMFI.FrameworkName);
1909+
Assert.Equal(string.Empty, actualPRMFI.TargetAlias);
1910+
}
1911+
18241912
private async Task<DependencyGraphSpec> CaptureNominateResultAsync(
18251913
IVsProjectRestoreInfo3 pri,
18261914
Mock<IProjectSystemCache>? cache = null)

0 commit comments

Comments
 (0)