Add return value to build fn.
This commit is contained in:
		
							parent
							
								
									0adb4bbe0e
								
							
						
					
					
						commit
						0a97cc01b9
					
				| @ -90,6 +90,57 @@ fn make_rule_matcher(child_spec: &ChildSpec) -> TokenStream { | |||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | fn make_child_arg(child_spec: &ChildSpec) -> Option<TokenStream> { | ||||||
|  |     match child_spec { | ||||||
|  |         ChildSpec::SkipChild(_) => None, | ||||||
|  |         ChildSpec::VecChild(vec_child) => { | ||||||
|  |             let child_ident = match vec_child.build() { | ||||||
|  |                 VecChildToBuild::Type(vec_type_child) => format_ident!("{}", vec_type_child.var_name()) | ||||||
|  |             }; | ||||||
|  |             Some(quote! { #child_ident }) | ||||||
|  |         }, | ||||||
|  |         ChildSpec::SingleChild(single_child) => { | ||||||
|  |             match single_child.build() { | ||||||
|  |                 SingleChildToBuild::Type(single_type_child) => { | ||||||
|  |                     let child_ident = format_ident!("{}", single_type_child.var_name()); | ||||||
|  |                     if single_type_child.optional() { | ||||||
|  |                         Some(quote! { #child_ident }) | ||||||
|  |                     } else if let Some(or_else) = single_type_child.or_else()  { | ||||||
|  |                         let child_type_ident = format_ident!("{}", single_type_child.build()); | ||||||
|  |                         let or_else_ident = format_ident!("{}", or_else); | ||||||
|  |                         Some(quote! { | ||||||
|  |                             #child_ident.unwrap_or_else(|| Box::new(#child_type_ident::#or_else_ident())) | ||||||
|  |                         }) | ||||||
|  |                     } else { | ||||||
|  |                         Some(quote! { #child_ident.unwrap() })                        
 | ||||||
|  |                     } | ||||||
|  |                 }, | ||||||
|  |                 SingleChildToBuild::Boolean(single_boolean_child) => { | ||||||
|  |                     let child_ident = format_ident!("{}", single_boolean_child.var_name()); | ||||||
|  |                     Some(quote! { #child_ident }) | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | fn make_return_value_stream(build_spec: &StructBuildSpec) -> TokenStream { | ||||||
|  |     let type_ident = format_ident!("{}", build_spec.build()); | ||||||
|  |     let child_args = build_spec | ||||||
|  |         .children() | ||||||
|  |         .iter() | ||||||
|  |         .map(|child| make_child_arg(child)) | ||||||
|  |         .filter(|child_arg| child_arg.is_some()) | ||||||
|  |         .map(|child_arg| child_arg.unwrap()) | ||||||
|  |         .collect::<Vec<_>>(); | ||||||
|  | 
 | ||||||
|  |     quote! { | ||||||
|  |         #type_ident::new( | ||||||
|  |             #(#child_args,)* | ||||||
|  |         ) | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
| pub fn make_struct_build_fn(build_spec: &StructBuildSpec) -> TokenStream { | pub fn make_struct_build_fn(build_spec: &StructBuildSpec) -> TokenStream { | ||||||
|     let build_fn_ident = format_ident!("{}", build_spec.with()); |     let build_fn_ident = format_ident!("{}", build_spec.with()); | ||||||
|     let pair_ident = format_ident!("{}_pair", build_spec.build().to_case(Case::Snake)); |     let pair_ident = format_ident!("{}_pair", build_spec.build().to_case(Case::Snake)); | ||||||
| @ -117,11 +168,15 @@ pub fn make_struct_build_fn(build_spec: &StructBuildSpec) -> TokenStream { | |||||||
|         } |         } | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|  |     let new_stream = make_return_value_stream(build_spec); | ||||||
|  | 
 | ||||||
|     quote! { |     quote! { | ||||||
|         fn #build_fn_ident(#pair_ident: Pair<Rule>) -> #return_type_ident { |         fn #build_fn_ident(#pair_ident: Pair<Rule>) -> #return_type_ident { | ||||||
|             #(#child_holders;)* |             #(#child_holders;)* | ||||||
| 
 | 
 | ||||||
|             #iter_stream |             #iter_stream | ||||||
|  | 
 | ||||||
|  |             #new_stream | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | |||||||
| @ -48,34 +48,56 @@ fn get_vec_child(name: &str, rule: &str, build: &Yaml) -> ChildSpec { | |||||||
| 
 | 
 | ||||||
| fn get_single_child_to_build(name: &str, rule: &str, optional: bool, build: &Yaml) -> SingleChildToBuild { | fn get_single_child_to_build(name: &str, rule: &str, optional: bool, build: &Yaml) -> SingleChildToBuild { | ||||||
|     if build.is_hash() { |     if build.is_hash() { | ||||||
|         let r#type = build["type"].as_str().unwrap(); |         match build["type"].as_str() { | ||||||
|         let var_name = build["var"] |             Some(r#type) => { | ||||||
|             .as_str() |                 let var_name = build["var"] | ||||||
|             .map(|s| s.to_string()) |                     .as_str() | ||||||
|             .unwrap_or(name.to_string()); |                     .map(|s| s.to_string()) | ||||||
|         let on = build["on"].as_str().unwrap(); |                     .unwrap_or(name.to_string()); | ||||||
|         if r#type.eq("boolean") && on.eq("rule_present") { |                 let on = build["on"].as_str().unwrap(); | ||||||
|             SingleChildToBuild::Boolean(SingleBooleanChildToBuild::new( |                 if r#type.eq("boolean") && on.eq("rule_present") { | ||||||
|                 &var_name, |                     SingleChildToBuild::Boolean(SingleBooleanChildToBuild::new( | ||||||
|                 BuildBooleanOn::RulePresent, |                         &var_name, | ||||||
|             )) |                         BuildBooleanOn::RulePresent, | ||||||
|         } else { |                     )) | ||||||
|             todo!("currently on boolean types with on: rule_present are supported") |                 } else { | ||||||
|  |                     todo!("currently on boolean types with on: rule_present are supported") | ||||||
|  |                 }       
 | ||||||
|  |             }, | ||||||
|  |             None => { | ||||||
|  |                 let or_else = build["or_else"] | ||||||
|  |                     .as_str() | ||||||
|  |                     .map(|s| s.to_string()) | ||||||
|  |                     .or_else(|| { | ||||||
|  |                         let or_else_default = build["or_else_default"] | ||||||
|  |                             .as_bool() | ||||||
|  |                             .unwrap_or_else(|| false); | ||||||
|  |                         if or_else_default { | ||||||
|  |                             Some(String::from("default")) | ||||||
|  |                         } else { | ||||||
|  |                             None | ||||||
|  |                         } | ||||||
|  |                     }); | ||||||
|  |                 SingleChildToBuild::Type(SingleTypeChildToBuild::from_build_or_rule( | ||||||
|  |                     rule, | ||||||
|  |                     or_else, | ||||||
|  |                     optional, | ||||||
|  |                 )) | ||||||
|  |             } | ||||||
|         } |         } | ||||||
|     } else { |     } else { | ||||||
|         match build.as_str() { |         match build.as_str() { | ||||||
|             Some(s) => SingleChildToBuild::Type(SingleTypeChildToBuild::from_build_or_rule(s, optional)), |             Some(s) => SingleChildToBuild::Type(SingleTypeChildToBuild::from_build_or_rule(s, None, optional)), | ||||||
|             None => SingleChildToBuild::Type(SingleTypeChildToBuild::from_build_or_rule(rule, optional)), |             None => SingleChildToBuild::Type(SingleTypeChildToBuild::from_build_or_rule(rule, None, optional)), | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| fn get_single_child(name: &str, rule: &str, optional: bool, or_else: Option<String>, build: &Yaml) -> ChildSpec { | fn get_single_child(name: &str, rule: &str, optional: bool, build: &Yaml) -> ChildSpec { | ||||||
|     ChildSpec::SingleChild(SingleChild::new( |     ChildSpec::SingleChild(SingleChild::new( | ||||||
|         name, |         name, | ||||||
|         rule, |         rule, | ||||||
|         get_single_child_to_build(name, rule, optional, build), |         get_single_child_to_build(name, rule, optional, build), | ||||||
|         or_else |  | ||||||
|     )) |     )) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -110,21 +132,8 @@ fn get_child_specs(children: &Yaml) -> Vec<ChildSpec> { | |||||||
|                     let optional = props["optional"] |                     let optional = props["optional"] | ||||||
|                         .as_bool() |                         .as_bool() | ||||||
|                         .unwrap_or_else(|| false); |                         .unwrap_or_else(|| false); | ||||||
|                     let or_else = props["or_else"] |  | ||||||
|                         .as_str() |  | ||||||
|                         .map(|s| s.to_string()) |  | ||||||
|                         .or_else(|| { |  | ||||||
|                             let or_else_default = props["or_else_default"] |  | ||||||
|                                 .as_bool() |  | ||||||
|                                 .unwrap_or_else(|| false); |  | ||||||
|                             if or_else_default { |  | ||||||
|                                 Some(String::from("default")) |  | ||||||
|                             } else { |  | ||||||
|                                 None |  | ||||||
|                             } |  | ||||||
|                         }); |  | ||||||
|                     
 |                     
 | ||||||
|                     get_single_child(name, &rule, optional, or_else, build) |                     get_single_child(name, &rule, optional, build) | ||||||
|                 } |                 } | ||||||
|             } else { |             } else { | ||||||
|                 ChildSpec::SingleChild(SingleChild::from_name_snake(child_spec.as_str().unwrap())) |                 ChildSpec::SingleChild(SingleChild::from_name_snake(child_spec.as_str().unwrap())) | ||||||
|  | |||||||
| @ -9,6 +9,7 @@ use proc_macro2::TokenStream; | |||||||
| use quote::quote; | use quote::quote; | ||||||
| use spec::BuildSpec; | use spec::BuildSpec; | ||||||
| use syn::File; | use syn::File; | ||||||
|  | use syn::spanned::Spanned; | ||||||
| 
 | 
 | ||||||
| fn debug_built_spec(build_spec: &BuildSpec, token_stream: &TokenStream) { | fn debug_built_spec(build_spec: &BuildSpec, token_stream: &TokenStream) { | ||||||
|     println!("*** BuildSpec ***"); |     println!("*** BuildSpec ***"); | ||||||
|  | |||||||
| @ -224,7 +224,6 @@ pub struct SingleChild { | |||||||
|     name: String, |     name: String, | ||||||
|     rule: String, |     rule: String, | ||||||
|     build: SingleChildToBuild, |     build: SingleChildToBuild, | ||||||
|     or_else: Option<String> |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl SingleChild { | impl SingleChild { | ||||||
| @ -234,18 +233,17 @@ impl SingleChild { | |||||||
|             rule: name.to_case(Case::Pascal), |             rule: name.to_case(Case::Pascal), | ||||||
|             build: SingleChildToBuild::Type(SingleTypeChildToBuild::from_build_or_rule( |             build: SingleChildToBuild::Type(SingleTypeChildToBuild::from_build_or_rule( | ||||||
|                 &name.to_case(Case::Pascal), |                 &name.to_case(Case::Pascal), | ||||||
|  |                 None, | ||||||
|                 false, |                 false, | ||||||
|             )), |             )), | ||||||
|             or_else: None, |  | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub fn new(name: &str, rule: &str, build: SingleChildToBuild, or_else: Option<String>) -> Self { |     pub fn new(name: &str, rule: &str, build: SingleChildToBuild) -> Self { | ||||||
|         Self { |         Self { | ||||||
|             name: name.to_string(), |             name: name.to_string(), | ||||||
|             rule: rule.to_string(), |             rule: rule.to_string(), | ||||||
|             build, |             build, | ||||||
|             or_else, |  | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -276,15 +274,21 @@ pub struct SingleTypeChildToBuild { | |||||||
|     build: String, |     build: String, | ||||||
|     var_name: String, |     var_name: String, | ||||||
|     with: String, |     with: String, | ||||||
|  |     or_else: Option<String>, | ||||||
|     optional: bool, |     optional: bool, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl SingleTypeChildToBuild { | impl SingleTypeChildToBuild { | ||||||
|     pub fn from_build_or_rule(build_or_rule: &str, optional: bool) -> Self { |     pub fn from_build_or_rule( | ||||||
|  |         build_or_rule: &str, | ||||||
|  |         or_else: Option<String>, | ||||||
|  |         optional: bool, | ||||||
|  |     ) -> Self { | ||||||
|         Self { |         Self { | ||||||
|             build: build_or_rule.to_string(), |             build: build_or_rule.to_string(), | ||||||
|             var_name: build_or_rule.to_case(Case::Snake), |             var_name: build_or_rule.to_case(Case::Snake), | ||||||
|             with: make_build_fn_name(build_or_rule), |             with: make_build_fn_name(build_or_rule), | ||||||
|  |             or_else, | ||||||
|             optional, |             optional, | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| @ -304,6 +308,11 @@ impl SingleTypeChildToBuild { | |||||||
|         &self.with |         &self.with | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     /// The default fn to call when unwrapping the child (before passing as arg to new).
 | ||||||
|  |     pub fn or_else(&self) -> Option<&str> { | ||||||
|  |         self.or_else.as_deref() | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     /// If the type should be wrapped in an Option.
 |     /// If the type should be wrapped in an Option.
 | ||||||
|     pub fn optional(&self) -> bool { |     pub fn optional(&self) -> bool { | ||||||
|         self.optional |         self.optional | ||||||
|  | |||||||
| @ -82,12 +82,6 @@ $defs: | |||||||
|       optional: |       optional: | ||||||
|         type: boolean |         type: boolean | ||||||
|         description: If true, this child will be stored as an Option. |         description: If true, this child will be stored as an Option. | ||||||
|       or_else: |  | ||||||
|         type: string |  | ||||||
|         description: The method name to call upon the built-type if the rule is not found. Takes precedence over "or_else_default". |  | ||||||
|       or_else_default: |  | ||||||
|         type: boolean |  | ||||||
|         description: Whether to call the default method on the built-type if the rule is not found. |  | ||||||
|       build: |       build: | ||||||
|         oneOf: |         oneOf: | ||||||
|           - type: string |           - type: string | ||||||
| @ -97,7 +91,19 @@ $defs: | |||||||
|     additionalProperties: false |     additionalProperties: false | ||||||
|     description: A definition of what exactly to build for a given child rule. |     description: A definition of what exactly to build for a given child rule. | ||||||
|     oneOf: |     oneOf: | ||||||
|  |       - $ref: "#/$defs/BuildSingleTypeChild" | ||||||
|       - $ref: "#/$defs/BuildBooleanChild" |       - $ref: "#/$defs/BuildBooleanChild" | ||||||
|  |   BuildSingleTypeChild: | ||||||
|  |     type: object | ||||||
|  |     additionalProperties: false | ||||||
|  |     description: A definition of a single-type child to build. | ||||||
|  |     properties: | ||||||
|  |       or_else: | ||||||
|  |         type: string | ||||||
|  |         description: The method name to call upon the built-type if the rule is not found. Takes precedence over "or_else_default". | ||||||
|  |       or_else_default: | ||||||
|  |         type: boolean | ||||||
|  |         description: Whether to call the default method on the built-type if the rule is not found. | ||||||
|   BuildBooleanChild: |   BuildBooleanChild: | ||||||
|     type: object |     type: object | ||||||
|     additionalProperties: false |     additionalProperties: false | ||||||
|  | |||||||
| @ -112,9 +112,11 @@ Interface: | |||||||
|         skip: true |         skip: true | ||||||
|     - identifier |     - identifier | ||||||
|     - generic_parameters: |     - generic_parameters: | ||||||
|         or_else_default: true |         build: | ||||||
|  |           or_else_default: true | ||||||
|     - implements_list: |     - implements_list: | ||||||
|         or_else_default: true |         build: | ||||||
|  |           or_else_default: true | ||||||
|     - declarations: |     - declarations: | ||||||
|         rule: InterfaceLevelDeclaration |         rule: InterfaceLevelDeclaration | ||||||
|         vec: true |         vec: true | ||||||
| @ -133,11 +135,14 @@ Class: | |||||||
|         skip: true |         skip: true | ||||||
|     - identifier |     - identifier | ||||||
|     - generic_parameters: |     - generic_parameters: | ||||||
|         or_else_default: true |         build: | ||||||
|  |           or_else_default: true | ||||||
|     - class_constructor: |     - class_constructor: | ||||||
|         or_else_default: true |         build: | ||||||
|  |           or_else_default: true | ||||||
|     - implements_list: |     - implements_list: | ||||||
|         or_else_default: true |         build: | ||||||
|  |           or_else_default: true | ||||||
|     - class_level_declarations: |     - class_level_declarations: | ||||||
|         rule: ClassLevelDeclaration |         rule: ClassLevelDeclaration | ||||||
|         vec: true |         vec: true | ||||||
| @ -155,11 +160,11 @@ Function: | |||||||
|         skip: true |         skip: true | ||||||
|     - generics: |     - generics: | ||||||
|         rule: GenericParameters |         rule: GenericParameters | ||||||
|         or_else_default: true |  | ||||||
|     - identifier |     - identifier | ||||||
|     - parameters |     - parameters | ||||||
|     - return_type: |     - return_type: | ||||||
|         or_else: void |         build: | ||||||
|  |           or_else: void | ||||||
|     - function_body |     - function_body | ||||||
| OperatorFunction: | OperatorFunction: | ||||||
|   children: |   children: | ||||||
| @ -173,11 +178,13 @@ OperatorFunction: | |||||||
|         skip: true |         skip: true | ||||||
|     - generics: |     - generics: | ||||||
|         rule: GenericParameters |         rule: GenericParameters | ||||||
|         or_else_default: true |         build: | ||||||
|  |           or_else_default: true | ||||||
|     - operator |     - operator | ||||||
|     - parameters |     - parameters | ||||||
|     - return_type: |     - return_type: | ||||||
|         or_else: void |         build: | ||||||
|  |           or_else: void | ||||||
|     - function_body |     - function_body | ||||||
| PlatformFunction: | PlatformFunction: | ||||||
|   children: |   children: | ||||||
| @ -194,7 +201,8 @@ PlatformFunction: | |||||||
|         skip: true |         skip: true | ||||||
|     - generics: |     - generics: | ||||||
|         rule: GenericParameters |         rule: GenericParameters | ||||||
|         or_else_default: true |         build: | ||||||
|  |           or_else_default: true | ||||||
|     - identifier |     - identifier | ||||||
|     - parameters |     - parameters | ||||||
|     - return_type |     - return_type | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 Jesse Brault
						Jesse Brault