@@ -6,7 +6,6 @@ use boolinator::Boolinator;
6
6
use proc_macro2:: Span ;
7
7
use quote:: { quote, quote_spanned, ToTokens } ;
8
8
use std:: cmp:: Ordering ;
9
- use std:: collections:: HashMap ;
10
9
use syn:: buffer:: Cursor ;
11
10
use syn:: parse;
12
11
use syn:: parse:: { Parse , ParseStream , Result as ParseResult } ;
@@ -341,17 +340,22 @@ impl ToTokens for HtmlComponentClose {
341
340
}
342
341
}
343
342
344
- enum PropType {
345
- List ,
346
- With ,
347
- }
348
-
349
343
enum Props {
350
344
List ( Box < ListProps > ) ,
351
345
With ( Box < WithProps > ) ,
352
346
None ,
353
347
}
354
348
349
+ struct ListProps {
350
+ props : Vec < HtmlProp > ,
351
+ node_ref : Option < Expr > ,
352
+ }
353
+
354
+ struct WithProps {
355
+ props : Ident ,
356
+ node_ref : Option < Expr > ,
357
+ }
358
+
355
359
impl Props {
356
360
fn node_ref ( & self ) -> Option < & Expr > {
357
361
match self {
@@ -360,181 +364,97 @@ impl Props {
360
364
Props :: None => None ,
361
365
}
362
366
}
367
+
363
368
fn collision_message ( ) -> & ' static str {
364
369
"Using special syntax `with props` along with named prop is not allowed. This rule does not apply to special `ref` prop"
365
370
}
371
+ }
366
372
367
- fn collect_props ( input : ParseStream ) -> ParseResult < Vec < HtmlProp > > {
368
- let mut props: Vec < HtmlProp > = Vec :: new ( ) ;
369
- while HtmlProp :: peek ( input. cursor ( ) ) . is_some ( ) {
370
- props. push ( input. parse :: < HtmlProp > ( ) ?) ;
371
- }
372
- Ok ( props)
373
- }
374
-
375
- fn remove_refs ( mut props : Vec < HtmlProp > ) -> ListProps {
376
- let ref_position = props. iter ( ) . position ( |p| p. label . to_string ( ) == "ref" ) ;
377
- let node_ref = ref_position. map ( |i| props. remove ( i) . value ) ;
378
- ListProps { props, node_ref }
379
- }
380
-
381
- fn return_type ( input : ParseStream ) -> ParseResult < PropType > {
382
- let stream = input. fork ( ) ;
383
- let mut is_with = false ;
384
- let mut ref_counter = 0 ;
385
- let mut props_counter = 0 ;
373
+ impl Parse for Props {
374
+ fn parse ( input : ParseStream ) -> ParseResult < Self > {
375
+ let mut props = Props :: None ;
376
+ let mut node_ref: Option < Expr > = None ;
386
377
387
- while let Some ( ( token, _) ) = stream. cursor ( ) . ident ( ) {
388
- let prop_value = stream. parse :: < HtmlProp > ( ) ;
378
+ while let Some ( ( token, _) ) = input. cursor ( ) . ident ( ) {
389
379
if token == "with" {
390
- is_with = true ;
391
- }
392
- if is_with && ( props_counter - ref_counter) > 0 {
393
- return Err ( syn:: Error :: new_spanned ( & token, Props :: collision_message ( ) ) ) ;
380
+ match props {
381
+ Props :: None => Ok ( ( ) ) ,
382
+ Props :: With ( _) => Err ( input. error ( "too many `with` tokens used" ) ) ,
383
+ Props :: List ( _) => Err ( syn:: Error :: new_spanned ( & token, Props :: collision_message ( ) ) ) ,
384
+ } ?;
385
+
386
+ input. parse :: < Ident > ( ) ?;
387
+ props = Props :: With ( Box :: new ( WithProps {
388
+ props : input. parse :: < Ident > ( ) ?,
389
+ node_ref : None ,
390
+ } ) ) ;
391
+
392
+ // Handle optional comma
393
+ let _ = input. parse :: < Token ! [ , ] > ( ) ;
394
+ continue ;
394
395
}
395
- if let Ok ( prop) = prop_value {
396
- if prop. label . to_string ( ) == "ref" {
397
- ref_counter = ref_counter + 1 ;
398
- if ref_counter > 1 {
399
- return Err ( syn:: Error :: new_spanned ( & prop. label , "too many refs set" ) ) ;
400
- }
401
- } else {
402
- if is_with {
403
- return Err ( syn:: Error :: new_spanned ( & token, Props :: collision_message ( ) ) ) ;
404
- }
405
- }
406
- if prop. label . to_string ( ) == "type" {
407
- return Err ( syn:: Error :: new_spanned ( & prop. label , "expected identifier" ) ) ;
408
- }
409
- if !prop. label . extended . is_empty ( ) {
410
- return Err ( syn:: Error :: new_spanned ( & prop. label , "expected identifier" ) ) ;
411
- }
412
- props_counter = props_counter + 1 ;
413
- }
414
- }
415
- if is_with {
416
- Ok ( PropType :: With )
417
- } else {
418
- Ok ( PropType :: List )
419
- }
420
- }
421
-
422
- fn get_type ( input : ParseStream ) -> ParseResult < Option < PropType > > {
423
- let props_type = match Props :: return_type ( input) {
424
- Ok ( props) => Some ( props) ,
425
- Err ( _) => None ,
426
- } ;
427
-
428
- match props_type {
429
- Some ( PropType :: With ) => println ! ( "props_type::with" ) ,
430
- Some ( PropType :: List ) => println ! ( "props_type::list" ) ,
431
- None => println ! ( "none" ) ,
432
- }
433
- let _ = Props :: collect_props ( input) ?;
434
-
435
- println ! ( "RETURN TYPE" ) ;
436
- Ok ( props_type)
437
- }
438
- }
439
-
440
- impl PeekValue < PropType > for Props {
441
- fn peek ( cursor : Cursor ) -> Option < PropType > {
442
- let ( ident, _) = cursor. ident ( ) ?;
443
396
444
- let prop_type = if ident == "with" {
445
- PropType :: With
446
- } else {
447
- PropType :: List
448
- } ;
449
-
450
- Some ( prop_type)
451
- }
452
- }
453
-
454
- impl Parse for Props {
455
- fn parse ( input : ParseStream ) -> ParseResult < Self > {
456
- match Props :: get_type ( input) ? {
457
- Some ( PropType :: List ) => input. parse ( ) . map ( |l| Props :: List ( Box :: new ( l) ) ) ,
458
- Some ( PropType :: With ) => {
459
- let result = input. parse ( ) . map ( |w| Props :: With ( Box :: new ( w) ) ) ;
460
- match result {
461
- Ok ( v) => Ok ( v) ,
462
- Err ( e) => {
463
- println ! ( "MY ERROR" ) ;
464
- return Err ( input. error ( "MY" ) ) ;
465
- }
466
- }
397
+ if ( HtmlProp :: peek ( input. cursor ( ) ) ) . is_none ( ) {
398
+ break ;
467
399
}
468
- None => Ok ( Props :: None ) ,
469
- }
470
- }
471
- }
472
400
473
- struct ListProps {
474
- props : Vec < HtmlProp > ,
475
- node_ref : Option < Expr > ,
476
- }
401
+ let prop = input. parse :: < HtmlProp > ( ) ?;
402
+ if prop. label . to_string ( ) == "ref" {
403
+ match node_ref {
404
+ None => Ok ( ( ) ) ,
405
+ Some ( _) => Err ( syn:: Error :: new_spanned ( & prop. label , "too many refs set" ) ) ,
406
+ } ?;
477
407
478
- impl Parse for ListProps {
479
- fn parse ( input : ParseStream ) -> ParseResult < Self > {
480
- let ListProps {
481
- mut props,
482
- node_ref,
483
- } = Props :: remove_refs ( Props :: collect_props ( input) ?) ;
484
-
485
- // alphabetize
486
- props. sort_by ( |a, b| {
487
- if a. label == b. label {
488
- Ordering :: Equal
489
- } else if a. label . to_string ( ) == "children" {
490
- Ordering :: Greater
491
- } else if b. label . to_string ( ) == "children" {
492
- Ordering :: Less
493
- } else {
494
- a. label
495
- . to_string ( )
496
- . partial_cmp ( & b. label . to_string ( ) )
497
- . unwrap ( )
408
+ node_ref = Some ( prop. value ) ;
409
+ continue ;
498
410
}
499
- } ) ;
500
411
501
- Ok ( ListProps { props , node_ref } )
502
- }
503
- }
412
+ if prop . label . to_string ( ) == "type" {
413
+ return Err ( syn :: Error :: new_spanned ( & prop . label , "expected identifier" ) ) ;
414
+ }
504
415
505
- struct WithProps {
506
- props : Ident ,
507
- node_ref : Option < Expr > ,
508
- }
416
+ if !prop. label . extended . is_empty ( ) {
417
+ return Err ( syn:: Error :: new_spanned ( & prop. label , "expected identifier" ) ) ;
418
+ }
509
419
510
- impl Parse for WithProps {
511
- fn parse ( input : ParseStream ) -> ParseResult < Self > {
512
- let with = input. parse :: < Ident > ( ) ?;
513
- if with != "with" {
514
- return Err ( input. error ( "expected to find `with` token" ) ) ;
420
+ match props {
421
+ ref mut props @ Props :: None => {
422
+ * props = Props :: List ( Box :: new ( ListProps {
423
+ props : vec ! [ prop] ,
424
+ node_ref : None ,
425
+ } ) ) ;
426
+ } ,
427
+ Props :: With ( _) => return Err ( syn:: Error :: new_spanned ( & token, Props :: collision_message ( ) ) ) ,
428
+ Props :: List ( ref mut list) => {
429
+ list. props . push ( prop) ;
430
+ }
431
+ } ;
515
432
}
516
- let props = input. parse :: < Ident > ( ) ?;
517
-
518
- let _ = input. parse :: < Token ! [ , ] > ( ) ;
519
-
520
- // Check for the ref tag after `with`
521
- let mut node_ref = None ;
522
433
523
- if input. cursor ( ) . ident ( ) . is_some ( ) {
524
- let ListProps {
525
- node_ref : reference,
526
- ..
527
- } = Props :: remove_refs ( Props :: collect_props ( input) ?) ;
528
- node_ref = reference;
529
-
530
- if let Some ( ident) = input. cursor ( ) . ident ( ) {
531
- let prop = input. parse :: < HtmlProp > ( ) ?;
532
- if ident. 0 == "ref" {
533
- node_ref = Some ( prop. value ) ;
534
- }
434
+ match props {
435
+ Props :: None => { } ,
436
+ Props :: With ( ref mut p) => p. node_ref = node_ref,
437
+ Props :: List ( ref mut p) => {
438
+ p. node_ref = node_ref;
439
+
440
+ // alphabetize
441
+ p. props . sort_by ( |a, b| {
442
+ if a. label == b. label {
443
+ Ordering :: Equal
444
+ } else if a. label . to_string ( ) == "children" {
445
+ Ordering :: Greater
446
+ } else if b. label . to_string ( ) == "children" {
447
+ Ordering :: Less
448
+ } else {
449
+ a. label
450
+ . to_string ( )
451
+ . partial_cmp ( & b. label . to_string ( ) )
452
+ . unwrap ( )
453
+ }
454
+ } ) ;
535
455
}
536
- }
456
+ } ;
537
457
538
- Ok ( WithProps { props, node_ref } )
458
+ Ok ( props)
539
459
}
540
460
}
0 commit comments