-
Notifications
You must be signed in to change notification settings - Fork 4.8k
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
Options validation source generator #87587
Conversation
Note regarding the This serves as a reminder for when your PR is modifying a ref *.cs file and adding/modifying public APIs, please make sure the API implementation in the src *.cs file is documented with triple slash comments, so the PR reviewers can sign off that change. |
Tagging subscribers to this area: @dotnet/area-extensions-options Issue Detailsnull
|
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 was just skimming to get an overview, and I saw a couple cosmetics I left comments on.
...icrosoft.Extensions.Options/tests/SourceGenerationTests/Baselines/NetCoreApp/Validators.g.cs
Outdated
Show resolved
Hide resolved
HashSet<string> fullyQualifiedAttributeNames, | ||
Action<Compilation, IEnumerable<SyntaxNode>, SourceProductionContext> process) => Initialize(context, fullyQualifiedAttributeNames, x => x, process); | ||
|
||
public static void Initialize( |
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 would strongly recommend not taking a dependency on this pattern, since it makes it impractical for the source generator to take advantage of incremental caching. The general pattern is to extract data as early as possible from the compilation before applying it to a SourceProductionContext
. You can find more details in the Roslyn guide as well as see real-world examples in runtime here:
cc @chsienki
@eiriktsarpalis could you please have a look at the last commit? Finally, I got it work using ForAttributeWithMetadataName. |
CC @geeknoid |
string Name, | ||
string SimpleName, | ||
bool SelfValidates, | ||
List<ValidatedMember> MembersToValidate); |
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.
Instead of List, consider using a collection type with sequence equality so that your model has the desired equality semantics. Here's one from the repo that you can use:
You could try moving the class to the common folder so that it's shared between the two projects.
string Name, | ||
string NameWithoutGenerics, | ||
string DeclarationKeyword, | ||
List<string> ParentTypes, |
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.
|
||
var parser = new Parser(compilation, context.ReportDiagnostic, symbolHolder!, context.CancellationToken); | ||
|
||
var validatorTypes = parser.GetValidatorTypes(types); |
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.
As a next step, you might want to move the parser logic inside an IncrementalValuesProvider.Select
declaration so that you end up with an IncrementalValuesProvider<ValidatorType>
.
To achieve this, the Parser class needs to be updated so that it just stores Diagnostic
values, to be reported by the SourceProductionContext
later:
public List<DiagnosticInfo> Diagnostics { get; } = new(); | |
public void ReportDiagnostic(DiagnosticDescriptor descriptor, Location? location, params object?[]? messageArgs) | |
{ | |
Diagnostics.Add(new DiagnosticInfo | |
{ | |
Descriptor = descriptor, | |
Location = location.GetTrimmedLocation(), | |
MessageArgs = messageArgs ?? Array.Empty<object?>(), | |
}); | |
} |
Consider adding a separate unit test project on top of the existing source generator tests project which lets you test the source generator in isolation like so: Lines 631 to 662 in 36439c5
Among other things this lets you test for diagnostic warnings and incremental compilation properties. |
...icrosoft.Extensions.Options/tests/SourceGenerationTests/Baselines/NetCoreApp/Validators.g.cs
Outdated
Show resolved
Hide resolved
…idator.TryValidateValue Instead of validating each attribute separately, instead we collect the list of the attributes we need to validate and then call Validator.TryValidateValue. This will guarantee performing the same validation order as the runtime.
...icrosoft.Extensions.Options/tests/SourceGenerationTests/Baselines/NetCoreApp/Validators.g.cs
Outdated
Show resolved
Hide resolved
...icrosoft.Extensions.Options/tests/SourceGenerationTests/Baselines/NetCoreApp/Validators.g.cs
Outdated
Show resolved
Hide resolved
I added that in the commit |
src/libraries/Microsoft.Extensions.Options/tests/SourceGeneration.Unit.Tests/Main.cs
Outdated
Show resolved
Hide resolved
src/libraries/Microsoft.Extensions.Options/tests/SourceGenerationTests/ParserTests.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.
Thanks
No description provided.