@@ -15,22 +15,26 @@ use crate::{to_parser_input::to_parser_input, tt_iter::TtIter, TokenMap};
15
15
/// Convert the syntax node to a `TokenTree` (what macro
16
16
/// will consume).
17
17
pub fn syntax_node_to_token_tree ( node : & SyntaxNode ) -> ( tt:: Subtree , TokenMap ) {
18
- syntax_node_to_token_tree_censored ( node, & Default :: default ( ) )
18
+ syntax_node_to_token_tree_censored ( node, Default :: default ( ) , Default :: default ( ) )
19
19
}
20
20
21
+ // TODO rename
21
22
/// Convert the syntax node to a `TokenTree` (what macro will consume)
22
23
/// with the censored range excluded.
23
24
pub fn syntax_node_to_token_tree_censored (
24
25
node : & SyntaxNode ,
25
- censor : & FxHashSet < SyntaxNode > ,
26
+ replace : FxHashMap < SyntaxNode , Vec < SyntheticToken > > ,
27
+ append : FxHashMap < SyntaxNode , Vec < SyntheticToken > > ,
26
28
) -> ( tt:: Subtree , TokenMap ) {
27
29
let global_offset = node. text_range ( ) . start ( ) ;
28
- let mut c = Convertor :: new ( node, global_offset, censor ) ;
30
+ let mut c = Convertor :: new ( node, global_offset, replace , append ) ;
29
31
let subtree = convert_tokens ( & mut c) ;
30
32
c. id_alloc . map . shrink_to_fit ( ) ;
31
33
( subtree, c. id_alloc . map )
32
34
}
33
35
36
+ pub type SyntheticToken = ( SyntaxKind , SmolStr ) ;
37
+
34
38
// The following items are what `rustc` macro can be parsed into :
35
39
// link: https://github.com/rust-lang/rust/blob/9ebf47851a357faa4cd97f4b1dc7835f6376e639/src/libsyntax/ext/expand.rs#L141
36
40
// * Expr(P<ast::Expr>) -> token_tree_to_expr
@@ -465,86 +469,124 @@ impl<'a> TokenConvertor for RawConvertor<'a> {
465
469
}
466
470
}
467
471
468
- struct Convertor < ' c > {
472
+ struct Convertor {
469
473
id_alloc : TokenIdAlloc ,
470
474
current : Option < SyntaxToken > ,
475
+ current_synthetic : Vec < SyntheticToken > ,
471
476
preorder : PreorderWithTokens ,
472
- censor : & ' c FxHashSet < SyntaxNode > ,
477
+ replace : FxHashMap < SyntaxNode , Vec < SyntheticToken > > ,
478
+ append : FxHashMap < SyntaxNode , Vec < SyntheticToken > > ,
473
479
range : TextRange ,
474
480
punct_offset : Option < ( SyntaxToken , TextSize ) > ,
475
481
}
476
482
477
- impl < ' c > Convertor < ' c > {
483
+ impl Convertor {
478
484
fn new (
479
485
node : & SyntaxNode ,
480
486
global_offset : TextSize ,
481
- censor : & ' c FxHashSet < SyntaxNode > ,
482
- ) -> Convertor < ' c > {
487
+ replace : FxHashMap < SyntaxNode , Vec < SyntheticToken > > ,
488
+ append : FxHashMap < SyntaxNode , Vec < SyntheticToken > > ,
489
+ ) -> Convertor {
483
490
let range = node. text_range ( ) ;
484
491
let mut preorder = node. preorder_with_tokens ( ) ;
485
- let first = Self :: next_token ( & mut preorder, censor ) ;
492
+ let ( first, synthetic ) = Self :: next_token ( & mut preorder, & replace , & append ) ;
486
493
Convertor {
487
494
id_alloc : { TokenIdAlloc { map : TokenMap :: default ( ) , global_offset, next_id : 0 } } ,
488
495
current : first,
496
+ current_synthetic : synthetic,
489
497
preorder,
490
498
range,
491
- censor,
499
+ replace,
500
+ append,
492
501
punct_offset : None ,
493
502
}
494
503
}
495
504
496
505
fn next_token (
497
506
preorder : & mut PreorderWithTokens ,
498
- censor : & FxHashSet < SyntaxNode > ,
499
- ) -> Option < SyntaxToken > {
507
+ replace : & FxHashMap < SyntaxNode , Vec < SyntheticToken > > ,
508
+ append : & FxHashMap < SyntaxNode , Vec < SyntheticToken > > ,
509
+ ) -> ( Option < SyntaxToken > , Vec < SyntheticToken > ) {
500
510
while let Some ( ev) = preorder. next ( ) {
501
511
let ele = match ev {
502
512
WalkEvent :: Enter ( ele) => ele,
513
+ WalkEvent :: Leave ( SyntaxElement :: Node ( node) ) => {
514
+ if let Some ( v) = append. get ( & node) {
515
+ eprintln ! ( "after {:?}, appending {:?}" , node, v) ;
516
+ if !v. is_empty ( ) {
517
+ let mut reversed = v. clone ( ) ;
518
+ reversed. reverse ( ) ;
519
+ return ( None , reversed) ;
520
+ }
521
+ }
522
+ continue ;
523
+ }
503
524
_ => continue ,
504
525
} ;
505
526
match ele {
506
- SyntaxElement :: Token ( t) => return Some ( t) ,
507
- SyntaxElement :: Node ( node) if censor. contains ( & node) => preorder. skip_subtree ( ) ,
508
- SyntaxElement :: Node ( _) => ( ) ,
527
+ SyntaxElement :: Token ( t) => return ( Some ( t) , Vec :: new ( ) ) ,
528
+ SyntaxElement :: Node ( node) => {
529
+ if let Some ( v) = replace. get ( & node) {
530
+ preorder. skip_subtree ( ) ;
531
+ eprintln ! ( "replacing {:?} by {:?}" , node, v) ;
532
+ if !v. is_empty ( ) {
533
+ let mut reversed = v. clone ( ) ;
534
+ reversed. reverse ( ) ;
535
+ return ( None , reversed) ;
536
+ }
537
+ }
538
+ }
509
539
}
510
540
}
511
- None
541
+ ( None , Vec :: new ( ) )
512
542
}
513
543
}
514
544
515
545
#[ derive( Debug ) ]
516
546
enum SynToken {
517
547
Ordinary ( SyntaxToken ) ,
548
+ // FIXME is this supposed to be `Punct`?
518
549
Punch ( SyntaxToken , TextSize ) ,
550
+ Synthetic ( SyntheticToken ) ,
519
551
}
520
552
521
553
impl SynToken {
522
- fn token ( & self ) -> & SyntaxToken {
554
+ fn token ( & self ) -> Option < & SyntaxToken > {
523
555
match self {
524
- SynToken :: Ordinary ( it) | SynToken :: Punch ( it, _) => it,
556
+ SynToken :: Ordinary ( it) | SynToken :: Punch ( it, _) => Some ( it) ,
557
+ SynToken :: Synthetic ( _) => None ,
525
558
}
526
559
}
527
560
}
528
561
529
- impl < ' a > SrcToken < Convertor < ' a > > for SynToken {
530
- fn kind ( & self , _ctx : & Convertor < ' a > ) -> SyntaxKind {
531
- self . token ( ) . kind ( )
562
+ impl SrcToken < Convertor > for SynToken {
563
+ fn kind ( & self , _ctx : & Convertor ) -> SyntaxKind {
564
+ match self {
565
+ SynToken :: Ordinary ( token) => token. kind ( ) ,
566
+ SynToken :: Punch ( token, _) => token. kind ( ) ,
567
+ SynToken :: Synthetic ( ( kind, _) ) => * kind,
568
+ }
532
569
}
533
- fn to_char ( & self , _ctx : & Convertor < ' a > ) -> Option < char > {
570
+ fn to_char ( & self , _ctx : & Convertor ) -> Option < char > {
534
571
match self {
535
572
SynToken :: Ordinary ( _) => None ,
536
573
SynToken :: Punch ( it, i) => it. text ( ) . chars ( ) . nth ( ( * i) . into ( ) ) ,
574
+ SynToken :: Synthetic ( _) => None ,
537
575
}
538
576
}
539
- fn to_text ( & self , _ctx : & Convertor < ' a > ) -> SmolStr {
540
- self . token ( ) . text ( ) . into ( )
577
+ fn to_text ( & self , _ctx : & Convertor ) -> SmolStr {
578
+ match self {
579
+ SynToken :: Ordinary ( token) => token. text ( ) . into ( ) ,
580
+ SynToken :: Punch ( token, _) => token. text ( ) . into ( ) ,
581
+ SynToken :: Synthetic ( ( _, text) ) => text. clone ( ) ,
582
+ }
541
583
}
542
584
}
543
585
544
- impl TokenConvertor for Convertor < ' _ > {
586
+ impl TokenConvertor for Convertor {
545
587
type Token = SynToken ;
546
588
fn convert_doc_comment ( & self , token : & Self :: Token ) -> Option < Vec < tt:: TokenTree > > {
547
- convert_doc_comment ( token. token ( ) )
589
+ convert_doc_comment ( token. token ( ) ? )
548
590
}
549
591
550
592
fn bump ( & mut self ) -> Option < ( Self :: Token , TextRange ) > {
@@ -558,11 +600,25 @@ impl TokenConvertor for Convertor<'_> {
558
600
}
559
601
}
560
602
603
+ if let Some ( synth_token) = self . current_synthetic . pop ( ) {
604
+ if self . current_synthetic . is_empty ( ) {
605
+ let ( new_current, new_synth) =
606
+ Self :: next_token ( & mut self . preorder , & self . replace , & self . append ) ;
607
+ self . current = new_current;
608
+ self . current_synthetic = new_synth;
609
+ }
610
+ // TODO fix range?
611
+ return Some ( ( SynToken :: Synthetic ( synth_token) , self . range ) ) ;
612
+ }
613
+
561
614
let curr = self . current . clone ( ) ?;
562
615
if !& self . range . contains_range ( curr. text_range ( ) ) {
563
616
return None ;
564
617
}
565
- self . current = Self :: next_token ( & mut self . preorder , self . censor ) ;
618
+ let ( new_current, new_synth) =
619
+ Self :: next_token ( & mut self . preorder , & self . replace , & self . append ) ;
620
+ self . current = new_current;
621
+ self . current_synthetic = new_synth;
566
622
let token = if curr. kind ( ) . is_punct ( ) {
567
623
self . punct_offset = Some ( ( curr. clone ( ) , 0 . into ( ) ) ) ;
568
624
let range = curr. text_range ( ) ;
@@ -585,6 +641,11 @@ impl TokenConvertor for Convertor<'_> {
585
641
}
586
642
}
587
643
644
+ if let Some ( synth_token) = self . current_synthetic . last ( ) {
645
+ // TODO fix range?
646
+ return Some ( SynToken :: Synthetic ( synth_token. clone ( ) ) ) ;
647
+ }
648
+
588
649
let curr = self . current . clone ( ) ?;
589
650
if !self . range . contains_range ( curr. text_range ( ) ) {
590
651
return None ;
0 commit comments