@@ -73,7 +73,7 @@ use rustc_hash::FxHashSet;
7373use stdx:: { format_to, impl_from, never} ;
7474use syntax:: {
7575 ast:: { self , HasAttrs as _, HasDocComments , HasName } ,
76- AstNode , AstPtr , SmolStr , SyntaxNodePtr , T ,
76+ AstNode , AstPtr , SmolStr , SyntaxNodePtr , TextRange , T ,
7777} ;
7878
7979use crate :: db:: { DefDatabase , HirDatabase } ;
@@ -628,78 +628,19 @@ fn emit_def_diagnostic(db: &dyn HirDatabase, acc: &mut Vec<AnyDiagnostic>, diag:
628628 }
629629
630630 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) ;
692632 acc. push (
693633 UnresolvedProcMacro { node, precise_location, macro_name, kind, krate : * krate }
694634 . into ( ) ,
695635 ) ;
696636 }
697637
698638 DefDiagnosticKind :: UnresolvedMacroCall { ast, path } => {
699- let node = ast . to_node ( db . upcast ( ) ) ;
639+ let ( node, precise_location , _ , _ ) = precise_macro_call_location ( ast , db ) ;
700640 acc. push (
701641 UnresolvedMacroCall {
702- macro_call : InFile :: new ( node. file_id , SyntaxNodePtr :: new ( & node. value ) ) ,
642+ macro_call : node,
643+ precise_location,
703644 path : path. clone ( ) ,
704645 is_bang : matches ! ( ast, MacroCallKind :: FnLike { .. } ) ,
705646 }
@@ -708,23 +649,8 @@ fn emit_def_diagnostic(db: &dyn HirDatabase, acc: &mut Vec<AnyDiagnostic>, diag:
708649 }
709650
710651 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 ( ) ) ;
728654 }
729655
730656 DefDiagnosticKind :: UnimplementedBuiltinMacro { ast } => {
@@ -771,6 +697,78 @@ fn emit_def_diagnostic(db: &dyn HirDatabase, acc: &mut Vec<AnyDiagnostic>, diag:
771697 }
772698}
773699
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+
774772impl HasVisibility for Module {
775773 fn visibility ( & self , db : & dyn HirDatabase ) -> Visibility {
776774 let def_map = self . id . def_map ( db. upcast ( ) ) ;
@@ -1156,6 +1154,7 @@ impl DefWithBody {
11561154 BodyDiagnostic :: MacroError { node, message } => acc. push (
11571155 MacroError {
11581156 node : node. clone ( ) . map ( |it| it. into ( ) ) ,
1157+ precise_location : None ,
11591158 message : message. to_string ( ) ,
11601159 }
11611160 . into ( ) ,
@@ -1173,6 +1172,7 @@ impl DefWithBody {
11731172 BodyDiagnostic :: UnresolvedMacroCall { node, path } => acc. push (
11741173 UnresolvedMacroCall {
11751174 macro_call : node. clone ( ) . map ( |ast_ptr| ast_ptr. into ( ) ) ,
1175+ precise_location : None ,
11761176 path : path. clone ( ) ,
11771177 is_bang : true ,
11781178 }
0 commit comments