-
Notifications
You must be signed in to change notification settings - Fork 229
Replace "file kind" strings with an enum #11722
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Add RazorFileKind enum that provides the allowable values from FileKinds. In addition, include a None value for scenarios where a file kind would be null.
Note: These helper methods will be removed once the code base is converted to RazorFIleKind.
Update RazorProjectItem.FileKind property to return a RazorFIleKind rather than a string. This requires changes to all sub types as well. Note: This will require changes to the RazorSdk, which declares custom RazorProjectItem descendants.
Update RazorIntegrationTestBase.FileKind to return a RazorFileKind and update inherited test classes.
Updates RemoteProjectItem to take a RazorFileKind rather than a string.
Updates NotFoundProjectItem to take a RazorFileKind rather than a string.
Updates SourceGeneratorProjectItem to take a RazorFileKind rather than a string.
Updates DefaultRazorProjectItem to take a RazorFileKind rather than a string.
Updates TestRazorProjectItem to take a RazorFileKind rather than a string.
Updates TestSnapshotProjectItem to take a RazorFileKind rather than a string.
Update RazorToolingIntegrationTestBase.FileKind to return a RazorFileKind and update inherited test classes.
Updates RazorProjectFileSystem.GetItem(...) to take a RazorFileKind rather than a string and update all overrides and callers.
This updates the various RazorProjectEngine Process and CreateCodeDocument methods to take a RazorFileKind rather than a string.
Also includes updates for DocumentSnapshotHandle, which affect serialization.
Note: This change deletes a lot of unused test infrastructure code from ToolingParserTestBase.
This change represents mechanical clean up: - Use collection expressions - Switch from IReadOnlyList<TagHelperDescriptor> to ImmutableArray<TagHelperDescriptor> - Make CreateProvider() helper private protected - Use primary constructor - Mark for nullability - Remove unused parameters - Update static test TagHelperDescriptors to be actual singletons and use fluent builder API.
- Add TryGetFileKindFromPath - Rename FilePathToRazorFileKind to GetFileKindFromPath and implement using TryGetFileKindFromPath. - Remove ComponentFilePathToRazorFileKind
583df77 to
90fb494
Compare
davidwengier
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/RazorFileKind.cs
Show resolved
Hide resolved
| return FileKinds.ComponentImport; | ||
| } | ||
| else if (string.Equals(".razor", Path.GetExtension(filePath), StringComparison.OrdinalIgnoreCase)) | ||
| if (string.Equals(LegacyFileExtension, extension, StringComparison.OrdinalIgnoreCase)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess this is based on pre-existing code, but it's weird we use OrdinalIgnoreCase in most comparisons here and Ordinal when checking for _Imports.razor.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Totally agree, but I took a look at the history and Ordinal has been used since that check was introduced.
|
|
||
| public enum RazorFileKind : byte | ||
| { | ||
| None = 0, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need both None file kind and nullable RazorFileKind? usages?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We do, unfortunately. None gets surfaced in certain cases, namely, RazorProjectItem instances representing legacy default imports. So, RazorFileKind? is needed in a few places to know whether a RazorFileKind has been provided or not.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure I follow. How did it surface previously when the file kind was a string? I imagine (string?)null corresponds to RazorFileKind.None, so we shouldn't need another value (RazorFileKind?)null.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
RazorFileKind.None allows us to represent valid "null" cases without forcing RazorFileKind? into our APIs. The same scenarios with string were marked as #nulalble disable, so calling code didn't really have to deal with it. A FileKind property could return null, but it was exceedingly rare, so most accesses never bothered checking for null. However, since RazorFIleKind is an enum, we would need to make FileKind properties return RazorFileKind? -- a nulalble struct -- and every caller would have to deal with it. IMO, this is a good happy medium for now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the one case that's truly problematic:
razor/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/RazorProjectItem.cs
Lines 48 to 51 in 00ef962
| public virtual RazorFileKind FileKind | |
| => FilePath == null | |
| ? RazorFileKind.None | |
| : FileKinds.GetFileKindFromPath(FilePath); |
I will be following up with another PR to rework RazorProjectItem and make this scenario essentially impossible.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That doesn't work unfortunately. RazorFileKind? is used to indicate that a RazorFileKind has not been provided and it should be calculated from the file path. RazorFileKind.None is not the right signal for that -- at least not right now. RazorFileKind.None is used for the specific case where the RazorFileKind couldn't be computed from the file path.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So yeah, I'm confused how it could have worked before this PR when the only "special value" we had was null - and now we have two (None and null) and use them to indicate different things. Why didn't we need two values previously? I thought this PR just maps from string to an enum and back, i.e., it's a bi-directional mapping. Something like:
(enum <-> string)
None <-> null
Component <-> "component"
Legacy <-> "mvc"
Imports <-> "imports"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I definitely understand your confusion, and I tried to avoid this situation. However, the design of RaorProjectItem.FileKind and all of the test helpers that took string? fileKind = null made tis tricky. As I mentioned, RazorFileKind.None is a valid result for RazorProjectItem.FileKind in the case of legacy imports files. Replacing every RazorFileKind? with RazorFileKind.None causes RazorFileKind.None have two meanings:
- The case where is
RazorFileKind.Noneis a valid value. - The case where
RazorFileKind.Nonewould used to indicate that aRazorFileKindhas not yet be specified and still needs to be computed.
I opted to keep RazorFileKind? in place for now to mean the latter case. I fully intend to clean this up with a different change to RazorProjectItem. However, I felt that change was outside the scope of this PR, which already touched a lot of code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay, thanks for the explanation, sorry if I was slow to understand
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not at all! I'm very glad that you quickly spotted the obvious wart in this change. 😄
1af82b1 to
2abd127
Compare
Throughout the compiler and tooling Razor files have a "kind" that is represented as a string. Prior to the Razor API being taken internal, using a string made it theoretically possible for the compiler to be extended to file types other than those that the Razor compiler already knows about. With extensibility no longer a priority, file kinds can be represented as an enum (
RazorFileKind) that provides the values that the compiler supports, e.g..Component,ComponentImport,Legacy. This makes checks for the file kind much cheaper, since they were all string comparisons before.There are a lot of files changed, but much of the work is mechanical.
Important
This is a breaking change for the RazorSDK. When the Razor compiler flows to the .NET SDK, it will introduce build errors that can be fixed by applying this commit: dotnet/sdk@f33a5e7.
VS Test Insertion: https://dev.azure.com/devdiv/DevDiv/_git/VS/pullrequest/626687