@@ -23,6 +23,7 @@ use std::path::{Component, Path, PathBuf};
23
23
use std:: rc:: { Rc , Weak } ;
24
24
use std:: ffi:: OsString ;
25
25
use std:: collections:: hash_map:: Entry ;
26
+ use std:: iter:: once;
26
27
27
28
use indexmap:: IndexMap ;
28
29
use itertools:: Itertools ;
@@ -34,6 +35,7 @@ use rustc_span::def_id::DefId;
34
35
use rustc_span:: Symbol ;
35
36
use serde:: ser:: SerializeSeq ;
36
37
use serde:: { Serialize , Deserialize , de:: DeserializeOwned , Serializer } ;
38
+ use regex:: Regex ;
37
39
38
40
use super :: { collect_paths_for_type, ensure_trailing_slash, Context , RenderMode } ;
39
41
use crate :: html:: render:: search_index:: build_index;
@@ -54,6 +56,12 @@ use crate::html::static_files::{self, suffix_path};
54
56
use crate :: visit:: DocVisitor ;
55
57
use crate :: { try_err, try_none} ;
56
58
59
+ // TODO
60
+ // sort template have diff thing
61
+ // weird behavior; extract crate list from search index? or somewhere similar
62
+ // string faster loading tetchnique
63
+ // run rest of the tests and fix things up
64
+
57
65
pub ( crate ) fn write_shared (
58
66
cx : & mut Context < ' _ > ,
59
67
krate : & Crate ,
@@ -64,12 +72,17 @@ pub(crate) fn write_shared(
64
72
let crate_name = crate_name. as_str ( ) ; // rand
65
73
let crate_name_json = SortedJson :: serialize ( crate_name) ; // "rand"
66
74
67
- // for current crate
75
+ if crate_name != "foo" {
76
+ panic ! ( "{crate_name} index{} read{} write{}" , opt. enable_index_page, opt. read_rendered_cci, opt. write_rendered_cci) ;
77
+ }
78
+
79
+ let external_crates = hack_get_external_crate_names ( cx) ?;
80
+
68
81
let sources = PartsAndLocations :: < SourcesPart > :: get ( cx) ?;
69
- let serialized_search_index = build_index ( & krate, & mut Rc :: get_mut ( & mut cx. shared ) . unwrap ( ) . cache , tcx) ;
70
- let search_index = PartsAndLocations :: < SearchIndexPart > :: get ( cx, & serialized_search_index ) ?;
82
+ let SerializedSearchIndex { index , desc } = build_index ( & krate, & mut Rc :: get_mut ( & mut cx. shared ) . unwrap ( ) . cache , tcx) ;
83
+ let search_index = PartsAndLocations :: < SearchIndexPart > :: get ( cx, index ) ?;
71
84
let all_crates = PartsAndLocations :: < AllCratesPart > :: get ( crate_name_json. clone ( ) ) ?;
72
- let crates_index = PartsAndLocations :: < CratesIndexPart > :: get ( & crate_name) ?;
85
+ let crates_index = PartsAndLocations :: < CratesIndexPart > :: get ( & crate_name, & external_crates ) ?;
73
86
let trait_aliases = PartsAndLocations :: < TraitAliasPart > :: get ( cx, & crate_name_json) ?;
74
87
let type_aliases = PartsAndLocations :: < TypeAliasPart > :: get ( cx, krate, & crate_name_json) ?;
75
88
@@ -90,7 +103,7 @@ pub(crate) fn write_shared(
90
103
91
104
if opt. write_rendered_cci {
92
105
write_static_files ( cx, & opt) ?;
93
- write_search_desc ( cx, & krate, & serialized_search_index ) ?;
106
+ write_search_desc ( cx, & krate, & desc ) ?;
94
107
if opt. emit . is_empty ( ) || opt. emit . contains ( & EmitType :: InvocationSpecific ) {
95
108
if cx. include_sources {
96
109
write_rendered_cci ( cx, opt. read_rendered_cci , & opt. parts_paths , & sources) ?;
@@ -165,14 +178,14 @@ fn write_static_files(
165
178
}
166
179
167
180
/// Write the search description shards to disk
168
- fn write_search_desc ( cx : & Context < ' _ > , krate : & Crate , search_index : & SerializedSearchIndex ) -> Result < ( ) , Error > {
181
+ fn write_search_desc ( cx : & mut Context < ' _ > , krate : & Crate , search_desc : & [ ( usize , String ) ] ) -> Result < ( ) , Error > {
169
182
let crate_name = krate. name ( cx. tcx ( ) ) . to_string ( ) ;
170
183
let encoded_crate_name = SortedJson :: serialize ( & crate_name) ;
171
184
let path = PathBuf :: from_iter ( [ & cx. dst , Path :: new ( "search.desc" ) , Path :: new ( & crate_name) ] ) ;
172
185
if Path :: new ( & path) . exists ( ) {
173
186
try_err ! ( fs:: remove_dir_all( & path) , & path) ;
174
187
}
175
- for ( i, ( _, part) ) in search_index . desc . iter ( ) . enumerate ( ) {
188
+ for ( i, ( _, part) ) in search_desc . iter ( ) . enumerate ( ) {
176
189
let filename = static_files:: suffix_path (
177
190
& format ! ( "{crate_name}-desc-{i}-.js" ) ,
178
191
& cx. shared . resource_suffix ,
@@ -212,7 +225,7 @@ pub(crate) trait NamedPart: Sized {
212
225
}
213
226
214
227
/// Paths (relative to `doc/`) and their pre-merge contents
215
- #[ derive( Serialize , Deserialize ) ]
228
+ #[ derive( Serialize , Deserialize , Debug , Clone ) ]
216
229
#[ serde( transparent) ]
217
230
struct PartsAndLocations < P > {
218
231
parts : Vec < ( PathBuf , P ) > ,
@@ -239,7 +252,7 @@ impl<T, U> PartsAndLocations<Part<T, U>> {
239
252
impl < T , U : Serialize > PartsAndLocations < Part < T , U > >
240
253
where Part < T , U > : NamedPart ,
241
254
{
242
- fn write ( & self , cx : & Context < ' _ > , parts_path : & PathToParts ) -> Result < ( ) , Error > {
255
+ fn write ( & self , cx : & mut Context < ' _ > , parts_path : & PathToParts ) -> Result < ( ) , Error > {
243
256
let name = ExternalCrate :: LOCAL . name ( cx. tcx ( ) ) ;
244
257
let path = parts_path. cci_path :: < Part < T , U > > ( name. as_str ( ) ) ;
245
258
write_create_parents ( cx, path, serde_json:: to_string ( self ) . unwrap ( ) ) ?;
@@ -260,9 +273,9 @@ else if (window.initSearch) window.initSearch(searchIndex);")
260
273
}
261
274
}
262
275
impl PartsAndLocations < SearchIndexPart > {
263
- fn get ( cx : & Context < ' _ > , search_index : & SerializedSearchIndex ) -> Result < Self , Error > {
276
+ fn get ( cx : & Context < ' _ > , search_index : SortedJson ) -> Result < Self , Error > {
264
277
let path = suffix_path ( "search-index.js" , & cx. shared . resource_suffix ) ;
265
- Ok ( Self :: with ( path, SortedJson :: serialize ( & search_index. index ) ) )
278
+ Ok ( Self :: with ( path, search_index) )
266
279
}
267
280
}
268
281
@@ -282,6 +295,24 @@ impl PartsAndLocations<AllCratesPart> {
282
295
Ok ( Self :: with ( path, crate_name_json) )
283
296
}
284
297
}
298
+ /// Reads `crates.js`, which seems like the best
299
+ /// place to obtain the list of externally documented crates if the index
300
+ /// page was disabled when documenting the deps
301
+ fn hack_get_external_crate_names ( cx : & Context < ' _ > ) -> Result < Vec < String > , Error > {
302
+ let path = cx. dst . join ( "crates.js" ) ;
303
+ let Ok ( content) = fs:: read_to_string ( & path) else {
304
+ // they didn't emit invocation specific, so we just say there were no crates
305
+ return Ok ( Vec :: default ( ) )
306
+ } ;
307
+ // this is run only one once so it's fine not to cache it
308
+ // dot_matches_new_line false: all crates on same line. greedy: match last bracket
309
+ let regex = Regex :: new ( r"\[.*\]" ) . unwrap ( ) ;
310
+ let Some ( content) = regex. find ( & content) else {
311
+ return Err ( Error :: new ( "could not find crates list in crates.js" , path) ) ;
312
+ } ;
313
+ let content: Vec < String > = try_err ! ( serde_json:: from_str( content. as_str( ) ) , & path) ;
314
+ Ok ( content)
315
+ }
285
316
286
317
#[ derive( Serialize , Deserialize , Clone , Default , Debug ) ]
287
318
struct CratesIndex ;
@@ -314,13 +345,18 @@ impl NamedPart for CratesIndexPart {
314
345
}
315
346
}
316
347
impl PartsAndLocations < CratesIndexPart > {
317
- fn get ( crate_name : & str ) -> Result < Self , Error > {
348
+ /// Might return parts that are duplicate with ones in prexisting index.html
349
+ fn get ( crate_name : & str , external_crates : & [ String ] ) -> Result < Self , Error > {
350
+ let mut ret = Self :: default ( ) ;
318
351
let path = PathBuf :: from ( "index.html" ) ;
319
- let part = format ! (
320
- "<li><a href=\" {trailing_slash}index.html\" >{crate_name}</a></li>" ,
321
- trailing_slash = ensure_trailing_slash( crate_name) ,
322
- ) ;
323
- Ok ( Self :: with ( path, part) )
352
+ for crate_name in external_crates. iter ( ) . map ( |s| s. as_str ( ) ) . chain ( once ( crate_name) ) {
353
+ let part = format ! (
354
+ "<li><a href=\" {trailing_slash}index.html\" >{crate_name}</a></li>" ,
355
+ trailing_slash = ensure_trailing_slash( crate_name) ,
356
+ ) ;
357
+ ret. push ( path. clone ( ) , part) ;
358
+ }
359
+ Ok ( ret)
324
360
}
325
361
}
326
362
@@ -784,19 +820,25 @@ impl Serialize for AliasSerializableImpl {
784
820
}
785
821
}
786
822
787
- fn write_create_parents ( cx : & Context < ' _ > , path : PathBuf , content : String ) -> Result < ( ) , Error > {
823
+ fn create_parents ( cx : & mut Context < ' _ > , path : & Path ) -> Result < ( ) , Error > {
788
824
let parent = path. parent ( ) . expect ( "trying to write to an empty path" ) ;
825
+ // TODO: check cache for whether this directory has already been created
789
826
try_err ! ( cx. shared. fs. create_dir_all( parent) , parent) ;
827
+ Ok ( ( ) )
828
+ }
829
+
830
+ fn write_create_parents ( cx : & mut Context < ' _ > , path : PathBuf , content : String ) -> Result < ( ) , Error > {
831
+ create_parents ( cx, & path) ?;
790
832
cx. shared . fs . write ( path, content) ?;
791
833
Ok ( ( ) )
792
834
}
793
835
794
- fn write_rendered_cci < T : NamedPart + DeserializeOwned + fmt:: Display > (
795
- cx : & Context < ' _ > ,
836
+ fn write_rendered_cci < T : NamedPart + DeserializeOwned + fmt:: Display + fmt :: Debug > (
837
+ cx : & mut Context < ' _ > ,
796
838
read_rendered_cci : bool ,
797
839
parts_paths : & FxHashMap < String , PathToParts > ,
798
840
our_parts_and_locations : & PartsAndLocations < T > ,
799
- ) -> Result < ( ) , Error > {
841
+ ) -> Result < ( ) , Error > where < T as NamedPart > :: FileFormat : std :: fmt :: Debug {
800
842
// read parts from disk
801
843
let path_parts = parts_paths. iter ( )
802
844
. map ( |( crate_name, parts_path) | {
@@ -810,11 +852,12 @@ fn write_rendered_cci<T: NamedPart + DeserializeOwned + fmt::Display>(
810
852
. map ( |parts_and_locations| parts_and_locations. parts . iter ( ) )
811
853
. flatten ( )
812
854
. chain ( our_parts_and_locations. parts . iter ( ) ) ;
813
- // read previous cci from storage, append to them
855
+ // read previous rendered cci from storage, append to them
814
856
let mut templates: FxHashMap < PathBuf , OffsetTemplate < T :: FileFormat > > = Default :: default ( ) ;
815
857
for ( path, part) in path_parts {
816
858
let part = format ! ( "{part}" ) ;
817
- match templates. entry ( cx. dst . join ( & path) ) {
859
+ let path = cx. dst . join ( & path) ;
860
+ match templates. entry ( path. clone ( ) ) {
818
861
Entry :: Vacant ( entry) => {
819
862
let template = entry. insert ( if read_rendered_cci {
820
863
match fs:: read_to_string ( & path) {
@@ -832,6 +875,8 @@ fn write_rendered_cci<T: NamedPart + DeserializeOwned + fmt::Display>(
832
875
}
833
876
// write the merged cci to disk
834
877
for ( path, template) in templates {
878
+ dbg ! ( & path, & template, & cx. dst) ;
879
+ create_parents ( cx, & path) ?;
835
880
let file = try_err ! ( File :: create( & path) , & path) ;
836
881
let mut file = BufWriter :: new ( file) ;
837
882
try_err ! ( write!( file, "{template}" ) , & path) ;
0 commit comments