1111use abi;
1212use ast:: * ;
1313use ast_util;
14- use codemap:: Span ;
14+ use codemap:: { Span , Spanned } ;
1515use fold:: Folder ;
1616use fold;
1717use parse:: token;
@@ -21,6 +21,7 @@ use util::small_vector::SmallVector;
2121use std:: cell:: RefCell ;
2222use std:: fmt;
2323use std:: gc:: { Gc , GC } ;
24+ use std:: io:: IoResult ;
2425use std:: iter;
2526use std:: slice;
2627
@@ -203,6 +204,10 @@ pub struct Map {
203204}
204205
205206impl Map {
207+ fn entry_count ( & self ) -> uint {
208+ self . map . borrow ( ) . len ( )
209+ }
210+
206211 fn find_entry ( & self , id : NodeId ) -> Option < MapEntry > {
207212 let map = self . map . borrow ( ) ;
208213 if map. len ( ) > id as uint {
@@ -405,6 +410,20 @@ impl Map {
405410 f ( attrs)
406411 }
407412
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+
408427 pub fn opt_span ( & self , id : NodeId ) -> Option < Span > {
409428 let sp = match self . find ( id) {
410429 Some ( NodeItem ( item) ) => item. span ,
@@ -438,6 +457,119 @@ impl Map {
438457 }
439458}
440459
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+
441573pub trait FoldOps {
442574 fn new_id ( & self , id : NodeId ) -> NodeId {
443575 id
@@ -688,6 +820,34 @@ pub fn map_decoded_item<F: FoldOps>(map: &Map,
688820 ii
689821}
690822
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+
691851fn node_id_to_string ( map : & Map , id : NodeId ) -> String {
692852 match map. find ( id) {
693853 Some ( NodeItem ( item) ) => {
0 commit comments