15
15
16
16
use std:: any:: Any ;
17
17
use std:: cell:: RefCell ;
18
- use std:: collections:: hash_map:: Entry ;
19
18
use std:: ffi:: OsString ;
20
19
use std:: fs:: File ;
21
20
use std:: io:: BufWriter ;
@@ -52,7 +51,7 @@ use crate::html::layout;
52
51
use crate :: html:: render:: search_index:: build_index;
53
52
use crate :: html:: render:: search_index:: SerializedSearchIndex ;
54
53
use crate :: html:: render:: sorted_json:: { EscapedJson , SortedJson } ;
55
- use crate :: html:: render:: sorted_template:: { self , SortedTemplate } ;
54
+ use crate :: html:: render:: sorted_template:: { self , FileFormat , SortedTemplate } ;
56
55
use crate :: html:: render:: { AssocItemLink , ImplRenderingParameters } ;
57
56
use crate :: html:: static_files:: { self , suffix_path} ;
58
57
use crate :: visit:: DocVisitor ;
@@ -78,33 +77,29 @@ pub(crate) fn write_shared(
78
77
let crate_name = krate. name ( cx. tcx ( ) ) ;
79
78
let crate_name = crate_name. as_str ( ) ; // rand
80
79
let crate_name_json = SortedJson :: serialize ( crate_name) ; // "rand"
81
- let external_crates = hack_get_external_crate_names ( cx ) ?;
80
+ let external_crates = hack_get_external_crate_names ( & cx . dst ) ?;
82
81
let info = CrateInfo {
83
82
src_files_js : SourcesPart :: get ( cx, & crate_name_json) ?,
84
- search_index_js : SearchIndexPart :: get ( cx , index ) ?,
83
+ search_index_js : SearchIndexPart :: get ( index , & cx . shared . resource_suffix ) ?,
85
84
all_crates : AllCratesPart :: get ( crate_name_json. clone ( ) ) ?,
86
85
crates_index : CratesIndexPart :: get ( & crate_name, & external_crates) ?,
87
86
trait_impl : TraitAliasPart :: get ( cx, & crate_name_json) ?,
88
87
type_impl : TypeAliasPart :: get ( cx, krate, & crate_name_json) ?,
89
88
} ;
90
89
91
- let crates_info = vec ! [ info] ; // we have info from just one crate
90
+ let crates = vec ! [ info] ; // we have info from just one crate. rest will found in out dir
92
91
93
92
write_static_files ( cx, & opt) ?;
94
93
let dst = & cx. dst ;
95
94
if opt. emit . is_empty ( ) || opt. emit . contains ( & EmitType :: InvocationSpecific ) {
96
95
if cx. include_sources {
97
- write_rendered_cci :: < SourcesPart , _ > ( SourcesPart :: blank, dst, & crates_info ) ?;
96
+ write_rendered_cci :: < SourcesPart , _ > ( SourcesPart :: blank, dst, & crates ) ?;
98
97
}
99
- write_rendered_cci :: < SearchIndexPart , _ > (
100
- SearchIndexPart :: blank,
101
- dst,
102
- & crates_info,
103
- ) ?;
104
- write_rendered_cci :: < AllCratesPart , _ > ( AllCratesPart :: blank, dst, & crates_info) ?;
105
- }
106
- write_rendered_cci :: < TraitAliasPart , _ > ( TraitAliasPart :: blank, dst, & crates_info) ?;
107
- write_rendered_cci :: < TypeAliasPart , _ > ( TypeAliasPart :: blank, dst, & crates_info) ?;
98
+ write_rendered_cci :: < SearchIndexPart , _ > ( SearchIndexPart :: blank, dst, & crates) ?;
99
+ write_rendered_cci :: < AllCratesPart , _ > ( AllCratesPart :: blank, dst, & crates) ?;
100
+ }
101
+ write_rendered_cci :: < TraitAliasPart , _ > ( TraitAliasPart :: blank, dst, & crates) ?;
102
+ write_rendered_cci :: < TypeAliasPart , _ > ( TypeAliasPart :: blank, dst, & crates) ?;
108
103
match & opt. index_page {
109
104
Some ( index_page) if opt. enable_index_page => {
110
105
let mut md_opts = opt. clone ( ) ;
@@ -119,7 +114,7 @@ pub(crate) fn write_shared(
119
114
write_rendered_cci :: < CratesIndexPart , _ > (
120
115
|| CratesIndexPart :: blank ( cx) ,
121
116
dst,
122
- & crates_info ,
117
+ & crates ,
123
118
) ?;
124
119
}
125
120
_ => { } // they don't want an index page
@@ -189,7 +184,8 @@ fn write_search_desc(
189
184
let path = path. join ( filename) ;
190
185
let part = SortedJson :: serialize ( & part) ;
191
186
let part = format ! ( "searchState.loadedDescShard({encoded_crate_name}, {i}, {part})" ) ;
192
- write_create_parents ( & path, part) ?;
187
+ create_parents ( & path) ?;
188
+ try_err ! ( fs:: write( & path, part) , & path) ;
193
189
}
194
190
Ok ( ( ) )
195
191
}
@@ -286,8 +282,11 @@ else if (window.initSearch) window.initSearch(searchIndex);",
286
282
)
287
283
}
288
284
289
- fn get ( cx : & Context < ' _ > , search_index : SortedJson ) -> Result < PartsAndLocations < Self > , Error > {
290
- let path = suffix_path ( "search-index.js" , & cx. shared . resource_suffix ) ;
285
+ fn get (
286
+ search_index : SortedJson ,
287
+ resource_suffix : & str ,
288
+ ) -> Result < PartsAndLocations < Self > , Error > {
289
+ let path = suffix_path ( "search-index.js" , resource_suffix) ;
291
290
let search_index = EscapedJson :: from ( search_index) ;
292
291
Ok ( PartsAndLocations :: with ( path, search_index) )
293
292
}
@@ -319,8 +318,8 @@ impl AllCratesPart {
319
318
///
320
319
/// This is to match the current behavior of rustdoc, which allows you to get all crates
321
320
/// on the index page, even if --enable-index-page is only passed to the last crate.
322
- fn hack_get_external_crate_names ( cx : & Context < ' _ > ) -> Result < Vec < String > , Error > {
323
- let path = cx . dst . join ( "crates.js" ) ;
321
+ fn hack_get_external_crate_names ( doc_root : & Path ) -> Result < Vec < String > , Error > {
322
+ let path = doc_root . join ( "crates.js" ) ;
324
323
let Ok ( content) = fs:: read_to_string ( & path) else {
325
324
// they didn't emit invocation specific, so we just say there were no crates
326
325
return Ok ( Vec :: default ( ) ) ;
@@ -361,7 +360,7 @@ impl CratesIndexPart {
361
360
match SortedTemplate :: magic ( & template, MAGIC ) {
362
361
Ok ( template) => template,
363
362
Err ( e) => panic ! (
364
- "{e}: Object Replacement Character (U+FFFC) should not appear in the --index-page"
363
+ "Object Replacement Character (U+FFFC) should not appear in the --index-page: {e} "
365
364
) ,
366
365
}
367
366
}
@@ -860,27 +859,35 @@ impl Serialize for AliasSerializableImpl {
860
859
}
861
860
}
862
861
862
+ fn get_path_parts < T : CciPart > (
863
+ dst : & Path ,
864
+ crates_info : & [ CrateInfo ] ,
865
+ ) -> FxHashMap < PathBuf , Vec < String > > {
866
+ let mut templates: FxHashMap < PathBuf , Vec < String > > = FxHashMap :: default ( ) ;
867
+ crates_info. iter ( ) . map ( |crate_info| crate_info. get :: < T > ( ) . parts . iter ( ) ) . flatten ( ) . for_each (
868
+ |( path, part) | {
869
+ let path = dst. join ( & path) ;
870
+ let part = part. to_string ( ) ;
871
+ templates. entry ( path) . or_default ( ) . push ( part) ;
872
+ } ,
873
+ ) ;
874
+ templates
875
+ }
876
+
863
877
/// Create all parents
864
878
fn create_parents ( path : & Path ) -> Result < ( ) , Error > {
865
879
let parent = path. parent ( ) . expect ( "should not have an empty path here" ) ;
866
880
try_err ! ( fs:: create_dir_all( parent) , parent) ;
867
881
Ok ( ( ) )
868
882
}
869
883
870
- /// Create parents and then write
871
- fn write_create_parents ( path : & Path , content : String ) -> Result < ( ) , Error > {
872
- create_parents ( path) ?;
873
- try_err ! ( fs:: write( path, content) , path) ;
874
- Ok ( ( ) )
875
- }
876
-
877
884
/// Returns a blank template unless we could find one to append to
878
- fn read_template_or_blank < F , T : CciPart > (
885
+ fn read_template_or_blank < F , T : FileFormat > (
879
886
mut make_blank : F ,
880
887
path : & Path ,
881
- ) -> Result < SortedTemplate < T :: FileFormat > , Error >
888
+ ) -> Result < SortedTemplate < T > , Error >
882
889
where
883
- F : FnMut ( ) -> SortedTemplate < T :: FileFormat > ,
890
+ F : FnMut ( ) -> SortedTemplate < T > ,
884
891
{
885
892
match fs:: read_to_string ( & path) {
886
893
Ok ( template) => Ok ( try_err ! ( SortedTemplate :: from_str( & template) , & path) ) ,
@@ -898,31 +905,21 @@ fn write_rendered_cci<T: CciPart, F>(
898
905
where
899
906
F : FnMut ( ) -> SortedTemplate < T :: FileFormat > ,
900
907
{
901
- // read parts from disk
902
- let path_parts =
903
- crates_info. iter ( ) . map ( |crate_info| crate_info. get :: < T > ( ) . parts . iter ( ) ) . flatten ( ) ;
904
- // read previous rendered cci from storage, append to them
905
- let mut templates: FxHashMap < PathBuf , SortedTemplate < T :: FileFormat > > = Default :: default ( ) ;
906
- for ( path, part) in path_parts {
907
- let part = format ! ( "{part}" ) ;
908
- let path = dst. join ( & path) ;
909
- match templates. entry ( path. clone ( ) ) {
910
- Entry :: Vacant ( entry) => {
911
- let template = read_template_or_blank :: < _ , T > ( & mut make_blank, & path) ?;
912
- let template = entry. insert ( template) ;
913
- template. append ( part) ;
914
- }
915
- Entry :: Occupied ( mut t) => t. get_mut ( ) . append ( part) ,
916
- }
917
- }
918
-
919
908
// write the merged cci to disk
920
- for ( path, template ) in templates {
909
+ for ( path, parts ) in get_path_parts :: < T > ( dst , crates_info ) {
921
910
create_parents ( & path) ?;
911
+ // read previous rendered cci from storage, append to them
912
+ let mut template = read_template_or_blank :: < _ , T :: FileFormat > ( & mut make_blank, & path) ?;
913
+ for part in parts {
914
+ template. append ( part) ;
915
+ }
922
916
let file = try_err ! ( File :: create( & path) , & path) ;
923
917
let mut file = BufWriter :: new ( file) ;
924
918
try_err ! ( write!( file, "{template}" ) , & path) ;
925
919
try_err ! ( file. flush( ) , & path) ;
926
920
}
927
921
Ok ( ( ) )
928
922
}
923
+
924
+ #[ cfg( test) ]
925
+ mod tests;
0 commit comments