@@ -19,9 +19,13 @@ use stack_graphs::stitching::Database;
19
19
use stack_graphs:: stitching:: DatabaseCandidates ;
20
20
use stack_graphs:: stitching:: ForwardPartialPathStitcher ;
21
21
use stack_graphs:: stitching:: StitcherConfig ;
22
+ use std:: collections:: hash_map:: Entry ;
23
+ use std:: collections:: HashMap ;
24
+ use std:: collections:: HashSet ;
22
25
use std:: path:: Path ;
23
26
use std:: path:: PathBuf ;
24
27
use std:: time:: Duration ;
28
+ use tree_sitter:: Language ;
25
29
use tree_sitter_graph:: Variables ;
26
30
27
31
use crate :: cli:: util:: duration_from_seconds_str;
@@ -176,10 +180,16 @@ impl TestArgs {
176
180
pub fn run ( self , mut loader : Loader ) -> anyhow:: Result < ( ) > {
177
181
let reporter = self . get_reporter ( ) ;
178
182
let mut total_result = TestResult :: new ( ) ;
183
+ let mut cache = HashMap :: new ( ) ;
179
184
for ( test_root, test_path, _) in iter_files_and_directories ( self . test_paths . clone ( ) ) {
180
185
let mut file_status = CLIFileReporter :: new ( & reporter, & test_path) ;
181
- let test_result =
182
- self . run_test ( & test_root, & test_path, & mut loader, & mut file_status) ?;
186
+ let test_result = self . run_test (
187
+ & test_root,
188
+ & test_path,
189
+ & mut loader,
190
+ & mut file_status,
191
+ & mut cache,
192
+ ) ?;
183
193
file_status. assert_reported ( ) ;
184
194
total_result. absorb ( test_result) ;
185
195
}
@@ -211,14 +221,15 @@ impl TestArgs {
211
221
}
212
222
213
223
/// Run test file. Takes care of the output when an error is returned.
214
- fn run_test (
224
+ fn run_test < ' a > (
215
225
& self ,
216
226
test_root : & Path ,
217
227
test_path : & Path ,
218
- loader : & mut Loader ,
228
+ loader : & ' a mut Loader ,
219
229
file_status : & mut CLIFileReporter ,
230
+ cache : & mut HashMap < Language , stack_graphs:: serde:: Database > ,
220
231
) -> anyhow:: Result < TestResult > {
221
- match self . run_test_inner ( test_root, test_path, loader, file_status) {
232
+ match self . run_test_inner ( test_root, test_path, loader, file_status, cache ) {
222
233
ok @ Ok ( _) => ok,
223
234
err @ Err ( _) => {
224
235
file_status. failure_if_processing ( "error" , None ) ;
@@ -227,12 +238,13 @@ impl TestArgs {
227
238
}
228
239
}
229
240
230
- fn run_test_inner (
241
+ fn run_test_inner < ' a > (
231
242
& self ,
232
243
test_root : & Path ,
233
244
test_path : & Path ,
234
- loader : & mut Loader ,
245
+ loader : & ' a mut Loader ,
235
246
file_status : & mut CLIFileReporter ,
247
+ cache : & mut HashMap < Language , stack_graphs:: serde:: Database > ,
236
248
) -> anyhow:: Result < TestResult > {
237
249
let cancellation_flag = CancelAfterDuration :: from_option ( self . max_test_time ) ;
238
250
@@ -263,11 +275,24 @@ impl TestArgs {
263
275
264
276
file_status. processing ( ) ;
265
277
278
+ let stitcher_config =
279
+ StitcherConfig :: default ( ) . with_detect_similar_paths ( !lc. no_similar_paths_in_file ) ;
280
+ let mut partials = PartialPaths :: new ( ) ;
281
+ let mut db = Database :: new ( ) ;
282
+
266
283
let source = file_reader. get ( test_path) ?;
267
284
let default_fragment_path = test_path. strip_prefix ( test_root) . unwrap ( ) ;
268
285
let mut test = Test :: from_source ( test_path, source, default_fragment_path) ?;
269
286
if !self . no_builtins {
270
- self . load_builtins_into ( & lc, & mut test. graph ) ?;
287
+ self . load_builtins_into (
288
+ & lc,
289
+ & mut test. graph ,
290
+ & mut partials,
291
+ & mut db,
292
+ stitcher_config,
293
+ cancellation_flag. as_ref ( ) ,
294
+ cache,
295
+ ) ?;
271
296
}
272
297
let mut globals = Variables :: new ( ) ;
273
298
for test_fragment in & test. fragments {
@@ -325,15 +350,11 @@ impl TestArgs {
325
350
Ok ( _) => { }
326
351
}
327
352
}
328
- let stitcher_config =
329
- StitcherConfig :: default ( ) . with_detect_similar_paths ( !lc. no_similar_paths_in_file ) ;
330
- let mut partials = PartialPaths :: new ( ) ;
331
- let mut db = Database :: new ( ) ;
332
- for file in test. graph . iter_files ( ) {
353
+ for fragment in & test. fragments {
333
354
ForwardPartialPathStitcher :: find_minimal_partial_path_set_in_file (
334
355
& test. graph ,
335
356
& mut partials,
336
- file,
357
+ fragment . file ,
337
358
stitcher_config,
338
359
& cancellation_flag. as_ref ( ) ,
339
360
|g, ps, p| {
@@ -387,14 +408,45 @@ impl TestArgs {
387
408
Ok ( result)
388
409
}
389
410
390
- fn load_builtins_into (
411
+ fn load_builtins_into < ' a > (
391
412
& self ,
392
- lc : & LanguageConfiguration ,
413
+ lc : & ' a LanguageConfiguration ,
393
414
graph : & mut StackGraph ,
415
+ partials : & mut PartialPaths ,
416
+ db : & mut Database ,
417
+ stitcher_config : StitcherConfig ,
418
+ cancellation_flag : & dyn CancellationFlag ,
419
+ cache : & mut HashMap < Language , stack_graphs:: serde:: Database > ,
394
420
) -> anyhow:: Result < ( ) > {
395
- if let Err ( h) = graph. add_from_graph ( & lc. builtins ) {
396
- return Err ( anyhow ! ( "Duplicate builtin file {}" , & graph[ h] ) ) ;
397
- }
421
+ let files = graph
422
+ . add_from_graph ( & lc. builtins )
423
+ . map_err ( |h| anyhow ! ( "Duplicate builtin file {}" , & graph[ h] ) ) ?;
424
+ let files = files. into_iter ( ) . collect :: < HashSet < _ > > ( ) ;
425
+ match cache. entry ( lc. language ) {
426
+ Entry :: Occupied ( o) => {
427
+ o. get ( ) . load_into ( graph, partials, db) ?;
428
+ }
429
+ Entry :: Vacant ( v) => {
430
+ for file in & files {
431
+ ForwardPartialPathStitcher :: find_minimal_partial_path_set_in_file (
432
+ graph,
433
+ partials,
434
+ * file,
435
+ stitcher_config,
436
+ & cancellation_flag,
437
+ |g, ps, p| {
438
+ db. add_partial_path ( g, ps, p. clone ( ) ) ;
439
+ } ,
440
+ ) ?;
441
+ }
442
+ v. insert ( db. to_serializable_filter (
443
+ graph,
444
+ partials,
445
+ & |_: & StackGraph , f : & Handle < File > | files. contains ( f) ,
446
+ ) ) ;
447
+ }
448
+ } ;
449
+
398
450
Ok ( ( ) )
399
451
}
400
452
0 commit comments