@@ -52,7 +52,7 @@ use std::sync::Arc;
5252
5353use externalfiles:: ExternalHtml ;
5454
55- use serialize:: json:: { self , ToJson } ;
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
@@ -534,101 +543,79 @@ pub fn run(mut krate: clean::Crate,
534543 cx. krate ( krate)
535544}
536545
546+ /// Build the search index from the collected metadata
537547fn build_index ( krate : & clean:: Crate , cache : & mut Cache ) -> String {
538- // Build the search index from the collected metadata
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- write ! ( & mut w, r#"searchIndex['{}'] = {{"items":["# , krate. name) . unwrap ( ) ;
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 ;
586581
587- let mut lastpath = "" . to_string ( ) ;
588- for ( i, item) in cache. search_index . iter ( ) . enumerate ( ) {
589- // Omit the path if it is same to that of the prior item.
590- let path;
591- if lastpath == item. path {
592- path = "" ;
593- } else {
594- lastpath = item. path . to_string ( ) ;
595- path = & item. path ;
596- } ;
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 ;
597590
598- if i > 0 {
599- write ! ( & mut w, "," ) . unwrap ( ) ;
600- }
601- write ! ( & mut w, r#"[{},"{}","{}",{}"# ,
602- item. ty as usize , item. name, path,
603- item. desc. to_json( ) . to_string( ) ) . unwrap ( ) ;
604- match item. parent {
605- Some ( nodeid) => {
606- let pathid = * nodeid_to_pathid. get ( & nodeid) . unwrap ( ) ;
607- write ! ( & mut w, ",{}" , pathid) . 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
608594 }
609- None => write ! ( & mut w, ",null" ) . unwrap ( )
610- }
611- match item. search_type {
612- Some ( ref t) => write ! ( & mut w, ",{}" , t) . unwrap ( ) ,
613- None => write ! ( & mut w, ",null" ) . unwrap ( )
614- }
615- write ! ( & mut w, "]" ) . unwrap ( ) ;
616- }
617-
618- write ! ( & mut w, r#"],"paths":["# ) . unwrap ( ) ;
595+ } ) ;
619596
620- for ( i, & did) in pathid_to_nodeid. iter ( ) . enumerate ( ) {
621- let & ( ref fqp, short) = cache. paths . get ( & did) . unwrap ( ) ;
622- if i > 0 {
623- write ! ( & mut w, "," ) . unwrap ( ) ;
597+ // Omit the parent path if it is same to that of the prior item.
598+ if lastpath == item. path {
599+ item. path . clear ( ) ;
600+ } else {
601+ lastpath = item. path . clone ( ) ;
624602 }
625- write ! ( & mut w, r#"[{},"{}"]"# ,
626- short as usize , * fqp. last( ) . unwrap( ) ) . unwrap ( ) ;
603+ crate_items. push ( item. to_json ( ) ) ;
627604 }
628605
629- write ! ( & mut w, "]}};" ) . unwrap ( ) ;
606+ let crate_doc = krate. module . as_ref ( ) . map ( |module| {
607+ Escape ( & shorter ( module. doc_value ( ) ) ) . to_string ( )
608+ } ) . unwrap_or ( String :: new ( ) ) ;
630609
631- String :: from_utf8 ( w. into_inner ( ) ) . 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) ) ;
614+
615+ // Collect the index into a string
616+ format ! ( "searchIndex[{}] = {};" ,
617+ as_json( & krate. name) ,
618+ Json :: Object ( crate_data) )
632619}
633620
634621fn write_shared ( cx : & Context ,
@@ -693,7 +680,7 @@ fn write_shared(cx: &Context,
693680 if !line. starts_with ( key) {
694681 continue
695682 }
696- if line. starts_with ( & format ! ( "{}['{}']" , key, krate) ) {
683+ if line. starts_with ( & format ! ( r# "{}["{}"]"# , key, krate) ) {
697684 continue
698685 }
699686 ret. push ( line. to_string ( ) ) ;
@@ -1067,6 +1054,7 @@ impl DocFolder for Cache {
10671054 path : path. join ( "::" ) . to_string ( ) ,
10681055 desc : Escape ( & shorter ( item. doc_value ( ) ) ) . to_string ( ) ,
10691056 parent : parent,
1057+ parent_idx : None ,
10701058 search_type : get_index_search_type ( & item, parent_basename) ,
10711059 } ) ;
10721060 }
@@ -1387,7 +1375,7 @@ impl Context {
13871375 let js_dst = this. dst . join ( "sidebar-items.js" ) ;
13881376 let mut js_out = BufWriter :: new ( try_err ! ( File :: create( & js_dst) , & js_dst) ) ;
13891377 try_err ! ( write!( & mut js_out, "initSidebarItems({});" ,
1390- json :: as_json( & items) ) , & js_dst) ;
1378+ as_json( & items) ) , & js_dst) ;
13911379 }
13921380
13931381 for item in m. items {
0 commit comments