@@ -2,7 +2,7 @@ use convert_case::{Case, Casing};
22use std:: io:: Write ;
33use std:: path:: Path ;
44
5- use proc_macro2:: { Ident , Span , TokenStream , TokenTree } ;
5+ use proc_macro2:: { Ident , Span , TokenStream } ;
66use quote:: { quote, ToTokens } ;
77use syn:: { self , parse:: Parse , parse:: ParseStream , parse_macro_input, Expr , FnArg , LitStr , Token } ;
88
@@ -164,6 +164,49 @@ impl Parse for ShopifyFunctionTargetArgs {
164164 }
165165}
166166
167+ #[ derive( Clone , Default ) ]
168+ struct GenerateTypeArgs {
169+ query_path : Option < LitStr > ,
170+ schema_path : Option < LitStr > ,
171+ input_stream : Option < Expr > ,
172+ output_stream : Option < Expr > ,
173+ }
174+
175+ impl GenerateTypeArgs {
176+ fn parse < K : syn:: parse:: Parse , V : syn:: parse:: Parse > (
177+ input : & ParseStream < ' _ > ,
178+ ) -> syn:: Result < V > {
179+ input. parse :: < K > ( ) ?;
180+ input. parse :: < Token ! [ =] > ( ) ?;
181+ let value: V = input. parse ( ) ?;
182+ if input. lookahead1 ( ) . peek ( Token ! [ , ] ) {
183+ input. parse :: < Token ! [ , ] > ( ) ?;
184+ }
185+ Ok ( value)
186+ }
187+ }
188+
189+ impl Parse for GenerateTypeArgs {
190+ fn parse ( input : syn:: parse:: ParseStream ) -> syn:: Result < Self > {
191+ let mut args = Self :: default ( ) ;
192+ while !input. is_empty ( ) {
193+ let lookahead = input. lookahead1 ( ) ;
194+ if lookahead. peek ( kw:: query_path) {
195+ args. query_path = Some ( Self :: parse :: < kw:: query_path , LitStr > ( & input) ?) ;
196+ } else if lookahead. peek ( kw:: schema_path) {
197+ args. schema_path = Some ( Self :: parse :: < kw:: schema_path , LitStr > ( & input) ?) ;
198+ } else if lookahead. peek ( kw:: input_stream) {
199+ args. input_stream = Some ( Self :: parse :: < kw:: input_stream , Expr > ( & input) ?) ;
200+ } else if lookahead. peek ( kw:: output_stream) {
201+ args. output_stream = Some ( Self :: parse :: < kw:: output_stream , Expr > ( & input) ?) ;
202+ } else {
203+ return Err ( lookahead. error ( ) ) ;
204+ }
205+ }
206+ Ok ( args)
207+ }
208+ }
209+
167210fn extract_shopify_function_return_type ( ast : & syn:: ItemFn ) -> Result < & syn:: Ident , syn:: Error > {
168211 use syn:: * ;
169212
@@ -302,22 +345,6 @@ pub fn shopify_function_target(
302345 . into ( )
303346}
304347
305- fn extract_attr ( attrs : & TokenStream , attr : & str ) -> String {
306- let attrs: Vec < TokenTree > = attrs. clone ( ) . into_iter ( ) . collect ( ) ;
307- let attr_index = attrs
308- . iter ( )
309- . position ( |item| match item {
310- TokenTree :: Ident ( ident) => ident. to_string ( ) . as_str ( ) == attr,
311- _ => false ,
312- } )
313- . unwrap_or_else ( || panic ! ( "No attribute with name {} found" , attr) ) ;
314- let value = attrs
315- . get ( attr_index + 2 )
316- . unwrap_or_else ( || panic ! ( "No value given for {} attribute" , attr) )
317- . to_string ( ) ;
318- value. as_str ( ) [ 1 ..value. len ( ) - 1 ] . to_string ( )
319- }
320-
321348const OUTPUT_QUERY_FILE_NAME : & str = ".output.graphql" ;
322349
323350/// Generate the types to interact with Shopify's API.
@@ -338,13 +365,19 @@ const OUTPUT_QUERY_FILE_NAME: &str = ".output.graphql";
338365/// hope we can avoid creating this file at some point in the future.
339366#[ proc_macro]
340367pub fn generate_types ( attr : proc_macro:: TokenStream ) -> proc_macro:: TokenStream {
341- let params = TokenStream :: from ( attr) ;
342-
343- let query_path = extract_attr ( & params, "query_path" ) ;
344- let schema_path = extract_attr ( & params, "schema_path" ) ;
345-
346- let input_struct = generate_struct ( "Input" , & query_path, & schema_path) ;
347- let output_struct = generate_struct ( "Output" , OUTPUT_QUERY_FILE_NAME , & schema_path) ;
368+ let args = parse_macro_input ! ( attr as GenerateTypeArgs ) ;
369+
370+ let query_path = args
371+ . query_path
372+ . expect ( "No value given for query_path" )
373+ . value ( ) ;
374+ let schema_path = args
375+ . schema_path
376+ . expect ( "No value given for schema_path" )
377+ . value ( ) ;
378+
379+ let input_struct = generate_struct ( "Input" , query_path. as_str ( ) , schema_path. as_str ( ) ) ;
380+ let output_struct = generate_struct ( "Output" , OUTPUT_QUERY_FILE_NAME , schema_path. as_str ( ) ) ;
348381 let output_query =
349382 "mutation Output($result: FunctionResult!) {\n handleResult(result: $result)\n }\n " ;
350383
0 commit comments