@@ -73,7 +73,7 @@ use rustc_hash::FxHashSet;
73
73
use stdx:: { format_to, impl_from, never} ;
74
74
use syntax:: {
75
75
ast:: { self , HasAttrs as _, HasDocComments , HasName } ,
76
- AstNode , AstPtr , SmolStr , SyntaxNodePtr , T ,
76
+ AstNode , AstPtr , SmolStr , SyntaxNodePtr , TextRange , T ,
77
77
} ;
78
78
79
79
use crate :: db:: { DefDatabase , HirDatabase } ;
@@ -628,78 +628,19 @@ fn emit_def_diagnostic(db: &dyn HirDatabase, acc: &mut Vec<AnyDiagnostic>, diag:
628
628
}
629
629
630
630
DefDiagnosticKind :: UnresolvedProcMacro { ast, krate } => {
631
- let ( node, precise_location, macro_name, kind) = match ast {
632
- MacroCallKind :: FnLike { ast_id, .. } => {
633
- let node = ast_id. to_node ( db. upcast ( ) ) ;
634
- (
635
- ast_id. with_value ( SyntaxNodePtr :: from ( AstPtr :: new ( & node) ) ) ,
636
- node. path ( ) . map ( |it| it. syntax ( ) . text_range ( ) ) ,
637
- node. path ( ) . and_then ( |it| it. segment ( ) ) . map ( |it| it. to_string ( ) ) ,
638
- MacroKind :: ProcMacro ,
639
- )
640
- }
641
- MacroCallKind :: Derive { ast_id, derive_attr_index, derive_index } => {
642
- let node = ast_id. to_node ( db. upcast ( ) ) ;
643
- // Compute the precise location of the macro name's token in the derive
644
- // list.
645
- let token = ( || {
646
- let derive_attr = node
647
- . doc_comments_and_attrs ( )
648
- . nth ( * derive_attr_index as usize )
649
- . and_then ( Either :: left) ?;
650
- let token_tree = derive_attr. meta ( ) ?. token_tree ( ) ?;
651
- let group_by = token_tree
652
- . syntax ( )
653
- . children_with_tokens ( )
654
- . filter_map ( |elem| match elem {
655
- syntax:: NodeOrToken :: Token ( tok) => Some ( tok) ,
656
- _ => None ,
657
- } )
658
- . group_by ( |t| t. kind ( ) == T ! [ , ] ) ;
659
- let ( _, mut group) = group_by
660
- . into_iter ( )
661
- . filter ( |& ( comma, _) | !comma)
662
- . nth ( * derive_index as usize ) ?;
663
- group. find ( |t| t. kind ( ) == T ! [ ident] )
664
- } ) ( ) ;
665
- (
666
- ast_id. with_value ( SyntaxNodePtr :: from ( AstPtr :: new ( & node) ) ) ,
667
- token. as_ref ( ) . map ( |tok| tok. text_range ( ) ) ,
668
- token. as_ref ( ) . map ( ToString :: to_string) ,
669
- MacroKind :: Derive ,
670
- )
671
- }
672
- MacroCallKind :: Attr { ast_id, invoc_attr_index, .. } => {
673
- let node = ast_id. to_node ( db. upcast ( ) ) ;
674
- let attr = node
675
- . doc_comments_and_attrs ( )
676
- . nth ( ( * invoc_attr_index) as usize )
677
- . and_then ( Either :: left)
678
- . unwrap_or_else ( || panic ! ( "cannot find attribute #{}" , invoc_attr_index) ) ;
679
-
680
- (
681
- ast_id. with_value ( SyntaxNodePtr :: from ( AstPtr :: new ( & attr) ) ) ,
682
- Some ( attr. syntax ( ) . text_range ( ) ) ,
683
- attr. path ( )
684
- . and_then ( |path| path. segment ( ) )
685
- . and_then ( |seg| seg. name_ref ( ) )
686
- . as_ref ( )
687
- . map ( ToString :: to_string) ,
688
- MacroKind :: Attr ,
689
- )
690
- }
691
- } ;
631
+ let ( node, precise_location, macro_name, kind) = precise_macro_call_location ( ast, db) ;
692
632
acc. push (
693
633
UnresolvedProcMacro { node, precise_location, macro_name, kind, krate : * krate }
694
634
. into ( ) ,
695
635
) ;
696
636
}
697
637
698
638
DefDiagnosticKind :: UnresolvedMacroCall { ast, path } => {
699
- let node = ast . to_node ( db . upcast ( ) ) ;
639
+ let ( node, precise_location , _ , _ ) = precise_macro_call_location ( ast , db ) ;
700
640
acc. push (
701
641
UnresolvedMacroCall {
702
- macro_call : InFile :: new ( node. file_id , SyntaxNodePtr :: new ( & node. value ) ) ,
642
+ macro_call : node,
643
+ precise_location,
703
644
path : path. clone ( ) ,
704
645
is_bang : matches ! ( ast, MacroCallKind :: FnLike { .. } ) ,
705
646
}
@@ -708,23 +649,8 @@ fn emit_def_diagnostic(db: &dyn HirDatabase, acc: &mut Vec<AnyDiagnostic>, diag:
708
649
}
709
650
710
651
DefDiagnosticKind :: MacroError { ast, message } => {
711
- let node = match ast {
712
- MacroCallKind :: FnLike { ast_id, .. } => {
713
- let node = ast_id. to_node ( db. upcast ( ) ) ;
714
- ast_id. with_value ( SyntaxNodePtr :: from ( AstPtr :: new ( & node) ) )
715
- }
716
- MacroCallKind :: Derive { ast_id, .. } => {
717
- // FIXME: point to the attribute instead, this creates very large diagnostics
718
- let node = ast_id. to_node ( db. upcast ( ) ) ;
719
- ast_id. with_value ( SyntaxNodePtr :: from ( AstPtr :: new ( & node) ) )
720
- }
721
- MacroCallKind :: Attr { ast_id, .. } => {
722
- // FIXME: point to the attribute instead, this creates very large diagnostics
723
- let node = ast_id. to_node ( db. upcast ( ) ) ;
724
- ast_id. with_value ( SyntaxNodePtr :: from ( AstPtr :: new ( & node) ) )
725
- }
726
- } ;
727
- acc. push ( MacroError { node, message : message. clone ( ) } . into ( ) ) ;
652
+ let ( node, precise_location, _, _) = precise_macro_call_location ( ast, db) ;
653
+ acc. push ( MacroError { node, precise_location, message : message. clone ( ) } . into ( ) ) ;
728
654
}
729
655
730
656
DefDiagnosticKind :: UnimplementedBuiltinMacro { ast } => {
@@ -771,6 +697,78 @@ fn emit_def_diagnostic(db: &dyn HirDatabase, acc: &mut Vec<AnyDiagnostic>, diag:
771
697
}
772
698
}
773
699
700
+ fn precise_macro_call_location (
701
+ ast : & MacroCallKind ,
702
+ db : & dyn HirDatabase ,
703
+ ) -> ( InFile < SyntaxNodePtr > , Option < TextRange > , Option < String > , MacroKind ) {
704
+ // FIXME: maaybe we actually want slightly different ranges for the different macro diagnostics
705
+ // - e.g. the full attribute for macro errors, but only the name for name resolution
706
+ match ast {
707
+ MacroCallKind :: FnLike { ast_id, .. } => {
708
+ let node = ast_id. to_node ( db. upcast ( ) ) ;
709
+ (
710
+ ast_id. with_value ( SyntaxNodePtr :: from ( AstPtr :: new ( & node) ) ) ,
711
+ node. path ( )
712
+ . and_then ( |it| it. segment ( ) )
713
+ . and_then ( |it| it. name_ref ( ) )
714
+ . map ( |it| it. syntax ( ) . text_range ( ) ) ,
715
+ node. path ( ) . and_then ( |it| it. segment ( ) ) . map ( |it| it. to_string ( ) ) ,
716
+ MacroKind :: ProcMacro ,
717
+ )
718
+ }
719
+ MacroCallKind :: Derive { ast_id, derive_attr_index, derive_index } => {
720
+ let node = ast_id. to_node ( db. upcast ( ) ) ;
721
+ // Compute the precise location of the macro name's token in the derive
722
+ // list.
723
+ let token = ( || {
724
+ let derive_attr = node
725
+ . doc_comments_and_attrs ( )
726
+ . nth ( * derive_attr_index as usize )
727
+ . and_then ( Either :: left) ?;
728
+ let token_tree = derive_attr. meta ( ) ?. token_tree ( ) ?;
729
+ let group_by = token_tree
730
+ . syntax ( )
731
+ . children_with_tokens ( )
732
+ . filter_map ( |elem| match elem {
733
+ syntax:: NodeOrToken :: Token ( tok) => Some ( tok) ,
734
+ _ => None ,
735
+ } )
736
+ . group_by ( |t| t. kind ( ) == T ! [ , ] ) ;
737
+ let ( _, mut group) = group_by
738
+ . into_iter ( )
739
+ . filter ( |& ( comma, _) | !comma)
740
+ . nth ( * derive_index as usize ) ?;
741
+ group. find ( |t| t. kind ( ) == T ! [ ident] )
742
+ } ) ( ) ;
743
+ (
744
+ ast_id. with_value ( SyntaxNodePtr :: from ( AstPtr :: new ( & node) ) ) ,
745
+ token. as_ref ( ) . map ( |tok| tok. text_range ( ) ) ,
746
+ token. as_ref ( ) . map ( ToString :: to_string) ,
747
+ MacroKind :: Derive ,
748
+ )
749
+ }
750
+ MacroCallKind :: Attr { ast_id, invoc_attr_index, .. } => {
751
+ let node = ast_id. to_node ( db. upcast ( ) ) ;
752
+ let attr = node
753
+ . doc_comments_and_attrs ( )
754
+ . nth ( ( * invoc_attr_index) as usize )
755
+ . and_then ( Either :: left)
756
+ . unwrap_or_else ( || panic ! ( "cannot find attribute #{}" , invoc_attr_index) ) ;
757
+
758
+ (
759
+ ast_id. with_value ( SyntaxNodePtr :: from ( AstPtr :: new ( & attr) ) ) ,
760
+ Some ( attr. syntax ( ) . text_range ( ) ) ,
761
+ attr. path ( )
762
+ . and_then ( |path| path. segment ( ) )
763
+ . and_then ( |seg| seg. name_ref ( ) )
764
+ . as_ref ( )
765
+ . map ( ToString :: to_string) ,
766
+ MacroKind :: Attr ,
767
+ )
768
+ }
769
+ }
770
+ }
771
+
774
772
impl HasVisibility for Module {
775
773
fn visibility ( & self , db : & dyn HirDatabase ) -> Visibility {
776
774
let def_map = self . id . def_map ( db. upcast ( ) ) ;
@@ -1156,6 +1154,7 @@ impl DefWithBody {
1156
1154
BodyDiagnostic :: MacroError { node, message } => acc. push (
1157
1155
MacroError {
1158
1156
node : node. clone ( ) . map ( |it| it. into ( ) ) ,
1157
+ precise_location : None ,
1159
1158
message : message. to_string ( ) ,
1160
1159
}
1161
1160
. into ( ) ,
@@ -1173,6 +1172,7 @@ impl DefWithBody {
1173
1172
BodyDiagnostic :: UnresolvedMacroCall { node, path } => acc. push (
1174
1173
UnresolvedMacroCall {
1175
1174
macro_call : node. clone ( ) . map ( |ast_ptr| ast_ptr. into ( ) ) ,
1175
+ precise_location : None ,
1176
1176
path : path. clone ( ) ,
1177
1177
is_bang : true ,
1178
1178
}
0 commit comments