From 3bb1196c91c04130fe3b16875abbe97975f7db33 Mon Sep 17 00:00:00 2001 From: Nikolche Kolev Date: Wed, 15 Apr 2026 13:58:29 -0700 Subject: [PATCH 1/6] NuGet.Protocol nullability v2 --- .../NuGet.Protocol/HttpSourceCacheContext.cs | 6 +- .../NuGet.Protocol/NullSourceCacheContext.cs | 8 +- .../NuGet.Protocol/PackageDownloadContext.cs | 14 ++-- .../PublicAPI/net472/PublicAPI.Shipped.txt | 84 +++++++++---------- .../PublicAPI/net8.0/PublicAPI.Shipped.txt | 84 +++++++++---------- .../RemoteSourceDependencyInfo.cs | 11 ++- .../NuGet.Protocol/SourceCacheContext.cs | 11 ++- .../SourcePackageDependencyInfo.cs | 22 +++-- src/NuGet.Core/NuGet.Protocol/UserAgent.cs | 2 - .../NuGet.Protocol/UserAgentStringBuilder.cs | 10 +-- 10 files changed, 121 insertions(+), 131 deletions(-) diff --git a/src/NuGet.Core/NuGet.Protocol/HttpSourceCacheContext.cs b/src/NuGet.Core/NuGet.Protocol/HttpSourceCacheContext.cs index 97fb1f4ab23..9bb9c2cc6b1 100644 --- a/src/NuGet.Core/NuGet.Protocol/HttpSourceCacheContext.cs +++ b/src/NuGet.Core/NuGet.Protocol/HttpSourceCacheContext.cs @@ -1,8 +1,6 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -#nullable disable - using System; using System.Diagnostics; @@ -10,7 +8,7 @@ namespace NuGet.Protocol.Core.Types { public class HttpSourceCacheContext { - private HttpSourceCacheContext(string rootTempFolder, TimeSpan maxAge, bool directDownload, SourceCacheContext cacheContext) + private HttpSourceCacheContext(string? rootTempFolder, TimeSpan maxAge, bool directDownload, SourceCacheContext cacheContext) { if (maxAge <= TimeSpan.Zero) { @@ -40,7 +38,7 @@ private HttpSourceCacheContext(string rootTempFolder, TimeSpan maxAge, bool dire /// A suggested root folder to drop temporary files under, it will get cleared by the /// disposal of the that was used to create this instance. /// - public string RootTempFolder { get; } + public string? RootTempFolder { get; } /// /// Inner cache context. diff --git a/src/NuGet.Core/NuGet.Protocol/NullSourceCacheContext.cs b/src/NuGet.Core/NuGet.Protocol/NullSourceCacheContext.cs index 280adade61f..40e3de1378c 100644 --- a/src/NuGet.Core/NuGet.Protocol/NullSourceCacheContext.cs +++ b/src/NuGet.Core/NuGet.Protocol/NullSourceCacheContext.cs @@ -1,10 +1,8 @@ -#nullable disable - namespace NuGet.Protocol.Core.Types { public class NullSourceCacheContext : SourceCacheContext { - private static SourceCacheContext _instance; + private static SourceCacheContext? _instance; public static SourceCacheContext Instance { @@ -28,8 +26,8 @@ public override string GeneratedTempFolder } } - public override SourceCacheContext WithRefreshCacheTrue() { return _instance; } + public override SourceCacheContext WithRefreshCacheTrue() { return Instance; } - public override SourceCacheContext Clone() { return _instance; } + public override SourceCacheContext Clone() { return Instance; } } } diff --git a/src/NuGet.Core/NuGet.Protocol/PackageDownloadContext.cs b/src/NuGet.Core/NuGet.Protocol/PackageDownloadContext.cs index bff25b24e37..59590c0c8d8 100644 --- a/src/NuGet.Core/NuGet.Protocol/PackageDownloadContext.cs +++ b/src/NuGet.Core/NuGet.Protocol/PackageDownloadContext.cs @@ -1,8 +1,6 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -#nullable disable - using System; using NuGet.Configuration; using NuGet.Packaging.Signing; @@ -21,7 +19,7 @@ public PackageDownloadContext(SourceCacheContext sourceCacheContext) : this( public PackageDownloadContext( SourceCacheContext sourceCacheContext, - string directDownloadDirectory, + string? directDownloadDirectory, bool directDownload) { if (sourceCacheContext == null) @@ -43,9 +41,9 @@ public PackageDownloadContext( public PackageDownloadContext( SourceCacheContext sourceCacheContext, - string directDownloadDirectory, + string? directDownloadDirectory, bool directDownload, - PackageSourceMapping packageSourceMappingConfiguration) : this( + PackageSourceMapping? packageSourceMappingConfiguration) : this( sourceCacheContext, directDownloadDirectory, directDownload) @@ -55,11 +53,11 @@ public PackageDownloadContext( public SourceCacheContext SourceCacheContext { get; } public bool DirectDownload { get; } - public string DirectDownloadDirectory { get; } + public string? DirectDownloadDirectory { get; } public Guid ParentId { get; set; } - public ClientPolicyContext ClientPolicyContext { get; set; } - public PackageSourceMapping PackageSourceMapping { get; } + public ClientPolicyContext? ClientPolicyContext { get; set; } + public PackageSourceMapping? PackageSourceMapping { get; } } } diff --git a/src/NuGet.Core/NuGet.Protocol/PublicAPI/net472/PublicAPI.Shipped.txt b/src/NuGet.Core/NuGet.Protocol/PublicAPI/net472/PublicAPI.Shipped.txt index 1bd269ca3f7..ea7a6b20f82 100644 --- a/src/NuGet.Core/NuGet.Protocol/PublicAPI/net472/PublicAPI.Shipped.txt +++ b/src/NuGet.Core/NuGet.Protocol/PublicAPI/net472/PublicAPI.Shipped.txt @@ -65,8 +65,8 @@ NuGet.Protocol.Core.Types.HttpHandlerResource.HttpHandlerResource() -> void NuGet.Protocol.Core.Types.HttpSourceCacheContext NuGet.Protocol.Core.Types.HttpSourceCacheContext.DirectDownload.get -> bool NuGet.Protocol.Core.Types.HttpSourceCacheContext.MaxAge.get -> System.TimeSpan -~NuGet.Protocol.Core.Types.HttpSourceCacheContext.RootTempFolder.get -> string -~NuGet.Protocol.Core.Types.HttpSourceCacheContext.SourceCacheContext.get -> NuGet.Protocol.Core.Types.SourceCacheContext +NuGet.Protocol.Core.Types.HttpSourceCacheContext.RootTempFolder.get -> string? +NuGet.Protocol.Core.Types.HttpSourceCacheContext.SourceCacheContext.get -> NuGet.Protocol.Core.Types.SourceCacheContext! NuGet.Protocol.Core.Types.ILegacyFeedCapabilityResource NuGet.Protocol.Core.Types.ILegacyFeedCapabilityResource.SupportsIsAbsoluteLatestVersionAsync(NuGet.Common.ILogger! log, System.Threading.CancellationToken token) -> System.Threading.Tasks.Task! NuGet.Protocol.Core.Types.ILegacyFeedCapabilityResource.SupportsSearchAsync(NuGet.Common.ILogger! log, System.Threading.CancellationToken token) -> System.Threading.Tasks.Task! @@ -138,17 +138,17 @@ NuGet.Protocol.Core.Types.OfflineFeedAddContext.ThrowIfPackageExistsAndInvalid.g NuGet.Protocol.Core.Types.OfflineFeedAddContext.ThrowIfSourcePackageIsInvalid.get -> bool NuGet.Protocol.Core.Types.OfflineFeedUtility NuGet.Protocol.Core.Types.PackageDownloadContext -~NuGet.Protocol.Core.Types.PackageDownloadContext.ClientPolicyContext.get -> NuGet.Packaging.Signing.ClientPolicyContext -~NuGet.Protocol.Core.Types.PackageDownloadContext.ClientPolicyContext.set -> void +NuGet.Protocol.Core.Types.PackageDownloadContext.ClientPolicyContext.get -> NuGet.Packaging.Signing.ClientPolicyContext? +NuGet.Protocol.Core.Types.PackageDownloadContext.ClientPolicyContext.set -> void NuGet.Protocol.Core.Types.PackageDownloadContext.DirectDownload.get -> bool -~NuGet.Protocol.Core.Types.PackageDownloadContext.DirectDownloadDirectory.get -> string -~NuGet.Protocol.Core.Types.PackageDownloadContext.PackageDownloadContext(NuGet.Protocol.Core.Types.SourceCacheContext sourceCacheContext) -> void -~NuGet.Protocol.Core.Types.PackageDownloadContext.PackageDownloadContext(NuGet.Protocol.Core.Types.SourceCacheContext sourceCacheContext, string directDownloadDirectory, bool directDownload) -> void -~NuGet.Protocol.Core.Types.PackageDownloadContext.PackageDownloadContext(NuGet.Protocol.Core.Types.SourceCacheContext sourceCacheContext, string directDownloadDirectory, bool directDownload, NuGet.Configuration.PackageSourceMapping packageSourceMappingConfiguration) -> void -~NuGet.Protocol.Core.Types.PackageDownloadContext.PackageSourceMapping.get -> NuGet.Configuration.PackageSourceMapping +NuGet.Protocol.Core.Types.PackageDownloadContext.DirectDownloadDirectory.get -> string? +NuGet.Protocol.Core.Types.PackageDownloadContext.PackageDownloadContext(NuGet.Protocol.Core.Types.SourceCacheContext! sourceCacheContext) -> void +NuGet.Protocol.Core.Types.PackageDownloadContext.PackageDownloadContext(NuGet.Protocol.Core.Types.SourceCacheContext! sourceCacheContext, string? directDownloadDirectory, bool directDownload) -> void +NuGet.Protocol.Core.Types.PackageDownloadContext.PackageDownloadContext(NuGet.Protocol.Core.Types.SourceCacheContext! sourceCacheContext, string? directDownloadDirectory, bool directDownload, NuGet.Configuration.PackageSourceMapping? packageSourceMappingConfiguration) -> void +NuGet.Protocol.Core.Types.PackageDownloadContext.PackageSourceMapping.get -> NuGet.Configuration.PackageSourceMapping? NuGet.Protocol.Core.Types.PackageDownloadContext.ParentId.get -> System.Guid NuGet.Protocol.Core.Types.PackageDownloadContext.ParentId.set -> void -~NuGet.Protocol.Core.Types.PackageDownloadContext.SourceCacheContext.get -> NuGet.Protocol.Core.Types.SourceCacheContext +NuGet.Protocol.Core.Types.PackageDownloadContext.SourceCacheContext.get -> NuGet.Protocol.Core.Types.SourceCacheContext! NuGet.Protocol.Core.Types.PackageMetadataResource NuGet.Protocol.Core.Types.PackageMetadataResource.PackageMetadataResource() -> void NuGet.Protocol.Core.Types.PackageProgressEventArgs @@ -241,13 +241,13 @@ NuGet.Protocol.Core.Types.PluginResourceProvider NuGet.Protocol.Core.Types.PluginResourceProvider.PluginResourceProvider() -> void ~NuGet.Protocol.Core.Types.PluginResourceProvider.PluginResourceProvider(NuGet.Protocol.Plugins.IPluginManager pluginManager) -> void NuGet.Protocol.Core.Types.RemoteSourceDependencyInfo -~NuGet.Protocol.Core.Types.RemoteSourceDependencyInfo.ContentUri.get -> string -~NuGet.Protocol.Core.Types.RemoteSourceDependencyInfo.ContentUri.set -> void -~NuGet.Protocol.Core.Types.RemoteSourceDependencyInfo.DependencyGroups.get -> System.Collections.Generic.IEnumerable -~NuGet.Protocol.Core.Types.RemoteSourceDependencyInfo.Equals(NuGet.Protocol.Core.Types.RemoteSourceDependencyInfo other) -> bool -~NuGet.Protocol.Core.Types.RemoteSourceDependencyInfo.Identity.get -> NuGet.Packaging.Core.PackageIdentity +NuGet.Protocol.Core.Types.RemoteSourceDependencyInfo.ContentUri.get -> string! +NuGet.Protocol.Core.Types.RemoteSourceDependencyInfo.ContentUri.set -> void +NuGet.Protocol.Core.Types.RemoteSourceDependencyInfo.DependencyGroups.get -> System.Collections.Generic.IEnumerable! +NuGet.Protocol.Core.Types.RemoteSourceDependencyInfo.Equals(NuGet.Protocol.Core.Types.RemoteSourceDependencyInfo? other) -> bool +NuGet.Protocol.Core.Types.RemoteSourceDependencyInfo.Identity.get -> NuGet.Packaging.Core.PackageIdentity! NuGet.Protocol.Core.Types.RemoteSourceDependencyInfo.Listed.get -> bool -~NuGet.Protocol.Core.Types.RemoteSourceDependencyInfo.RemoteSourceDependencyInfo(NuGet.Packaging.Core.PackageIdentity identity, bool listed, System.Collections.Generic.IEnumerable dependencyGroups, string contentUri) -> void +NuGet.Protocol.Core.Types.RemoteSourceDependencyInfo.RemoteSourceDependencyInfo(NuGet.Packaging.Core.PackageIdentity! identity, bool listed, System.Collections.Generic.IEnumerable! dependencyGroups, string! contentUri) -> void NuGet.Protocol.Core.Types.Repository NuGet.Protocol.Core.Types.Repository.ProviderFactory NuGet.Protocol.Core.Types.Repository.ProviderFactory.ProviderFactory() -> void @@ -297,13 +297,13 @@ NuGet.Protocol.Core.Types.SourceCacheContext.SessionId.get -> System.Guid NuGet.Protocol.Core.Types.SourceCacheContext.SessionId.set -> void NuGet.Protocol.Core.Types.SourceCacheContext.SourceCacheContext() -> void NuGet.Protocol.Core.Types.SourcePackageDependencyInfo -~NuGet.Protocol.Core.Types.SourcePackageDependencyInfo.DownloadUri.get -> System.Uri +NuGet.Protocol.Core.Types.SourcePackageDependencyInfo.DownloadUri.get -> System.Uri? NuGet.Protocol.Core.Types.SourcePackageDependencyInfo.Listed.get -> bool -~NuGet.Protocol.Core.Types.SourcePackageDependencyInfo.PackageHash.get -> string -~NuGet.Protocol.Core.Types.SourcePackageDependencyInfo.Source.get -> NuGet.Protocol.Core.Types.SourceRepository -~NuGet.Protocol.Core.Types.SourcePackageDependencyInfo.SourcePackageDependencyInfo(NuGet.Packaging.Core.PackageIdentity identity, System.Collections.Generic.IEnumerable dependencies, bool listed, NuGet.Protocol.Core.Types.SourceRepository source, System.Uri downloadUri, string packageHash) -> void -~NuGet.Protocol.Core.Types.SourcePackageDependencyInfo.SourcePackageDependencyInfo(string id, NuGet.Versioning.NuGetVersion version, System.Collections.Generic.IEnumerable dependencies, bool listed, NuGet.Protocol.Core.Types.SourceRepository source) -> void -~NuGet.Protocol.Core.Types.SourcePackageDependencyInfo.SourcePackageDependencyInfo(string id, NuGet.Versioning.NuGetVersion version, System.Collections.Generic.IEnumerable dependencies, bool listed, NuGet.Protocol.Core.Types.SourceRepository source, System.Uri downloadUri, string packageHash) -> void +NuGet.Protocol.Core.Types.SourcePackageDependencyInfo.PackageHash.get -> string? +NuGet.Protocol.Core.Types.SourcePackageDependencyInfo.Source.get -> NuGet.Protocol.Core.Types.SourceRepository? +NuGet.Protocol.Core.Types.SourcePackageDependencyInfo.SourcePackageDependencyInfo(NuGet.Packaging.Core.PackageIdentity! identity, System.Collections.Generic.IEnumerable! dependencies, bool listed, NuGet.Protocol.Core.Types.SourceRepository? source, System.Uri? downloadUri, string? packageHash) -> void +NuGet.Protocol.Core.Types.SourcePackageDependencyInfo.SourcePackageDependencyInfo(string! id, NuGet.Versioning.NuGetVersion! version, System.Collections.Generic.IEnumerable! dependencies, bool listed, NuGet.Protocol.Core.Types.SourceRepository? source) -> void +NuGet.Protocol.Core.Types.SourcePackageDependencyInfo.SourcePackageDependencyInfo(string! id, NuGet.Versioning.NuGetVersion! version, System.Collections.Generic.IEnumerable! dependencies, bool listed, NuGet.Protocol.Core.Types.SourceRepository? source, System.Uri? downloadUri, string? packageHash) -> void NuGet.Protocol.Core.Types.SourceRepository NuGet.Protocol.Core.Types.SourceRepository.FeedTypeOverride.get -> NuGet.Protocol.FeedType NuGet.Protocol.Core.Types.SourceRepository.SourceRepository() -> void @@ -322,11 +322,11 @@ NuGet.Protocol.Core.Types.SymbolPackageUpdateResourceV3 ~NuGet.Protocol.Core.Types.SymbolPackageUpdateResourceV3.SymbolPackageUpdateResourceV3(string source, NuGet.Protocol.HttpSource httpSource) -> void NuGet.Protocol.Core.Types.UserAgent NuGet.Protocol.Core.Types.UserAgentStringBuilder -~NuGet.Protocol.Core.Types.UserAgentStringBuilder.Build() -> string -~NuGet.Protocol.Core.Types.UserAgentStringBuilder.NuGetClientVersion.get -> string +NuGet.Protocol.Core.Types.UserAgentStringBuilder.Build() -> string! +NuGet.Protocol.Core.Types.UserAgentStringBuilder.NuGetClientVersion.get -> string! NuGet.Protocol.Core.Types.UserAgentStringBuilder.UserAgentStringBuilder() -> void -~NuGet.Protocol.Core.Types.UserAgentStringBuilder.UserAgentStringBuilder(string clientName) -> void -~NuGet.Protocol.Core.Types.UserAgentStringBuilder.WithVisualStudioSKU(string vsInfo) -> NuGet.Protocol.Core.Types.UserAgentStringBuilder +NuGet.Protocol.Core.Types.UserAgentStringBuilder.UserAgentStringBuilder(string! clientName) -> void +NuGet.Protocol.Core.Types.UserAgentStringBuilder.WithVisualStudioSKU(string? vsInfo) -> NuGet.Protocol.Core.Types.UserAgentStringBuilder! NuGet.Protocol.Core.Types.VersionInfo NuGet.Protocol.Core.Types.VersionInfo.DownloadCount.get -> long? NuGet.Protocol.Core.Types.VersionInfo.PackageSearchMetadata.get -> NuGet.Protocol.Core.Types.IPackageSearchMetadata? @@ -1637,18 +1637,18 @@ const NuGet.Protocol.JsonExtensions.JsonSerializationMaxDepth = 512 -> int ~override NuGet.Protocol.AutoCompleteResourceV3.IdStartsWith(string packageIdPrefix, bool includePrerelease, NuGet.Common.ILogger log, System.Threading.CancellationToken token) -> System.Threading.Tasks.Task> ~override NuGet.Protocol.AutoCompleteResourceV3.VersionStartsWith(string packageId, string versionPrefix, bool includePrerelease, NuGet.Protocol.Core.Types.SourceCacheContext sourceCacheContext, NuGet.Common.ILogger log, System.Threading.CancellationToken token) -> System.Threading.Tasks.Task> ~override NuGet.Protocol.AutoCompleteResourceV3Provider.TryCreate(NuGet.Protocol.Core.Types.SourceRepository source, System.Threading.CancellationToken token) -> System.Threading.Tasks.Task> -~override NuGet.Protocol.Core.Types.NullSourceCacheContext.Clone() -> NuGet.Protocol.Core.Types.SourceCacheContext -~override NuGet.Protocol.Core.Types.NullSourceCacheContext.GeneratedTempFolder.get -> string -~override NuGet.Protocol.Core.Types.NullSourceCacheContext.WithRefreshCacheTrue() -> NuGet.Protocol.Core.Types.SourceCacheContext +override NuGet.Protocol.Core.Types.NullSourceCacheContext.Clone() -> NuGet.Protocol.Core.Types.SourceCacheContext! +override NuGet.Protocol.Core.Types.NullSourceCacheContext.GeneratedTempFolder.get -> string! +override NuGet.Protocol.Core.Types.NullSourceCacheContext.WithRefreshCacheTrue() -> NuGet.Protocol.Core.Types.SourceCacheContext! ~override NuGet.Protocol.Core.Types.PluginFindPackageByIdResource.CopyNupkgToStreamAsync(string id, NuGet.Versioning.NuGetVersion version, System.IO.Stream destination, NuGet.Protocol.Core.Types.SourceCacheContext cacheContext, NuGet.Common.ILogger logger, System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.Task ~override NuGet.Protocol.Core.Types.PluginFindPackageByIdResource.DoesPackageExistAsync(string id, NuGet.Versioning.NuGetVersion version, NuGet.Protocol.Core.Types.SourceCacheContext cacheContext, NuGet.Common.ILogger logger, System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.Task ~override NuGet.Protocol.Core.Types.PluginFindPackageByIdResource.GetAllVersionsAsync(string id, NuGet.Protocol.Core.Types.SourceCacheContext cacheContext, NuGet.Common.ILogger logger, System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.Task> ~override NuGet.Protocol.Core.Types.PluginFindPackageByIdResource.GetDependencyInfoAsync(string id, NuGet.Versioning.NuGetVersion version, NuGet.Protocol.Core.Types.SourceCacheContext cacheContext, NuGet.Common.ILogger logger, System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.Task ~override NuGet.Protocol.Core.Types.PluginFindPackageByIdResource.GetPackageDownloaderAsync(NuGet.Packaging.Core.PackageIdentity packageIdentity, NuGet.Protocol.Core.Types.SourceCacheContext cacheContext, NuGet.Common.ILogger logger, System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.Task ~override NuGet.Protocol.Core.Types.PluginResourceProvider.TryCreate(NuGet.Protocol.Core.Types.SourceRepository source, System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.Task> -~override NuGet.Protocol.Core.Types.RemoteSourceDependencyInfo.Equals(object obj) -> bool +override NuGet.Protocol.Core.Types.RemoteSourceDependencyInfo.Equals(object? obj) -> bool override NuGet.Protocol.Core.Types.RemoteSourceDependencyInfo.GetHashCode() -> int -~override NuGet.Protocol.Core.Types.RemoteSourceDependencyInfo.ToString() -> string +override NuGet.Protocol.Core.Types.RemoteSourceDependencyInfo.ToString() -> string! ~override NuGet.Protocol.Core.Types.SourceRepository.ToString() -> string ~override NuGet.Protocol.DependencyInfoResourceV2Feed.ResolvePackage(NuGet.Packaging.Core.PackageIdentity package, NuGet.Frameworks.NuGetFramework projectFramework, NuGet.Protocol.Core.Types.SourceCacheContext sourceCacheContext, NuGet.Common.ILogger log, System.Threading.CancellationToken token) -> System.Threading.Tasks.Task ~override NuGet.Protocol.DependencyInfoResourceV2Feed.ResolvePackages(string packageId, NuGet.Frameworks.NuGetFramework projectFramework, NuGet.Protocol.Core.Types.SourceCacheContext sourceCacheContext, NuGet.Common.ILogger log, System.Threading.CancellationToken token) -> System.Threading.Tasks.Task> @@ -1895,11 +1895,11 @@ override NuGet.Protocol.VersionRangeConverter.WriteJson(Newtonsoft.Json.JsonWrit ~static NuGet.Protocol.CachingUtility.ReadCacheFile(System.TimeSpan maxAge, string cacheFile) -> System.IO.Stream ~static NuGet.Protocol.CachingUtility.RemoveInvalidFileNameChars(string value) -> string ~static NuGet.Protocol.Core.Types.FindPackageByIdResource.GetDependencyInfo(NuGet.Packaging.NuspecReader reader) -> NuGet.Protocol.Core.Types.FindPackageByIdDependencyInfo -~static NuGet.Protocol.Core.Types.HttpSourceCacheContext.Create(NuGet.Protocol.Core.Types.SourceCacheContext cacheContext, bool isFirstAttempt) -> NuGet.Protocol.Core.Types.HttpSourceCacheContext -~static NuGet.Protocol.Core.Types.HttpSourceCacheContext.Create(NuGet.Protocol.Core.Types.SourceCacheContext cacheContext, int retryCount) -> NuGet.Protocol.Core.Types.HttpSourceCacheContext +static NuGet.Protocol.Core.Types.HttpSourceCacheContext.Create(NuGet.Protocol.Core.Types.SourceCacheContext! cacheContext, bool isFirstAttempt) -> NuGet.Protocol.Core.Types.HttpSourceCacheContext! +static NuGet.Protocol.Core.Types.HttpSourceCacheContext.Create(NuGet.Protocol.Core.Types.SourceCacheContext! cacheContext, int retryCount) -> NuGet.Protocol.Core.Types.HttpSourceCacheContext! static NuGet.Protocol.Core.Types.NuGetTestMode.Enabled.get -> bool static NuGet.Protocol.Core.Types.NuGetTestMode.InvokeTestFunctionAgainstTestMode(System.Func! function, bool testModeEnabled) -> T -~static NuGet.Protocol.Core.Types.NullSourceCacheContext.Instance.get -> NuGet.Protocol.Core.Types.SourceCacheContext +static NuGet.Protocol.Core.Types.NullSourceCacheContext.Instance.get -> NuGet.Protocol.Core.Types.SourceCacheContext! ~static NuGet.Protocol.Core.Types.OfflineFeedUtility.AddPackageToSource(NuGet.Protocol.Core.Types.OfflineFeedAddContext offlineFeedAddContext, System.Threading.CancellationToken token) -> System.Threading.Tasks.Task ~static NuGet.Protocol.Core.Types.OfflineFeedUtility.GetPackageDirectory(NuGet.Packaging.Core.PackageIdentity packageIdentity, string offlineFeed) -> string ~static NuGet.Protocol.Core.Types.OfflineFeedUtility.PackageExists(NuGet.Packaging.Core.PackageIdentity packageIdentity, string offlineFeed, out bool isValidPackage) -> bool @@ -1920,9 +1920,9 @@ static NuGet.Protocol.Core.Types.NuGetTestMode.InvokeTestFunctionAgainstTestMode ~static NuGet.Protocol.Core.Types.Repository.Factory.get -> NuGet.Protocol.Core.Types.Repository.RepositoryFactory ~static NuGet.Protocol.Core.Types.Repository.Provider.get -> NuGet.Protocol.Core.Types.Repository.ProviderFactory ~static NuGet.Protocol.Core.Types.Repository.Provider.set -> void -~static NuGet.Protocol.Core.Types.UserAgent.SetUserAgent(System.Net.Http.HttpClient client) -> void -~static NuGet.Protocol.Core.Types.UserAgent.SetUserAgentString(NuGet.Protocol.Core.Types.UserAgentStringBuilder builder) -> void -~static NuGet.Protocol.Core.Types.UserAgent.UserAgentString.get -> string +static NuGet.Protocol.Core.Types.UserAgent.SetUserAgent(System.Net.Http.HttpClient! client) -> void +static NuGet.Protocol.Core.Types.UserAgent.SetUserAgentString(NuGet.Protocol.Core.Types.UserAgentStringBuilder! builder) -> void +static NuGet.Protocol.Core.Types.UserAgent.UserAgentString.get -> string! static NuGet.Protocol.Events.ProtocolDiagnostics.HttpEvent -> NuGet.Protocol.Events.ProtocolDiagnostics.ProtocolDiagnosticHttpEventHandler static NuGet.Protocol.Events.ProtocolDiagnostics.NupkgCopiedEvent -> NuGet.Protocol.Events.ProtocolDiagnostics.ProtocolDiagnosticsNupkgCopiedEventHandler static NuGet.Protocol.Events.ProtocolDiagnostics.ResourceEvent -> NuGet.Protocol.Events.ProtocolDiagnostics.ProtocolDiagnosticResourceEventHandler @@ -2038,7 +2038,7 @@ static NuGet.Protocol.Resources.OwnerDetailsUriTemplateResourceV3.CreateOrNull(S ~static NuGet.Protocol.VisualStudio.FactoryExtensionsVS.GetVisualStudio(this NuGet.Protocol.Core.Types.Repository.RepositoryFactory factory, NuGet.Configuration.PackageSource source) -> NuGet.Protocol.Core.Types.SourceRepository ~static NuGet.Protocol.VisualStudio.FactoryExtensionsVS.GetVisualStudio(this NuGet.Protocol.Core.Types.Repository.RepositoryFactory factory, string source) -> NuGet.Protocol.Core.Types.SourceRepository ~static NuGet.Repositories.NuGetv3LocalRepositoryUtility.GetPackage(System.Collections.Generic.IReadOnlyList repositories, string id, NuGet.Versioning.NuGetVersion version) -> NuGet.Repositories.LocalPackageSourceInfo -~static readonly NuGet.Protocol.Core.Types.UserAgentStringBuilder.DefaultNuGetClientName -> string +static readonly NuGet.Protocol.Core.Types.UserAgentStringBuilder.DefaultNuGetClientName -> string! ~static readonly NuGet.Protocol.HttpRequestMessageConfiguration.Default -> NuGet.Protocol.HttpRequestMessageConfiguration static readonly NuGet.Protocol.HttpRetryHandlerRequest.DefaultDownloadTimeout -> System.TimeSpan static readonly NuGet.Protocol.HttpRetryHandlerRequest.DefaultMaxTries -> int @@ -2088,11 +2088,11 @@ virtual NuGet.Protocol.Core.Types.ResourceProvider.After.get -> System.Collectio virtual NuGet.Protocol.Core.Types.ResourceProvider.Before.get -> System.Collections.Generic.IEnumerable! virtual NuGet.Protocol.Core.Types.ResourceProvider.Name.get -> string! virtual NuGet.Protocol.Core.Types.ResourceProvider.ResourceType.get -> System.Type! -~virtual NuGet.Protocol.Core.Types.SourceCacheContext.Clone() -> NuGet.Protocol.Core.Types.SourceCacheContext +virtual NuGet.Protocol.Core.Types.SourceCacheContext.Clone() -> NuGet.Protocol.Core.Types.SourceCacheContext! virtual NuGet.Protocol.Core.Types.SourceCacheContext.Dispose(bool disposing) -> void -~virtual NuGet.Protocol.Core.Types.SourceCacheContext.GeneratedTempFolder.get -> string -~virtual NuGet.Protocol.Core.Types.SourceCacheContext.GeneratedTempFolder.set -> void -~virtual NuGet.Protocol.Core.Types.SourceCacheContext.WithRefreshCacheTrue() -> NuGet.Protocol.Core.Types.SourceCacheContext +virtual NuGet.Protocol.Core.Types.SourceCacheContext.GeneratedTempFolder.get -> string! +virtual NuGet.Protocol.Core.Types.SourceCacheContext.GeneratedTempFolder.set -> void +virtual NuGet.Protocol.Core.Types.SourceCacheContext.WithRefreshCacheTrue() -> NuGet.Protocol.Core.Types.SourceCacheContext! ~virtual NuGet.Protocol.Core.Types.SourceRepository.GetFeedType(System.Threading.CancellationToken token) -> System.Threading.Tasks.Task ~virtual NuGet.Protocol.Core.Types.SourceRepository.GetResource() -> T ~virtual NuGet.Protocol.Core.Types.SourceRepository.GetResource(System.Threading.CancellationToken token) -> T diff --git a/src/NuGet.Core/NuGet.Protocol/PublicAPI/net8.0/PublicAPI.Shipped.txt b/src/NuGet.Core/NuGet.Protocol/PublicAPI/net8.0/PublicAPI.Shipped.txt index 60dad4c68fd..cca4a5f5e10 100644 --- a/src/NuGet.Core/NuGet.Protocol/PublicAPI/net8.0/PublicAPI.Shipped.txt +++ b/src/NuGet.Core/NuGet.Protocol/PublicAPI/net8.0/PublicAPI.Shipped.txt @@ -65,8 +65,8 @@ NuGet.Protocol.Core.Types.HttpHandlerResource.HttpHandlerResource() -> void NuGet.Protocol.Core.Types.HttpSourceCacheContext NuGet.Protocol.Core.Types.HttpSourceCacheContext.DirectDownload.get -> bool NuGet.Protocol.Core.Types.HttpSourceCacheContext.MaxAge.get -> System.TimeSpan -~NuGet.Protocol.Core.Types.HttpSourceCacheContext.RootTempFolder.get -> string -~NuGet.Protocol.Core.Types.HttpSourceCacheContext.SourceCacheContext.get -> NuGet.Protocol.Core.Types.SourceCacheContext +NuGet.Protocol.Core.Types.HttpSourceCacheContext.RootTempFolder.get -> string? +NuGet.Protocol.Core.Types.HttpSourceCacheContext.SourceCacheContext.get -> NuGet.Protocol.Core.Types.SourceCacheContext! NuGet.Protocol.Core.Types.ILegacyFeedCapabilityResource NuGet.Protocol.Core.Types.ILegacyFeedCapabilityResource.SupportsIsAbsoluteLatestVersionAsync(NuGet.Common.ILogger! log, System.Threading.CancellationToken token) -> System.Threading.Tasks.Task! NuGet.Protocol.Core.Types.ILegacyFeedCapabilityResource.SupportsSearchAsync(NuGet.Common.ILogger! log, System.Threading.CancellationToken token) -> System.Threading.Tasks.Task! @@ -138,17 +138,17 @@ NuGet.Protocol.Core.Types.OfflineFeedAddContext.ThrowIfPackageExistsAndInvalid.g NuGet.Protocol.Core.Types.OfflineFeedAddContext.ThrowIfSourcePackageIsInvalid.get -> bool NuGet.Protocol.Core.Types.OfflineFeedUtility NuGet.Protocol.Core.Types.PackageDownloadContext -~NuGet.Protocol.Core.Types.PackageDownloadContext.ClientPolicyContext.get -> NuGet.Packaging.Signing.ClientPolicyContext -~NuGet.Protocol.Core.Types.PackageDownloadContext.ClientPolicyContext.set -> void +NuGet.Protocol.Core.Types.PackageDownloadContext.ClientPolicyContext.get -> NuGet.Packaging.Signing.ClientPolicyContext? +NuGet.Protocol.Core.Types.PackageDownloadContext.ClientPolicyContext.set -> void NuGet.Protocol.Core.Types.PackageDownloadContext.DirectDownload.get -> bool -~NuGet.Protocol.Core.Types.PackageDownloadContext.DirectDownloadDirectory.get -> string -~NuGet.Protocol.Core.Types.PackageDownloadContext.PackageDownloadContext(NuGet.Protocol.Core.Types.SourceCacheContext sourceCacheContext) -> void -~NuGet.Protocol.Core.Types.PackageDownloadContext.PackageDownloadContext(NuGet.Protocol.Core.Types.SourceCacheContext sourceCacheContext, string directDownloadDirectory, bool directDownload) -> void -~NuGet.Protocol.Core.Types.PackageDownloadContext.PackageDownloadContext(NuGet.Protocol.Core.Types.SourceCacheContext sourceCacheContext, string directDownloadDirectory, bool directDownload, NuGet.Configuration.PackageSourceMapping packageSourceMappingConfiguration) -> void -~NuGet.Protocol.Core.Types.PackageDownloadContext.PackageSourceMapping.get -> NuGet.Configuration.PackageSourceMapping +NuGet.Protocol.Core.Types.PackageDownloadContext.DirectDownloadDirectory.get -> string? +NuGet.Protocol.Core.Types.PackageDownloadContext.PackageDownloadContext(NuGet.Protocol.Core.Types.SourceCacheContext! sourceCacheContext) -> void +NuGet.Protocol.Core.Types.PackageDownloadContext.PackageDownloadContext(NuGet.Protocol.Core.Types.SourceCacheContext! sourceCacheContext, string? directDownloadDirectory, bool directDownload) -> void +NuGet.Protocol.Core.Types.PackageDownloadContext.PackageDownloadContext(NuGet.Protocol.Core.Types.SourceCacheContext! sourceCacheContext, string? directDownloadDirectory, bool directDownload, NuGet.Configuration.PackageSourceMapping? packageSourceMappingConfiguration) -> void +NuGet.Protocol.Core.Types.PackageDownloadContext.PackageSourceMapping.get -> NuGet.Configuration.PackageSourceMapping? NuGet.Protocol.Core.Types.PackageDownloadContext.ParentId.get -> System.Guid NuGet.Protocol.Core.Types.PackageDownloadContext.ParentId.set -> void -~NuGet.Protocol.Core.Types.PackageDownloadContext.SourceCacheContext.get -> NuGet.Protocol.Core.Types.SourceCacheContext +NuGet.Protocol.Core.Types.PackageDownloadContext.SourceCacheContext.get -> NuGet.Protocol.Core.Types.SourceCacheContext! NuGet.Protocol.Core.Types.PackageMetadataResource NuGet.Protocol.Core.Types.PackageMetadataResource.PackageMetadataResource() -> void NuGet.Protocol.Core.Types.PackageProgressEventArgs @@ -241,13 +241,13 @@ NuGet.Protocol.Core.Types.PluginResourceProvider NuGet.Protocol.Core.Types.PluginResourceProvider.PluginResourceProvider() -> void ~NuGet.Protocol.Core.Types.PluginResourceProvider.PluginResourceProvider(NuGet.Protocol.Plugins.IPluginManager pluginManager) -> void NuGet.Protocol.Core.Types.RemoteSourceDependencyInfo -~NuGet.Protocol.Core.Types.RemoteSourceDependencyInfo.ContentUri.get -> string -~NuGet.Protocol.Core.Types.RemoteSourceDependencyInfo.ContentUri.set -> void -~NuGet.Protocol.Core.Types.RemoteSourceDependencyInfo.DependencyGroups.get -> System.Collections.Generic.IEnumerable -~NuGet.Protocol.Core.Types.RemoteSourceDependencyInfo.Equals(NuGet.Protocol.Core.Types.RemoteSourceDependencyInfo other) -> bool -~NuGet.Protocol.Core.Types.RemoteSourceDependencyInfo.Identity.get -> NuGet.Packaging.Core.PackageIdentity +NuGet.Protocol.Core.Types.RemoteSourceDependencyInfo.ContentUri.get -> string! +NuGet.Protocol.Core.Types.RemoteSourceDependencyInfo.ContentUri.set -> void +NuGet.Protocol.Core.Types.RemoteSourceDependencyInfo.DependencyGroups.get -> System.Collections.Generic.IEnumerable! +NuGet.Protocol.Core.Types.RemoteSourceDependencyInfo.Equals(NuGet.Protocol.Core.Types.RemoteSourceDependencyInfo? other) -> bool +NuGet.Protocol.Core.Types.RemoteSourceDependencyInfo.Identity.get -> NuGet.Packaging.Core.PackageIdentity! NuGet.Protocol.Core.Types.RemoteSourceDependencyInfo.Listed.get -> bool -~NuGet.Protocol.Core.Types.RemoteSourceDependencyInfo.RemoteSourceDependencyInfo(NuGet.Packaging.Core.PackageIdentity identity, bool listed, System.Collections.Generic.IEnumerable dependencyGroups, string contentUri) -> void +NuGet.Protocol.Core.Types.RemoteSourceDependencyInfo.RemoteSourceDependencyInfo(NuGet.Packaging.Core.PackageIdentity! identity, bool listed, System.Collections.Generic.IEnumerable! dependencyGroups, string! contentUri) -> void NuGet.Protocol.Core.Types.Repository NuGet.Protocol.Core.Types.Repository.ProviderFactory NuGet.Protocol.Core.Types.Repository.ProviderFactory.ProviderFactory() -> void @@ -297,13 +297,13 @@ NuGet.Protocol.Core.Types.SourceCacheContext.SessionId.get -> System.Guid NuGet.Protocol.Core.Types.SourceCacheContext.SessionId.set -> void NuGet.Protocol.Core.Types.SourceCacheContext.SourceCacheContext() -> void NuGet.Protocol.Core.Types.SourcePackageDependencyInfo -~NuGet.Protocol.Core.Types.SourcePackageDependencyInfo.DownloadUri.get -> System.Uri +NuGet.Protocol.Core.Types.SourcePackageDependencyInfo.DownloadUri.get -> System.Uri? NuGet.Protocol.Core.Types.SourcePackageDependencyInfo.Listed.get -> bool -~NuGet.Protocol.Core.Types.SourcePackageDependencyInfo.PackageHash.get -> string -~NuGet.Protocol.Core.Types.SourcePackageDependencyInfo.Source.get -> NuGet.Protocol.Core.Types.SourceRepository -~NuGet.Protocol.Core.Types.SourcePackageDependencyInfo.SourcePackageDependencyInfo(NuGet.Packaging.Core.PackageIdentity identity, System.Collections.Generic.IEnumerable dependencies, bool listed, NuGet.Protocol.Core.Types.SourceRepository source, System.Uri downloadUri, string packageHash) -> void -~NuGet.Protocol.Core.Types.SourcePackageDependencyInfo.SourcePackageDependencyInfo(string id, NuGet.Versioning.NuGetVersion version, System.Collections.Generic.IEnumerable dependencies, bool listed, NuGet.Protocol.Core.Types.SourceRepository source) -> void -~NuGet.Protocol.Core.Types.SourcePackageDependencyInfo.SourcePackageDependencyInfo(string id, NuGet.Versioning.NuGetVersion version, System.Collections.Generic.IEnumerable dependencies, bool listed, NuGet.Protocol.Core.Types.SourceRepository source, System.Uri downloadUri, string packageHash) -> void +NuGet.Protocol.Core.Types.SourcePackageDependencyInfo.PackageHash.get -> string? +NuGet.Protocol.Core.Types.SourcePackageDependencyInfo.Source.get -> NuGet.Protocol.Core.Types.SourceRepository? +NuGet.Protocol.Core.Types.SourcePackageDependencyInfo.SourcePackageDependencyInfo(NuGet.Packaging.Core.PackageIdentity! identity, System.Collections.Generic.IEnumerable! dependencies, bool listed, NuGet.Protocol.Core.Types.SourceRepository? source, System.Uri? downloadUri, string? packageHash) -> void +NuGet.Protocol.Core.Types.SourcePackageDependencyInfo.SourcePackageDependencyInfo(string! id, NuGet.Versioning.NuGetVersion! version, System.Collections.Generic.IEnumerable! dependencies, bool listed, NuGet.Protocol.Core.Types.SourceRepository? source) -> void +NuGet.Protocol.Core.Types.SourcePackageDependencyInfo.SourcePackageDependencyInfo(string! id, NuGet.Versioning.NuGetVersion! version, System.Collections.Generic.IEnumerable! dependencies, bool listed, NuGet.Protocol.Core.Types.SourceRepository? source, System.Uri? downloadUri, string? packageHash) -> void NuGet.Protocol.Core.Types.SourceRepository NuGet.Protocol.Core.Types.SourceRepository.FeedTypeOverride.get -> NuGet.Protocol.FeedType NuGet.Protocol.Core.Types.SourceRepository.SourceRepository() -> void @@ -322,11 +322,11 @@ NuGet.Protocol.Core.Types.SymbolPackageUpdateResourceV3 ~NuGet.Protocol.Core.Types.SymbolPackageUpdateResourceV3.SymbolPackageUpdateResourceV3(string source, NuGet.Protocol.HttpSource httpSource) -> void NuGet.Protocol.Core.Types.UserAgent NuGet.Protocol.Core.Types.UserAgentStringBuilder -~NuGet.Protocol.Core.Types.UserAgentStringBuilder.Build() -> string -~NuGet.Protocol.Core.Types.UserAgentStringBuilder.NuGetClientVersion.get -> string +NuGet.Protocol.Core.Types.UserAgentStringBuilder.Build() -> string! +NuGet.Protocol.Core.Types.UserAgentStringBuilder.NuGetClientVersion.get -> string! NuGet.Protocol.Core.Types.UserAgentStringBuilder.UserAgentStringBuilder() -> void -~NuGet.Protocol.Core.Types.UserAgentStringBuilder.UserAgentStringBuilder(string clientName) -> void -~NuGet.Protocol.Core.Types.UserAgentStringBuilder.WithVisualStudioSKU(string vsInfo) -> NuGet.Protocol.Core.Types.UserAgentStringBuilder +NuGet.Protocol.Core.Types.UserAgentStringBuilder.UserAgentStringBuilder(string! clientName) -> void +NuGet.Protocol.Core.Types.UserAgentStringBuilder.WithVisualStudioSKU(string? vsInfo) -> NuGet.Protocol.Core.Types.UserAgentStringBuilder! NuGet.Protocol.Core.Types.VersionInfo NuGet.Protocol.Core.Types.VersionInfo.DownloadCount.get -> long? NuGet.Protocol.Core.Types.VersionInfo.PackageSearchMetadata.get -> NuGet.Protocol.Core.Types.IPackageSearchMetadata? @@ -1630,18 +1630,18 @@ const NuGet.Protocol.JsonExtensions.JsonSerializationMaxDepth = 512 -> int ~override NuGet.Protocol.AutoCompleteResourceV3.IdStartsWith(string packageIdPrefix, bool includePrerelease, NuGet.Common.ILogger log, System.Threading.CancellationToken token) -> System.Threading.Tasks.Task> ~override NuGet.Protocol.AutoCompleteResourceV3.VersionStartsWith(string packageId, string versionPrefix, bool includePrerelease, NuGet.Protocol.Core.Types.SourceCacheContext sourceCacheContext, NuGet.Common.ILogger log, System.Threading.CancellationToken token) -> System.Threading.Tasks.Task> ~override NuGet.Protocol.AutoCompleteResourceV3Provider.TryCreate(NuGet.Protocol.Core.Types.SourceRepository source, System.Threading.CancellationToken token) -> System.Threading.Tasks.Task> -~override NuGet.Protocol.Core.Types.NullSourceCacheContext.Clone() -> NuGet.Protocol.Core.Types.SourceCacheContext -~override NuGet.Protocol.Core.Types.NullSourceCacheContext.GeneratedTempFolder.get -> string -~override NuGet.Protocol.Core.Types.NullSourceCacheContext.WithRefreshCacheTrue() -> NuGet.Protocol.Core.Types.SourceCacheContext +override NuGet.Protocol.Core.Types.NullSourceCacheContext.Clone() -> NuGet.Protocol.Core.Types.SourceCacheContext! +override NuGet.Protocol.Core.Types.NullSourceCacheContext.GeneratedTempFolder.get -> string! +override NuGet.Protocol.Core.Types.NullSourceCacheContext.WithRefreshCacheTrue() -> NuGet.Protocol.Core.Types.SourceCacheContext! ~override NuGet.Protocol.Core.Types.PluginFindPackageByIdResource.CopyNupkgToStreamAsync(string id, NuGet.Versioning.NuGetVersion version, System.IO.Stream destination, NuGet.Protocol.Core.Types.SourceCacheContext cacheContext, NuGet.Common.ILogger logger, System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.Task ~override NuGet.Protocol.Core.Types.PluginFindPackageByIdResource.DoesPackageExistAsync(string id, NuGet.Versioning.NuGetVersion version, NuGet.Protocol.Core.Types.SourceCacheContext cacheContext, NuGet.Common.ILogger logger, System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.Task ~override NuGet.Protocol.Core.Types.PluginFindPackageByIdResource.GetAllVersionsAsync(string id, NuGet.Protocol.Core.Types.SourceCacheContext cacheContext, NuGet.Common.ILogger logger, System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.Task> ~override NuGet.Protocol.Core.Types.PluginFindPackageByIdResource.GetDependencyInfoAsync(string id, NuGet.Versioning.NuGetVersion version, NuGet.Protocol.Core.Types.SourceCacheContext cacheContext, NuGet.Common.ILogger logger, System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.Task ~override NuGet.Protocol.Core.Types.PluginFindPackageByIdResource.GetPackageDownloaderAsync(NuGet.Packaging.Core.PackageIdentity packageIdentity, NuGet.Protocol.Core.Types.SourceCacheContext cacheContext, NuGet.Common.ILogger logger, System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.Task ~override NuGet.Protocol.Core.Types.PluginResourceProvider.TryCreate(NuGet.Protocol.Core.Types.SourceRepository source, System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.Task> -~override NuGet.Protocol.Core.Types.RemoteSourceDependencyInfo.Equals(object obj) -> bool +override NuGet.Protocol.Core.Types.RemoteSourceDependencyInfo.Equals(object? obj) -> bool override NuGet.Protocol.Core.Types.RemoteSourceDependencyInfo.GetHashCode() -> int -~override NuGet.Protocol.Core.Types.RemoteSourceDependencyInfo.ToString() -> string +override NuGet.Protocol.Core.Types.RemoteSourceDependencyInfo.ToString() -> string! ~override NuGet.Protocol.Core.Types.SourceRepository.ToString() -> string ~override NuGet.Protocol.DependencyInfoResourceV2Feed.ResolvePackage(NuGet.Packaging.Core.PackageIdentity package, NuGet.Frameworks.NuGetFramework projectFramework, NuGet.Protocol.Core.Types.SourceCacheContext sourceCacheContext, NuGet.Common.ILogger log, System.Threading.CancellationToken token) -> System.Threading.Tasks.Task ~override NuGet.Protocol.DependencyInfoResourceV2Feed.ResolvePackages(string packageId, NuGet.Frameworks.NuGetFramework projectFramework, NuGet.Protocol.Core.Types.SourceCacheContext sourceCacheContext, NuGet.Common.ILogger log, System.Threading.CancellationToken token) -> System.Threading.Tasks.Task> @@ -1885,11 +1885,11 @@ override NuGet.Protocol.VersionRangeConverter.WriteJson(Newtonsoft.Json.JsonWrit ~static NuGet.Protocol.CachingUtility.ReadCacheFile(System.TimeSpan maxAge, string cacheFile) -> System.IO.Stream ~static NuGet.Protocol.CachingUtility.RemoveInvalidFileNameChars(string value) -> string ~static NuGet.Protocol.Core.Types.FindPackageByIdResource.GetDependencyInfo(NuGet.Packaging.NuspecReader reader) -> NuGet.Protocol.Core.Types.FindPackageByIdDependencyInfo -~static NuGet.Protocol.Core.Types.HttpSourceCacheContext.Create(NuGet.Protocol.Core.Types.SourceCacheContext cacheContext, bool isFirstAttempt) -> NuGet.Protocol.Core.Types.HttpSourceCacheContext -~static NuGet.Protocol.Core.Types.HttpSourceCacheContext.Create(NuGet.Protocol.Core.Types.SourceCacheContext cacheContext, int retryCount) -> NuGet.Protocol.Core.Types.HttpSourceCacheContext +static NuGet.Protocol.Core.Types.HttpSourceCacheContext.Create(NuGet.Protocol.Core.Types.SourceCacheContext! cacheContext, bool isFirstAttempt) -> NuGet.Protocol.Core.Types.HttpSourceCacheContext! +static NuGet.Protocol.Core.Types.HttpSourceCacheContext.Create(NuGet.Protocol.Core.Types.SourceCacheContext! cacheContext, int retryCount) -> NuGet.Protocol.Core.Types.HttpSourceCacheContext! static NuGet.Protocol.Core.Types.NuGetTestMode.Enabled.get -> bool static NuGet.Protocol.Core.Types.NuGetTestMode.InvokeTestFunctionAgainstTestMode(System.Func! function, bool testModeEnabled) -> T -~static NuGet.Protocol.Core.Types.NullSourceCacheContext.Instance.get -> NuGet.Protocol.Core.Types.SourceCacheContext +static NuGet.Protocol.Core.Types.NullSourceCacheContext.Instance.get -> NuGet.Protocol.Core.Types.SourceCacheContext! ~static NuGet.Protocol.Core.Types.OfflineFeedUtility.AddPackageToSource(NuGet.Protocol.Core.Types.OfflineFeedAddContext offlineFeedAddContext, System.Threading.CancellationToken token) -> System.Threading.Tasks.Task ~static NuGet.Protocol.Core.Types.OfflineFeedUtility.GetPackageDirectory(NuGet.Packaging.Core.PackageIdentity packageIdentity, string offlineFeed) -> string ~static NuGet.Protocol.Core.Types.OfflineFeedUtility.PackageExists(NuGet.Packaging.Core.PackageIdentity packageIdentity, string offlineFeed, out bool isValidPackage) -> bool @@ -1910,9 +1910,9 @@ static NuGet.Protocol.Core.Types.NuGetTestMode.InvokeTestFunctionAgainstTestMode ~static NuGet.Protocol.Core.Types.Repository.Factory.get -> NuGet.Protocol.Core.Types.Repository.RepositoryFactory ~static NuGet.Protocol.Core.Types.Repository.Provider.get -> NuGet.Protocol.Core.Types.Repository.ProviderFactory ~static NuGet.Protocol.Core.Types.Repository.Provider.set -> void -~static NuGet.Protocol.Core.Types.UserAgent.SetUserAgent(System.Net.Http.HttpClient client) -> void -~static NuGet.Protocol.Core.Types.UserAgent.SetUserAgentString(NuGet.Protocol.Core.Types.UserAgentStringBuilder builder) -> void -~static NuGet.Protocol.Core.Types.UserAgent.UserAgentString.get -> string +static NuGet.Protocol.Core.Types.UserAgent.SetUserAgent(System.Net.Http.HttpClient! client) -> void +static NuGet.Protocol.Core.Types.UserAgent.SetUserAgentString(NuGet.Protocol.Core.Types.UserAgentStringBuilder! builder) -> void +static NuGet.Protocol.Core.Types.UserAgent.UserAgentString.get -> string! static NuGet.Protocol.Events.ProtocolDiagnostics.HttpEvent -> NuGet.Protocol.Events.ProtocolDiagnostics.ProtocolDiagnosticHttpEventHandler static NuGet.Protocol.Events.ProtocolDiagnostics.NupkgCopiedEvent -> NuGet.Protocol.Events.ProtocolDiagnostics.ProtocolDiagnosticsNupkgCopiedEventHandler static NuGet.Protocol.Events.ProtocolDiagnostics.ResourceEvent -> NuGet.Protocol.Events.ProtocolDiagnostics.ProtocolDiagnosticResourceEventHandler @@ -2026,7 +2026,7 @@ static NuGet.Protocol.Resources.OwnerDetailsUriTemplateResourceV3.CreateOrNull(S ~static NuGet.Protocol.VisualStudio.FactoryExtensionsVS.GetVisualStudio(this NuGet.Protocol.Core.Types.Repository.RepositoryFactory factory, NuGet.Configuration.PackageSource source) -> NuGet.Protocol.Core.Types.SourceRepository ~static NuGet.Protocol.VisualStudio.FactoryExtensionsVS.GetVisualStudio(this NuGet.Protocol.Core.Types.Repository.RepositoryFactory factory, string source) -> NuGet.Protocol.Core.Types.SourceRepository ~static NuGet.Repositories.NuGetv3LocalRepositoryUtility.GetPackage(System.Collections.Generic.IReadOnlyList repositories, string id, NuGet.Versioning.NuGetVersion version) -> NuGet.Repositories.LocalPackageSourceInfo -~static readonly NuGet.Protocol.Core.Types.UserAgentStringBuilder.DefaultNuGetClientName -> string +static readonly NuGet.Protocol.Core.Types.UserAgentStringBuilder.DefaultNuGetClientName -> string! ~static readonly NuGet.Protocol.HttpRequestMessageConfiguration.Default -> NuGet.Protocol.HttpRequestMessageConfiguration static readonly NuGet.Protocol.HttpRetryHandlerRequest.DefaultDownloadTimeout -> System.TimeSpan static readonly NuGet.Protocol.HttpRetryHandlerRequest.DefaultMaxTries -> int @@ -2076,11 +2076,11 @@ virtual NuGet.Protocol.Core.Types.ResourceProvider.After.get -> System.Collectio virtual NuGet.Protocol.Core.Types.ResourceProvider.Before.get -> System.Collections.Generic.IEnumerable! virtual NuGet.Protocol.Core.Types.ResourceProvider.Name.get -> string! virtual NuGet.Protocol.Core.Types.ResourceProvider.ResourceType.get -> System.Type! -~virtual NuGet.Protocol.Core.Types.SourceCacheContext.Clone() -> NuGet.Protocol.Core.Types.SourceCacheContext +virtual NuGet.Protocol.Core.Types.SourceCacheContext.Clone() -> NuGet.Protocol.Core.Types.SourceCacheContext! virtual NuGet.Protocol.Core.Types.SourceCacheContext.Dispose(bool disposing) -> void -~virtual NuGet.Protocol.Core.Types.SourceCacheContext.GeneratedTempFolder.get -> string -~virtual NuGet.Protocol.Core.Types.SourceCacheContext.GeneratedTempFolder.set -> void -~virtual NuGet.Protocol.Core.Types.SourceCacheContext.WithRefreshCacheTrue() -> NuGet.Protocol.Core.Types.SourceCacheContext +virtual NuGet.Protocol.Core.Types.SourceCacheContext.GeneratedTempFolder.get -> string! +virtual NuGet.Protocol.Core.Types.SourceCacheContext.GeneratedTempFolder.set -> void +virtual NuGet.Protocol.Core.Types.SourceCacheContext.WithRefreshCacheTrue() -> NuGet.Protocol.Core.Types.SourceCacheContext! ~virtual NuGet.Protocol.Core.Types.SourceRepository.GetFeedType(System.Threading.CancellationToken token) -> System.Threading.Tasks.Task ~virtual NuGet.Protocol.Core.Types.SourceRepository.GetResource() -> T ~virtual NuGet.Protocol.Core.Types.SourceRepository.GetResource(System.Threading.CancellationToken token) -> T diff --git a/src/NuGet.Core/NuGet.Protocol/RemoteSourceDependencyInfo.cs b/src/NuGet.Core/NuGet.Protocol/RemoteSourceDependencyInfo.cs index 6ee08d0a0f8..7c3954c3777 100644 --- a/src/NuGet.Core/NuGet.Protocol/RemoteSourceDependencyInfo.cs +++ b/src/NuGet.Core/NuGet.Protocol/RemoteSourceDependencyInfo.cs @@ -1,8 +1,6 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -#nullable disable - using System; using System.Collections.Generic; using System.Globalization; @@ -40,6 +38,11 @@ public RemoteSourceDependencyInfo( throw new ArgumentNullException(nameof(dependencyGroups)); } + if (contentUri == null) + { + throw new ArgumentNullException(nameof(contentUri)); + } + Identity = identity; Listed = listed; DependencyGroups = dependencyGroups.ToList(); @@ -66,7 +69,7 @@ public RemoteSourceDependencyInfo( /// public string ContentUri { get; set; } - public bool Equals(RemoteSourceDependencyInfo other) + public bool Equals(RemoteSourceDependencyInfo? other) { return other != null && Identity.Equals(other.Identity) && @@ -74,7 +77,7 @@ public bool Equals(RemoteSourceDependencyInfo other) string.Equals(ContentUri, other.ContentUri, StringComparison.Ordinal); } - public override bool Equals(object obj) => Equals(obj as PackageDependencyInfo); + public override bool Equals(object? obj) => Equals(obj as RemoteSourceDependencyInfo); public override int GetHashCode() { diff --git a/src/NuGet.Core/NuGet.Protocol/SourceCacheContext.cs b/src/NuGet.Core/NuGet.Protocol/SourceCacheContext.cs index 1bbfaf7b437..09ecfa7451f 100644 --- a/src/NuGet.Core/NuGet.Protocol/SourceCacheContext.cs +++ b/src/NuGet.Core/NuGet.Protocol/SourceCacheContext.cs @@ -1,8 +1,6 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -#nullable disable - using System; using System.Diagnostics; using System.IO; @@ -19,7 +17,7 @@ public class SourceCacheContext : IDisposable /// /// Path of temp folder if requested by GeneratedTempFolder /// - private string _generatedTempFolder = null; + private string? _generatedTempFolder; /// /// Default amount of time to cache version lists. @@ -121,16 +119,17 @@ public virtual string GeneratedTempFolder /// public virtual SourceCacheContext Clone() { - return new SourceCacheContext() + var clone = new SourceCacheContext() { DirectDownload = DirectDownload, IgnoreFailedSources = IgnoreFailedSources, MaxAge = MaxAge, NoCache = NoCache, - GeneratedTempFolder = _generatedTempFolder, RefreshMemoryCache = RefreshMemoryCache, SessionId = SessionId }; + clone._generatedTempFolder = _generatedTempFolder; + return clone; } /// @@ -161,7 +160,7 @@ protected virtual void Dispose(bool disposing) { try { - Directory.Delete(_generatedTempFolder, recursive: true); + Directory.Delete(currentTempFolder, recursive: true); } catch { diff --git a/src/NuGet.Core/NuGet.Protocol/SourcePackageDependencyInfo.cs b/src/NuGet.Core/NuGet.Protocol/SourcePackageDependencyInfo.cs index 5158546f5e5..6361eda8015 100644 --- a/src/NuGet.Core/NuGet.Protocol/SourcePackageDependencyInfo.cs +++ b/src/NuGet.Core/NuGet.Protocol/SourcePackageDependencyInfo.cs @@ -1,8 +1,6 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -#nullable disable - using System; using System.Collections.Generic; using NuGet.Packaging.Core; @@ -17,7 +15,7 @@ public SourcePackageDependencyInfo( NuGetVersion version, IEnumerable dependencies, bool listed, - SourceRepository source) + SourceRepository? source) : this( new PackageIdentity(id, version), dependencies, @@ -33,9 +31,9 @@ public SourcePackageDependencyInfo( NuGetVersion version, IEnumerable dependencies, bool listed, - SourceRepository source, - Uri downloadUri, - string packageHash) + SourceRepository? source, + Uri? downloadUri, + string? packageHash) : this( new PackageIdentity(id, version), dependencies, @@ -50,9 +48,9 @@ public SourcePackageDependencyInfo( PackageIdentity identity, IEnumerable dependencies, bool listed, - SourceRepository source, - Uri downloadUri, - string packageHash) + SourceRepository? source, + Uri? downloadUri, + string? packageHash) : base(identity, dependencies) { Listed = listed; @@ -70,18 +68,18 @@ public SourcePackageDependencyInfo( /// /// Source repository the dependency information was retrieved from. /// - public SourceRepository Source { get; } + public SourceRepository? Source { get; } /// /// The HTTP, UNC, or local file URI to the package nupkg. /// /// Optional - public Uri DownloadUri { get; } + public Uri? DownloadUri { get; } /// /// Package hash /// /// Optional - public string PackageHash { get; } + public string? PackageHash { get; } } } diff --git a/src/NuGet.Core/NuGet.Protocol/UserAgent.cs b/src/NuGet.Core/NuGet.Protocol/UserAgent.cs index 97fb8097984..ee5a27cba69 100644 --- a/src/NuGet.Core/NuGet.Protocol/UserAgent.cs +++ b/src/NuGet.Core/NuGet.Protocol/UserAgent.cs @@ -1,8 +1,6 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -#nullable disable - using System; using System.Net.Http; using NuGet.Packaging; diff --git a/src/NuGet.Core/NuGet.Protocol/UserAgentStringBuilder.cs b/src/NuGet.Core/NuGet.Protocol/UserAgentStringBuilder.cs index 164834cafcf..cf82151c7b3 100644 --- a/src/NuGet.Core/NuGet.Protocol/UserAgentStringBuilder.cs +++ b/src/NuGet.Core/NuGet.Protocol/UserAgentStringBuilder.cs @@ -1,8 +1,6 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -#nullable disable - #if NETCOREAPP using System; #endif @@ -22,9 +20,9 @@ public class UserAgentStringBuilder private const string UserAgentTemplate = "{0}/{1}"; private readonly string _clientName; - private string _vsInfo; - private string _osInfo; - private string _ciInfo; + private string? _vsInfo; + private string? _osInfo; + private string? _ciInfo; public UserAgentStringBuilder() : this(DefaultNuGetClientName) @@ -54,7 +52,7 @@ internal UserAgentStringBuilder(string clientName, IEnvironmentVariableReader en public string NuGetClientVersion { get; } - public UserAgentStringBuilder WithVisualStudioSKU(string vsInfo) + public UserAgentStringBuilder WithVisualStudioSKU(string? vsInfo) { _vsInfo = vsInfo; return this; From a03e0436afe3b09ad3d5ecd9078171efb539385b Mon Sep 17 00:00:00 2001 From: Nikolche Kolev Date: Fri, 24 Apr 2026 18:04:58 -0700 Subject: [PATCH 2/6] RemoteSourceDependencyInfo: replace contentUri null check with NULL_INC remark Remove the newly-added ArgumentNullException guard for contentUri to avoid introducing a new throw in a previously-permissive code path. The non-null annotation is kept but marked with NULL_INC for future telemetry-guided follow-up. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../NuGet.Protocol/RemoteSourceDependencyInfo.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/NuGet.Core/NuGet.Protocol/RemoteSourceDependencyInfo.cs b/src/NuGet.Core/NuGet.Protocol/RemoteSourceDependencyInfo.cs index 7c3954c3777..22cb65aa0f4 100644 --- a/src/NuGet.Core/NuGet.Protocol/RemoteSourceDependencyInfo.cs +++ b/src/NuGet.Core/NuGet.Protocol/RemoteSourceDependencyInfo.cs @@ -38,11 +38,6 @@ public RemoteSourceDependencyInfo( throw new ArgumentNullException(nameof(dependencyGroups)); } - if (contentUri == null) - { - throw new ArgumentNullException(nameof(contentUri)); - } - Identity = identity; Listed = listed; DependencyGroups = dependencyGroups.ToList(); @@ -67,6 +62,11 @@ public RemoteSourceDependencyInfo( /// /// The content url of this resource. /// + /// + /// NULL_INC: Annotated as non-null but no runtime check is enforced in the constructor + /// to avoid introducing a new throw in a previously-permissive code path. + /// Revisit with telemetry to confirm callers never pass null. + /// public string ContentUri { get; set; } public bool Equals(RemoteSourceDependencyInfo? other) From b16af0ba21e67d944c6d8a9ff3dfa431ea07d996 Mon Sep 17 00:00:00 2001 From: Nikolche Kolev Date: Fri, 24 Apr 2026 18:10:36 -0700 Subject: [PATCH 3/6] Add nullable-enablement skill for repeatable nullable migration work Covers annotation philosophy (non-null bias), PublicAPI.Shipped.txt update rules, NULL_INC escape hatch criteria, and step-by-step migration workflow. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- docs/skills/nullable-enablement/SKILL.md | 205 +++++++++++++++++++++++ 1 file changed, 205 insertions(+) create mode 100644 docs/skills/nullable-enablement/SKILL.md diff --git a/docs/skills/nullable-enablement/SKILL.md b/docs/skills/nullable-enablement/SKILL.md new file mode 100644 index 00000000000..70fc03b152e --- /dev/null +++ b/docs/skills/nullable-enablement/SKILL.md @@ -0,0 +1,205 @@ +--- +name: nullable-enablement +description: Enable C# nullable reference types on files that still have `#nullable disable` in the NuGet.Client codebase. Use this skill whenever the user asks to enable nullable, migrate nullable, remove `#nullable disable`, annotate nullability, or fix nullable warnings for any NuGet project or file. Also trigger when the user mentions a GitHub issue about nullable enablement, references PublicAPI.Shipped.txt annotation updates, or says things like "let's do nullable on X" or "enable nullable for these files." +--- + +# Nullable Enablement Skill + +This skill guides the process of enabling C# nullable reference types on files in the NuGet.Client repository that currently opt out with `#nullable disable`. The codebase has nullable globally enabled via `build/common.project.props`, so individual files opt *out* with `#nullable disable` at the top. Migration means removing that directive, annotating types correctly, and updating the public API surface files. + +The work is inherently incremental — don't try to migrate an entire project at once. Work in batches of related files, fix cascading warnings, build, and repeat. + +## Annotation Philosophy: Prefer Non-Null + +The default mindset when annotating is **non-null unless proven otherwise**. Before marking something `?`, ask: "Can I make this non-null instead?" Sometimes a small, non-breaking code change can eliminate nullability — and that's preferable to marking something nullable. But be careful not to replace null problems with empty-value problems. + +**Good non-null opportunities:** +- **Use `required`** on internal/private types so the constructor enforces initialization. +- **Set a property in the constructor** instead of relying on callers to set it later. +- **Use `??` or `?? throw`** at assignment sites to guarantee non-null storage. +- **Initialize a field** to a sensible default — but only when the consuming code already handles that default gracefully. Don't initialize to `string.Empty` or `Array.Empty()` if downstream code would silently misbehave with an empty value instead of correctly handling null. Empty should not become the new null. + +**When `?` is the right answer:** +- The value is genuinely optional — configuration, cache misses, "not found" semantics. +- The only non-null alternative is a sentinel value (empty string, empty collection) that downstream code doesn't expect and would silently mishandle. +- The type represents something that can legitimately be absent at runtime. + +The goal is to shrink the nullable surface area, but honestly — not by hiding nullability behind empty values that shift the bug downstream. + +## High-Level Workflow + +1. **Identify target files** — find files with `#nullable disable` in the target project. +2. **Pick a batch** — group related files (e.g., a class and its immediate dependencies). Small batches (1–5 files) are easier to review. +3. **For each file:** + a. Remove `#nullable disable` + b. Annotate types (parameters, return types, properties, fields) + c. Update `PublicAPI.Shipped.txt` for both TFMs + d. Fix cascading warnings in dependent files +4. **Build** to verify zero warnings/errors. +5. **Repeat** with the next batch. + +## Step-by-Step: Migrating a Single File + +### 1. Remove the directive + +Delete the `#nullable disable` line (and any blank line it leaves behind). + +### 2. Annotate types + +Work through every public and internal member with a **non-null bias** — look for opportunities to keep or make things non-null before reaching for `?`: + +- **Parameters** → default to non-null. Only mark `?` when the parameter genuinely accepts null by design. If a parameter was oblivious and callers never pass null in practice, annotate it as non-null and add a null check. +- **Properties/fields** → prefer non-null. Can you initialize in the constructor, use a default value, or use `required`? Do that instead of marking `?`. +- **Return types** → prefer non-null. Can the method return an empty collection, `string.Empty`, or a sentinel instead of null? If so, make the return non-null. +- **Only mark `?` when the value is genuinely, unavoidably absent** — optional configuration, cache misses, "not found" semantics, etc. +- **`IEnumerable` and other generics** → annotate the element type too: `IEnumerable!` in the API file means both the collection and its elements are non-null + +### 3. Risk Assessment for Null Checks + +When a parameter is annotated as non-null, the **default** is to add a runtime `ArgumentNullException` check if one doesn't already exist. Most of the time, this is the right thing to do: + +**Add the check (the common case):** +- The parameter already had a null check — keep it +- The parameter is new, internal, or has no history of null being passed +- The parameter is used in a way that would throw `NullReferenceException` anyway — `ArgumentNullException` is more informative and fail-fast + +**`NULL_INC` — rare, last-resort escape hatch:** + +`NULL_INC` exists for the narrow case where a shipped public API parameter is practically never null, but you can't be 100% certain no caller passes null, and adding a throw would be a risky behavioral change. This should be **very few** instances across the entire codebase — if you're reaching for `NULL_INC` more than once or twice per PR, you're probably using it too liberally. + +The criteria are strict — ALL of these must be true: +- The parameter is on a **shipped public API** (not internal) +- The parameter **never** had a null check +- The value is **practically never null** in real-world usage (it's not an "optional" parameter — callers almost certainly always provide a value) +- But you lack telemetry to be **absolutely certain** no caller passes null + +Place the `NULL_INC` as an XML `` on the relevant property or as a comment on the constructor, using this format: +```xml +/// +/// NULL_INC: Annotated as non-null but no runtime check is enforced in the constructor +/// to avoid introducing a new throw in a previously-permissive code path. +/// Revisit with telemetry to confirm callers never pass null. +/// +``` + +If in doubt between adding a null check and using `NULL_INC`, **add the null check**. The bar for `NULL_INC` is intentionally high. + +**Never suppress nullability with `!` (the forgiveness operator) when the value genuinely can be null.** Make the type honest and let callers handle it. + +### 4. Common Annotation Patterns + +**Constructor-initialized properties:** +```csharp +// Non-null — set in constructor, guaranteed by null check +public PackageIdentity Identity { get; } + +// Nullable — no guarantee +public string? Description { get; set; } +``` + +**`required` keyword for internal types:** +```csharp +// Prefer `required` over `null!` initializer for internal/private types +internal class Options +{ + public required string Path { get; init; } +} +``` + +**TryCreate / TryGet patterns:** +```csharp +public bool TryGetValue(string key, [NotNullWhen(true)] out string? value) +``` +- Out parameters need `?` +- Add `[NotNullWhen(true)]` only when it's actually guaranteed non-null on success for ALL code paths +- Callers use `!` after the success guard + +**`Debug.Assert(x != null)` + `x!`:** +When the parameter type is non-null and all callers are nullable-enabled, you can remove both the assert and the `!` — they're redundant. + +**Covariant return nullability:** +A subclass method returning `byte[]` can override a base returning `byte[]?` — this is valid in C# 9+. Use it when the subclass guarantees non-null. + +**IEquatable and Equals:** +```csharp +public bool Equals(MyType? other) // parameter is nullable +public override bool Equals(object? obj) // always nullable +``` + +## PublicAPI.Shipped.txt Updates + +This is the most precision-sensitive part of the migration. Every public type and member has an entry in `PublicAPI.Shipped.txt`. Each project has **two** TFM directories (e.g., `net8.0/` and `net472/`). Both must be updated identically. + +### The `~` (oblivious) prefix + +Lines starting with `~` represent nullable-oblivious signatures. When you annotate a type, **replace the `~` line in place** with the correctly annotated line. Do NOT add to `PublicAPI.Unshipped.txt`. + +### Annotation syntax + +| C# type | PublicAPI notation | +|---|---| +| `string` (non-null) | `string!` | +| `string?` | `string?` | +| `byte[]` (non-null) | `byte[]!` | +| `byte[]?` | `byte[]?` | +| `string[]` (non-null array of non-null strings) | `string![]!` | +| `IEnumerable` (non-null) | `System.Collections.Generic.IEnumerable<...PackageIdentity!>!` | +| `Task` (non-null) | `System.Threading.Tasks.Task!` | +| Unconstrained generic `T` | `T` (NO `!` — generics don't get annotated) | +| `Func` (non-null) | `Func!` (the `Func` gets `!`, not `T`) | + +### Rules + +- **Match existing format precisely** — look at other annotated entries in the same file for guidance. +- **Internal types don't need Shipped.txt updates** — only public API surfaces. +- **Never add to Unshipped.txt** for nullable annotation changes — always replace in-place in Shipped.txt. +- **Both TFMs must match** — update `net8.0/PublicAPI.Shipped.txt` and `net472/PublicAPI.Shipped.txt` (or whatever TFMs the project targets) identically. + +### Example transformation + +Before (oblivious): +``` +~NuGet.Protocol.Core.Types.PackageDownloadContext.PackageDownloadContext(NuGet.Protocol.Core.Types.SourceCacheContext sourceCacheContext, string directDownloadDirectory, bool directDownload) -> void +``` + +After (annotated): +``` +NuGet.Protocol.Core.Types.PackageDownloadContext.PackageDownloadContext(NuGet.Protocol.Core.Types.SourceCacheContext! sourceCacheContext, string? directDownloadDirectory, bool directDownload) -> void +``` + +## Building and Verifying + +After each batch of changes, build the affected project to ensure zero warnings/errors: + +``` +msbuild src\NuGet.Core\\.csproj /t:Build /p:Configuration=Release +``` + +or use the solution filter: + +``` +msbuild NuGet-Src.slnf /t:Build /p:Configuration=Release +``` + +Common build errors after nullable migration: + +| Error | Fix | +|---|---| +| **RS0016** "Symbol not in PublicAPI" | You added a new annotated entry but didn't remove the `~` line — replace, don't add | +| **RS0017** "Symbol removed" | You removed the `~` line but the replacement doesn't match — check annotation syntax | +| **CS8600–CS8605** nullable warnings | Annotate the type correctly, or add a null check | +| **CS8618** non-nullable field not initialized | Use `required`, add a constructor init, or make the field nullable | + +## XLF Files + +**Never edit `.xlf` files directly.** They are generated from `.resx` files. If you need to change localized strings, edit the `.resx` file and build — the xlf files will be regenerated automatically. + +## Checklist Before Submitting + +- [ ] All `#nullable disable` directives removed from target files +- [ ] Types annotated correctly with a non-null bias (prefer non-null, only `?` when genuinely absent) +- [ ] `NULL_INC` remarks added only for the rare cases meeting all criteria (shipped API, practically never null, no telemetry) +- [ ] `PublicAPI.Shipped.txt` updated for ALL TFMs (`~` lines replaced in place) +- [ ] No entries added to `PublicAPI.Unshipped.txt` +- [ ] Project builds with zero warnings/errors +- [ ] No `.xlf` files edited manually From 39a08fd34825beea73ba49c3c3493ef6568ec47e Mon Sep 17 00:00:00 2001 From: Nikolche Kolev Date: Fri, 24 Apr 2026 18:13:40 -0700 Subject: [PATCH 4/6] RemoteSourceDependencyInfo: add protocol context to NULL_INC remark ContentUri maps to the required packageContent field in the NuGet V3 registration API, so null is not expected in practice. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- src/NuGet.Core/NuGet.Protocol/RemoteSourceDependencyInfo.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/NuGet.Core/NuGet.Protocol/RemoteSourceDependencyInfo.cs b/src/NuGet.Core/NuGet.Protocol/RemoteSourceDependencyInfo.cs index 22cb65aa0f4..ddff07c330f 100644 --- a/src/NuGet.Core/NuGet.Protocol/RemoteSourceDependencyInfo.cs +++ b/src/NuGet.Core/NuGet.Protocol/RemoteSourceDependencyInfo.cs @@ -65,7 +65,9 @@ public RemoteSourceDependencyInfo( /// /// NULL_INC: Annotated as non-null but no runtime check is enforced in the constructor /// to avoid introducing a new throw in a previously-permissive code path. - /// Revisit with telemetry to confirm callers never pass null. + /// This maps to the packageContent field in the NuGet V3 registration API + /// (https://learn.microsoft.com/en-us/nuget/api/registration-base-url-resource#registration-leaf-object-in-a-page) + /// which is required by protocol, so null is not expected in practice. /// public string ContentUri { get; set; } From 1d4ffaa9d2e956d2abadf5fbc1438a8faed22212 Mon Sep 17 00:00:00 2001 From: Nikolche Kolev Date: Fri, 24 Apr 2026 18:27:41 -0700 Subject: [PATCH 5/6] Fix CS8602 in LocalDependencyInfoResourceTests for nullable DownloadUri Add null-forgiving operator on DownloadUri access in test assertions where the value is known non-null from the test setup. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../LocalDependencyInfoResourceTests.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/test/NuGet.Core.Tests/NuGet.Protocol.Tests/LocalResourceTests/LocalDependencyInfoResourceTests.cs b/test/NuGet.Core.Tests/NuGet.Protocol.Tests/LocalResourceTests/LocalDependencyInfoResourceTests.cs index 54a3f442b97..2f37af969a3 100644 --- a/test/NuGet.Core.Tests/NuGet.Protocol.Tests/LocalResourceTests/LocalDependencyInfoResourceTests.cs +++ b/test/NuGet.Core.Tests/NuGet.Protocol.Tests/LocalResourceTests/LocalDependencyInfoResourceTests.cs @@ -98,7 +98,7 @@ public async Task LocalDependencyInfoResource_BasicAsync() Assert.Equal(1, resultsA.Count); Assert.Equal(packageA.Identity, resultsA[0], PackageIdentity.Comparer); Assert.True(resultsA[0].Listed); - Assert.Contains("a.1.0.0.nupkg", resultsA[0].DownloadUri.LocalPath); + Assert.Contains("a.1.0.0.nupkg", resultsA[0].DownloadUri!.LocalPath); Assert.Equal(2, resultsA[0].Dependencies.Count()); Assert.Equal("c", resultsA[0].Dependencies.First().Id); Assert.Equal("[1.0.0, )", resultsA[0].Dependencies.First().VersionRange.ToNormalizedString()); @@ -109,7 +109,7 @@ public async Task LocalDependencyInfoResource_BasicAsync() Assert.Equal(1, resultsX.Count); Assert.Equal(packageX.Identity, resultsX[0], PackageIdentity.Comparer); Assert.True(resultsX[0].Listed); - Assert.Contains("x.1.0.0.nupkg", resultsX[0].DownloadUri.LocalPath); + Assert.Contains("x.1.0.0.nupkg", resultsX[0].DownloadUri!.LocalPath); Assert.Equal(0, resultsX[0].Dependencies.Count()); // not found @@ -158,7 +158,7 @@ public async Task LocalDependencyInfoResource_NoDependenciesAsync() Assert.Equal(1, results.Count); Assert.Equal(packageX.Identity, results[0], PackageIdentity.Comparer); Assert.True(results[0].Listed); - Assert.Contains("x.1.0.0.nupkg", results[0].DownloadUri.LocalPath); + Assert.Contains("x.1.0.0.nupkg", results[0].DownloadUri!.LocalPath); Assert.Equal(0, results[0].Dependencies.Count()); } } @@ -287,7 +287,7 @@ public async Task LocalDependencyInfoResource_MissingDependencyAsync() Assert.Equal(1, results.Count); Assert.Equal(packageA.Identity, results[0], PackageIdentity.Comparer); Assert.True(results[0].Listed); - Assert.Contains("a.1.0.0.nupkg", results[0].DownloadUri.LocalPath); + Assert.Contains("a.1.0.0.nupkg", results[0].DownloadUri!.LocalPath); Assert.Equal(1, results[0].Dependencies.Count()); Assert.Equal(0, resultsX.Count); @@ -338,7 +338,7 @@ public async Task LocalDependencyInfoResource_SinglePackageAsync() // Assert Assert.Equal(packageA.Identity, result, PackageIdentity.Comparer); Assert.True(result.Listed); - Assert.Contains("a.1.0.0.nupkg", result.DownloadUri.LocalPath); + Assert.Contains("a.1.0.0.nupkg", result.DownloadUri!.LocalPath); Assert.Equal(1, result.Dependencies.Count()); Assert.Equal("x", result.Dependencies.Single().Id); } From 4b0322283a684bf86f6cf25d66db186b4db8e596 Mon Sep 17 00:00:00 2001 From: Nikolche Kolev Date: Fri, 24 Apr 2026 18:41:31 -0700 Subject: [PATCH 6/6] Fix CS8625 in DownloadResourceV2FeedTests: pass empty dependencies instead of null The dependencies parameter is non-null after nullable enablement. These tests don't use dependencies, so Enumerable.Empty() is correct. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../NuGet.Protocol.FuncTest/DownloadResourceV2FeedTests.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/NuGet.Core.FuncTests/NuGet.Protocol.FuncTest/DownloadResourceV2FeedTests.cs b/test/NuGet.Core.FuncTests/NuGet.Protocol.FuncTest/DownloadResourceV2FeedTests.cs index 07b9ae279da..0e191c54905 100644 --- a/test/NuGet.Core.FuncTests/NuGet.Protocol.FuncTest/DownloadResourceV2FeedTests.cs +++ b/test/NuGet.Core.FuncTests/NuGet.Protocol.FuncTest/DownloadResourceV2FeedTests.cs @@ -24,7 +24,7 @@ public async Task DownloadResourceFromUrl() var downloadResource = await repo.GetResourceAsync(CancellationToken.None); - var package = new SourcePackageDependencyInfo("WindowsAzure.Storage", new NuGetVersion("6.2.0"), null, true, repo, new Uri($@"{TestSources.NuGetV2Uri}/package/WindowsAzure.Storage/6.2.0"), ""); + var package = new SourcePackageDependencyInfo("WindowsAzure.Storage", new NuGetVersion("6.2.0"), Enumerable.Empty(), true, repo, new Uri($@"{TestSources.NuGetV2Uri}/package/WindowsAzure.Storage/6.2.0"), ""); // Act & Assert using (var packagesFolder = TestDirectory.Create()) @@ -78,7 +78,7 @@ public async Task DownloadResourceFromInvalidIdInUrl() var downloadResource = await repo.GetResourceAsync(CancellationToken.None); - var package = new SourcePackageDependencyInfo("not-found", new NuGetVersion("6.2.0"), null, true, repo, new Uri($@"{TestSources.NuGetV2Uri}/package/not-found/6.2.0"), ""); + var package = new SourcePackageDependencyInfo("not-found", new NuGetVersion("6.2.0"), Enumerable.Empty(), true, repo, new Uri($@"{TestSources.NuGetV2Uri}/package/not-found/6.2.0"), ""); // Act using (var packagesFolder = TestDirectory.Create())