11
11
use abi;
12
12
use ast:: * ;
13
13
use ast_util;
14
- use codemap:: Span ;
14
+ use codemap:: { Span , Spanned } ;
15
15
use fold:: Folder ;
16
16
use fold;
17
17
use parse:: token;
@@ -21,6 +21,7 @@ use util::small_vector::SmallVector;
21
21
use std:: cell:: RefCell ;
22
22
use std:: fmt;
23
23
use std:: gc:: { Gc , GC } ;
24
+ use std:: io:: IoResult ;
24
25
use std:: iter;
25
26
use std:: slice;
26
27
@@ -203,6 +204,10 @@ pub struct Map {
203
204
}
204
205
205
206
impl Map {
207
+ fn entry_count ( & self ) -> uint {
208
+ self . map . borrow ( ) . len ( )
209
+ }
210
+
206
211
fn find_entry ( & self , id : NodeId ) -> Option < MapEntry > {
207
212
let map = self . map . borrow ( ) ;
208
213
if map. len ( ) > id as uint {
@@ -405,6 +410,20 @@ impl Map {
405
410
f ( attrs)
406
411
}
407
412
413
+ /// Returns an iterator that yields the node id's with paths that
414
+ /// match `parts`. (Requires `parts` is non-empty.)
415
+ ///
416
+ /// For example, if given `parts` equal to `["bar", "quux"]`, then
417
+ /// the iterator will produce node id's for items with paths
418
+ /// such as `foo::bar::quux`, `bar::quux`, `other::bar::quux`, and
419
+ /// any other such items it can find in the map.
420
+ pub fn nodes_matching_suffix < ' a , S : Str > ( & ' a self , parts : & ' a [ S ] ) -> NodesMatchingSuffix < ' a , S > {
421
+ NodesMatchingSuffix { map : self ,
422
+ item_name : parts. last ( ) . unwrap ( ) ,
423
+ where : parts. slice_to ( parts. len ( ) - 1 ) ,
424
+ idx : 0 }
425
+ }
426
+
408
427
pub fn opt_span ( & self , id : NodeId ) -> Option < Span > {
409
428
let sp = match self . find ( id) {
410
429
Some ( NodeItem ( item) ) => item. span ,
@@ -438,6 +457,119 @@ impl Map {
438
457
}
439
458
}
440
459
460
+ pub struct NodesMatchingSuffix < ' a , S > {
461
+ map : & ' a Map ,
462
+ item_name : & ' a S ,
463
+ where : & ' a [ S ] ,
464
+ idx : NodeId ,
465
+ }
466
+
467
+ impl < ' a , S : Str > NodesMatchingSuffix < ' a , S > {
468
+ /// Returns true only if some suffix of the module path for parent
469
+ /// matches `self.where`.
470
+ ///
471
+ /// In other words: let `[x_0,x_1,...,x_k]` be `self.where`;
472
+ /// returns true if parent's path ends with the suffix
473
+ /// `x_0::x_1::...::x_k`.
474
+ fn suffix_matches ( & self , parent : NodeId ) -> bool {
475
+ let mut cursor = parent;
476
+ for part in self . where . iter ( ) . rev ( ) {
477
+ let ( mod_id, mod_name) = match find_first_mod_parent ( self . map , cursor) {
478
+ None => return false ,
479
+ Some ( ( node_id, name) ) => ( node_id, name) ,
480
+ } ;
481
+ if part. as_slice ( ) != mod_name. as_str ( ) {
482
+ return false ;
483
+ }
484
+ cursor = self . map . get_parent ( mod_id) ;
485
+ }
486
+ return true ;
487
+
488
+ // Finds the first mod in parent chain for `id`, along with
489
+ // that mod's name.
490
+ //
491
+ // If `id` itself is a mod named `m` with parent `p`, then
492
+ // returns `Some(id, m, p)`. If `id` has no mod in its parent
493
+ // chain, then returns `None`.
494
+ fn find_first_mod_parent < ' a > ( map : & ' a Map , mut id : NodeId ) -> Option < ( NodeId , Name ) > {
495
+ loop {
496
+ match map. find ( id) {
497
+ None => return None ,
498
+ Some ( NodeItem ( item) ) if item_is_mod ( & * item) =>
499
+ return Some ( ( id, item. ident . name ) ) ,
500
+ _ => { }
501
+ }
502
+ let parent = map. get_parent ( id) ;
503
+ if parent == id { return None }
504
+ id = parent;
505
+ }
506
+
507
+ fn item_is_mod ( item : & Item ) -> bool {
508
+ match item. node {
509
+ ItemMod ( _) => true ,
510
+ _ => false ,
511
+ }
512
+ }
513
+ }
514
+ }
515
+
516
+ // We are looking at some node `n` with a given name and parent
517
+ // id; do their names match what I am seeking?
518
+ fn matches_names ( & self , parent_of_n : NodeId , name : Name ) -> bool {
519
+ name. as_str ( ) == self . item_name . as_slice ( ) &&
520
+ self . suffix_matches ( parent_of_n)
521
+ }
522
+ }
523
+
524
+ impl < ' a , S : Str > Iterator < NodeId > for NodesMatchingSuffix < ' a , S > {
525
+ fn next ( & mut self ) -> Option < NodeId > {
526
+ loop {
527
+ let idx = self . idx ;
528
+ if idx as uint >= self . map . entry_count ( ) {
529
+ return None ;
530
+ }
531
+ self . idx += 1 ;
532
+ let ( p, name) = match self . map . find_entry ( idx) {
533
+ Some ( EntryItem ( p, n) ) => ( p, n. name ( ) ) ,
534
+ Some ( EntryForeignItem ( p, n) ) => ( p, n. name ( ) ) ,
535
+ Some ( EntryTraitMethod ( p, n) ) => ( p, n. name ( ) ) ,
536
+ Some ( EntryMethod ( p, n) ) => ( p, n. name ( ) ) ,
537
+ Some ( EntryVariant ( p, n) ) => ( p, n. name ( ) ) ,
538
+ _ => continue ,
539
+ } ;
540
+ if self . matches_names ( p, name) {
541
+ return Some ( idx)
542
+ }
543
+ }
544
+ }
545
+ }
546
+
547
+ trait Named {
548
+ fn name ( & self ) -> Name ;
549
+ }
550
+
551
+ impl < T : Named > Named for Spanned < T > { fn name ( & self ) -> Name { self . node . name ( ) } }
552
+
553
+ impl Named for Item { fn name ( & self ) -> Name { self . ident . name } }
554
+ impl Named for ForeignItem { fn name ( & self ) -> Name { self . ident . name } }
555
+ impl Named for Variant_ { fn name ( & self ) -> Name { self . name . name } }
556
+ impl Named for TraitMethod {
557
+ fn name ( & self ) -> Name {
558
+ match * self {
559
+ Required ( ref tm) => tm. ident . name ,
560
+ Provided ( m) => m. name ( ) ,
561
+ }
562
+ }
563
+ }
564
+ impl Named for Method {
565
+ fn name ( & self ) -> Name {
566
+ match self . node {
567
+ MethDecl ( i, _, _, _, _, _, _, _) => i. name ,
568
+ MethMac ( _) => fail ! ( "encountered unexpanded method macro." ) ,
569
+ }
570
+ }
571
+ }
572
+
441
573
pub trait FoldOps {
442
574
fn new_id ( & self , id : NodeId ) -> NodeId {
443
575
id
@@ -688,6 +820,34 @@ pub fn map_decoded_item<F: FoldOps>(map: &Map,
688
820
ii
689
821
}
690
822
823
+ pub trait NodePrinter {
824
+ fn print_node ( & mut self , node : & Node ) -> IoResult < ( ) > ;
825
+ }
826
+
827
+ impl < ' a > NodePrinter for pprust:: State < ' a > {
828
+ fn print_node ( & mut self , node : & Node ) -> IoResult < ( ) > {
829
+ match * node {
830
+ NodeItem ( a) => self . print_item ( & * a) ,
831
+ NodeForeignItem ( a) => self . print_foreign_item ( & * a) ,
832
+ NodeTraitMethod ( a) => self . print_trait_method ( & * a) ,
833
+ NodeMethod ( a) => self . print_method ( & * a) ,
834
+ NodeVariant ( a) => self . print_variant ( & * a) ,
835
+ NodeExpr ( a) => self . print_expr ( & * a) ,
836
+ NodeStmt ( a) => self . print_stmt ( & * a) ,
837
+ NodePat ( a) => self . print_pat ( & * a) ,
838
+ NodeBlock ( a) => self . print_block ( & * a) ,
839
+ NodeLifetime ( a) => self . print_lifetime ( & * a) ,
840
+
841
+ // these cases do not carry enough information in the
842
+ // ast_map to reconstruct their full structure for pretty
843
+ // printing.
844
+ NodeLocal ( _) => fail ! ( "cannot print isolated Local" ) ,
845
+ NodeArg ( _) => fail ! ( "cannot print isolated Arg" ) ,
846
+ NodeStructCtor ( _) => fail ! ( "cannot print isolated StructCtor" ) ,
847
+ }
848
+ }
849
+ }
850
+
691
851
fn node_id_to_string ( map : & Map , id : NodeId ) -> String {
692
852
match map. find ( id) {
693
853
Some ( NodeItem ( item) ) => {
0 commit comments