@@ -9,12 +9,15 @@ use db::TokenExpander;
99use either:: Either ;
1010use mbe:: Origin ;
1111use parser:: SyntaxKind ;
12- use syntax:: { ast, AstNode , SyntaxNode , TextRange , TextSize } ;
12+ use syntax:: {
13+ ast:: { self , AttrsOwner } ,
14+ AstNode , SyntaxNode , TextRange , TextSize ,
15+ } ;
1316
1417use crate :: {
1518 db:: { self , AstDatabase } ,
1619 name:: { AsName , Name } ,
17- HirFileId , HirFileIdRepr , InFile , MacroCallLoc , MacroDefKind , MacroFile ,
20+ HirFileId , HirFileIdRepr , InFile , MacroCallKind , MacroCallLoc , MacroDefKind , MacroFile ,
1821} ;
1922
2023#[ derive( Clone , Debug ) ]
@@ -121,11 +124,12 @@ impl HygieneFrames {
121124#[ derive( Debug , Clone , PartialEq , Eq ) ]
122125struct HygieneInfo {
123126 file : MacroFile ,
124- /// The `macro_rules!` arguments.
125- def_start : Option < InFile < TextSize > > ,
127+ /// The start offset of the `macro_rules!` arguments or attribute input .
128+ attr_input_or_mac_def_start : Option < InFile < TextSize > > ,
126129
127130 macro_def : Arc < TokenExpander > ,
128131 macro_arg : Arc < ( tt:: Subtree , mbe:: TokenMap ) > ,
132+ macro_arg_shift : mbe:: Shift ,
129133 exp_map : Arc < mbe:: TokenMap > ,
130134}
131135
@@ -136,22 +140,34 @@ impl HygieneInfo {
136140 token : TextRange ,
137141 ) -> Option < ( InFile < TextRange > , Origin ) > {
138142 let token_id = self . exp_map . token_by_range ( token) ?;
143+ let ( mut token_id, origin) = self . macro_def . map_id_up ( token_id) ;
139144
140- let ( token_id, origin) = self . macro_def . map_id_up ( token_id) ;
141- let ( token_map, tt) = match origin {
142- mbe:: Origin :: Call => {
143- let call_id = self . file . macro_call_id ;
144- let loc: MacroCallLoc = db. lookup_intern_macro ( call_id) ;
145- let arg_start = loc. kind . arg ( db) ?. text_range ( ) . start ( ) ;
146- ( & self . macro_arg . 1 , InFile :: new ( loc. kind . file_id ( ) , arg_start) )
147- }
148- mbe:: Origin :: Def => match ( & * self . macro_def , self . def_start ) {
149- (
150- TokenExpander :: MacroDef { def_site_token_map, .. }
151- | TokenExpander :: MacroRules { def_site_token_map, .. } ,
152- Some ( tt) ,
153- ) => ( def_site_token_map, tt) ,
154- _ => panic ! ( "`Origin::Def` used with non-`macro_rules!` macro" ) ,
145+ let loc = db. lookup_intern_macro ( self . file . macro_call_id ) ;
146+
147+ let ( token_map, tt) = match & loc. kind {
148+ MacroCallKind :: Attr { attr_args, .. } => match self . macro_arg_shift . unshift ( token_id) {
149+ Some ( unshifted) => {
150+ token_id = unshifted;
151+ ( & attr_args. 1 , self . attr_input_or_mac_def_start ?)
152+ }
153+ None => (
154+ & self . macro_arg . 1 ,
155+ InFile :: new ( loc. kind . file_id ( ) , loc. kind . arg ( db) ?. text_range ( ) . start ( ) ) ,
156+ ) ,
157+ } ,
158+ _ => match origin {
159+ mbe:: Origin :: Call => (
160+ & self . macro_arg . 1 ,
161+ InFile :: new ( loc. kind . file_id ( ) , loc. kind . arg ( db) ?. text_range ( ) . start ( ) ) ,
162+ ) ,
163+ mbe:: Origin :: Def => match ( & * self . macro_def , & self . attr_input_or_mac_def_start ) {
164+ (
165+ TokenExpander :: MacroDef { def_site_token_map, .. }
166+ | TokenExpander :: MacroRules { def_site_token_map, .. } ,
167+ Some ( tt) ,
168+ ) => ( def_site_token_map, * tt) ,
169+ _ => panic ! ( "`Origin::Def` used with non-`macro_rules!` macro" ) ,
170+ } ,
155171 } ,
156172 } ;
157173
@@ -165,19 +181,34 @@ fn make_hygiene_info(
165181 macro_file : MacroFile ,
166182 loc : & MacroCallLoc ,
167183) -> Option < HygieneInfo > {
168- let def_offset = loc. def . ast_id ( ) . left ( ) . and_then ( |id| {
184+ let def = loc. def . ast_id ( ) . left ( ) . and_then ( |id| {
169185 let def_tt = match id. to_node ( db) {
170- ast:: Macro :: MacroRules ( mac) => mac. token_tree ( ) ?. syntax ( ) . text_range ( ) . start ( ) ,
171- ast:: Macro :: MacroDef ( mac) => mac. body ( ) ?. syntax ( ) . text_range ( ) . start ( ) ,
186+ ast:: Macro :: MacroRules ( mac) => mac. token_tree ( ) ?,
187+ ast:: Macro :: MacroDef ( mac) => mac. body ( ) ?,
172188 } ;
173189 Some ( InFile :: new ( id. file_id , def_tt) )
174190 } ) ;
191+ let attr_input_or_mac_def = def. or_else ( || match loc. kind {
192+ MacroCallKind :: Attr { ast_id, invoc_attr_index, .. } => {
193+ let tt = ast_id. to_node ( db) . attrs ( ) . nth ( invoc_attr_index as usize ) ?. token_tree ( ) ?;
194+ Some ( InFile :: new ( ast_id. file_id , tt) )
195+ }
196+ _ => None ,
197+ } ) ;
175198
176199 let macro_def = db. macro_def ( loc. def ) ?;
177200 let ( _, exp_map) = db. parse_macro_expansion ( macro_file) . value ?;
178201 let macro_arg = db. macro_arg ( macro_file. macro_call_id ) ?;
179202
180- Some ( HygieneInfo { file : macro_file, def_start : def_offset, macro_arg, macro_def, exp_map } )
203+ Some ( HygieneInfo {
204+ file : macro_file,
205+ attr_input_or_mac_def_start : attr_input_or_mac_def
206+ . map ( |it| it. map ( |tt| tt. syntax ( ) . text_range ( ) . start ( ) ) ) ,
207+ macro_arg_shift : mbe:: Shift :: new ( & macro_arg. 0 ) ,
208+ macro_arg,
209+ macro_def,
210+ exp_map,
211+ } )
181212}
182213
183214impl HygieneFrame {
@@ -214,7 +245,7 @@ impl HygieneFrame {
214245 Some ( it) => it,
215246 } ;
216247
217- let def_site = info. def_start . map ( |it| db. hygiene_frame ( it. file_id ) ) ;
248+ let def_site = info. attr_input_or_mac_def_start . map ( |it| db. hygiene_frame ( it. file_id ) ) ;
218249 let call_site = Some ( db. hygiene_frame ( calling_file) ) ;
219250
220251 HygieneFrame { expansion : Some ( info) , local_inner, krate, call_site, def_site }
0 commit comments