-
Notifications
You must be signed in to change notification settings - Fork 258
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
Refactor type generation, remove code duplication #352
Conversation
codegen/src/types/composite_def.rs
Outdated
pub struct CompositeDefFields { | ||
named: bool, | ||
fields: Vec<CompositeDefField>, | ||
} |
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 wonder whether a slightly better fitting type here would be something like:
enum CompositeDefFields {
Named(Vec<(syn::Ident, CompositeDefField)>),
Unnamed(Vec<CompositeDefField>)
}
And then remove the name
from CompositeDefField
. You wouldn't have to check a boolean or handle the option in that case :)
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.
Indeed, that is similar to the type as it currently is:
subxt/codegen/src/struct_def.rs
Lines 40 to 43 in 415e122
pub enum StructDefFields { | |
Named(Vec<(syn::Ident, TypePath)>), | |
Unnamed(Vec<TypePath>), | |
} |
It's been a while since I did this but I remember getting into difficulties with this type across it's different usage contexts, hence the relaxing of the strict type.
I will look again at this to see whether it can be 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.
This change has now been applied, let me know if it looks good
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.
Barring a small suggestion this looks good to me!
codegen/src/types/composite_def.rs
Outdated
} | ||
} | ||
CompositeDefKind::EnumVariant => { | ||
let fields = self.fields.field_tokens(None, None, false); |
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 wonder if it would make sense to have separate field_tokens
methods for Struct vs Enums, e.g. struct_tokens()
/enum_tokens()
, to make the signature a bit easier on the eyes here.
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.
Done, let me know if that works now.
use std::collections::HashSet; | ||
|
||
#[derive(Clone, Debug, Default)] | ||
pub struct TypeDefParameters { |
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.
SOme docs would be good here. Maybe on on the module level as well.
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.
Done
codegen/src/types/type_def_params.rs
Outdated
if self.unused.is_empty() { | ||
return None | ||
} | ||
let mut params = self.unused.iter().collect::<Vec<_>>(); |
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.
Maybe let mut params = Vec::from_iter(self.unused);
?
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.
Hm, actually I have just changed this from HashSet
to a BTreeSet
for consistent ordering of params, so the conversion to Vec
is no longer required.
That said I'm never 100% sure when to use the explicit form e.g. Vec::from_iter
. Although probably better than the turbofish in this case, perhaps let mut params: Vec<_> = self.unused.iter().collect();
implicit form is most idiomatic?
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, left a few nitpicks.
* codegen: fix compact unnamed fields * Fmt * codegen: move derives and struct_def to types * codegen: rename struct_def to composite_def.r * WIP: deduplicate struct def code * Fmt * WIP refactoring composite type codegen duplication * Fmt * Fix TokenStream import * Fix field_tokens ty_path parse error * Fix call struct generation * Refactor ty_path() * Optional derives and move CompactAs derive to composite_def * Fmt * Introduce CompositeDefFieldType * Restore default codec derives * Extract TypeDefParameters and TypeDefGen construction * Fmt * Reset codegen to master * Introduce CompositeDefFields * Introduce CompositeDefFields * Fix up errors * Fix Box field types * Fmt * Fix compact attribute * Handle no fields case * Handle no fields with trailing semi * Fix compact field detection * Fix generic phantom marker * Fmt * Fix generic type parm fields * Clippy * Fix up boxed call fields * Fmt * Add comments to composite_def.rs * Fix license headers * Restore Debug derive in tests * Fix empty struct codegen test * Use BTreeSet for type params for ordering * code review: fix comment * code review: refactor CompositeDefFields as enum * Fix empty named fields * Fix generation of call variant enum structs * Expand field_tokens into separate methods for struct and enum variants * Add TypeDefParameters docs * Fix doc link * Clippy redundant return
Closes #328. Pure refactoring of the codegen to unify code generating structs and fields, the duplication of which has caused bugs such as: #327.
The main goal of this refactoring was to consolidate the generation of code which produces a set of fields, give some
scale_info::Field
s. This is required in several different places:scale_info::Field
s.call
andevent
structs, extracted from the variants of the top levelCall
andEvent
types.This refactoring moves most of the core code generation for types which consist of a set of fields to the
CompositeDef
type. This type is an "intermediate representation" of some set of fields for generation of astruct
or anenum
variant. A good place to start is to look at it'sToTokens
implementation and thefield_tokens
method which performs the actual codegen of the fields. You will see that all logic to do with adding compact attributes and phantom data fields is consolidated here, where previously it was spread around in various places. See code removed instruct_def.rs
andtype_def.rs
.I hope that it also improves the modularity of the types codegen to make it easier to understand and maintain. I think there could be more improvements here but this is a step in the right direction.