13
13
//! )
14
14
//! ```
15
15
16
- use crate :: { extract_spans , Diagnostic } ;
16
+ use crate :: Diagnostic ;
17
17
use once_cell:: sync:: Lazy ;
18
18
use proc_macro2:: { Span , TokenStream } ;
19
19
use quote:: quote;
@@ -25,10 +25,9 @@ use std::{
25
25
} ;
26
26
use syn:: {
27
27
self ,
28
- parse:: { Parse , ParseStream , Result as ParseResult } ,
29
- parse2,
28
+ parse:: { ParseStream , Parser , Result as ParseResult } ,
30
29
spanned:: Spanned ,
31
- Lit , LitByteStr , LitStr , Macro , Meta , MetaNameValue , Token ,
30
+ LitByteStr , LitStr , Macro ,
32
31
} ;
33
32
34
33
static CARGO_MANIFEST_DIR : Lazy < PathBuf > = Lazy :: new ( || {
@@ -233,83 +232,76 @@ impl CompilationSource {
233
232
}
234
233
}
235
234
236
- /// This is essentially just a comma-separated list of Meta nodes, aka the inside of a MetaList.
237
- struct PyCompileInput {
238
- span : Span ,
239
- metas : Vec < Meta > ,
240
- }
241
-
242
- impl PyCompileInput {
243
- fn parse ( & self , allow_dir : bool ) -> Result < PyCompileArgs , Diagnostic > {
235
+ impl PyCompileArgs {
236
+ fn parse ( input : TokenStream , allow_dir : bool ) -> Result < PyCompileArgs , Diagnostic > {
244
237
let mut module_name = None ;
245
238
let mut mode = None ;
246
239
let mut source: Option < CompilationSource > = None ;
247
240
let mut crate_name = None ;
248
241
249
- fn assert_source_empty ( source : & Option < CompilationSource > ) -> Result < ( ) , Diagnostic > {
242
+ fn assert_source_empty ( source : & Option < CompilationSource > ) -> Result < ( ) , syn :: Error > {
250
243
if let Some ( source) = source {
251
- Err ( Diagnostic :: spans_error (
252
- source. span ,
244
+ Err ( syn :: Error :: new (
245
+ source. span . 0 ,
253
246
"Cannot have more than one source" ,
254
247
) )
255
248
} else {
256
249
Ok ( ( ) )
257
250
}
258
251
}
259
252
260
- for meta in & self . metas {
261
- if let Meta :: NameValue ( name_value) = meta {
262
- let ident = match name_value. path . get_ident ( ) {
263
- Some ( ident) => ident,
264
- None => continue ,
265
- } ;
266
- let check_str = || match & name_value. lit {
267
- Lit :: Str ( s) => Ok ( s) ,
268
- _ => Err ( err_span ! ( name_value. lit, "{ident} must be a string" ) ) ,
269
- } ;
270
- if ident == "mode" {
271
- let s = check_str ( ) ?;
272
- match s. value ( ) . parse ( ) {
273
- Ok ( mode_val) => mode = Some ( mode_val) ,
274
- Err ( e) => bail_span ! ( s, "{}" , e) ,
275
- }
276
- } else if ident == "module_name" {
277
- module_name = Some ( check_str ( ) ?. value ( ) )
278
- } else if ident == "source" {
279
- assert_source_empty ( & source) ?;
280
- let code = check_str ( ) ?. value ( ) ;
281
- source = Some ( CompilationSource {
282
- kind : CompilationSourceKind :: SourceCode ( code) ,
283
- span : extract_spans ( & name_value) . unwrap ( ) ,
284
- } ) ;
285
- } else if ident == "file" {
286
- assert_source_empty ( & source) ?;
287
- let path = check_str ( ) ?. value ( ) . into ( ) ;
288
- source = Some ( CompilationSource {
289
- kind : CompilationSourceKind :: File ( path) ,
290
- span : extract_spans ( & name_value) . unwrap ( ) ,
291
- } ) ;
292
- } else if ident == "dir" {
293
- if !allow_dir {
294
- bail_span ! ( ident, "py_compile doesn't accept dir" )
295
- }
296
-
297
- assert_source_empty ( & source) ?;
298
- let path = check_str () ?. value ( ) . into ( ) ;
299
- source = Some ( CompilationSource {
300
- kind : CompilationSourceKind :: Dir ( path) ,
301
- span : extract_spans ( & name_value) . unwrap ( ) ,
302
- } ) ;
303
- } else if ident == "crate_name" {
304
- let name = check_str ( ) ?. parse ( ) ?;
305
- crate_name = Some ( name) ;
253
+ syn:: meta:: parser ( |meta| {
254
+ let ident = meta
255
+ . path
256
+ . get_ident ( )
257
+ . ok_or_else ( || meta. error ( "unknown arg" ) ) ?;
258
+ let check_str = || meta. value ( ) ?. call ( parse_str) ;
259
+ if ident == "mode" {
260
+ let s = check_str ( ) ?;
261
+ match s. value ( ) . parse ( ) {
262
+ Ok ( mode_val) => mode = Some ( mode_val) ,
263
+ Err ( e) => bail_span ! ( s, "{}" , e) ,
264
+ }
265
+ } else if ident == "module_name" {
266
+ module_name = Some ( check_str ( ) ?. value ( ) )
267
+ } else if ident == "source" {
268
+ assert_source_empty ( & source) ?;
269
+ let code = check_str ( ) ?. value ( ) ;
270
+ source = Some ( CompilationSource {
271
+ kind : CompilationSourceKind :: SourceCode ( code) ,
272
+ span : ( ident. span ( ) , meta. input . cursor ( ) . span ( ) ) ,
273
+ } ) ;
274
+ } else if ident == "file" {
275
+ assert_source_empty ( & source) ?;
276
+ let path = check_str ( ) ?. value ( ) . into ( ) ;
277
+ source = Some ( CompilationSource {
278
+ kind : CompilationSourceKind :: File ( path) ,
279
+ span : ( ident. span ( ) , meta. input . cursor ( ) . span ( ) ) ,
280
+ } ) ;
281
+ } else if ident == "dir" {
282
+ if !allow_dir {
283
+ bail_span ! ( ident, "py_compile doesn't accept dir" )
306
284
}
285
+
286
+ assert_source_empty
E377
span>( & source) ?;
287
+ let path = check_str ( ) ?. value ( ) . into ( ) ;
288
+ source = Some ( CompilationSource {
289
+ kind : CompilationSourceKind :: Dir ( path) ,
290
+ span : ( ident. span ( ) , meta. input . cursor ( ) . span ( ) ) ,
291
+ } ) ;
292
+ } else if ident == "crate_name" {
293
+ let name = check_str ( ) ?. parse ( ) ?;
294
+ crate_name = Some ( name) ;
295
+ } else {
296
+ return Err ( meta. error ( "unknown attr" ) ) ;
307
297
}
308
- }
298
+ Ok ( ( ) )
299
+ } )
300
+ . parse2 ( input) ?;
309
301
310
302
let source = source. ok_or_else ( || {
311
303
syn:: Error :: new (
312
- self . span ,
304
+ Span :: call_site ( ) ,
313
305
"Must have either file or source in py_compile!()/py_freeze!()" ,
314
306
)
315
307
} ) ?;
@@ -323,38 +315,17 @@ impl PyCompileInput {
323
315
}
324
316
}
325
317
326
- fn parse_meta ( input : ParseStream ) -> ParseResult < Meta > {
327
- let path = input. call ( syn:: Path :: parse_mod_style) ?;
328
- let eq_token: Token ! [ =] = input. parse ( ) ?;
318
+ fn parse_str ( input : ParseStream ) -> ParseResult < LitStr > {
329
319
let span = input. span ( ) ;
330
320
if input. peek ( LitStr ) {
331
- Ok ( Meta :: NameValue ( MetaNameValue {
332
- path,
333
- eq_token,
334
- lit : Lit :: Str ( input. parse ( ) ?) ,
335
- } ) )
321
+ input. parse ( )
336
322
} else if let Ok ( mac) = input. parse :: < Macro > ( ) {
337
- Ok ( Meta :: NameValue ( MetaNameValue {
338
- path,
339
- eq_token,
340
- lit : Lit :: Str ( LitStr :: new ( & mac. tokens . to_string ( ) , mac. span ( ) ) ) ,
341
- } ) )
323
+ Ok ( LitStr :: new ( & mac. tokens . to_string ( ) , mac. span ( ) ) )
342
324
} else {
343
325
Err ( syn:: Error :: new ( span, "Expected string or stringify macro" ) )
344
326
}
345
327
}
346
328
347
- impl Parse for PyCompileInput {
348
- fn parse ( input : ParseStream ) -> ParseResult < Self > {
349
- let span = input. cursor ( ) . span ( ) ;
350
- let metas = input
351
- . parse_terminated :: < Meta , Token ! [ , ] > ( parse_meta) ?
352
- . into_iter ( )
353
- . collect ( ) ;
354
- Ok ( PyCompileInput { span, metas } )
355
- }
356
- }
357
-
358
329
struct PyCompileArgs {
359
330
source : CompilationSource ,
360
331
mode : Mode ,
@@ -366,8 +337,7 @@ pub fn impl_py_compile(
366
337
input : TokenStream ,
367
338
compiler : & dyn Compiler ,
368
339
) -> Result < TokenStream , Diagnostic > {
369
- let input: PyCompileInput = parse2 ( input) ?;
370
- let args = input. parse ( false ) ?;
340
+ let args = PyCompileArgs :: parse ( input, false ) ?;
371
341
372
342
let crate_name = args. crate_name ;
373
343
let code = args
@@ -388,8 +358,7 @@ pub fn impl_py_freeze(
388
358
input : TokenStream ,
389
359
compiler : & dyn Compiler ,
390
360
) -> Result < TokenStream , Diagnostic > {
391
- let input: PyCompileInput = parse2 ( input) ?;
392
- let args = input. parse ( true ) ?;
361
+ let args = PyCompileArgs :: parse ( input, true ) ?;
393
362
394
363
let crate_name = args. crate_name ;
395
364
let code_map = args. source . compile ( args. mode , args. module_name , compiler) ?;
0 commit comments