@@ -70,7 +70,7 @@ use html::markdown;
70
70
pub struct Context {
71
71
/// Current hierarchy of components leading down to what's currently being
72
72
/// rendered
73
- pub current : Vec < String > ,
73
+ pub current : Vec < String > ,
74
74
/// String representation of how to get back to the root path of the 'doc/'
75
75
/// folder in terms of a relative URL.
76
76
pub root_path : String ,
@@ -90,6 +90,10 @@ pub struct Context {
90
90
/// the source files are present in the html rendering, then this will be
91
91
/// `true`.
92
92
pub include_sources : bool ,
93
+ /// A flag, which when turned off, will render pages which redirect to the
94
+ /// real location of an item. This is used to allow external links to
95
+ /// publicly reused items to redirect to the right location.
96
+ pub render_redirect_pages : bool ,
93
97
}
94
98
95
99
/// Indicates where an external crate can be found.
@@ -227,6 +231,7 @@ pub fn run(mut krate: clean::Crate, dst: Path) -> io::IoResult<()> {
227
231
krate : krate. name . clone ( ) ,
228
232
} ,
229
233
include_sources : true ,
234
+ render_redirect_pages : false ,
230
235
} ;
231
236
try!( mkdir ( & cx. dst ) ) ;
232
237
@@ -493,7 +498,17 @@ fn write_shared(cx: &Context,
493
498
let dst = cx. dst . join ( "implementors" ) ;
494
499
try!( mkdir ( & dst) ) ;
495
500
for ( & did, imps) in cache. implementors . iter ( ) {
496
- let & ( ref remote_path, remote_item_type) = cache. paths . get ( & did) ;
501
+ // Private modules can leak through to this phase of rustdoc, which
502
+ // could contain implementations for otherwise private types. In some
503
+ // rare cases we could find an implementation for an item which wasn't
504
+ // indexed, so we just skip this step in that case.
505
+ //
506
+ // FIXME: this is a vague explanation for why this can't be a `get`, in
507
+ // theory it should be...
508
+ let & ( ref remote_path, remote_item_type) = match cache. paths . find ( & did) {
509
+ Some ( p) => p,
510
+ None => continue ,
511
+ } ;
497
512
498
513
let mut mydst = dst. clone ( ) ;
499
514
for part in remote_path. slice_to ( remote_path. len ( ) - 1 ) . iter ( ) {
@@ -823,7 +838,7 @@ impl DocFolder for Cache {
823
838
clean:: StructItem ( ..) | clean:: EnumItem ( ..) |
824
839
clean:: TypedefItem ( ..) | clean:: TraitItem ( ..) |
825
840
clean:: FunctionItem ( ..) | clean:: ModuleItem ( ..) |
826
- clean:: ForeignFunctionItem ( ..) => {
841
+ clean:: ForeignFunctionItem ( ..) if ! self . privmod => {
827
842
// Reexported items mean that the same id can show up twice
828
843
// in the rustdoc ast that we're looking at. We know,
829
844
// however, that a reexported item doesn't show up in the
@@ -840,7 +855,7 @@ impl DocFolder for Cache {
840
855
}
841
856
// link variants to their parent enum because pages aren't emitted
842
857
// for each variant
843
- clean:: VariantItem ( ..) => {
858
+ clean:: VariantItem ( ..) if ! self . privmod => {
844
859
let mut stack = self . stack . clone ( ) ;
845
860
stack. pop ( ) ;
846
861
self . paths . insert ( item. def_id , ( stack, item_type:: Enum ) ) ;
@@ -932,14 +947,6 @@ impl DocFolder for Cache {
932
947
}
933
948
None
934
949
}
935
- // Private modules may survive the strip-private pass if
936
- // they contain impls for public types, but those will get
937
- // stripped here
938
- clean:: Item { inner : clean:: ModuleItem ( ref m) ,
939
- visibility, .. }
940
- if ( m. items . len ( ) == 0 &&
941
- item. doc_value ( ) . is_none ( ) ) ||
942
- visibility != Some ( ast:: Public ) => None ,
943
950
944
951
i => Some ( i) ,
945
952
}
@@ -1020,7 +1027,7 @@ impl Context {
1020
1027
/// The rendering driver uses this closure to queue up more work.
1021
1028
fn item ( & mut self , item : clean:: Item ,
1022
1029
f : |& mut Context , clean:: Item |) -> io:: IoResult < ( ) > {
1023
- fn render ( w : io:: File , cx : & mut Context , it : & clean:: Item ,
1030
+ fn render ( w : io:: File , cx : & Context , it : & clean:: Item ,
1024
1031
pushname : bool ) -> io:: IoResult < ( ) > {
1025
1032
info ! ( "Rendering an item to {}" , w. path( ) . display( ) ) ;
1026
1033
// A little unfortunate that this is done like this, but it sure
@@ -1047,16 +1054,42 @@ impl Context {
1047
1054
// of the pain by using a buffered writer instead of invoking the
1048
1055
// write sycall all the time.
1049
1056
let mut writer = BufferedWriter :: new ( w) ;
1050
- try!( layout:: render ( & mut writer as & mut Writer , & cx. layout , & page,
1051
- & Sidebar { cx : cx, item : it } ,
1052
- & Item { cx : cx, item : it } ) ) ;
1057
+ if !cx. render_redirect_pages {
1058
+ try!( layout:: render ( & mut writer, & cx. layout , & page,
1059
+ & Sidebar { cx : cx, item : it } ,
1060
+ & Item { cx : cx, item : it } ) ) ;
1061
+ } else {
1062
+ let mut url = "../" . repeat ( cx. current . len ( ) ) ;
1063
+ match cache_key. get ( ) . unwrap ( ) . paths . find ( & it. def_id ) {
1064
+ Some ( & ( ref names, _) ) => {
1065
+ for name in names. slice_to ( names. len ( ) - 1 ) . iter ( ) {
1066
+ url. push_str ( name. as_slice ( ) ) ;
1067
+ url. push_str ( "/" ) ;
1068
+ }
1069
+ url. push_str ( item_path ( it) . as_slice ( ) ) ;
1070
+ try!( layout:: redirect ( & mut writer, url. as_slice ( ) ) ) ;
1071
+ }
1072
+ None => { }
1073
+ }
1074
+ }
1053
1075
writer. flush ( )
1054
1076
}
1055
1077
1056
1078
match item. inner {
1057
1079
// modules are special because they add a namespace. We also need to
1058
1080
// recurse into the items of the module as well.
1059
1081
clean:: ModuleItem ( ..) => {
1082
+ // Private modules may survive the strip-private pass if they
1083
+ // contain impls for public types. These modules can also
1084
+ // contain items such as publicly reexported structures.
1085
+ //
1086
+ // External crates will provide links to these structures, so
1087
+ // these modules are recursed into, but not rendered normally (a
1088
+ // flag on the context).
1089
+ if !self . render_redirect_pages {
1090
+ self . render_redirect_pages = ignore_private_module ( & item) ;
1091
+ }
1092
+
1060
1093
let name = item. name . get_ref ( ) . to_string ( ) ;
1061
1094
let mut item = Some ( item) ;
1062
1095
self . recurse ( name, |this| {
@@ -1289,8 +1322,9 @@ fn document(w: &mut fmt::Formatter, item: &clean::Item) -> fmt::Result {
1289
1322
fn item_module ( w : & mut fmt:: Formatter , cx : & Context ,
1290
1323
item : & clean:: Item , items : & [ clean:: Item ] ) -> fmt:: Result {
1291
1324
try!( document ( w, item) ) ;
1292
- debug ! ( "{:?}" , items) ;
1293
- let mut indices = Vec :: from_fn ( items. len ( ) , |i| i) ;
1325
+ let mut indices = range ( 0 , items. len ( ) ) . filter ( |i| {
1326
+ !ignore_private_module ( & items[ * i] )
1327
+ } ) . collect :: < Vec < uint > > ( ) ;
1294
1328
1295
1329
fn cmp ( i1 : & clean:: Item , i2 : & clean:: Item , idx1 : uint , idx2 : uint ) -> Ordering {
1296
1330
if shortty ( i1) == shortty ( i2) {
@@ -1332,7 +1366,6 @@ fn item_module(w: &mut fmt::Formatter, cx: &Context,
1332
1366
}
1333
1367
}
1334
1368
1335
- debug ! ( "{:?}" , indices) ;
1336
1369
indices. sort_by ( |& i1, & i2| cmp ( & items[ i1] , & items[ i2] , i1, i2) ) ;
1337
1370
1338
1371
debug ! ( "{:?}" , indices) ;
@@ -1976,6 +2009,8 @@ impl<'a> fmt::Show for Sidebar<'a> {
1976
2009
fn build_sidebar ( m : & clean:: Module ) -> HashMap < String , Vec < String > > {
1977
2010
let mut map = HashMap :: new ( ) ;
1978
2011
for item in m. items . iter ( ) {
2012
+ if ignore_private_module ( item) { continue }
2013
+
1979
2014
let short = shortty ( item) . to_static_str ( ) ;
1980
2015
let myname = match item. name {
1981
2016
None => continue ,
@@ -2023,3 +2058,13 @@ fn item_primitive(w: &mut fmt::Formatter,
2023
2058
try!( document ( w, it) ) ;
2024
2059
render_methods ( w, it)
2025
2060
}
2061
+
2062
+ fn ignore_private_module ( it : & clean:: Item ) -> bool {
2063
+ match it. inner {
2064
+ clean:: ModuleItem ( ref m) => {
2065
+ ( m. items . len ( ) == 0 && it. doc_value ( ) . is_none ( ) ) ||
2066
+ it. visibility != Some ( ast:: Public )
2067
+ }
2068
+ _ => false ,
2069
+ }
2070
+ }
0 commit comments