@@ -2,7 +2,7 @@ use convert_case::{Case, Casing};
2
2
use std:: io:: Write ;
3
3
use std:: path:: Path ;
4
4
5
- use proc_macro2:: { Ident , Span , TokenStream , TokenTree } ;
5
+ use proc_macro2:: { Ident , Span , TokenStream } ;
6
6
use quote:: { quote, ToTokens } ;
7
7
use syn:: { self , parse:: Parse , parse:: ParseStream , parse_macro_input, Expr , FnArg , LitStr , Token } ;
8
8
@@ -164,6 +164,49 @@ impl Parse for ShopifyFunctionTargetArgs {
164
164
}
165
165
}
166
166
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
+
167
210
fn extract_shopify_function_return_type ( ast : & syn:: ItemFn ) -> Result < & syn:: Ident , syn:: Error > {
168
211
use syn:: * ;
169
212
@@ -302,22 +345,6 @@ pub fn shopify_function_target(
302
345
. into ( )
303
346
}
304
347
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
-
321
348
const OUTPUT_QUERY_FILE_NAME : & str = ".output.graphql" ;
322
349
323
350
/// Generate the types to interact with Shopify's API.
@@ -338,13 +365,19 @@ const OUTPUT_QUERY_FILE_NAME: &str = ".output.graphql";
338
365
/// hope we can avoid creating this file at some point in the future.
339
366
#[ proc_macro]
340
367
pub 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 ( ) ) ;
348
381
let output_query =
349
382
"mutation Output($result: FunctionResult!) {\n handleResult(result: $result)\n }\n " ;
350
383
0 commit comments