-
Notifications
You must be signed in to change notification settings - Fork 516
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
Clean up CodeGenerator
by moving compilation-global data and logic to Context
#1190
base: master
Are you sure you want to change the base?
Conversation
205a126
to
7a01e89
Compare
I would like this to be merged before I add an enum type registry, which is necessary to properly implement imports (and later with editions, the |
7a01e89
to
75d81e1
Compare
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 see plenty of internal changes that I like: better naming, cleanup of boxed, more helper functions.
- Is it possible to separate those from the API changes? Then we can that merge that before doing a version number bump
- Is it possible to separate each improvement into a separate commit? That will make reviewing easier.
buf: &mut String, | ||
) { | ||
impl<'a, 'b> CodeGenerator<'a, 'b> { | ||
pub fn generate(context: &mut Context<'b>, file: FileDescriptorProto, buf: &mut String) { |
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 an API breaking change, right? I don't understand how the Context
instance should be created by prost
users as there is no documentation changes included.
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.
No, CodeGenerator
is private to the crate, as is the newly added Context
.
pub struct CodeGenerator<'a> { | ||
config: &'a mut Config, | ||
pub struct CodeGenerator<'a, 'b> { | ||
context: &'a mut Context<'b>, |
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 understand why some fields are in CodeGenerator
, Context
or Config
. For example, depth
also feels like it could be part of Context
.
Can you explain when a field should be in each of those structs?
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.
Config
is the public settings configured by the API user.
Context
is a private helper that captures data global to the compilation requests: the message graph, the map of extern paths, and the reference to the Config
. I also plan to add a map of enum openness flags for a proper implementation of open enums in #1079.
It is populated before code generation and the instance is shared between successive calls to CodeGenerator::generate
for the requested members. This replaces several arguments that did the same thing with the disparate data structures.
The owned members of CodeGenerator
manage state specific to code generation for a proto file. So depth
belongs there.
/// It also provides a more disciplined access to Config | ||
/// and its mutable instance of ServiceGenerator. | ||
pub struct Context<'a> { | ||
config: &'a mut Config, |
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.
In the PR description, you mention that a mutable Config is awkward. But it is still mut
can you further explain what has been improved?
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 improvement is in the accessor methods below. CodeGenerator
cannot access the private members of Context
, so, even though its reference to Context
is mutable, ...
pub struct CodeGenerator<'a> { | ||
config: &'a mut Config, | ||
pub struct CodeGenerator<'a, 'b> { | ||
context: &'a mut Context<'b>, |
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.
Config
is the public settings configured by the API user.
Context
is a private helper that captures data global to the compilation requests: the message graph, the map of extern paths, and the reference to the Config
. I also plan to add a map of enum openness flags for a proper implementation of open enums in #1079.
It is populated before code generation and the instance is shared between successive calls to CodeGenerator::generate
for the requested members. This replaces several arguments that did the same thing with the disparate data structures.
The owned members of CodeGenerator
manage state specific to code generation for a proto file. So depth
belongs there.
/// It also provides a more disciplined access to Config | ||
/// and its mutable instance of ServiceGenerator. | ||
pub struct Context<'a> { | ||
config: &'a mut Config, |
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 improvement is in the accessor methods below. CodeGenerator
cannot access the private members of Context
, so, even though its reference to Context
is mutable, ...
} | ||
} | ||
|
||
pub fn config(&self) -> &Config { |
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.
... it can only get an immutable reference to Config
via this method,...
self.config | ||
} | ||
|
||
pub fn service_generator(&mut self) -> Option<&mut (dyn ServiceGenerator + 'static)> { |
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.
... but with this method, it can get a reference to the mutable object providing a ServiceGenerator
vtable. Which was the only reason for passing a mutable reference to Config
to CodeGenerator
before, even though it does not need to (and really should not) mutate any other members of Config
.
CodeGenerator
by moving compilation-global data and logic to Context
Move global context data and logic around it from CodeGenerator to a new Context struct. Also move the logic of can_message_derive_copy and can_field_derive_copy from MessageGraph where it caused some data duplication.
75d81e1
to
1218d3a
Compare
Refactoring improvements to prost-build:
CodeGenerator
to a newContext
struct.Context
fromMessageGraph
, where it caused some data duplication.Config
reference needing to be mutable for its user-provided service generator, by exposing both fromContext
in a more disciplined way.