From 63890e06e924727dab0b91f1a4f25d8ed0730508 Mon Sep 17 00:00:00 2001 From: Sven Boemer Date: Thu, 25 Jun 2026 12:09:13 -0700 Subject: [PATCH 1/2] Skip NU1703 for empty MonoAndroid assets Avoid emitting the MonoAndroid deprecation warning when restore selects only _._ placeholder assets from a package. Keep warning behavior for packages that contribute real MonoAndroid compile or runtime assets. Assisted-by: GitHub Copilot CLI:gpt-5.5 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../RestoreCommand/LockFileBuilder.cs | 7 ++-- .../RestoreCommand/MonoAndroidDeprecation.cs | 32 +++++++++++++++++++ .../MonoAndroidDeprecationTests.cs | 24 ++++++++++++++ 3 files changed, 61 insertions(+), 2 deletions(-) diff --git a/src/NuGet.Core/NuGet.Commands/RestoreCommand/LockFileBuilder.cs b/src/NuGet.Core/NuGet.Commands/RestoreCommand/LockFileBuilder.cs index 80572729569..2af263f55da 100644 --- a/src/NuGet.Core/NuGet.Commands/RestoreCommand/LockFileBuilder.cs +++ b/src/NuGet.Core/NuGet.Commands/RestoreCommand/LockFileBuilder.cs @@ -288,8 +288,11 @@ public LockFile CreateLockFile(LockFile previousLockFile, // Log NU1703 warning if the package uses the deprecated MonoAndroid framework if (checkMonoAndroidDeprecation && !librariesWithMonoAndroidWarnings.Contains(library) - && (MonoAndroidDeprecation.IsMonoAndroidFramework(compileAssetFramework) - || MonoAndroidDeprecation.IsMonoAndroidFramework(runtimeAssetFramework))) + && MonoAndroidDeprecation.ShouldWarn( + compileAssetFramework, + targetLibrary.CompileTimeAssemblies, + runtimeAssetFramework, + targetLibrary.RuntimeAssemblies)) { var message = string.Format(CultureInfo.CurrentCulture, Strings.Warning_MonoAndroidFrameworkDeprecated, diff --git a/src/NuGet.Core/NuGet.Commands/RestoreCommand/MonoAndroidDeprecation.cs b/src/NuGet.Core/NuGet.Commands/RestoreCommand/MonoAndroidDeprecation.cs index 4bbd0b0a61c..578fc3b9a93 100644 --- a/src/NuGet.Core/NuGet.Commands/RestoreCommand/MonoAndroidDeprecation.cs +++ b/src/NuGet.Core/NuGet.Commands/RestoreCommand/MonoAndroidDeprecation.cs @@ -2,7 +2,10 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.Collections.Generic; +using System.Linq; using NuGet.Frameworks; +using NuGet.Packaging.Core; using NuGet.ProjectModel; namespace NuGet.Commands @@ -54,5 +57,34 @@ internal static bool IsMonoAndroidFramework(NuGetFramework framework) framework.Framework, FrameworkConstants.FrameworkIdentifiers.MonoAndroid); } + + /// + /// Determines whether selected MonoAndroid assets should produce a deprecation warning. + /// + /// The framework selected for compile assets. + /// The selected compile assets. + /// The framework selected for runtime assets. + /// The selected runtime assets. + /// True when a package contributes non-placeholder MonoAndroid compile or runtime assets. + internal static bool ShouldWarn( + NuGetFramework compileAssetFramework, + IEnumerable compileTimeAssemblies, + NuGetFramework runtimeAssetFramework, + IEnumerable runtimeAssemblies) + { + return HasNonEmptyMonoAndroidAssets(compileAssetFramework, compileTimeAssemblies) + || HasNonEmptyMonoAndroidAssets(runtimeAssetFramework, runtimeAssemblies); + } + + private static bool HasNonEmptyMonoAndroidAssets(NuGetFramework framework, IEnumerable assets) + { + return IsMonoAndroidFramework(framework) + && assets?.Any(asset => !IsEmptyFolder(asset.Path)) == true; + } + + private static bool IsEmptyFolder(string path) + { + return path.EndsWith(PackagingCoreConstants.ForwardSlashEmptyFolder, StringComparison.Ordinal); + } } } diff --git a/test/NuGet.Core.Tests/NuGet.Commands.Test/RestoreCommandTests/MonoAndroidDeprecationTests.cs b/test/NuGet.Core.Tests/NuGet.Commands.Test/RestoreCommandTests/MonoAndroidDeprecationTests.cs index aea50ceabbf..e2d4041a643 100644 --- a/test/NuGet.Core.Tests/NuGet.Commands.Test/RestoreCommandTests/MonoAndroidDeprecationTests.cs +++ b/test/NuGet.Core.Tests/NuGet.Commands.Test/RestoreCommandTests/MonoAndroidDeprecationTests.cs @@ -119,6 +119,30 @@ public void IsMonoAndroidFramework_Null_ReturnsFalse() #endregion + #region ShouldWarn tests + + [Fact] + public void ShouldWarn_MonoAndroidWithOnlyEmptyFolderPlaceholders_ReturnsFalse() + { + var monoAndroid = NuGetFramework.Parse("monoandroid10.0"); + var compileItems = new[] + { + new LockFileItem("ref/MonoAndroid10/_._") + }; + var runtimeItems = new[] + { + new LockFileItem("lib/MonoAndroid10/_._") + }; + + MonoAndroidDeprecation.ShouldWarn( + monoAndroid, + compileItems, + monoAndroid, + runtimeItems).Should().BeFalse(); + } + + #endregion + #region Integration tests [Fact] From b0142356dbe920fe862fc0857c26378fedb19768 Mon Sep 17 00:00:00 2001 From: Sven Boemer Date: Thu, 25 Jun 2026 13:32:40 -0700 Subject: [PATCH 2/2] Address NU1703 empty asset review feedback Remove the unnecessary null-conditional when checking selected MonoAndroid assets; restore passes non-null asset collections. Assisted-by: GitHub Copilot CLI:gpt-5.5 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../NuGet.Commands/RestoreCommand/MonoAndroidDeprecation.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/NuGet.Core/NuGet.Commands/RestoreCommand/MonoAndroidDeprecation.cs b/src/NuGet.Core/NuGet.Commands/RestoreCommand/MonoAndroidDeprecation.cs index 578fc3b9a93..22d0ae2bf3d 100644 --- a/src/NuGet.Core/NuGet.Commands/RestoreCommand/MonoAndroidDeprecation.cs +++ b/src/NuGet.Core/NuGet.Commands/RestoreCommand/MonoAndroidDeprecation.cs @@ -79,7 +79,7 @@ internal static bool ShouldWarn( private static bool HasNonEmptyMonoAndroidAssets(NuGetFramework framework, IEnumerable assets) { return IsMonoAndroidFramework(framework) - && assets?.Any(asset => !IsEmptyFolder(asset.Path)) == true; + && assets.Any(asset => !IsEmptyFolder(asset.Path)); } private static bool IsEmptyFolder(string path)