-
Notifications
You must be signed in to change notification settings - Fork 10.5k
Implement RouteHandlerServices.Map and use in RequestDelegateGenerator #46180
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
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.
🥇
e2c1815 to
6327fcf
Compare
| builder.Metadata.Add(new SourceKey{{StaticRouteHandlerModelEmitter.EmitSourceKey(endpoint)}}); | ||
| if (options == null) | ||
| { | ||
| return new RequestDelegateMetadataResult { EndpointMetadata = new List<object>().AsReadOnly() }; |
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.
nit:
Replace new List<object>().AsReadOnly() with ReadOnlyCollection<object>.Empty, at least 3 places can be changed
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.
TIL! Looks like this was added in 8.0? Very nice...
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.
Oh, I just assumed it existed and saw that it did 😄
Didn't realize it's new!
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 made the same comment, but you can use Array.Empty<object>() instead.
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 ended up using ReadOnlyCollection<object>. In the interest of readability it does a better job of communicating the type passed to the initializer here and I don't think there's any memory implications with that singleton.
src/Http/Http.Extensions/gen/RequestDelegateGeneratorSources.cs
Outdated
Show resolved
Hide resolved
src/Http/Http.Extensions/test/RequestDelegateGenerator/RequestDelegateGeneratorTests.cs
Show resolved
Hide resolved
eerhardt
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.
This is awesome work, @captainsafia.
I feel like I'm better able to give a decent code review now that I can see the generated code.
...test/RequestDelegateGenerator/Baselines/MapGet_NoParam_StringReturn_WithFilter.generated.txt
Show resolved
Hide resolved
...test/RequestDelegateGenerator/Baselines/MapGet_NoParam_StringReturn_WithFilter.generated.txt
Show resolved
Hide resolved
...test/RequestDelegateGenerator/Baselines/MapGet_NoParam_StringReturn_WithFilter.generated.txt
Outdated
Show resolved
Hide resolved
...test/RequestDelegateGenerator/Baselines/MapGet_NoParam_StringReturn_WithFilter.generated.txt
Outdated
Show resolved
Hide resolved
...test/RequestDelegateGenerator/Baselines/MapGet_NoParam_StringReturn_WithFilter.generated.txt
Show resolved
Hide resolved
...test/RequestDelegateGenerator/Baselines/MapGet_NoParam_StringReturn_WithFilter.generated.txt
Outdated
Show resolved
Hide resolved
...test/RequestDelegateGenerator/Baselines/MapGet_NoParam_StringReturn_WithFilter.generated.txt
Outdated
Show resolved
Hide resolved
|
|
||
| }; | ||
|
|
||
| %GENERATEDCODEATTRIBUTE% |
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.
Similar comment as above. Do we need this attribute on these methods when the whole class is marked as generated?
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 noodled on our use of the GeneratedCode attribute here a little bit more. Since the primary goal of the attribute is to make it easier to inspect if a type is codegenned from metadata, I think it makes sense to only include it in types that could be referenced from user code. Specifically, this would be:
- The
SourceKeydefinition - The strongly-typed
Mapoverloads
I refactored the code to apply it to these places. Note, I opted to remove it from the static class containing the strongly-typed Map overloads since it's unlikely that user code ends up resolving that directly.
Let me know if you think this philosophy makes sense
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 believe we want the GeneratedCodeAttribute on all the classes we generate in this file.
The reason is so things like analyzers, code-style, and code coverage tools don't warn/report things from inside this code. The devs can't change this code, so they shouldn't see tools talking about.
Even for the internal static class GenerateRouteBuilderEndpoints class. The Regex generator puts it on the partial methods, and not the class, because the class is partial to the user's code. So it would be incorrect to put it on the whole class, since the user writes code in this class too.
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.
The Regex generator puts it on the partial methods, and not the class, because the class is partial to the user's code. So it would be incorrect to put it on the whole class, since the user writes code in this class too.
This insights makes sense to me.
Here's the modification I made:
- Moved the
GenerateRouteBuilderEndpointsto the code generated in theMicrosoft.AspNetCore.Buildernamespace to fix theglobal::using issue - Added the
GeneratedCodeattribute to theGenerateRouteBuilderEndpointsclass
So, all the classes we codegen inside that namespacce are marked.
Classes marked as file private are not marked, which I assume is fine.
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.
Classes marked as file private are not marked, which I assume is fine.
I think they should be marked as well. That way they don't show up in code coverage reports, that devs can't do anything about.
...test/RequestDelegateGenerator/Baselines/MapGet_NoParam_StringReturn_WithFilter.generated.txt
Outdated
Show resolved
Hide resolved
...test/RequestDelegateGenerator/Baselines/MapGet_NoParam_StringReturn_WithFilter.generated.txt
Outdated
Show resolved
Hide resolved
...test/RequestDelegateGenerator/Baselines/MapGet_NoParam_StringReturn_WithFilter.generated.txt
Outdated
Show resolved
Hide resolved
| // </auto-generated> | ||
| //------------------------------------------------------------------------------ | ||
| #nullable enable | ||
| using global::Microsoft.AspNetCore.Http; |
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.
What's this using left for? I assume it shouldn't be needed, since everything outside of the namespace Microsoft.AspNetCore.Http.Generated should be fully qualified.
|
|
||
| }; | ||
|
|
||
| %GENERATEDCODEATTRIBUTE% |
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 believe we want the GeneratedCodeAttribute on all the classes we generate in this file.
The reason is so things like analyzers, code-style, and code coverage tools don't warn/report things from inside this code. The devs can't change this code, so they shouldn't see tools talking about.
Even for the internal static class GenerateRouteBuilderEndpoints class. The Regex generator puts it on the partial methods, and not the class, because the class is partial to the user's code. So it would be incorrect to put it on the whole class, since the user writes code in this class too.
...test/RequestDelegateGenerator/Baselines/MapGet_NoParam_StringReturn_WithFilter.generated.txt
Outdated
Show resolved
Hide resolved
...test/RequestDelegateGenerator/Baselines/MapGet_NoParam_StringReturn_WithFilter.generated.txt
Outdated
Show resolved
Hide resolved
...test/RequestDelegateGenerator/Baselines/MapGet_NoParam_StringReturn_WithFilter.generated.txt
Outdated
Show resolved
Hide resolved
eerhardt
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. Thanks for fixing all my nits. :) I think the code gen looks really clean now.
| private static void PopulateMetadata<T>(MethodInfo method, EndpointBuilder builder) where T : IEndpointMetadataProvider | ||
| { | ||
| T.PopulateMetadata(method, builder); | ||
| } | ||
|
|
||
| private static void PopulateMetadata<T>(ParameterInfo parameter, EndpointBuilder builder) where T : IEndpointParameterMetadataProvider | ||
| { | ||
| T.PopulateMetadata(parameter, builder); | ||
| } |
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 don't see these methods used. I assume they will be used in the future. Not a huge deal, but in the future we might want to only generate them if they are actually being used.
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.
Yes 🙊 ... we'll eventually use this when we add support for populating metadata for types that implement the IEndpointMetadataProvider interfaces. I can remove it in the next PR...
dotnet#46180) * Implement RouteHandlerServices.Map and use in RequestDelegateGenerator * Tweak generated code * Remove warnings from generated code * Fix docstring for RouteHandlerServices.Map * Add baseline tests and fix global:: issue * Clean up generated code * Add HTTP verb caching and fix usings * Use FQN and remove GeneratedCode attribute
Addresses #46163
RouteHandlerServices.Mapimplementation per API review aboveSourceGeneratorEndpointDataSourceimplementation in RequestDelegateGenerator's outputIEndpointRouteBuilder.GetOrAddRouteEndpointDataSourceinternal to support invocation fromRouteHandlerServices.MapRouteHandlerServices.Map