Skip to content

Commit 43826bc

Browse files
authored
add more ToTokens impls for models (#1409)
1 parent bc8ba72 commit 43826bc

File tree

1 file changed

+208
-79
lines changed

1 file changed

+208
-79
lines changed

services/autorust/codegen/src/codegen_models.rs

+208-79
Original file line numberDiff line numberDiff line change
@@ -361,9 +361,9 @@ pub fn all_schemas_resolved(spec: &Spec) -> Result<Vec<(RefKey, SchemaGen)>> {
361361
}
362362

363363
pub enum ModelCode {
364-
Struct(TokenStream),
364+
Struct(StructCode),
365365
Enum(StructFieldCode),
366-
VecAlias(TokenStream),
366+
VecAlias(VecAliasCode),
367367
TypeAlias(TypeAliasCode),
368368
}
369369

@@ -519,12 +519,7 @@ fn create_enum(
519519
for enum_value in &enum_values {
520520
let value = &enum_value.value;
521521
let nm = value.to_camel_case_ident()?;
522-
let doc_comment = match &enum_value.description {
523-
Some(description) => {
524-
quote! { #[doc = #description] }
525-
}
526-
None => quote! {},
527-
};
522+
let doc_comment = DocCommentCode::from(&enum_value.description);
528523
let lower = value.to_lowercase();
529524
let rename = if &nm.to_string() == value {
530525
quote! {}
@@ -642,12 +637,7 @@ fn create_enum(
642637
quote! {}
643638
};
644639

645-
let doc_comment = match &property.schema.common.description {
646-
Some(description) => {
647-
quote! { #[doc = #description] }
648-
}
649-
None => quote! {},
650-
};
640+
let doc_comment = DocCommentCode::from(&property.schema.common.description);
651641

652642
let code = quote! {
653643
#doc_comment
@@ -667,11 +657,96 @@ fn create_enum(
667657
})
668658
}
669659

670-
fn create_vec_alias(schema: &SchemaGen) -> Result<TokenStream> {
660+
pub struct VecAliasCode {
661+
pub id: Ident,
662+
pub value: TypeNameCode,
663+
}
664+
665+
impl ToTokens for VecAliasCode {
666+
fn to_tokens(&self, tokens: &mut TokenStream) {
667+
let id = &self.id;
668+
let value = &self.value;
669+
tokens.extend(quote! {
670+
pub type #id = Vec<#value>;
671+
});
672+
}
673+
}
674+
675+
fn create_vec_alias(schema: &SchemaGen) -> Result<VecAliasCode> {
671676
let items = schema.array_items()?;
672-
let typ = schema.name()?.to_camel_case_ident()?;
673-
let items_typ = TypeNameCode::new(&get_type_name_for_schema_ref(items)?)?;
674-
Ok(quote! { pub type #typ = Vec<#items_typ>; })
677+
let id = schema.name()?.to_camel_case_ident()?;
678+
let value = TypeNameCode::new(&get_type_name_for_schema_ref(items)?)?;
679+
Ok(VecAliasCode { id, value })
680+
}
681+
682+
pub struct StructCode {
683+
doc_comment: DocCommentCode,
684+
struct_name_code: Ident,
685+
default_code: TokenStream,
686+
props: Vec<StructPropCode>,
687+
continuable: TokenStream,
688+
implement_default: bool,
689+
new_fn_params: Vec<TokenStream>,
690+
new_fn_body: TokenStream,
691+
mod_code: TokenStream,
692+
ns: Ident,
693+
}
694+
695+
impl ToTokens for StructCode {
696+
fn to_tokens(&self, tokens: &mut TokenStream) {
697+
let StructCode {
698+
doc_comment,
699+
struct_name_code,
700+
default_code,
701+
props,
702+
continuable,
703+
implement_default,
704+
new_fn_params,
705+
new_fn_body,
706+
mod_code,
707+
ns,
708+
} = self;
709+
710+
let struct_code = quote! {
711+
#doc_comment
712+
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
713+
#default_code
714+
pub struct #struct_name_code {
715+
#(#props)*
716+
}
717+
#continuable
718+
};
719+
tokens.extend(struct_code);
720+
721+
tokens.extend(if *implement_default {
722+
quote! {
723+
impl #struct_name_code {
724+
pub fn new() -> Self {
725+
Self::default()
726+
}
727+
}
728+
}
729+
} else {
730+
quote! {
731+
impl #struct_name_code {
732+
pub fn new(#(#new_fn_params),*) -> Self {
733+
Self {
734+
#new_fn_body
735+
}
736+
}
737+
}
738+
}
739+
});
740+
741+
if !mod_code.is_empty() {
742+
tokens.extend(quote! {
743+
pub mod #ns {
744+
use super::*;
745+
#mod_code
746+
}
747+
});
748+
}
749+
}
675750
}
676751

677752
fn create_struct(
@@ -680,10 +755,9 @@ fn create_struct(
680755
struct_name: &str,
681756
pageable: Option<&MsPageable>,
682757
mut needs_boxing: HashSet<String>,
683-
) -> Result<TokenStream> {
684-
let mut code = TokenStream::new();
758+
) -> Result<StructCode> {
685759
let mut mod_code = TokenStream::new();
686-
let mut props = TokenStream::new();
760+
let mut props = Vec::new();
687761
let mut new_fn_params: Vec<TokenStream> = Vec::new();
688762
let mut new_fn_body = TokenStream::new();
689763
let ns = struct_name.to_snake_case_ident()?;
@@ -697,9 +771,11 @@ fn create_struct(
697771
let schema_name = schema.name()?;
698772
let type_name = schema_name.to_camel_case_ident()?;
699773
let field_name = schema_name.to_snake_case_ident()?;
700-
props.extend(quote! {
701-
#[serde(flatten)]
702-
pub #field_name: #type_name,
774+
props.push(StructPropCode {
775+
doc_comments: Vec::new(),
776+
serde: SerdeCode::flatten(),
777+
field_name: field_name.clone(),
778+
field_type: type_name.clone().into(),
703779
});
704780
if schema.implement_default() {
705781
new_fn_body.extend(quote! { #field_name: #type_name::default(), });
@@ -738,9 +814,10 @@ fn create_struct(
738814
needs_boxing.clone(),
739815
)?;
740816
mod_code.extend(field_code.into_token_stream());
817+
let mut doc_comments = Vec::new();
741818
// uncomment the next two lines to help identify entries that need boxed
742819
// let prop_nm_str = format!("{} , {} , {}", prop_nm.file_path, prop_nm.schema_name, property_name);
743-
// props.extend(quote! { #[doc = #prop_nm_str ]});
820+
// doc_comments.push(DocCommentCode::from(&Some(prop_nm_str)));
744821

745822
let mut boxed = false;
746823
if needs_boxing.contains(&type_name.to_string().to_camel_case_ident()?.to_string()) {
@@ -795,27 +872,21 @@ fn create_struct(
795872
serde_attrs.push(quote! { with = "azure_core::xml::text_content"});
796873
}
797874
}
798-
let serde = if !serde_attrs.is_empty() {
799-
quote! { #[serde(#(#serde_attrs),*)] }
800-
} else {
801-
quote! {}
802-
};
875+
let serde = SerdeCode::new(serde_attrs);
803876

804877
// see if a field should be wrapped in a Box
805878
if cg.should_box_property(prop_nm) {
806879
boxed = true;
807880
}
808881
type_name = type_name.boxed(boxed);
809882

810-
let doc_comment = match &property.schema.schema.common.description {
811-
Some(description) => quote! { #[doc = #description] },
812-
None => quote! {},
813-
};
883+
doc_comments.push(DocCommentCode::from(&property.schema.schema.common.description));
814884

815-
props.extend(quote! {
816-
#doc_comment
817-
#serde
818-
pub #field_name: #type_name,
885+
props.push(StructPropCode {
886+
doc_comments,
887+
serde,
888+
field_name: field_name.clone(),
889+
field_type: type_name.clone(),
819890
});
820891

821892
if is_required {
@@ -839,10 +910,7 @@ fn create_struct(
839910
quote! {}
840911
};
841912

842-
let doc_comment = match &schema.schema.common.description {
843-
Some(description) => quote! { #[doc = #description] },
844-
None => quote! {},
845-
};
913+
let doc_comment = DocCommentCode::from(&schema.schema.common.description);
846914

847915
let mut continuable = quote! {};
848916
if let Some(pageable) = pageable {
@@ -906,47 +974,108 @@ fn create_struct(
906974
}
907975
}
908976

909-
let struct_code = quote! {
910-
#doc_comment
911-
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
912-
#default_code
913-
pub struct #struct_name_code {
914-
#props
977+
Ok(StructCode {
978+
doc_comment,
979+
struct_name_code,
980+
default_code,
981+
props,
982+
continuable,
983+
implement_default: schema.implement_default(),
984+
new_fn_params,
985+
new_fn_body,
986+
mod_code,
987+
ns,
988+
})
989+
}
990+
991+
pub struct StructPropCode {
992+
pub doc_comments: Vec<DocCommentCode>,
993+
pub serde: SerdeCode,
994+
pub field_name: Ident,
995+
pub field_type: TypeNameCode,
996+
}
997+
998+
impl StructPropCode {
999+
pub fn new(field_name: Ident, field_type: TypeNameCode) -> Self {
1000+
Self {
1001+
doc_comments: Vec::new(),
1002+
serde: SerdeCode::default(),
1003+
field_name,
1004+
field_type,
9151005
}
916-
#continuable
917-
};
918-
code.extend(struct_code);
1006+
}
1007+
}
9191008

920-
code.extend(if schema.implement_default() {
921-
quote! {
922-
impl #struct_name_code {
923-
pub fn new() -> Self {
924-
Self::default()
925-
}
926-
}
1009+
impl ToTokens for StructPropCode {
1010+
fn to_tokens(&self, tokens: &mut TokenStream) {
1011+
let doc_comments = &self.doc_comments;
1012+
let serde = &self.serde;
1013+
let field_name = &self.field_name;
1014+
let field_type = &self.field_type;
1015+
tokens.extend(quote! {
1016+
#(#doc_comments)*
1017+
#serde
1018+
pub #field_name: #field_type,
1019+
});
1020+
}
1021+
}
1022+
1023+
#[derive(Default)]
1024+
pub struct SerdeCode {
1025+
pub attributes: Vec<TokenStream>,
1026+
}
1027+
1028+
impl SerdeCode {
1029+
pub fn new(attributes: Vec<TokenStream>) -> Self {
1030+
Self { attributes }
1031+
}
1032+
pub fn flatten() -> Self {
1033+
Self {
1034+
attributes: vec![quote! { flatten }],
9271035
}
928-
} else {
929-
quote! {
930-
impl #struct_name_code {
931-
pub fn new(#(#new_fn_params),*) -> Self {
932-
Self {
933-
#new_fn_body
934-
}
935-
}
936-
}
1036+
}
1037+
}
1038+
1039+
impl ToTokens for SerdeCode {
1040+
fn to_tokens(&self, tokens: &mut TokenStream) {
1041+
let attributes = &self.attributes;
1042+
if !attributes.is_empty() {
1043+
tokens.extend(quote! {
1044+
#[serde(#(#attributes),*)]
1045+
});
9371046
}
938-
});
1047+
}
1048+
}
9391049

940-
if !mod_code.is_empty() {
941-
code.extend(quote! {
942-
pub mod #ns {
943-
use super::*;
944-
#mod_code
945-
}
946-
});
1050+
#[derive(Default)]
1051+
pub struct DocCommentCode {
1052+
description: Option<String>,
1053+
}
1054+
1055+
impl From<&str> for DocCommentCode {
1056+
fn from(description: &str) -> Self {
1057+
Self {
1058+
description: Some(description.to_string()),
1059+
}
9471060
}
1061+
}
9481062

949-
Ok(code)
1063+
impl From<&Option<String>> for DocCommentCode {
1064+
fn from(description: &Option<String>) -> Self {
1065+
Self {
1066+
description: description.clone(),
1067+
}
1068+
}
1069+
}
1070+
1071+
impl ToTokens for DocCommentCode {
1072+
fn to_tokens(&self, tokens: &mut TokenStream) {
1073+
if let Some(description) = &self.description {
1074+
tokens.extend(quote! {
1075+
#[doc = #description]
1076+
});
1077+
}
1078+
}
9501079
}
9511080

9521081
pub struct StructFieldCode {
@@ -963,16 +1092,16 @@ impl ToTokens for StructFieldCode {
9631092
}
9641093

9651094
enum TypeCode {
966-
Struct(TokenStream),
1095+
Struct(StructCode),
9671096
Enum(TokenStream),
9681097
XmlWrapped(XmlWrappedCode),
9691098
}
9701099

9711100
impl ToTokens for TypeCode {
9721101
fn to_tokens(&self, tokens: &mut TokenStream) {
9731102
match self {
974-
TypeCode::Struct(code) => tokens.extend(code.clone()),
975-
TypeCode::Enum(code) => tokens.extend(code.clone()),
1103+
TypeCode::Struct(code) => code.to_tokens(tokens),
1104+
TypeCode::Enum(code) => code.to_tokens(tokens),
9761105
TypeCode::XmlWrapped(code) => code.to_tokens(tokens),
9771106
}
9781107
}

0 commit comments

Comments
 (0)