@@ -150,7 +150,10 @@ pub struct Cache {
150
150
/// When rendering traits, it's often useful to be able to list all
151
151
/// implementors of the trait, and this mapping is exactly, that: a mapping
152
152
/// of trait ids to the list of known implementors of the trait
153
- pub implementors : HashMap < ast:: NodeId , Vec < Implementor > > ,
153
+ pub implementors : HashMap < ast:: NodeId , Vec < Implementor > > ,
154
+
155
+ /// Implementations of external traits, keyed by the external trait def id.
156
+ pub foreign_implementors : HashMap < ast:: DefId , Vec < Implementor > > ,
154
157
155
158
/// Cache of where external crate documentation can be found.
156
159
pub extern_locations : HashMap < ast:: CrateNum , ExternalLocation > ,
@@ -268,6 +271,7 @@ pub fn run(mut krate: clean::Crate, dst: Path) -> io::IoResult<()> {
268
271
paths : paths,
269
272
traits : HashMap :: new ( ) ,
270
273
implementors : HashMap :: new ( ) ,
274
+ foreign_implementors : HashMap :: new ( ) ,
271
275
stack : Vec :: new ( ) ,
272
276
parent_stack : Vec :: new ( ) ,
273
277
search_index : Vec :: new ( ) ,
@@ -396,26 +400,84 @@ pub fn run(mut krate: clean::Crate, dst: Path) -> io::IoResult<()> {
396
400
try!( write ( cx. dst . join ( "Heuristica-Bold.woff" ) ,
397
401
include_bin ! ( "static/Heuristica-Bold.woff" ) ) ) ;
398
402
399
- // Update the search index
400
- let dst = cx. dst . join ( "search-index.js" ) ;
401
- let mut all_indexes = Vec :: new ( ) ;
402
- all_indexes. push ( index) ;
403
- if dst. exists ( ) {
404
- for line in BufferedReader :: new ( File :: open ( & dst) ) . lines ( ) {
405
- let line = try!( line) ;
406
- if !line. starts_with ( "searchIndex" ) { continue }
407
- if line. starts_with ( format ! ( "searchIndex['{}']" , krate. name) ) {
408
- continue
403
+ fn collect ( path : & Path , krate : & str ,
404
+ key : & str ) -> io:: IoResult < Vec < StrBuf > > {
405
+ let mut ret = Vec :: new ( ) ;
406
+ if path. exists ( ) {
407
+ for line in BufferedReader :: new ( File :: open ( path) ) . lines ( ) {
408
+ let line = try!( line) ;
409
+ if !line. starts_with ( key) { continue }
410
+ if line. starts_with ( format ! ( "{}['{}']" , key, krate) ) {
411
+ continue
412
+ }
413
+ ret. push ( line. to_strbuf ( ) ) ;
409
414
}
410
- all_indexes. push ( line) ;
411
415
}
416
+ return Ok ( ret) ;
412
417
}
418
+
419
+ // Update the search index
420
+ let dst = cx. dst . join ( "search-index.js" ) ;
421
+ let all_indexes = try!( collect ( & dst, krate. name . as_slice ( ) ,
422
+ "searchIndex" ) ) ;
413
423
let mut w = try!( File :: create ( & dst) ) ;
414
424
try!( writeln ! ( & mut w, r"var searchIndex = \{\};" ) ) ;
425
+ try!( writeln ! ( & mut w, "{}" , index) ) ;
415
426
for index in all_indexes. iter ( ) {
416
427
try!( writeln ! ( & mut w, "{}" , * index) ) ;
417
428
}
418
429
try!( writeln ! ( & mut w, "initSearch(searchIndex);" ) ) ;
430
+
431
+ // Update the list of all implementors for traits
432
+ let dst = cx. dst . join ( "implementors" ) ;
433
+ try!( mkdir ( & dst) ) ;
434
+ for ( & did, imps) in cache. foreign_implementors . iter ( ) {
435
+ let & ( ref remote_path, remote_item_type) = cache. paths . get ( & did) ;
436
+
437
+ let mut mydst = dst. clone ( ) ;
438
+ for part in remote_path. slice_to ( remote_path. len ( ) - 1 ) . iter ( ) {
439
+ mydst. push ( part. as_slice ( ) ) ;
440
+ try!( mkdir ( & mydst) ) ;
441
+ }
442
+ mydst. push ( format ! ( "{}.{}.js" ,
443
+ remote_item_type. to_static_str( ) ,
444
+ * remote_path. get( remote_path. len( ) - 1 ) ) ) ;
445
+ let all_implementors = try!( collect ( & mydst, krate. name . as_slice ( ) ,
446
+ "implementors" ) ) ;
447
+
448
+ try!( mkdir ( & mydst. dir_path ( ) ) ) ;
449
+ let mut f = BufferedWriter :: new ( try!( File :: create ( & mydst) ) ) ;
450
+ try!( writeln ! ( & mut f, r"(function() \{var implementors = \{\};" ) ) ;
451
+
452
+ for implementor in all_implementors. iter ( ) {
453
+ try!( writeln ! ( & mut f, "{}" , * implementor) ) ;
454
+ }
455
+
456
+ try!( write ! ( & mut f, r"implementors['{}'] = \{" , krate. name) ) ;
457
+ for imp in imps. iter ( ) {
458
+ let & ( ref path, item_type) = match * imp {
459
+ PathType ( clean:: ResolvedPath { did, .. } ) => {
460
+ cache. paths . get ( & did)
461
+ }
462
+ PathType ( ..) | OtherType ( ..) => continue ,
463
+ } ;
464
+ try!( write ! ( & mut f, r#"{}:"# , * path. get( path. len( ) - 1 ) ) ) ;
465
+ try!( write ! ( & mut f, r#""{}"# ,
466
+ path. slice_to( path. len( ) - 1 ) . connect( "/" ) ) ) ;
467
+ try!( write ! ( & mut f, r#"/{}.{}.html","# ,
468
+ item_type. to_static_str( ) ,
469
+ * path. get( path. len( ) - 1 ) ) ) ;
470
+ }
471
+ try!( writeln ! ( & mut f, r"\};" ) ) ;
472
+ try!( writeln ! ( & mut f, "{}" , r"
473
+ if (window.register_implementors) {
474
+ window.register_implementors(implementors);
475
+ } else {
476
+ window.pending_implementors = implementors;
477
+ }
478
+ " ) ) ;
479
+ try!( writeln ! ( & mut f, r"\})()" ) ) ;
480
+ }
419
481
}
420
482
421
483
// Render all source files (this may turn into a giant no-op)
@@ -635,13 +697,13 @@ impl DocFolder for Cache {
635
697
match i. trait_ {
636
698
// FIXME: this is_local() check seems to be losing
637
699
// information
638
- Some ( clean:: ResolvedPath { did, .. } )
639
- if ast_util:: is_local ( did) =>
640
- {
641
- let id = did . node ;
642
- let v = self . implementors . find_or_insert_with ( id , |_| {
643
- Vec :: new ( )
644
- } ) ;
700
+ Some ( clean:: ResolvedPath { did, .. } ) => {
701
+ let v = if ast_util:: is_local ( did) {
702
+ self . implementors . find_or_insert ( did . node , Vec :: new ( ) )
703
+ } else {
704
+ self . foreign_implementors . find_or_insert ( did ,
705
+ Vec :: new ( ) )
706
+ } ;
645
707
match i. for_ {
646
708
clean:: ResolvedPath { ..} => {
647
709
v. unshift ( PathType ( i. for_ . clone ( ) ) ) ;
@@ -1050,7 +1112,7 @@ impl<'a> fmt::Show for Item<'a> {
1050
1112
}
1051
1113
clean:: FunctionItem ( ref f) | clean:: ForeignFunctionItem ( ref f) =>
1052
1114
item_function ( fmt, self . item , f) ,
1053
- clean:: TraitItem ( ref t) => item_trait ( fmt, self . item , t) ,
1115
+ clean:: TraitItem ( ref t) => item_trait ( fmt, self . cx , self . item , t) ,
1054
1116
clean:: StructItem ( ref s) => item_struct ( fmt, self . item , s) ,
1055
1117
clean:: EnumItem ( ref e) => item_enum ( fmt, self . item , e) ,
1056
1118
clean:: TypedefItem ( ref t) => item_typedef ( fmt, self . item , t) ,
@@ -1273,7 +1335,7 @@ fn item_function(w: &mut fmt::Formatter, it: &clean::Item,
1273
1335
document ( w, it)
1274
1336
}
1275
1337
1276
- fn item_trait ( w : & mut fmt:: Formatter , it : & clean:: Item ,
1338
+ fn item_trait ( w : & mut fmt:: Formatter , cx : & Context , it : & clean:: Item ,
1277
1339
t : & clean:: Trait ) -> fmt:: Result {
1278
1340
let mut parents = StrBuf :: new ( ) ;
1279
1341
if t. parents . len ( ) > 0 {
@@ -1353,7 +1415,7 @@ fn item_trait(w: &mut fmt::Formatter, it: &clean::Item,
1353
1415
Some ( implementors) => {
1354
1416
try!( write ! ( w, "
1355
1417
<h2 id='implementors'>Implementors</h2>
1356
- <ul class='item-list'>
1418
+ <ul class='item-list' id='implementors-list' >
1357
1419
" ) ) ;
1358
1420
for i in implementors. iter ( ) {
1359
1421
match * i {
@@ -1367,6 +1429,13 @@ fn item_trait(w: &mut fmt::Formatter, it: &clean::Item,
1367
1429
}
1368
1430
}
1369
1431
try!( write ! ( w, "</ul>" ) ) ;
1432
+ try!( write ! ( w, r#"<script type="text/javascript" async
1433
+ src="{}/implementors/{}/{}.{}.js"></script>"# ,
1434
+ cx. current. iter( ) . map( |_| ".." )
1435
+ . collect:: <Vec <& str >>( ) . connect( "/" ) ,
1436
+ cx. current. connect( "/" ) ,
1437
+ shortty( it) . to_static_str( ) ,
1438
+ * it. name. get_ref( ) ) ) ;
1370
1439
}
1371
1440
None => { }
1372
1441
}
0 commit comments