-
Notifications
You must be signed in to change notification settings - Fork 212
Add ParserOptions and CodeGenerationOptions properties to RazorCodeDocument and rationalize options configuration #11526
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
Add ParserOptions and CodeGenerationOptions properties to RazorCodeDocument and rationalize options configuration #11526
Conversation
- Remove unused usings - Use ArgHelper.ThrowIfNull throughout - Annotate for nullability
There are two RazorProjectEngineBuilderExtensions classes in the compiler in different namespaces. This merges the two, which may be a breaking change for the RazorSDK, which uses the SetCSharpLanguageVersion extension method. This change also merges the RazorProjectEngineBuilderExtensionsTest files and tweaks the SetCSharpLanguageVersion test to be a bit more useful. Finally, a few using directives have been removed since SetCSharpLanguageVersion now resolves from a different namespace.
Adds ConfigureParserOptions and ConfigureCodeGenerationOptions extension methods for RazorProjectEngineBuilder
Replaces uses of ConfigureRazorCodeGenerationOptions class with call to ConfigureCodeGenerationOptions(...) helper.
Replaces uses of ConfigureRazorParserOptions class with call to ConfigureParserOptions(...) helper. This is a much larger change because there are many more uses of this class in both product and test code. I've updated each of these mechanically and removed "#nullable disable" when it wouldn't introduce warnings.
Most IConfigureRazorParserOptionsFeature implementations are trivial and can be replaced with calls to the RazorProjectEngineBuilder.ConfigureParserOptions(...) helper method.
Most IConfigureRazorCodeGenerationOptionsFeature implementations are trivial and can be replaced with calls to the RazorProjectEngineBuilder.ConfigureCodeGenerationOptions(...) helper method.
The goal of this rewrite is to avoid exposing collection interfaces and making consumers understand the semantics of the logic. Instead, it now has a simple API to add and get directives.
Change the signature of AddDirective to take a ReadOnlySpan<string> and make it internal. This API is not used by the RazorSDK, so it shouldn't be considered a breaking change. In addition, I've removed some code duplication for features that need to get a feature or create one if it doesn't exist.
AddDefaultImports is only used by tests and isn't consumed by the RazorSDK. So, it isn't a breaking change to move out of product code.
Three methods on RazorProjectEngineBuilderExtensions aren't actually used by anything in Razor or the RazorSDK: ConfigureClass, SetBaseType, and SetNamespace. These have been removed. In addition, AddTargetExtension is only used in Razor and not the RazorSDK. So, I've changed its accessibility to internal.
Both IConfigureRazorParserOptionsFeature and IConfigureRazorCodeGenerationOptionsFeature support Order properties that should be used. ConfigureDirectivesFeature sets Order to 100 to ensure that it runs last. So, this change honors that.
- "designTime" is always false for DefaultRazorCodeGenerationOptionsFeature - "designTime" is always false for DefaultRazorParserOptionsFeature - "fileKind" is always null for DefaultRazorParserOptionsFeature
This is a larger change that rationalizes the RazorCodeGenerationOptions and its builder APIs. RazorCodeGenerationOptions: - Added "Wither" methods - Removed Create(...) methods - Removed ToBuilder() method RazorCodeGenerationOptionsBuilder: - Replaced Configuration property with LanguageVersion. - Converted SetDesignTime method to property. - Removed excess constructors. - Renamed Build() method to ToOptions() The remaining files changed are largely mechanical changes responding to the API changes.
This is a larger change that rationalizes the RazorParserOptions and its builder APIs. RazorParserOptions : - Introduced RazorParserOptionsFlags to hold boolean values. - Convert CreateDefault() method to a Default property. - Added "Wither" methods - Removed Create(...) methods RazorParserOptionsBuilder: - Remove Configuration property. - Converted SetDesignTime method to property. - Removed excess constructors. - Renamed Build() method to ToOptions() - Use RazorParserOptionsFlags for all boolean values. - Add FeatureFlags property to hold RazorParserFeatureFlags. The remaining files changed are largely mechanical changes responding to the API changes.
RazorProjectOptionsBuilder is initialized with CSharpParseOptions.Default, so it's unnecesary to set that value.
This change nests RazorParserOptions' builder and flags within it. The flags have been made private along with the RazorParserOptions constructor.
This change nests RazorCodeGenerationOptions' builder and flags within it. The flags have been made private along with the RazorCodeGenerationOptions constructor.
This change pulls the RazorParserFeatureFlags values into RazorParserOptions.
This change removes DefaultRazorParserOptionsFactoryProjectFeature and DefaultRazorCodeGenerationOptionsFactoryProjectFeature and their associated interfaces. The purpose of these features can be achieved within RazorProjectEngine.
This makes RazorCodeGenerationOptions consistent with RazorParserOptions (and their builders).
This change converts the following extension methods to RazorCodeDocument instance methods: - GetParserOptions() - GetCodeGenerationOptions() - SetParserOptions() - SetCodeGenerationOptions() The options instances are now stored directly as fields on RazorCodeDocument rather than in the Items collection.
This method simply calls RazorCodeDocument.Create(Source, Imports). So, the test helper is unnecessary.
Because RazorCodeDocument now owns its ParserOptions and CodeGenerationOptions, it is generally important to create a RazorCodeDocument by calling RazorProjectEngine.CreateCodeDocument(...) in order to configure the options correctly.
…r passes Call RazroProjectEngine.CreateCodeDocument(...) rather than RazorCodeDocument.Create(...) within the compiler to ensure in is created with the configured options.
There's a RazorProjectEngineTestBase.CreateEngine() method that returns a RazorEngine and is only used by a handful of tests. These tests should be using RazorProjectEngine to create RazorCodeDocuments. So, this change updates those tests and removes CreateEngine(). In addition, several helper methods have been moved to MS.ANC.Razor.Test.Common as extension methods to prepare for further test clean up.
This change updates MS.ANC.Mvc.Razor.Extensions.Test\ModelDirectiveTest to create and use RazorCodeDocuments from the RazorProjectEngine. In addition, this change adds helpers for creating design-time RazorCodeDocuments.
Both of the design-time tests fail after being updated to use code documents from the project engine. The reason is that the test was initially buggy. Previously, the design-time tests created a RazorProjectEngine with options configured for design-time. However, the RazorCodeDocument was created without those options. So, DocumentIntermediateNode.Options.DesignTime wouldn't be set, and ModelDirective.Pass.ExecuteCore(...) would follow a runtime code path. Now that the RazorCodeDocument is correctly configured, it takes the correct design-time code path and the assertions need to be updated. IOW, the test was wrong and now it's correct.
src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/RazorCodeGenerationOptions.cs
Show resolved
Hide resolved
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.
Tooling changes look good. PR description is simply a work of art, 5/7 perfect!
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.
Generally LGTM. Did notice one thing that I think was just a typo.
src/Shared/Microsoft.AspNetCore.Razor.Test.Common/Language/RazorProjectEngineTestBase.cs
Outdated
Show resolved
Hide resolved
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.
Tooling side LGTM
11/10 would review again
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.
Looks great, this is a really nice change. Thanks!
A normal null-coalescing expression works just fine. Co-authored-by: Fred Silberberg <[email protected]>
/azp run |
Azure Pipelines successfully started running 2 pipeline(s). |
Important
This contains RazorSDK breaking changes! I've prepared a fix for these changes that can applied when the SDK build fails: DustinCampbell/sdk@4e955e1
Warning
This is a big change with a lot of commits. To facilitate code reviews, I've tried to keep the commit history informative. Most commits have explanatory messages and product and pure test changes are in separate commits.
The majority of the changes are in the compiler, so this will require two compiler reviews from @chsienki, @333fred, @jjonescz, or @jaredpar.
CI Build: https://dev.azure.com/dnceng/internal/_build/results?buildId=2647163&view=results
Test Insertion: https://dev.azure.com/devdiv/DevDiv/_git/VS/pullrequest/612761
Summary
RazorParserOptions
API and its builder pattern.RazorCodeGenerationOptions
API and its builder pattern.RazorProjectEngineBuilder
extension methods to configure parser and code generation options.IConfigureRazorParserOptionsFeature
andIConfigureRazorCodeGenerationOptionsFeature
implementations.ICollection<T>
andIReadOnlyDictionary<TKey, TValue>
.ParserOptions
andCodeGenerationOptions
properties toRazorCodeDocument
(and remove them fromRazorCodeDocument.Items
)RazorCodeDocument
is always created with valid parser and code generation options.IRazorParserOptionsFeature
andIRazorCodeGenerationOptionsFeature
interfaces and their implementations. These served as fallbacks when aRazorCodeDocument
didn't have parser or code gen options. However, that's no longer the case, so the fallbacks can be removed.IRazorParserOptionsFactoryProjectFeature
andIRazorCodeGenerationOptionsFactoryProjectFeature
interfaces and their implementations. These were only used byRazorProjectEngine
when creating aRazorCodeDocument
and their functionality has been rolled intoRazorProjectEngine.
RazorCodeDocument
from aRazorProjectEngine
.RazorProjectEngine
-based tests. The same test infrastructure is shared across the Language and "Extensions" testsRazorCodeDocumentProcessor
helper class for executing particular compiler phases and passes with aRazorCodeDocument
.RazorCodeDocuments
from aRazorProjectEngine
. This ensures that the options are always configured correctly.RazorCodeDocument.Create(...)
API. Realistically, this should rarely be used. It's always best to acquire aRazorCodeDocument
from aRazorProjectEngine
.#nullable disable
where it's easy to do. 😄Tip
If you wish to only review product changes, you can skip the following commits. Note that 1, 2, and 15 are strays, but 3-14 are grouped together in the commit history.