Add nullable annotations to NuGet.Common - #5333
#5333Add nullable annotations to NuGet.Common#5333zivkan merged 4 commits intodevNuGet/NuGet.Client:devfrom dev-zivkan-nullable-NuGet.CommonNuGet/NuGet.Client:dev-zivkan-nullable-NuGet.CommonCopy head branch name to clipboard
Conversation
| // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. | ||
|
|
||
| // BCL annotations on Environment.GetEnvironmentVariable makes this file difficult to annotate in .NET 5+ | ||
| #nullable disable |
There was a problem hiding this comment.
This file nearly made me give up. .NET Core 1.0 didn't have Environment.GetFolderPath, so this file has #if to compile different code for .NET Framework and everything else. On .NET Framework it uses GetFolderPath, which is annotated in .NET 5+ to not return nulls. But in our .NET Standard (and .NET (Core) if we add those TFMs) it will use Environment.GetEnvironmentVariable, which can return null.
However, .NET Core 2.0 added GetFolderPath, so I think that porting the .NET Standard code to use that. However, it's significantly higher risk than the rest of this PR, so I want to do it in a separate PR in case it needs to be reverted.
| { | ||
| throw new ArgumentException(paramName: nameof(telemetryEvent), message: "Property 'Name' must not be null"); | ||
| } | ||
| _telemetryActivity = NuGetTelemetryService?.StartActivity(telemetryEvent.Name); |
There was a problem hiding this comment.
This exposes an API design problem. We have code creating instances of TelemetryEvent with a null name, but this code will throw a NullReferenceException if such an instance is used here.
| } | ||
| else | ||
| { | ||
| Debug.Fail("Looking at all references to the static Create methods, I don't think this code path is possible."); |
There was a problem hiding this comment.
I didn't feel comfortable deleting the if != null statement, but looking at usage it should never be null. I thought maybe this Debug.Fail will give us confidence in a few weeks if none of us hit this debug point, so we can make the change later.
martinrrm
left a comment
There was a problem hiding this comment.
I didn't review the tests but I trust they are good since CI is passing.
|
Reviewed until src/NuGet.Core/NuGet.Common/Migrations/Migration1.cs. Might need an extra day to go through the rest. |
| string? destFileDirectory = Path.GetDirectoryName(destFilePath); | ||
| if (destFileDirectory is null) | ||
| { | ||
| throw new ArgumentException(paramName: destFilePath, message: "Path.GetDirectoryName(destFilePath) returned null"); |
There was a problem hiding this comment.
There was a problem hiding this comment.
I don't expect any customers to ever see this message, so no, I don't think it needs to be localized. It's only feasible if someone using NuGet.Common (part of the Client SDK) as part of their app calls the API with bad input (or if someone modifying NuGet starts calling this in a way that is buggy). Frankly, I think it's a bad API, NuGet shouldn't be in the business of proving and supporting trivial file utility APIs.
I also think it's a bad idea to parse exception messages. .NET Core changed some exception messages from what they were on the .NET Framework (I think ArgumentNullException's message is an example), and exception messages that are localized will have unexpected results when running on machines not using the same language as the developer who wrote code trying to parse the exception message. Even for tests this is a bad idea, since I don't want to exclude people running their devbox in something other than en-US from being able to run tests locally.
There was a problem hiding this comment.
I'm okay with the answer. Suggestion for message: "Not a valid file path".
nkolev92
left a comment
There was a problem hiding this comment.
Looks pretty good. Nicely done.
TelemetryEvent is really the only type where I wish we can do better.
| private static ILogger _instance; | ||
| private static ILogger? _instance; | ||
|
|
||
| public static ILogger Instance |
There was a problem hiding this comment.
tbh this optimization seems pointless
There was a problem hiding this comment.
What optimization? I was annotating exactly what was implemented
There was a problem hiding this comment.
the lazy creation of the null logger. It's not really heavy so no need to delay it.
My bad, I should've pointed out that it was the existing code.
Up to you whether you change it or not.
There was a problem hiding this comment.
ah, since I had to annotate hundreds of APIs, I didn't pay attention to most of what I was annotating. Trying to resolve all the compiler errors, and minimize risk of regression by avoiding unnecessary code changes.
d246c7b to
3582fc9
Compare
| if (firstParentDirectory is not null) | ||
| { | ||
| isCaseInsensitive &= result; | ||
| isCaseInsensitive &= CheckIfFileSystemIsCaseInsensitive(firstParentDirectory); |
There was a problem hiding this comment.
I don't know.
Technically, the whole thing is flawed, because individual filesystems can be case sensitive or not. On Windows I can configure a specific partition to be case sensitive, even though Windows' default is case insensitive filesystems. I expect there are filesystems on Linux where you can enable insensitivity. But I imagine that the number of people who change the defaults is very close to zero, and NuGet wouldn't be the only software that breaks when those defaults are changed.
|
|
||
| var tempPath = GetTempFilePath(Path.GetDirectoryName(destFilePath)); | ||
| string? destFileDirectory = Path.GetDirectoryName(destFilePath); | ||
| if (destFileDirectory is null) |
There was a problem hiding this comment.
Should we also raise an exception if the destFileDirectory is an Empty string? https://learn.microsoft.com/en-us/dotnet/api/system.io.path.getdirectoryname?view=net-7.0
There was a problem hiding this comment.
It looks like an exception will be thrown either way (either by us, or by the BCL). The difference is that the ArgumentException's ParamName value will be a different name, a name that doesn't exist in our API. But given our code is open source and this API only has a single path parameter, it's trivial to discover which parameter had an input error.
So, it's still the caller's responsibility to pass in sensible input. It doesn't cause the API to produce incorrect results. Since pushing changes resets approvals, unfortunately I don't feel motivated to add such a minor change (same goes for reverting my "see if this fixes E2E tests" commit)
There was a problem hiding this comment.
you could do a follow up PR :)
Bug
Fixes: NuGet/Home#12775
Regression? Last working version:
Description
<Nullable>enable</Nullable>to NuGet.Common and test project.PR Checklist
PR has a meaningful title
PR has a linked issue.
Described changes
Tests
Documentation