@@ -94,7 +94,7 @@ impl DocBuilder {
94
94
}
95
95
96
96
/// Parse the sources and build the documentation.
97
- pub fn build ( self ) -> eyre:: Result < ( ) > {
97
+ pub fn build ( self , compiler : & mut solar :: sema :: Compiler ) -> eyre:: Result < ( ) > {
98
98
fs:: create_dir_all ( self . root . join ( & self . config . out ) )
99
99
. wrap_err ( "failed to create output directory" ) ?;
100
100
@@ -124,135 +124,149 @@ impl DocBuilder {
124
124
. collect :: < Vec < _ > > ( ) ;
125
125
126
126
let out_dir = self . out_dir ( ) ?;
127
- let documents = combined_sources
128
- . par_iter ( )
129
- . enumerate ( )
130
- . map ( |( i, ( path, from_library) ) | {
131
- let path = * path;
132
- let from_library = * from_library;
133
-
134
- // Read and parse source file
135
- let source = fs:: read_to_string ( path) ?;
136
- let source =
137
- forge_fmt:: format ( & source, self . fmt . clone ( ) ) . into_result ( ) . unwrap_or ( source) ;
138
-
139
- let ( mut source_unit, comments) = match solang_parser:: parse ( & source, i) {
140
- Ok ( res) => res,
141
- Err ( err) => {
142
- if from_library {
143
- // Ignore failures for library files
144
- return Ok ( Vec :: new ( ) ) ;
145
- } else {
146
- return Err ( eyre:: eyre!(
147
- "Failed to parse Solidity code for {}\n Debug info: {:?}" ,
148
- path. display( ) ,
149
- err
150
- ) ) ;
127
+ let documents = compiler. enter_mut ( |compiler| -> eyre:: Result < Vec < Vec < Document > > > {
128
+ let gcx = compiler. gcx ( ) ;
129
+ let documents = combined_sources
130
+ . par_iter ( )
131
+ . enumerate ( )
132
+ . map ( |( i, ( path, from_library) ) | {
133
+ let path = * path;
134
+ let from_library = * from_library;
135
+ let mut files = vec ! [ ] ;
136
+
137
+ // Read and parse source file
138
+ if let Some ( ( _, ast) ) = gcx. get_ast_source ( path)
139
+ && let Some ( source) =
140
+ forge_fmt:: format_ast ( gcx, ast, self . fmt . clone ( ) . into ( ) )
141
+ {
142
+ let ( mut source_unit, comments) = match solang_parser:: parse ( & source, i) {
143
+ Ok ( res) => res,
144
+ Err ( err) => {
145
+ if from_library {
146
+ // Ignore failures for library files
147
+ return Ok ( files) ;
148
+ } else {
149
+ return Err ( eyre:: eyre!(
150
+ "Failed to parse Solidity code for {}\n Debug info: {:?}" ,
151
+ path. display( ) ,
152
+ err
153
+ ) ) ;
154
+ }
155
+ }
156
+ } ;
157
+
158
+ // Visit the parse tree
159
+ let mut doc = Parser :: new ( comments, source) ;
160
+ source_unit
161
+ . visit ( & mut doc)
162
+ . map_err ( |err| eyre:: eyre!( "Failed to parse source: {err}" ) ) ?;
163
+
164
+ // Split the parsed items on top-level constants and rest.
165
+ let ( items, consts) : ( Vec < ParseItem > , Vec < ParseItem > ) = doc
166
+ . items ( )
167
+ . into_iter ( )
168
+ . partition ( |item| !matches ! ( item. source, ParseSource :: Variable ( _) ) ) ;
169
+
170
+ // Attempt to group overloaded top-level functions
171
+ let mut remaining = Vec :: with_capacity ( items. len ( ) ) ;
172
+ let mut funcs: HashMap < String , Vec < ParseItem > > = HashMap :: default ( ) ;
173
+ for item in items {
174
+ if matches ! ( item. source, ParseSource :: Function ( _) ) {
175
+ funcs. entry ( item. source . ident ( ) ) . or_default ( ) . push ( item) ;
176
+ } else {
177
+ // Put the item back
178
+ remaining. push ( item) ;
179
+ }
151
180
}
152
- }
153
- } ;
154
-
155
- // Visit the parse tree
156
- let mut doc = Parser :: new ( comments, source) ;
157
- source_unit
158
- . visit ( & mut doc)
159
- . map_err ( |err| eyre:: eyre!( "Failed to parse source: {err}" ) ) ?;
160
-
161
- // Split the parsed items on top-level constants and rest.
162
- let ( items, consts) : ( Vec < ParseItem > , Vec < ParseItem > ) = doc
163
- . items ( )
164
- . into_iter ( )
165
- . partition ( |item| !matches ! ( item. source, ParseSource :: Variable ( _) ) ) ;
166
-
167
- // Attempt to group overloaded top-level functions
168
- let mut remaining = Vec :: with_capacity ( items. len ( ) ) ;
169
- let mut funcs: HashMap < String , Vec < ParseItem > > = HashMap :: default ( ) ;
170
- for item in items {
171
- if matches ! ( item. source, ParseSource :: Function ( _) ) {
172
- funcs. entry ( item. source . ident ( ) ) . or_default ( ) . push ( item) ;
173
- } else {
174
- // Put the item back
175
- remaining. push ( item) ;
176
- }
177
- }
178
- let ( items, overloaded) : (
179
- HashMap < String , Vec < ParseItem > > ,
180
- HashMap < String , Vec < ParseItem > > ,
181
- ) = funcs. into_iter ( ) . partition ( |( _, v) | v. len ( ) == 1 ) ;
182
- remaining. extend ( items. into_iter ( ) . flat_map ( |( _, v) | v) ) ;
183
-
184
- // Each regular item will be written into its own file.
185
- let mut files = remaining
186
- . into_iter ( )
187
- . map ( |item| {
188
- let relative_path = path. strip_prefix ( & self . root ) ?. join ( item. filename ( ) ) ;
189
-
190
- let target_path = out_dir. join ( Self :: SRC ) . join ( relative_path) ;
191
- let ident = item. source . ident ( ) ;
192
- Ok ( Document :: new (
193
- path. clone ( ) ,
194
- target_path,
195
- from_library,
196
- self . config . out . clone ( ) ,
197
- )
198
- . with_content ( DocumentContent :: Single ( item) , ident) )
199
- } )
200
- . collect :: < eyre:: Result < Vec < _ > > > ( ) ?;
201
-
202
- // If top-level constants exist, they will be written to the same file.
203
- if !consts. is_empty ( ) {
204
- let filestem = path. file_stem ( ) . and_then ( |stem| stem. to_str ( ) ) ;
205
-
206
- let filename = {
207
- let mut name = "constants" . to_owned ( ) ;
208
- if let Some ( stem) = filestem {
209
- name. push_str ( & format ! ( ".{stem}" ) ) ;
181
+ let ( items, overloaded) : (
182
+ HashMap < String , Vec < ParseItem > > ,
183
+ HashMap < String , Vec < ParseItem > > ,
184
+ ) = funcs. into_iter ( ) . partition ( |( _, v) | v. len ( ) == 1 ) ;
185
+ remaining. extend ( items. into_iter ( ) . flat_map ( |( _, v) | v) ) ;
186
+
187
+ // Each regular item will be written into its own file.
188
+ files = remaining
189
+ . into_iter ( )
190
+ . map ( |item| {
191
+ let relative_path =
192
+ path. strip_prefix ( & self . root ) ?. join ( item. filename ( ) ) ;
193
+
194
+ let target_path = out_dir. join ( Self :: SRC ) . join ( relative_path) ;
195
+ let ident = item. source . ident ( ) ;
196
+ Ok ( Document :: new (
197
+ path. clone ( ) ,
198
+ target_path,
199
+ from_library,
200
+ self . config . out . clone ( ) ,
201
+ )
202
+ . with_content ( DocumentContent :: Single ( item) , ident) )
203
+ } )
204
+ . collect :: < eyre:: Result < Vec < _ > > > ( ) ?;
205
+
206
+ // If top-level constants exist, they will be written to the same file.
207
+ if !consts. is_empty ( ) {
208
+ let filestem = path. file_stem ( ) . and_then ( |stem| stem. to_str ( ) ) ;
209
+
210
+ let filename = {
211
+ let mut name = "constants" . to_owned ( ) ;
212
+ if let Some ( stem) = filestem {
213
+ name. push_str ( & format ! ( ".{stem}" ) ) ;
214
+ }
215
+ name. push_str ( ".md" ) ;
216
+ name
217
+ } ;
218
+ let relative_path = path. strip_prefix ( & self . root ) ?. join ( filename) ;
219
+ let target_path = out_dir. join ( Self :: SRC ) . join ( relative_path) ;
220
+
221
+ let identity = match filestem {
222
+ Some ( stem) if stem. to_lowercase ( ) . contains ( "constants" ) => {
223
+ stem. to_owned ( )
224
+ }
225
+ Some ( stem) => format ! ( "{stem} constants" ) ,
226
+ None => "constants" . to_owned ( ) ,
227
+ } ;
228
+
229
+ files. push (
230
+ Document :: new (
231
+ path. clone ( ) ,
232
+ target_path,
233
+ from_library,
234
+ self . config . out . clone ( ) ,
235
+ )
236
+ . with_content ( DocumentContent :: Constants ( consts) , identity) ,
237
+ )
210
238
}
211
- name. push_str ( ".md" ) ;
212
- name
213
- } ;
214
- let relative_path = path. strip_prefix ( & self . root ) ?. join ( filename) ;
215
- let target_path = out_dir. join ( Self :: SRC ) . join ( relative_path) ;
216
239
217
- let identity = match filestem {
218
- Some ( stem) if stem. to_lowercase ( ) . contains ( "constants" ) => stem. to_owned ( ) ,
219
- Some ( stem) => format ! ( "{stem} constants" ) ,
220
- None => "constants" . to_owned ( ) ,
240
+ // If overloaded functions exist, they will be written to the same file
241
+ if !overloaded. is_empty ( ) {
242
+ for ( ident, funcs) in overloaded {
243
+ let filename =
244
+ funcs. first ( ) . expect ( "no overloaded functions" ) . filename ( ) ;
245
+ let relative_path = path. strip_prefix ( & self . root ) ?. join ( filename) ;
246
+
247
+ let target_path = out_dir. join ( Self :: SRC ) . join ( relative_path) ;
248
+ files. push (
249
+ Document :: new (
250
+ path. clone ( ) ,
251
+ target_path,
252
+ from_library,
253
+ self . config . out . clone ( ) ,
254
+ )
255
+ . with_content (
256
+ DocumentContent :: OverloadedFunctions ( funcs) ,
257
+ ident,
258
+ ) ,
259
+ ) ;
260
+ }
261
+ }
221
262
} ;
222
263
223
- files. push (
224
- Document :: new (
225
- path. clone ( ) ,
226
- target_path,
227
- from_library,
228
- self . config . out . clone ( ) ,
229
- )
230
- . with_content ( DocumentContent :: Constants ( consts) , identity) ,
231
- )
232
- }
264
+ Ok ( files)
265
+ } )
266
+ . collect :: < eyre:: Result < Vec < _ > > > ( ) ?;
233
267
234
- // If overloaded functions exist, they will be written to the same file
235
- if !overloaded. is_empty ( ) {
236
- for ( ident, funcs) in overloaded {
237
- let filename = funcs. first ( ) . expect ( "no overloaded functions" ) . filename ( ) ;
238
- let relative_path = path. strip_prefix ( & self . root ) ?. join ( filename) ;
239
-
240
- let target_path = out_dir. join ( Self :: SRC ) . join ( relative_path) ;
241
- files. push (
242
- Document :: new (
243
- path. clone ( ) ,
244
- target_path,
245
- from_library,
246
- self . config . out . clone ( ) ,
247
- )
248
- . with_content ( DocumentContent :: OverloadedFunctions ( funcs) , ident) ,
249
- ) ;
250
- }
251
- }
252
-
253
- Ok ( files)
254
- } )
255
- . collect :: < eyre:: Result < Vec < _ > > > ( ) ?;
268
+ Ok ( documents)
269
+ } ) ?;
256
270
257
271
// Flatten results and apply preprocessors to files
258
272
let documents = self
@@ -262,15 +276,17 @@ impl DocBuilder {
262
276
p. preprocess ( docs)
263
277
} ) ?;
264
278
265
- // Sort the results
266
- let documents = documents. into_iter ( ) . sorted_by ( |doc1, doc2| {
267
- doc1. item_path . display ( ) . to_string ( ) . cmp ( & doc2. item_path . display ( ) . to_string ( ) )
268
- } ) ;
279
+ // Sort the results and filter libraries.
280
+ let documents = documents
281
+ . into_iter ( )
282
+ . sorted_by ( |doc1, doc2| {
283
+ doc1. item_path . display ( ) . to_string ( ) . cmp ( & doc2. item_path . display ( ) . to_string ( ) )
284
+ } )
285
+ . filter ( |d| !d. from_library || self . include_libraries )
286
+ . collect_vec ( ) ;
269
287
270
288
// Write mdbook related files
271
- self . write_mdbook (
272
- documents. filter ( |d| !d. from_library || self . include_libraries ) . collect_vec ( ) ,
273
- ) ?;
289
+ self . write_mdbook ( documents) ?;
274
290
275
291
// Build the book if requested
276
292
if self . should_build {
0 commit comments