@@ -19,14 +19,14 @@ use crate::{
19
19
} ;
20
20
21
21
macro_rules! register_builtin {
22
- ( LAZY : $( ( $name: ident, $kind: ident) => $expand: ident) ,* , EAGER : $( ( $e_name: ident, $e_kind: ident) => $e_expand: ident) ,* ) => {
22
+ ( $ LAZY: ident : $( ( $name: ident, $kind: ident) => $expand: ident) ,* , $ EAGER: ident : $( ( $e_name: ident, $e_kind: ident) => $e_expand: ident) ,* ) => {
23
23
#[ derive( Debug , Clone , Copy , PartialEq , Eq , Hash ) ]
24
- pub enum BuiltinFnLikeExpander {
24
+ pub enum $LAZY {
25
25
$( $kind) ,*
26
26
}
27
27
28
28
#[ derive( Debug , Clone , Copy , PartialEq , Eq , Hash ) ]
29
- pub enum EagerExpander {
29
+ pub enum $EAGER {
30
30
$( $e_kind) ,*
31
31
}
32
32
@@ -84,6 +84,17 @@ impl EagerExpander {
84
84
pub fn is_include ( & self ) -> bool {
85
85
matches ! ( self , EagerExpander :: Include )
86
86
}
87
+
88
+ pub fn is_include_like ( & self ) -> bool {
89
+ matches ! (
90
+ self ,
91
+ EagerExpander :: Include | EagerExpander :: IncludeStr | EagerExpander :: IncludeBytes
92
+ )
93
+ }
94
+
95
+ pub fn is_env_or_option_env ( & self ) -> bool {
96
+ matches ! ( self , EagerExpander :: Env | EagerExpander :: OptionEnv )
97
+ }
87
98
}
88
99
89
100
pub fn find_builtin_macro (
@@ -93,7 +104,7 @@ pub fn find_builtin_macro(
93
104
}
94
105
95
106
register_builtin ! {
96
- LAZY :
107
+ BuiltinFnLikeExpander :
97
108
( column, Column ) => line_expand,
98
109
( file, File ) => file_expand,
99
110
( line, Line ) => line_expand,
@@ -114,7 +125,7 @@ register_builtin! {
114
125
( format_args_nl, FormatArgsNl ) => format_args_nl_expand,
115
126
( quote, Quote ) => quote_expand,
116
127
117
- EAGER :
128
+ EagerExpander :
118
129
( compile_error, CompileError ) => compile_error_expand,
119
130
( concat, Concat ) => concat_expand,
120
131
( concat_idents, ConcatIdents ) => concat_idents_expand,
@@ -426,22 +437,25 @@ fn use_panic_2021(db: &dyn ExpandDatabase, span: Span) -> bool {
426
437
}
427
438
}
428
439
429
- fn unquote_str ( lit : & tt:: Literal ) -> Option < String > {
440
+ fn unquote_str ( lit : & tt:: Literal ) -> Option < ( String , Span ) > {
441
+ let span = lit. span ;
430
442
let lit = ast:: make:: tokens:: literal ( & lit. to_string ( ) ) ;
431
443
let token = ast:: String :: cast ( lit) ?;
432
- token. value ( ) . map ( |it| it. into_owned ( ) )
444
+ token. value ( ) . map ( |it| ( it. into_owned ( ) , span ) )
433
445
}
434
446
435
- fn unquote_char ( lit : & tt:: Literal ) -> Option < char > {
447
+ fn unquote_char ( lit : & tt:: Literal ) -> Option < ( char , Span ) > {
448
+ let span = lit. span ;
436
449
let lit = ast:: make:: tokens:: literal ( & lit. to_string ( ) ) ;
437
450
let token = ast:: Char :: cast ( lit) ?;
438
- token. value ( )
451
+ token. value ( ) . zip ( Some ( span ) )
439
452
}
440
453
441
- fn unquote_byte_string ( lit : & tt:: Literal ) -> Option < Vec < u8 > > {
454
+ fn unquote_byte_string ( lit : & tt:: Literal ) -> Option < ( Vec < u8 > , Span ) > {
455
+ let span = lit. span ;
442
456
let lit = ast:: make:: tokens:: literal ( & lit. to_string ( ) ) ;
443
457
let token = ast:: ByteString :: cast ( lit) ?;
444
- token. value ( ) . map ( |it| it. into_owned ( ) )
458
+ token. value ( ) . map ( |it| ( it. into_owned ( ) , span ) )
445
459
}
446
460
447
461
fn compile_error_expand (
@@ -452,7 +466,7 @@ fn compile_error_expand(
452
466
) -> ExpandResult < tt:: Subtree > {
453
467
let err = match & * tt. token_trees {
454
468
[ tt:: TokenTree :: Leaf ( tt:: Leaf :: Literal ( it) ) ] => match unquote_str ( it) {
455
- Some ( unquoted) => ExpandError :: other ( unquoted. into_boxed_str ( ) ) ,
469
+ Some ( ( unquoted, _ ) ) => ExpandError :: other ( unquoted. into_boxed_str ( ) ) ,
456
470
None => ExpandError :: other ( "`compile_error!` argument must be a string" ) ,
457
471
} ,
458
472
_ => ExpandError :: other ( "`compile_error!` argument must be a string" ) ,
@@ -465,10 +479,16 @@ fn concat_expand(
465
479
_db : & dyn ExpandDatabase ,
466
480
_arg_id : MacroCallId ,
467
481
tt : & tt:: Subtree ,
468
- span : Span ,
482
+ _ : Span ,
469
483
) -> ExpandResult < tt:: Subtree > {
470
484
let mut err = None ;
471
485
let mut text = String :: new ( ) ;
486
+ let mut span: Option < Span > = None ;
487
+ let mut record_span = |s : Span | match & mut span {
488
+ Some ( span) if span. anchor == s. anchor => span. range = span. range . cover ( s. range ) ,
489
+ Some ( _) => ( ) ,
490
+ None => span = Some ( s) ,
491
+ } ;
472
492
for ( i, mut t) in tt. token_trees . iter ( ) . enumerate ( ) {
473
493
// FIXME: hack on top of a hack: `$e:expr` captures get surrounded in parentheses
474
494
// to ensure the right parsing order, so skip the parentheses here. Ideally we'd
@@ -486,44 +506,56 @@ fn concat_expand(
486
506
// concat works with string and char literals, so remove any quotes.
487
507
// It also works with integer, float and boolean literals, so just use the rest
488
508
// as-is.
489
- if let Some ( c ) = unquote_char ( it) {
509
+ if let Some ( ( c , span ) ) = unquote_char ( it) {
490
510
text. push ( c) ;
511
+ record_span ( span) ;
491
512
} else {
492
- let component = unquote_str ( it) . unwrap_or_else ( || it. text . to_string ( ) ) ;
513
+ let ( component, span) =
514
+ unquote_str ( it) . unwrap_or_else ( || ( it. text . to_string ( ) , it. span ) ) ;
493
515
text. push_str ( & component) ;
516
+ record_span ( span) ;
494
517
}
495
518
}
496
519
// handle boolean literals
497
520
tt:: TokenTree :: Leaf ( tt:: Leaf :: Ident ( id) )
498
521
if i % 2 == 0 && ( id. text == "true" || id. text == "false" ) =>
499
522
{
500
523
text. push_str ( id. text . as_str ( ) ) ;
524
+ record_span ( id. span ) ;
501
525
}
502
526
tt:: TokenTree :: Leaf ( tt:: Leaf :: Punct ( punct) ) if i % 2 == 1 && punct. char == ',' => ( ) ,
503
527
_ => {
504
528
err. get_or_insert ( mbe:: ExpandError :: UnexpectedToken . into ( ) ) ;
505
529
}
506
530
}
507
531
}
532
+ let span = span. unwrap_or ( tt. delimiter . open ) ;
508
533
ExpandResult { value : quote ! ( span =>#text) , err }
509
534
}
510
535
511
536
fn concat_bytes_expand (
512
537
_db : & dyn ExpandDatabase ,
513
538
_arg_id : MacroCallId ,
514
539
tt : & tt:: Subtree ,
515
- span : Span ,
540
+ call_site : Span ,
516
541
) -> ExpandResult < tt:: Subtree > {
517
542
let mut bytes = Vec :: new ( ) ;
518
543
let mut err = None ;
544
+ let mut span: Option < Span > = None ;
545
+ let mut record_span = |s : Span | match & mut span {
546
+ Some ( span) if span. anchor == s. anchor => span. range = span. range . cover ( s. range ) ,
547
+ Some ( _) => ( ) ,
548
+ None => span = Some ( s) ,
549
+ } ;
519
550
for ( i, t) in tt. token_trees . iter ( ) . enumerate ( ) {
520
551
match t {
521
552
tt:: TokenTree :: Leaf ( tt:: Leaf :: Literal ( lit) ) => {
522
553
let token = ast:: make:: tokens:: literal ( & lit. to_string ( ) ) ;
554
+ record_span ( lit. span ) ;
523
555
match token. kind ( ) {
524
556
syntax:: SyntaxKind :: BYTE => bytes. push ( token. text ( ) . to_owned ( ) ) ,
525
557
syntax:: SyntaxKind :: BYTE_STRING => {
526
- let components = unquote_byte_string ( lit) . unwrap_or_default ( ) ;
558
+ let components = unquote_byte_string ( lit) . map_or ( vec ! [ ] , | ( it , _ ) | it ) ;
527
559
components. into_iter ( ) . for_each ( |it| bytes. push ( it. to_string ( ) ) ) ;
528
560
}
529
561
_ => {
@@ -534,7 +566,7 @@ fn concat_bytes_expand(
534
566
}
535
567
tt:: TokenTree :: Leaf ( tt:: Leaf :: Punct ( punct) ) if i % 2 == 1 && punct. char == ',' => ( ) ,
536
568
tt:: TokenTree :: Subtree ( tree) if tree. delimiter . kind == tt:: DelimiterKind :: Bracket => {
537
- if let Err ( e) = concat_bytes_expand_subtree ( tree, & mut bytes) {
569
+ if let Err ( e) = concat_bytes_expand_subtree ( tree, & mut bytes, & mut record_span ) {
538
570
err. get_or_insert ( e) ;
539
571
break ;
540
572
}
@@ -546,17 +578,24 @@ fn concat_bytes_expand(
546
578
}
547
579
}
548
580
let value = tt:: Subtree {
549
- delimiter : tt:: Delimiter { open : span, close : span, kind : tt:: DelimiterKind :: Bracket } ,
581
+ delimiter : tt:: Delimiter {
582
+ open : call_site,
583
+ close : call_site,
584
+ kind : tt:: DelimiterKind :: Bracket ,
585
+ } ,
550
586
token_trees : {
551
587
Itertools :: intersperse_with (
552
588
bytes. into_iter ( ) . map ( |it| {
553
- tt:: TokenTree :: Leaf ( tt:: Leaf :: Literal ( tt:: Literal { text : it. into ( ) , span } ) )
589
+ tt:: TokenTree :: Leaf ( tt:: Leaf :: Literal ( tt:: Literal {
590
+ text : it. into ( ) ,
591
+ span : span. unwrap_or ( call_site) ,
592
+ } ) )
554
593
} ) ,
555
594
|| {
556
595
tt:: TokenTree :: Leaf ( tt:: Leaf :: Punct ( tt:: Punct {
557
596
char : ',' ,
558
597
spacing : tt:: Spacing :: Alone ,
559
- span,
598
+ span : call_site ,
560
599
} ) )
561
600
} ,
562
601
)
@@ -569,13 +608,15 @@ fn concat_bytes_expand(
569
608
fn concat_bytes_expand_subtree (
570
609
tree : & tt:: Subtree ,
571
610
bytes : & mut Vec < String > ,
611
+ mut record_span : impl FnMut ( Span ) ,
572
612
) -> Result < ( ) , ExpandError > {
573
613
for ( ti, tt) in tree. token_trees . iter ( ) . enumerate ( ) {
574
614
match tt {
575
- tt:: TokenTree :: Leaf ( tt:: Leaf :: Literal ( lit ) ) => {
576
- let lit = ast:: make:: tokens:: literal ( & lit . to_string ( ) ) ;
615
+ tt:: TokenTree :: Leaf ( tt:: Leaf :: Literal ( it ) ) => {
616
+ let lit = ast:: make:: tokens:: literal ( & it . to_string ( ) ) ;
577
617
match lit. kind ( ) {
578
618
syntax:: SyntaxKind :: BYTE | syntax:: SyntaxKind :: INT_NUMBER => {
619
+ record_span ( it. span ) ;
579
620
bytes. push ( lit. text ( ) . to_owned ( ) )
580
621
}
581
622
_ => {
@@ -635,7 +676,7 @@ fn relative_file(
635
676
}
636
677
}
637
678
638
- fn parse_string ( tt : & tt:: Subtree ) -> Result < String , ExpandError > {
679
+ fn parse_string ( tt : & tt:: Subtree ) -> Result < ( String , Span ) , ExpandError > {
639
680
tt. token_trees
640
681
. first ( )
641
682
. and_then ( |tt| match tt {
@@ -675,7 +716,7 @@ pub fn include_input_to_file_id(
675
716
arg_id : MacroCallId ,
676
717
arg : & tt:: Subtree ,
677
718
) -> Result < FileId , ExpandError > {
678
- relative_file ( db, arg_id, & parse_string ( arg) ?, false )
719
+ relative_file ( db, arg_id, & parse_string ( arg) ?. 0 , false )
679
720
}
680
721
681
722
fn include_bytes_expand (
@@ -701,7 +742,7 @@ fn include_str_expand(
701
742
tt : & tt:: Subtree ,
702
743
span : Span ,
703
744
) -> ExpandResult < tt:: Subtree > {
704
- let path = match parse_string ( tt) {
745
+ let ( path, span ) = match parse_string ( tt) {
705
746
Ok ( it) => it,
706
747
Err ( e) => {
707
748
return ExpandResult :: new ( tt:: Subtree :: empty ( DelimSpan { open : span, close : span } ) , e)
@@ -736,7 +777,7 @@ fn env_expand(
736
777
tt : & tt:: Subtree ,
737
778
span : Span ,
738
779
) -> ExpandResult < tt:: Subtree > {
739
- let key = match parse_string ( tt) {
780
+ let ( key, span ) = match parse_string ( tt) {
740
781
Ok ( it) => it,
741
782
Err ( e) => {
742
783
return ExpandResult :: new ( tt:: Subtree :: empty ( DelimSpan { open : span, close : span } ) , e)
@@ -766,18 +807,24 @@ fn option_env_expand(
766
807
db : & dyn ExpandDatabase ,
767
808
arg_id : MacroCallId ,
768
809
tt : & tt:: Subtree ,
769
- span : Span ,
810
+ call_site : Span ,
770
811
) -> ExpandResult < tt:: Subtree > {
771
- let key = match parse_string ( tt) {
812
+ let ( key, span ) = match parse_string ( tt) {
772
813
Ok ( it) => it,
773
814
Err ( e) => {
774
- return ExpandResult :: new ( tt:: Subtree :: empty ( DelimSpan { open : span, close : span } ) , e)
815
+ return ExpandResult :: new (
816
+ tt:: Subtree :: empty ( DelimSpan { open : call_site, close : call_site } ) ,
817
+ e,
818
+ )
775
819
}
776
820
} ;
777
- let dollar_crate = dollar_crate ( span ) ;
821
+ let dollar_crate = dollar_crate ( call_site ) ;
778
822
let expanded = match get_env_inner ( db, arg_id, & key) {
779
- None => quote ! { span => #dollar_crate:: option:: Option :: None :: <& str > } ,
780
- Some ( s) => quote ! { span => #dollar_crate:: option:: Option :: Some ( #s) } ,
823
+ None => quote ! { call_site => #dollar_crate:: option:: Option :: None :: <& str > } ,
824
+ Some ( s) => {
825
+ let s = quote ! ( span => #s) ;
826
+ quote ! { call_site => #dollar_crate:: option:: Option :: Some ( #s) }
827
+ }
781
828
} ;
782
829
783
830
ExpandResult :: ok ( expanded)
0 commit comments