@@ -52,7 +52,7 @@ use std::sync::Arc;
5252
5353use externalfiles:: ExternalHtml ;
5454
55- use serialize:: json:: as_json;
55+ use serialize:: json:: { ToJson , Json , as_json} ;
5656use syntax:: { abi, ast} ;
5757use syntax:: feature_gate:: UnstableFeatures ;
5858use rustc:: middle:: cstore:: LOCAL_CRATE ;
@@ -290,22 +290,40 @@ struct IndexItem {
290290 path : String ,
291291 desc : String ,
292292 parent : Option < DefId > ,
293+ parent_idx : Option < usize > ,
293294 search_type : Option < IndexItemFunctionType > ,
294295}
295296
297+ impl ToJson for IndexItem {
298+ fn to_json ( & self ) -> Json {
299+ assert_eq ! ( self . parent. is_some( ) , self . parent_idx. is_some( ) ) ;
300+
301+ let mut data = Vec :: with_capacity ( 6 ) ;
302+ data. push ( ( self . ty as usize ) . to_json ( ) ) ;
303+ data. push ( self . name . to_json ( ) ) ;
304+ data. push ( self . path . to_json ( ) ) ;
305+ data. push ( self . desc . to_json ( ) ) ;
306+ data. push ( self . parent_idx . to_json ( ) ) ;
307+ data. push ( self . search_type . to_json ( ) ) ;
308+
309+ Json :: Array ( data)
310+ }
311+ }
312+
296313/// A type used for the search index.
297314struct Type {
298315 name : Option < String > ,
299316}
300317
301- impl fmt:: Display for Type {
302- /// Formats type as {name: $name}.
303- fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
304- // Wrapping struct fmt should never call us when self.name is None,
305- // but just to be safe we write `null` in that case.
318+ impl ToJson for Type {
319+ fn to_json ( & self ) -> Json {
306320 match self . name {
307- Some ( ref n) => write ! ( f, "{{\" name\" :\" {}\" }}" , n) ,
308- None => write ! ( f, "null" )
321+ Some ( ref name) => {
322+ let mut data = BTreeMap :: new ( ) ;
323+ data. insert ( "name" . to_owned ( ) , name. to_json ( ) ) ;
324+ Json :: Object ( data)
325+ } ,
326+ None => Json :: Null
309327 }
310328 }
311329}
@@ -316,26 +334,17 @@ struct IndexItemFunctionType {
316334 output : Option < Type >
317335}
318336
319- impl fmt:: Display for IndexItemFunctionType {
320- /// Formats a full fn type as a JSON {inputs: [Type], outputs: Type/null}.
321- fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
337+ impl ToJson for IndexItemFunctionType {
338+ fn to_json ( & self ) -> Json {
322339 // If we couldn't figure out a type, just write `null`.
323- if self . inputs . iter ( ) . any ( |ref i| i. name . is_none ( ) ) ||
324- ( self . output . is_some ( ) && self . output . as_ref ( ) . unwrap ( ) . name . is_none ( ) ) {
325- return write ! ( f, "null" )
340+ if self . inputs . iter ( ) . chain ( self . output . iter ( ) ) . any ( |ref i| i. name . is_none ( ) ) {
341+ Json :: Null
342+ } else {
343+ let mut data = BTreeMap :: new ( ) ;
344+ data. insert ( "inputs" . to_owned ( ) , self . inputs . to_json ( ) ) ;
345+ data. insert ( "output" . to_owned ( ) , self . output . to_json ( ) ) ;
346+ Json :: Object ( data)
326347 }
327-
328- let inputs: Vec < String > = self . inputs . iter ( ) . map ( |ref t| {
329- format ! ( "{}" , t)
330- } ) . collect ( ) ;
331- try!( write ! ( f, "{{\" inputs\" :[{}],\" output\" :" , inputs. join( "," ) ) ) ;
332-
333- match self . output {
334- Some ( ref t) => try!( write ! ( f, "{}" , t) ) ,
335- None => try!( write ! ( f, "null" ) )
336- } ;
337-
338- Ok ( try!( write ! ( f, "}}" ) ) )
339348 }
340349}
341350
@@ -537,104 +546,76 @@ pub fn run(mut krate: clean::Crate,
537546/// Build the search index from the collected metadata
538547fn build_index ( krate : & clean:: Crate , cache : & mut Cache ) -> String {
539548 let mut nodeid_to_pathid = HashMap :: new ( ) ;
540- let mut pathid_to_nodeid = Vec :: new ( ) ;
541- {
542- let Cache { ref mut search_index,
543- ref orphan_methods,
544- ref mut paths, .. } = * cache;
545-
546- // Attach all orphan methods to the type's definition if the type
547- // has since been learned.
548- for & ( did, ref item) in orphan_methods {
549- match paths. get ( & did) {
550- Some ( & ( ref fqp, _) ) => {
551- // Needed to determine `self` type.
552- let parent_basename = Some ( fqp[ fqp. len ( ) - 1 ] . clone ( ) ) ;
553- search_index. push ( IndexItem {
554- ty : shortty ( item) ,
555- name : item. name . clone ( ) . unwrap ( ) ,
556- path : fqp[ ..fqp. len ( ) - 1 ] . join ( "::" ) ,
557- desc : Escape ( & shorter ( item. doc_value ( ) ) ) . to_string ( ) ,
558- parent : Some ( did) ,
559- search_type : get_index_search_type ( & item, parent_basename) ,
560- } ) ;
561- } ,
562- None => { }
563- }
564- }
565-
566- // Reduce `NodeId` in paths into smaller sequential numbers,
567- // and prune the paths that do not appear in the index.
568- for item in search_index. iter ( ) {
569- match item. parent {
570- Some ( nodeid) => {
571- if !nodeid_to_pathid. contains_key ( & nodeid) {
572- let pathid = pathid_to_nodeid. len ( ) ;
573- nodeid_to_pathid. insert ( nodeid, pathid) ;
574- pathid_to_nodeid. push ( nodeid) ;
575- }
576- }
577- None => { }
578- }
549+ let mut crate_items = Vec :: with_capacity ( cache. search_index . len ( ) ) ;
550+ let mut crate_paths = Vec :: < Json > :: new ( ) ;
551+
552+ let Cache { ref mut search_index,
553+ ref orphan_methods,
554+ ref mut paths, .. } = * cache;
555+
556+ // Attach all orphan methods to the type's definition if the type
557+ // has since been learned.
558+ for & ( did, ref item) in orphan_methods {
559+ match paths. get ( & did) {
560+ Some ( & ( ref fqp, _) ) => {
561+ // Needed to determine `self` type.
562+ let parent_basename = Some ( fqp[ fqp. len ( ) - 1 ] . clone ( ) ) ;
563+ search_index. push ( IndexItem {
564+ ty : shortty ( item) ,
565+ name : item. name . clone ( ) . unwrap ( ) ,
566+ path : fqp[ ..fqp. len ( ) - 1 ] . join ( "::" ) ,
567+ desc : Escape ( & shorter ( item. doc_value ( ) ) ) . to_string ( ) ,
568+ parent : Some ( did) ,
569+ parent_idx : None ,
570+ search_type : get_index_search_type ( & item, parent_basename) ,
571+ } ) ;
572+ } ,
573+ None => { }
579574 }
580- assert_eq ! ( nodeid_to_pathid. len( ) , pathid_to_nodeid. len( ) ) ;
581575 }
582576
583- // Collect the index into a string
584- let mut w = io:: Cursor :: new ( Vec :: new ( ) ) ;
585- let krate_doc = krate. module . as_ref ( ) . map ( |module| {
586- Escape ( & shorter ( module. doc_value ( ) ) ) . to_string ( )
587- } ) . unwrap_or ( "" . to_owned ( ) ) ;
577+ // Reduce `NodeId` in paths into smaller sequential numbers,
578+ // and prune the paths that do not appear in the index.
579+ let mut lastpath = String :: new ( ) ;
580+ let mut lastpathid = 0usize ;
581+
582+ for item in search_index {
583+ item. parent_idx = item. parent . map ( |nodeid| {
584+ if nodeid_to_pathid. contains_key ( & nodeid) {
585+ * nodeid_to_pathid. get ( & nodeid) . unwrap ( )
586+ } else {
587+ let pathid = lastpathid;
588+ nodeid_to_pathid. insert ( nodeid, pathid) ;
589+ lastpathid += 1 ;
588590
589- write ! ( & mut w, r#"searchIndex[{}] = {{doc: {}, "items":["# ,
590- as_json( & krate. name) ,
591- as_json( & krate_doc) ) . unwrap ( ) ;
591+ let & ( ref fqp, short) = paths. get ( & nodeid) . unwrap ( ) ;
592+ crate_paths. push ( ( ( short as usize ) , fqp. last ( ) . unwrap ( ) . clone ( ) ) . to_json ( ) ) ;
593+ pathid
594+ }
595+ } ) ;
592596
593- let mut lastpath = "" . to_string ( ) ;
594- for ( i, item) in cache. search_index . iter ( ) . enumerate ( ) {
595- // Omit the path if it is same to that of the prior item.
596- let path;
597+ // Omit the parent path if it is same to that of the prior item.
597598 if lastpath == item. path {
598- path = "" ;
599+ item . path . clear ( ) ;
599600 } else {
600- lastpath = item. path . to_string ( ) ;
601- path = & item. path ;
602- } ;
603-
604- if i > 0 {
605- write ! ( & mut w, "," ) . unwrap ( ) ;
606- }
607- write ! ( & mut w, "[{},{},{},{}" ,
608- item. ty as usize ,
609- as_json( & item. name) , as_json( & path) , as_json( & item. desc) ) . unwrap ( ) ;
610- match item. parent {
611- Some ( nodeid) => {
612- let pathid = * nodeid_to_pathid. get ( & nodeid) . unwrap ( ) ;
613- write ! ( & mut w, ",{}" , pathid) . unwrap ( ) ;
614- }
615- None => write ! ( & mut w, ",null" ) . unwrap ( )
616- }
617- match item. search_type {
618- Some ( ref t) => write ! ( & mut w, ",{}" , t) . unwrap ( ) ,
619- None => write ! ( & mut w, ",null" ) . unwrap ( )
601+ lastpath = item. path . clone ( ) ;
620602 }
621- write ! ( & mut w , "]" ) . unwrap ( ) ;
603+ crate_items . push ( item . to_json ( ) ) ;
622604 }
623605
624- write ! ( & mut w, r#"],"paths":["# ) . unwrap ( ) ;
625-
626- for ( i, & did) in pathid_to_nodeid. iter ( ) . enumerate ( ) {
627- let & ( ref fqp, short) = cache. paths . get ( & did) . unwrap ( ) ;
628- if i > 0 {
629- write ! ( & mut w, "," ) . unwrap ( ) ;
630- }
631- write ! ( & mut w, r#"[{},"{}"]"# ,
632- short as usize , * fqp. last( ) . unwrap( ) ) . unwrap ( ) ;
633- }
606+ let crate_doc = krate. module . as_ref ( ) . map ( |module| {
607+ Escape ( & shorter ( module. doc_value ( ) ) ) . to_string ( )
608+ } ) . unwrap_or ( String :: new ( ) ) ;
634609
635- write ! ( & mut w, "]}};" ) . unwrap ( ) ;
610+ let mut crate_data = BTreeMap :: new ( ) ;
611+ crate_data. insert ( "doc" . to_owned ( ) , Json :: String ( crate_doc) ) ;
612+ crate_data. insert ( "items" . to_owned ( ) , Json :: Array ( crate_items) ) ;
613+ crate_data. insert ( "paths" . to_owned ( ) , Json :: Array ( crate_paths) ) ;
636614
637- String :: from_utf8 ( w. into_inner ( ) ) . unwrap ( )
615+ // Collect the index into a string
616+ format ! ( "searchIndex[{}] = {};" ,
617+ as_json( & krate. name) ,
618+ Json :: Object ( crate_data) )
638619}
639620
640621fn write_shared ( cx : & Context ,
@@ -1073,6 +1054,7 @@ impl DocFolder for Cache {
10731054 path : path. join ( "::" ) . to_string ( ) ,
10741055 desc : Escape ( & shorter ( item. doc_value ( ) ) ) . to_string ( ) ,
10751056 parent : parent,
1057+ parent_idx : None ,
10761058 search_type : get_index_search_type ( & item, parent_basename) ,
10771059 } ) ;
10781060 }
0 commit comments