@@ -3,6 +3,7 @@ use crate::{
3
3
document:: DocumentContent , helpers:: merge_toml_table,
4
4
} ;
5
5
use alloy_primitives:: map:: HashMap ;
6
+ use eyre:: { Context , Result } ;
6
7
use forge_fmt:: { FormatterConfig , Visitable } ;
7
8
use foundry_compilers:: { compilers:: solc:: SOLC_EXTENSIONS , utils:: source_files_iter} ;
8
9
use foundry_config:: { DocConfig , filter:: expand_globs} ;
@@ -22,24 +23,23 @@ use toml::value;
22
23
#[ derive( Debug ) ]
23
24
pub struct DocBuilder {
24
25
/// The project root
25
- pub root : PathBuf ,
26
+ root : PathBuf ,
26
27
/// Path to Solidity source files.
27
- pub sources : PathBuf ,
28
+ sources : PathBuf ,
28
29
/// Paths to external libraries.
29
- pub libraries : Vec < PathBuf > ,
30
+ libraries : Vec < PathBuf > ,
30
31
/// Flag whether to build mdbook.
31
- pub should_build : bool ,
32
+ should_build : bool ,
32
33
/// Documentation configuration.
33
- pub config : DocConfig ,
34
+ config : DocConfig ,
34
35
/// The array of preprocessors to apply.
35
- pub preprocessors : Vec < Box < dyn Preprocessor > > ,
36
+ preprocessors : Vec < Box < dyn Preprocessor > > ,
36
37
/// The formatter config.
37
- pub fmt : FormatterConfig ,
38
+ fmt : FormatterConfig ,
38
39
/// Whether to include libraries to the output.
39
- pub include_libraries : bool ,
40
+ include_libraries : bool ,
40
41
}
41
42
42
- // TODO: consider using `tfio`
43
43
impl DocBuilder {
44
44
pub ( crate ) const SRC : & ' static str = "src" ;
45
45
const SOL_EXT : & ' static str = "sol" ;
@@ -90,12 +90,15 @@ impl DocBuilder {
90
90
}
91
91
92
92
/// Get the output directory
93
- pub fn out_dir ( & self ) -> PathBuf {
94
- self . root . join ( & self . config . out )
93
+ pub fn out_dir ( & self ) -> Result < PathBuf > {
94
+ Ok ( self . root . join ( & self . config . out ) . canonicalize ( ) ? )
95
95
}
96
96
97
97
/// Parse the sources and build the documentation.
98
98
pub fn build ( self ) -> eyre:: Result < ( ) > {
99
+ fs:: create_dir_all ( self . root . join ( & self . config . out ) )
100
+ . wrap_err ( "failed to create output directory" ) ?;
101
+
99
102
// Expand ignore globs
100
103
let ignored = expand_globs ( & self . root , self . config . ignore . iter ( ) ) ?;
101
104
@@ -121,6 +124,7 @@ impl DocBuilder {
121
124
. chain ( library_sources. iter ( ) . map ( |path| ( path, true ) ) )
122
125
. collect :: < Vec < _ > > ( ) ;
123
126
127
+ let out_dir = self . out_dir ( ) ?;
124
128
let documents = combined_sources
125
129
. par_iter ( )
126
130
. enumerate ( )
@@ -181,7 +185,8 @@ impl DocBuilder {
181
185
. into_iter ( )
182
186
. map ( |item| {
183
187
let relative_path = path. strip_prefix ( & self . root ) ?. join ( item. filename ( ) ) ;
184
- let target_path = self . config . out . join ( Self :: SRC ) . join ( relative_path) ;
188
+
189
+ let target_path = out_dir. join ( Self :: SRC ) . join ( relative_path) ;
185
190
let ident = item. source . ident ( ) ;
186
191
Ok ( Document :: new (
187
192
path. clone ( ) ,
@@ -206,7 +211,7 @@ impl DocBuilder {
206
211
name
207
212
} ;
208
213
let relative_path = path. strip_prefix ( & self . root ) ?. join ( filename) ;
209
- let target_path = self . config . out . join ( Self :: SRC ) . join ( relative_path) ;
214
+ let target_path = out_dir . join ( Self :: SRC ) . join ( relative_path) ;
210
215
211
216
let identity = match filestem {
212
217
Some ( stem) if stem. to_lowercase ( ) . contains ( "constants" ) => stem. to_owned ( ) ,
@@ -230,7 +235,8 @@ impl DocBuilder {
230
235
for ( ident, funcs) in overloaded {
231
236
let filename = funcs. first ( ) . expect ( "no overloaded functions" ) . filename ( ) ;
232
237
let relative_path = path. strip_prefix ( & self . root ) ?. join ( filename) ;
233
- let target_path = self . config . out . join ( Self :: SRC ) . join ( relative_path) ;
238
+
239
+ let target_path = out_dir. join ( Self :: SRC ) . join ( relative_path) ;
234
240
files. push (
235
241
Document :: new (
236
242
path. clone ( ) ,
@@ -267,7 +273,7 @@ impl DocBuilder {
267
273
268
274
// Build the book if requested
269
275
if self . should_build {
270
- MDBook :: load ( self . out_dir ( ) )
276
+ MDBook :: load ( self . out_dir ( ) . wrap_err ( "failed to construct output directory" ) ? )
271
277
. and_then ( |book| book. build ( ) )
272
278
. map_err ( |err| eyre:: eyre!( "failed to build book: {err:?}" ) ) ?;
273
279
}
@@ -276,7 +282,7 @@ impl DocBuilder {
276
282
}
277
283
278
284
fn write_mdbook ( & self , documents : Vec < Document > ) -> eyre:: Result < ( ) > {
279
- let out_dir = self . out_dir ( ) ;
285
+ let out_dir = self . out_dir ( ) . wrap_err ( "failed to construct output directory" ) ? ;
280
286
let out_dir_src = out_dir. join ( Self :: SRC ) ;
281
287
fs:: create_dir_all ( & out_dir_src) ?;
282
288
@@ -321,11 +327,11 @@ impl DocBuilder {
321
327
fs:: write ( out_dir. join ( "book.css" ) , include_str ! ( "../static/book.css" ) ) ?;
322
328
323
329
// Write book config
324
- fs:: write ( self . out_dir ( ) . join ( "book.toml" ) , self . book_config ( ) ?) ?;
330
+ fs:: write ( out_dir. join ( "book.toml" ) , self . book_config ( ) ?) ?;
325
331
326
332
// Write .gitignore
327
333
let gitignore = "book/" ;
328
- fs:: write ( self . out_dir ( ) . join ( ".gitignore" ) , gitignore) ?;
334
+ fs:: write ( out_dir. join ( ".gitignore" ) , gitignore) ?;
329
335
330
336
// Write doc files
331
337
for document in documents {
@@ -427,15 +433,14 @@ impl DocBuilder {
427
433
}
428
434
} ) ;
429
435
436
+ let out_dir = self . out_dir ( ) . wrap_err ( "failed to construct output directory" ) ?;
430
437
let mut readme = BufWriter :: new ( "\n \n # Contents\n " ) ;
431
438
for ( path, files) in grouped {
432
439
if path. extension ( ) . map ( |ext| ext == Self :: SOL_EXT ) . unwrap_or_default ( ) {
433
440
for file in files {
434
441
let ident = & file. identity ;
435
442
436
- let summary_path = file
437
- . target_path
438
- . strip_prefix ( self . out_dir ( ) . strip_prefix ( & self . root ) ?. join ( Self :: SRC ) ) ?;
443
+ let summary_path = & file. target_path . strip_prefix ( out_dir. join ( Self :: SRC ) ) ?;
439
444
summary. write_link_list_item (
440
445
ident,
441
446
& summary_path. display ( ) . to_string ( ) ,
@@ -458,7 +463,7 @@ impl DocBuilder {
458
463
if !readme. is_empty ( )
459
464
&& let Some ( path) = base_path
460
465
{
461
- let path = self . out_dir ( ) . join ( Self :: SRC ) . join ( path) ;
466
+ let path = out_dir. join ( Self :: SRC ) . join ( path) ;
462
467
fs:: create_dir_all ( & path) ?;
463
468
fs:: write ( path. join ( Self :: README ) , readme. finish ( ) ) ?;
464
469
}
0 commit comments