Skip to content

Commit 56a619f

Browse files
Merge pull request #427 from github/hendrikvanantwerpen/cache-builtins-in-tests
Cache partial paths for builtins when running tests
2 parents 328942b + 6499341 commit 56a619f

File tree

3 files changed

+81
-21
lines changed

3 files changed

+81
-21
lines changed

stack-graphs/src/graph.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1497,12 +1497,16 @@ impl StackGraph {
14971497

14981498
/// Copies the given stack graph into this stack graph. Panics if any of the files
14991499
/// in the other stack graph are already defined in the current one.
1500-
pub fn add_from_graph(&mut self, other: &StackGraph) -> Result<(), Handle<File>> {
1500+
pub fn add_from_graph(
1501+
&mut self,
1502+
other: &StackGraph,
1503+
) -> Result<Vec<Handle<File>>, Handle<File>> {
15011504
let mut files = HashMap::new();
15021505
for other_file in other.iter_files() {
15031506
let file = self.add_file(other[other_file].name())?;
15041507
files.insert(other_file, file);
15051508
}
1509+
let files = files;
15061510
let node_id = |other_node_id: NodeID| {
15071511
if other_node_id.is_root() {
15081512
NodeID::root()
@@ -1645,7 +1649,7 @@ impl StackGraph {
16451649
}
16461650
}
16471651
}
1648-
Ok(())
1652+
Ok(files.into_values().collect())
16491653
}
16501654
}
16511655

tree-sitter-stack-graphs/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
99

1010
### CLI
1111

12+
#### Added
13+
14+
- Tests run faster for languages with builtins sources by caching the partial paths for the builtins.
15+
1216
#### Changed
1317

1418
- Failure to index a file will not abort indexing anymore, but simply mark the file as failed, as we already do for files with parse errors.

tree-sitter-stack-graphs/src/cli/test.rs

Lines changed: 71 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,13 @@ use stack_graphs::stitching::Database;
1919
use stack_graphs::stitching::DatabaseCandidates;
2020
use stack_graphs::stitching::ForwardPartialPathStitcher;
2121
use stack_graphs::stitching::StitcherConfig;
22+
use std::collections::hash_map::Entry;
23+
use std::collections::HashMap;
24+
use std::collections::HashSet;
2225
use std::path::Path;
2326
use std::path::PathBuf;
2427
use std::time::Duration;
28+
use tree_sitter::Language;
2529
use tree_sitter_graph::Variables;
2630

2731
use crate::cli::util::duration_from_seconds_str;
@@ -176,10 +180,16 @@ impl TestArgs {
176180
pub fn run(self, mut loader: Loader) -> anyhow::Result<()> {
177181
let reporter = self.get_reporter();
178182
let mut total_result = TestResult::new();
183+
let mut cache = HashMap::new();
179184
for (test_root, test_path, _) in iter_files_and_directories(self.test_paths.clone()) {
180185
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+
)?;
183193
file_status.assert_reported();
184194
total_result.absorb(test_result);
185195
}
@@ -211,14 +221,15 @@ impl TestArgs {
211221
}
212222

213223
/// Run test file. Takes care of the output when an error is returned.
214-
fn run_test(
224+
fn run_test<'a>(
215225
&self,
216226
test_root: &Path,
217227
test_path: &Path,
218-
loader: &mut Loader,
228+
loader: &'a mut Loader,
219229
file_status: &mut CLIFileReporter,
230+
cache: &mut HashMap<Language, stack_graphs::serde::Database>,
220231
) -> 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) {
222233
ok @ Ok(_) => ok,
223234
err @ Err(_) => {
224235
file_status.failure_if_processing("error", None);
@@ -227,12 +238,13 @@ impl TestArgs {
227238
}
228239
}
229240

230-
fn run_test_inner(
241+
fn run_test_inner<'a>(
231242
&self,
232243
test_root: &Path,
233244
test_path: &Path,
234-
loader: &mut Loader,
245+
loader: &'a mut Loader,
235246
file_status: &mut CLIFileReporter,
247+
cache: &mut HashMap<Language, stack_graphs::serde::Database>,
236248
) -> anyhow::Result<TestResult> {
237249
let cancellation_flag = CancelAfterDuration::from_option(self.max_test_time);
238250

@@ -263,11 +275,24 @@ impl TestArgs {
263275

264276
file_status.processing();
265277

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+
266283
let source = file_reader.get(test_path)?;
267284
let default_fragment_path = test_path.strip_prefix(test_root).unwrap();
268285
let mut test = Test::from_source(test_path, source, default_fragment_path)?;
269286
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+
)?;
271296
}
272297
let mut globals = Variables::new();
273298
for test_fragment in &test.fragments {
@@ -325,15 +350,11 @@ impl TestArgs {
325350
Ok(_) => {}
326351
}
327352
}
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 {
333354
ForwardPartialPathStitcher::find_minimal_partial_path_set_in_file(
334355
&test.graph,
335356
&mut partials,
336-
file,
357+
fragment.file,
337358
stitcher_config,
338359
&cancellation_flag.as_ref(),
339360
|g, ps, p| {
@@ -387,14 +408,45 @@ impl TestArgs {
387408
Ok(result)
388409
}
389410

390-
fn load_builtins_into(
411+
fn load_builtins_into<'a>(
391412
&self,
392-
lc: &LanguageConfiguration,
413+
lc: &'a LanguageConfiguration,
393414
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>,
394420
) -> 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+
398450
Ok(())
399451
}
400452

0 commit comments

Comments
 (0)