@@ -15,6 +15,8 @@ use std::env;
15
15
use std:: fs:: { self , File } ;
16
16
use std:: path:: { Path , PathBuf } ;
17
17
18
+ use rustc:: ast_map:: NodeItem ;
19
+
18
20
use syntax:: { attr} ;
19
21
use syntax:: ast:: { self , NodeId , DefId } ;
20
22
use syntax:: ast_util;
@@ -61,6 +63,10 @@ pub enum Data {
61
63
VariableRefData ( VariableRefData ) ,
62
64
/// Data for a reference to a type or trait.
63
65
TypeRefData ( TypeRefData ) ,
66
+ /// Data about a function call.
67
+ FunctionCallData ( FunctionCallData ) ,
68
+ /// Data about a method call.
69
+ MethodCallData ( MethodCallData ) ,
64
70
}
65
71
66
72
/// Data for all kinds of functions and methods.
@@ -120,7 +126,7 @@ pub struct ImplData {
120
126
}
121
127
122
128
/// Data for the use of some item (e.g., the use of a local variable, which
123
- /// will refere to that variables declaration (by ref_id)).
129
+ /// will refer to that variables declaration (by ref_id)).
124
130
#[ derive( Debug ) ]
125
131
pub struct VariableRefData {
126
132
pub name : String ,
@@ -137,6 +143,24 @@ pub struct TypeRefData {
137
143
pub ref_id : DefId ,
138
144
}
139
145
146
+ /// Data about a function call.
147
+ #[ derive( Debug ) ]
148
+ pub struct FunctionCallData {
149
+ pub span : Span ,
150
+ pub scope : NodeId ,
151
+ pub ref_id : DefId ,
152
+ }
153
+
154
+ /// Data about a method call.
155
+ #[ derive( Debug ) ]
156
+ pub struct MethodCallData {
157
+ pub span : Span ,
158
+ pub scope : NodeId ,
159
+ pub ref_id : Option < DefId > ,
160
+ pub decl_id : Option < DefId > ,
161
+ }
162
+
163
+
140
164
141
165
impl < ' l , ' tcx : ' l > SaveContext < ' l , ' tcx > {
142
166
pub fn new ( tcx : & ' l ty:: ctxt < ' tcx > ,
@@ -172,7 +196,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
172
196
qualname : qualname,
173
197
declaration : None ,
174
198
span : sub_span. unwrap ( ) ,
175
- scope : self . tcx . map . get_enclosing_scope ( item. id ) . unwrap_or ( 0 ) ,
199
+ scope : self . enclosing_scope ( item. id ) ,
176
200
} )
177
201
}
178
202
ast:: ItemStatic ( ref typ, mt, ref expr) => {
@@ -191,7 +215,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
191
215
name : get_ident ( item. ident ) . to_string ( ) ,
192
216
qualname : qualname,
193
217
span : sub_span. unwrap ( ) ,
194
- scope : self . tcx . map . get_enclosing_scope ( item. id ) . unwrap_or ( 0 ) ,
218
+ scope : self . enclosing_scope ( item. id ) ,
195
219
value : value,
196
220
type_value : ty_to_string ( & typ) ,
197
221
} )
@@ -205,7 +229,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
205
229
name : get_ident ( item. ident ) . to_string ( ) ,
206
230
qualname : qualname,
207
231
span : sub_span. unwrap ( ) ,
208
- scope : self . tcx . map . get_enclosing_scope ( item. id ) . unwrap_or ( 0 ) ,
232
+ scope : self . enclosing_scope ( item. id ) ,
209
233
value : self . span_utils . snippet ( expr. span ) ,
210
234
type_value : ty_to_string ( & typ) ,
211
235
} )
@@ -223,7 +247,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
223
247
name : get_ident ( item. ident ) . to_string ( ) ,
224
248
qualname : qualname,
225
249
span : sub_span. unwrap ( ) ,
226
- scope : self . tcx . map . get_enclosing_scope ( item. id ) . unwrap_or ( 0 ) ,
250
+ scope : self . enclosing_scope ( item. id ) ,
227
251
filename : filename,
228
252
} )
229
253
} ,
@@ -237,14 +261,14 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
237
261
value : val,
238
262
span : sub_span. unwrap ( ) ,
239
263
qualname : enum_name,
240
- scope : self . tcx . map . get_enclosing_scope ( item. id ) . unwrap_or ( 0 ) ,
264
+ scope : self . enclosing_scope ( item. id ) ,
241
265
} )
242
266
} ,
243
267
ast:: ItemImpl ( _, _, _, ref trait_ref, ref typ, _) => {
244
268
let mut type_data = None ;
245
269
let sub_span;
246
270
247
- let parent = self . tcx . map . get_enclosing_scope ( item. id ) . unwrap_or ( 0 ) ;
271
+ let parent = self . enclosing_scope ( item. id ) ;
248
272
249
273
match typ. node {
250
274
// Common case impl for a struct or something basic.
@@ -281,34 +305,114 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
281
305
}
282
306
}
283
307
284
- // FIXME: we ought to be able to get the parent id ourselves, but we can't
285
- // for now.
286
- pub fn get_field_data ( & self , field : & ast:: StructField , parent : NodeId ) -> Option < Data > {
308
+ pub fn get_field_data ( & self , field : & ast:: StructField , scope : NodeId ) -> Option < VariableData > {
287
309
match field. node . kind {
288
310
ast:: NamedField ( ident, _) => {
289
311
let name = get_ident ( ident) ;
290
312
let qualname = format ! ( "::{}::{}" ,
291
- self . tcx. map. path_to_string( parent ) ,
313
+ self . tcx. map. path_to_string( scope ) ,
292
314
name) ;
293
315
let typ = self . tcx . node_types ( ) . get ( & field. node . id ) . unwrap ( )
294
316
. to_string ( ) ;
295
317
let sub_span = self . span_utils . sub_span_before_token ( field. span , token:: Colon ) ;
296
- Some ( Data :: VariableData ( VariableData {
318
+ Some ( VariableData {
297
319
id : field. node . id ,
298
320
name : get_ident ( ident) . to_string ( ) ,
299
321
qualname : qualname,
300
322
span : sub_span. unwrap ( ) ,
301
- scope : parent ,
323
+ scope : scope ,
302
324
value : "" . to_owned ( ) ,
303
325
type_value : typ,
304
- } ) )
326
+ } )
305
327
} ,
306
328
_ => None ,
307
329
}
308
330
}
309
331
310
- // FIXME: we ought to be able to get the parent id ourselves, but we can't
311
- // for now.
332
+ // FIXME would be nice to take a MethodItem here, but the ast provides both
333
+ // trait and impl flavours, so the caller must do the disassembly.
334
+ pub fn get_method_data ( & self ,
335
+ id : ast:: NodeId ,
336
+ name : ast:: Name ,
337
+ span : Span ) -> FunctionData {
338
+ // The qualname for a method is the trait name or name of the struct in an impl in
339
+ // which the method is declared in, followed by the method's name.
340
+ let qualname = match self . tcx . impl_of_method ( ast_util:: local_def ( id) ) {
341
+ Some ( impl_id) => match self . tcx . map . get ( impl_id. node ) {
342
+ NodeItem ( item) => {
343
+ match item. node {
344
+ ast:: ItemImpl ( _, _, _, _, ref ty, _) => {
345
+ let mut result = String :: from ( "<" ) ;
346
+ result. push_str ( & ty_to_string ( & * * ty) ) ;
347
+
348
+ match self . tcx . trait_of_item ( ast_util:: local_def ( id) ) {
349
+ Some ( def_id) => {
350
+ result. push_str ( " as " ) ;
351
+ result. push_str (
352
+ & self . tcx . item_path_str ( def_id) ) ;
353
+ } ,
354
+ None => { }
355
+ }
356
+ result. push_str ( ">" ) ;
357
+ result
358
+ }
359
+ _ => {
360
+ self . tcx . sess . span_bug ( span,
361
+ & format ! ( "Container {} for method {} not an impl?" ,
362
+ impl_id. node, id) ) ;
363
+ } ,
364
+ }
365
+ } ,
366
+ _ => {
367
+ self . tcx . sess . span_bug ( span,
368
+ & format ! ( "Container {} for method {} is not a node item {:?}" ,
369
+ impl_id. node, id, self . tcx. map. get( impl_id. node) ) ) ;
370
+ } ,
371
+ } ,
372
+ None => match self . tcx . trait_of_item ( ast_util:: local_def ( id) ) {
373
+ Some ( def_id) => {
374
+ match self . tcx . map . get ( def_id. node ) {
375
+ NodeItem ( _) => {
376
+ format ! ( "::{}" , self . tcx. item_path_str( def_id) )
377
+ }
378
+ _ => {
379
+ self . tcx . sess . span_bug ( span,
380
+ & format ! ( "Could not find container {} for method {}" ,
381
+ def_id. node, id) ) ;
382
+ }
383
+ }
384
+ } ,
385
+ None => {
386
+ self . tcx . sess . span_bug ( span,
387
+ & format ! ( "Could not find container for method {}" , id) ) ;
388
+ } ,
389
+ } ,
390
+ } ;
391
+
392
+ let qualname = format ! ( "{}::{}" , qualname, & token:: get_name( name) ) ;
393
+
394
+ let decl_id = self . tcx . trait_item_of_item ( ast_util:: local_def ( id) )
395
+ . and_then ( |new_id| {
396
+ let def_id = new_id. def_id ( ) ;
397
+ if def_id. node != 0 && def_id != ast_util:: local_def ( id) {
398
+ Some ( def_id)
399
+ } else {
400
+ None
401
+ }
402
+ } ) ;
403
+
404
+ let sub_span = self . span_utils . sub_span_after_keyword ( span, keywords:: Fn ) ;
405
+
406
+ FunctionData {
407
+ id : id,
408
+ name : token:: get_name ( name) . to_string ( ) ,
409
+ qualname : qualname,
410
+ declaration : decl_id,
411
+ span : sub_span. unwrap ( ) ,
412
+ scope : self . enclosing_scope ( id) ,
413
+ }
414
+ }
415
+
312
416
pub fn get_trait_ref_data ( & self ,
313
417
trait_ref : & ast:: TraitRef ,
314
418
parent : NodeId )
@@ -337,7 +441,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
337
441
return Some ( Data :: VariableRefData ( VariableRefData {
338
442
name : get_ident ( ident. node ) . to_string ( ) ,
339
443
span : sub_span. unwrap ( ) ,
340
- scope : self . tcx . map . get_enclosing_scope ( expr. id ) . unwrap_or ( 0 ) ,
444
+ scope : self . enclosing_scope ( expr. id ) ,
341
445
ref_id : f. id ,
342
446
} ) ) ;
343
447
}
@@ -360,7 +464,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
360
464
let sub_span = self . span_utils . span_for_last_ident ( path. span ) ;
361
465
Some ( Data :: TypeRefData ( TypeRefData {
362
466
span : sub_span. unwrap ( ) ,
363
- scope : self . tcx . map . get_enclosing_scope ( expr. id ) . unwrap_or ( 0 ) ,
467
+ scope : self . enclosing_scope ( expr. id ) ,
364
468
ref_id : def_id,
365
469
} ) )
366
470
}
@@ -372,13 +476,116 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
372
476
}
373
477
}
374
478
}
479
+ ast:: ExprMethodCall ( ..) => {
480
+ let method_call = ty:: MethodCall :: expr ( expr. id ) ;
481
+ let method_id = self . tcx . tables . borrow ( ) . method_map [ & method_call] . def_id ;
482
+ let ( def_id, decl_id) = match self . tcx . impl_or_trait_item ( method_id) . container ( ) {
483
+ ty:: ImplContainer ( _) => ( Some ( method_id) , None ) ,
484
+ ty:: TraitContainer ( _) => ( None , Some ( method_id) )
485
+ } ;
486
+ let sub_span = self . span_utils . sub_span_for_meth_name ( expr. span ) ;
487
+ let parent = self . enclosing_scope ( expr. id ) ;
488
+ Some ( Data :: MethodCallData ( MethodCallData {
489
+ span : sub_span. unwrap ( ) ,
490
+ scope : parent,
491
+ ref_id : def_id,
492
+ decl_id : decl_id,
493
+ } ) )
494
+ }
495
+ ast:: ExprPath ( _, ref path) => {
496
+ Some ( self . get_path_data ( expr. id , path) )
497
+ }
375
498
_ => {
376
499
// FIXME
377
500
unimplemented ! ( ) ;
378
501
}
379
502
}
380
503
}
381
504
505
+ pub fn get_path_data ( & self ,
506
+ id : NodeId ,
507
+ path : & ast:: Path )
508
+ -> Data {
509
+ let def_map = self . tcx . def_map . borrow ( ) ;
510
+ if !def_map. contains_key ( & id) {
511
+ self . tcx . sess . span_bug ( path. span ,
512
+ & format ! ( "def_map has no key for {} in visit_expr" , id) ) ;
513
+ }
514
+ let def = def_map. get ( & id) . unwrap ( ) . full_def ( ) ;
515
+ let sub_span = self . span_utils . span_for_last_ident ( path. span ) ;
516
+ match def {
517
+ def:: DefUpvar ( ..) |
518
+ def:: DefLocal ( ..) |
519
+ def:: DefStatic ( ..) |
520
+ def:: DefConst ( ..) |
521
+ def:: DefAssociatedConst ( ..) |
522
+ def:: DefVariant ( ..) => {
523
+ Data :: VariableRefData ( VariableRefData {
524
+ name : self . span_utils . snippet ( sub_span. unwrap ( ) ) ,
525
+ span : sub_span. unwrap ( ) ,
526
+ scope : self . enclosing_scope ( id) ,
527
+ ref_id : def. def_id ( ) ,
528
+ } )
529
+ }
530
+ def:: DefStruct ( def_id) | def:: DefTy ( def_id, _) => {
531
+ Data :: TypeRefData ( TypeRefData {
532
+ span : sub_span. unwrap ( ) ,
533
+ ref_id : def_id,
534
+ scope : self . enclosing_scope ( id) ,
535
+ } )
536
+ }
537
+ def:: DefMethod ( decl_id, provenence) => {
538
+ let sub_span = self . span_utils . sub_span_for_meth_name ( path. span ) ;
539
+ let def_id = if decl_id. krate == ast:: LOCAL_CRATE {
540
+ let ti = self . tcx . impl_or_trait_item ( decl_id) ;
541
+ match provenence {
542
+ def:: FromTrait ( def_id) => {
543
+ Some ( self . tcx . trait_items ( def_id)
544
+ . iter ( )
545
+ . find ( |mr| {
546
+ mr. name ( ) == ti. name ( )
547
+ } )
548
+ . unwrap ( )
549
+ . def_id ( ) )
550
+ }
551
+ def:: FromImpl ( def_id) => {
552
+ let impl_items = self . tcx . impl_items . borrow ( ) ;
553
+ Some ( impl_items. get ( & def_id)
554
+ . unwrap ( )
555
+ . iter ( )
556
+ . find ( |mr| {
557
+ self . tcx . impl_or_trait_item ( mr. def_id ( ) ) . name ( )
558
+ == ti. name ( )
559
+ } )
560
+ . unwrap ( )
561
+ . def_id ( ) )
562
+ }
563
+ }
564
+ } else {
565
+ None
566
+ } ;
567
+ Data :: MethodCallData ( MethodCallData {
568
+ span : sub_span. unwrap ( ) ,
569
+ scope : self . enclosing_scope ( id) ,
570
+ ref_id : def_id,
571
+ decl_id : Some ( decl_id) ,
572
+ } )
573
+ } ,
574
+ def:: DefFn ( def_id, _) => {
575
+ Data :: FunctionCallData ( FunctionCallData {
576
+ ref_id : def_id,
577
+ span : sub_span. unwrap ( ) ,
578
+ scope : self . enclosing_scope ( id) ,
579
+ } )
580
+ }
581
+ _ => self . tcx . sess . span_bug ( path. span ,
582
+ & format ! ( "Unexpected def kind while looking \
583
+ up path in `{}`: `{:?}`",
584
+ self . span_utils. snippet( path. span) ,
585
+ def) ) ,
586
+ }
587
+ }
588
+
382
589
pub fn get_field_ref_data ( & self ,
383
590
field_ref : & ast:: Field ,
384
591
struct_id : DefId ,
@@ -420,6 +627,10 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
420
627
}
421
628
}
422
629
630
+ #[ inline]
631
+ fn enclosing_scope ( & self , id : NodeId ) -> NodeId {
632
+ self . tcx . map . get_enclosing_scope ( id) . unwrap_or ( 0 )
633
+ }
423
634
}
424
635
425
636
// An AST visitor for collecting paths from patterns.
0 commit comments